From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:41286) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S4vHJ-00073Y-TY for qemu-devel@nongnu.org; Tue, 06 Mar 2012 09:22:18 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S4vHE-0004F8-71 for qemu-devel@nongnu.org; Tue, 06 Mar 2012 09:22:13 -0500 Received: from david.siemens.de ([192.35.17.14]:26577) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S4vHD-0004Ew-Te for qemu-devel@nongnu.org; Tue, 06 Mar 2012 09:22:08 -0500 Message-ID: <4F561D8A.4010404@siemens.com> Date: Tue, 06 Mar 2012 15:22:02 +0100 From: Jan Kiszka MIME-Version: 1.0 References: <4F5601BF.3070107@siemens.com> <4F560980.2060803@redhat.com> <4F560C13.4030900@redhat.com> In-Reply-To: <4F560C13.4030900@redhat.com> Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PATCH v2] target-i386: Mask NX bit from cpu_get_phys_page_debug result List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Blue Swirl , Anthony Liguori , qemu-devel Cc: Avi Kivity 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. Signed-off-by: Jan Kiszka --- Changes in v2 (as suggested by Avi): - Mask PDEs as well - Mask user-definable bits target-i386/cpu.h | 1 + target-i386/helper.c | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 196b0c5..36e3d29 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -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 diff --git a/target-i386/helper.c b/target-i386/helper.c index af6bba2..f4f3c27 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 { -- 1.7.3.4