qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH v2 2/7] target-arm: Migrate CCSIDR registers


From: Alvise Rigo
Subject: [Qemu-devel] [PATCH v2 2/7] target-arm: Migrate CCSIDR registers
Date: Tue, 18 Mar 2014 10:19:44 +0100

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 <address@hidden>
---
 target-arm/cpu.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

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
 };
 
-- 
1.8.3.2




reply via email to

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