VirtualBox

Changeset 14411 in vbox


Ignore:
Timestamp:
Nov 20, 2008 1:26:47 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
39642
Message:

RDTSCP support added. Enabled only for AMD-V guests.

Location:
trunk
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/cpum.h

    r13975 r14411  
    361361 */
    362362#define CPUMCTX2CORE(pCtx) ((PCPUMCTXCORE)(void *)&(pCtx)->edi)
    363 
    364363
    365364/**
     
    543542} CPUMCTX_VER1_6;
    544543#pragma pack()
     544
     545/* Guest MSR state. */
     546typedef union CPUMCTXMSR
     547{
     548    struct
     549    {
     550        uint64_t        tscAux;         /* MSR_K8_TSC_AUX */
     551    } msr;
     552    uint64_t    au64[64];
     553} CPUMCTXMSR;
     554/** Pointer to the guest MSR state. */
     555typedef CPUMCTXMSR *PCPUMCTXMSR;
     556/** Pointer to the const guest MSR state. */
     557typedef const CPUMCTXMSR *PCCPUMCTXMSR;
    545558
    546559
     
    584597    /** The x2APIC  feature bit. (Std) */
    585598    CPUMCPUIDFEATURE_X2APIC,
     599    /** The RDTSCP feature bit. (Ext) */
     600    CPUMCPUIDFEATURE_RDTSCP,
    586601    /** 32bit hackishness. */
    587602    CPUMCPUIDFEATURE_32BIT_HACK = 0x7fffffff
     
    649664VMMDECL(uint64_t)   CPUMGetGuestEFER(PVM pVM);
    650665VMMDECL(uint64_t)   CPUMGetGuestMsr(PVM pVM, unsigned idMsr);
     666VMMDECL(void)       CPUMSetGuestMsr(PVM pVM, unsigned idMsr, uint64_t valMsr);
    651667/** @} */
    652668
  • trunk/include/VBox/cpum.mac

    r13954 r14411  
    196196    ; padding
    197197;;;    .padding            resd    6
     198endstruc
     199
     200
     201;;/* Guest MSR state. */
     202struc CPUMCTXMSR
     203    .au64               resq  64
    198204endstruc
    199205
  • trunk/include/VBox/em.h

    r13858 r14411  
    126126VMMDECL(int)        EMInterpretCpuId(PVM pVM, PCPUMCTXCORE pRegFrame);
    127127VMMDECL(int)        EMInterpretRdtsc(PVM pVM, PCPUMCTXCORE pRegFrame);
     128VMMDECL(int)        EMInterpretRdtscp(PVM pVM, PCPUMCTX pCtx);
    128129VMMDECL(int)        EMInterpretInvlpg(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPTR pAddrGC);
    129130VMMDECL(int)        EMInterpretIret(PVM pVM, PCPUMCTXCORE pRegFrame);
  • trunk/include/VBox/vm.h

    r14244 r14411  
    113113        struct CPUMCPU      s;
    114114#endif
    115         char                padding[2048];      /* multiple of 64 */
     115        char                padding[2560];      /* multiple of 64 */
    116116    } cpum;
    117117    /** VMM part. */
  • trunk/src/VBox/VMM/CPUM.cpp

    r14091 r14411  
    6868*******************************************************************************/
    6969/** The saved state version. */
    70 #define CPUM_SAVED_STATE_VERSION            9
     70#define CPUM_SAVED_STATE_VERSION                10
     71/** The saved state version for the 2.1 trunk before the MSR changes. */
     72#define CPUM_SAVED_STATE_VERSION_VER2_1_NOMSR   9
    7173/** The saved state version of 2.0, used for backwards compatibility. */
    72 #define CPUM_SAVED_STATE_VERSION_VER2_0     8
     74#define CPUM_SAVED_STATE_VERSION_VER2_0         8
    7375/** The saved state version of 1.6, used for backwards compatability. */
    74 #define CPUM_SAVED_STATE_VERSION_VER1_6     6
     76#define CPUM_SAVED_STATE_VERSION_VER1_6         6
    7577
    7678
     
    350352                                       | X86_CPUID_AMD_FEATURE_EDX_FFXSR
    351353                                       //| X86_CPUID_AMD_FEATURE_EDX_PAGE1GB
    352                                        //| X86_CPUID_AMD_FEATURE_EDX_RDTSCP
    353                                        //| X86_CPUID_AMD_FEATURE_EDX_LONG_MODE - not yet.
     354                                       //| X86_CPUID_AMD_FEATURE_EDX_RDTSCP - AMD only; turned on when necessary
     355                                       //| X86_CPUID_AMD_FEATURE_EDX_LONG_MODE - turned on when necessary
    354356                                       | X86_CPUID_AMD_FEATURE_EDX_3DNOW_EX
    355357                                       | X86_CPUID_AMD_FEATURE_EDX_3DNOW
     
    782784        SSMR3PutU32(pSSM, pVM->aCpus[i].cpum.s.fUseFlags);
    783785        SSMR3PutU32(pSSM, pVM->aCpus[i].cpum.s.fChanged);
     786        SSMR3PutMem(pSSM, &pVM->aCpus[i].cpum.s.GuestMsr, sizeof(pVM->aCpus[i].cpum.s.GuestMsr));
    784787    }
    785788
     
    912915     */
    913916    if (    u32Version != CPUM_SAVED_STATE_VERSION
     917        &&  u32Version != CPUM_SAVED_STATE_VERSION_VER2_1_NOMSR
    914918        &&  u32Version != CPUM_SAVED_STATE_VERSION_VER2_0
    915919        &&  u32Version != CPUM_SAVED_STATE_VERSION_VER1_6)
     
    947951    else
    948952    {
    949         if (u32Version == CPUM_SAVED_STATE_VERSION)
     953        if (u32Version >= CPUM_SAVED_STATE_VERSION_VER2_1_NOMSR)
    950954        {
    951955            int rc = SSMR3GetU32(pSSM, &pVM->cCPUs);
     
    967971            SSMR3GetU32(pSSM, &pVM->aCpus[i].cpum.s.fUseFlags);
    968972            SSMR3GetU32(pSSM, &pVM->aCpus[i].cpum.s.fChanged);
     973            if (u32Version == CPUM_SAVED_STATE_VERSION)
     974                SSMR3GetMem(pSSM, &pVM->aCpus[i].cpum.s.GuestMsr, sizeof(pVM->aCpus[i].cpum.s.GuestMsr));
    969975        }
    970976    }
  • trunk/src/VBox/VMM/CPUMInternal.h

    r13960 r14411  
    340340    CPUMCTX                 Guest;
    341341
     342    /**
     343     * Guest context - misc MSRs
     344     * Aligned on a 64-byte boundrary.
     345     */
     346    CPUMCTXMSR              GuestMsr;
     347
    342348    /** Use flags.
    343349     * These flags indicates both what is to be used and what has been used.
  • trunk/src/VBox/VMM/CPUMInternal.mac

    r13960 r14411  
    402402    .Guest.trHid.Attr         resd    1
    403403
     404    .GuestMsr.au64            resq    64
     405
    404406    .fUseFlags            resd    1
    405407    .fChanged             resd    1
  • trunk/src/VBox/VMM/HWACCM.cpp

    r14109 r14411  
    764764                CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_SEP);
    765765                CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_SYSCALL);
     766                CPUMSetGuestCpuidFeature(pVM, CPUMCPUIDFEATURE_RDTSCP);
    766767#ifdef VBOX_ENABLE_64_BITS_GUESTS
    767768                CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_PAE);
  • trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp

    r13975 r14411  
    839839            break;
    840840
     841        case MSR_K8_TSC_AUX:
     842            u64 = pCpumCpu->GuestMsr.msr.tscAux;
     843            break;
     844
    841845        /* fs & gs base skipped on purpose as the current context might not be up-to-date. */
    842846        default:
     
    847851}
    848852
     853VMMDECL(void) CPUMSetGuestMsr(PVM pVM, unsigned idMsr, uint64_t valMsr)
     854{
     855    PCPUMCPU pCpumCpu = cpumGetCpumCpu(pVM);
     856
     857    /* On purpose only a limited number of MSRs; use the emulation function to update the others. */
     858    switch (idMsr)
     859    {
     860        case MSR_K8_TSC_AUX:
     861            pCpumCpu->GuestMsr.msr.tscAux = valMsr;
     862            break;
     863
     864        default:
     865            AssertFailed();
     866            break;
     867    }
     868}
    849869
    850870VMMDECL(RTGCPTR) CPUMGetGuestIDTR(PVM pVM, uint16_t *pcbLimit)
     
    14311451        }
    14321452
     1453        case CPUMCPUIDFEATURE_RDTSCP:
     1454        {
     1455            if (    pVM->cpum.s.aGuestCpuIdExt[0].eax < 0x80000001
     1456                ||  !(ASMCpuId_EDX(0x80000001) & X86_CPUID_AMD_FEATURE_EDX_RDTSCP))
     1457            {
     1458                LogRel(("WARNING: Can't turn on RDTSCP when the host doesn't support it!!\n"));
     1459                return;
     1460            }
     1461
     1462            /* Valid for AMD only (for now). */
     1463            pVM->cpum.s.aGuestCpuIdExt[1].edx |= X86_CPUID_AMD_FEATURE_EDX_RDTSCP;
     1464            LogRel(("CPUMSetGuestCpuIdFeature: Enabled RDTSCP.\n"));
     1465            break;
     1466        }
     1467
    14331468        default:
    14341469            AssertMsgFailed(("enmFeature=%d\n", enmFeature));
     
    14561491            if (pVM->cpum.s.aGuestCpuIdStd[0].eax >= 1)
    14571492                return !!(pVM->cpum.s.aGuestCpuIdStd[1].edx & X86_CPUID_FEATURE_EDX_PAE);
     1493            break;
     1494        }
     1495
     1496        case CPUMCPUIDFEATURE_RDTSCP:
     1497        {
     1498            if (pVM->cpum.s.aGuestCpuIdExt[0].eax >= 0x80000001)
     1499                return !!(pVM->cpum.s.aGuestCpuIdExt[1].edx & X86_CPUID_AMD_FEATURE_EDX_RDTSCP);
    14581500            break;
    14591501        }
  • trunk/src/VBox/VMM/VMMAll/EMAll.cpp

    r14257 r14411  
    24522452}
    24532453
     2454VMMDECL(int) EMInterpretRdtscp(PVM pVM, PCPUMCTX pCtx)
     2455{
     2456    unsigned uCR4 = CPUMGetGuestCR4(pVM);
     2457
     2458    if (!CPUMGetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_RDTSCP))
     2459    {
     2460        AssertFailed();
     2461        return VERR_EM_INTERPRETER; /* genuine #UD */
     2462    }
     2463
     2464    if (uCR4 & X86_CR4_TSD)
     2465        return VERR_EM_INTERPRETER; /* genuine #GP */
     2466
     2467    uint64_t uTicks = TMCpuTickGet(pVM);
     2468
     2469    /* Same behaviour in 32 & 64 bits mode */
     2470    pCtx->rax = (uint32_t)uTicks;
     2471    pCtx->rdx = (uTicks >> 32ULL);
     2472    /* Low dword of the TSC_AUX msr only. */
     2473    pCtx->rcx = (uint32_t)CPUMGetGuestMsr(pVM, MSR_K8_TSC_AUX);
     2474
     2475    return VINF_SUCCESS;
     2476}
    24542477
    24552478/**
     
    25432566        return "MSR_K8_KERNEL_GS_BASE";
    25442567    case MSR_K8_TSC_AUX:
    2545         return "Unsupported MSR_K8_TSC_AUX";
     2568        return "MSR_K8_TSC_AUX";
    25462569    case MSR_IA32_BIOS_SIGN_ID:
    25472570        return "Unsupported MSR_IA32_BIOS_SIGN_ID";
     
    26632686        break;
    26642687
     2688    case MSR_K8_TSC_AUX:
     2689        val = CPUMGetGuestMsr(pVM, MSR_K8_TSC_AUX);
     2690        break;
     2691
    26652692#if 0 /*def IN_RING0 */
    26662693    case MSR_IA32_PLATFORM_ID:
     
    28212848    case MSR_K8_KERNEL_GS_BASE:
    28222849        pCtx->msrKERNELGSBASE = val;
     2850        break;
     2851
     2852    case MSR_K8_TSC_AUX:
     2853        CPUMSetGuestMsr(pVM, MSR_K8_TSC_AUX, val);
    28232854        break;
    28242855
  • trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp

    r14366 r14411  
    327327                                        | SVM_CTRL2_INTERCEPT_CLGI
    328328                                        | SVM_CTRL2_INTERCEPT_SKINIT
    329                                         | SVM_CTRL2_INTERCEPT_RDTSCP        /* AMD only; we don't support this one */
    330329                                        | SVM_CTRL2_INTERCEPT_WBINVD
    331330                                        | SVM_CTRL2_INTERCEPT_MWAIT_UNCOND; /* don't execute mwait or else we'll idle inside the guest (host thinks the cpu load is high) */
     
    781780    if (TMCpuTickCanUseRealTSC(pVM, &pVMCB->ctrl.u64TSCOffset))
    782781    {
    783         pVMCB->ctrl.u32InterceptCtrl1 &= ~SVM_CTRL1_INTERCEPT_RDTSC;
     782        pVMCB->ctrl.u32InterceptCtrl1 &= ~(SVM_CTRL1_INTERCEPT_RDTSC | SVM_CTRL2_INTERCEPT_RDTSCP);
    784783        STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatTSCOffset);
    785784    }
    786785    else
    787786    {
    788         pVMCB->ctrl.u32InterceptCtrl1 |= SVM_CTRL1_INTERCEPT_RDTSC;
     787        pVMCB->ctrl.u32InterceptCtrl1 |= (SVM_CTRL1_INTERCEPT_RDTSC | SVM_CTRL2_INTERCEPT_RDTSCP);
    789788        STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatTSCIntercept);
    790789    }
     
    10371036                                             | SVM_CTRL2_INTERCEPT_CLGI
    10381037                                             | SVM_CTRL2_INTERCEPT_SKINIT
    1039                                              | SVM_CTRL2_INTERCEPT_RDTSCP        /* AMD only; we don't support this one */
    10401038                                             | SVM_CTRL2_INTERCEPT_WBINVD
    10411039                                             | SVM_CTRL2_INTERCEPT_MWAIT_UNCOND  /* don't execute mwait or else we'll idle inside the guest (host thinks the cpu load is high) */
     
    16271625    }
    16281626
     1627    case SVM_EXIT_RDTSCP:                /* Guest software attempted to execute RDTSCP. */
     1628    {
     1629        Log2(("SVM: Rdtscp\n"));
     1630        STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatExitRdtsc);
     1631        rc = EMInterpretRdtscp(pVM, pCtx);
     1632        if (rc == VINF_SUCCESS)
     1633        {
     1634            /* Update EIP and continue execution. */
     1635            pCtx->rip += 3;             /* Note! hardcoded opcode size! */
     1636            STAM_PROFILE_ADV_STOP(&pVCpu->hwaccm.s.StatExit, x);
     1637            goto ResumeExecution;
     1638        }
     1639        AssertMsgFailed(("EMU: rdtscp failed with %Rrc\n", rc));
     1640        rc = VINF_EM_RAW_EMULATE_INSTR;
     1641        break;
     1642    }
     1643
    16291644    case SVM_EXIT_INVLPG:               /* Guest software attempted to execute INVPG. */
    16301645    {
     
    19771992    case SVM_EXIT_CLGI:
    19781993    case SVM_EXIT_SKINIT:
    1979     case SVM_EXIT_RDTSCP:
    19801994    {
    19811995        /* Unsupported instructions. */
  • trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp

    r14155 r14411  
    8282    GEN_CHECK_SIZE(CPUMHOSTCTX);
    8383    GEN_CHECK_SIZE(CPUMCTX);
     84    GEN_CHECK_SIZE(CPUMCTXMSR);
    8485    GEN_CHECK_SIZE(CPUMCTXCORE);
    8586    GEN_CHECK_SIZE(STAMRATIOU32);
  • trunk/src/VBox/VMM/testcase/tstVMStructSize.cpp

    r13961 r14411  
    234234    CHECK_SIZE_ALIGNMENT(CPUMCTX, 64);
    235235    CHECK_SIZE_ALIGNMENT(CPUMHOSTCTX, 64);
     236    CHECK_SIZE_ALIGNMENT(CPUMCTXMSR, 64);
    236237
    237238    /* pdm */
  • trunk/src/recompiler/VBoxREMWrapper.cpp

    r13852 r14411  
    480480};
    481481
     482/* CPUMGetGuestMsr args */
     483static const REMPARMDESC g_aArgsCPUMGetGuestMsr[] =
     484{
     485    { REMPARMDESC_FLAGS_INT,        sizeof(PVM), NULL },
     486    { REMPARMDESC_FLAGS_INT,        sizeof(uint32_t), NULL },
     487};
     488
     489/* CPUMGetGuestMsr args */
     490static const REMPARMDESC g_aArgsCPUMSetGuestMsr[] =
     491{
     492    { REMPARMDESC_FLAGS_INT,        sizeof(PVM), NULL },
     493    { REMPARMDESC_FLAGS_INT,        sizeof(uint32_t), NULL },
     494    { REMPARMDESC_FLAGS_INT,        sizeof(uint64_t), NULL },
     495};
     496
    482497static const REMPARMDESC g_aArgsCPUMGetGuestCpuId[] =
    483498{
     
    10431058    { "CPUMSetChangedFlags",                    (void *)(uintptr_t)&CPUMSetChangedFlags,            &g_aArgsCPUMSetChangedFlags[0],             RT_ELEMENTS(g_aArgsCPUMSetChangedFlags),               REMFNDESC_FLAGS_RET_VOID,   0,                  NULL },
    10441059    { "CPUMGetGuestCPL",                        (void *)(uintptr_t)&CPUMGetGuestCPL,                &g_aArgsCPUMGetGuestCpl[0],                 RT_ELEMENTS(g_aArgsCPUMGetGuestCpl),                   REMFNDESC_FLAGS_RET_INT,    sizeof(unsigned),   NULL },
     1060    { "CPUMGetGuestMsr",                        (void *)(uintptr_t)&CPUMGetGuestMsr,                &g_aArgsCPUMGetGuestMsr[0],                 RT_ELEMENTS(g_aArgsCPUMGetGuestMsr),                   REMFNDESC_FLAGS_RET_INT,    sizeof(uint64_t),   NULL },
     1061    { "CPUMSetGuestMsr",                        (void *)(uintptr_t)&CPUMSetGuestMsr,                &g_aArgsCPUMSetGuestMsr[0],                 RT_ELEMENTS(g_aArgsCPUMSetGuestMsr),                   REMFNDESC_FLAGS_RET_VOID,   0,                  NULL },
    10451062    { "CPUMGetGuestCpuId",                      (void *)(uintptr_t)&CPUMGetGuestCpuId,              &g_aArgsCPUMGetGuestCpuId[0],               RT_ELEMENTS(g_aArgsCPUMGetGuestCpuId),                 REMFNDESC_FLAGS_RET_VOID,   0,                  NULL },
    10461063    { "CPUMGetGuestEAX",                        (void *)(uintptr_t)&CPUMGetGuestEAX,                &g_aArgsVM[0],                              RT_ELEMENTS(g_aArgsVM),                                REMFNDESC_FLAGS_RET_INT,    sizeof(uint32_t),   NULL },
  • trunk/src/recompiler/VBoxRecompiler.c

    r13840 r14411  
    17731773#endif
    17741774
    1775 
    17761775    /*
    17771776     * Registers which are rarely changed and require special handling / order when changed.
     
    41334132    LogFlow(("cpu_apic_wrmsr: rc=%Rrc\n", rc)); NOREF(rc);
    41344133}
     4134
     4135uint64_t cpu_rdmsr(CPUX86State *env, uint32_t msr)
     4136{
     4137    return CPUMGetGuestMsr(env->pVM, msr);
     4138}
     4139
     4140void cpu_wrmsr(CPUX86State *env, uint32_t msr, uint64_t val)
     4141{
     4142    CPUMSetGuestMsr(env->pVM, msr, val);
     4143}
     4144
    41354145/* -+- I/O Ports -+- */
    41364146
  • trunk/src/recompiler/target-i386/cpu.h

    r13034 r14411  
    857857void cpu_smm_update(CPUX86State *env);
    858858
     859#ifdef VBOX
     860uint64_t cpu_rdmsr(CPUX86State *env, uint32_t msr);
     861void     cpu_wrmsr(CPUX86State *env, uint32_t msr, uint64_t val);
     862#endif
     863
    859864/* will be suppressed */
    860865void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
  • trunk/src/recompiler/target-i386/exec.h

    r11982 r14411  
    215215void helper_sysret(int dflag);
    216216void helper_rdtsc(void);
     217#ifdef VBOX
     218void helper_rdtscp(void);
     219#endif
    217220void helper_rdmsr(void);
    218221void helper_wrmsr(void);
  • trunk/src/recompiler/target-i386/helper.c

    r13839 r14411  
    30233023}
    30243024
     3025#ifdef VBOX
     3026void helper_rdtscp(void)
     3027{
     3028    uint64_t val;
     3029
     3030    if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
     3031        raise_exception(EXCP0D_GPF);
     3032    }
     3033
     3034    val = cpu_get_tsc(env);
     3035    EAX = (uint32_t)(val);
     3036    EDX = (uint32_t)(val >> 32);
     3037    ECX = cpu_rdmsr(env, MSR_K8_TSC_AUX);
     3038}
     3039#endif
     3040
    30253041#if defined(CONFIG_USER_ONLY)
    30263042void helper_wrmsr(void)
     
    31063122        break;
    31073123    }
     3124    case MSR_K8_TSC_AUX:
     3125        cpu_wrmsr(env, MSR_K8_TSC_AUX, val);
     3126        break;
    31083127#endif /* VBOX */
    31093128    }
     
    31703189        break;
    31713190    }
     3191    case MSR_K8_TSC_AUX:
     3192        val = cpu_rdmsr(env, MSR_K8_TSC_AUX);
     3193        break;
    31723194#endif /* VBOX */
    31733195    }
  • trunk/src/recompiler/target-i386/op.c

    r13449 r14411  
    10551055    helper_rdtsc();
    10561056}
     1057
     1058#ifdef VBOX
     1059void OPPROTO op_rdtscp(void)
     1060{
     1061    helper_rdtscp();
     1062}
     1063#endif
    10571064
    10581065void OPPROTO op_cpuid(void)
  • trunk/src/recompiler/target-i386/translate.c

    r13839 r14411  
    59405940        op = (modrm >> 3) & 7;
    59415941        rm = modrm & 7;
     5942
     5943#ifdef VBOX
     5944        /* 0f 01 f9 */
     5945        if (modrm == 0xf9)
     5946        {
     5947            if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP))
     5948                 goto illegal_op;
     5949            gen_jmp_im(pc_start - s->cs_base);
     5950            gen_op_rdtscp();
     5951            break;
     5952        }
     5953#endif
     5954
    59425955        switch(op) {
    59435956        case 0: /* sgdt */
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette