VirtualBox

Changeset 87280 in vbox for trunk/src/VBox/Runtime/r3


Ignore:
Timestamp:
Jan 15, 2021 4:29:06 PM (4 years ago)
Author:
vboxsync
Message:

IPRT/mp-darwin.cpp: get the clock-frequency from the CPU IOService if RTMpGetMaxFrequency is unable to figure out things using sysctl. bugref:9898

File:
1 edited

Legend:

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

    r87198 r87280  
    2929*   Header Files                                                                                                                 *
    3030*********************************************************************************************************************************/
    31 #define LOG_GROUP RTLOGGROUP_SYSTEM
     31#define LOG_GROUP RTLOGGROUP_DEFAULT /*RTLOGGROUP_SYSTEM*/
    3232#include <iprt/types.h>
    3333
     
    4040#include <mach/mach.h>
    4141
     42#include <CoreFoundation/CFBase.h>
     43#include <IOKit/IOKitLib.h>
     44/*#include <IOKit/IOBSD.h>
     45#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
     46#include <IOKit/storage/IOBlockStorageDevice.h>
     47#include <IOKit/storage/IOMedia.h>
     48#include <IOKit/storage/IOCDMedia.h>
     49#include <IOKit/scsi/SCSITaskLib.h>
     50#include <SystemConfiguration/SystemConfiguration.h>
     51#include <mach/mach_error.h>
     52#include <sys/param.h>
     53#include <paths.h>*/
     54
    4255#include <iprt/mp.h>
    4356#include <iprt/cpuset.h>
    4457#include <iprt/assert.h>
     58#include <iprt/log.h>
    4559#include <iprt/string.h>
    4660
     
    246260
    247261
     262/**
     263 * Worker for RTMpGetMaxFrequency.
     264 * @returns Non-zero frequency in MHz on success, 0 on failure.
     265 */
     266static uint32_t rtMpDarwinGetMaxFrequencyFromIOService(io_service_t hCpu)
     267{
     268    io_struct_inband_t  Buf = {0};
     269    uint32_t            cbActual = sizeof(Buf);
     270    kern_return_t krc = IORegistryEntryGetProperty(hCpu, "clock-frequency", Buf, &cbActual);
     271    Log2(("rtMpDarwinGetMaxFrequencyFromIOService: krc=%d; cbActual=%#x %.16Rhxs\n", krc, cbActual, Buf));
     272    if (krc == kIOReturnSuccess)
     273    {
     274        switch (cbActual)
     275        {
     276            case sizeof(uint32_t):
     277                return RT_BE2H_U32(*(uint32_t *)Buf) / 1000;
     278            case sizeof(uint64_t):
     279                AssertFailed();
     280                return RT_BE2H_U64(*(uint64_t *)Buf) / 1000;
     281            default:
     282                AssertFailed();
     283        }
     284    }
     285    return 0;
     286}
     287
     288
    248289RTDECL(uint32_t) RTMpGetMaxFrequency(RTCPUID idCpu)
    249290{
     
    271312    if (rc != -1 && cCpus >= 1)
    272313        return cCpus;
     314
     315    /*
     316     * The above does not work for Apple M1 / xnu 20.1.0, so go look at the I/O registry instead.
     317     *
     318     * A sample ARM layout:
     319     *  | +-o cpu1@1  <class IOPlatformDevice, id 0x100000110, registered, matched, active, busy 0 (182 ms), retain 8>
     320     *  | | +-o AppleARMCPU  <class AppleARMCPU, id 0x10000021b, registered, matched, active, busy 0 (1 ms), retain 6>
     321     *  | +-o cpu2@2  <class IOPlatformDevice, id 0x100000111, registered, matched, active, busy 0 (175 ms), retain 8>
     322     *  | | +-o AppleARMCPU  <class AppleARMCPU, id 0x10000021c, registered, matched, active, busy 0 (3 ms), retain 6>
     323     *  | +-o cpu3@3  <class IOPlatformDevice, id 0x100000112, registered, matched, active, busy 0 (171 ms), retain 8>
     324     *  | | +-o AppleARMCPU  <class AppleARMCPU, id 0x10000021d, registered, matched, active, busy 0 (1 ms), retain 6>
     325     *  | +-o cpu4@100  <class IOPlatformDevice, id 0x100000113, registered, matched, active, busy 0 (171 ms), retain 8>
     326     *  | | +-o AppleARMCPU  <class AppleARMCPU, id 0x10000021e, registered, matched, active, busy 0 (1 ms), retain 6>
     327     *  | +-o cpu5@101  <class IOPlatformDevice, id 0x100000114, registered, matched, active, busy 0 (179 ms), retain 8>
     328     *  | | +-o AppleARMCPU  <class AppleARMCPU, id 0x10000021f, registered, matched, active, busy 0 (9 ms), retain 6>
     329     *  | +-o cpu6@102  <class IOPlatformDevice, id 0x100000115, registered, matched, active, busy 0 (172 ms), retain 8>
     330     *  | | +-o AppleARMCPU  <class AppleARMCPU, id 0x100000220, registered, matched, active, busy 0 (1 ms), retain 6>
     331     *  | +-o cpu7@103  <class IOPlatformDevice, id 0x100000116, registered, matched, active, busy 0 (175 ms), retain 8>
     332     *  | | +-o AppleARMCPU  <class AppleARMCPU, id 0x100000221, registered, matched, active, busy 0 (5 ms), retain 6>
     333     *  | +-o cpus  <class IOPlatformDevice, id 0x10000010e, registered, matched, active, busy 0 (12 ms), retain 15>
     334     *
     335     */
     336
     337    /* Assume names on the form "cpu<N>" are only for CPUs. */
     338    char szCpuName[32];
     339    RTStrPrintf(szCpuName, sizeof(szCpuName), "cpu%u", idCpu);
     340    CFMutableDictionaryRef hMatchingDict = IOServiceNameMatching(szCpuName);
     341    AssertReturn(hMatchingDict, 0);
     342
     343    /* Just get the first one. */
     344    io_object_t hCpu = IOServiceGetMatchingService(kIOMasterPortDefault, hMatchingDict);
     345    if (hCpu != 0)
     346    {
     347        uint32_t uCpuFrequency = rtMpDarwinGetMaxFrequencyFromIOService(hCpu);
     348        IOObjectRelease(hCpu);
     349        if (uCpuFrequency)
     350            return uCpuFrequency;
     351    }
     352
     353#if 1 /* Just in case... */
     354    /* Create a matching dictionary for searching for CPU services in the IOKit. */
     355# if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
     356    hMatchingDict = IOServiceMatching("AppleARMCPU");
     357# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     358    hMatchingDict = IOServiceMatching("AppleACPICPU");
     359# else
     360#  error "Port me!"
     361# endif
     362    AssertReturn(hMatchingDict, 0);
     363
     364    /* Perform the search and get a collection of Apple CPU services. */
     365    io_iterator_t hCpuServices = IO_OBJECT_NULL;
     366    IOReturn irc = IOServiceGetMatchingServices(kIOMasterPortDefault, hMatchingDict, &hCpuServices);
     367    AssertMsgReturn(irc == kIOReturnSuccess, ("irc=%d\n", irc), 0);
     368    hMatchingDict = NULL; /* the reference is consumed by IOServiceGetMatchingServices. */
     369
     370    /* Enumerate the matching services. */
     371    uint32_t    uCpuFrequency = 0;
     372    io_object_t hCurCpu;
     373    while (uCpuFrequency == 0 && (hCurCpu = IOIteratorNext(hCpuServices)) != IO_OBJECT_NULL)
     374    {
     375        io_object_t hParent = (io_object_t)0;
     376        irc = IORegistryEntryGetParentEntry(hCurCpu, kIOServicePlane, &hParent);
     377        if (irc == kIOReturnSuccess && hParent)
     378        {
     379            uCpuFrequency = rtMpDarwinGetMaxFrequencyFromIOService(hParent);
     380            IOObjectRelease(hParent);
     381        }
     382        IOObjectRelease(hCurCpu);
     383    }
     384    IOObjectRelease(hCpuServices);
     385#endif
     386
    273387    AssertFailed();
    274388    return 0;
    275389}
     390
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