VirtualBox

Changeset 94091 in vbox for trunk


Ignore:
Timestamp:
Mar 4, 2022 9:28:14 PM (3 years ago)
Author:
vboxsync
Message:

IPRT: Better RTMpGetDescription for darwin.arm (first M1 has two clusters of 4 cores with different energy characteristics and names). bugref:9898

Location:
trunk/src/VBox/Runtime
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/darwin/RTMpGetDescription-generic.cpp

    r94087 r94091  
    3535
    3636#include <sys/sysctl.h>
     37#if defined(RT_ARCH_ARM64)
     38# include <IOKit/IOKitLib.h>
     39#endif
    3740
    3841
     
    4851
    4952    /*
     53     * For ARM there are typically two different types of cores, so look up the
     54     * processor in the IODeviceTree and get the core name and type from there
     55     * if we can.
     56     */
     57    char   szExtra[256];
     58    size_t cchExtra = 0;
     59
     60#if defined(RT_ARCH_ARM64)
     61    char szArmCpuPath[64];
     62    RTStrPrintf(szArmCpuPath, sizeof(szArmCpuPath), "IODeviceTree:/cpus/cpu%u", idCpu);
     63    io_registry_entry_t hIoRegEntry = IORegistryEntryFromPath(kIOMasterPortDefault, szArmCpuPath);
     64    if (hIoRegEntry != MACH_PORT_NULL)
     65    {
     66        /* This property is typically "E" or "P".  Don't know why it's mapped
     67           to a CFDataRef rather than a CFStringRef... */
     68        CFTypeRef hValRef = IORegistryEntryCreateCFProperty(hIoRegEntry, CFSTR("cluster-type"), kCFAllocatorDefault, kNilOptions);
     69        if (hValRef)
     70        {
     71            if (CFGetTypeID(hValRef) == CFDataGetTypeID())
     72            {
     73                size_t const          cbData = CFDataGetLength((CFDataRef)hValRef);
     74                uint8_t const * const pbData = (uint8_t const *)CFDataGetBytePtr((CFDataRef)hValRef);
     75                if (cbData > 0 && pbData != NULL)
     76                {
     77                    int rc = RTStrValidateEncodingEx((const char *)pbData, cbData, RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
     78                    AssertMsgRC(rc, ("%p LB %#zx: %.*Rhxs\n", pbData, cbData, cbData, pbData));
     79                    if (RT_SUCCESS(rc))
     80                    {
     81                        RTStrCopy(&szExtra[1], sizeof(szExtra) - 1, (const char *)pbData);
     82                        szExtra[0] = ' ';
     83                        cchExtra = strlen(szExtra);
     84                    }
     85                }
     86            }
     87            else
     88                AssertMsgFailed(("%p=%#lx\n", hValRef, CFGetTypeID(hValRef)));
     89
     90            CFRelease(hValRef);
     91        }
     92
     93        /* The compatible property is an "array" of zero terminated strings.
     94           For the M1 mini the first entry is either "apple,firestorm" (P cores)
     95           or "apple,icestorm" (E cores).  We extract the bits after the comma
     96           and append it to the extra string. (Again, dunno why it's a CFDataRef.) */
     97        hValRef = IORegistryEntryCreateCFProperty(hIoRegEntry, CFSTR("compatible"), kCFAllocatorDefault, 0);
     98        if (hValRef)
     99        {
     100            if (CFGetTypeID(hValRef) == CFDataGetTypeID())
     101            {
     102                size_t const          cbData = CFDataGetLength((CFDataRef)hValRef);
     103                uint8_t const * const pbData = (uint8_t const *)CFDataGetBytePtr((CFDataRef)hValRef);
     104                if (cbData > 0 && pbData != NULL)
     105                {
     106                    Assert(pbData[cbData - 1] == '\0');
     107                    if (pbData[cbData - 1] == '\0')
     108                    {
     109                        size_t offData = 0;
     110                        while (offData < cbData)
     111                        {
     112                            const char  *psz = (const char *)&pbData[offData];
     113                            size_t const cch = strlen(psz);
     114
     115                            if (RTStrStartsWith(psz, "apple,"))
     116                            {
     117                                psz += sizeof("apple,") - 1;
     118                                psz = RTStrStripL(psz);
     119                                if (*psz)
     120                                {
     121                                    if (RTStrIsValidEncoding(psz))
     122                                        cchExtra += RTStrPrintf(&szExtra[cchExtra], sizeof(szExtra) - cchExtra, " (%s)", psz);
     123                                    else
     124                                        AssertFailed();
     125                                }
     126                            }
     127
     128                            /* advance */
     129                            offData += cch + 1;
     130                        }
     131                    }
     132                }
     133            }
     134            else
     135                AssertMsgFailed(("%p=%#lx\n", hValRef, CFGetTypeID(hValRef)));
     136            CFRelease(hValRef);
     137        }
     138
     139        IOObjectRelease(hIoRegEntry);
     140    }
     141#endif
     142    szExtra[cchExtra] = '\0';
     143
     144    /*
    50145     * Just use the sysctl machdep.cpu.brand_string value for now.
    51146     */
    52     /** @todo on arm this is very boring and there are two different types of
    53      *        cores in the system, "E" and "P" cores. The I/O registry can
    54      *        be used to find out which @a idCpu is.  There are also codename
    55      *        available there. */
    56147    char szBrand[128] = {0};
    57148    size_t cb = sizeof(szBrand);
     
    61152
    62153    char *pszStripped = RTStrStrip(szBrand);
    63     if (*pszStripped)
    64         return RTStrCopy(pszBuf, cbBuf, pszStripped);
    65     return RTStrCopy(pszBuf, cbBuf, "Unknown");
     154    if (*pszStripped == '\0')
     155        pszStripped = strcpy(szBrand, "Unknown");
     156
     157    rc = RTStrCopy(pszBuf, cbBuf, pszStripped);
     158    if (cchExtra > 0 && RT_SUCCESS(rc))
     159        rc = RTStrCat(pszBuf, cbBuf, szExtra);
     160    return rc;
    66161}
    67162RT_EXPORT_SYMBOL(RTMpGetDescription);
  • trunk/src/VBox/Runtime/testcase/tstRTMp-1.cpp

    r93115 r94091  
    219219        RTTestIFailed("RTMpGetPresentSet -> %p, expected %p\n", pSet, &Set);
    220220
    221 
    222     /* Find an online cpu for the next test. */
     221    /*
     222     * Quick test of RTMpGetDescription on the first and last online CPUs.
     223     */
    223224    RTCPUID idCpuOnline;
    224225    for (idCpuOnline = 0; idCpuOnline < RTCPUSET_MAX_CPUS; idCpuOnline++)
    225226        if (RTMpIsCpuOnline(idCpuOnline))
    226227            break;
    227 
    228     /*
    229      * Quick test of RTMpGetDescription.
    230      */
    231     char szBuf[64];
    232     int rc = RTMpGetDescription(idCpuOnline, &szBuf[0], sizeof(szBuf));
    233     if (RT_SUCCESS(rc))
    234     {
    235         RTTestIPrintf(RTTESTLVL_ALWAYS, "RTMpGetDescription -> '%s'\n", szBuf);
    236 
    237         size_t cch = strlen(szBuf);
    238         rc = RTMpGetDescription(idCpuOnline, &szBuf[0], cch);
    239         if (rc != VERR_BUFFER_OVERFLOW)
    240             RTTestIFailed("RTMpGetDescription -> %Rrc, expected VERR_BUFFER_OVERFLOW\n", rc);
    241 
    242         rc = RTMpGetDescription(idCpuOnline, &szBuf[0], cch + 1);
    243         if (RT_FAILURE(rc))
    244             RTTestIFailed("RTMpGetDescription -> %Rrc, expected VINF_SUCCESS\n", rc);
    245     }
    246     else
    247         RTTestIFailed("RTMpGetDescription -> %Rrc\n", rc);
     228    RTCPUID aidCpuIds[2] = { idCpuOnline, idCpuOnline };
     229    for (idCpuOnline++; idCpuOnline < RTCPUSET_MAX_CPUS; idCpuOnline++)
     230        if (RTMpIsCpuOnline(idCpuOnline))
     231            aidCpuIds[1] = idCpuOnline;
     232    for (size_t i = 0; i < RT_ELEMENTS(aidCpuIds); i++)
     233    {
     234        idCpuOnline = aidCpuIds[i];
     235        char szBuf[64];
     236        int rc = RTMpGetDescription(idCpuOnline, &szBuf[0], sizeof(szBuf));
     237        if (RT_SUCCESS(rc))
     238        {
     239            RTTestIPrintf(RTTESTLVL_ALWAYS, "RTMpGetDescription(%d,,) -> '%s'\n", idCpuOnline, szBuf);
     240
     241            size_t cch = strlen(szBuf);
     242            rc = RTMpGetDescription(idCpuOnline, &szBuf[0], cch);
     243            if (rc != VERR_BUFFER_OVERFLOW)
     244                RTTestIFailed("RTMpGetDescription(%d,,) -> %Rrc, expected VERR_BUFFER_OVERFLOW\n", idCpuOnline, rc);
     245
     246            rc = RTMpGetDescription(idCpuOnline, &szBuf[0], cch + 1);
     247            if (RT_FAILURE(rc))
     248                RTTestIFailed("RTMpGetDescription(%d,,) -> %Rrc, expected VINF_SUCCESS\n", idCpuOnline, rc);
     249        }
     250        else
     251            RTTestIFailed("RTMpGetDescription(%d,,) -> %Rrc\n", idCpuOnline, rc);
     252    }
     253
     254    /* */
    248255
    249256    return RTTestSummaryAndDestroy(hTest);
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