[Qemu-devel] [RFC 5/6] target/arm: Conditionalize DBGDIDR vs ID_AA64DFR0_EL1 assert

Richard Henderson posted 6 patches 6 years, 8 months ago
Maintainers: Peter Maydell <peter.maydell@linaro.org>
[Qemu-devel] [RFC 5/6] target/arm: Conditionalize DBGDIDR vs ID_AA64DFR0_EL1 assert
Posted by Richard Henderson 6 years, 8 months ago
Only perform the assert when both registers exist.
Extract the variables from ID_AA64DFR0_EL1 for AArch64.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/helper.c | 58 +++++++++++++++++++++++++++++----------------
 1 file changed, 38 insertions(+), 20 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index fbdca9324b..1d8c8998c4 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -5544,32 +5544,50 @@ static void define_debug_regs(ARMCPU *cpu)
     /* Define v7 and v8 architectural debug registers.
      * These are just dummy implementations for now.
      */
-    int i;
-    int wrps, brps, ctx_cmps;
-    ARMCPRegInfo dbgdidr = {
-        .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0,
-        .access = PL0_R, .accessfn = access_tda,
-        .type = ARM_CP_CONST, .resetvalue = cpu->dbgdidr,
-    };
+    int i, wrps, brps, ctx_cmps;
+    bool have_aa32;
 
-    /* Note that all these register fields hold "number of Xs minus 1". */
-    brps = extract32(cpu->dbgdidr, 24, 4);
-    wrps = extract32(cpu->dbgdidr, 28, 4);
-    ctx_cmps = extract32(cpu->dbgdidr, 20, 4);
-
-    assert(ctx_cmps <= brps);
-
-    /* The DBGDIDR and ID_AA64DFR0_EL1 define various properties
+    /*
+     * The DBGDIDR and ID_AA64DFR0_EL1 define various properties
      * of the debug registers such as number of breakpoints;
      * check that if they both exist then they agree.
+     *
+     * Note that all these register fields hold "number of Xs minus 1".
      */
     if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
-        assert(extract32(cpu->id_aa64dfr0, 12, 4) == brps);
-        assert(extract32(cpu->id_aa64dfr0, 20, 4) == wrps);
-        assert(extract32(cpu->id_aa64dfr0, 28, 4) == ctx_cmps);
-    }
+        brps = extract32(cpu->id_aa64dfr0, 12, 4);
+        wrps = extract32(cpu->id_aa64dfr0, 20, 4);
+        ctx_cmps = extract32(cpu->id_aa64dfr0, 28, 4);
 
-    define_one_arm_cp_reg(cpu, &dbgdidr);
+        /*
+         * There are cpus with aarch32 only at EL0, and which do not
+         * have the 32-bit system registers.
+         */
+        have_aa32
+            = (FIELD_EX64(cpu->isar.id_aa64pfr0, ID_AA64PFR0, EL1) >= 2 ||
+               FIELD_EX64(cpu->isar.id_aa64pfr0, ID_AA64PFR0, EL2) >= 2 ||
+               FIELD_EX64(cpu->isar.id_aa64pfr0, ID_AA64PFR0, EL3) >= 2);
+        if (have_aa32) {
+            assert(extract32(cpu->dbgdidr, 24, 4) == brps);
+            assert(extract32(cpu->dbgdidr, 28, 4) == wrps);
+            assert(extract32(cpu->dbgdidr, 20, 4) == ctx_cmps);
+        }
+    } else {
+        have_aa32 = true;
+        brps = extract32(cpu->dbgdidr, 24, 4);
+        wrps = extract32(cpu->dbgdidr, 28, 4);
+        ctx_cmps = extract32(cpu->dbgdidr, 20, 4);
+    }
+    assert(ctx_cmps <= brps);
+
+    if (have_aa32) {
+        ARMCPRegInfo dbgdidr = {
+            .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0,
+            .opc1 = 0, .opc2 = 0, .access = PL0_R, .accessfn = access_tda,
+            .type = ARM_CP_CONST, .resetvalue = cpu->dbgdidr,
+        };
+        define_one_arm_cp_reg(cpu, &dbgdidr);
+    }
     define_arm_cp_regs(cpu, debug_cp_reginfo);
 
     if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) {
-- 
2.17.2


Re: [Qemu-devel] [RFC 5/6] target/arm: Conditionalize DBGDIDR vs ID_AA64DFR0_EL1 assert
Posted by Peter Maydell 6 years, 6 months ago
On Sat, 23 Feb 2019 at 02:40, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Only perform the assert when both registers exist.
> Extract the variables from ID_AA64DFR0_EL1 for AArch64.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

> +    if (have_aa32) {
> +        ARMCPRegInfo dbgdidr = {
> +            .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0,
> +            .opc1 = 0, .opc2 = 0, .access = PL0_R, .accessfn = access_tda,
> +            .type = ARM_CP_CONST, .resetvalue = cpu->dbgdidr,
> +        };
> +        define_one_arm_cp_reg(cpu, &dbgdidr);
> +    }

So if only EL0 has AArch32 it doesn't architecturally require
that this AArch32 system register doesn't exist, because the
register is still readable from EL0. The Arm ARM says that
"implementation of this register is optional and deprecated".
I would suggest that we should probably go with "implement the
register if cpu->dbgdidr is non-zero", since at least bit 15
must be set so zero isn't a valid real value for it.

Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM