aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZero Tang <zero.tangptr@gmail.com>2025-08-18 12:16:47 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2025-08-27 10:57:03 +0200
commitc12cbaa007c9da97a11e74119ea3aed9fcc3ac4c (patch)
tree950cc4f8be357511c2f964de90078885429fecba
parenta7542a38f399c50337e10aadd60513a400c45013 (diff)
downloadqemu-c12cbaa007c9da97a11e74119ea3aed9fcc3ac4c.zip
qemu-c12cbaa007c9da97a11e74119ea3aed9fcc3ac4c.tar.gz
qemu-c12cbaa007c9da97a11e74119ea3aed9fcc3ac4c.tar.bz2
i386/tcg/svm: fix incorrect canonicalization
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>
-rw-r--r--target/i386/tcg/system/svm_helper.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/target/i386/tcg/system/svm_helper.c b/target/i386/tcg/system/svm_helper.c
index b27049b..dea039b 100644
--- a/target/i386/tcg/system/svm_helper.c
+++ b/target/i386/tcg/system/svm_helper.c
@@ -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,