The current implementation of virHostCPUGetInfo for macOS (__APPLE__)
reads "hw.cpufrequency" from sysctl, which is available only on x86_64
architecture.
On Apple Silicon ARM Macs, it's not available:
$ sysctl hw.cpufrequency # No output
$ arch -x86_64 sysctl hw.cpufrequency # Run with Rosetta 2
hw.cpufrequency: 2400000000
When running libvirtd on Apple Silicon, I got the error:
cannot obtain CPU freq: No such file or directory.
To fix it, we can calculate it with "hw.tbfrequency" and
"kern.clockrate" instead:
$ sysctl hw.tbfrequency
hw.tbfrequency: 24000000
$ sysctl kern.clockrate
kern.clockrate: { hz = 100, tick = 10000, tickadj = 0, profhz = 100, stathz = 100 }
The result value would be hw.tbfrequency * kern.clockrate.hz.
Signed-off-by: Menci <huanghaorui301(a)gmail.com>
---
src/util/virhostcpu.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c
index a07c00a0e9..72983c91f3 100644
--- a/src/util/virhostcpu.c
+++ b/src/util/virhostcpu.c
@@ -927,9 +927,18 @@ virHostCPUGetInfo(virArch hostarch G_GNUC_UNUSED,
*mhz = cpu_freq;
# else
+ /* This works for Intel Macs */
if (sysctlbyname("hw.cpufrequency", &cpu_freq, &cpu_freq_len, NULL,
0) < 0) {
- virReportSystemError(errno, "%s", _("cannot obtain CPU
freq"));
- return -1;
+ /* On Apple Silicon fallback to hw.tbfrequency and kern.clockrate.hz */
+ struct clockinfo clockrate;
+ size_t clockrate_len = sizeof(clockrate);
+ if (sysctlbyname("hw.tbfrequency", &cpu_freq, &cpu_freq_len,
NULL, 0) < 0 ||
+ sysctlbyname("kern.clockrate", &clockrate, &clockrate_len,
NULL, 0) < 0) {
+ virReportSystemError(errno, "%s", _("cannot obtain CPU
freq"));
+ return -1;
+ }
+
+ cpu_freq *= clockrate.hz;
}
*mhz = cpu_freq / 1000000;
--
2.34.1