@@ -80,6 +80,7 @@
GlobalProperty pc_compat_9_0[] = {
{ TYPE_X86_CPU, "guest-phys-bits", "0" },
+ { TYPE_X86_CPU, "legacy-kvmclock", "true" },
};
const size_t pc_compat_9_0_len = G_N_ELEMENTS(pc_compat_9_0);
@@ -7941,6 +7941,7 @@ static Property x86_cpu_properties[] = {
*/
DEFINE_PROP_BOOL("legacy-cache", X86CPU, legacy_cache, true),
DEFINE_PROP_BOOL("xen-vapic", X86CPU, xen_vapic, false),
+ DEFINE_PROP_BOOL("legacy-kvmclock", X86CPU, legacy_kvmclock, false),
/*
* From "Requirements for Implementing the Microsoft
@@ -2070,6 +2070,13 @@ struct ArchCPU {
int32_t hv_max_vps;
bool xen_vapic;
+
+ /*
+ * Compatibility bits for old machine types.
+ * If true, always set/unset KVM_FEATURE_CLOCKSOURCE and
+ * KVM_FEATURE_CLOCKSOURCE2 at the same time.
+ */
+ bool legacy_kvmclock;
};
typedef struct X86CPUModel X86CPUModel;
@@ -18,6 +18,8 @@
#include "kvm_i386.h"
#include "hw/core/accel-cpu.h"
+#include "standard-headers/asm-x86/kvm_para.h"
+
static void kvm_set_guest_phys_bits(CPUState *cs)
{
X86CPU *cpu = X86_CPU(cs);
@@ -72,6 +74,23 @@ static bool kvm_cpu_realizefn(CPUState *cs, Error **errp)
MSR_IA32_UCODE_REV);
}
}
+
+ if (cpu->legacy_kvmclock) {
+ /*
+ * The old and new kvmclock are both set by default from the
+ * oldest KVM supported (v4.5, see "OS requirements" section at
+ * docs/system/target-i386.rst). So when one of them is missing,
+ * it is only possible that the user is actively masking it.
+ * Then, mask both at the same time for compatibility with v9.0
+ * and older QEMU's kvmclock behavior.
+ */
+ if (!(env->features[FEAT_KVM] & CPUID_FEAT_KVM_CLOCK) ||
+ !(env->features[FEAT_KVM] & CPUID_FEAT_KVM_CLOCK2)) {
+ env->features[FEAT_KVM] &= ~(CPUID_FEAT_KVM_CLOCK |
+ CPUID_FEAT_KVM_CLOCK2);
+ }
+ }
+
ret = host_cpu_realizefn(cs, errp);
if (!ret) {
return ret;