The vector state sync handles vstart, vl and vtype, but leaves vcsr
behind.  vxrm and vxsat in the migration stream are therefore stale,
and the destination does not restore the values held by KVM.

Read vcsr when collecting vector state and split it into vxrm and
vxsat.  Rebuild it from those fields when writing vector state back.

Fixes: 3ca78c0689d5 ("target/riscv/kvm: add RVV and Vector CSR regs")
Cc: [email protected]
Signed-off-by: Xie Bo <[email protected]>
---
 target/riscv/kvm/kvm-cpu.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index 1993bd446b..45ad5e1525 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -910,6 +910,13 @@ static int kvm_riscv_get_regs_vector(CPUState *cs)
     }
     env->vtype = reg;
 
+    ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(vcsr), &reg);
+    if (ret) {
+        return ret;
+    }
+    env->vxrm = (reg & VCSR_VXRM) >> VCSR_VXRM_SHIFT;
+    env->vxsat = (reg & VCSR_VXSAT) >> VCSR_VXSAT_SHIFT;
+
     if (kvm_v_vlenb.supported) {
         ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(vlenb), &reg);
         if (ret) {
@@ -966,6 +973,13 @@ static int kvm_riscv_put_regs_vector(CPUState *cs)
         return ret;
     }
 
+    reg = (env->vxrm << VCSR_VXRM_SHIFT) |
+          (env->vxsat << VCSR_VXSAT_SHIFT);
+    ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(vcsr), &reg);
+    if (ret) {
+        return ret;
+    }
+
     if (kvm_v_vlenb.supported) {
         reg = cpu->cfg.vlenb;
         ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(vlenb), &reg);
-- 
2.17.1


Reply via email to