summaryrefslogtreecommitdiffstats
path: root/target-i386/helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-i386/helper.c')
-rw-r--r--target-i386/helper.c88
1 files changed, 59 insertions, 29 deletions
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 55c04577dc..372f0e3ecb 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -385,22 +385,25 @@ void x86_cpu_set_a20(X86CPU *cpu, int a20_state)
a20_state = (a20_state != 0);
if (a20_state != ((env->a20_mask >> 20) & 1)) {
+ CPUState *cs = CPU(cpu);
+
#if defined(DEBUG_MMU)
printf("A20 update: a20=%d\n", a20_state);
#endif
/* if the cpu is currently executing code, we must unlink it and
all the potentially executing TB */
- cpu_interrupt(CPU(cpu), CPU_INTERRUPT_EXITTB);
+ cpu_interrupt(cs, CPU_INTERRUPT_EXITTB);
/* when a20 is changed, all the MMU mappings are invalid, so
we must flush everything */
- tlb_flush(env, 1);
+ tlb_flush(cs, 1);
env->a20_mask = ~(1 << 20) | (a20_state << 20);
}
}
void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
{
+ X86CPU *cpu = x86_env_get_cpu(env);
int pe_state;
#if defined(DEBUG_MMU)
@@ -408,7 +411,7 @@ void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
#endif
if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
(env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
- tlb_flush(env, 1);
+ tlb_flush(CPU(cpu), 1);
}
#ifdef TARGET_X86_64
@@ -444,24 +447,28 @@ void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
the PDPT */
void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
{
+ X86CPU *cpu = x86_env_get_cpu(env);
+
env->cr[3] = new_cr3;
if (env->cr[0] & CR0_PG_MASK) {
#if defined(DEBUG_MMU)
printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
#endif
- tlb_flush(env, 0);
+ tlb_flush(CPU(cpu), 0);
}
}
void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
{
+ X86CPU *cpu = x86_env_get_cpu(env);
+
#if defined(DEBUG_MMU)
printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
#endif
if ((new_cr4 ^ env->cr[4]) &
(CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK |
CR4_SMEP_MASK | CR4_SMAP_MASK)) {
- tlb_flush(env, 1);
+ tlb_flush(CPU(cpu), 1);
}
/* SSE handling */
if (!(env->features[FEAT_1_EDX] & CPUID_SSE)) {
@@ -485,15 +492,18 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
#if defined(CONFIG_USER_ONLY)
-int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
+int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
int is_write, int mmu_idx)
{
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+
/* user mode only emulation */
is_write &= 1;
env->cr[2] = addr;
env->error_code = (is_write << PG_ERROR_W_BIT);
env->error_code |= PG_ERROR_U_MASK;
- env->exception_index = EXCP0E_PAGE;
+ cs->exception_index = EXCP0E_PAGE;
return 1;
}
@@ -508,14 +518,15 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
# endif
/* return value:
- -1 = cannot handle fault
- 0 = nothing more to do
- 1 = generate PF fault
-*/
-int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
+ * -1 = cannot handle fault
+ * 0 = nothing more to do
+ * 1 = generate PF fault
+ */
+int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
int is_write1, int mmu_idx)
{
- CPUState *cs = ENV_GET_CPU(env);
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
uint64_t ptep, pte;
target_ulong pde_addr, pte_addr;
int error_code, is_dirty, prot, page_size, is_write, is_user;
@@ -525,7 +536,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
is_user = mmu_idx == MMU_USER_IDX;
#if defined(DEBUG_MMU)
- printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
+ printf("MMU fault: addr=%" VADDR_PRIx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
addr, is_write1, is_user, env->eip);
#endif
is_write = is_write1 & 1;
@@ -557,7 +568,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
sext = (int64_t)addr >> 47;
if (sext != 0 && sext != -1) {
env->error_code = 0;
- env->exception_index = EXCP0D_GPF;
+ cs->exception_index = EXCP0D_GPF;
return 1;
}
@@ -866,7 +877,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
paddr = (pte & TARGET_PAGE_MASK) + page_offset;
vaddr = virt_addr + page_offset;
- tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
+ tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, page_size);
return 0;
do_fault_protect:
error_code = PG_ERROR_P_MASK;
@@ -888,7 +899,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
env->cr[2] = addr;
}
env->error_code = error_code;
- env->exception_index = EXCP0E_PAGE;
+ cs->exception_index = EXCP0E_PAGE;
return 1;
}
@@ -930,6 +941,14 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
pdpe = ldq_phys(cs->as, pdpe_addr);
if (!(pdpe & PG_PRESENT_MASK))
return -1;
+
+ if (pdpe & PG_PSE_MASK) {
+ page_size = 1024 * 1024 * 1024;
+ pte = pdpe & ~( (page_size - 1) & ~0xfff);
+ pte &= ~(PG_NX_MASK | PG_HI_USER_MASK);
+ goto out;
+ }
+
} else
#endif
{
@@ -982,6 +1001,9 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
pte = pte & env->a20_mask;
}
+#ifdef TARGET_X86_64
+out:
+#endif
page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
paddr = (pte & TARGET_PAGE_MASK) + page_offset;
return paddr;
@@ -989,12 +1011,13 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
void hw_breakpoint_insert(CPUX86State *env, int index)
{
+ CPUState *cs = CPU(x86_env_get_cpu(env));
int type = 0, err = 0;
switch (hw_breakpoint_type(env->dr[7], index)) {
case DR7_TYPE_BP_INST:
if (hw_breakpoint_enabled(env->dr[7], index)) {
- err = cpu_breakpoint_insert(env, env->dr[index], BP_CPU,
+ err = cpu_breakpoint_insert(cs, env->dr[index], BP_CPU,
&env->cpu_breakpoint[index]);
}
break;
@@ -1010,7 +1033,7 @@ void hw_breakpoint_insert(CPUX86State *env, int index)
}
if (type != 0) {
- err = cpu_watchpoint_insert(env, env->dr[index],
+ err = cpu_watchpoint_insert(cs, env->dr[index],
hw_breakpoint_len(env->dr[7], index),
type, &env->cpu_watchpoint[index]);
}
@@ -1022,17 +1045,21 @@ void hw_breakpoint_insert(CPUX86State *env, int index)
void hw_breakpoint_remove(CPUX86State *env, int index)
{
- if (!env->cpu_breakpoint[index])
+ CPUState *cs;
+
+ if (!env->cpu_breakpoint[index]) {
return;
+ }
+ cs = CPU(x86_env_get_cpu(env));
switch (hw_breakpoint_type(env->dr[7], index)) {
case DR7_TYPE_BP_INST:
if (hw_breakpoint_enabled(env->dr[7], index)) {
- cpu_breakpoint_remove_by_ref(env, env->cpu_breakpoint[index]);
+ cpu_breakpoint_remove_by_ref(cs, env->cpu_breakpoint[index]);
}
break;
case DR7_TYPE_DATA_WR:
case DR7_TYPE_DATA_RW:
- cpu_watchpoint_remove_by_ref(env, env->cpu_watchpoint[index]);
+ cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]);
break;
case DR7_TYPE_IO_RW:
/* No support for I/O watchpoints yet */
@@ -1084,19 +1111,20 @@ bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update)
void breakpoint_handler(CPUX86State *env)
{
+ CPUState *cs = CPU(x86_env_get_cpu(env));
CPUBreakpoint *bp;
- if (env->watchpoint_hit) {
- if (env->watchpoint_hit->flags & BP_CPU) {
- env->watchpoint_hit = NULL;
+ if (cs->watchpoint_hit) {
+ if (cs->watchpoint_hit->flags & BP_CPU) {
+ cs->watchpoint_hit = NULL;
if (check_hw_breakpoints(env, false)) {
raise_exception(env, EXCP01_DB);
} else {
- cpu_resume_from_signal(env, NULL);
+ cpu_resume_from_signal(cs, NULL);
}
}
} else {
- QTAILQ_FOREACH(bp, &env->breakpoints, entry)
+ QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == env->eip) {
if (bp->flags & BP_CPU) {
check_hw_breakpoints(env, true);
@@ -1104,6 +1132,7 @@ void breakpoint_handler(CPUX86State *env)
}
break;
}
+ }
}
}
@@ -1250,13 +1279,14 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
{
X86CPU *cpu = x86_env_get_cpu(env);
+ CPUState *cs = CPU(cpu);
if (kvm_enabled()) {
env->tpr_access_type = access;
- cpu_interrupt(CPU(cpu), CPU_INTERRUPT_TPR);
+ cpu_interrupt(cs, CPU_INTERRUPT_TPR);
} else {
- cpu_restore_state(env, env->mem_io_pc);
+ cpu_restore_state(cs, cs->mem_io_pc);
apic_handle_tpr_access_report(cpu->apic_state, env->eip, access);
}