~ubuntu-bugs-auftrags-killer/qemu/proper-error-characters

« back to all changes in this revision

Viewing changes to target-i386/op_helper.c

  • Committer: bellard
  • Date: 2008-05-28 16:16:54 UTC
  • Revision ID: git-v1:872929aa59cba19fd83b98f87929ccda12a2cbbb
SVM rework

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4605 c046a42c-6fe2-441c-8c8c-71466251a162

Show diffs side-by-side

added added

removed removed

Lines of Context:
625
625
    int has_error_code, new_stack, shift;
626
626
    uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
627
627
    uint32_t old_eip, sp_mask;
628
 
    int svm_should_check = 1;
629
 
 
630
 
    if ((env->intercept & INTERCEPT_SVM_MASK) && !is_int && next_eip==-1) {
631
 
        next_eip = EIP;
632
 
        svm_should_check = 0;
633
 
    }
634
 
 
635
 
    if (svm_should_check
636
 
        && (INTERCEPTEDl(_exceptions, 1 << intno)
637
 
        && !is_int)) {
638
 
        raise_interrupt(intno, is_int, error_code, 0);
639
 
    }
 
628
 
640
629
    has_error_code = 0;
641
630
    if (!is_int && !is_hw) {
642
631
        switch(intno) {
872
861
    int has_error_code, new_stack;
873
862
    uint32_t e1, e2, e3, ss;
874
863
    target_ulong old_eip, esp, offset;
875
 
    int svm_should_check = 1;
876
864
 
877
 
    if ((env->intercept & INTERCEPT_SVM_MASK) && !is_int && next_eip==-1) {
878
 
        next_eip = EIP;
879
 
        svm_should_check = 0;
880
 
    }
881
 
    if (svm_should_check
882
 
        && INTERCEPTEDl(_exceptions, 1 << intno)
883
 
        && !is_int) {
884
 
        raise_interrupt(intno, is_int, error_code, 0);
885
 
    }
886
865
    has_error_code = 0;
887
866
    if (!is_int && !is_hw) {
888
867
        switch(intno) {
1139
1118
    int selector;
1140
1119
    uint32_t offset, esp;
1141
1120
    uint32_t old_cs, old_eip;
1142
 
    int svm_should_check = 1;
1143
1121
 
1144
 
    if ((env->intercept & INTERCEPT_SVM_MASK) && !is_int && next_eip==-1) {
1145
 
        next_eip = EIP;
1146
 
        svm_should_check = 0;
1147
 
    }
1148
 
    if (svm_should_check
1149
 
        && INTERCEPTEDl(_exceptions, 1 << intno)
1150
 
        && !is_int) {
1151
 
        raise_interrupt(intno, is_int, error_code, 0);
1152
 
    }
1153
1122
    /* real mode (simpler !) */
1154
1123
    dt = &env->idt;
1155
1124
    if (intno * 4 + 3 > dt->limit)
1307
1276
    if (!is_int) {
1308
1277
        helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code);
1309
1278
        intno = check_exception(intno, &error_code);
 
1279
    } else {
 
1280
        helper_svm_check_intercept_param(SVM_EXIT_SWINT, 0);
1310
1281
    }
1311
1282
 
1312
1283
    env->exception_index = intno;
1316
1287
    cpu_loop_exit();
1317
1288
}
1318
1289
 
1319
 
/* same as raise_exception_err, but do not restore global registers */
1320
 
static void raise_exception_err_norestore(int exception_index, int error_code)
1321
 
{
1322
 
    exception_index = check_exception(exception_index, &error_code);
1323
 
 
1324
 
    env->exception_index = exception_index;
1325
 
    env->error_code = error_code;
1326
 
    env->exception_is_int = 0;
1327
 
    env->exception_next_eip = 0;
1328
 
    longjmp(env->jmp_env, 1);
1329
 
}
1330
 
 
1331
1290
/* shortcuts to generate exceptions */
1332
1291
 
1333
1292
void (raise_exception_err)(int exception_index, int error_code)
1921
1880
void helper_cpuid(void)
1922
1881
{
1923
1882
    uint32_t index;
 
1883
 
 
1884
    helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0);
 
1885
    
1924
1886
    index = (uint32_t)EAX;
1925
 
 
1926
1887
    /* test if maximum index reached */
1927
1888
    if (index & 0x80000000) {
1928
1889
        if (index > env->cpuid_xlevel)
2957
2918
#endif
2958
2919
}
2959
2920
 
2960
 
void helper_movl_crN_T0(int reg, target_ulong t0)
2961
 
{
2962
 
#if !defined(CONFIG_USER_ONLY)
 
2921
#if defined(CONFIG_USER_ONLY)
 
2922
target_ulong helper_read_crN(int reg)
 
2923
{
 
2924
    return 0;
 
2925
}
 
2926
 
 
2927
void helper_write_crN(int reg, target_ulong t0)
 
2928
{
 
2929
}
 
2930
#else
 
2931
target_ulong helper_read_crN(int reg)
 
2932
{
 
2933
    target_ulong val;
 
2934
 
 
2935
    helper_svm_check_intercept_param(SVM_EXIT_READ_CR0 + reg, 0);
 
2936
    switch(reg) {
 
2937
    default:
 
2938
        val = env->cr[reg];
 
2939
        break;
 
2940
    case 8:
 
2941
        val = cpu_get_apic_tpr(env);
 
2942
        break;
 
2943
    }
 
2944
    return val;
 
2945
}
 
2946
 
 
2947
void helper_write_crN(int reg, target_ulong t0)
 
2948
{
 
2949
    helper_svm_check_intercept_param(SVM_EXIT_WRITE_CR0 + reg, 0);
2963
2950
    switch(reg) {
2964
2951
    case 0:
2965
2952
        cpu_x86_update_cr0(env, t0);
2978
2965
        env->cr[reg] = t0;
2979
2966
        break;
2980
2967
    }
 
2968
}
2981
2969
#endif
2982
 
}
2983
2970
 
2984
2971
void helper_lmsw(target_ulong t0)
2985
2972
{
2986
2973
    /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
2987
2974
       if already set to one. */
2988
2975
    t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
2989
 
    helper_movl_crN_T0(0, t0);
 
2976
    helper_write_crN(0, t0);
2990
2977
}
2991
2978
 
2992
2979
void helper_clts(void)
3010
2997
 
3011
2998
void helper_invlpg(target_ulong addr)
3012
2999
{
 
3000
    helper_svm_check_intercept_param(SVM_EXIT_INVLPG, 0);
3013
3001
    cpu_x86_flush_tlb(env, addr);
3014
3002
}
3015
3003
 
3020
3008
    if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
3021
3009
        raise_exception(EXCP0D_GPF);
3022
3010
    }
 
3011
    helper_svm_check_intercept_param(SVM_EXIT_RDTSC, 0);
 
3012
 
3023
3013
    val = cpu_get_tsc(env);
3024
3014
    EAX = (uint32_t)(val);
3025
3015
    EDX = (uint32_t)(val >> 32);
3030
3020
    if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
3031
3021
        raise_exception(EXCP0D_GPF);
3032
3022
    }
