target/arm/cpu: Add the kvm-no-adjvtime CPU property

kvm-no-adjvtime is a KVM specific CPU property and a first of its
kind. To accommodate it we also add kvm_arm_add_vcpu_properties()
and a KVM specific CPU properties description to the CPU features
document.

Signed-off-by: Andrew Jones <drjones@redhat.com>
Message-id: 20200120101023.16030-7-drjones@redhat.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Andrew Jones 2020-01-30 16:02:06 +00:00 committed by Peter Maydell
parent e5ac4200b4
commit dea101a1ae
9 changed files with 92 additions and 1 deletions

View File

@ -31,7 +31,9 @@ supporting the feature or only supporting the feature under certain
configurations. For example, the `aarch64` CPU feature, which, when
disabled, enables the optional AArch32 CPU feature, is only supported
when using the KVM accelerator and when running on a host CPU type that
supports the feature.
supports the feature. While `aarch64` currently only works with KVM,
it could work with TCG. CPU features that are specific to KVM are
prefixed with "kvm-" and are described in "KVM VCPU Features".
CPU Feature Probing
===================
@ -171,6 +173,39 @@ disabling many SVE vector lengths would be quite verbose, the `sve<N>` CPU
properties have special semantics (see "SVE CPU Property Parsing
Semantics").
KVM VCPU Features
=================
KVM VCPU features are CPU features that are specific to KVM, such as
paravirt features or features that enable CPU virtualization extensions.
The features' CPU properties are only available when KVM is enabled and
are named with the prefix "kvm-". KVM VCPU features may be probed,
enabled, and disabled in the same way as other CPU features. Below is
the list of KVM VCPU features and their descriptions.
kvm-no-adjvtime By default kvm-no-adjvtime is disabled. This
means that by default the virtual time
adjustment is enabled (vtime is *not not*
adjusted).
When virtual time adjustment is enabled each
time the VM transitions back to running state
the VCPU's virtual counter is updated to ensure
stopped time is not counted. This avoids time
jumps surprising guest OSes and applications,
as long as they use the virtual counter for
timekeeping. However it has the side effect of
the virtual and physical counters diverging.
All timekeeping based on the virtual counter
will appear to lag behind any timekeeping that
does not subtract VM stopped time. The guest
may resynchronize its virtual counter with
other time sources as needed.
Enable kvm-no-adjvtime to disable virtual time
adjustment, also restoring the legacy (pre-5.0)
behavior.
SVE CPU Properties
==================

View File

@ -1663,6 +1663,11 @@ static void machvirt_init(MachineState *machine)
}
}
if (vmc->kvm_no_adjvtime &&
object_property_find(cpuobj, "kvm-no-adjvtime", NULL)) {
object_property_set_bool(cpuobj, true, "kvm-no-adjvtime", NULL);
}
if (vmc->no_pmu && object_property_find(cpuobj, "pmu", NULL)) {
object_property_set_bool(cpuobj, false, "pmu", NULL);
}
@ -2153,8 +2158,11 @@ DEFINE_VIRT_MACHINE_AS_LATEST(5, 0)
static void virt_machine_4_2_options(MachineClass *mc)
{
VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
virt_machine_5_0_options(mc);
compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len);
vmc->kvm_no_adjvtime = true;
}
DEFINE_VIRT_MACHINE(4, 2)

View File

@ -109,6 +109,7 @@ typedef struct {
bool smbios_old_sys_ver;
bool no_highmem_ecam;
bool no_ged; /* Machines < 4.2 has no support for ACPI GED device */
bool kvm_no_adjvtime;
} VirtMachineClass;
typedef struct {

View File

@ -2551,6 +2551,7 @@ static void arm_max_initfn(Object *obj)
if (kvm_enabled()) {
kvm_arm_set_cpu_features_from_host(cpu);
kvm_arm_add_vcpu_properties(obj);
} else {
cortex_a15_initfn(obj);
@ -2743,6 +2744,7 @@ static void arm_host_initfn(Object *obj)
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
aarch64_add_sve_properties(obj);
}
kvm_arm_add_vcpu_properties(obj);
arm_cpu_post_init(obj);
}

View File

@ -605,6 +605,7 @@ static void aarch64_max_initfn(Object *obj)
if (kvm_enabled()) {
kvm_arm_set_cpu_features_from_host(cpu);
kvm_arm_add_vcpu_properties(obj);
} else {
uint64_t t;
uint32_t u;

View File

@ -17,6 +17,8 @@
#include "qemu/timer.h"
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
#include "qom/object.h"
#include "qapi/error.h"
#include "sysemu/sysemu.h"
#include "sysemu/kvm.h"
#include "sysemu/kvm_int.h"
@ -179,6 +181,32 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
env->features = arm_host_cpu_features.features;
}
static bool kvm_no_adjvtime_get(Object *obj, Error **errp)
{
return !ARM_CPU(obj)->kvm_adjvtime;
}
static void kvm_no_adjvtime_set(Object *obj, bool value, Error **errp)
{
ARM_CPU(obj)->kvm_adjvtime = !value;
}
/* KVM VCPU properties should be prefixed with "kvm-". */
void kvm_arm_add_vcpu_properties(Object *obj)
{
if (!kvm_enabled()) {
return;
}
ARM_CPU(obj)->kvm_adjvtime = true;
object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get,
kvm_no_adjvtime_set, &error_abort);
object_property_set_description(obj, "kvm-no-adjvtime",
"Set on to disable the adjustment of "
"the virtual counter. VM stopped time "
"will be counted.", &error_abort);
}
bool kvm_arm_pmu_supported(CPUState *cpu)
{
return kvm_check_extension(cpu->kvm_state, KVM_CAP_ARM_PMU_V3);

View File

@ -255,6 +255,15 @@ void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map);
*/
void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
/**
* kvm_arm_add_vcpu_properties:
* @obj: The CPU object to add the properties to
*
* Add all KVM specific CPU properties to the CPU object. These
* are the CPU properties with "kvm-" prefixed names.
*/
void kvm_arm_add_vcpu_properties(Object *obj);
/**
* kvm_arm_aarch32_supported:
* @cs: CPUState
@ -345,6 +354,8 @@ static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
cpu->host_cpu_probe_failed = true;
}
static inline void kvm_arm_add_vcpu_properties(Object *obj) {}
static inline bool kvm_arm_aarch32_supported(CPUState *cs)
{
return false;

View File

@ -103,6 +103,7 @@ static const char *cpu_model_advertised_features[] = {
"sve128", "sve256", "sve384", "sve512",
"sve640", "sve768", "sve896", "sve1024", "sve1152", "sve1280",
"sve1408", "sve1536", "sve1664", "sve1792", "sve1920", "sve2048",
"kvm-no-adjvtime",
NULL
};

View File

@ -428,6 +428,8 @@ static void test_query_cpu_model_expansion(const void *data)
assert_has_feature_enabled(qts, "cortex-a15", "pmu");
assert_has_not_feature(qts, "cortex-a15", "aarch64");
assert_has_not_feature(qts, "max", "kvm-no-adjvtime");
if (g_str_equal(qtest_get_arch(), "aarch64")) {
assert_has_feature_enabled(qts, "max", "aarch64");
assert_has_feature_enabled(qts, "max", "sve");
@ -462,6 +464,8 @@ static void test_query_cpu_model_expansion_kvm(const void *data)
return;
}
assert_has_feature_disabled(qts, "host", "kvm-no-adjvtime");
if (g_str_equal(qtest_get_arch(), "aarch64")) {
bool kvm_supports_sve;
char max_name[8], name[8];