summaryrefslogtreecommitdiffstats
path: root/rsnix/src/gdt.rs
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-08-02 15:21:34 +0200
committersalmonik <salmonik@tuta.io>2026-08-02 15:21:34 +0200
commitc7d92071e1dd11c45999457b16554b4abaa73b28 (patch)
treeaff7c7f19adcffe1dd91e1c2514af02c77fd524e /rsnix/src/gdt.rs
parentv0.5.5: fix real-hardware boot crash — shadow back in heap as first allocation (diff)
downloadrs-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.rs24
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
121struct 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.
125const IST_STACK_SIZE: usize = 32 * 1024;
122 126
123static mut PF_STACK: Page = Page([0; 4096]);
124static mut DF_STACK: Page = Page([0; 4096]);
125static mut TSS: Tss = Tss::zero(); 127static 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];