3033
 
 
3034
3023
    helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0);
3035
3024
    
3036
3025
    /* currently unimplemented */
3050
3039
{
3051
3040
    uint64_t val;
3052
3041
 
 
3042
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 1);
 
3043
 
3053
3044
    val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
3054
3045
 
3055
3046
    switch((uint32_t)ECX) {
3119
3110
void helper_rdmsr(void)
3120
3111
{
3121
3112
    uint64_t val;
 
3113
 
 
3114
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 0);
 
3115
 
3122
3116
    switch((uint32_t)ECX) {
3123
3117
    case MSR_IA32_SYSENTER_CS:
3124
3118
        val = env->sysenter_cs;
4549
4543
 
4550
4544
void helper_hlt(void)
4551
4545
{
 
4546
    helper_svm_check_intercept_param(SVM_EXIT_HLT, 0);
 
4547
    
4552
4548
    env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
4553
4549
    env->hflags |= HF_HALTED_MASK;
4554
4550
    env->exception_index = EXCP_HLT;
4560
4556
    if ((uint32_t)ECX != 0)
4561
4557
        raise_exception(EXCP0D_GPF);
4562
4558
    /* XXX: store address ? */
 
4559
    helper_svm_check_intercept_param(SVM_EXIT_MONITOR, 0);
4563
4560
}
4564
4561
 
4565
4562
void helper_mwait(void)
4566
4563
{
4567
4564
    if ((uint32_t)ECX != 0)
4568
4565
        raise_exception(EXCP0D_GPF);
 
4566
    helper_svm_check_intercept_param(SVM_EXIT_MWAIT, 0);
4569
4567
    /* XXX: not complete but not completely erroneous */
4570
4568
    if (env->cpu_index != 0 || env->next_cpu != NULL) {
4571
4569
        /* more than one CPU: do not sleep because another CPU may
4706
4704
                cpu_restore_state(tb, env, pc, NULL);
4707
4705
            }
4708
4706
        }
4709
 
        if (retaddr)
4710
 
            raise_exception_err(env->exception_index, env->error_code);
4711
 
        else
4712
 
            raise_exception_err_norestore(env->exception_index, env->error_code);
 
4707
        raise_exception_err(env->exception_index, env->error_code);
4713
4708
    }
4714
4709
    env = saved_env;
4715
4710
}
4717
4712
 
4718
4713
/* Secure Virtual Machine helpers */
4719
4714
 
4720
 
void helper_stgi(void)
4721
 
{
4722
 
    env->hflags |= HF_GIF_MASK;
4723
 
}
4724
 
 
4725
 
void helper_clgi(void)
4726
 
{
4727
 
    env->hflags &= ~HF_GIF_MASK;
4728
 
}
4729
 
 
4730
4715
#if defined(CONFIG_USER_ONLY)
4731
4716
 
4732
4717
void helper_vmrun(void) 
4741
4726
void helper_vmsave(void) 
4742
4727
4743
4728
}
 
4729
void helper_stgi(void)
 
4730
{
 
4731
}
 
4732
void helper_clgi(void)
 
4733
{
 
4734
}
4744
4735
void helper_skinit(void) 
4745
4736
4746
4737
}
4760
4751
}
4761
4752
#else
4762
4753
 
4763
 
static inline uint32_t
4764
 
vmcb2cpu_attrib(uint16_t vmcb_attrib, uint32_t vmcb_base, uint32_t vmcb_limit)
4765
 
{
4766
 
    return    ((vmcb_attrib & 0x00ff) << 8)          /* Type, S, DPL, P */
4767
 
            | ((vmcb_attrib & 0x0f00) << 12)         /* AVL, L, DB, G */
4768
 
            | ((vmcb_base >> 16) & 0xff)             /* Base 23-16 */
4769
 
            | (vmcb_base & 0xff000000)               /* Base 31-24 */
4770
 
            | (vmcb_limit & 0xf0000);                /* Limit 19-16 */
4771
 
}
4772
 
 
4773
 
static inline uint16_t cpu2vmcb_attrib(uint32_t cpu_attrib)
4774
 
{
4775
 
    return    ((cpu_attrib >> 8) & 0xff)             /* Type, S, DPL, P */
4776
 
            | ((cpu_attrib & 0xf00000) >> 12);       /* AVL, L, DB, G */
 
4754
static inline void svm_save_seg(target_phys_addr_t addr,
 
4755
                                const SegmentCache *sc)
 
4756
{
 
4757
    stw_phys(addr + offsetof(struct vmcb_seg, selector), 
 
4758
             sc->selector);
 
4759
    stq_phys(addr + offsetof(struct vmcb_seg, base), 
 
4760
             sc->base);
 
4761
    stl_phys(addr + offsetof(struct vmcb_seg, limit), 
 
4762
             sc->limit);
 
4763
    stw_phys(addr + offsetof(struct vmcb_seg, attrib), 
 
4764
             (sc->flags >> 8) | ((sc->flags >> 12) & 0x0f00));
 
4765
}
 
4766
                                
 
4767
static inline void svm_load_seg(target_phys_addr_t addr, SegmentCache *sc)
 
4768
{
 
4769
    unsigned int flags;
 
4770
 
 
4771
    sc->selector = lduw_phys(addr + offsetof(struct vmcb_seg, selector));
 
4772
    sc->base = ldq_phys(addr + offsetof(struct vmcb_seg, base));
 
4773
    sc->limit = ldl_phys(addr + offsetof(struct vmcb_seg, limit));
 
4774
    flags = lduw_phys(addr + offsetof(struct vmcb_seg, attrib));
 
4775
    sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12);
 
4776
}
 
4777
 
 
4778
static inline void svm_load_seg_cache(target_phys_addr_t addr, 
 
4779
                                      CPUState *env, int seg_reg)
 
4780
{
 
4781
    SegmentCache sc1, *sc = &sc1;
 
4782
    svm_load_seg(addr, sc);
 
4783
    cpu_x86_load_seg_cache(env, seg_reg, sc->selector,
 
4784
                           sc->base, sc->limit, sc->flags);
4777
4785
}
4778
4786
 
4779
4787
void helper_vmrun(void)
4782
4790
    uint32_t event_inj;
4783
4791
    uint32_t int_ctl;
4784
4792
 
 
4793
    helper_svm_check_intercept_param(SVM_EXIT_VMRUN, 0);
 
4794
 
4785
4795
    addr = EAX;
4786
4796
    if (loglevel & CPU_LOG_TB_IN_ASM)
4787
4797
        fprintf(logfile,"vmrun! " TARGET_FMT_lx "\n", addr);
4806
4816
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
4807
4817
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags());
4808
4818
 
