diff options
author | Blue Swirl <blauwirbel@gmail.com> | 2012-04-28 19:35:10 +0000 |
---|---|---|
committer | Blue Swirl <blauwirbel@gmail.com> | 2012-06-28 20:28:08 +0000 |
commit | 77b2bc2c096be44a36c45d777abb81a298c05c98 (patch) | |
tree | 6b102bf6993d28825d37938b3c26939c3ef33b7d /target-i386 | |
parent | 20054ef03e0bd051178edd9d1378aa59570dbcf5 (diff) | |
download | qemu-77b2bc2c096be44a36c45d777abb81a298c05c98.zip qemu-77b2bc2c096be44a36c45d777abb81a298c05c98.tar.gz qemu-77b2bc2c096be44a36c45d777abb81a298c05c98.tar.bz2 |
x86: avoid AREG0 for exceptions
Add an explicit CPUX86State parameter instead of relying on AREG0.
Merge raise_exception_env() to raise_exception(), likewise with
raise_exception_err_env() and raise_exception_err().
Introduce cpu_svm_check_intercept_param() and cpu_vmexit()
as wrappers.
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Diffstat (limited to 'target-i386')
-rw-r--r-- | target-i386/cpu.h | 10 | ||||
-rw-r--r-- | target-i386/helper.c | 4 | ||||
-rw-r--r-- | target-i386/helper.h | 4 | ||||
-rw-r--r-- | target-i386/op_helper.c | 418 | ||||
-rw-r--r-- | target-i386/translate.c | 4 |
5 files changed, 225 insertions, 215 deletions
diff --git a/target-i386/cpu.h b/target-i386/cpu.h index bcf663e..c546723 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1074,13 +1074,15 @@ void cpu_x86_inject_mce(Monitor *mon, CPUX86State *cenv, int bank, /* op_helper.c */ void do_interrupt(CPUX86State *env); void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw); -void QEMU_NORETURN raise_exception_env(int exception_index, CPUX86State *nenv); -void QEMU_NORETURN raise_exception_err_env(CPUX86State *nenv, int exception_index, - int error_code); +void QEMU_NORETURN raise_exception(CPUX86State *env, int exception_index); +void QEMU_NORETURN raise_exception_err(CPUX86State *env, int exception_index, + int error_code); void do_smm_enter(CPUX86State *env1); -void svm_check_intercept(CPUX86State *env1, uint32_t type); +void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type, + uint64_t param); +void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1); uint32_t cpu_cc_compute_all(CPUX86State *env1, int op); diff --git a/target-i386/helper.c b/target-i386/helper.c index 2cc8097..d3af6ea 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -951,7 +951,7 @@ static void breakpoint_handler(CPUX86State *env) if (env->watchpoint_hit->flags & BP_CPU) { env->watchpoint_hit = NULL; if (check_hw_breakpoints(env, 0)) - raise_exception_env(EXCP01_DB, env); + raise_exception(env, EXCP01_DB); else cpu_resume_from_signal(env, NULL); } @@ -960,7 +960,7 @@ static void breakpoint_handler(CPUX86State *env) if (bp->pc == env->eip) { if (bp->flags & BP_CPU) { check_hw_breakpoints(env, 1); - raise_exception_env(EXCP01_DB, env); + raise_exception(env, EXCP01_DB); } break; } diff --git a/target-i386/helper.h b/target-i386/helper.h index 761954e..99ca183 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -63,8 +63,8 @@ DEF_HELPER_1(monitor, void, tl) DEF_HELPER_1(mwait, void, int) DEF_HELPER_0(debug, void) DEF_HELPER_0(reset_rf, void) -DEF_HELPER_2(raise_interrupt, void, int, int) -DEF_HELPER_1(raise_exception, void, int) +DEF_HELPER_3(raise_interrupt, void, env, int, int) +DEF_HELPER_2(raise_exception, void, env, int) DEF_HELPER_0(cli, void) DEF_HELPER_0(sti, void) DEF_HELPER_0(set_inhibit_irq, void) diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c index b9c1b93..773148c 100644 --- a/target-i386/op_helper.c +++ b/target-i386/op_helper.c @@ -139,16 +139,13 @@ static inline void cpu_load_efer(CPUX86State *env, uint64_t val) } #if 0 -#define raise_exception_err(a, b) \ +#define raise_exception_err(env, a, b) \ do { \ qemu_log("raise_exception line=%d\n", __LINE__); \ - (raise_exception_err)(a, b); \ + (raise_exception_err)(env, a, b); \ } while (0) #endif -static void QEMU_NORETURN raise_exception_err(int exception_index, - int error_code); - static const uint8_t parity_table[256] = { CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, @@ -317,7 +314,7 @@ static inline void get_ss_esp_from_tss(uint32_t *ss_ptr, shift = type >> 3; index = (dpl * 4 + 2) << shift; if (index + (4 << shift) - 1 > env->tr.limit) { - raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, env->tr.selector & 0xfffc); } if (shift == 0) { *esp_ptr = lduw_kernel(env->tr.base + index); @@ -336,47 +333,47 @@ static void tss_load_seg(int seg_reg, int selector) if ((selector & 0xfffc) != 0) { if (load_segment(&e1, &e2, selector) != 0) { - raise_exception_err(EXCP0A_TSS, selector & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc); } if (!(e2 & DESC_S_MASK)) { - raise_exception_err(EXCP0A_TSS, selector & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc); } rpl = selector & 3; dpl = (e2 >> DESC_DPL_SHIFT) & 3; cpl = env->hflags & HF_CPL_MASK; if (seg_reg == R_CS) { if (!(e2 & DESC_CS_MASK)) { - raise_exception_err(EXCP0A_TSS, selector & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc); } /* XXX: is it correct? */ if (dpl != rpl) { - raise_exception_err(EXCP0A_TSS, selector & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc); } if ((e2 & DESC_C_MASK) && dpl > rpl) { - raise_exception_err(EXCP0A_TSS, selector & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc); } } else if (seg_reg == R_SS) { /* SS must be writable data */ if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK)) { - raise_exception_err(EXCP0A_TSS, selector & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc); } if (dpl != cpl || dpl != rpl) { - raise_exception_err(EXCP0A_TSS, selector & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc); } } else { /* not readable code */ if ((e2 & DESC_CS_MASK) && !(e2 & DESC_R_MASK)) { - raise_exception_err(EXCP0A_TSS, selector & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc); } /* if data or non conforming code, checks the rights */ if (((e2 >> DESC_TYPE_SHIFT) & 0xf) < 12) { if (dpl < cpl || dpl < rpl) { - raise_exception_err(EXCP0A_TSS, selector & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc); } } } if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); + raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc); } cpu_x86_load_seg_cache(env, seg_reg, selector, get_seg_base(e1, e2), @@ -384,7 +381,7 @@ static void tss_load_seg(int seg_reg, int selector) e2); } else { if (seg_reg == R_SS || seg_reg == R_CS) { - raise_exception_err(EXCP0A_TSS, selector & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc); } } } @@ -414,26 +411,26 @@ static void switch_tss(int tss_selector, /* if task gate, we read the TSS segment and we load it */ if (type == 5) { if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc); + raise_exception_err(env, EXCP0B_NOSEG, tss_selector & 0xfffc); } tss_selector = e1 >> 16; if (tss_selector & 4) { - raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, tss_selector & 0xfffc); } if (load_segment(&e1, &e2, tss_selector) != 0) { - raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, tss_selector & 0xfffc); } if (e2 & DESC_S_MASK) { - raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, tss_selector & 0xfffc); } type = (e2 >> DESC_TYPE_SHIFT) & 0xf; if ((type & 7) != 1) { - raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, tss_selector & 0xfffc); } } if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc); + raise_exception_err(env, EXCP0B_NOSEG, tss_selector & 0xfffc); } if (type & 8) { @@ -445,7 +442,7 @@ static void switch_tss(int tss_selector, tss_base = get_seg_base(e1, e2); if ((tss_selector & 4) != 0 || tss_limit < tss_limit_max) { - raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, tss_selector & 0xfffc); } old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf; if (old_type & 8) { @@ -619,23 +616,23 @@ static void switch_tss(int tss_selector, /* load the LDT */ if (new_ldt & 4) { - raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, new_ldt & 0xfffc); } if ((new_ldt & 0xfffc) != 0) { dt = &env->gdt; index = new_ldt & ~7; if ((index + 7) > dt->limit) { - raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, new_ldt & 0xfffc); } ptr = dt->base + index; e1 = ldl_kernel(ptr); e2 = ldl_kernel(ptr + 4); if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2) { - raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, new_ldt & 0xfffc); } if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, new_ldt & 0xfffc); } load_seg_cache_raw_dt(&env->ldt, e1, e2); } @@ -653,7 +650,7 @@ static void switch_tss(int tss_selector, /* check that EIP is in the CS segment limits */ if (new_eip > env->segs[R_CS].limit) { /* XXX: different exception if CALL? */ - raise_exception_err(EXCP0D_GPF, 0); + raise_exception_err(env, EXCP0D_GPF, 0); } #ifndef CONFIG_USER_ONLY @@ -692,7 +689,7 @@ static inline void check_io(int addr, int size) /* all bits must be zero to allow the I/O */ if ((val & mask) != 0) { fail: - raise_exception_err(EXCP0D_GPF, 0); + raise_exception_err(env, EXCP0D_GPF, 0); } } @@ -835,7 +832,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, dt = &env->idt; if (intno * 8 + 7 > dt->limit) { - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); + raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2); } ptr = dt->base + intno * 8; e1 = ldl_kernel(ptr); @@ -846,7 +843,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, case 5: /* task gate */ /* must do that check here to return the correct error code */ if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2); + raise_exception_err(env, EXCP0B_NOSEG, intno * 8 + 2); } switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip); if (has_error_code) { @@ -877,60 +874,60 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, case 15: /* 386 trap gate */ break; default: - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); + raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2); break; } dpl = (e2 >> DESC_DPL_SHIFT) & 3; cpl = env->hflags & HF_CPL_MASK; /* check privilege if software int */ if (is_int && dpl < cpl) { - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); + raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2); } /* check valid bit */ if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2); + raise_exception_err(env, EXCP0B_NOSEG, intno * 8 + 2); } selector = e1 >> 16; offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff); if ((selector & 0xfffc) == 0) { - raise_exception_err(EXCP0D_GPF, 0); + raise_exception_err(env, EXCP0D_GPF, 0); } if (load_segment(&e1, &e2, selector) != 0) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } dpl = (e2 >> DESC_DPL_SHIFT) & 3; if (dpl > cpl) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); + raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc); } if (!(e2 & DESC_C_MASK) && dpl < cpl) { /* to inner privilege */ get_ss_esp_from_tss(&ss, &esp, dpl); if ((ss & 0xfffc) == 0) { - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc); } if ((ss & 3) != dpl) { - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc); } if (load_segment(&ss_e1, &ss_e2, ss) != 0) { - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc); } ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3; if (ss_dpl != dpl) { - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc); } if (!(ss_e2 & DESC_S_MASK) || (ss_e2 & DESC_CS_MASK) || !(ss_e2 & DESC_W_MASK)) { - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc); } if (!(ss_e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc); } new_stack = 1; sp_mask = get_sp_mask(ss_e2); @@ -938,7 +935,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, } else if ((e2 & DESC_C_MASK) || dpl == cpl) { /* to same privilege */ if (env->eflags & VM_MASK) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } new_stack = 0; sp_mask = get_sp_mask(env->segs[R_SS].flags); @@ -946,7 +943,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, esp = ESP; dpl = cpl; } else { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); new_stack = 0; /* avoid warning */ sp_mask = 0; /* avoid warning */ ssp = 0; /* avoid warning */ @@ -1055,7 +1052,7 @@ static inline target_ulong get_rsp_from_tss(int level) } index = 8 * level + 4; if ((index + 7) > env->tr.limit) { - raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, env->tr.selector & 0xfffc); } return ldq_kernel(env->tr.base + index); } @@ -1083,7 +1080,7 @@ static void do_interrupt64(int intno, int is_int, int error_code, dt = &env->idt; if (intno * 16 + 15 > dt->limit) { - raise_exception_err(EXCP0D_GPF, intno * 16 + 2); + raise_exception_err(env, EXCP0D_GPF, intno * 16 + 2); } ptr = dt->base + intno * 16; e1 = ldl_kernel(ptr); @@ -1096,41 +1093,41 @@ static void do_interrupt64(int intno, int is_int, int error_code, case 15: /* 386 trap gate */ break; default: - raise_exception_err(EXCP0D_GPF, intno * 16 + 2); + raise_exception_err(env, EXCP0D_GPF, intno * 16 + 2); break; } dpl = (e2 >> DESC_DPL_SHIFT) & 3; cpl = env->hflags & HF_CPL_MASK; /* check privilege if software int */ if (is_int && dpl < cpl) { - raise_exception_err(EXCP0D_GPF, intno * 16 + 2); + raise_exception_err(env, EXCP0D_GPF, intno * 16 + 2); } /* check valid bit */ if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0B_NOSEG, intno * 16 + 2); + raise_exception_err(env, EXCP0B_NOSEG, intno * 16 + 2); } selector = e1 >> 16; offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff); ist = e2 & 7; if ((selector & 0xfffc) == 0) { - raise_exception_err(EXCP0D_GPF, 0); + raise_exception_err(env, EXCP0D_GPF, 0); } if (load_segment(&e1, &e2, selector) != 0) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } dpl = (e2 >> DESC_DPL_SHIFT) & 3; if (dpl > cpl) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); + raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc); } if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK)) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) { /* to inner privilege */ @@ -1145,7 +1142,7 @@ static void do_interrupt64(int intno, int is_int, int error_code, } else if ((e2 & DESC_C_MASK) || dpl == cpl) { /* to same privilege */ if (env->eflags & VM_MASK) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } new_stack = 0; if (ist != 0) { @@ -1156,7 +1153,7 @@ static void do_interrupt64(int intno, int is_int, int error_code, esp &= ~0xfLL; /* align stack */ dpl = cpl; } else { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); new_stack = 0; /* avoid warning */ esp = 0; /* avoid warning */ } @@ -1206,7 +1203,7 @@ void helper_syscall(int next_eip_addend) int selector; if (!(env->efer & MSR_EFER_SCE)) { - raise_exception_err(EXCP06_ILLOP, 0); + raise_exception_err(env, EXCP06_ILLOP, 0); } selector = (env->star >> 32) & 0xffff; if (env->hflags & HF_LMA_MASK) { @@ -1263,11 +1260,11 @@ void helper_sysret(int dflag) int cpl, selector; if (!(env->efer & MSR_EFER_SCE)) { - raise_exception_err(EXCP06_ILLOP, 0); + raise_exception_err(env, EXCP06_ILLOP, 0); } cpl = env->hflags & HF_CPL_MASK; if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) { - raise_exception_err(EXCP0D_GPF, 0); + raise_exception_err(env, EXCP0D_GPF, 0); } selector = (env->star >> 48) & 0xffff; if (env->hflags & HF_LMA_MASK) { @@ -1326,7 +1323,7 @@ static void do_interrupt_real(int intno, int is_int, int error_code, /* real mode (simpler!) */ dt = &env->idt; if (intno * 4 + 3 > dt->limit) { - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); + raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2); } ptr = dt->base + intno * 4; offset = lduw_kernel(ptr); @@ -1375,7 +1372,7 @@ static void do_interrupt_user(int intno, int is_int, int error_code, cpl = env->hflags & HF_CPL_MASK; /* check privilege if software int */ if (is_int && dpl < cpl) { - raise_exception_err(EXCP0D_GPF, (intno << shift) + 2); + raise_exception_err(env, EXCP0D_GPF, (intno << shift) + 2); } /* Since we emulate only user space, we cannot do more than @@ -1540,7 +1537,7 @@ void qemu_system_reset_request(void); * needed. It should only be called, if this is not an interrupt. * Returns the new exception number. */ -static int check_exception(int intno, int *error_code) +static int check_exception(CPUX86State *env, int intno, int *error_code) { int first_contributory = env->old_exception == 0 || (env->old_exception >= 10 && @@ -1554,7 +1551,7 @@ static int check_exception(int intno, int *error_code) #if !defined(CONFIG_USER_ONLY) if (env->old_exception == EXCP08_DBLE) { if (env->hflags & HF_SVMI_MASK) { - helper_vmexit(SVM_EXIT_SHUTDOWN, 0); /* does not return */ + cpu_vmexit(env, SVM_EXIT_SHUTDOWN, 0); /* does not return */ } qemu_log_mask(CPU_LOG_RESET, "Triple fault\n"); @@ -1585,15 +1582,16 @@ static int check_exception(int intno, int *error_code) * EIP value AFTER the interrupt instruction. It is only relevant if * is_int is TRUE. */ -static void QEMU_NORETURN raise_interrupt(int intno, int is_int, int error_code, - int next_eip_addend) +static void QEMU_NORETURN raise_interrupt2(CPUX86State *env, int intno, + int is_int, int error_code, + int next_eip_addend) { if (!is_int) { - helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, - error_code); - intno = check_exception(intno, &error_code); + cpu_svm_check_intercept_param(env, SVM_EXIT_EXCP_BASE + intno, + error_code); + intno = check_exception(env, intno, &error_code); } else { - helper_svm_check_intercept_param(SVM_EXIT_SWINT, 0); + cpu_svm_check_intercept_param(env, SVM_EXIT_SWINT, 0); } env->exception_index = intno; @@ -1605,28 +1603,26 @@ static void QEMU_NORETURN raise_interrupt(int intno, int is_int, int error_code, /* shortcuts to generate exceptions */ -static void QEMU_NORETURN raise_exception_err(int exception_index, - int error_code) -{ - raise_interrupt(exception_index, 0, error_code, 0); -} - -void raise_exception_err_env(CPUX86State *nenv, int exception_index, - int error_code) +static void QEMU_NORETURN raise_interrupt(CPUX86State *nenv, + int intno, int is_int, + int error_code, + int next_eip_addend) { env = nenv; - raise_interrupt(exception_index, 0, error_code, 0); + raise_interrupt2(env, intno, is_int, error_code, next_eip_addend); } -static void QEMU_NORETURN raise_exception(int exception_index) +void raise_exception_err(CPUX86State *nenv, int exception_index, + int error_code) { - raise_interrupt(exception_index, 0, 0, 0); + env = nenv; + raise_interrupt2(env, exception_index, 0, error_code, 0); } -void raise_exception_env(int exception_index, CPUX86State *nenv) +void raise_exception(CPUX86State *nenv, int exception_index) { env = nenv; - raise_exception(exception_index); + raise_interrupt2(env, exception_index, 0, 0, 0); } /* SMM support */ @@ -1922,11 +1918,11 @@ void helper_divb_AL(target_ulong t0) num = (EAX & 0xffff); den = (t0 & 0xff); if (den == 0) { - raise_exception(EXCP00_DIVZ); + raise_exception(env, EXCP00_DIVZ); } q = (num / den); if (q > 0xff) { - raise_exception(EXCP00_DIVZ); + raise_exception(env, EXCP00_DIVZ); } q &= 0xff; r = (num % den) & 0xff; @@ -1940,11 +1936,11 @@ void helper_idivb_AL(target_ulong t0) num = (int16_t)EAX; den = (int8_t)t0; if (den == 0) { - raise_exception(EXCP00_DIVZ); + raise_exception(env, EXCP00_DIVZ); } q = (num / den); if (q != (int8_t)q) { - raise_exception(EXCP00_DIVZ); + raise_exception(env, EXCP00_DIVZ); } q &= 0xff; r = (num % den) & 0xff; @@ -1958,11 +1954,11 @@ void helper_divw_AX(target_ulong t0) num = (EAX & 0xffff) | ((EDX & 0xffff) << 16); den = (t0 & 0xffff); if (den == 0) { - raise_exception(EXCP00_DIVZ); + raise_exception(env, EXCP00_DIVZ); } q = (num / den); if (q > 0xffff) { - raise_exception(EXCP00_DIVZ); + raise_exception(env, EXCP00_DIVZ); } q &= 0xffff; r = (num % den) & 0xffff; @@ -1977,11 +1973,11 @@ void helper_idivw_AX(target_ulong t0) num = (EAX & 0xffff) | ((EDX & 0xffff) << 16); den = (int16_t)t0; if (den == 0) { - raise_exception(EXCP00_DIVZ); + raise_exception(env, EXCP00_DIVZ); } q = (num / den); if (q != (int16_t)q) { - raise_exception(EXCP00_DIVZ); + raise_exception(env, EXCP00_DIVZ); } q &= 0xffff; r = (num % den) & 0xffff; @@ -1997,12 +1993,12 @@ void helper_divl_EAX(target_ulong t0) num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32); den = t0; if (den == 0) { - raise_exception(EXCP00_DIVZ); + raise_exception(env, EXCP00_DIVZ); } q = (num / den); r = (num % den); if (q > 0xffffffff) { - raise_exception(EXCP00_DIVZ); + raise_exception(env, EXCP00_DIVZ); } EAX = (uint32_t)q; EDX = (uint32_t)r; @@ -2016,12 +2012,12 @@ void helper_idivl_EAX(target_ulong t0) num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32); den = t0; if (den == 0) { - raise_exception(EXCP00_DIVZ); + raise_exception(env, EXCP00_DIVZ); } q = (num / den); r = (num % den); if (q != (int32_t)q) { - raise_exception(EXCP00_DIVZ); + raise_exception(env, EXCP00_DIVZ); } EAX = (uint32_t)q; EDX = (uint32_t)r; @@ -2164,7 +2160,7 @@ void helper_into(int next_eip_addend) eflags = helper_cc_compute_all(CC_OP); if (eflags & CC_O) { - raise_interrupt(EXCP04_INTO, 1, 0, next_eip_addend); + raise_interrupt(env, EXCP04_INTO, 1, 0, next_eip_addend); } } @@ -2195,7 +2191,7 @@ void helper_cmpxchg16b(target_ulong a0) int eflags; if ((a0 & 0xf) != 0) { - raise_exception(EXCP0D_GPF); + raise_exception(env, EXCP0D_GPF); } eflags = helper_cc_compute_all(CC_OP); d0 = ldq(a0); @@ -2222,7 +2218,7 @@ void helper_single_step(void) check_hw_breakpoints(env, 1); env->dr[6] |= DR6_BS; #endif - raise_exception(EXCP01_DB); + raise_exception(env, EXCP01_DB); } void helper_cpuid(void) @@ -2316,7 +2312,7 @@ void helper_lldt(int selector) env->ldt.limit = 0; } else { if (selector & 0x4) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } dt = &env->gdt; index = selector & ~7; @@ -2329,16 +2325,16 @@ void helper_lldt(int selector) entry_limit = 7; } if ((index + entry_limit) > dt->limit) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } ptr = dt->base + index; e1 = ldl_kernel(ptr); e2 = ldl_kernel(ptr + 4); if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); + raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc); } #ifdef TARGET_X86_64 if (env->hflags & HF_LMA_MASK) { @@ -2371,7 +2367,7 @@ void helper_ltr(int selector) env->tr.flags = 0; } else { if (selector & 0x4) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } dt = &env->gdt; index = selector & ~7; @@ -2384,7 +2380,7 @@ void helper_ltr(int selector) entry_limit = 7; } if ((index + entry_limit) > dt->limit) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } ptr = dt->base + index; e1 = ldl_kernel(ptr); @@ -2392,10 +2388,10 @@ void helper_ltr(int selector) type = (e2 >> DESC_TYPE_SHIFT) & 0xf; if ((e2 & DESC_S_MASK) || (type != 1 && type != 9)) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); + raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc); } #ifdef TARGET_X86_64 if (env->hflags & HF_LMA_MASK) { @@ -2404,7 +2400,7 @@ void helper_ltr(int selector) e3 = ldl_kernel(ptr + 8); e4 = ldl_kernel(ptr + 12); if ((e4 >> DESC_TYPE_SHIFT) & 0xf) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } load_seg_cache_raw_dt(&env->tr, e1, e2); env->tr.base |= (target_ulong)e3 << 32; @@ -2437,7 +2433,7 @@ void helper_load_seg(int seg_reg, int selector) && (!(env->hflags & HF_CS64_MASK) || cpl == 3) #endif ) { - raise_exception_err(EXCP0D_GPF, 0); + raise_exception_err(env, EXCP0D_GPF, 0); } cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0); } else { @@ -2449,44 +2445,44 @@ void helper_load_seg(int seg_reg, int selector) } index = selector & ~7; if ((index + 7) > dt->limit) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } ptr = dt->base + index; e1 = ldl_kernel(ptr); e2 = ldl_kernel(ptr + 4); if (!(e2 & DESC_S_MASK)) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } rpl = selector & 3; dpl = (e2 >> DESC_DPL_SHIFT) & 3; if (seg_reg == R_SS) { /* must be writable segment */ if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK)) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } if (rpl != cpl || dpl != cpl) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } } else { /* must be readable segment */ if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) { /* if not conforming code, test rights */ if (dpl < cpl || dpl < rpl) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } } } if (!(e2 & DESC_P_MASK)) { if (seg_reg == R_SS) { - raise_exception_err(EXCP0C_STACK, selector & 0xfffc); + raise_exception_err(env, EXCP0C_STACK, selector & 0xfffc); } else { - raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); + raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc); } } @@ -2516,39 +2512,39 @@ void helper_ljmp_protected(int new_cs, target_ulong new_eip, target_ulong next_eip; if ((new_cs & 0xfffc) == 0) { - raise_exception_err(EXCP0D_GPF, 0); + raise_exception_err(env, EXCP0D_GPF, 0); } if (load_segment(&e1, &e2, new_cs) != 0) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } cpl = env->hflags & HF_CPL_MASK; if (e2 & DESC_S_MASK) { if (!(e2 & DESC_CS_MASK)) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } dpl = (e2 >> DESC_DPL_SHIFT) & 3; if (e2 & DESC_C_MASK) { /* conforming code segment */ if (dpl > cpl) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } } else { /* non conforming code segment */ rpl = new_cs & 3; if (rpl > cpl) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } if (dpl != cpl) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } } if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc); + raise_exception_err(env, EXCP0B_NOSEG, new_cs & 0xfffc); } limit = get_seg_limit(e1, e2); if (new_eip > limit && !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK)) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl, get_seg_base(e1, e2), limit, e2); @@ -2564,7 +2560,7 @@ void helper_ljmp_protected(int new_cs, target_ulong new_eip, case 9: /* 386 TSS */ case 5: /* task gate */ if (dpl < cpl || dpl < rpl) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } next_eip = env->eip + next_eip_addend; switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip); @@ -2573,10 +2569,10 @@ void helper_ljmp_protected(int new_cs, target_ulong new_eip, case 4: /* 286 call gate */ case 12: /* 386 call gate */ if ((dpl < cpl) || (dpl < rpl)) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc); + raise_exception_err(env, EXCP0B_NOSEG, new_cs & 0xfffc); } gate_cs = e1 >> 16; new_eip = (e1 & 0xffff); @@ -2584,31 +2580,31 @@ void helper_ljmp_protected(int new_cs, target_ulong new_eip, new_eip |= (e2 & 0xffff0000); } if (load_segment(&e1, &e2, gate_cs) != 0) { - raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, gate_cs & 0xfffc); } dpl = (e2 >> DESC_DPL_SHIFT) & 3; /* must be code segment */ if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) != (DESC_S_MASK | DESC_CS_MASK))) { - raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, gate_cs & 0xfffc); } if (((e2 & DESC_C_MASK) && (dpl > cpl)) || (!(e2 & DESC_C_MASK) && (dpl != cpl))) { - raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, gate_cs & 0xfffc); } if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, gate_cs & 0xfffc); } limit = get_seg_limit(e1, e2); if (new_eip > limit) { - raise_exception_err(EXCP0D_GPF, 0); + raise_exception_err(env, EXCP0D_GPF, 0); } cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl, get_seg_base(e1, e2), limit, e2); EIP = new_eip; break; default: - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); break; } } @@ -2654,35 +2650,35 @@ void helper_lcall_protected(int new_cs, target_ulong new_eip, LOG_PCALL("lcall %04x:%08x s=%d\n", new_cs, (uint32_t)new_eip, shift); LOG_PCALL_STATE(env); if ((new_cs & 0xfffc) == 0) { - raise_exception_err(EXCP0D_GPF, 0); + raise_exception_err(env, EXCP0D_GPF, 0); } if (load_segment(&e1, &e2, new_cs) != 0) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } cpl = env->hflags & HF_CPL_MASK; LOG_PCALL("desc=%08x:%08x\n", e1, e2); if (e2 & DESC_S_MASK) { if (!(e2 & DESC_CS_MASK)) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } dpl = (e2 >> DESC_DPL_SHIFT) & 3; if (e2 & DESC_C_MASK) { /* conforming code segment */ if (dpl > cpl) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } } else { /* non conforming code segment */ rpl = new_cs & 3; if (rpl > cpl) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } if (dpl != cpl) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } } if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc); + raise_exception_err(env, EXCP0B_NOSEG, new_cs & 0xfffc); } #ifdef TARGET_X86_64 @@ -2716,7 +2712,7 @@ void helper_lcall_protected(int new_cs, target_ulong new_eip, limit = get_seg_limit(e1, e2); if (new_eip > limit) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } /* from this point, not restartable */ SET_ESP(sp, sp_mask); @@ -2734,7 +2730,7 @@ void helper_lcall_protected(int new_cs, target_ulong new_eip, case 9: /* available 386 TSS */ case 5: /* task gate */ if (dpl < cpl || dpl < rpl) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip); CC_OP = CC_OP_EFLAGS; @@ -2743,37 +2739,37 @@ void helper_lcall_protected(int new_cs, target_ulong new_eip, case 12: /* 386 call gate */ break; default: - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); break; } shift = type >> 3; if (dpl < cpl || dpl < rpl) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } /* check valid bit */ if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc); + raise_exception_err(env, EXCP0B_NOSEG, new_cs & 0xfffc); } selector = e1 >> 16; offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff); param_count = e2 & 0x1f; if ((selector & 0xfffc) == 0) { - raise_exception_err(EXCP0D_GPF, 0); + raise_exception_err(env, EXCP0D_GPF, 0); } if (load_segment(&e1, &e2, selector) != 0) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } dpl = (e2 >> DESC_DPL_SHIFT) & 3; if (dpl > cpl) { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc); } if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); + raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc); } if (!(e2 & DESC_C_MASK) && dpl < cpl) { @@ -2783,25 +2779,25 @@ void helper_lcall_protected(int new_cs, target_ulong new_eip, "\n", ss, sp, param_count, ESP); if ((ss & 0xfffc) == 0) { - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc); } if ((ss & 3) != dpl) { - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc); } if (load_segment(&ss_e1, &ss_e2, ss) != 0) { - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc); } ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3; if (ss_dpl != dpl) { - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc); } if (!(ss_e2 & DESC_S_MASK) || (ss_e2 & DESC_CS_MASK) || !(ss_e2 & DESC_W_MASK)) { - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc); } if (!(ss_e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc); } /* push_size = ((param_count * 2) + 8) << shift; */ @@ -2983,32 +2979,32 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) new_cs, new_eip, shift, addend); LOG_PCALL_STATE(env); if ((new_cs & 0xfffc) == 0) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } if (load_segment(&e1, &e2, new_cs) != 0) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } if (!(e2 & DESC_S_MASK) || !(e2 & DESC_CS_MASK)) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } cpl = env->hflags & HF_CPL_MASK; rpl = new_cs & 3; if (rpl < cpl) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } dpl = (e2 >> DESC_DPL_SHIFT) & 3; if (e2 & DESC_C_MASK) { if (dpl > rpl) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } } else { if (dpl != rpl) { - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } } if (!(e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc); + raise_exception_err(env, EXCP0B_NOSEG, new_cs & 0xfffc); } sp += addend; @@ -3056,26 +3052,26 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) } else #endif { - raise_exception_err(EXCP0D_GPF, 0); + raise_exception_err(env, EXCP0D_GPF, 0); } } else { if ((new_ss & 3) != rpl) { - raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc); } if (load_segment(&ss_e1, &ss_e2, new_ss) != 0) { - raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc); } if (!(ss_e2 & DESC_S_MASK) || (ss_e2 & DESC_CS_MASK) || !(ss_e2 & DESC_W_MASK)) { - raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc); } dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3; if (dpl != rpl) { - raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); + raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc); } if (!(ss_e2 & DESC_P_MASK)) { - raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc); + raise_exception_err(env, EXCP0B_NOSEG, new_ss & 0xfffc); } cpu_x86_load_seg_cache(env, R_SS, new_ss, get_seg_base(ss_e1, ss_e2), @@ -3157,20 +3153,20 @@ void helper_iret_protected(int shift, int next_eip) if (env->eflags & NT_MASK) { #ifdef TARGET_X86_64 if (env->hflags & HF_LMA_MASK) { - raise_exception_err(EXCP0D_GPF, 0); + raise_exception_err(env, EXCP0D_GPF, 0); } #endif tss_selector = lduw_kernel(env->tr.base + 0); if (tss_selector & 4) { - raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, tss_selector & 0xfffc); } if (load_segment(&e1, &e2, tss_selector) != 0) { - raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, tss_selector & 0xfffc); } type = (e2 >> DESC_TYPE_SHIFT) & 0x17; /* NOTE: we check both segment and busy TSS */ if (type != 3) { - raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc); + raise_exception_err(env, EXCP0A_TSS, tss_selector & 0xfffc); } switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip); } else { @@ -3187,7 +3183,7 @@ void helper_lret_protected(int shift, int addend) void helper_sysenter(void) { if (env->sysenter_cs == 0) { - raise_exception_err(EXCP0D_GPF, 0); + raise_exception_err(env, EXCP0D_GPF, 0); } env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK); cpu_x86_set_cpl(env, 0); @@ -3224,7 +3220,7 @@ void helper_sysexit(int dflag) cpl = env->hflags & HF_CPL_MASK; if (env->sysenter_cs == 0 || cpl != 0) { - raise_exception_err(EXCP0D_GPF, 0); + raise_exception_err(env, EXCP0D_GPF, 0); } cpu_x86_set_cpl(env, 3); #ifdef TARGET_X86_64 @@ -3364,7 +3360,7 @@ void helper_rdtsc(void) uint64_t val; if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { - raise_exception(EXCP0D_GPF); + raise_exception(env, EXCP0D_GPF); } helper_svm_check_intercept_param(SVM_EXIT_RDTSC, 0); @@ -3382,13 +3378,13 @@ void helper_rdtscp(void) void helper_rdpmc(void) { if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { - raise_exception(EXCP0D_GPF); + raise_exception(env, EXCP0D_GPF); } helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0); /* currently unimplemented */ qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n"); - raise_exception_err(EXCP06_ILLOP, 0); + raise_exception_err(env, EXCP06_ILLOP, 0); } #if defined(CONFIG_USER_ONLY) @@ -3900,7 +3896,7 @@ static inline floatx80 helper_fdiv(floatx80 a, floatx80 b) static void fpu_raise_exception(void) { if (env->cr[0] & CR0_NE_MASK) { - raise_exception(EXCP10_COPR); + raise_exception(env, EXCP10_COPR); } #if !defined(CONFIG_USER_ONLY) else { @@ -4894,7 +4890,7 @@ void helper_fxsave(target_ulong ptr, int data64) /* The operand must be 16 byte aligned */ if (ptr & 0xf) { - raise_exception(EXCP0D_GPF); + raise_exception(env, EXCP0D_GPF); } fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; @@ -4956,7 +4952,7 @@ void helper_fxrstor(target_ulong ptr, int data64) /* The operand must be 16 byte aligned */ if (ptr & 0xf) { - raise_exception(EXCP0D_GPF); + raise_exception(env, EXCP0D_GPF); } env->fpuc = lduw(ptr); @@ -5144,12 +5140,12 @@ void helper_divq_EAX(target_ulong t0) uint64_t r0, r1; if (t0 == 0) { - raise_exception(EXCP00_DIVZ); + raise_exception(env, EXCP00_DIVZ); } r0 = EAX; r1 = EDX; if (div64(&r0, &r1, t0)) { - raise_exception(EXCP00_DIVZ); + raise_exception(env, EXCP00_DIVZ); } EAX = r0; EDX = r1; @@ -5160,12 +5156,12 @@ void helper_idivq_EAX(target_ulong t0) uint64_t r0, r1; if (t0 == 0) { - raise_exception(EXCP00_DIVZ); + raise_exception(env, EXCP00_DIVZ); } r0 = EAX; r1 = EDX; if (idiv64(&r0, &r1, t0)) { - raise_exception(EXCP00_DIVZ); + raise_exception(env, EXCP00_DIVZ); } EAX = r0; EDX = r1; @@ -5191,7 +5187,7 @@ void helper_hlt(int next_eip_addend) void helper_monitor(target_ulong ptr) { if ((uint32_t)ECX != 0) { - raise_exception(EXCP0D_GPF); + raise_exception(env, EXCP0D_GPF); } /* XXX: store address? */ helper_svm_check_intercept_param(SVM_EXIT_MONITOR, 0); @@ -5200,7 +5196,7 @@ void helper_monitor(target_ulong ptr) void helper_mwait(int next_eip_addend) { if ((uint32_t)ECX != 0) { - raise_exception(EXCP0D_GPF); + raise_exception(env, EXCP0D_GPF); } helper_svm_check_intercept_param(SVM_EXIT_MWAIT, 0); EIP += next_eip_addend; @@ -5225,14 +5221,14 @@ void helper_reset_rf(void) env->eflags &= ~RF_MASK; } -void helper_raise_interrupt(int intno, int next_eip_addend) +void helper_raise_interrupt(CPUX86State *env, int intno, int next_eip_addend) { - raise_interrupt(intno, 1, 0, next_eip_addend); + raise_interrupt(env, intno, 1, 0, next_eip_addend); } -void helper_raise_exception(int exception_index) +void helper_raise_exception(CPUX86State *env, int exception_index) { - raise_exception(exception_index); + raise_exception(env, exception_index); } void helper_cli(void) @@ -5256,7 +5252,7 @@ void helper_sti_vm(void) { env->eflags |= VIF_MASK; if (env->eflags & VIP_MASK) { - raise_exception(EXCP0D_GPF); + raise_exception(env, EXCP0D_GPF); } } #endif @@ -5279,7 +5275,7 @@ void helper_boundw(target_ulong a0, int v) high = ldsw(a0 + 2); v = (int16_t)v; if (v < low || v > high) { - raise_exception(EXCP05_BOUND); + raise_exception(env, EXCP05_BOUND); } } @@ -5290,7 +5286,7 @@ void helper_boundl(target_ulong a0, int v) low = ldl(a0); high = ldl(a0 + 4); if (v < low || v > high) { - raise_exception(EXCP05_BOUND); + raise_exception(env, EXCP05_BOUND); } } @@ -5338,7 +5334,7 @@ void tlb_fill(CPUX86State *env1, target_ulong addr, int is_write, int mmu_idx, cpu_restore_state(tb, env, retaddr); } } - raise_exception_err(env->exception_index, env->error_code); + raise_exception_err(env, env->exception_index, env->error_code); } env = saved_env; } @@ -5384,11 +5380,16 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) { } +void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1) +{ +} + void helper_svm_check_intercept_param(uint32_t type, uint64_t param) { } -void svm_check_intercept(CPUX86State *env1, uint32_t type) +void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type, + uint64_t param) { } @@ -5605,7 +5606,7 @@ void helper_vmrun(int aflag, int next_eip_addend) env->exception_next_eip = -1; qemu_log_mask(CPU_LOG_TB_IN_ASM, "INTR"); /* XXX: is it always correct? */ - do_interrupt_all(vector, 0, 0, 0, 1); + do_interrupt_x86_hardirq(env, vector, 1); break; case SVM_EVTINJ_TYPE_NMI: env->exception_index = EXCP02_NMI; @@ -5640,7 +5641,7 @@ void helper_vmrun(int aflag, int next_eip_addend) void helper_vmmcall(void) { helper_svm_check_intercept_param(SVM_EXIT_VMMCALL, 0); - raise_exception(EXCP06_ILLOP); + raise_exception(env, EXCP06_ILLOP); } void helper_vmload(int aflag) @@ -5741,7 +5742,7 @@ void helper_skinit(void) { helper_svm_check_intercept_param(SVM_EXIT_SKINIT, 0); /* XXX: not implemented */ - raise_exception(EXCP06_ILLOP); + raise_exception(env, EXCP06_ILLOP); } void helper_invlpga(int aflag) @@ -5834,13 +5835,14 @@ void helper_svm_check_intercept_param(uint32_t type, uint64_t param) } } -void svm_check_intercept(CPUX86State *env1, uint32_t type) +void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type, + uint64_t param) { CPUX86State *saved_env; saved_env = env; env = env1; - helper_svm_check_intercept_param(type, 0); + helper_svm_check_intercept_param(type, param); env = saved_env; } @@ -6022,6 +6024,12 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) cpu_loop_exit(env); } +void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1) +{ + env = nenv; + helper_vmexit(exit_code, exit_info_1); +} + #endif /* MMX/SSE */ diff --git a/target-i386/translate.c b/target-i386/translate.c index c1ede1a..8ac6132 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -2659,7 +2659,7 @@ static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(cur_eip); - gen_helper_raise_exception(tcg_const_i32(trapno)); + gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno)); s->is_jmp = DISAS_TB_JUMP; } @@ -2671,7 +2671,7 @@ static void gen_interrupt(DisasContext *s, int intno, if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(cur_eip); - gen_helper_raise_interrupt(tcg_const_i32(intno), + gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno), tcg_const_i32(next_eip - cur_eip)); s->is_jmp = DISAS_TB_JUMP; } |