diff options
author | Jan Kiszka <jan.kiszka@siemens.com> | 2012-03-06 15:22:02 +0100 |
---|---|---|
committer | Blue Swirl <blauwirbel@gmail.com> | 2012-03-11 11:22:39 +0000 |
commit | 3f2cbf0d1a1340bed4a63e05b044c46df93f4768 (patch) | |
tree | c6ef216ba1164a3649444af31d266dd53a73c1b1 /target-i386/helper.c | |
parent | dac6b1b22cbad29ca34735a1e56c9feb9586e3c0 (diff) | |
download | qemu-3f2cbf0d1a1340bed4a63e05b044c46df93f4768.tar.gz qemu-3f2cbf0d1a1340bed4a63e05b044c46df93f4768.tar.bz2 qemu-3f2cbf0d1a1340bed4a63e05b044c46df93f4768.zip |
target-i386: Mask NX bit from cpu_get_phys_page_debug result
This was a long pending bug, now revealed by the assert in
phys_page_find that stumbled over the large page index returned by
cpu_get_phys_page_debug for NX-marked pages: We need to mask out NX and
all user-definable bits 52..62 from PDEs and the final PTE to avoid
corrupting physical addresses.
Reviewed-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Diffstat (limited to 'target-i386/helper.c')
-rw-r--r-- | target-i386/helper.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/target-i386/helper.c b/target-i386/helper.c index af6bba2680..f4f3c2726a 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -885,8 +885,8 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) if (!(pml4e & PG_PRESENT_MASK)) return -1; - pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) & - env->a20_mask; + pdpe_addr = ((pml4e & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) + + (((addr >> 30) & 0x1ff) << 3)) & env->a20_mask; pdpe = ldq_phys(pdpe_addr); if (!(pdpe & PG_PRESENT_MASK)) return -1; @@ -900,8 +900,8 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) return -1; } - pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) & - env->a20_mask; + pde_addr = ((pdpe & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) + + (((addr >> 21) & 0x1ff) << 3)) & env->a20_mask; pde = ldq_phys(pde_addr); if (!(pde & PG_PRESENT_MASK)) { return -1; @@ -912,11 +912,12 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */ } else { /* 4 KB page */ - pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) & - env->a20_mask; + pte_addr = ((pde & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) + + (((addr >> 12) & 0x1ff) << 3)) & env->a20_mask; page_size = 4096; pte = ldq_phys(pte_addr); } + pte &= ~(PG_NX_MASK | PG_HI_USER_MASK); if (!(pte & PG_PRESENT_MASK)) return -1; } else { |