4809
 
    SVM_SAVE_SEG(env->vm_hsave, segs[R_ES], es);
4810
 
    SVM_SAVE_SEG(env->vm_hsave, segs[R_CS], cs);
4811
 
    SVM_SAVE_SEG(env->vm_hsave, segs[R_SS], ss);
4812
 
    SVM_SAVE_SEG(env->vm_hsave, segs[R_DS], ds);
 
4819
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.es), 
 
4820
                  &env->segs[R_ES]);
 
4821
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.cs), 
 
4822
                 &env->segs[R_CS]);
 
4823
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ss), 
 
4824
                 &env->segs[R_SS]);
 
4825
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ds), 
 
4826
                 &env->segs[R_DS]);
4813
4827
 
4814
4828
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip), EIP);
4815
4829
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP);
4817
4831
 
4818
4832
    /* load the interception bitmaps so we do not need to access the
4819
4833
       vmcb in svm mode */
4820
 
    /* We shift all the intercept bits so we can OR them with the TB
4821
 
       flags later on */
4822
 
    env->intercept            = (ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept)) << INTERCEPT_INTR) | INTERCEPT_SVM_MASK;
 
4834
    env->intercept            = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept));
4823
4835
    env->intercept_cr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read));
4824
4836
    env->intercept_cr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write));
