From 45389dfedc3c4d8c11ef0e22c0dce4848f41ccbf Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 26 Jan 2024 12:38:06 +0100 Subject: [PATCH] SVSM/cpu/gdt: Fix boot issue around TSS loading in release builds In release builds the compiler did not recognize that the assembly between set_tss_entry() and clear_tss_entry() did actually consume the data written by set_tss_entry(). This make the compiler optimize away the set_tss_entry() call entirely in release builds, making the SVSM fail to boot. Use volatile writes to update the GDT for TSS entries to force the compiler not to optimize the writes away. Signed-off-by: Joerg Roedel --- src/cpu/gdt.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/cpu/gdt.rs b/src/cpu/gdt.rs index f97fcab83..72e627ca7 100644 --- a/src/cpu/gdt.rs +++ b/src/cpu/gdt.rs @@ -107,28 +107,27 @@ impl GDT { } } - fn set_tss_entry(&mut self, desc0: GDTEntry, desc1: GDTEntry) { + unsafe fn set_tss_entry(&mut self, desc0: GDTEntry, desc1: GDTEntry) { let idx = (SVSM_TSS / 8) as usize; - self.entries[idx] = desc0; - self.entries[idx + 1] = desc1; - } + let tss_entries = &self.entries[idx..idx + 1].as_mut_ptr(); - fn clear_tss_entry(&mut self) { - let idx = (SVSM_TSS / 8) as usize; + tss_entries.add(0).write_volatile(desc0); + tss_entries.add(1).write_volatile(desc1); + } - self.entries[idx] = GDTEntry::null(); - self.entries[idx + 1] = GDTEntry::null(); + unsafe fn clear_tss_entry(&mut self) { + self.set_tss_entry(GDTEntry::null(), GDTEntry::null()); } pub fn load_tss(&mut self, tss: &X86Tss) { let (desc0, desc1) = tss.to_gdt_entry(); - self.set_tss_entry(desc0, desc1); unsafe { + self.set_tss_entry(desc0, desc1); asm!("ltr %ax", in("ax") SVSM_TSS, options(att_syntax)); + self.clear_tss_entry() } - self.clear_tss_entry() } }