kernel: attempt to correct stack overflow test
This commit is contained in:
parent
8f441135e0
commit
87d7f5860d
|
|
@ -10,4 +10,4 @@ target = "x86_64-unknown-kernel.json"
|
||||||
runner = "./run.sh"
|
runner = "./run.sh"
|
||||||
rustflags = [
|
rustflags = [
|
||||||
"-C", "force-frame-pointers=yes",
|
"-C", "force-frame-pointers=yes",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use core::{
|
use core::{
|
||||||
arch::asm,
|
arch::asm,
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
mem::offset_of,
|
mem::{MaybeUninit, offset_of},
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -468,12 +468,16 @@ impl DerefMut for TssEntry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PRIVILEGE_STACK_TABLE_SIZE: usize = 3;
|
||||||
|
const INTERRUPT_STACK_TABLE_SIZE: usize = 7;
|
||||||
|
|
||||||
#[repr(C, packed(4))]
|
#[repr(C, packed(4))]
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct TaskStateSegment {
|
pub struct TaskStateSegment {
|
||||||
_reserved1: [u8; 4],
|
_reserved1: [u8; 4],
|
||||||
pub privilege_stack_table: [u64; 3],
|
pub privilege_stack_table: [u64; PRIVILEGE_STACK_TABLE_SIZE],
|
||||||
_reserved2: [u8; 8],
|
_reserved2: [u8; 8],
|
||||||
pub interrupt_stack_table: [u64; 7],
|
pub interrupt_stack_table: [u64; INTERRUPT_STACK_TABLE_SIZE],
|
||||||
_reserved3: [u8; 10],
|
_reserved3: [u8; 10],
|
||||||
pub iomap_base: u16,
|
pub iomap_base: u16,
|
||||||
}
|
}
|
||||||
|
|
@ -489,6 +493,13 @@ impl TaskStateSegment {
|
||||||
_reserved3: [0; 10],
|
_reserved3: [0; 10],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn set_stack(&mut self, index: u8, stack: &'static Stack) {
|
||||||
|
assert!(
|
||||||
|
(index as usize) < INTERRUPT_STACK_TABLE_SIZE,
|
||||||
|
"Interrupt stack table index out of bounds"
|
||||||
|
);
|
||||||
|
self.interrupt_stack_table[index as usize] = stack.top().to_address();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const impl Default for TaskStateSegment {
|
const impl Default for TaskStateSegment {
|
||||||
|
|
@ -500,17 +511,35 @@ const impl Default for TaskStateSegment {
|
||||||
pub const DF_STACK: u8 = 0;
|
pub const DF_STACK: u8 = 0;
|
||||||
pub const NMI_STACK: u8 = 1;
|
pub const NMI_STACK: u8 = 1;
|
||||||
pub const MC_STACK: u8 = 2;
|
pub const MC_STACK: u8 = 2;
|
||||||
|
pub const PF_STACK: u8 = 3;
|
||||||
|
|
||||||
|
const STACK_SIZE: usize = super::PAGE_SIZE * 5;
|
||||||
|
#[repr(align(16))]
|
||||||
|
pub struct Stack(MaybeUninit<[u8; STACK_SIZE]>);
|
||||||
|
|
||||||
|
impl Stack {
|
||||||
|
const fn new() -> Self {
|
||||||
|
Stack(MaybeUninit::uninit())
|
||||||
|
}
|
||||||
|
fn top(&self) -> *const u8 {
|
||||||
|
unsafe {
|
||||||
|
(&raw const *self)
|
||||||
|
.cast::<u8>()
|
||||||
|
.byte_add(super::PAGE_SIZE * 5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub static TSS: LazyLock<TaskStateSegment> = LazyLock::new(|| {
|
pub static TSS: LazyLock<TaskStateSegment> = LazyLock::new(|| {
|
||||||
let mut tss = TaskStateSegment::new();
|
let mut tss = TaskStateSegment::new();
|
||||||
const STACK_SIZE: usize = super::PAGE_SIZE * 5;
|
static mut STACKS: [Stack; 4] = [const { Stack::new() }; 4];
|
||||||
static mut STACKS: [[u8; STACK_SIZE]; 3] = [[0; STACK_SIZE]; 3];
|
|
||||||
|
|
||||||
let stack_top = |n: usize| unsafe { STACKS[n].as_ptr().add(STACK_SIZE).to_address() };
|
tss.set_stack(DF_STACK, unsafe { &STACKS[DF_STACK as usize] });
|
||||||
|
tss.set_stack(NMI_STACK, unsafe { &STACKS[NMI_STACK as usize] });
|
||||||
|
tss.set_stack(MC_STACK, unsafe { &STACKS[MC_STACK as usize] });
|
||||||
|
tss.set_stack(PF_STACK, unsafe { &STACKS[PF_STACK as usize] });
|
||||||
|
|
||||||
tss.interrupt_stack_table[DF_STACK as usize] = stack_top(DF_STACK as usize);
|
serial_println!("Initialized TSS {:#?}", tss);
|
||||||
tss.interrupt_stack_table[NMI_STACK as usize] = stack_top(NMI_STACK as usize);
|
|
||||||
tss.interrupt_stack_table[MC_STACK as usize] = stack_top(MC_STACK as usize);
|
|
||||||
|
|
||||||
tss
|
tss
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,9 @@ impl Entry {
|
||||||
ExceptionVector::NON_MASKABLE_INTERRUPT => {
|
ExceptionVector::NON_MASKABLE_INTERRUPT => {
|
||||||
options.set_interrupt_stack_table_index(super::gdt::NMI_STACK);
|
options.set_interrupt_stack_table_index(super::gdt::NMI_STACK);
|
||||||
}
|
}
|
||||||
|
ExceptionVector::PAGE_FAULT => {
|
||||||
|
options.set_interrupt_stack_table_index(super::gdt::PF_STACK);
|
||||||
|
}
|
||||||
ExceptionVector::MACHINE_CHECK => {
|
ExceptionVector::MACHINE_CHECK => {
|
||||||
options.set_interrupt_stack_table_index(super::gdt::MC_STACK);
|
options.set_interrupt_stack_table_index(super::gdt::MC_STACK);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,13 @@ pub extern "C" fn main() -> ! {
|
||||||
_stack_frame: &mut idt::InterruptStackFrame,
|
_stack_frame: &mut idt::InterruptStackFrame,
|
||||||
_error_code: u64,
|
_error_code: u64,
|
||||||
) -> ! {
|
) -> ! {
|
||||||
kernel::serial_println!("[ok] Double fault handler called");
|
kernel::serial_println!("[ok] Fault handler called");
|
||||||
kernel::testing::exit_qemu(kernel::testing::QemuExitCode::Success)
|
kernel::testing::exit_qemu(kernel::testing::QemuExitCode::Success)
|
||||||
}
|
}
|
||||||
|
|
||||||
static IDT: LazyLock<InterruptDescriptorTable> = LazyLock::new(|| {
|
static IDT: LazyLock<InterruptDescriptorTable> = LazyLock::new(|| {
|
||||||
let mut idt = InterruptDescriptorTable::new_default();
|
let mut idt = InterruptDescriptorTable::new_default();
|
||||||
|
|
||||||
idt.double_fault = unsafe {
|
idt.double_fault = unsafe {
|
||||||
Entry::new(
|
Entry::new(
|
||||||
double_fault_handler as *const (),
|
double_fault_handler as *const (),
|
||||||
|
|
@ -38,7 +39,19 @@ pub extern "C" fn main() -> ! {
|
||||||
idt::EntryOptions::empty_interrupt_gate()
|
idt::EntryOptions::empty_interrupt_gate()
|
||||||
.with_present(true)
|
.with_present(true)
|
||||||
.with_privilege_level(RING0)
|
.with_privilege_level(RING0)
|
||||||
.with_interrupt_stack_table_index(DF_STACK),
|
.with_interrupt_stack_table_index(kernel::x86_64::gdt::DF_STACK),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
// this should fire #PF since we have it installed anways in the default idt
|
||||||
|
idt.page_fault = unsafe {
|
||||||
|
Entry::new(
|
||||||
|
double_fault_handler as *const (),
|
||||||
|
offset_of!(GlobalDescriptorTable, kernel_code) as u16,
|
||||||
|
idt::EntryOptions::empty_interrupt_gate()
|
||||||
|
.with_present(true)
|
||||||
|
.with_privilege_level(RING0)
|
||||||
|
.with_interrupt_stack_table_index(kernel::x86_64::gdt::PF_STACK),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue