target/arm/kvm: Adjust virtual time
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 upstream url: https://patchwork.kernel.org/cover/11341629/
This commit is contained in:
parent
5b01d214e0
commit
976278e59b
@ -101,6 +101,10 @@ Patch0088: block-file-posix-Let-post-EOF-fallocate-serialize.patch
|
|||||||
Patch0089: block-posix-Always-allocate-the-first-block.patch
|
Patch0089: block-posix-Always-allocate-the-first-block.patch
|
||||||
Patch0090: block-create-Do-not-abort-if-a-block-driver-is-not-a.patch
|
Patch0090: block-create-Do-not-abort-if-a-block-driver-is-not-a.patch
|
||||||
Patch0091: mirror-Keep-mirror_top_bs-drained-after-dropping-per.patch
|
Patch0091: mirror-Keep-mirror_top_bs-drained-after-dropping-per.patch
|
||||||
|
Patch0092: target-arm-kvm-trivial-Clean-up-header-documentation.patch
|
||||||
|
Patch0093: target-arm-kvm64-kvm64-cpus-have-timer-registers.patch
|
||||||
|
Patch0094: target-arm-kvm-Implement-virtual-time-adjustment.patch
|
||||||
|
Patch0095: target-arm-cpu-Add-the-kvm-no-adjvtime-CPU-property.patch
|
||||||
|
|
||||||
|
|
||||||
BuildRequires: flex
|
BuildRequires: flex
|
||||||
@ -447,6 +451,9 @@ getent passwd qemu >/dev/null || \
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed Apr 22 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
|
||||||
|
- backport patch to enable target/arm/kvm Adjust virtual time
|
||||||
|
|
||||||
* Fri Apr 17 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
|
* Fri Apr 17 2020 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
|
||||||
- backport patch bundles from qemu stable v4.1.1
|
- backport patch bundles from qemu stable v4.1.1
|
||||||
|
|
||||||
|
|||||||
152
target-arm-cpu-Add-the-kvm-no-adjvtime-CPU-property.patch
Normal file
152
target-arm-cpu-Add-the-kvm-no-adjvtime-CPU-property.patch
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
From 860035652c7866b033762f6d90f81d5ddedf855c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ying Fang <fangying1@huawei.com>
|
||||||
|
Date: Wed, 22 Apr 2020 17:08:43 +0800
|
||||||
|
Subject: [PATCH] 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>
|
||||||
|
|
||||||
|
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||||
|
index e9a2a959..cfda6cc5 100644
|
||||||
|
--- a/hw/arm/virt.c
|
||||||
|
+++ b/hw/arm/virt.c
|
||||||
|
@@ -1748,6 +1748,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);
|
||||||
|
}
|
||||||
|
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
|
||||||
|
index 43a6ce91..a9d6977a 100644
|
||||||
|
--- a/include/hw/arm/virt.h
|
||||||
|
+++ b/include/hw/arm/virt.h
|
||||||
|
@@ -107,6 +107,7 @@ typedef struct {
|
||||||
|
bool claim_edge_triggered_timers;
|
||||||
|
bool smbios_old_sys_ver;
|
||||||
|
bool no_highmem_ecam;
|
||||||
|
+ bool kvm_no_adjvtime;
|
||||||
|
} VirtMachineClass;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
|
||||||
|
index bc3da9a3..39bbe7e2 100644
|
||||||
|
--- a/target/arm/cpu.c
|
||||||
|
+++ b/target/arm/cpu.c
|
||||||
|
@@ -2441,6 +2441,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);
|
||||||
|
|
||||||
|
@@ -2629,6 +2630,7 @@ static void arm_host_initfn(Object *obj)
|
||||||
|
ARMCPU *cpu = ARM_CPU(obj);
|
||||||
|
|
||||||
|
kvm_arm_set_cpu_features_from_host(cpu);
|
||||||
|
+ kvm_arm_add_vcpu_properties(obj);
|
||||||
|
arm_cpu_post_init(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
|
||||||
|
index dbf44b92..b30ca7c9 100644
|
||||||
|
--- a/target/arm/cpu64.c
|
||||||
|
+++ b/target/arm/cpu64.c
|
||||||
|
@@ -312,6 +312,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 21fb7ecd..327b3bc3 100644
|
||||||
|
--- a/target/arm/kvm.c
|
||||||
|
+++ b/target/arm/kvm.c
|
||||||
|
@@ -16,6 +16,8 @@
|
||||||
|
#include "qemu-common.h"
|
||||||
|
#include "qemu/timer.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
|
+#include "qom/object.h"
|
||||||
|
+#include "qapi/error.h"
|
||||||
|
#include "sysemu/sysemu.h"
|
||||||
|
#include "sysemu/kvm.h"
|
||||||
|
#include "sysemu/kvm_int.h"
|
||||||
|
@@ -162,6 +164,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);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
|
||||||
|
{
|
||||||
|
KVMState *s = KVM_STATE(ms->accelerator);
|
||||||
|
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
|
||||||
|
index 97560d4e..0de5f83e 100644
|
||||||
|
--- a/target/arm/kvm_arm.h
|
||||||
|
+++ b/target/arm/kvm_arm.h
|
||||||
|
@@ -230,6 +230,15 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf);
|
||||||
|
*/
|
||||||
|
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_get_max_vm_ipa_size:
|
||||||
|
* @ms: Machine state handle
|
||||||
|
@@ -294,6 +303,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 int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
|
||||||
|
{
|
||||||
|
return -ENOENT;
|
||||||
|
--
|
||||||
|
2.23.0
|
||||||
290
target-arm-kvm-Implement-virtual-time-adjustment.patch
Normal file
290
target-arm-kvm-Implement-virtual-time-adjustment.patch
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
From 77ee224418fac859acecd9aca4d18555ced42db6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ying Fang <fangying1@huawei.com>
|
||||||
|
Date: Tue, 21 Apr 2020 17:32:31 +0800
|
||||||
|
Subject: [PATCH 3/4] target/arm/kvm: Implement virtual time adjustment
|
||||||
|
|
||||||
|
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>
|
||||||
|
Message-id: 20200120101023.16030-6-drjones@redhat.com
|
||||||
|
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
|
||||||
|
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
||||||
|
---
|
||||||
|
target/arm/cpu.h | 7 ++++
|
||||||
|
target/arm/kvm.c | 92 ++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
target/arm/kvm32.c | 2 +
|
||||||
|
target/arm/kvm64.c | 2 +
|
||||||
|
target/arm/kvm_arm.h | 37 ++++++++++++++++++
|
||||||
|
target/arm/machine.c | 7 ++++
|
||||||
|
6 files changed, 147 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
|
||||||
|
index 94c990cd..e19531a7 100644
|
||||||
|
--- a/target/arm/cpu.h
|
||||||
|
+++ b/target/arm/cpu.h
|
||||||
|
@@ -816,6 +816,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 cc7a46df..21fb7ecd 100644
|
||||||
|
--- a/target/arm/kvm.c
|
||||||
|
+++ b/target/arm/kvm.c
|
||||||
|
@@ -336,6 +336,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).
|
||||||
|
@@ -489,6 +505,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;
|
||||||
|
@@ -556,6 +589,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;
|
||||||
|
@@ -667,6 +744,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 51f78f72..ee158830 100644
|
||||||
|
--- a/target/arm/kvm32.c
|
||||||
|
+++ b/target/arm/kvm32.c
|
||||||
|
@@ -195,6 +195,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 f2f0a92e..4f0bf000 100644
|
||||||
|
--- a/target/arm/kvm64.c
|
||||||
|
+++ b/target/arm/kvm64.c
|
||||||
|
@@ -609,6 +609,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 32d97ce5..97560d4e 100644
|
||||||
|
--- a/target/arm/kvm_arm.h
|
||||||
|
+++ b/target/arm/kvm_arm.h
|
||||||
|
@@ -113,6 +113,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
|
||||||
|
@@ -241,6 +258,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);
|
||||||
|
@@ -272,6 +307,8 @@ static inline int kvm_arm_vgic_probe(void)
|
||||||
|
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_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 3fd319a3..ee3c59a6 100644
|
||||||
|
--- a/target/arm/machine.c
|
||||||
|
+++ b/target/arm/machine.c
|
||||||
|
@@ -644,6 +644,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. */
|
||||||
|
@@ -746,6 +752,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.23.0
|
||||||
144
target-arm-kvm-trivial-Clean-up-header-documentation.patch
Normal file
144
target-arm-kvm-trivial-Clean-up-header-documentation.patch
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
From c057499f90af4be8b26f57f8755aca0ddfcf9467 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ying Fang <fangying1@huawei.com>
|
||||||
|
Date: Tue, 21 Apr 2020 16:52:07 +0800
|
||||||
|
Subject: [PATCH 1/4] target/arm/kvm: trivial: Clean up header documentation
|
||||||
|
|
||||||
|
Signed-off-by: Andrew Jones <drjones@redhat.com>
|
||||||
|
Message-id: 20200120101023.16030-2-drjones@redhat.com
|
||||||
|
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
|
||||||
|
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
||||||
|
---
|
||||||
|
target/arm/kvm_arm.h | 38 +++++++++++++++++++++++---------------
|
||||||
|
1 file changed, 23 insertions(+), 15 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
|
||||||
|
index a9f3ccab..32d97ce5 100644
|
||||||
|
--- a/target/arm/kvm_arm.h
|
||||||
|
+++ b/target/arm/kvm_arm.h
|
||||||
|
@@ -61,8 +61,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
|
||||||
|
@@ -71,8 +71,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.
|
||||||
|
@@ -134,6 +134,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);
|
||||||
|
|
||||||
|
@@ -142,6 +144,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);
|
||||||
|
|
||||||
|
@@ -191,10 +195,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);
|
||||||
|
|
||||||
|
@@ -208,26 +214,30 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf);
|
||||||
|
void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
|
||||||
|
|
||||||
|
/**
|
||||||
|
- * 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);
|
||||||
|
|
||||||
|
@@ -241,7 +251,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;
|
||||||
|
@@ -310,23 +321,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.23.0
|
||||||
37
target-arm-kvm64-kvm64-cpus-have-timer-registers.patch
Normal file
37
target-arm-kvm64-kvm64-cpus-have-timer-registers.patch
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
From 07bd62920f968da7d1d8962cc7fd3d29652d25f4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ying Fang <fangying1@huawei.com>
|
||||||
|
Date: Tue, 21 Apr 2020 17:04:13 +0800
|
||||||
|
Subject: [PATCH 2/4] target/arm/kvm64: kvm64 cpus have timer registers
|
||||||
|
|
||||||
|
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>
|
||||||
|
Message-id: 20200120101023.16030-4-drjones@redhat.com
|
||||||
|
Signed-off-by: Peter Maydell <peter.maydell@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 22d19c9a..f2f0a92e 100644
|
||||||
|
--- a/target/arm/kvm64.c
|
||||||
|
+++ b/target/arm/kvm64.c
|
||||||
|
@@ -587,6 +587,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.23.0
|
||||||
Loading…
x
Reference in New Issue
Block a user