whpx: i386: expose HV_X64_MSR_APIC_FREQUENCY when kernel-irqchip=off
Now that we expose AccessFrequencyRegs, expose HV_X64_MSR_APIC_FREQUENCY as well for the case when the Hyper-V LAPIC is not used. If the Hyper-V LAPIC is used, this will be handled by the hypervisor instead of the VMM, hence gating it on !whpx_irqchip_in_kernel(). Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr> Link: https://lore.kernel.org/r/20260228214704.19048-8-mohamed@unpredictable.fr Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Mohamed Mediouni committed
Feb 28, 2026 at 22:47 UTC
f2875e19d207de13b3308d859bb3cbb687f05d3c
1 file changed
+16
-2
target/i386/whpx/whpx-all.c
+16
-2
@@ -45,6 +45,8 @@
45
#include <winhvplatform.h>
46
47
#define HYPERV_APIC_BUS_FREQUENCY (200000000ULL)
48
+/* for kernel-irqchip=off */
49
+#define HV_X64_MSR_APIC_FREQUENCY 0x40000023
50
51
static const WHV_REGISTER_NAME whpx_register_names[] = {
52
@@ -1802,6 +1804,7 @@ int whpx_vcpu_run(CPUState *cpu)
1804
WHV_REGISTER_VALUE reg_values[3] = {0};
1805
WHV_REGISTER_NAME reg_names[3];
1806
UINT32 reg_count;
1807
+ bool is_known_msr = 0;
1808
1809
reg_names[0] = WHvX64RegisterRip;
1810
reg_names[1] = WHvX64RegisterRax;
@@ -1811,6 +1814,12 @@ int whpx_vcpu_run(CPUState *cpu)
1814
vcpu->exit_ctx.VpContext.Rip +
1815
vcpu->exit_ctx.VpContext.InstructionLength;
1816
1817
+ if (vcpu->exit_ctx.MsrAccess.MsrNumber == HV_X64_MSR_APIC_FREQUENCY
1818
+ && !vcpu->exit_ctx.MsrAccess.AccessInfo.IsWrite
1819
+ && !whpx_irqchip_in_kernel()) {
1820
+ is_known_msr = 1;
1821
+ reg_values[1].Reg32 = (uint32_t)X86_CPU(cpu)->env.apic_bus_freq;
1822
+ }
1823
/*
1824
* For all unsupported MSR access we:
1825
* ignore writes
@@ -1819,8 +1828,10 @@ int whpx_vcpu_run(CPUState *cpu)
1828
reg_count = vcpu->exit_ctx.MsrAccess.AccessInfo.IsWrite ?
1829
1 : 3;
1830
1822
- warn_report("WHPX: Unsupported MSR access (0x%x), IsWrite=%i",
1831
+ if (!is_known_msr) {
1832
+ warn_report("WHPX: Unsupported MSR access (0x%x), IsWrite=%i",
1833
vcpu->exit_ctx.MsrAccess.MsrNumber, vcpu->exit_ctx.MsrAccess.AccessInfo.IsWrite);
1834
+ }
1835
1836
hr = whp_dispatch.WHvSetVirtualProcessorRegisters(
1837
whpx->partition,
@@ -1988,6 +1999,10 @@ int whpx_init_vcpu(CPUState *cpu)
1999
}
2000
}
2001
2002
+ /* When not using the Hyper-V APIC, the frequency is 1 GHz */
2003
+ if (!whpx_irqchip_in_kernel()) {
2004
+ env->apic_bus_freq = 1000000000;
2005
+ }
2006
2007
vcpu->interruptable = true;
2008
cpu->vcpu_dirty = true;
@@ -2201,7 +2216,6 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
2216
synthetic_features.Bank0.Hv1 = 1;
2217
synthetic_features.Bank0.AccessPartitionReferenceCounter = 1;
2218
synthetic_features.Bank0.AccessPartitionReferenceTsc = 1;
2204
- /* if kernel-irqchip=off, HV_X64_MSR_APIC_FREQUENCY = 0. */
2219
synthetic_features.Bank0.AccessFrequencyRegs = 1;
2220
synthetic_features.Bank0.AccessVpIndex = 1;
2221
synthetic_features.Bank0.AccessHypercallRegs = 1;