diff --git a/kernel/src/cpu/gdt.rs b/kernel/src/cpu/gdt.rs index 1ff46be78..0b5f29a4d 100644 --- a/kernel/src/cpu/gdt.rs +++ b/kernel/src/cpu/gdt.rs @@ -80,7 +80,18 @@ impl GDT { let tss_entries = &self.entries[idx..idx + 1].as_mut_ptr(); + // SAFETY: + // For add(): + // - idx and idx + size_of::() don't overflow isize. + // - the borrow checker guarantees that self is still allocated + // - self.entries[6:8] fits in self's allocation. + // For write_volatile(): + // - the borrow checker guarantees that self.entries is allocated + // - alignment is checked inside unsafe { + assert_eq!(align_of_val(&tss_entries.add(0)), align_of::()); + assert_eq!(align_of_val(&tss_entries.add(1)), align_of::()); + tss_entries.add(0).write_volatile(desc0); tss_entries.add(1).write_volatile(desc1); } @@ -93,11 +104,12 @@ impl GDT { pub fn load_tss(&mut self, tss: &X86Tss) { let (desc0, desc1) = tss.to_gdt_entry(); - unsafe { - self.set_tss_entry(desc0, desc1); - asm!("ltr %ax", in("ax") SVSM_TSS, options(att_syntax)); - self.clear_tss_entry() - } + self.set_tss_entry(desc0, desc1); + // SAFETY: loading task register must me done in assembly. + // It's safe to do so as long as a global GDT is in use and still + // allocated, which is always our case. + unsafe { asm!("ltr %ax", in("ax") SVSM_TSS, options(att_syntax)) }; + self.clear_tss_entry() } pub fn kernel_cs(&self) -> GDTEntry {