diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-28 16:16:54 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-28 16:16:54 +0000 |
commit | 872929aa59cba19fd83b98f87929ccda12a2cbbb (patch) | |
tree | c48d33acaf7c44d48c35507fba462b84f1022149 /target-i386/translate.c | |
parent | 893f986502196aeb43d176161179c3ff22a7e0a8 (diff) | |
download | hqemu-872929aa59cba19fd83b98f87929ccda12a2cbbb.zip hqemu-872929aa59cba19fd83b98f87929ccda12a2cbbb.tar.gz |
SVM rework
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4605 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-i386/translate.c')
-rw-r--r-- | target-i386/translate.c | 238 |
1 files changed, 101 insertions, 137 deletions
diff --git a/target-i386/translate.c b/target-i386/translate.c index bba9b56..ba6284f 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -733,7 +733,7 @@ static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip, tcg_gen_helper_0_1(gen_check_io_func[ot], cpu_tmp2_i32); } - if(s->flags & (1ULL << INTERCEPT_IOIO_PROT)) { + if(s->flags & HF_SVMI_MASK) { if (!state_saved) { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); @@ -2322,59 +2322,24 @@ static inline int svm_is_rep(int prefixes) return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0); } -static inline int +static inline void gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start, uint32_t type, uint64_t param) { - if(!(s->flags & (INTERCEPT_SVM_MASK))) - /* no SVM activated */ - return 0; - switch(type) { - /* CRx and DRx reads/writes */ - case SVM_EXIT_READ_CR0 ... SVM_EXIT_EXCP_BASE - 1: - if (s->cc_op != CC_OP_DYNAMIC) { - gen_op_set_cc_op(s->cc_op); - } - gen_jmp_im(pc_start - s->cs_base); - tcg_gen_helper_0_2(helper_svm_check_intercept_param, - tcg_const_i32(type), tcg_const_i64(param)); - /* this is a special case as we do not know if the interception occurs - so we assume there was none */ - return 0; - case SVM_EXIT_MSR: - if(s->flags & (1ULL << INTERCEPT_MSR_PROT)) { - if (s->cc_op != CC_OP_DYNAMIC) { - gen_op_set_cc_op(s->cc_op); - } - gen_jmp_im(pc_start - s->cs_base); - tcg_gen_helper_0_2(helper_svm_check_intercept_param, - tcg_const_i32(type), tcg_const_i64(param)); - /* this is a special case as we do not know if the interception occurs - so we assume there was none */ - return 0; - } - break; - default: - if(s->flags & (1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR))) { - if (s->cc_op != CC_OP_DYNAMIC) { - gen_op_set_cc_op(s->cc_op); - } - gen_jmp_im(pc_start - s->cs_base); - tcg_gen_helper_0_2(helper_vmexit, - tcg_const_i32(type), tcg_const_i64(param)); - /* we can optimize this one so TBs don't get longer - than up to vmexit */ - gen_eob(s); - return 1; - } - } - return 0; + /* no SVM activated; fast case */ + if (likely(!(s->flags & HF_SVMI_MASK))) + return; + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); + gen_jmp_im(pc_start - s->cs_base); + tcg_gen_helper_0_2(helper_svm_check_intercept_param, + tcg_const_i32(type), tcg_const_i64(param)); } -static inline int +static inline void gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type) { - return gen_svm_check_intercept_param(s, pc_start, type, 0); + gen_svm_check_intercept_param(s, pc_start, type, 0); } static inline void gen_stack_update(DisasContext *s, int addend) @@ -5743,8 +5708,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) val = 0; goto do_lret; case 0xcf: /* iret */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET)) - break; + gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET); if (!s->pe) { /* real mode */ tcg_gen_helper_0_1(helper_iret_real, tcg_const_i32(s->dflag)); @@ -5890,8 +5854,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) /************************/ /* flags */ case 0x9c: /* pushf */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF)) - break; + gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF); if (s->vm86 && s->iopl != 3) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { @@ -5902,8 +5865,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } break; case 0x9d: /* popf */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF)) - break; + gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF); if (s->vm86 && s->iopl != 3) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { @@ -6187,14 +6149,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } break; case 0xcc: /* int3 */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT)) - break; gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base); break; case 0xcd: /* int N */ val = ldub_code(s->pc++); - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT)) - break; if (s->vm86 && s->iopl != 3) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { @@ -6204,16 +6162,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0xce: /* into */ if (CODE64(s)) goto illegal_op; - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT)) - break; if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); tcg_gen_helper_0_1(helper_into, tcg_const_i32(s->pc - pc_start)); break; case 0xf1: /* icebp (undocumented, exits to external debugger) */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP)) - break; + gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP); #if 1 gen_debug(s, pc_start - s->cs_base); #else @@ -6371,25 +6326,25 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { - int retval = 0; + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); + gen_jmp_im(pc_start - s->cs_base); if (b & 2) { - retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 0); tcg_gen_helper_0_0(helper_rdmsr); } else { - retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 1); tcg_gen_helper_0_0(helper_wrmsr); } - if(retval) - gen_eob(s); } break; case 0x131: /* rdtsc */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RDTSC)) - break; + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); tcg_gen_helper_0_0(helper_rdtsc); break; case 0x133: /* rdpmc */ + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); tcg_gen_helper_0_0(helper_rdpmc); break; @@ -6452,16 +6407,12 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) break; #endif case 0x1a2: /* cpuid */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CPUID)) - break; tcg_gen_helper_0_0(helper_cpuid); break; case 0xf4: /* hlt */ if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_HLT)) - break; if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(s->pc - s->cs_base); @@ -6477,8 +6428,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0: /* sldt */ if (!s->pe || s->vm86) goto illegal_op; - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ)) - break; + gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ); tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector)); ot = OT_WORD; if (mod == 3) @@ -6491,8 +6441,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE)) - break; + gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE); gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); gen_jmp_im(pc_start - s->cs_base); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); @@ -6502,8 +6451,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 1: /* str */ if (!s->pe || s->vm86) goto illegal_op; - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ)) - break; + gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ); tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector)); ot = OT_WORD; if (mod == 3) @@ -6516,8 +6464,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE)) - break; + gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE); gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); gen_jmp_im(pc_start - s->cs_base); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); @@ -6550,8 +6497,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0: /* sgdt */ if (mod == 3) goto illegal_op; - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ)) - break; + gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ); gen_lea_modrm(s, modrm, ®_addr, &offset_addr); tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit)); gen_op_st_T0_A0(OT_WORD + s->mem_index); @@ -6568,8 +6514,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || s->cpl != 0) goto illegal_op; - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MONITOR)) - break; gen_jmp_im(pc_start - s->cs_base); #ifdef TARGET_X86_64 if (s->aflag == 2) { @@ -6592,8 +6536,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_op_set_cc_op(s->cc_op); s->cc_op = CC_OP_DYNAMIC; } - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MWAIT)) - break; gen_jmp_im(s->pc - s->cs_base); tcg_gen_helper_0_0(helper_mwait); gen_eob(s); @@ -6602,8 +6544,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) goto illegal_op; } } else { /* sidt */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ)) - break; + gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ); gen_lea_modrm(s, modrm, ®_addr, &offset_addr); tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit)); gen_op_st_T0_A0(OT_WORD + s->mem_index); @@ -6617,52 +6558,85 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 2: /* lgdt */ case 3: /* lidt */ if (mod == 3) { + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); + gen_jmp_im(pc_start - s->cs_base); switch(rm) { case 0: /* VMRUN */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMRUN)) + if (!(s->flags & HF_SVME_MASK) || !s->pe) + goto illegal_op; + if (s->cpl != 0) { + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); break; - if (s->cc_op != CC_OP_DYNAMIC) - gen_op_set_cc_op(s->cc_op); - gen_jmp_im(s->pc - s->cs_base); - tcg_gen_helper_0_0(helper_vmrun); - s->cc_op = CC_OP_EFLAGS; - gen_eob(s); + } else { + tcg_gen_helper_0_0(helper_vmrun); + s->cc_op = CC_OP_EFLAGS; + gen_eob(s); + } break; case 1: /* VMMCALL */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMMCALL)) - break; - /* FIXME: cause #UD if hflags & SVM */ + if (!(s->flags & HF_SVME_MASK)) + goto illegal_op; tcg_gen_helper_0_0(helper_vmmcall); break; case 2: /* VMLOAD */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMLOAD)) - break; - tcg_gen_helper_0_0(helper_vmload); + if (!(s->flags & HF_SVME_MASK) || !s->pe) + goto illegal_op; + if (s->cpl != 0) { + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); + break; + } else { + tcg_gen_helper_0_0(helper_vmload); + } break; case 3: /* VMSAVE */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMSAVE)) - break; - tcg_gen_helper_0_0(helper_vmsave); + if (!(s->flags & HF_SVME_MASK) || !s->pe) + goto illegal_op; + if (s->cpl != 0) { + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); + break; + } else { + tcg_gen_helper_0_0(helper_vmsave); + } break; case 4: /* STGI */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_STGI)) - break; - tcg_gen_helper_0_0(helper_stgi); + if ((!(s->flags & HF_SVME_MASK) && + !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) || + !s->pe) + goto illegal_op; + if (s->cpl != 0) { + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); + break; + } else { + tcg_gen_helper_0_0(helper_stgi); + } break; case 5: /* CLGI */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CLGI)) - break; - tcg_gen_helper_0_0(helper_clgi); + if (!(s->flags & HF_SVME_MASK) || !s->pe) + goto illegal_op; + if (s->cpl != 0) { + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); + break; + } else { + tcg_gen_helper_0_0(helper_clgi); + } break; case 6: /* SKINIT */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SKINIT)) - break; + if ((!(s->flags & HF_SVME_MASK) && + !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) || + !s->pe) + goto illegal_op; tcg_gen_helper_0_0(helper_skinit); break; case 7: /* INVLPGA */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPGA)) - break; - tcg_gen_helper_0_0(helper_invlpga); + if (!(s->flags & HF_SVME_MASK) || !s->pe) + goto illegal_op; + if (s->cpl != 0) { + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); + break; + } else { + tcg_gen_helper_0_0(helper_invlpga); + } break; default: goto illegal_op; @@ -6670,9 +6644,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } else if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { - if (gen_svm_check_intercept(s, pc_start, - op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE)) - break; + gen_svm_check_intercept(s, pc_start, + op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE); gen_lea_modrm(s, modrm, ®_addr, &offset_addr); gen_op_ld_T1_A0(OT_WORD + s->mem_index); gen_add_A0_im(s, 2); @@ -6689,8 +6662,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } break; case 4: /* smsw */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0)) - break; + gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0); tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0])); gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1); break; @@ -6698,8 +6670,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0)) - break; + gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0); gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); tcg_gen_helper_0_1(helper_lmsw, cpu_T[0]); gen_jmp_im(s->pc - s->cs_base); @@ -6724,8 +6695,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) goto illegal_op; } } else { - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPG)) - break; gen_lea_modrm(s, modrm, ®_addr, &offset_addr); tcg_gen_helper_0_1(helper_invlpg, cpu_A0); gen_jmp_im(s->pc - s->cs_base); @@ -6742,8 +6711,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { - if (gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD)) - break; + gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD); /* nothing to do */ } break; @@ -6892,21 +6860,18 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 3: case 4: case 8: + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); + gen_jmp_im(pc_start - s->cs_base); if (b & 2) { - gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0 + reg); gen_op_mov_TN_reg(ot, 0, rm); - tcg_gen_helper_0_2(helper_movl_crN_T0, + tcg_gen_helper_0_2(helper_write_crN, tcg_const_i32(reg), cpu_T[0]); gen_jmp_im(s->pc - s->cs_base); gen_eob(s); } else { - gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0 + reg); -#if !defined(CONFIG_USER_ONLY) - if (reg == 8) - tcg_gen_helper_1_0(helper_movtl_T0_cr8, cpu_T[0]); - else -#endif - tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[reg])); + tcg_gen_helper_1_1(helper_read_crN, + cpu_T[0], tcg_const_i32(reg)); gen_op_mov_reg_T0(ot, rm); } break; @@ -7054,8 +7019,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) /* ignore for now */ break; case 0x1aa: /* rsm */ - if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM)) - break; + gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM); if (!(s->flags & HF_SMM_MASK)) goto illegal_op; if (s->cc_op != CC_OP_DYNAMIC) { |