This patch fixes two critical issues in QEMU with KVM:

1. Post-Migration Failure in User Mode: When QEMU with KVM is running in user 
mode, the guest may fail to function correctly after migration due to incorrect 
privilege state restoration.

2. Multi-Core Guest Inconsistency: After migration, only the first CPU (core 0) 
remains functional, while all other cores become unresponsive. This patch 
ensures all cores are properly set to runnable state after migration.

Changes include:
- Properly restoring guest privileged state during register synchronization.
- Correctly updating multi-core state after migration to ensure all cores are 
active.

Signed-off-by: Xie Bo <x...@ultrarisc.com>

---
 target/riscv/kvm/kvm-cpu.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -576,6 +576,14 @@ static int kvm_riscv_get_regs_core(CPUState *cs)
     }
     env->pc = reg;

+    /* Restore guest privilege level after migration */
+    ret = kvm_get_one_reg(cs, RISCV_CORE_REG(env, mode), &reg);
+    if (ret) {
+        return ret;
+    }
+    if (reg != 3) {
+        env->priv = reg;
+    }

     for (i = 1; i < 32; i++) {
         uint64_t id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CORE, i);
         ret = kvm_get_one_reg(cs, id, &reg);
@@ -601,6 +609,15 @@ static int kvm_riscv_put_regs_core(CPUState *cs)
         return ret;
     }

+    /* Save guest privilege level before migration */
+    reg = env->priv;
+    if (reg != 3) {
+        ret = kvm_set_one_reg(cs, RISCV_CORE_REG(env, mode), &reg);
+        if (ret) {
+            return ret;
+        }
+    }
+
     for (i = 1; i < 32; i++) {
         uint64_t id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CORE, i);
         reg = env->gpr[i];
@@ -1289,6 +1306,12 @@ int kvm_arch_put_registers(CPUState *cs, int level, 
Error **errp)
         return ret;
     }

+    /* Ensure all non-core 0 CPUs are runnable after migration */
+    if ((level == KVM_PUT_FULL_STATE) && (cs->cpu_index != 0)) {
+        RISCVCPU *cpu = RISCV_CPU(cs);
+        ret = kvm_riscv_sync_mpstate_to_kvm(cpu, KVM_MP_STATE_RUNNABLE);
+        if (ret) {
+            return ret;
+        }
+    }

     if (KVM_PUT_RESET_STATE == level) {
         RISCVCPU *cpu = RISCV_CPU(cs);
         if (cs->cpu_index == 0) {
-- 
2.34.1

______________________www.ultrarisc.com
重要提示:本邮件包括附件的内容是受法律保护的保密信息,如果您不是指定收件人,请立即将本邮件删除,法律禁止任何非法的披露、复制、传播或以任何方式使用本邮件。本邮件中包含的意见、建议是基于或受到我方表达和定义的条款及条件的限定,如无我方的正式书面澄清或授权,不可被单独作为任何情形下的证据或依据。感谢您的理解与配合。版权所有。IMPORTANT
 NOTICE: This email, including its attachment if any, is confidential. If you 
are not the intended recipient, please delete it from your computer 
immediately. Any disclosure, copying, or distribution of this message, or 
taking of any action based on it is strictly prohibited.  Any opinions and 
suggestions contained in this email are subject to the terms and conditions 
expressed and defined by us and should not be relied upon unconditionally under 
any circumstances unless they are confirmed in official written clarification 
or authorization from us.  Thank you for your understanding and cooperation.All 
rights reserved.

Reply via email to