diff options
Diffstat (limited to 'rsnix/src/gdt.rs')
| -rw-r--r-- | rsnix/src/gdt.rs | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/rsnix/src/gdt.rs b/rsnix/src/gdt.rs index 514ed2e..f3d8b9a 100644 --- a/rsnix/src/gdt.rs +++ b/rsnix/src/gdt.rs | |||
| @@ -116,12 +116,14 @@ impl Tss { | |||
| 116 | } | 116 | } |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | /// 4 KiB page-aligned block for the IST stacks. | 119 | /// IST stack size: the fault path (fault dump + best-effort crash-log |
| 120 | #[repr(align(4096))] | 120 | /// FAT write) is deep, so each IST stack is 32 KiB, allocated from the |
| 121 | struct Page([u8; 4096]); | 121 | /// heap at init. They must NOT live in .bss: a 4 KiB .bss stack placed |
| 122 | /// next to kernel statics silently overwrites them on overflow (the FAT | ||
| 123 | /// ACTIVE_VOL was clobbered this way — a "no volume at slot 8" crash in | ||
| 124 | /// the fault path). The heap region is far from the kernel image. | ||
| 125 | const IST_STACK_SIZE: usize = 32 * 1024; | ||
| 122 | 126 | ||
| 123 | static mut PF_STACK: Page = Page([0; 4096]); | ||
| 124 | static mut DF_STACK: Page = Page([0; 4096]); | ||
| 125 | static mut TSS: Tss = Tss::zero(); | 127 | static mut TSS: Tss = Tss::zero(); |
| 126 | // GDT slots are 8 bytes except the TSS descriptor at index 63, which is | 128 | // GDT slots are 8 bytes except the TSS descriptor at index 63, which is |
| 127 | // 16 bytes — total 64*8 + 16. | 129 | // 16 bytes — total 64*8 + 16. |
| @@ -193,8 +195,16 @@ pub fn init() -> bool { | |||
| 193 | 195 | ||
| 194 | // TSS descriptor (16 bytes) at index 63. | 196 | // TSS descriptor (16 bytes) at index 63. |
| 195 | let tss_base = core::ptr::addr_of_mut!(TSS) as usize as u64; | 197 | let tss_base = core::ptr::addr_of_mut!(TSS) as usize as u64; |
| 196 | TSS.ist1 = core::ptr::addr_of_mut!(PF_STACK.0[0]) as usize as u64 + 4096; | 198 | // IST stacks come from the heap (see IST_STACK_SIZE): 32 KiB each, |
| 197 | TSS.ist2 = core::ptr::addr_of_mut!(DF_STACK.0[0]) as usize as u64 + 4096; | 199 | // well away from the kernel image/.bss so an overflowing fault |
| 200 | // path can't silently overwrite statics. | ||
| 201 | let pf = crate::memory::allocate(IST_STACK_SIZE); | ||
| 202 | let df = crate::memory::allocate(IST_STACK_SIZE); | ||
| 203 | if pf.is_null() || df.is_null() { | ||
| 204 | return false; | ||
| 205 | } | ||
| 206 | TSS.ist1 = pf as u64 + IST_STACK_SIZE as u64; | ||
| 207 | TSS.ist2 = df as u64 + IST_STACK_SIZE as u64; | ||
| 198 | TSS.iomap_base = TSS_SIZE as u16; // no I/O bitmap | 208 | TSS.iomap_base = TSS_SIZE as u16; // no I/O bitmap |
| 199 | 209 | ||
| 200 | let mut td = [0u8; 16]; | 210 | let mut td = [0u8; 16]; |
