Index | Thread | Search

From:
Stefan Fritsch <sf@sfritsch.de>
Subject:
vmm: Expose pvclock only if tsc frequency is known
To:
tech@openbsd.org
Cc:
Dave Voutila <dv@sisu.io>, Mike Larkin <mlarkin@nested.page>, Jan Klemkow <j.klemkow@wemelug.de>
Date:
Sat, 24 Jan 2026 10:59:30 +0100

Download raw body.

Thread
  • Stefan Fritsch:

    vmm: Expose pvclock only if tsc frequency is known

Hi,

Jan had some problems with a linux VM running in nested virtualization on 
opembsd/vmm which was running on linux/KVM. The VM would hang during boot. 
Not exposing both CLOCKSOURCE feature flags fixed the problem. Only 
omitting the KVM_FEATURE_CLOCKSOURCE_STABLE_BIT did not fix the issue. Not 
all linux versions showed the problem.

I think offering pvclock if the tsc frequency is not known is wrong in 
general and not only for linux guests. If the tsc frequency is unknown, 
tsc_frequency == 0 and vmm will set vc_pvclock_system_tsc_mul = 0 which 
will cause the guest's pvclock to not advance until vmm updates the struct 
pvclock_time_info on the next vmentry.

Therefore, if tsc_frequency == 0, we should not expose the pvclock feature 
bits, both in the KVM and in the VMM hypervisor signature.

We should also try to fix that the TSC frequency cannot be determined, but 
that is a different issue.

What do you think? ok?

Cheers,
Stefan

diff --git a/sys/arch/amd64/amd64/vmm_machdep.c b/sys/arch/amd64/amd64/vmm_machdep.c
index 4b86c73c8c2..7bd3fc007eb 100644
--- a/sys/arch/amd64/amd64/vmm_machdep.c
+++ b/sys/arch/amd64/amd64/vmm_machdep.c
@@ -6499,8 +6499,11 @@ vmm_handle_cpuid(struct vcpu *vcpu)
 		*rdx = *((uint32_t *)&vmm_hv_signature[8]);
 		break;
 	case 0x40000001:	/* KVM hypervisor features */
-		*rax = (1 << KVM_FEATURE_CLOCKSOURCE2) |
-		    (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT);
+		if (tsc_frequency > 0)
+			*rax = (1 << KVM_FEATURE_CLOCKSOURCE2) |
+			    (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT);
+		else
+			*rax = 0;
 		*rbx = 0;
 		*rcx = 0;
 		*rdx = 0;
@@ -6512,9 +6515,10 @@ vmm_handle_cpuid(struct vcpu *vcpu)
 		*rdx = *((uint32_t *)&kvm_hv_signature[8]);
 		break;
 	case 0x40000101:	/* KVM hypervisor features */
-		*rax = (1 << KVM_FEATURE_CLOCKSOURCE2) |
-		    (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT) |
-		    (1 << KVM_FEATURE_NOP_IO_DELAY);
+		*rax = 1 << KVM_FEATURE_NOP_IO_DELAY;
+		if (tsc_frequency > 0)
+			*rax |= (1 << KVM_FEATURE_CLOCKSOURCE2) |
+			    (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT);
 		*rbx = 0;
 		*rcx = 0;
 		*rdx = 0;