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>
This commit is contained in:
Jan Kiszka 2012-03-06 15:22:02 +01:00 committed by Blue Swirl
parent dac6b1b22c
commit 3f2cbf0d1a
2 changed files with 8 additions and 6 deletions

View File

@ -241,6 +241,7 @@
#define PG_DIRTY_MASK (1 << PG_DIRTY_BIT) #define PG_DIRTY_MASK (1 << PG_DIRTY_BIT)
#define PG_PSE_MASK (1 << PG_PSE_BIT) #define PG_PSE_MASK (1 << PG_PSE_BIT)
#define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT) #define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT)
#define PG_HI_USER_MASK 0x7ff0000000000000LL
#define PG_NX_MASK (1LL << PG_NX_BIT) #define PG_NX_MASK (1LL << PG_NX_BIT)
#define PG_ERROR_W_BIT 1 #define PG_ERROR_W_BIT 1

View File

@ -885,8 +885,8 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
if (!(pml4e & PG_PRESENT_MASK)) if (!(pml4e & PG_PRESENT_MASK))
return -1; return -1;
pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) & pdpe_addr = ((pml4e & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) +
env->a20_mask; (((addr >> 30) & 0x1ff) << 3)) & env->a20_mask;
pdpe = ldq_phys(pdpe_addr); pdpe = ldq_phys(pdpe_addr);
if (!(pdpe & PG_PRESENT_MASK)) if (!(pdpe & PG_PRESENT_MASK))
return -1; return -1;
@ -900,8 +900,8 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
return -1; return -1;
} }
pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) & pde_addr = ((pdpe & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) +
env->a20_mask; (((addr >> 21) & 0x1ff) << 3)) & env->a20_mask;
pde = ldq_phys(pde_addr); pde = ldq_phys(pde_addr);
if (!(pde & PG_PRESENT_MASK)) { if (!(pde & PG_PRESENT_MASK)) {
return -1; 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 */ pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
} else { } else {
/* 4 KB page */ /* 4 KB page */
pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) & pte_addr = ((pde & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) +
env->a20_mask; (((addr >> 12) & 0x1ff) << 3)) & env->a20_mask;
page_size = 4096; page_size = 4096;
pte = ldq_phys(pte_addr); pte = ldq_phys(pte_addr);
} }
pte &= ~(PG_NX_MASK | PG_HI_USER_MASK);
if (!(pte & PG_PRESENT_MASK)) if (!(pte & PG_PRESENT_MASK))
return -1; return -1;
} else { } else {