4825
4837
    env->intercept_dr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read));
4826
4838
    env->intercept_dr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write));
4827
4839
    env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions));
4828
4840
 
 
4841
    /* enable intercepts */
 
4842
    env->hflags |= HF_SVMI_MASK;
 
4843
 
4829
4844
    env->gdt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base));
4830
4845
    env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit));
4831
4846
 
4857
4872
    load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)),
4858
4873
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
4859
4874
    CC_OP = CC_OP_EFLAGS;
4860
 
    CC_DST = 0xffffffff;
4861
4875
 
4862
 
    SVM_LOAD_SEG(env->vm_vmcb, ES, es);
4863
 
    SVM_LOAD_SEG(env->vm_vmcb, CS, cs);
4864
 
    SVM_LOAD_SEG(env->vm_vmcb, SS, ss);
4865
 
    SVM_LOAD_SEG(env->vm_vmcb, DS, ds);
 
4876
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.es),
 
4877
                       env, R_ES);
 
4878
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.cs),
 
4879
                       env, R_CS);
 
4880
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ss),
 
4881
                       env, R_SS);
 
4882
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ds),
 
4883
                       env, R_DS);
4866
4884
 
4867
4885
    EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip));
4868
4886
    env->eip = EIP;
4933
4951
        if (loglevel & CPU_LOG_TB_IN_ASM)
