136 lines
3.7 KiB
Diff
136 lines
3.7 KiB
Diff
From b341b4c1b514d1ca41b39bdf4d4bc4b0267350a3 Mon Sep 17 00:00:00 2001
|
|
From: Ying Fang <fangying1@huawei.com>
|
|
Date: Mon, 29 Jul 2019 15:47:27 +0800
|
|
Subject: [PATCH] ARM64: record vtimer tick when cpu is stopped
|
|
|
|
The vtimer kick still increases even if the vcpu is stopped when VM has
|
|
save/restore or suspend/resume operation. This will cause guest watchdog
|
|
soft-lockup if the VM has lots of memory in use.
|
|
|
|
Signed-off-by: Hao Hong <honghao5@huawei.com>
|
|
Signed-off-by: Haibin Wang <wanghaibin.wang@huawei.com>
|
|
Signed-off-by: Ying Fang <fangying1@huawei.com>
|
|
---
|
|
cpus.c | 59 ++++++++++++++++++++++++++++++++++++++++++++
|
|
target/arm/cpu.h | 2 ++
|
|
target/arm/machine.c | 1 +
|
|
3 files changed, 62 insertions(+)
|
|
|
|
diff --git a/cpus.c b/cpus.c
|
|
index e83f72b4..94c3b8ca 100644
|
|
--- a/cpus.c
|
|
+++ b/cpus.c
|
|
@@ -1063,6 +1063,28 @@ void cpu_synchronize_all_pre_loadvm(void)
|
|
}
|
|
}
|
|
|
|
+#ifdef __aarch64__
|
|
+static void get_vcpu_timer_tick(CPUState *cs)
|
|
+{
|
|
+ CPUARMState *env = &ARM_CPU(cs)->env;
|
|
+ int err;
|
|
+ struct kvm_one_reg reg;
|
|
+ uint64_t timer_tick;
|
|
+
|
|
+ reg.id = KVM_REG_ARM_TIMER_CNT;
|
|
+ reg.addr = (uintptr_t) &timer_tick;
|
|
+
|
|
+ err = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
|
+ if (err < 0) {
|
|
+ error_report("get vcpu tick failed, ret = %d", err);
|
|
+ env->vtimer = 0;
|
|
+ return;
|
|
+ }
|
|
+ env->vtimer = timer_tick;
|
|
+ return;
|
|
+}
|
|
+#endif
|
|
+
|
|
static int do_vm_stop(RunState state, bool send_stop)
|
|
{
|
|
int ret = 0;
|
|
@@ -1070,6 +1092,11 @@ static int do_vm_stop(RunState state, bool send_stop)
|
|
if (runstate_is_running()) {
|
|
cpu_disable_ticks();
|
|
pause_all_vcpus();
|
|
+#ifdef __aarch64__
|
|
+ if (first_cpu) {
|
|
+ get_vcpu_timer_tick(first_cpu);
|
|
+ }
|
|
+#endif
|
|
runstate_set(state);
|
|
vm_state_notify(0, state);
|
|
if (send_stop) {
|
|
@@ -1909,11 +1936,43 @@ void cpu_resume(CPUState *cpu)
|
|
qemu_cpu_kick(cpu);
|
|
}
|
|
|
|
+#ifdef __aarch64__
|
|
+static void set_vcpu_timer_tick(CPUState *cs)
|
|
+{
|
|
+ CPUARMState *env = &ARM_CPU(cs)->env;
|
|
+
|
|
+ if (env->vtimer == 0) {
|
|
+ error_report("Do not set vcpu tick.");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ int err;
|
|
+ struct kvm_one_reg reg;
|
|
+ uint64_t timer_tick = env->vtimer;
|
|
+ env->vtimer = 0;
|
|
+
|
|
+ reg.id = KVM_REG_ARM_TIMER_CNT;
|
|
+ reg.addr = (uintptr_t) &timer_tick;
|
|
+
|
|
+ err = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
|
+ if (err < 0) {
|
|
+ error_report("Set vcpu tick failed, ret = %d", err);
|
|
+ return;
|
|
+ }
|
|
+ return;
|
|
+}
|
|
+#endif
|
|
+
|
|
void resume_all_vcpus(void)
|
|
{
|
|
CPUState *cpu;
|
|
|
|
qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
|
|
+#ifdef __aarch64__
|
|
+ if (first_cpu) {
|
|
+ set_vcpu_timer_tick(first_cpu);
|
|
+ }
|
|
+#endif
|
|
CPU_FOREACH(cpu) {
|
|
cpu_resume(cpu);
|
|
}
|
|
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
|
|
index d4d28369..e107e395 100644
|
|
--- a/target/arm/cpu.h
|
|
+++ b/target/arm/cpu.h
|
|
@@ -270,6 +270,8 @@ typedef struct CPUARMState {
|
|
uint64_t elr_el[4]; /* AArch64 exception link regs */
|
|
uint64_t sp_el[4]; /* AArch64 banked stack pointers */
|
|
|
|
+ uint64_t vtimer; /* Timer tick when vcpu stop */
|
|
+
|
|
/* System control coprocessor (cp15) */
|
|
struct {
|
|
uint32_t c0_cpuid;
|
|
diff --git a/target/arm/machine.c b/target/arm/machine.c
|
|
index b2925496..d64a0057 100644
|
|
--- a/target/arm/machine.c
|
|
+++ b/target/arm/machine.c
|
|
@@ -792,6 +792,7 @@ const VMStateDescription vmstate_arm_cpu = {
|
|
VMSTATE_UINT32(env.exception.syndrome, ARMCPU),
|
|
VMSTATE_UINT32(env.exception.fsr, ARMCPU),
|
|
VMSTATE_UINT64(env.exception.vaddress, ARMCPU),
|
|
+ VMSTATE_UINT64(env.vtimer, ARMCPU),
|
|
VMSTATE_TIMER_PTR(gt_timer[GTIMER_PHYS], ARMCPU),
|
|
VMSTATE_TIMER_PTR(gt_timer[GTIMER_VIRT], ARMCPU),
|
|
{
|
|
--
|
|
2.19.1
|
|
|