diff options
author | Paolo Bonzini | 2021-11-04 14:47:46 +0100 |
---|---|---|
committer | Paolo Bonzini | 2021-11-08 08:55:20 +0100 |
commit | b04dc92e013d55c9ac8082caefff45dcfb1310e7 (patch) | |
tree | da65b6752a9cd55fd9b2a7d9ecb162a5e4373a3f /target/i386 | |
parent | target-i386: mmu: use pg_mode instead of HF_LMA_MASK (diff) | |
download | qemu-b04dc92e013d55c9ac8082caefff45dcfb1310e7.tar.gz qemu-b04dc92e013d55c9ac8082caefff45dcfb1310e7.tar.xz qemu-b04dc92e013d55c9ac8082caefff45dcfb1310e7.zip |
target-i386: mmu: fix handling of noncanonical virtual addresses
mmu_translate is supposed to return an error code for page faults; it is
not able to handle other exceptions. The #GP case for noncanonical
virtual addresses is not handled correctly, and incorrectly raised as
a page fault with error code 1. Since it cannot happen for nested
page tables, move it directly to handle_mmu_fault, even before the
invocation of mmu_translate.
Fixes: #676
Fixes: 661ff4879e ("target/i386: extract mmu_translate", 2021-05-11)
Cc: qemu-stable@nongnu.org
Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'target/i386')
-rw-r--r-- | target/i386/tcg/sysemu/excp_helper.c | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/target/i386/tcg/sysemu/excp_helper.c b/target/i386/tcg/sysemu/excp_helper.c index 492b777de9..5ba739fbed 100644 --- a/target/i386/tcg/sysemu/excp_helper.c +++ b/target/i386/tcg/sysemu/excp_helper.c @@ -94,15 +94,6 @@ static int mmu_translate(CPUState *cs, hwaddr addr, MMUTranslateFunc get_hphys_f bool la57 = pg_mode & PG_MODE_LA57; uint64_t pml5e_addr, pml5e; uint64_t pml4e_addr, pml4e; - int32_t sext; - - /* test virtual address sign extension */ - sext = la57 ? (int64_t)addr >> 56 : (int64_t)addr >> 47; - if (get_hphys_func && sext != 0 && sext != -1) { - env->error_code = 0; - cs->exception_index = EXCP0D_GPF; - return 1; - } if (la57) { pml5e_addr = ((cr3 & ~0xfff) + @@ -423,6 +414,18 @@ static int handle_mmu_fault(CPUState *cs, vaddr addr, int size, page_size = 4096; } else { pg_mode = get_pg_mode(env); + if (pg_mode & PG_MODE_LMA) { + int32_t sext; + + /* test virtual address sign extension */ + sext = (int64_t)addr >> (pg_mode & PG_MODE_LA57 ? 56 : 47); + if (sext != 0 && sext != -1) { + env->error_code = 0; + cs->exception_index = EXCP0D_GPF; + return 1; + } + } + error_code = mmu_translate(cs, addr, get_hphys, env->cr[3], is_write1, mmu_idx, pg_mode, &paddr, &page_size, &prot); |