* [RFC PATCH v3 0/6] target/arm/kvm: Adjust virtual time
@ 2020-01-20 10:10 Andrew Jones
2020-01-20 10:10 ` [RFC PATCH v3 1/6] target/arm/kvm: trivial: Clean up header documentation Andrew Jones
` (7 more replies)
0 siblings, 8 replies; 10+ messages in thread
From: Andrew Jones @ 2020-01-20 10:10 UTC (permalink / raw)
To: qemu-devel, qemu-arm
Cc: peter.maydell, bijan.mottahedeh, maz, richard.henderson, guoheyi,
msys.mizuma
v3:
- Added a target/arm/kvm_arm.h comment cleanup patch (1/6)
- Minor refactoring of assert_has_feature_enabled/disabled in 4/6,
kept Richard's r-b.
- Rewrote kvm-no-adjvtime documentation in 6/6.
- Reworked approach in 5/6 to properly deal with migration and to
track running vs. !running, rather than running vs. paused states.
v2:
- Reworked it enough that I brought back the RFC tag and retitled the
series. Also had to drop r-b's from a couple of patches, and even
drop patches.
- Changed approach from writing the QEMU virtual time to the guest
vtime counter to saving and restoring the guest vtime counter.
- Changed the kvm-adjvtime property, which was off by default, to a
kvm-no-adjvtime property, which is also off by default, meaning the
effective "adjust vtime" property is now on by default (but only
for 5.0 virt machine types and later)
v1:
- move from RFC status to v1
- put kvm_arm_vm_state_change() in kvm.c to share among kvm32.c and kvm64.c
- add r-b's from Richard
This series is inspired by a series[1] posted by Bijan Mottahedeh over
a year ago and by the patch[2] posted by Heyi Guo almost a year ago.
The problem described in the cover letter of [1] is easily reproducible
and some users would like to have the option to avoid it. However the
solution, which is to adjust the virtual counter each time the VM
transitions to the running state, introduces a different problem, which
is that the virtual and physical counters diverge. As described in the
cover letter of [1] this divergence is easily observed when comparing
the output of `date` and `hwclock` after suspending the guest, waiting
a while, and then resuming it. Because this different problem may actually
be worse for some users, unlike [1], the series posted here makes the
virtual counter adjustment optional. Besides the adjustment being
optional, this series approaches the needed changes differently to apply
them in more appropriate locations.
Additional notes
----------------
Note 1
------
As described above, when running a guest with kvm-no-adjtime disabled
it will be less likely the guest OS and guest applications get surprise
time jumps when they use the virtual counter. However the counter will
no longer reflect real time. It will lag behind. If this is a problem
then the guest can resynchronize its time from an external source or
even from its physical counter. If the suspend/resume is done with
libvirt's virsh, and the guest is running the guest agent, then it's
also possible to use a sequence like this
$ virsh suspend $GUEST
$ virsh resume $GUEST
$ virsh domtime --sync $GUEST
in order to resynchronize a guest right after the resume. Of course
there will still be time when the clock is not right, possibly creating
confusing timestamps in logs, for example, and the guest must still be
tolerant to the time synchronizations.
Note 2
------
Userspace that wants to set KVM_REG_ARM_TIMER_CNT should beware that
the KVM register ID is not correct. This cannot be fixed because it's
UAPI and if the UAPI headers are used then it can't be a problem.
However, if a userspace attempts to create the ID themselves from the
register's specification, then they will get KVM_REG_ARM_TIMER_CVAL
instead, as the _CNT and _CVAL definitions have their register
parameters swapped.
Note 3
------
I didn't test this with a 32-bit KVM host, but the changes to kvm32.c
are the same as kvm64.c. So what could go wrong? Test results would be
appreciated.
[1] https://lists.gnu.org/archive/html/qemu-devel/2018-11/msg05713.html
[2] https://lists.gnu.org/archive/html/qemu-devel/2019-03/msg03695.html
Thanks,
drew
Andrew Jones (6):
target/arm/kvm: trivial: Clean up header documentation
hw/arm/virt: Add missing 5.0 options call to 4.2 options
target/arm/kvm64: kvm64 cpus have timer registers
tests/arm-cpu-features: Check feature default values
target/arm/kvm: Implement virtual time adjustment
target/arm/cpu: Add the kvm-no-adjvtime CPU property
docs/arm-cpu-features.rst | 37 +++++++++-
hw/arm/virt.c | 9 +++
include/hw/arm/virt.h | 1 +
target/arm/cpu.c | 2 +
target/arm/cpu.h | 7 ++
target/arm/cpu64.c | 1 +
target/arm/kvm.c | 120 +++++++++++++++++++++++++++++++++
target/arm/kvm32.c | 3 +
target/arm/kvm64.c | 4 ++
target/arm/kvm_arm.h | 95 ++++++++++++++++++++------
target/arm/machine.c | 7 ++
target/arm/monitor.c | 1 +
tests/qtest/arm-cpu-features.c | 41 ++++++++---
13 files changed, 299 insertions(+), 29 deletions(-)
--
2.21.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC PATCH v3 1/6] target/arm/kvm: trivial: Clean up header documentation
2020-01-20 10:10 [RFC PATCH v3 0/6] target/arm/kvm: Adjust virtual time Andrew Jones
@ 2020-01-20 10:10 ` Andrew Jones
2020-01-20 10:10 ` [RFC PATCH v3 2/6] hw/arm/virt: Add missing 5.0 options call to 4.2 options Andrew Jones
` (6 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Andrew Jones @ 2020-01-20 10:10 UTC (permalink / raw)
To: qemu-devel, qemu-arm
Cc: peter.maydell, bijan.mottahedeh, maz, richard.henderson, guoheyi,
msys.mizuma
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
target/arm/kvm_arm.h | 46 ++++++++++++++++++++++++++------------------
1 file changed, 27 insertions(+), 19 deletions(-)
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index 8e14d400e8ab..b48a9c95573b 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -28,9 +28,9 @@
int kvm_arm_vcpu_init(CPUState *cs);
/**
- * kvm_arm_vcpu_finalize
+ * kvm_arm_vcpu_finalize:
* @cs: CPUState
- * @feature: int
+ * @feature: feature to finalize
*
* Finalizes the configuration of the specified VCPU feature by
* invoking the KVM_ARM_VCPU_FINALIZE ioctl. Features requiring
@@ -75,8 +75,8 @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group,
int kvm_arm_init_cpreg_list(ARMCPU *cpu);
/**
- * kvm_arm_reg_syncs_via_cpreg_list
- * regidx: KVM register index
+ * kvm_arm_reg_syncs_via_cpreg_list:
+ * @regidx: KVM register index
*
* Return true if this KVM register should be synchronized via the
* cpreg list of arbitrary system registers, false if it is synchronized
@@ -85,8 +85,8 @@ int kvm_arm_init_cpreg_list(ARMCPU *cpu);
bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx);
/**
- * kvm_arm_cpreg_level
- * regidx: KVM register index
+ * kvm_arm_cpreg_level:
+ * @regidx: KVM register index
*
* Return the level of this coprocessor/system register. Return value is
* either KVM_PUT_RUNTIME_STATE, KVM_PUT_RESET_STATE, or KVM_PUT_FULL_STATE.
@@ -148,6 +148,8 @@ void kvm_arm_init_serror_injection(CPUState *cs);
* @cpu: ARMCPU
*
* Get VCPU related state from kvm.
+ *
+ * Returns: 0 if success else < 0 error code
*/
int kvm_get_vcpu_events(ARMCPU *cpu);
@@ -156,6 +158,8 @@ int kvm_get_vcpu_events(ARMCPU *cpu);
* @cpu: ARMCPU
*
* Put VCPU related state to kvm.
+ *
+ * Returns: 0 if success else < 0 error code
*/
int kvm_put_vcpu_events(ARMCPU *cpu);
@@ -205,10 +209,12 @@ typedef struct ARMHostCPUFeatures {
/**
* kvm_arm_get_host_cpu_features:
- * @ahcc: ARMHostCPUClass to fill in
+ * @ahcf: ARMHostCPUClass to fill in
*
* Probe the capabilities of the host kernel's preferred CPU and fill
* in the ARMHostCPUClass struct accordingly.
+ *
+ * Returns true on success and false otherwise.
*/
bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf);
@@ -242,7 +248,7 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
bool kvm_arm_aarch32_supported(CPUState *cs);
/**
- * bool kvm_arm_pmu_supported:
+ * kvm_arm_pmu_supported:
* @cs: CPUState
*
* Returns: true if the KVM VCPU can enable its PMU
@@ -251,7 +257,7 @@ bool kvm_arm_aarch32_supported(CPUState *cs);
bool kvm_arm_pmu_supported(CPUState *cs);
/**
- * bool kvm_arm_sve_supported:
+ * kvm_arm_sve_supported:
* @cs: CPUState
*
* Returns true if the KVM VCPU can enable SVE and false otherwise.
@@ -259,26 +265,30 @@ bool kvm_arm_pmu_supported(CPUState *cs);
bool kvm_arm_sve_supported(CPUState *cs);
/**
- * kvm_arm_get_max_vm_ipa_size - Returns the number of bits in the
- * IPA address space supported by KVM
- *
+ * kvm_arm_get_max_vm_ipa_size:
* @ms: Machine state handle
+ *
+ * Returns the number of bits in the IPA address space supported by KVM
*/
int kvm_arm_get_max_vm_ipa_size(MachineState *ms);
/**
- * kvm_arm_sync_mpstate_to_kvm
+ * kvm_arm_sync_mpstate_to_kvm:
* @cpu: ARMCPU
*
* If supported set the KVM MP_STATE based on QEMU's model.
+ *
+ * Returns 0 on success and -1 on failure.
*/
int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu);
/**
- * kvm_arm_sync_mpstate_to_qemu
+ * kvm_arm_sync_mpstate_to_qemu:
* @cpu: ARMCPU
*
* If supported get the MP_STATE from KVM and store in QEMU's model.
+ *
+ * Returns 0 on success and aborts on failure.
*/
int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu);
@@ -292,7 +302,8 @@ int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level);
static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
{
- /* This should never actually be called in the "not KVM" case,
+ /*
+ * This should never actually be called in the "not KVM" case,
* but set up the fields to indicate an error anyway.
*/
cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
@@ -377,23 +388,20 @@ bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit);
*
* Return: TRUE if any hardware breakpoints in use.
*/
-
bool kvm_arm_hw_debug_active(CPUState *cs);
/**
* kvm_arm_copy_hw_debug_data:
- *
* @ptr: kvm_guest_debug_arch structure
*
* Copy the architecture specific debug registers into the
* kvm_guest_debug ioctl structure.
*/
struct kvm_guest_debug_arch;
-
void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr);
/**
- * its_class_name
+ * its_class_name:
*
* Return the ITS class name to use depending on whether KVM acceleration
* and KVM CAP_SIGNAL_MSI are supported
--
2.21.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC PATCH v3 2/6] hw/arm/virt: Add missing 5.0 options call to 4.2 options
2020-01-20 10:10 [RFC PATCH v3 0/6] target/arm/kvm: Adjust virtual time Andrew Jones
2020-01-20 10:10 ` [RFC PATCH v3 1/6] target/arm/kvm: trivial: Clean up header documentation Andrew Jones
@ 2020-01-20 10:10 ` Andrew Jones
2020-01-20 10:10 ` [RFC PATCH v3 3/6] target/arm/kvm64: kvm64 cpus have timer registers Andrew Jones
` (5 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Andrew Jones @ 2020-01-20 10:10 UTC (permalink / raw)
To: qemu-devel, qemu-arm
Cc: peter.maydell, bijan.mottahedeh, maz, richard.henderson, guoheyi,
msys.mizuma
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
hw/arm/virt.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 39ab5f47e0bd..27ca26b05e27 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2153,6 +2153,7 @@ DEFINE_VIRT_MACHINE_AS_LATEST(5, 0)
static void virt_machine_4_2_options(MachineClass *mc)
{
+ virt_machine_5_0_options(mc);
compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len);
}
DEFINE_VIRT_MACHINE(4, 2)
--
2.21.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC PATCH v3 3/6] target/arm/kvm64: kvm64 cpus have timer registers
2020-01-20 10:10 [RFC PATCH v3 0/6] target/arm/kvm: Adjust virtual time Andrew Jones
2020-01-20 10:10 ` [RFC PATCH v3 1/6] target/arm/kvm: trivial: Clean up header documentation Andrew Jones
2020-01-20 10:10 ` [RFC PATCH v3 2/6] hw/arm/virt: Add missing 5.0 options call to 4.2 options Andrew Jones
@ 2020-01-20 10:10 ` Andrew Jones
2020-01-20 10:10 ` [RFC PATCH v3 4/6] tests/arm-cpu-features: Check feature default values Andrew Jones
` (4 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Andrew Jones @ 2020-01-20 10:10 UTC (permalink / raw)
To: qemu-devel, qemu-arm
Cc: peter.maydell, bijan.mottahedeh, maz, richard.henderson, guoheyi,
msys.mizuma
Add the missing GENERIC_TIMER feature to kvm64 cpus.
We don't currently use these registers when KVM is enabled, but it's
probably best we add the feature flag for consistency and potential
future use. There's also precedent, as we add the PMU feature flag to
KVM enabled guests, even though we don't use those registers either.
This change was originally posted as a hunk of a different, never
merged patch from Bijan Mottahedeh.
Signed-off-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/kvm64.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index 876184b8fe4d..5cafcb7d36dd 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -605,6 +605,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
set_feature(&features, ARM_FEATURE_NEON);
set_feature(&features, ARM_FEATURE_AARCH64);
set_feature(&features, ARM_FEATURE_PMU);
+ set_feature(&features, ARM_FEATURE_GENERIC_TIMER);
ahcf->features = features;
--
2.21.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC PATCH v3 4/6] tests/arm-cpu-features: Check feature default values
2020-01-20 10:10 [RFC PATCH v3 0/6] target/arm/kvm: Adjust virtual time Andrew Jones
` (2 preceding siblings ...)
2020-01-20 10:10 ` [RFC PATCH v3 3/6] target/arm/kvm64: kvm64 cpus have timer registers Andrew Jones
@ 2020-01-20 10:10 ` Andrew Jones
2020-01-20 10:10 ` [RFC PATCH v3 5/6] target/arm/kvm: Implement virtual time adjustment Andrew Jones
` (3 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Andrew Jones @ 2020-01-20 10:10 UTC (permalink / raw)
To: qemu-devel, qemu-arm
Cc: peter.maydell, bijan.mottahedeh, maz, richard.henderson, guoheyi,
msys.mizuma
If we know what the default value should be then we can test for
that as well as the feature existence.
Signed-off-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
tests/qtest/arm-cpu-features.c | 37 +++++++++++++++++++++++++---------
1 file changed, 28 insertions(+), 9 deletions(-)
diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
index bef3ed24b604..a039e3c8d724 100644
--- a/tests/qtest/arm-cpu-features.c
+++ b/tests/qtest/arm-cpu-features.c
@@ -159,6 +159,25 @@ static bool resp_get_feature(QDict *resp, const char *feature)
qobject_unref(_resp); \
})
+#define assert_feature(qts, cpu_type, feature, expected_value) \
+({ \
+ QDict *_resp, *_props; \
+ \
+ _resp = do_query_no_props(qts, cpu_type); \
+ g_assert(_resp); \
+ g_assert(resp_has_props(_resp)); \
+ _props = resp_get_props(_resp); \
+ g_assert(qdict_get(_props, feature)); \
+ g_assert(qdict_get_bool(_props, feature) == (expected_value)); \
+ qobject_unref(_resp); \
+})
+
+#define assert_has_feature_enabled(qts, cpu_type, feature) \
+ assert_feature(qts, cpu_type, feature, true)
+
+#define assert_has_feature_disabled(qts, cpu_type, feature) \
+ assert_feature(qts, cpu_type, feature, false)
+
static void assert_type_full(QTestState *qts)
{
const char *error;
@@ -405,16 +424,16 @@ static void test_query_cpu_model_expansion(const void *data)
assert_error(qts, "host", "The CPU type 'host' requires KVM", NULL);
/* Test expected feature presence/absence for some cpu types */
- assert_has_feature(qts, "max", "pmu");
- assert_has_feature(qts, "cortex-a15", "pmu");
+ assert_has_feature_enabled(qts, "max", "pmu");
+ assert_has_feature_enabled(qts, "cortex-a15", "pmu");
assert_has_not_feature(qts, "cortex-a15", "aarch64");
if (g_str_equal(qtest_get_arch(), "aarch64")) {
- assert_has_feature(qts, "max", "aarch64");
- assert_has_feature(qts, "max", "sve");
- assert_has_feature(qts, "max", "sve128");
- assert_has_feature(qts, "cortex-a57", "pmu");
- assert_has_feature(qts, "cortex-a57", "aarch64");
+ assert_has_feature_enabled(qts, "max", "aarch64");
+ assert_has_feature_enabled(qts, "max", "sve");
+ assert_has_feature_enabled(qts, "max", "sve128");
+ assert_has_feature_enabled(qts, "cortex-a57", "pmu");
+ assert_has_feature_enabled(qts, "cortex-a57", "aarch64");
sve_tests_default(qts, "max");
@@ -451,8 +470,8 @@ static void test_query_cpu_model_expansion_kvm(const void *data)
QDict *resp;
char *error;
- assert_has_feature(qts, "host", "aarch64");
- assert_has_feature(qts, "host", "pmu");
+ assert_has_feature_enabled(qts, "host", "aarch64");
+ assert_has_feature_enabled(qts, "host", "pmu");
assert_error(qts, "cortex-a15",
"We cannot guarantee the CPU type 'cortex-a15' works "
--
2.21.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC PATCH v3 5/6] target/arm/kvm: Implement virtual time adjustment
2020-01-20 10:10 [RFC PATCH v3 0/6] target/arm/kvm: Adjust virtual time Andrew Jones
` (3 preceding siblings ...)
2020-01-20 10:10 ` [RFC PATCH v3 4/6] tests/arm-cpu-features: Check feature default values Andrew Jones
@ 2020-01-20 10:10 ` Andrew Jones
2020-01-20 10:10 ` [RFC PATCH v3 6/6] target/arm/cpu: Add the kvm-no-adjvtime CPU property Andrew Jones
` (2 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Andrew Jones @ 2020-01-20 10:10 UTC (permalink / raw)
To: qemu-devel, qemu-arm
Cc: peter.maydell, bijan.mottahedeh, maz, richard.henderson, guoheyi,
msys.mizuma
When a VM is stopped (such as when it's paused) guest virtual time
should stop counting. Otherwise, when the VM is resumed it will
experience time jumps and its kernel may report soft lockups. Not
counting virtual time while the VM is stopped has the side effect
of making the guest's time appear to lag when compared with real
time, and even with time derived from the physical counter. For
this reason, this change, which is enabled by default, comes with
a KVM CPU feature allowing it to be disabled, restoring legacy
behavior.
This patch only provides the implementation of the virtual time
adjustment. A subsequent patch will provide the CPU property
allowing the change to be enabled and disabled.
Reported-by: Bijan Mottahedeh <bijan.mottahedeh@oracle.com>
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
target/arm/cpu.h | 7 ++++
target/arm/kvm.c | 92 ++++++++++++++++++++++++++++++++++++++++++++
target/arm/kvm32.c | 3 ++
target/arm/kvm64.c | 3 ++
target/arm/kvm_arm.h | 38 ++++++++++++++++++
target/arm/machine.c | 7 ++++
6 files changed, 150 insertions(+)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 40f2c45e17e3..2e6477c92c9c 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -821,6 +821,13 @@ struct ARMCPU {
/* KVM init features for this CPU */
uint32_t kvm_init_features[7];
+ /* KVM CPU state */
+
+ /* KVM virtual time adjustment */
+ bool kvm_adjvtime;
+ bool kvm_vtime_dirty;
+ uint64_t kvm_vtime;
+
/* Uniprocessor system with MP extensions */
bool mp_is_up;
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index b87b59a02ad8..91e38def6b29 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -359,6 +359,22 @@ static int compare_u64(const void *a, const void *b)
return 0;
}
+/*
+ * cpreg_values are sorted in ascending order by KVM register ID
+ * (see kvm_arm_init_cpreg_list). This allows us to cheaply find
+ * the storage for a KVM register by ID with a binary search.
+ */
+static uint64_t *kvm_arm_get_cpreg_ptr(ARMCPU *cpu, uint64_t regidx)
+{
+ uint64_t *res;
+
+ res = bsearch(®idx, cpu->cpreg_indexes, cpu->cpreg_array_len,
+ sizeof(uint64_t), compare_u64);
+ assert(res);
+
+ return &cpu->cpreg_values[res - cpu->cpreg_indexes];
+}
+
/* Initialize the ARMCPU cpreg list according to the kernel's
* definition of what CPU registers it knows about (and throw away
* the previous TCG-created cpreg list).
@@ -512,6 +528,23 @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level)
return ok;
}
+void kvm_arm_cpu_pre_save(ARMCPU *cpu)
+{
+ /* KVM virtual time adjustment */
+ if (cpu->kvm_vtime_dirty) {
+ *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT) = cpu->kvm_vtime;
+ }
+}
+
+void kvm_arm_cpu_post_load(ARMCPU *cpu)
+{
+ /* KVM virtual time adjustment */
+ if (cpu->kvm_adjvtime) {
+ cpu->kvm_vtime = *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT);
+ cpu->kvm_vtime_dirty = true;
+ }
+}
+
void kvm_arm_reset_vcpu(ARMCPU *cpu)
{
int ret;
@@ -579,6 +612,50 @@ int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu)
return 0;
}
+void kvm_arm_get_virtual_time(CPUState *cs)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+ struct kvm_one_reg reg = {
+ .id = KVM_REG_ARM_TIMER_CNT,
+ .addr = (uintptr_t)&cpu->kvm_vtime,
+ };
+ int ret;
+
+ if (cpu->kvm_vtime_dirty) {
+ return;
+ }
+
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
+ if (ret) {
+ error_report("Failed to get KVM_REG_ARM_TIMER_CNT");
+ abort();
+ }
+
+ cpu->kvm_vtime_dirty = true;
+}
+
+void kvm_arm_put_virtual_time(CPUState *cs)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+ struct kvm_one_reg reg = {
+ .id = KVM_REG_ARM_TIMER_CNT,
+ .addr = (uintptr_t)&cpu->kvm_vtime,
+ };
+ int ret;
+
+ if (!cpu->kvm_vtime_dirty) {
+ return;
+ }
+
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
+ if (ret) {
+ error_report("Failed to set KVM_REG_ARM_TIMER_CNT");
+ abort();
+ }
+
+ cpu->kvm_vtime_dirty = false;
+}
+
int kvm_put_vcpu_events(ARMCPU *cpu)
{
CPUARMState *env = &cpu->env;
@@ -690,6 +767,21 @@ MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
return MEMTXATTRS_UNSPECIFIED;
}
+void kvm_arm_vm_state_change(void *opaque, int running, RunState state)
+{
+ CPUState *cs = opaque;
+ ARMCPU *cpu = ARM_CPU(cs);
+
+ if (running) {
+ if (cpu->kvm_adjvtime) {
+ kvm_arm_put_virtual_time(cs);
+ }
+ } else {
+ if (cpu->kvm_adjvtime) {
+ kvm_arm_get_virtual_time(cs);
+ }
+ }
+}
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
{
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
index 32bf8d6757c4..3a8b437eef0b 100644
--- a/target/arm/kvm32.c
+++ b/target/arm/kvm32.c
@@ -16,6 +16,7 @@
#include "qemu-common.h"
#include "cpu.h"
#include "qemu/timer.h"
+#include "sysemu/runstate.h"
#include "sysemu/kvm.h"
#include "kvm_arm.h"
#include "internals.h"
@@ -198,6 +199,8 @@ int kvm_arch_init_vcpu(CPUState *cs)
return -EINVAL;
}
+ qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs);
+
/* Determine init features for this CPU */
memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features));
if (cpu->start_powered_off) {
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index 5cafcb7d36dd..e486eaf1f944 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -23,6 +23,7 @@
#include "qemu/host-utils.h"
#include "qemu/main-loop.h"
#include "exec/gdbstub.h"
+#include "sysemu/runstate.h"
#include "sysemu/kvm.h"
#include "sysemu/kvm_int.h"
#include "kvm_arm.h"
@@ -735,6 +736,8 @@ int kvm_arch_init_vcpu(CPUState *cs)
return -EINVAL;
}
+ qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs);
+
/* Determine init features for this CPU */
memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features));
if (cpu->start_powered_off) {
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index b48a9c95573b..01a9a1827851 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -127,6 +127,23 @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level);
*/
bool write_kvmstate_to_list(ARMCPU *cpu);
+/**
+ * kvm_arm_cpu_pre_save:
+ * @cpu: ARMCPU
+ *
+ * Called after write_kvmstate_to_list() from cpu_pre_save() to update
+ * the cpreg list with KVM CPU state.
+ */
+void kvm_arm_cpu_pre_save(ARMCPU *cpu);
+
+/**
+ * kvm_arm_cpu_post_load:
+ * @cpu: ARMCPU
+ *
+ * Called from cpu_post_load() to update KVM CPU state from the cpreg list.
+ */
+void kvm_arm_cpu_post_load(ARMCPU *cpu);
+
/**
* kvm_arm_reset_vcpu:
* @cpu: ARMCPU
@@ -292,6 +309,24 @@ int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu);
*/
int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu);
+/**
+ * kvm_arm_get_virtual_time:
+ * @cs: CPUState
+ *
+ * Gets the VCPU's virtual counter and stores it in the KVM CPU state.
+ */
+void kvm_arm_get_virtual_time(CPUState *cs);
+
+/**
+ * kvm_arm_put_virtual_time:
+ * @cs: CPUState
+ *
+ * Sets the VCPU's virtual counter to the value stored in the KVM CPU state.
+ */
+void kvm_arm_put_virtual_time(CPUState *cs);
+
+void kvm_arm_vm_state_change(void *opaque, int running, RunState state);
+
int kvm_arm_vgic_probe(void);
void kvm_arm_pmu_set_irq(CPUState *cs, int irq);
@@ -339,6 +374,9 @@ static inline void kvm_arm_pmu_set_irq(CPUState *cs, int irq) {}
static inline void kvm_arm_pmu_init(CPUState *cs) {}
static inline void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map) {}
+
+static inline void kvm_arm_get_virtual_time(CPUState *cs) {}
+static inline void kvm_arm_put_virtual_time(CPUState *cs) {}
#endif
static inline const char *gic_class_name(void)
diff --git a/target/arm/machine.c b/target/arm/machine.c
index eb28b2381bb5..241890ac8cf7 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -642,6 +642,12 @@ static int cpu_pre_save(void *opaque)
/* This should never fail */
abort();
}
+
+ /*
+ * kvm_arm_cpu_pre_save() must be called after
+ * write_kvmstate_to_list()
+ */
+ kvm_arm_cpu_pre_save(cpu);
} else {
if (!write_cpustate_to_list(cpu, false)) {
/* This should never fail. */
@@ -744,6 +750,7 @@ static int cpu_post_load(void *opaque, int version_id)
* we're using it.
*/
write_list_to_cpustate(cpu);
+ kvm_arm_cpu_post_load(cpu);
} else {
if (!write_list_to_cpustate(cpu)) {
return -1;
--
2.21.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC PATCH v3 6/6] target/arm/cpu: Add the kvm-no-adjvtime CPU property
2020-01-20 10:10 [RFC PATCH v3 0/6] target/arm/kvm: Adjust virtual time Andrew Jones
` (4 preceding siblings ...)
2020-01-20 10:10 ` [RFC PATCH v3 5/6] target/arm/kvm: Implement virtual time adjustment Andrew Jones
@ 2020-01-20 10:10 ` Andrew Jones
2020-01-30 15:50 ` [RFC PATCH v3 0/6] target/arm/kvm: Adjust virtual time Peter Maydell
2020-01-31 11:40 ` Andrea Bolognani
7 siblings, 0 replies; 10+ messages in thread
From: Andrew Jones @ 2020-01-20 10:10 UTC (permalink / raw)
To: qemu-devel, qemu-arm
Cc: peter.maydell, bijan.mottahedeh, maz, richard.henderson, guoheyi,
msys.mizuma
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>
---
docs/arm-cpu-features.rst | 37 +++++++++++++++++++++++++++++++++-
hw/arm/virt.c | 8 ++++++++
include/hw/arm/virt.h | 1 +
target/arm/cpu.c | 2 ++
target/arm/cpu64.c | 1 +
target/arm/kvm.c | 28 +++++++++++++++++++++++++
target/arm/kvm_arm.h | 11 ++++++++++
target/arm/monitor.c | 1 +
tests/qtest/arm-cpu-features.c | 4 ++++
9 files changed, 92 insertions(+), 1 deletion(-)
diff --git a/docs/arm-cpu-features.rst b/docs/arm-cpu-features.rst
index 9b537a75e695..dbf3b7cf42c0 100644
--- a/docs/arm-cpu-features.rst
+++ b/docs/arm-cpu-features.rst
@@ -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
==================
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 27ca26b05e27..08b3c34c345c 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -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)
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 38f0c33c77c4..71508bf40c34 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -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 {
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index d62fd5fdc644..c2347f1cd335 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2562,6 +2562,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);
@@ -2755,6 +2756,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);
}
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 61fd0ade29a8..2d97bf45e1ec 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -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;
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 91e38def6b29..418bcedc3e6e 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -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)
{
KVMState *s = KVM_STATE(current_machine->accelerator);
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index 01a9a1827851..ae9e075d7545 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -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;
diff --git a/target/arm/monitor.c b/target/arm/monitor.c
index fa054f8a369c..9725dfff16d4 100644
--- a/target/arm/monitor.c
+++ b/target/arm/monitor.c
@@ -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
};
diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
index a039e3c8d724..469217367661 100644
--- a/tests/qtest/arm-cpu-features.c
+++ b/tests/qtest/arm-cpu-features.c
@@ -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];
--
2.21.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [RFC PATCH v3 0/6] target/arm/kvm: Adjust virtual time
2020-01-20 10:10 [RFC PATCH v3 0/6] target/arm/kvm: Adjust virtual time Andrew Jones
` (5 preceding siblings ...)
2020-01-20 10:10 ` [RFC PATCH v3 6/6] target/arm/cpu: Add the kvm-no-adjvtime CPU property Andrew Jones
@ 2020-01-30 15:50 ` Peter Maydell
2020-01-31 11:40 ` Andrea Bolognani
7 siblings, 0 replies; 10+ messages in thread
From: Peter Maydell @ 2020-01-30 15:50 UTC (permalink / raw)
To: Andrew Jones
Cc: bijan.mottahedeh, Marc Zyngier, Richard Henderson,
QEMU Developers, qemu-arm, Heyi Guo, msys.mizuma
On Mon, 20 Jan 2020 at 10:10, Andrew Jones <drjones@redhat.com> wrote:
>
> v3:
> - Added a target/arm/kvm_arm.h comment cleanup patch (1/6)
> - Minor refactoring of assert_has_feature_enabled/disabled in 4/6,
> kept Richard's r-b.
> - Rewrote kvm-no-adjvtime documentation in 6/6.
> - Reworked approach in 5/6 to properly deal with migration and to
> track running vs. !running, rather than running vs. paused states.
Applied to target-arm.next, thanks.
-- PMM
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH v3 0/6] target/arm/kvm: Adjust virtual time
2020-01-20 10:10 [RFC PATCH v3 0/6] target/arm/kvm: Adjust virtual time Andrew Jones
` (6 preceding siblings ...)
2020-01-30 15:50 ` [RFC PATCH v3 0/6] target/arm/kvm: Adjust virtual time Peter Maydell
@ 2020-01-31 11:40 ` Andrea Bolognani
2020-01-31 11:46 ` Peter Maydell
7 siblings, 1 reply; 10+ messages in thread
From: Andrea Bolognani @ 2020-01-31 11:40 UTC (permalink / raw)
To: Andrew Jones, qemu-devel, qemu-arm
Cc: peter.maydell, bijan.mottahedeh, maz, richard.henderson, guoheyi,
msys.mizuma
On Mon, 2020-01-20 at 11:10 +0100, Andrew Jones wrote:
> v3:
> - Added a target/arm/kvm_arm.h comment cleanup patch (1/6)
> - Minor refactoring of assert_has_feature_enabled/disabled in 4/6,
> kept Richard's r-b.
> - Rewrote kvm-no-adjvtime documentation in 6/6.
> - Reworked approach in 5/6 to properly deal with migration and to
> track running vs. !running, rather than running vs. paused states.
Probably too late since Peter already queued the series, but FWIW
Tested-by: Andrea Bolognani <abologna@redhat.com>
--
Andrea Bolognani / Red Hat / Virtualization
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH v3 0/6] target/arm/kvm: Adjust virtual time
2020-01-31 11:40 ` Andrea Bolognani
@ 2020-01-31 11:46 ` Peter Maydell
0 siblings, 0 replies; 10+ messages in thread
From: Peter Maydell @ 2020-01-31 11:46 UTC (permalink / raw)
To: Andrea Bolognani
Cc: Andrew Jones, bijan.mottahedeh, Marc Zyngier, Richard Henderson,
QEMU Developers, qemu-arm, Heyi Guo, msys.mizuma
On Fri, 31 Jan 2020 at 11:40, Andrea Bolognani <abologna@redhat.com> wrote:
>
> On Mon, 2020-01-20 at 11:10 +0100, Andrew Jones wrote:
> > v3:
> > - Added a target/arm/kvm_arm.h comment cleanup patch (1/6)
> > - Minor refactoring of assert_has_feature_enabled/disabled in 4/6,
> > kept Richard's r-b.
> > - Rewrote kvm-no-adjvtime documentation in 6/6.
> > - Reworked approach in 5/6 to properly deal with migration and to
> > track running vs. !running, rather than running vs. paused states.
>
> Probably too late since Peter already queued the series, but FWIW
>
> Tested-by: Andrea Bolognani <abologna@redhat.com>
Yeah, the commits hit master yesterday evening -- but the
testing is useful and appreciated even if we didn't manage
to get your tag into git...
thanks
-- PMM
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2020-01-31 11:47 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-01-20 10:10 [RFC PATCH v3 0/6] target/arm/kvm: Adjust virtual time Andrew Jones
2020-01-20 10:10 ` [RFC PATCH v3 1/6] target/arm/kvm: trivial: Clean up header documentation Andrew Jones
2020-01-20 10:10 ` [RFC PATCH v3 2/6] hw/arm/virt: Add missing 5.0 options call to 4.2 options Andrew Jones
2020-01-20 10:10 ` [RFC PATCH v3 3/6] target/arm/kvm64: kvm64 cpus have timer registers Andrew Jones
2020-01-20 10:10 ` [RFC PATCH v3 4/6] tests/arm-cpu-features: Check feature default values Andrew Jones
2020-01-20 10:10 ` [RFC PATCH v3 5/6] target/arm/kvm: Implement virtual time adjustment Andrew Jones
2020-01-20 10:10 ` [RFC PATCH v3 6/6] target/arm/cpu: Add the kvm-no-adjvtime CPU property Andrew Jones
2020-01-30 15:50 ` [RFC PATCH v3 0/6] target/arm/kvm: Adjust virtual time Peter Maydell
2020-01-31 11:40 ` Andrea Bolognani
2020-01-31 11:46 ` Peter Maydell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).