mirror of https://github.com/xemu-project/xemu.git
target-i386: commonize checks for PAE and non-PAE
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
487cad8853
commit
7c82256006
target-i386
|
@ -659,6 +659,43 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
|
|||
}
|
||||
|
||||
ptep ^= PG_NX_MASK;
|
||||
} else {
|
||||
uint32_t pde;
|
||||
|
||||
/* page directory entry */
|
||||
pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
|
||||
env->a20_mask;
|
||||
pde = ldl_phys(cs->as, pde_addr);
|
||||
if (!(pde & PG_PRESENT_MASK)) {
|
||||
error_code = 0;
|
||||
goto do_fault;
|
||||
}
|
||||
/* if PSE bit is set, then we use a 4MB page */
|
||||
if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
|
||||
page_size = 4096 * 1024;
|
||||
ptep = pde;
|
||||
pte_addr = pde_addr;
|
||||
pte = pde;
|
||||
} else {
|
||||
if (!(pde & PG_ACCESSED_MASK)) {
|
||||
pde |= PG_ACCESSED_MASK;
|
||||
stl_phys_notdirty(cs->as, pde_addr, pde);
|
||||
}
|
||||
|
||||
/* page directory entry */
|
||||
pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
|
||||
env->a20_mask;
|
||||
pte = ldl_phys(cs->as, pte_addr);
|
||||
if (!(pte & PG_PRESENT_MASK)) {
|
||||
error_code = 0;
|
||||
goto do_fault;
|
||||
}
|
||||
/* combine pde and pte user and rw protections */
|
||||
ptep = pte & pde;
|
||||
page_size = 4096;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ptep & PG_NX_MASK) && is_write1 == 2) {
|
||||
goto do_fault_protect;
|
||||
}
|
||||
|
@ -702,82 +739,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
|
|||
/* align to page_size */
|
||||
pte &= ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);
|
||||
virt_addr = addr & ~(page_size - 1);
|
||||
} else {
|
||||
uint32_t pde;
|
||||
|
||||
/* page directory entry */
|
||||
pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
|
||||
env->a20_mask;
|
||||
pde = ldl_phys(cs->as, pde_addr);
|
||||
if (!(pde & PG_PRESENT_MASK)) {
|
||||
error_code = 0;
|
||||
goto do_fault;
|
||||
}
|
||||
/* if PSE bit is set, then we use a 4MB page */
|
||||
if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
|
||||
page_size = 4096 * 1024;
|
||||
ptep = pde;
|
||||
pte_addr = pde_addr;
|
||||
pte = pde;
|
||||
} else {
|
||||
if (!(pde & PG_ACCESSED_MASK)) {
|
||||
pde |= PG_ACCESSED_MASK;
|
||||
stl_phys_notdirty(cs->as, pde_addr, pde);
|
||||
}
|
||||
|
||||
/* page directory entry */
|
||||
pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
|
||||
env->a20_mask;
|
||||
pte = ldl_phys(cs->as, pte_addr);
|
||||
if (!(pte & PG_PRESENT_MASK)) {
|
||||
error_code = 0;
|
||||
goto do_fault;
|
||||
}
|
||||
/* combine pde and pte user and rw protections */
|
||||
ptep = pte & pde;
|
||||
page_size = 4096;
|
||||
}
|
||||
switch (mmu_idx) {
|
||||
case MMU_USER_IDX:
|
||||
if (!(ptep & PG_USER_MASK)) {
|
||||
goto do_fault_protect;
|
||||
}
|
||||
if (is_write && !(ptep & PG_RW_MASK)) {
|
||||
goto do_fault_protect;
|
||||
}
|
||||
break;
|
||||
|
||||
case MMU_KSMAP_IDX:
|
||||
if (is_write1 != 2 && (ptep & PG_USER_MASK)) {
|
||||
goto do_fault_protect;
|
||||
}
|
||||
/* fall through */
|
||||
case MMU_KNOSMAP_IDX:
|
||||
if (is_write1 == 2 && (env->cr[4] & CR4_SMEP_MASK) &&
|
||||
(ptep & PG_USER_MASK)) {
|
||||
goto do_fault_protect;
|
||||
}
|
||||
if ((env->cr[0] & CR0_WP_MASK) &&
|
||||
is_write && !(ptep & PG_RW_MASK)) {
|
||||
goto do_fault_protect;
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* cannot happen */
|
||||
break;
|
||||
}
|
||||
is_dirty = is_write && !(pte & PG_DIRTY_MASK);
|
||||
if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
|
||||
pte |= PG_ACCESSED_MASK;
|
||||
if (is_dirty) {
|
||||
pte |= PG_DIRTY_MASK;
|
||||
}
|
||||
stl_phys_notdirty(cs->as, pte_addr, pte);
|
||||
}
|
||||
/* align to page_size */
|
||||
pte &= ~((page_size - 1) & ~0xfff);
|
||||
virt_addr = addr & ~(page_size - 1);
|
||||
}
|
||||
/* the page can be put in the TLB */
|
||||
prot = PAGE_READ;
|
||||
if (!(ptep & PG_NX_MASK))
|
||||
|
|
Loading…
Reference in New Issue