mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-02-02 04:51:05 +00:00
target/i386: enable A20 automatically in system management mode
Ignore env->a20_mask when running in system management mode. Backports commit c8bc83a4dd29a9a33f5be81686bfe6e2e628097b from qemu
This commit is contained in:
parent
fb8d3e2f6a
commit
710f393c13
|
@ -272,25 +272,27 @@ void x86_cpu_get_memory_mapping(CPUState *cs, MemoryMappingList *list,
|
||||||
{
|
{
|
||||||
X86CPU *cpu = X86_CPU(cs->uc, cs);
|
X86CPU *cpu = X86_CPU(cs->uc, cs);
|
||||||
CPUX86State *env = &cpu->env;
|
CPUX86State *env = &cpu->env;
|
||||||
|
int32_t a20_mask;
|
||||||
|
|
||||||
if (!cpu_paging_enabled(cs)) {
|
if (!cpu_paging_enabled(cs)) {
|
||||||
/* paging is disabled */
|
/* paging is disabled */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a20_mask = x86_get_a20_mask(env);
|
||||||
if (env->cr[4] & CR4_PAE_MASK) {
|
if (env->cr[4] & CR4_PAE_MASK) {
|
||||||
#ifdef TARGET_X86_64
|
#ifdef TARGET_X86_64
|
||||||
if (env->hflags & HF_LMA_MASK) {
|
if (env->hflags & HF_LMA_MASK) {
|
||||||
if (env->cr[4] & CR4_LA57_MASK) {
|
if (env->cr[4] & CR4_LA57_MASK) {
|
||||||
hwaddr pml5e_addr;
|
hwaddr pml5e_addr;
|
||||||
|
|
||||||
pml5e_addr = (env->cr[3] & PLM4_ADDR_MASK) & env->a20_mask;
|
pml5e_addr = (env->cr[3] & PLM4_ADDR_MASK) & a20_mask;
|
||||||
walk_pml5e(list, cs->as, pml5e_addr, env->a20_mask);
|
walk_pml5e(list, cs->as, pml5e_addr, a20_mask);
|
||||||
} else {
|
} else {
|
||||||
hwaddr pml4e_addr;
|
hwaddr pml4e_addr;
|
||||||
|
|
||||||
pml4e_addr = (env->cr[3] & PLM4_ADDR_MASK) & env->a20_mask;
|
pml4e_addr = (env->cr[3] & PLM4_ADDR_MASK) & a20_mask;
|
||||||
walk_pml4e(list, cs->as, pml4e_addr, env->a20_mask,
|
walk_pml4e(list, cs->as, pml4e_addr, a20_mask,
|
||||||
0xffffULL << 48);
|
0xffffULL << 48);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
@ -298,16 +300,16 @@ void x86_cpu_get_memory_mapping(CPUState *cs, MemoryMappingList *list,
|
||||||
{
|
{
|
||||||
hwaddr pdpe_addr;
|
hwaddr pdpe_addr;
|
||||||
|
|
||||||
pdpe_addr = (env->cr[3] & ~0x1f) & env->a20_mask;
|
pdpe_addr = (env->cr[3] & ~0x1f) & a20_mask;
|
||||||
walk_pdpe2(list, cs->as, pdpe_addr, env->a20_mask);
|
walk_pdpe2(list, cs->as, pdpe_addr, a20_mask);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
hwaddr pde_addr;
|
hwaddr pde_addr;
|
||||||
bool pse;
|
bool pse;
|
||||||
|
|
||||||
pde_addr = (env->cr[3] & ~0xfff) & env->a20_mask;
|
pde_addr = (env->cr[3] & ~0xfff) & a20_mask;
|
||||||
pse = !!(env->cr[4] & CR4_PSE_MASK);
|
pse = !!(env->cr[4] & CR4_PSE_MASK);
|
||||||
walk_pde2(list, cs->as, pde_addr, env->a20_mask, pse);
|
walk_pde2(list, cs->as, pde_addr, a20_mask, pse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1600,6 +1600,15 @@ static inline MemTxAttrs cpu_get_mem_attrs(CPUX86State *env)
|
||||||
return attrs;
|
return attrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int32_t x86_get_a20_mask(CPUX86State *env)
|
||||||
|
{
|
||||||
|
if (env->hflags & HF_SMM_MASK) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return env->a20_mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* fpu_helper.c */
|
/* fpu_helper.c */
|
||||||
void cpu_set_mxcsr(CPUX86State *env, uint32_t val);
|
void cpu_set_mxcsr(CPUX86State *env, uint32_t val);
|
||||||
void cpu_set_fpuc(CPUX86State *env, uint16_t val);
|
void cpu_set_fpuc(CPUX86State *env, uint16_t val);
|
||||||
|
|
|
@ -532,6 +532,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
|
||||||
X86CPU *cpu = X86_CPU(cs->uc, cs);
|
X86CPU *cpu = X86_CPU(cs->uc, cs);
|
||||||
CPUX86State *env = &cpu->env;
|
CPUX86State *env = &cpu->env;
|
||||||
uint64_t ptep, pte;
|
uint64_t ptep, pte;
|
||||||
|
int32_t a20_mask;
|
||||||
target_ulong pde_addr, pte_addr;
|
target_ulong pde_addr, pte_addr;
|
||||||
int error_code = 0;
|
int error_code = 0;
|
||||||
int is_dirty, prot, page_size, is_write, is_user;
|
int is_dirty, prot, page_size, is_write, is_user;
|
||||||
|
@ -547,6 +548,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
|
||||||
#endif
|
#endif
|
||||||
is_write = is_write1 & 1;
|
is_write = is_write1 & 1;
|
||||||
|
|
||||||
|
a20_mask = x86_get_a20_mask(env);
|
||||||
if (!(env->cr[0] & CR0_PG_MASK)) {
|
if (!(env->cr[0] & CR0_PG_MASK)) {
|
||||||
pte = addr;
|
pte = addr;
|
||||||
#ifdef TARGET_X86_64
|
#ifdef TARGET_X86_64
|
||||||
|
@ -585,7 +587,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
|
||||||
|
|
||||||
if (la57) {
|
if (la57) {
|
||||||
pml5e_addr = ((env->cr[3] & ~0xfff) +
|
pml5e_addr = ((env->cr[3] & ~0xfff) +
|
||||||
(((addr >> 48) & 0x1ff) << 3)) & env->a20_mask;
|
(((addr >> 48) & 0x1ff) << 3)) & a20_mask;
|
||||||
pml5e = x86_ldq_phys(cs, pml5e_addr);
|
pml5e = x86_ldq_phys(cs, pml5e_addr);
|
||||||
if (!(pml5e & PG_PRESENT_MASK)) {
|
if (!(pml5e & PG_PRESENT_MASK)) {
|
||||||
goto do_fault;
|
goto do_fault;
|
||||||
|
@ -604,7 +606,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
pml4e_addr = ((pml5e & PG_ADDRESS_MASK) +
|
pml4e_addr = ((pml5e & PG_ADDRESS_MASK) +
|
||||||
(((addr >> 39) & 0x1ff) << 3)) & env->a20_mask;
|
(((addr >> 39) & 0x1ff) << 3)) & a20_mask;
|
||||||
pml4e = x86_ldq_phys(cs, pml4e_addr);
|
pml4e = x86_ldq_phys(cs, pml4e_addr);
|
||||||
if (!(pml4e & PG_PRESENT_MASK)) {
|
if (!(pml4e & PG_PRESENT_MASK)) {
|
||||||
goto do_fault;
|
goto do_fault;
|
||||||
|
@ -618,7 +620,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
|
||||||
}
|
}
|
||||||
ptep &= pml4e ^ PG_NX_MASK;
|
ptep &= pml4e ^ PG_NX_MASK;
|
||||||
pdpe_addr = ((pml4e & PG_ADDRESS_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
|
pdpe_addr = ((pml4e & PG_ADDRESS_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
|
||||||
env->a20_mask;
|
a20_mask;
|
||||||
pdpe = x86_ldq_phys(cs, pdpe_addr);
|
pdpe = x86_ldq_phys(cs, pdpe_addr);
|
||||||
if (!(pdpe & PG_PRESENT_MASK)) {
|
if (!(pdpe & PG_PRESENT_MASK)) {
|
||||||
goto do_fault;
|
goto do_fault;
|
||||||
|
@ -656,7 +658,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
pde_addr = ((pdpe & PG_ADDRESS_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
|
pde_addr = ((pdpe & PG_ADDRESS_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
|
||||||
env->a20_mask;
|
a20_mask;
|
||||||
pde = x86_ldq_phys(cs, pde_addr);
|
pde = x86_ldq_phys(cs, pde_addr);
|
||||||
if (!(pde & PG_PRESENT_MASK)) {
|
if (!(pde & PG_PRESENT_MASK)) {
|
||||||
goto do_fault;
|
goto do_fault;
|
||||||
|
@ -678,7 +680,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
|
||||||
x86_stl_phys_notdirty(cs, pde_addr, pde);
|
x86_stl_phys_notdirty(cs, pde_addr, pde);
|
||||||
}
|
}
|
||||||
pte_addr = ((pde & PG_ADDRESS_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
|
pte_addr = ((pde & PG_ADDRESS_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
|
||||||
env->a20_mask;
|
a20_mask;
|
||||||
pte = x86_ldq_phys(cs, pte_addr);
|
pte = x86_ldq_phys(cs, pte_addr);
|
||||||
if (!(pte & PG_PRESENT_MASK)) {
|
if (!(pte & PG_PRESENT_MASK)) {
|
||||||
goto do_fault;
|
goto do_fault;
|
||||||
|
@ -694,7 +696,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
|
||||||
|
|
||||||
/* page directory entry */
|
/* page directory entry */
|
||||||
pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
|
pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
|
||||||
env->a20_mask;
|
a20_mask;
|
||||||
pde = x86_ldl_phys(cs, pde_addr);
|
pde = x86_ldl_phys(cs, pde_addr);
|
||||||
if (!(pde & PG_PRESENT_MASK)) {
|
if (!(pde & PG_PRESENT_MASK)) {
|
||||||
goto do_fault;
|
goto do_fault;
|
||||||
|
@ -801,7 +803,7 @@ do_check_protect_pse36:
|
||||||
|
|
||||||
do_mapping:
|
do_mapping:
|
||||||
#if 0
|
#if 0
|
||||||
pte = pte & env->a20_mask;
|
pte = pte & a20_mask;
|
||||||
|
|
||||||
/* align to page_size */
|
/* align to page_size */
|
||||||
pte &= PG_ADDRESS_MASK & ~(page_size - 1);
|
pte &= PG_ADDRESS_MASK & ~(page_size - 1);
|
||||||
|
@ -854,11 +856,13 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
||||||
CPUX86State *env = &cpu->env;
|
CPUX86State *env = &cpu->env;
|
||||||
target_ulong pde_addr, pte_addr;
|
target_ulong pde_addr, pte_addr;
|
||||||
uint64_t pte;
|
uint64_t pte;
|
||||||
|
int32_t a20_mask;
|
||||||
uint32_t page_offset;
|
uint32_t page_offset;
|
||||||
int page_size;
|
int page_size;
|
||||||
|
|
||||||
|
a20_mask = x86_get_a20_mask(env);
|
||||||
if (!(env->cr[0] & CR0_PG_MASK)) {
|
if (!(env->cr[0] & CR0_PG_MASK)) {
|
||||||
pte = addr & env->a20_mask;
|
pte = addr & a20_mask;
|
||||||
page_size = 4096;
|
page_size = 4096;
|
||||||
} else if (env->cr[4] & CR4_PAE_MASK) {
|
} else if (env->cr[4] & CR4_PAE_MASK) {
|
||||||
target_ulong pdpe_addr;
|
target_ulong pdpe_addr;
|
||||||
|
@ -879,7 +883,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
||||||
|
|
||||||
if (la57) {
|
if (la57) {
|
||||||
pml5e_addr = ((env->cr[3] & ~0xfff) +
|
pml5e_addr = ((env->cr[3] & ~0xfff) +
|
||||||
(((addr >> 48) & 0x1ff) << 3)) & env->a20_mask;
|
(((addr >> 48) & 0x1ff) << 3)) & a20_mask;
|
||||||
pml5e = x86_ldq_phys(cs, pml5e_addr);
|
pml5e = x86_ldq_phys(cs, pml5e_addr);
|
||||||
if (!(pml5e & PG_PRESENT_MASK)) {
|
if (!(pml5e & PG_PRESENT_MASK)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -889,13 +893,13 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pml4e_addr = ((pml5e & PG_ADDRESS_MASK) +
|
pml4e_addr = ((pml5e & PG_ADDRESS_MASK) +
|
||||||
(((addr >> 39) & 0x1ff) << 3)) & env->a20_mask;
|
(((addr >> 39) & 0x1ff) << 3)) & a20_mask;
|
||||||
pml4e = x86_ldq_phys(cs, pml4e_addr);
|
pml4e = x86_ldq_phys(cs, pml4e_addr);
|
||||||
if (!(pml4e & PG_PRESENT_MASK)) {
|
if (!(pml4e & PG_PRESENT_MASK)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
pdpe_addr = ((pml4e & PG_ADDRESS_MASK) +
|
pdpe_addr = ((pml4e & PG_ADDRESS_MASK) +
|
||||||
(((addr >> 30) & 0x1ff) << 3)) & env->a20_mask;
|
(((addr >> 30) & 0x1ff) << 3)) & a20_mask;
|
||||||
pdpe = x86_ldq_phys(cs, pdpe_addr);
|
pdpe = x86_ldq_phys(cs, pdpe_addr);
|
||||||
if (!(pdpe & PG_PRESENT_MASK)) {
|
if (!(pdpe & PG_PRESENT_MASK)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -910,14 +914,14 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
|
pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
|
||||||
env->a20_mask;
|
a20_mask;
|
||||||
pdpe = x86_ldq_phys(cs, pdpe_addr);
|
pdpe = x86_ldq_phys(cs, pdpe_addr);
|
||||||
if (!(pdpe & PG_PRESENT_MASK))
|
if (!(pdpe & PG_PRESENT_MASK))
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pde_addr = ((pdpe & PG_ADDRESS_MASK) +
|
pde_addr = ((pdpe & PG_ADDRESS_MASK) +
|
||||||
(((addr >> 21) & 0x1ff) << 3)) & env->a20_mask;
|
(((addr >> 21) & 0x1ff) << 3)) & a20_mask;
|
||||||
pde = x86_ldq_phys(cs, pde_addr);
|
pde = x86_ldq_phys(cs, pde_addr);
|
||||||
if (!(pde & PG_PRESENT_MASK)) {
|
if (!(pde & PG_PRESENT_MASK)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -929,7 +933,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
||||||
} else {
|
} else {
|
||||||
/* 4 KB page */
|
/* 4 KB page */
|
||||||
pte_addr = ((pde & PG_ADDRESS_MASK) +
|
pte_addr = ((pde & PG_ADDRESS_MASK) +
|
||||||
(((addr >> 12) & 0x1ff) << 3)) & env->a20_mask;
|
(((addr >> 12) & 0x1ff) << 3)) & a20_mask;
|
||||||
page_size = 4096;
|
page_size = 4096;
|
||||||
pte = x86_ldq_phys(cs, pte_addr);
|
pte = x86_ldq_phys(cs, pte_addr);
|
||||||
}
|
}
|
||||||
|
@ -940,7 +944,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
||||||
uint32_t pde;
|
uint32_t pde;
|
||||||
|
|
||||||
/* page directory entry */
|
/* page directory entry */
|
||||||
pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
|
pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & a20_mask;
|
||||||
pde = x86_ldl_phys(cs, pde_addr);
|
pde = x86_ldl_phys(cs, pde_addr);
|
||||||
if (!(pde & PG_PRESENT_MASK))
|
if (!(pde & PG_PRESENT_MASK))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -949,14 +953,14 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
||||||
page_size = 4096 * 1024;
|
page_size = 4096 * 1024;
|
||||||
} else {
|
} else {
|
||||||
/* page directory entry */
|
/* page directory entry */
|
||||||
pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
|
pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask;
|
||||||
pte = x86_ldl_phys(cs, pte_addr);
|
pte = x86_ldl_phys(cs, pte_addr);
|
||||||
if (!(pte & PG_PRESENT_MASK)) {
|
if (!(pte & PG_PRESENT_MASK)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
page_size = 4096;
|
page_size = 4096;
|
||||||
}
|
}
|
||||||
pte = pte & env->a20_mask;
|
pte = pte & a20_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TARGET_X86_64
|
#ifdef TARGET_X86_64
|
||||||
|
|
Loading…
Reference in a new issue