kernel: attempt to correct stack overflow test
This commit is contained in:
parent
8f441135e0
commit
87d7f5860d
|
|
@ -1,7 +1,7 @@
|
|||
use core::{
|
||||
arch::asm,
|
||||
fmt::Debug,
|
||||
mem::offset_of,
|
||||
mem::{MaybeUninit, offset_of},
|
||||
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))]
|
||||
#[derive(Debug)]
|
||||
pub struct TaskStateSegment {
|
||||
_reserved1: [u8; 4],
|
||||
pub privilege_stack_table: [u64; 3],
|
||||
pub privilege_stack_table: [u64; PRIVILEGE_STACK_TABLE_SIZE],
|
||||
_reserved2: [u8; 8],
|
||||
pub interrupt_stack_table: [u64; 7],
|
||||
pub interrupt_stack_table: [u64; INTERRUPT_STACK_TABLE_SIZE],
|
||||
_reserved3: [u8; 10],
|
||||
pub iomap_base: u16,
|
||||
}
|
||||
|
|
@ -489,6 +493,13 @@ impl TaskStateSegment {
|
|||
_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 {
|
||||
|
|
@ -500,17 +511,35 @@ const impl Default for TaskStateSegment {
|
|||
pub const DF_STACK: u8 = 0;
|
||||
pub const NMI_STACK: u8 = 1;
|
||||
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(|| {
|
||||
let mut tss = TaskStateSegment::new();
|
||||
const STACK_SIZE: usize = super::PAGE_SIZE * 5;
|
||||
static mut STACKS: [[u8; STACK_SIZE]; 3] = [[0; STACK_SIZE]; 3];
|
||||
static mut STACKS: [Stack; 4] = [const { Stack::new() }; 4];
|
||||
|
||||
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);
|
||||
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);
|
||||
serial_println!("Initialized TSS {:#?}", tss);
|
||||
|
||||
tss
|
||||
});
|
||||
|
|
|
|||
|
|
@ -89,6 +89,9 @@ impl Entry {
|
|||
ExceptionVector::NON_MASKABLE_INTERRUPT => {
|
||||
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 => {
|
||||
options.set_interrupt_stack_table_index(super::gdt::MC_STACK);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,12 +25,13 @@ pub extern "C" fn main() -> ! {
|
|||
_stack_frame: &mut idt::InterruptStackFrame,
|
||||
_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)
|
||||
}
|
||||
|
||||
static IDT: LazyLock<InterruptDescriptorTable> = LazyLock::new(|| {
|
||||
let mut idt = InterruptDescriptorTable::new_default();
|
||||
|
||||
idt.double_fault = unsafe {
|
||||
Entry::new(
|
||||
double_fault_handler as *const (),
|
||||
|
|
@ -38,7 +39,19 @@ pub extern "C" fn main() -> ! {
|
|||
idt::EntryOptions::empty_interrupt_gate()
|
||||
.with_present(true)
|
||||
.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