diff mbox

[v2,2/7] target-arm: Migrate CCSIDR registers

Message ID 1395134389-25778-3-git-send-email-a.rigo@virtualopensystems.com
State New
Headers show

Commit Message

Alvise Rigo March 18, 2014, 9:19 a.m. UTC
Since KVM migrates the values of the CCSIDR registes as cp17
coprocessors registers values, we do the same in TCG, in such a way to
not let the migration fail.
The values of these registers will be read by the guest with the usual
mechanism (writing into CSSELR to select the desired Cache Size ID register
and then reading it from the CCSIDR register).

Signed-off-by: Alvise Rigo <a.rigo@virtualopensystems.com>
---
 target-arm/cpu.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)
diff mbox

Patch

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 1ce8a9b..3f0a9b3 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -692,6 +692,51 @@  static uint64_t a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
 }
 #endif
 
+static void cssidr_id_decode(const ARMCPRegInfo *ri,
+               uint32_t *level, uint32_t *instr_bit)
+{
+    /* the Cortex-A15 doesn't support more than 2 levels of cache,
+     * so both the instruction bit and level bits of the CSSELR encoding
+     * stay in the first 3 bits - opc2 bits */
+    *level = (ri->opc2 >> 1) & 3;
+    *instr_bit = ri->opc2 & 1;
+}
+
+static uint64_t a15_read_ccsidr(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    ARMCPU *cpu = arm_env_get_cpu(env);
+    uint32_t level, instr_bit;
+    cssidr_id_decode(ri, &level, &instr_bit);
+
+    switch (level) {
+    case 0: /* both L1 caches supported */
+        return cpu->ccsidr[instr_bit];
+    case 1: /* only one L2 unified cache */
+        if (!instr_bit) {
+            return cpu->ccsidr[2];
+        }
+    }
+
+    return 0;
+}
+
+static void a15_write_ccsidr(CPUARMState *env, const ARMCPRegInfo *ri,
+                                                       uint64_t value)
+{
+    ARMCPU *cpu = arm_env_get_cpu(env);
+    uint32_t level, instr_bit;
+    cssidr_id_decode(ri, &level, &instr_bit);
+
+    switch (level) {
+    case 0: /* both L1 caches supported */
+        cpu->ccsidr[instr_bit] = value;
+    case 1: /* only one L2 unified cache */
+        if (!instr_bit) {
+            cpu->ccsidr[2] = value;
+        }
+    }
+}
+
 static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
 #ifndef CONFIG_USER_ONLY
     { .name = "L2CTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
@@ -700,6 +745,25 @@  static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
 #endif
     { .name = "L2ECTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 3,
       .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    /* The following registers follows the CSSELR econding and are only used
+     * to migrate their data; the default values are set by cortex_a15_initfn.
+     * Their values are read by the system through the CCSELR and CCSIDR
+     * coprocessor registers. */
+    { .name = "L1_DCACHE",
+      .cp = 17, .opc1 = 0, .opc2 = 0, .crn = 0, .crm = 0,
+      .access = PL0_RW, .resetfn = arm_cp_reset_ignore,
+      .writefn = a15_write_ccsidr, .readfn = a15_read_ccsidr,
+      .state = ARM_CP_STATE_AA32, },
+    { .name = "L1_ICACHE",
+      .cp = 17, .opc1 = 0, .opc2 = 1, .crn = 0, .crm = 0,
+      .access = PL0_RW, .resetfn = arm_cp_reset_ignore,
+      .writefn = a15_write_ccsidr, .readfn = a15_read_ccsidr,
+      .state = ARM_CP_STATE_AA32, },
+    { .name = "L2_CACHE",
+      .cp = 17, .opc1 = 0, .opc2 = 2, .crn = 0, .crm = 0,
+      .access = PL0_RW, .resetfn = arm_cp_reset_ignore,
+      .writefn = a15_write_ccsidr, .readfn = a15_read_ccsidr,
+      .state = ARM_CP_STATE_AA32, },
     REGINFO_SENTINEL
 };