qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v2 3/7] target-arm: Add a way to mask some


From: Alvise Rigo
Subject: [Qemu-devel] [PATCH v2 3/7] target-arm: Add a way to mask some
Date: Tue, 18 Mar 2014 10:19:45 +0100

One of the issues blocking the migration from KVM to TCG is that the
former processor reads the coprocessors values directly from the
underlying hardware. TCG however, for the way it emulates some
registers, is not able to verify the incoming values, failing the
migration.

Add a mask to the ARMCPRegInfo structure to exclude the bits not supported of
the incoming registers values.
In case of an outgoing migration, the unsupported data is retrieved from the
cpreg_vmstate array.

Signed-off-by: Alvise Rigo <address@hidden>
---
 target-arm/cpu.h    |  1 +
 target-arm/helper.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 0a7edfe..adcfa42 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -955,6 +955,7 @@ struct ARMCPRegInfo {
      * fieldoffset is 0 then no reset will be done.
      */
     CPResetFn *resetfn;
+    uint64_t attr_mask;
 };
 
 /* Macros which are lvalues for the field in CPUARMState for the
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 2791dac..30973cc 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -166,6 +166,50 @@ static void write_raw_cp_reg(CPUARMState *env, const 
ARMCPRegInfo *ri,
     }
 }
 
+static bool cpreg_find_vmstate_val(ARMCPU *cpu, uint64_t id,
+                                        const uint64_t *val)
+{
+    int i;
+
+    for (i = 0; i < cpu->cpreg_vmstate_array_len; i++) {
+        if (cpu->cpreg_vmstate_indexes[i] == id) {
+            val = &cpu->cpreg_vmstate_values[i];
+            return true;
+        }
+    }
+
+    return false;
+}
+
+static uint64_t read_incoming_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *ri,
+                                                         uint64_t reg_id)
+{
+    CPUARMState *env = &cpu->env;
+    uint64_t val = read_raw_cp_reg(env, ri);
+    const uint64_t *inc_val = NULL;
+
+    if (cpreg_find_vmstate_val(cpu, reg_id, inc_val) && ri->attr_mask) {
+        val &= ri->attr_mask;
+        val |= (*inc_val & ~ri->attr_mask);
+    }
+
+    return val;
+}
+
+static void write_incoming_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri,
+                             uint64_t *v)
+{
+    if (ri->attr_mask) {
+        *v &= ri->attr_mask;
+        if (ri->type & ARM_CP_CONST) {
+            /* verify equality only of the supported values */
+            *v |= ri->resetvalue & ~ri->attr_mask;
+        }
+    }
+
+    write_raw_cp_reg(env, ri, *v);
+}
+
 bool write_cpustate_to_list(ARMCPU *cpu)
 {
     /* Write the coprocessor state from cpu->env to the (index,value) list. */
@@ -184,7 +228,8 @@ bool write_cpustate_to_list(ARMCPU *cpu)
         if (ri->type & ARM_CP_NO_MIGRATE) {
             continue;
         }
-        cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
+        cpu->cpreg_values[i] = read_incoming_cp_reg(cpu, ri,
+                                     cpu->cpreg_indexes[i]);
     }
     return ok;
 }
@@ -211,7 +256,7 @@ bool write_list_to_cpustate(ARMCPU *cpu)
          * (to catch read-only registers and partially read-only
          * registers where the incoming migration value doesn't match)
          */
-        write_raw_cp_reg(&cpu->env, ri, v);
+        write_incoming_cp_reg(&cpu->env, ri, &v);
         if (read_raw_cp_reg(&cpu->env, ri) != v) {
             ok = false;
         }
-- 
1.8.3.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]