VirtualBox

Changeset 46297 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
May 28, 2013 2:38:48 PM (12 years ago)
Author:
vboxsync
Message:

VMM: Started HMSVMR0 work. Unify the AMD-V erratum 170 verification code between R0 and R3. General HM tidying.

Location:
trunk/src/VBox/VMM
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/HMAll.cpp

    r45701 r46297  
    3434#include <iprt/string.h>
    3535#include <iprt/x86.h>
     36#include <iprt/asm-amd64-x86.h>
    3637
    3738
     
    371372}
    372373
     374
     375/**
     376 * Checks if the current AMD CPU is subject to erratum 170 "In SVM mode,
     377 * incorrect code bytes may be fetched after a world-switch".
     378 *
     379 * @param   pu32Family      Where to store the CPU family (can be NULL).
     380 * @param   pu32Model       Where to store the CPU model (can be NULL).
     381 * @param   pu32Stepping    Where to store the CPU stepping (can be NULL).
     382 * @returns true if the erratum applies, false otherwise.
     383 */
     384VMM_INT_DECL(int) HMAmdIsSubjectToErratum170(uint32_t *pu32Family, uint32_t *pu32Model, uint32_t *pu32Stepping)
     385{
     386    /*
     387     * Erratum 170 which requires a forced TLB flush for each world switch:
     388     * See AMD spec. "Revision Guide for AMD NPT Family 0Fh Processors".
     389     *
     390     * All BH-G1/2 and DH-G1/2 models include a fix:
     391     * Athlon X2:   0x6b 1/2
     392     *              0x68 1/2
     393     * Athlon 64:   0x7f 1
     394     *              0x6f 2
     395     * Sempron:     0x7f 1/2
     396     *              0x6f 2
     397     *              0x6c 2
     398     *              0x7c 2
     399     * Turion 64:   0x68 2
     400     */
     401    uint32_t u32Dummy;
     402    uint32_t u32Version, u32Family, u32Model, u32Stepping, u32BaseFamily;
     403    ASMCpuId(1, &u32Version, &u32Dummy, &u32Dummy, &u32Dummy);
     404    u32BaseFamily = (u32Version >> 8) & 0xf;
     405    u32Family     = u32BaseFamily + (u32BaseFamily == 0xf ? ((u32Version >> 20) & 0x7f) : 0);
     406    u32Model      = ((u32Version >> 4) & 0xf);
     407    u32Model      = u32Model | ((u32BaseFamily == 0xf ? (u32Version >> 16) & 0x0f : 0) << 4);
     408    u32Stepping   = u32Version & 0xf;
     409
     410    bool fErratumApplies = false;
     411    if (   u32Family == 0xf
     412        && !((u32Model == 0x68 || u32Model == 0x6b || u32Model == 0x7f) && u32Stepping >= 1)
     413        && !((u32Model == 0x6f || u32Model == 0x6c || u32Model == 0x7c) && u32Stepping >= 2))
     414    {
     415        fErratumApplies = true;
     416    }
     417
     418    if (pu32Family)
     419        *pu32Family   = u32Family;
     420    if (pu32Model)
     421        *pu32Model    = u32Model;
     422    if (pu32Stepping)
     423        *pu32Stepping = u32Stepping;
     424
     425    return fErratumApplies;
     426}
     427
  • trunk/src/VBox/VMM/VMMR0/HMR0.cpp

    r45947 r46297  
    550550/**
    551551 * AMD-specific initialization code.
    552  */
    553 static void hmR0InitAmd(uint32_t u32FeaturesEDX, uint32_t uMaxExtLeaf)
     552 *
     553 * @returns VBox status code.
     554 */
     555static int hmR0InitAmd(uint32_t u32FeaturesEDX, uint32_t uMaxExtLeaf)
    554556{
    555557    /*
     
    557559     * We also assume all SVM-enabled CPUs support fxsave/fxrstor.
    558560     */
     561    int rc;
    559562    if (   (g_HvmR0.cpuid.u32AMDFeatureECX & X86_CPUID_AMD_FEATURE_ECX_SVM)
    560563        && (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_MSR)
     
    564567       )
    565568    {
     569        /* Call the global AMD-V initialization routine. */
     570        rc = SVMR0GlobalInit();
     571        if (RT_FAILURE(rc))
     572        {
     573            g_HvmR0.lLastError = rc;
     574            return rc;
     575        }
     576
     577        /*
     578         * Install the AMD-V methods.
     579         */
    566580        g_HvmR0.pfnEnterSession     = SVMR0Enter;
    567581        g_HvmR0.pfnLeaveSession     = SVMR0Leave;
     
    585599        HMR0FIRSTRC FirstRc;
    586600        hmR0FirstRcInit(&FirstRc);
    587         int rc = RTMpOnAll(hmR0InitAmdCpu, &FirstRc, NULL);
     601        rc = RTMpOnAll(hmR0InitAmdCpu, &FirstRc, NULL);
    588602        AssertRC(rc);
    589603        if (RT_SUCCESS(rc))
     
    603617    }
    604618    else
    605         g_HvmR0.lLastError = VERR_SVM_NO_SVM;
     619    {
     620        rc = VERR_SVM_NO_SVM;
     621        g_HvmR0.lLastError = rc;
     622    }
     623    return rc;
    606624}
    607625
     
    679697            }
    680698            else if (ASMIsAmdCpuEx(u32VendorEBX, u32VendorECX, u32VendorEDX))
    681                 hmR0InitAmd(u32FeaturesEDX, uMaxExtLeaf);
     699            {
     700                rc = hmR0InitAmd(u32FeaturesEDX, uMaxExtLeaf);
     701                if (RT_FAILURE(rc))
     702                    return rc;
     703            }
    682704            else
    683705                g_HvmR0.lLastError = VERR_HM_UNKNOWN_CPU;
     
    772794    }
    773795
    774     /** @todo This needs cleaning up. There's no matching hmR0TermIntel() and all
    775      *        the VT-x/AMD-V specific bits should move into their respective
    776      *        modules. */
     796    /** @todo This needs cleaning up. There's no matching
     797     *        hmR0TermIntel()/hmR0TermAmd() and all the VT-x/AMD-V specific bits
     798     *        should move into their respective modules. */
    777799    /* Finally, call global VT-x/AMD-V termination. */
    778800    if (g_HvmR0.vmx.fSupported)
    779801        VMXR0GlobalTerm();
     802    else if (g_HvmR0.svm.fSupported)
     803        SVMR0GlobalTerm();
    780804
    781805    return rc;
     
    825849
    826850/**
    827  * Worker function used by hmR0PowerCallback  and HMR0Init to initalize
    828  * VT-x / AMD-V on a CPU.
     851 * Worker function used by hmR0PowerCallback() and HMR0Init() to initalize AMD-V
     852 * on a CPU.
    829853 *
    830854 * @param   idCpu       The identifier for the CPU the function is called on.
  • trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp

    r45965 r46297  
    178178
    179179/**
     180 * Does global AMD-V initialization (called during module initialization).
     181 *
     182 * @returns VBox status code.
     183 */
     184VMMR0DECL(int) SVMR0GlobalInit(void)
     185{
     186    return VINF_SUCCESS;
     187}
     188
     189
     190/**
     191 * Does global VT-x termination (called during module termination).
     192 */
     193VMMR0DECL(void) SVMR0GlobalTerm(void)
     194{
     195}
     196
     197
     198/**
    180199 * Does Ring-0 per VM AMD-V init.
    181200 *
     
    199218    ASMMemFill32(pVM->hm.s.svm.pvIOBitmap, 3 << PAGE_SHIFT, 0xffffffff);
    200219
    201     /*
    202      * Erratum 170 which requires a forced TLB flush for each world switch:
    203      * See http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/33610.pdf
    204      *
    205      * All BH-G1/2 and DH-G1/2 models include a fix:
    206      * Athlon X2:   0x6b 1/2
    207      *              0x68 1/2
    208      * Athlon 64:   0x7f 1
    209      *              0x6f 2
    210      * Sempron:     0x7f 1/2
    211      *              0x6f 2
    212      *              0x6c 2
    213      *              0x7c 2
    214      * Turion 64:   0x68 2
    215      */
    216     uint32_t u32Dummy;
    217     uint32_t u32Version, u32Family, u32Model, u32Stepping, u32BaseFamily;
    218     ASMCpuId(1, &u32Version, &u32Dummy, &u32Dummy, &u32Dummy);
    219     u32BaseFamily = (u32Version >> 8) & 0xf;
    220     u32Family     = u32BaseFamily + (u32BaseFamily == 0xf ? ((u32Version >> 20) & 0x7f) : 0);
    221     u32Model      = ((u32Version >> 4) & 0xf);
    222     u32Model      = u32Model | ((u32BaseFamily == 0xf ? (u32Version >> 16) & 0x0f : 0) << 4);
    223     u32Stepping   = u32Version & 0xf;
    224     if (    u32Family == 0xf
    225         &&  !((u32Model == 0x68 || u32Model == 0x6b || u32Model == 0x7f) &&  u32Stepping >= 1)
    226         &&  !((u32Model == 0x6f || u32Model == 0x6c || u32Model == 0x7c) &&  u32Stepping >= 2))
     220    /* Check for an AMD CPU erratum which requires us to flush the TLB before every world-switch. */
     221    uint32_t u32Family;
     222    uint32_t u32Model;
     223    uint32_t u32Stepping;
     224    if (HMAmdIsSubjectToErratum170(&u32Family, &u32Model, &u32Stepping))
    227225    {
    228226        Log(("SVMR0InitVM: AMD cpu with erratum 170 family %x model %x stepping %x\n", u32Family, u32Model, u32Stepping));
  • trunk/src/VBox/VMM/VMMR0/HWSVMR0.h

    r45786 r46297  
    3838#ifdef IN_RING0
    3939
    40 /**
    41  * Enters the AMD-V session
    42  *
    43  * @returns VBox status code.
    44  * @param   pVM         Pointer to the VM.
    45  * @param   pVCpu       Pointer to the VMCPU.
    46  * @param   pCpu        Pointer to the CPU info struct.
    47  */
    48 VMMR0DECL(int) SVMR0Enter(PVM pVM, PVMCPU pVCpu, PHMGLOBLCPUINFO pCpu);
    49 
    50 /**
    51  * Leaves the AMD-V session
    52  *
    53  * @returns VBox status code.
    54  * @param   pVM         Pointer to the VM.
    55  * @param   pVCpu       Pointer to the VMCPU.
    56  * @param   pCtx        Pointer to the guest CPU context.
    57  */
    58 VMMR0DECL(int) SVMR0Leave(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
    59 
    60 VMMR0DECL(int) SVMR0EnableCpu(PHMGLOBLCPUINFO pCpu, PVM pVM, void *pvPageCpu, RTHCPHYS HCPhysCpuPage, bool fEnabledBySystem);
    61 
    62 /**
    63  * Deactivates AMD-V on the current CPU
    64  *
    65  * @returns VBox status code.
    66  * @param   pCpu            Pointer to the CPU info struct.
    67  * @param   pvPageCpu       Pointer to the global CPU page.
    68  * @param   pPageCpuPhys    Physical address of the global CPU page.
    69  */
    70 VMMR0DECL(int) SVMR0DisableCpu(PHMGLOBLCPUINFO pCpu, void *pvPageCpu, RTHCPHYS pPageCpuPhys);
    71 
    72 /**
    73  * Does Ring-0 per VM AMD-V init.
    74  *
    75  * @returns VBox status code.
    76  * @param   pVM         Pointer to the VM.
    77  */
    78 VMMR0DECL(int) SVMR0InitVM(PVM pVM);
    79 
    80 /**
    81  * Does Ring-0 per VM AMD-V termination.
    82  *
    83  * @returns VBox status code.
    84  * @param   pVM         Pointer to the VM.
    85  */
    86 VMMR0DECL(int) SVMR0TermVM(PVM pVM);
    87 
    88 /**
    89  * Sets up AMD-V for the specified VM
    90  *
    91  * @returns VBox status code.
    92  * @param   pVM         Pointer to the VM.
    93  */
    94 VMMR0DECL(int) SVMR0SetupVM(PVM pVM);
    95 
    96 
    97 /**
    98  * Runs guest code in an AMD-V VM.
    99  *
    100  * @returns VBox status code.
    101  * @param   pVM         Pointer to the VM.
    102  * @param   pVCpu       Pointer to the VMCPU.
    103  * @param   pCtx        Pointer to the guest CPU context.
    104  */
    105 VMMR0DECL(int) SVMR0RunGuestCode(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
    106 
    107 
    108 /**
    109  * Save the host state.
    110  *
    111  * @returns VBox status code.
    112  * @param   pVM         Pointer to the VM.
    113  * @param   pVCpu       Pointer to the VMCPU.
    114  */
    115 VMMR0DECL(int) SVMR0SaveHostState(PVM pVM, PVMCPU pVCpu);
    116 
    117 /**
    118  * Loads the guest state.
    119  *
    120  * @returns VBox status code.
    121  * @param   pVM         Pointer to the VM.
    122  * @param   pVCpu       Pointer to the VMCPU.
    123  * @param   pCtx        Pointer to the guest CPU context.
    124  */
    125 VMMR0DECL(int) SVMR0LoadGuestState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
    126 
     40VMMR0DECL(int)  SVMR0GlobalInit(void);
     41VMMR0DECL(void) SVMR0GlobalTerm(void);
     42VMMR0DECL(int)  SVMR0Enter(PVM pVM, PVMCPU pVCpu, PHMGLOBLCPUINFO pCpu);
     43VMMR0DECL(int)  SVMR0Leave(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
     44VMMR0DECL(int)  SVMR0EnableCpu(PHMGLOBLCPUINFO pCpu, PVM pVM, void *pvPageCpu, RTHCPHYS HCPhysCpuPage, bool fEnabledBySystem);
     45VMMR0DECL(int)  SVMR0DisableCpu(PHMGLOBLCPUINFO pCpu, void *pvPageCpu, RTHCPHYS pPageCpuPhys);
     46VMMR0DECL(int)  SVMR0InitVM(PVM pVM);
     47VMMR0DECL(int)  SVMR0TermVM(PVM pVM);
     48VMMR0DECL(int)  SVMR0SetupVM(PVM pVM);
     49VMMR0DECL(int)  SVMR0RunGuestCode(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
     50VMMR0DECL(int)  SVMR0SaveHostState(PVM pVM, PVMCPU pVCpu);
     51VMMR0DECL(int)  SVMR0LoadGuestState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
    12752
    12853#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS) && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)
  • trunk/src/VBox/VMM/VMMR3/HM.cpp

    r46280 r46297  
    13591359    Log(("pVM->hm.s.svm.fSupported = %d\n", pVM->hm.s.svm.fSupported));
    13601360
    1361     /* Erratum 170 which requires a forced TLB flush for each world switch:
    1362      * See http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/33610.pdf
    1363      *
    1364      * All BH-G1/2 and DH-G1/2 models include a fix:
    1365      * Athlon X2:   0x6b 1/2
    1366      *              0x68 1/2
    1367      * Athlon 64:   0x7f 1
    1368      *              0x6f 2
    1369      * Sempron:     0x7f 1/2
    1370      *              0x6f 2
    1371      *              0x6c 2
    1372      *              0x7c 2
    1373      * Turion 64:   0x68 2
    1374      *
    1375      */
    1376     uint32_t u32Dummy;
    1377     uint32_t u32Version, u32Family, u32Model, u32Stepping, u32BaseFamily;
    1378     ASMCpuId(1, &u32Version, &u32Dummy, &u32Dummy, &u32Dummy);
    1379     u32BaseFamily= (u32Version >> 8) & 0xf;
    1380     u32Family    = u32BaseFamily + (u32BaseFamily == 0xf ? ((u32Version >> 20) & 0x7f) : 0);
    1381     u32Model     = ((u32Version >> 4) & 0xf);
    1382     u32Model     = u32Model | ((u32BaseFamily == 0xf ? (u32Version >> 16) & 0x0f : 0) << 4);
    1383     u32Stepping  = u32Version & 0xf;
    1384     if (    u32Family == 0xf
    1385         &&  !((u32Model == 0x68 || u32Model == 0x6b || u32Model == 0x7f) &&  u32Stepping >= 1)
    1386         &&  !((u32Model == 0x6f || u32Model == 0x6c || u32Model == 0x7c) &&  u32Stepping >= 2))
    1387     {
    1388         LogRel(("HM: AMD cpu with erratum 170 family %x model %x stepping %x\n", u32Family, u32Model, u32Stepping));
    1389     }
    1390 
     1361    uint32_t u32Family;
     1362    uint32_t u32Model;
     1363    uint32_t u32Stepping;
     1364    if (HMAmdIsSubjectToErratum170(&u32Family, &u32Model, &u32Stepping))
     1365        LogRel(("HM: AMD Cpu with erratum 170 family %#x model %#x stepping %#x\n", u32Family, u32Model, u32Stepping));
    13911366    LogRel(("HM: cpuid 0x80000001.u32AMDFeatureECX = %RX32\n", pVM->hm.s.cpuid.u32AMDFeatureECX));
    13921367    LogRel(("HM: cpuid 0x80000001.u32AMDFeatureEDX = %RX32\n", pVM->hm.s.cpuid.u32AMDFeatureEDX));
Note: See TracChangeset for help on using the changeset viewer.

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