On Apple M3 and later, the timer frequency within apps and VM guests are different from each other.
Note that app binaries compiled with older SDKs continue to retain a non-1 GHz timer frequency on Apple M3/M4.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
target/arm/hvf/hvf.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index c9cfcdc08b..4331a3386a 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -1018,6 +1018,13 @@ int hvf_arch_init_vcpu(CPUState *cpu)
int i;
env->aarch64 = true;
+ /*
+ * TODO: This does not correspond to the exposed generic
+ * timer frequency to the guest on Apple M3/M4.
+ * This is due to a scaled 1GHz counter being exposed
+ * to applications built with newer SDKs when running
+ * on that silicon, while VMs get an unscaled counter.
+ */
asm volatile("mrs %0, cntfrq_el0" : "=r"(arm_cpu->gt_cntfrq_hz));
/* Allocate enough space for our sysreg sync */
--
2.39.5 (Apple Git-154)
Hi Mohamed,
On 21/7/25 17:29, Mohamed Mediouni wrote:
> On Apple M3 and later, the timer frequency within apps and VM guests are different from each other.
Also M1/M2, so all Apple Silicon chipsets IMO.
This might be the issue I fixed here:
https://lore.kernel.org/qemu-devel/20250620130709.31073-18-philmd@linaro.org/
>
> Note that app binaries compiled with older SDKs continue to retain a non-1 GHz timer frequency on Apple M3/M4.
>
> Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
> ---
> target/arm/hvf/hvf.c | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
> index c9cfcdc08b..4331a3386a 100644
> --- a/target/arm/hvf/hvf.c
> +++ b/target/arm/hvf/hvf.c
> @@ -1018,6 +1018,13 @@ int hvf_arch_init_vcpu(CPUState *cpu)
> int i;
>
> env->aarch64 = true;
> + /*
> + * TODO: This does not correspond to the exposed generic
> + * timer frequency to the guest on Apple M3/M4.
> + * This is due to a scaled 1GHz counter being exposed
> + * to applications built with newer SDKs when running
> + * on that silicon, while VMs get an unscaled counter.
> + */
> asm volatile("mrs %0, cntfrq_el0" : "=r"(arm_cpu->gt_cntfrq_hz));
Hello,
Nevermind.
It turns out that… the timer frequency exposed is different depending on the entitlements the program has...
With this tiny test sequence:
diff --git a/accel/hvf/hvf-all.c b/accel/hvf/hvf-all.c
index e67a8105a6..390afb03a4 100644
--- a/accel/hvf/hvf-all.c
+++ b/accel/hvf/hvf-all.c
@@ -262,7 +262,9 @@ static int hvf_accel_init(AccelState *as, MachineState *ms)
return -EINVAL;
}
}
-
+ uint64_t frq;
+ asm volatile("mrs %0, cntfrq_el0" : "=r"(frq));
+ printf("Timer frequency before hvf_arch_vm_create: %" PRIu64 "\n", frq);
ret = hvf_arch_vm_create(ms, (uint32_t)pa_range);
if (ret == HV_DENIED) {
error_report("Could not access HVF. Is the executable signed"
It turns out that:
% ./qemu-system-aarch64-unsigned -M virt,accel=hvf,gic-version=3,nested=on,its=off […]
Timer frequency before hvf_arch_vm_create: 1000000000
qemu-system-aarch64-unsigned: Could not access HVF. Is the executable signed with com.apple.security.hypervisor entitlement?
% ./qemu-system-aarch64-unsigned -M virt,accel=hvf,gic-version=3,nested=on,its=off […]
Timer frequency before hvf_arch_vm_create: 24000000
[…]
Sigh.
> On 22. Jul 2025, at 07:52, Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>
> Hi Mohamed,
>
> On 21/7/25 17:29, Mohamed Mediouni wrote:
>> On Apple M3 and later, the timer frequency within apps and VM guests are different from each other.
>
> Also M1/M2, so all Apple Silicon chipsets IMO.
>
> This might be the issue I fixed here:
> https://lore.kernel.org/qemu-devel/20250620130709.31073-18-philmd@linaro.org/
>
>> Note that app binaries compiled with older SDKs continue to retain a non-1 GHz timer frequency on Apple M3/M4.
>> Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
>> ---
>> target/arm/hvf/hvf.c | 7 +++++++
>> 1 file changed, 7 insertions(+)
>> diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
>> index c9cfcdc08b..4331a3386a 100644
>> --- a/target/arm/hvf/hvf.c
>> +++ b/target/arm/hvf/hvf.c
>> @@ -1018,6 +1018,13 @@ int hvf_arch_init_vcpu(CPUState *cpu)
>> int i;
>> env->aarch64 = true;
>> + /*
>> + * TODO: This does not correspond to the exposed generic
>> + * timer frequency to the guest on Apple M3/M4.
>> + * This is due to a scaled 1GHz counter being exposed
>> + * to applications built with newer SDKs when running
>> + * on that silicon, while VMs get an unscaled counter.
>> + */
>> asm volatile("mrs %0, cntfrq_el0" : "=r"(arm_cpu->gt_cntfrq_hz));
>
>
© 2016 - 2025 Red Hat, Inc.