4934
4952
            fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code);
4935
4953
    }
4936
 
    if ((int_ctl & V_IRQ_MASK) || (env->intercept & INTERCEPT_VINTR)) {
 
4954
    if ((int_ctl & V_IRQ_MASK) || 
 
4955
        (env->intercept & (1ULL << (SVM_EXIT_INTR - SVM_EXIT_INTR)))) {
4937
4956
        env->interrupt_request |= CPU_INTERRUPT_VIRQ;
4938
4957
    }
4939
4958
 
4942
4961
 
4943
4962
void helper_vmmcall(void)
4944
4963
{
4945
 
    if (loglevel & CPU_LOG_TB_IN_ASM)
4946
 
        fprintf(logfile,"vmmcall!\n");
 
4964
    helper_svm_check_intercept_param(SVM_EXIT_VMMCALL, 0);
 
4965
    raise_exception(EXCP06_ILLOP);
4947
4966
}
4948
4967
 
4949
4968
void helper_vmload(void)
4950
4969
{
4951
4970
    target_ulong addr;
 
4971
    helper_svm_check_intercept_param(SVM_EXIT_VMLOAD, 0);
 
4972
 
 
4973
    /* XXX: invalid in 32 bit */
4952
4974
    addr = EAX;
4953
4975
    if (loglevel & CPU_LOG_TB_IN_ASM)
4954
4976
        fprintf(logfile,"vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
4955
4977
                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
4956
4978
                env->segs[R_FS].base);
4957
4979
 
4958
 
    SVM_LOAD_SEG2(addr, segs[R_FS], fs);
4959
 
    SVM_LOAD_SEG2(addr, segs[R_GS], gs);
4960
 
    SVM_LOAD_SEG2(addr, tr, tr);
4961
 
    SVM_LOAD_SEG2(addr, ldt, ldtr);
 
4980
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.fs),
 
4981
                       env, R_FS);
 
4982
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.gs),
 
4983
                       env, R_GS);
 
4984
    svm_load_seg(addr + offsetof(struct vmcb, save.tr),
 
4985
                 &env->tr);
 
4986
    svm_load_seg(addr + offsetof(struct vmcb, save.ldtr),
 
4987
                 &env->ldt);
4962
4988
 
4963
4989
#ifdef TARGET_X86_64
4964
4990
    env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base));
4975
5001
void helper_vmsave(void)
4976
5002
{
4977
5003
    target_ulong addr;
 
5004
    helper_svm_check_intercept_param(SVM_EXIT_VMSAVE, 0);
4978
5005
    addr = EAX;
4979
5006
    if (loglevel & CPU_LOG_TB_IN_ASM)
4980
5007
        fprintf(logfile,"vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
4981
5008
                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
4982
5009
                env->segs[R_FS].base);
4983
5010
 
4984
 
    SVM_SAVE_SEG(addr, segs[R_FS], fs);
4985
 
    SVM_SAVE_SEG(addr, segs[R_GS], gs);
4986
 
    SVM_SAVE_SEG(addr, tr, tr);
4987
 
    SVM_SAVE_SEG(addr, ldt, ldtr);
 
5011
    svm_save_seg(addr + offsetof(struct vmcb, save.fs), 
 
5012
                 &env->segs[R_FS]);
 
5013
    svm_save_seg(addr + offsetof(struct vmcb, save.gs), 
 
5014
                 &env->segs[R_GS]);
 
5015
    svm_save_seg(addr + offsetof(struct vmcb, save.tr), 
 
5016
                 &env->tr);
 
5017
    svm_save_seg(addr + offsetof(struct vmcb, save.ldtr), 
 
5018
                 &env->ldt);
4988
5019
 
4989
5020
#ifdef TARGET_X86_64
4990
5021
    stq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base), env->kernelgsbase);
