]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
i386/tcg/svm: fix incorrect canonicalization
authorZero Tang <zero.tangptr@gmail.com>
Mon, 18 Aug 2025 10:16:47 +0000 (12:16 +0200)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 27 Aug 2025 08:57:03 +0000 (10:57 +0200)
For all 32-bit systems and 64-bit Windows systems, "long" is 4 bytes long.
Due to using "long" for a linear address, svm_canonicalization would
set all high bits to 1 when (assuming 48-bit linear address) the segment
base is bigger than 0x7FFF.

This fixes booting guests under TCG when the guest IDT and GDT bases are
above 0x7FFF, thereby resulting in incorrect bases. When an interrupt
arrives, it would trigger a #PF exception; the #PF would trigger again,
resulting in a #DF exception; the #PF would trigger for the third time,
resulting in triple-fault, and eventually causes a shutdown VM-Exit to
the hypervisor right after guest boot.

Cc: qemu-stable@nongnu.org
Signed-off-by: Zero Tang <zero.tangptr@gmail.com>
target/i386/tcg/system/svm_helper.c

index b27049b9ed138c2cebb1d7ff8b1448912cefe2a4..dea039b87a64553195a0883035ea9e7476f2bab7 100644 (file)
@@ -49,7 +49,7 @@ static void svm_save_seg(CPUX86State *env, int mmu_idx, hwaddr addr,
 static inline void svm_canonicalization(CPUX86State *env, target_ulong *seg_base)
 {
     uint16_t shift_amt = 64 - cpu_x86_virtual_addr_width(env);
-    *seg_base = ((((long) *seg_base) << shift_amt) >> shift_amt);
+    *seg_base = (((int64_t) *seg_base) << shift_amt) >> shift_amt;
 }
 
 static void svm_load_seg(CPUX86State *env, int mmu_idx, hwaddr addr,