VirtualBox

Changeset 94934 in vbox for trunk/src/VBox/VMM/VMMR0


Ignore:
Timestamp:
May 9, 2022 8:41:13 AM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
151342
Message:

VMM/CPUM: Kicked out the VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI code, as it was for raw-mode use. bugref:9517

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/CPUMR0.cpp

    r94933 r94934  
    3333#include <iprt/asm-amd64-x86.h>
    3434#include <iprt/mem.h>
    35 #ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
    36 # include <iprt/memobj.h>
    37 # include <VBox/apic.h>
    38 #endif
    3935#include <iprt/x86.h>
    40 
    41 
    42 /*********************************************************************************************************************************
    43 *   Structures and Typedefs                                                                                                      *
    44 *********************************************************************************************************************************/
    45 #ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
    46 /**
    47  * Local APIC mappings.
    48  */
    49 typedef struct CPUMHOSTLAPIC
    50 {
    51     /** Indicates that the entry is in use and have valid data. */
    52     bool        fEnabled;
    53     /** Whether it's operating in X2APIC mode (EXTD). */
    54     bool        fX2Apic;
    55     /** The APIC version number. */
    56     uint32_t    uVersion;
    57     /** The physical address of the APIC registers. */
    58     RTHCPHYS    PhysBase;
    59     /** The memory object entering the physical address. */
    60     RTR0MEMOBJ  hMemObj;
    61     /** The mapping object for hMemObj. */
    62     RTR0MEMOBJ  hMapObj;
    63     /** The mapping address APIC registers.
    64      * @remarks Different CPUs may use the same physical address to map their
    65      *          APICs, so this pointer is only valid when on the CPU owning the
    66      *          APIC. */
    67     void       *pv;
    68 } CPUMHOSTLAPIC;
    69 #endif
    7036
    7137
     
    7844static CPUMMSRS     g_CpumHostMsrs;
    7945
    80 #ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
    81 static CPUMHOSTLAPIC g_aLApics[RTCPUSET_MAX_CPUS];
    82 #endif
    83 
    8446/**
    8547 * CPUID bits to unify among all cores.
     
    10567*   Internal Functions                                                                                                           *
    10668*********************************************************************************************************************************/
    107 #ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
    108 static int  cpumR0MapLocalApics(void);
    109 static void cpumR0UnmapLocalApics(void);
    110 #endif
    11169static int  cpumR0SaveHostDebugState(PVMCPUCC pVCpu);
    11270
     
    155113    AssertLogRelRCReturn(rc, rc);
    156114
    157 #ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
    158     return cpumR0MapLocalApics();
    159 #else
    160115    return VINF_SUCCESS;
    161 #endif
    162116}
    163117
     
    168122VMMR0_INT_DECL(int) CPUMR0ModuleTerm(void)
    169123{
    170 #ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
    171     cpumR0UnmapLocalApics();
    172 #endif
    173124    return VINF_SUCCESS;
    174125}
     
    752703}
    753704
    754 #ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
    755 
    756 /**
    757  * Per-CPU callback that probes the CPU for APIC support.
    758  *
    759  * @param   idCpu       The identifier for the CPU the function is called on.
    760  * @param   pvUser1     Ignored.
    761  * @param   pvUser2     Ignored.
    762  */
    763 static DECLCALLBACK(void) cpumR0MapLocalApicCpuProber(RTCPUID idCpu, void *pvUser1, void *pvUser2)
    764 {
    765     NOREF(pvUser1); NOREF(pvUser2);
    766     int iCpu = RTMpCpuIdToSetIndex(idCpu);
    767     AssertReturnVoid(iCpu >= 0 && (unsigned)iCpu < RT_ELEMENTS(g_aLApics));
    768 
    769     /*
    770      * Check for APIC support.
    771      */
    772     uint32_t uMaxLeaf, u32EBX, u32ECX, u32EDX;
    773     ASMCpuId(0, &uMaxLeaf, &u32EBX, &u32ECX, &u32EDX);
    774     if (   (   RTX86IsIntelCpu(u32EBX, u32ECX, u32EDX)
    775             || RTX86IsAmdCpu(u32EBX, u32ECX, u32EDX)
    776             || RTX86IsViaCentaurCpu(u32EBX, u32ECX, u32EDX)
    777             || RTX86IsShanghaiCpu(u32EBX, u32ECX, u32EDX)
    778             || RTX86IsHygonCpu(u32EBX, u32ECX, u32EDX))
    779         && RTX86IsValidStdRange(uMaxLeaf))
    780     {
    781         uint32_t uDummy;
    782         ASMCpuId(1, &uDummy, &u32EBX, &u32ECX, &u32EDX);
    783         if (    (u32EDX & X86_CPUID_FEATURE_EDX_APIC)
    784             &&  (u32EDX & X86_CPUID_FEATURE_EDX_MSR))
    785         {
    786             /*
    787              * Safe to access the MSR. Read it and calc the BASE (a little complicated).
    788              */
    789             uint64_t u64ApicBase = ASMRdMsr(MSR_IA32_APICBASE);
    790             uint64_t u64Mask     = MSR_IA32_APICBASE_BASE_MIN;
    791 
    792             /* see Intel Manual: Local APIC Status and Location: MAXPHYADDR default is bit 36 */
    793             uint32_t uMaxExtLeaf;
    794             ASMCpuId(0x80000000, &uMaxExtLeaf, &u32EBX, &u32ECX, &u32EDX);
    795             if (   uMaxExtLeaf >= UINT32_C(0x80000008)
    796                 && RTX86IsValidExtRange(uMaxExtLeaf))
    797             {
    798                 uint32_t u32PhysBits;
    799                 ASMCpuId(0x80000008, &u32PhysBits, &u32EBX, &u32ECX, &u32EDX);
    800                 u32PhysBits &= 0xff;
    801                 u64Mask = ((UINT64_C(1) << u32PhysBits) - 1) & UINT64_C(0xfffffffffffff000);
    802             }
    803 
    804             AssertCompile(sizeof(g_aLApics[iCpu].PhysBase) == sizeof(u64ApicBase));
    805             g_aLApics[iCpu].PhysBase    = u64ApicBase & u64Mask;
    806             g_aLApics[iCpu].fEnabled    = RT_BOOL(u64ApicBase & MSR_IA32_APICBASE_EN);
    807             g_aLApics[iCpu].fX2Apic     =    (u64ApicBase & (MSR_IA32_APICBASE_EXTD | MSR_IA32_APICBASE_EN))
    808                                           == (MSR_IA32_APICBASE_EXTD | MSR_IA32_APICBASE_EN);
    809         }
    810     }
    811 }
    812 
    813 
    814 
    815 /**
    816  * Per-CPU callback that verifies our APIC expectations.
    817  *
    818  * @param   idCpu       The identifier for the CPU the function is called on.
    819  * @param   pvUser1     Ignored.
    820  * @param   pvUser2     Ignored.
    821  */
    822 static DECLCALLBACK(void) cpumR0MapLocalApicCpuChecker(RTCPUID idCpu, void *pvUser1, void *pvUser2)
    823 {
    824     NOREF(pvUser1); NOREF(pvUser2);
    825 
    826     int iCpu = RTMpCpuIdToSetIndex(idCpu);
    827     AssertReturnVoid(iCpu >= 0 && (unsigned)iCpu < RT_ELEMENTS(g_aLApics));
    828     if (!g_aLApics[iCpu].fEnabled)
    829         return;
    830 
    831     /*
    832      * 0x0X       82489 external APIC
    833      * 0x1X       Local APIC
    834      * 0x2X..0xFF reserved
    835      */
    836     uint32_t uApicVersion;
    837     if (g_aLApics[iCpu].fX2Apic)
    838         uApicVersion = ApicX2RegRead32(APIC_REG_VERSION);
    839     else
    840         uApicVersion = ApicRegRead(g_aLApics[iCpu].pv, APIC_REG_VERSION);
    841     if ((APIC_REG_VERSION_GET_VER(uApicVersion) & 0xF0) == 0x10)
    842     {
    843         g_aLApics[iCpu].uVersion    = uApicVersion;
    844 
    845 # if 0 /* enable if you need it. */
    846         if (g_aLApics[iCpu].fX2Apic)
    847             SUPR0Printf("CPUM: X2APIC %02u - ver %#010x, lint0=%#07x lint1=%#07x pc=%#07x thmr=%#07x cmci=%#07x\n",
    848                         iCpu, uApicVersion,
    849                         ApicX2RegRead32(APIC_REG_LVT_LINT0), ApicX2RegRead32(APIC_REG_LVT_LINT1),
    850                         ApicX2RegRead32(APIC_REG_LVT_PC), ApicX2RegRead32(APIC_REG_LVT_THMR),
    851                         ApicX2RegRead32(APIC_REG_LVT_CMCI));
    852         else
    853         {
    854             SUPR0Printf("CPUM: APIC %02u at %RGp (mapped at %p) - ver %#010x, lint0=%#07x lint1=%#07x pc=%#07x thmr=%#07x cmci=%#07x\n",
    855                         iCpu, g_aLApics[iCpu].PhysBase, g_aLApics[iCpu].pv, uApicVersion,
    856                         ApicRegRead(g_aLApics[iCpu].pv, APIC_REG_LVT_LINT0), ApicRegRead(g_aLApics[iCpu].pv, APIC_REG_LVT_LINT1),
    857                         ApicRegRead(g_aLApics[iCpu].pv, APIC_REG_LVT_PC), ApicRegRead(g_aLApics[iCpu].pv, APIC_REG_LVT_THMR),
    858                         ApicRegRead(g_aLApics[iCpu].pv, APIC_REG_LVT_CMCI));
    859             if (uApicVersion & 0x80000000)
    860             {
    861                 uint32_t uExtFeatures = ApicRegRead(g_aLApics[iCpu].pv, 0x400);
    862                 uint32_t cEiLvt = (uExtFeatures >> 16) & 0xff;
    863                 SUPR0Printf("CPUM: APIC %02u: ExtSpace available. extfeat=%08x eilvt[0..3]=%08x %08x %08x %08x\n",
    864                             iCpu,
    865                             ApicRegRead(g_aLApics[iCpu].pv, 0x400),
    866                             cEiLvt >= 1 ? ApicRegRead(g_aLApics[iCpu].pv, 0x500) : 0,
    867                             cEiLvt >= 2 ? ApicRegRead(g_aLApics[iCpu].pv, 0x510) : 0,
    868                             cEiLvt >= 3 ? ApicRegRead(g_aLApics[iCpu].pv, 0x520) : 0,
    869                             cEiLvt >= 4 ? ApicRegRead(g_aLApics[iCpu].pv, 0x530) : 0);
    870             }
    871         }
    872 # endif
    873     }
    874     else
    875     {
    876         g_aLApics[iCpu].fEnabled = false;
    877         g_aLApics[iCpu].fX2Apic  = false;
    878         SUPR0Printf("VBox/CPUM: Unsupported APIC version %#x (iCpu=%d)\n", uApicVersion, iCpu);
    879     }
    880 }
    881 
    882 
    883 /**
    884  * Map the MMIO page of each local APIC in the system.
    885  */
    886 static int cpumR0MapLocalApics(void)
    887 {
    888     /*
    889      * Check that we'll always stay within the array bounds.
    890      */
    891     if (RTMpGetArraySize() > RT_ELEMENTS(g_aLApics))
    892     {
    893         LogRel(("CPUM: Too many real CPUs/cores/threads - %u, max %u\n", RTMpGetArraySize(), RT_ELEMENTS(g_aLApics)));
    894         return VERR_TOO_MANY_CPUS;
    895     }
    896 
    897     /*
    898      * Create mappings for all online CPUs we think have legacy APICs.
    899      */
    900     int rc = RTMpOnAll(cpumR0MapLocalApicCpuProber, NULL, NULL);
    901 
    902     for (unsigned iCpu = 0; RT_SUCCESS(rc) && iCpu < RT_ELEMENTS(g_aLApics); iCpu++)
    903     {
    904         if (g_aLApics[iCpu].fEnabled && !g_aLApics[iCpu].fX2Apic)
    905         {
    906             rc = RTR0MemObjEnterPhys(&g_aLApics[iCpu].hMemObj, g_aLApics[iCpu].PhysBase,
    907                                      HOST_PAGE_SIZE, RTMEM_CACHE_POLICY_MMIO);
    908             if (RT_SUCCESS(rc))
    909             {
    910                 rc = RTR0MemObjMapKernel(&g_aLApics[iCpu].hMapObj, g_aLApics[iCpu].hMemObj, (void *)-1,
    911                                          HOST_PAGE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
    912                 if (RT_SUCCESS(rc))
    913                 {
    914                     g_aLApics[iCpu].pv = RTR0MemObjAddress(g_aLApics[iCpu].hMapObj);
    915                     continue;
    916                 }
    917                 RTR0MemObjFree(g_aLApics[iCpu].hMemObj, true /* fFreeMappings */);
    918             }
    919             g_aLApics[iCpu].fEnabled = false;
    920         }
    921         g_aLApics[iCpu].pv = NULL;
    922     }
    923 
    924     /*
    925      * Check the APICs.
    926      */
    927     if (RT_SUCCESS(rc))
    928         rc = RTMpOnAll(cpumR0MapLocalApicCpuChecker, NULL, NULL);
    929 
    930     if (RT_FAILURE(rc))
    931     {
    932         cpumR0UnmapLocalApics();
    933         return rc;
    934     }
    935 
    936 # ifdef LOG_ENABLED
    937     /*
    938      * Log the result (pretty useless, requires enabling CPUM in VBoxDrv
    939      * and !VBOX_WITH_R0_LOGGING).
    940      */
    941     if (LogIsEnabled())
    942     {
    943         uint32_t cEnabled = 0;
    944         uint32_t cX2Apics = 0;
    945         for (unsigned iCpu = 0; iCpu < RT_ELEMENTS(g_aLApics); iCpu++)
    946             if (g_aLApics[iCpu].fEnabled)
    947             {
    948                 cEnabled++;
    949                 cX2Apics += g_aLApics[iCpu].fX2Apic;
    950             }
    951         Log(("CPUM: %u APICs, %u X2APICs\n", cEnabled, cX2Apics));
    952     }
    953 # endif
    954 
    955     return VINF_SUCCESS;
    956 }
    957 
    958 
    959 /**
    960  * Unmap the Local APIC of all host CPUs.
    961  */
    962 static void cpumR0UnmapLocalApics(void)
    963 {
    964     for (unsigned iCpu = RT_ELEMENTS(g_aLApics); iCpu-- > 0;)
    965     {
    966         if (g_aLApics[iCpu].pv)
    967         {
    968             RTR0MemObjFree(g_aLApics[iCpu].hMapObj, true /* fFreeMappings */);
    969             RTR0MemObjFree(g_aLApics[iCpu].hMemObj, true /* fFreeMappings */);
    970             g_aLApics[iCpu].hMapObj  = NIL_RTR0MEMOBJ;
    971             g_aLApics[iCpu].hMemObj  = NIL_RTR0MEMOBJ;
    972             g_aLApics[iCpu].fEnabled = false;
    973             g_aLApics[iCpu].fX2Apic  = false;
    974             g_aLApics[iCpu].pv       = NULL;
    975         }
    976     }
    977 }
    978 
    979 
    980 /**
    981  * Updates CPUMCPU::pvApicBase and CPUMCPU::fX2Apic prior to world switch.
    982  *
    983  * Writes the Local APIC mapping address of the current host CPU to CPUMCPU so
    984  * the world switchers can access the APIC registers for the purpose of
    985  * disabling and re-enabling the NMIs.  Must be called with disabled preemption
    986  * or disabled interrupts!
    987  *
    988  * @param   pVCpu       The cross context virtual CPU structure of the calling EMT.
    989  * @param   iHostCpuSet The CPU set index of the current host CPU.
    990  */
    991 VMMR0_INT_DECL(void) CPUMR0SetLApic(PVMCPUCC pVCpu, uint32_t iHostCpuSet)
    992 {
    993     Assert(iHostCpuSet <= RT_ELEMENTS(g_aLApics));
    994     pVCpu->cpum.s.pvApicBase = g_aLApics[iHostCpuSet].pv;
    995     pVCpu->cpum.s.fX2Apic    = g_aLApics[iHostCpuSet].fX2Apic;
    996 //    Log6(("CPUMR0SetLApic: pvApicBase=%p fX2Apic=%d\n", g_aLApics[idxCpu].pv, g_aLApics[idxCpu].fX2Apic));
    997 }
    998 
    999 #endif /* VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI */
    1000 
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