Commit 3f2cbf0d authored by Jan Kiszka's avatar Jan Kiszka Committed by Blue Swirl
Browse files

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: default avatarAvi Kivity <avi@redhat.com>
Signed-off-by: default avatarJan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: default avatarBlue Swirl <blauwirbel@gmail.com>
parent dac6b1b2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -241,6 +241,7 @@
#define PG_DIRTY_MASK	 (1 << PG_DIRTY_BIT)
#define PG_PSE_MASK	 (1 << PG_PSE_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_ERROR_W_BIT     1
+7 −6
Original line number Diff line number Diff line
@@ -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 {