mirror of https://gitee.com/openkylin/qemu.git
x86/x86-64 MMU PAE fixes
This patch fixes MMU emulation in PAE mode for > 4GB physical addresses: - a20_mask should have the correct size to not clear the high part of the addresses. - PHYS_ADDR_MASK should not clear the high part of the addresses. - pdpe, pde and pte could be located anywhere in memory on x86-64, but only in the first 4GB on x86, define their pointer to as target_ulong. - pml4e_addr could be located anywhere in memory, define its pointer as uint64_t. - paddr represents a physical address and thus should be of type target_phys_addr_t. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4239 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
967032c3d5
commit
0ba5f006bb
|
@ -499,7 +499,7 @@ typedef struct CPUX86State {
|
|||
SegmentCache idt; /* only base and limit are used */
|
||||
|
||||
target_ulong cr[9]; /* NOTE: cr1, cr5-7 are unused */
|
||||
uint32_t a20_mask;
|
||||
uint64_t a20_mask;
|
||||
|
||||
/* FPU state */
|
||||
unsigned int fpstt; /* top of stack index */
|
||||
|
|
|
@ -377,7 +377,7 @@ void cpu_reset(CPUX86State *env)
|
|||
env->hflags |= HF_GIF_MASK;
|
||||
|
||||
cpu_x86_update_cr0(env, 0x60000010);
|
||||
env->a20_mask = 0xffffffff;
|
||||
env->a20_mask = ~0x0;
|
||||
env->smbase = 0x30000;
|
||||
|
||||
env->idt.limit = 0xffff;
|
||||
|
@ -695,7 +695,7 @@ void cpu_x86_set_a20(CPUX86State *env, int a20_state)
|
|||
/* when a20 is changed, all the MMU mappings are invalid, so
|
||||
we must flush everything */
|
||||
tlb_flush(env, 1);
|
||||
env->a20_mask = 0xffefffff | (a20_state << 20);
|
||||
env->a20_mask = (~0x100000) | (a20_state << 20);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -800,7 +800,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
|
|||
|
||||
#else
|
||||
|
||||
#define PHYS_ADDR_MASK 0xfffff000
|
||||
#define PHYS_ADDR_MASK (~0xfff)
|
||||
|
||||
/* return value:
|
||||
-1 = cannot handle fault
|
||||
|
@ -812,9 +812,10 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
|
|||
int is_write1, int mmu_idx, int is_softmmu)
|
||||
{
|
||||
uint64_t ptep, pte;
|
||||
uint32_t pdpe_addr, pde_addr, pte_addr;
|
||||
target_ulong pde_addr, pte_addr;
|
||||
int error_code, is_dirty, prot, page_size, ret, is_write, is_user;
|
||||
unsigned long paddr, page_offset;
|
||||
target_phys_addr_t paddr;
|
||||
uint32_t page_offset;
|
||||
target_ulong vaddr, virt_addr;
|
||||
|
||||
is_user = mmu_idx == MMU_USER_IDX;
|
||||
|
@ -834,12 +835,11 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
|
|||
|
||||
if (env->cr[4] & CR4_PAE_MASK) {
|
||||
uint64_t pde, pdpe;
|
||||
target_ulong pdpe_addr;
|
||||
|
||||
/* XXX: we only use 32 bit physical addresses */
|
||||
#ifdef TARGET_X86_64
|
||||
if (env->hflags & HF_LMA_MASK) {
|
||||
uint32_t pml4e_addr;
|
||||
uint64_t pml4e;
|
||||
uint64_t pml4e_addr, pml4e;
|
||||
int32_t sext;
|
||||
|
||||
/* test virtual address sign extension */
|
||||
|
@ -1101,17 +1101,19 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
|
|||
|
||||
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
|
||||
{
|
||||
uint32_t pde_addr, pte_addr;
|
||||
uint32_t pde, pte, paddr, page_offset, page_size;
|
||||
target_ulong pde_addr, pte_addr;
|
||||
uint64_t pte;
|
||||
target_phys_addr_t paddr;
|
||||
uint32_t page_offset;
|
||||
int page_size;
|
||||
|
||||
if (env->cr[4] & CR4_PAE_MASK) {
|
||||
uint32_t pdpe_addr, pde_addr, pte_addr;
|
||||
uint32_t pdpe;
|
||||
target_ulong pdpe_addr;
|
||||
uint64_t pde, pdpe;
|
||||
|
||||
/* XXX: we only use 32 bit physical addresses */
|
||||
#ifdef TARGET_X86_64
|
||||
if (env->hflags & HF_LMA_MASK) {
|
||||
uint32_t pml4e_addr, pml4e;
|
||||
uint64_t pml4e_addr, pml4e;
|
||||
int32_t sext;
|
||||
|
||||
/* test virtual address sign extension */
|
||||
|
@ -1121,13 +1123,13 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
|
|||
|
||||
pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
|
||||
env->a20_mask;
|
||||
pml4e = ldl_phys(pml4e_addr);
|
||||
pml4e = ldq_phys(pml4e_addr);
|
||||
if (!(pml4e & PG_PRESENT_MASK))
|
||||
return -1;
|
||||
|
||||
pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
|
||||
env->a20_mask;
|
||||
pdpe = ldl_phys(pdpe_addr);
|
||||
pdpe = ldq_phys(pdpe_addr);
|
||||
if (!(pdpe & PG_PRESENT_MASK))
|
||||
return -1;
|
||||
} else
|
||||
|
@ -1135,14 +1137,14 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
|
|||
{
|
||||
pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
|
||||
env->a20_mask;
|
||||
pdpe = ldl_phys(pdpe_addr);
|
||||
pdpe = ldq_phys(pdpe_addr);
|
||||
if (!(pdpe & PG_PRESENT_MASK))
|
||||
return -1;
|
||||
}
|
||||
|
||||
pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
|
||||
env->a20_mask;
|
||||
pde = ldl_phys(pde_addr);
|
||||
pde = ldq_phys(pde_addr);
|
||||
if (!(pde & PG_PRESENT_MASK)) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -1155,9 +1157,11 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
|
|||
pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
|
||||
env->a20_mask;
|
||||
page_size = 4096;
|
||||
pte = ldl_phys(pte_addr);
|
||||
pte = ldq_phys(pte_addr);
|
||||
}
|
||||
} else {
|
||||
uint32_t pde;
|
||||
|
||||
if (!(env->cr[0] & CR0_PG_MASK)) {
|
||||
pte = addr;
|
||||
page_size = 4096;
|
||||
|
|
Loading…
Reference in New Issue