4998
5029
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_eip), env->sysenter_eip);
4999
5030
}
5000
5031
 
 
5032
void helper_stgi(void)
 
5033
{
 
5034
    helper_svm_check_intercept_param(SVM_EXIT_STGI, 0);
 
5035
    env->hflags |= HF_GIF_MASK;
 
5036
}
 
5037
 
 
5038
void helper_clgi(void)
 
5039
{
 
5040
    helper_svm_check_intercept_param(SVM_EXIT_CLGI, 0);
 
5041
    env->hflags &= ~HF_GIF_MASK;
 
5042
}
 
5043
 
5001
5044
void helper_skinit(void)
5002
5045
{
 
5046
    helper_svm_check_intercept_param(SVM_EXIT_SKINIT, 0);
 
5047
    /* XXX: not implemented */
5003
5048
    if (loglevel & CPU_LOG_TB_IN_ASM)
5004
5049
        fprintf(logfile,"skinit!\n");
 
5050
    raise_exception(EXCP06_ILLOP);
5005
5051
}
5006
5052
 
5007
5053
void helper_invlpga(void)
5008
5054
{
 
5055
    helper_svm_check_intercept_param(SVM_EXIT_INVLPGA, 0);
5009
5056
    tlb_flush(env, 0);
5010
5057
}
5011
5058
 
5012
5059
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
5013
5060
{
 
5061
    if (likely(!(env->hflags & HF_SVMI_MASK)))
 
5062
        return;
5014
5063
    switch(type) {
5015
5064
    case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
5016
 
        if (INTERCEPTEDw(_cr_read, (1 << (type - SVM_EXIT_READ_CR0)))) {
5017
 
            helper_vmexit(type, param);
5018
 
        }
5019
 
        break;
5020
 
    case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 8:
5021
 
        if (INTERCEPTEDw(_dr_read, (1 << (type - SVM_EXIT_READ_DR0)))) {
 
5065
        if (env->intercept_cr_read & (1 << (type - SVM_EXIT_READ_CR0))) {
5022
5066
            helper_vmexit(type, param);
5023
5067
        }
5024
5068
        break;
5025
5069
    case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
5026
 
        if (INTERCEPTEDw(_cr_write, (1 << (type - SVM_EXIT_WRITE_CR0)))) {
5027
 
            helper_vmexit(type, param);
5028
 
        }
5029
 
        break;
5030
 
    case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 8:
5031
 
        if (INTERCEPTEDw(_dr_write, (1 << (type - SVM_EXIT_WRITE_DR0)))) {
5032
 
            helper_vmexit(type, param);
5033
 
        }
5034
 
        break;
5035
 
    case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 16:
5036
 
        if (INTERCEPTEDl(_exceptions, (1 << (type - SVM_EXIT_EXCP_BASE)))) {
5037
 
            helper_vmexit(type, param);
5038
 
        }
5039
 
        break;
5040
 
    case SVM_EXIT_IOIO:
5041
 
        break;
5042
 
 
 
5070
        if (env->intercept_cr_write & (1 << (type - SVM_EXIT_WRITE_CR0))) {
 
5071
            helper_vmexit(type, param);
 
5072
        }
 
5073
        break;
 
5074
    case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 7:
 
5075
        if (env->intercept_dr_read & (1 << (type - SVM_EXIT_READ_DR0))) {
 
5076
            helper_vmexit(type, param);
 
5077
        }
 
5078
        break;
 
5079
    case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 7:
 
5080
        if (env->intercept_dr_write & (1 << (type - SVM_EXIT_WRITE_DR0))) {
 
5081
            helper_vmexit(type, param);
 
5082
        }
 
5083
        break;
 
5084
    case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 31:
 
5085
        if (env->intercept_exceptions & (1 << (type - SVM_EXIT_EXCP_BASE))) {
 
5086
            helper_vmexit(type, param);
 
5087
        }
 
5088
        break;
5043
5089
    case SVM_EXIT_MSR:
5044
 
        if (INTERCEPTED(1ULL << INTERCEPT_MSR_PROT)) {
 
5090
        if (env->intercept & (1ULL << (SVM_EXIT_MSR - SVM_EXIT_INTR))) {
5045
5091
            /* FIXME: this should be read in at vmrun (faster this way?) */
5046
5092
            uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.msrpm_base_pa));
5047
5093
            uint32_t t0, t1;
5071
5117
        }
5072
5118
        break;
5073
5119
    default:
5074
 
        if (INTERCEPTED((1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR)))) {
 
5120
        if (env->intercept & (1ULL << (type - SVM_EXIT_INTR))) {
5075
5121
            helper_vmexit(type, param);
5076
5122
        }
5077
5123
        break;
5081
5127
void helper_svm_check_io(uint32_t port, uint32_t param, 
5082
5128
                         uint32_t next_eip_addend)
5083
5129
{
5084
 
    if (INTERCEPTED(1ULL << INTERCEPT_IOIO_PROT)) {
 
5130
    if (env->intercept & (1ULL << (SVM_EXIT_IOIO - SVM_EXIT_INTR))) {
5085
5131
        /* FIXME: this should be read in at vmrun (faster this way?) */
5086
5132
        uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa));
5087
5133
        uint16_t mask = (1 << ((param >> 4) & 7)) - 1;
5113
5159
    }
5114
5160
 
5115
5161
    /* Save the VM state in the vmcb */
5116
 
    SVM_SAVE_SEG(env->vm_vmcb, segs[R_ES], es);
5117
 
    SVM_SAVE_SEG(env->vm_vmcb, segs[R_CS], cs);
5118
 
    SVM_SAVE_SEG(env->vm_vmcb, segs[R_SS], ss);
5119
 
    SVM_SAVE_SEG(env->vm_vmcb, segs[R_DS], ds);
 
5162
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.es), 
 
5163
                 &env->segs[R_ES]);
 
