VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/darwin/RTMpGetDescription-generic.cpp@ 94091

Last change on this file since 94091 was 94091, checked in by vboxsync, 3 years ago

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

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.4 KB
Line 
1/* $Id: RTMpGetDescription-generic.cpp 94091 2022-03-04 21:28:14Z vboxsync $ */
2/** @file
3 * IPRT - Multiprocessor, RTMpGetDescription for darwin/arm.
4 */
5
6/*
7 * Copyright (C) 2009-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/mp.h>
32#include "internal/iprt.h"
33#include <iprt/err.h>
34#include <iprt/string.h>
35
36#include <sys/sysctl.h>
37#if defined(RT_ARCH_ARM64)
38# include <IOKit/IOKitLib.h>
39#endif
40
41
42RTDECL(int) RTMpGetDescription(RTCPUID idCpu, char *pszBuf, size_t cbBuf)
43{
44 /*
45 * Check that the specified cpu is valid & online.
46 */
47 if (idCpu != NIL_RTCPUID && !RTMpIsCpuOnline(idCpu))
48 return RTMpIsCpuPossible(idCpu)
49 ? VERR_CPU_OFFLINE
50 : VERR_CPU_NOT_FOUND;
51
52 /*
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 /*
145 * Just use the sysctl machdep.cpu.brand_string value for now.
146 */
147 char szBrand[128] = {0};
148 size_t cb = sizeof(szBrand);
149 int rc = sysctlbyname("machdep.cpu.brand_string", &szBrand, &cb, NULL, 0);
150 if (rc == -1)
151 szBrand[0] = '\0';
152
153 char *pszStripped = RTStrStrip(szBrand);
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;
161}
162RT_EXPORT_SYMBOL(RTMpGetDescription);
163
Note: See TracBrowser for help on using the repository browser.

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