Support resolving addresses in PAE mode in cpu_get_phys_page_debug
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1240 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
82e41634cd
commit
f51589dad5
@ -742,33 +742,87 @@ target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
|
|||||||
#else
|
#else
|
||||||
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
|
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
|
||||||
{
|
{
|
||||||
uint8_t *pde_ptr, *pte_ptr;
|
uint32_t pde_addr, pte_addr;
|
||||||
uint32_t pde, pte, paddr, page_offset, page_size;
|
uint32_t pde, pte, paddr, page_offset, page_size;
|
||||||
|
|
||||||
if (!(env->cr[0] & CR0_PG_MASK)) {
|
if (env->cr[4] & CR4_PAE_MASK) {
|
||||||
pte = addr;
|
uint32_t pdpe_addr, pde_addr, pte_addr;
|
||||||
page_size = 4096;
|
uint32_t pdpe;
|
||||||
} else {
|
|
||||||
/* page directory entry */
|
/* XXX: we only use 32 bit physical addresses */
|
||||||
pde_ptr = phys_ram_base +
|
#ifdef TARGET_X86_64
|
||||||
(((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask);
|
if (env->hflags & HF_LMA_MASK) {
|
||||||
pde = ldl_raw(pde_ptr);
|
uint32_t pml4e_addr, pml4e;
|
||||||
if (!(pde & PG_PRESENT_MASK))
|
int32_t sext;
|
||||||
|
|
||||||
|
/* test virtual address sign extension */
|
||||||
|
sext = (int64_t)addr >> 47;
|
||||||
|
if (sext != 0 && sext != -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
|
||||||
|
env->a20_mask;
|
||||||
|
pml4e = ldl_phys_aligned(pml4e_addr);
|
||||||
|
if (!(pml4e & PG_PRESENT_MASK))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
|
||||||
|
env->a20_mask;
|
||||||
|
pdpe = ldl_phys_aligned(pdpe_addr);
|
||||||
|
if (!(pdpe & PG_PRESENT_MASK))
|
||||||
|
return -1;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 30) << 3)) &
|
||||||
|
env->a20_mask;
|
||||||
|
pdpe = ldl_phys_aligned(pdpe_addr);
|
||||||
|
if (!(pdpe & PG_PRESENT_MASK))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
|
||||||
|
env->a20_mask;
|
||||||
|
pde = ldl_phys_aligned(pde_addr);
|
||||||
|
if (!(pde & PG_PRESENT_MASK)) {
|
||||||
return -1;
|
return -1;
|
||||||
if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
|
}
|
||||||
pte = pde & ~0x003ff000; /* align to 4MB */
|
if (pde & PG_PSE_MASK) {
|
||||||
page_size = 4096 * 1024;
|
/* 2 MB page */
|
||||||
|
page_size = 2048 * 1024;
|
||||||
|
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;
|
||||||
|
page_size = 4096;
|
||||||
|
pte = ldl_phys_aligned(pte_addr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!(env->cr[0] & CR0_PG_MASK)) {
|
||||||
|
pte = addr;
|
||||||
|
page_size = 4096;
|
||||||
} else {
|
} else {
|
||||||
/* page directory entry */
|
/* page directory entry */
|
||||||
pte_ptr = phys_ram_base +
|
pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask;
|
||||||
(((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask);
|
pde = ldl_phys_aligned(pde_addr);
|
||||||
pte = ldl_raw(pte_ptr);
|
if (!(pde & PG_PRESENT_MASK))
|
||||||
if (!(pte & PG_PRESENT_MASK))
|
|
||||||
return -1;
|
return -1;
|
||||||
page_size = 4096;
|
if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
|
||||||
|
pte = pde & ~0x003ff000; /* align to 4MB */
|
||||||
|
page_size = 4096 * 1024;
|
||||||
|
} else {
|
||||||
|
/* page directory entry */
|
||||||
|
pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
|
||||||
|
pte = ldl_phys_aligned(pte_addr);
|
||||||
|
if (!(pte & PG_PRESENT_MASK))
|
||||||
|
return -1;
|
||||||
|
page_size = 4096;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
pte = pte & env->a20_mask;
|
||||||
}
|
}
|
||||||
pte = pte & env->a20_mask;
|
|
||||||
page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
|
page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
|
||||||
paddr = (pte & TARGET_PAGE_MASK) + page_offset;
|
paddr = (pte & TARGET_PAGE_MASK) + page_offset;
|
||||||
return paddr;
|
return paddr;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user