diff options
| author | salmonik <salmonik@tuta.io> | 2026-08-02 15:21:34 +0200 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-08-02 15:21:34 +0200 |
| commit | c7d92071e1dd11c45999457b16554b4abaa73b28 (patch) | |
| tree | aff7c7f19adcffe1dd91e1c2514af02c77fd524e /rsnix/src/gdt.rs | |
| parent | v0.5.5: fix real-hardware boot crash — shadow back in heap as first allocation (diff) | |
| download | rs-dos-c7d92071e1dd11c45999457b16554b4abaa73b28.tar.gz rs-dos-c7d92071e1dd11c45999457b16554b4abaa73b28.zip | |
v0.5.5: crash reports go to a dedicated CRASHLOG USB stick
The fault handler now writes crash.log to the volume labeled CRASHLOG
(label-selected via fat::crash_vol), falling back to slot 0. On real
hardware the boot USB may be unwritable, so a second stick labeled
CRASHLOG survives the write; the shell auto-prints the previous crash
report from it at next boot (read_crash_log resolves /disk/<uid>/crash.log
through the FAT path, since Disk nodes hold no cached children).
- fat.rs: volume_label() + crash_vol() (no allocation)
- fs.rs: write_crash_log targets crash_vol(); read_crash_log prefers the
CRASHLOG disk node; drop now-unused first_disk()
- mkdisk.sh: --label option
- test-fault.sh: boots with a dedicated CRASHLOG stick (mkfs -F 32 -n
CRASHLOG), verifies crash.log lands there and NOT on the ESP
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]; |
