Skip to content
This repository was archived by the owner on Mar 20, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ test-timeout = 300 # In seconds (5 minutes)
name = "should_panic"
harness = false

[[test]]
name = "stack_overflow"
harness = false

[profile.dev]
panic = "abort"

Expand Down
47 changes: 47 additions & 0 deletions src/gdt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use lazy_static::lazy_static;
use x86_64::structures::gdt::{Descriptor, GlobalDescriptorTable};
use x86_64::structures::gdt::SegmentSelector;
use x86_64::structures::tss::TaskStateSegment;
use x86_64::VirtAddr;

pub const DOUBLE_FAULT_IST_INDEX: u16 = 0;

pub fn init() {
use x86_64::instructions::tables::load_tss;
use x86_64::instructions::segmentation::{CS, Segment};

GDT.0.load();
unsafe {
CS::set_reg(GDT.1.code_selector);
load_tss(GDT.1.tss_selector);
}
}

lazy_static! {
static ref TSS: TaskStateSegment = {
let mut tss = TaskStateSegment::new();
tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX as usize] = {
const STACK_SIZE: usize = 4096 * 5;
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];

let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
let stack_end = stack_start + STACK_SIZE;
stack_end
};
tss
};
}

lazy_static! {
static ref GDT: (GlobalDescriptorTable, Selectors) = {
let mut gdt = GlobalDescriptorTable::new();
let code_selector = gdt.add_entry(Descriptor::kernel_code_segment());
let tss_selector = gdt.add_entry(Descriptor::tss_segment(&TSS));
(gdt, Selectors { code_selector, tss_selector })
};
}

struct Selectors {
code_selector: SegmentSelector,
tss_selector: SegmentSelector,
}
13 changes: 11 additions & 2 deletions src/interrupts.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
use crate::println;
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};

use lazy_static::lazy_static;
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
use crate::gdt;

lazy_static! {
static ref IDT: InterruptDescriptorTable = {
let mut idt = InterruptDescriptorTable::new();
idt.breakpoint.set_handler_fn(breakpoint_handler);
unsafe {
idt.double_fault.set_handler_fn(double_fault_handler)
.set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX); // new
}

idt
};
}
Expand All @@ -19,6 +24,10 @@ extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) {
println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame);
}

extern "x86-interrupt" fn double_fault_handler(stack_frame: InterruptStackFrame, _error_code: u64,) -> ! {
panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame);
}

#[test_case]
fn test_breakpoint_exception() {
x86_64::instructions::interrupts::int3();
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@

use core::panic::PanicInfo;

pub mod gdt;
pub mod interrupts;
pub mod serial;
pub mod vga_buffer;

pub fn init() {
gdt::init();
interrupts::init_idt();
}

Expand Down
23 changes: 14 additions & 9 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,8 @@ use infinity_os::println;

#[no_mangle]
pub extern "C" fn _start() -> ! {
println!(" _____ __ _ _ _ ____ _____ ");
println!(" |_ _| / _(_) (_) | / __ \\ / ____|");
println!(" | | _ __ | |_ _ _ __ _| |_ _ _| | | | (___ ");
println!(" | | | '_ \\| _| | '_ \\| | __| | | | | | |\\___ \\ ");
println!(" _| |_| | | | | | | | | | | |_| |_| | |__| |____) |");
println!(" |_____|_| |_|_| |_|_| |_|_|\\__|\\__, |\\____/|_____/ ");
println!(" __/ | ");
println!(" |___/ ");

infinity_os::init();
print_logo();

#[cfg(test)]
test_main();
Expand All @@ -38,3 +30,16 @@ fn panic(info: &PanicInfo) -> ! {
fn panic(info: &PanicInfo) -> ! {
infinity_os::test_panic_handler(info)
}

fn print_logo() {
println!("");
println!(" _____ __ _ _ _ ____ _____ ");
println!(" |_ _| / _(_) (_) | / __ \\ / ____|");
println!(" | | _ __ | |_ _ _ __ _| |_ _ _| | | | (___ ");
println!(" | | | '_ \\| _| | '_ \\| | __| | | | | | |\\___ \\ ");
println!(" _| |_| | | | | | | | | | | |_| |_| | |__| |____) |");
println!(" |_____|_| |_|_| |_|_| |_|_|\\__|\\__, |\\____/|_____/ ");
println!(" __/ | ");
println!(" |___/ ");
println!("");
}
58 changes: 58 additions & 0 deletions tests/stack_overflow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#![no_std]
#![no_main]
#![feature(abi_x86_interrupt)]

use infinity_os::{exit_qemu, serial_print, serial_println, QemuExitCode};
use core::panic::PanicInfo;
use lazy_static::lazy_static;
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};

#[no_mangle]
pub extern "C" fn _start() -> ! {
serial_print!("stack_overflow::stack_overflow...\t");

infinity_os::gdt::init();
init_test_idt();

// trigger a stack overflow
stack_overflow();

panic!("Execution continued after stack overflow");
}

#[allow(unconditional_recursion)]
fn stack_overflow() {
stack_overflow(); // for each recursion, the return address is pushed
volatile::Volatile::new(0).read(); // prevent tail recursion optimizations
}

lazy_static! {
static ref TEST_IDT: InterruptDescriptorTable = {
let mut idt = InterruptDescriptorTable::new();
unsafe {
idt.double_fault
.set_handler_fn(test_double_fault_handler)
.set_stack_index(infinity_os::gdt::DOUBLE_FAULT_IST_INDEX);
}

idt
};
}

pub fn init_test_idt() {
TEST_IDT.load();
}

extern "x86-interrupt" fn test_double_fault_handler(
_stack_frame: InterruptStackFrame,
_error_code: u64,
) -> ! {
serial_println!("[ok]");
exit_qemu(QemuExitCode::Success);
loop {}
}

#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
infinity_os::test_panic_handler(info)
}