5164
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.cs), 
 
5165
                 &env->segs[R_CS]);
 
5166
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ss), 
 
5167
                 &env->segs[R_SS]);
 
5168
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ds), 
 
5169
                 &env->segs[R_DS]);
5120
5170
 
5121
5171
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
5122
5172
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
5146
5196
 
5147
5197
    /* Reload the host state from vm_hsave */
5148
5198
    env->hflags &= ~HF_HIF_MASK;
 
5199
    env->hflags &= ~HF_SVMI_MASK;
5149
5200
    env->intercept = 0;
5150
5201
    env->intercept_exceptions = 0;
5151
5202
    env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
5169
5220
    env->hflags &= ~HF_LMA_MASK;
5170
5221
    if (env->efer & MSR_EFER_LMA)
5171
5222
       env->hflags |= HF_LMA_MASK;
 
5223
    /* XXX: should also emulate the VM_CR MSR */
 
5224
    env->hflags &= ~HF_SVME_MASK;
 
5225
    if (env->cpuid_ext3_features & CPUID_EXT3_SVM) {
 
5226
        if (env->efer & MSR_EFER_SVME)
 
5227
            env->hflags |= HF_SVME_MASK;
 
5228
    } else {
 
5229
        env->efer &= ~MSR_EFER_SVME;
 
5230
    }
5172
5231
#endif
5173
5232
 
5174
5233
    env->eflags = 0;
5176
5235
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
5177
5236
    CC_OP = CC_OP_EFLAGS;
5178
5237
 
5179
 
    SVM_LOAD_SEG(env->vm_hsave, ES, es);
5180
 
    SVM_LOAD_SEG(env->vm_hsave, CS, cs);
5181
 
    SVM_LOAD_SEG(env->vm_hsave, SS, ss);
5182
 
    SVM_LOAD_SEG(env->vm_hsave, DS, ds);
 
5238
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.es),
 
5239
                       env, R_ES);
 
5240
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.cs),
 
5241
                       env, R_CS);
 
5242
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ss),
 
5243
                       env, R_SS);
 
5244
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ds),
 
5245
                       env, R_DS);
5183
5246
 
5184
5247
    EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip));
5185
5248
    ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp));