[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 23/52] target/arm: Stop assuming DBGDIDR always exists
From: |
Peter Maydell |
Subject: |
[PULL 23/52] target/arm: Stop assuming DBGDIDR always exists |
Date: |
Fri, 21 Feb 2020 13:07:11 +0000 |
The AArch32 DBGDIDR defines properties like the number of
breakpoints, watchpoints and context-matching comparators. On an
AArch64 CPU, the register may not even exist if AArch32 is not
supported at EL1.
Currently we hard-code use of DBGDIDR to identify the number of
breakpoints etc; this works for all our TCG CPUs, but will break if
we ever add an AArch64-only CPU. We also have an assert() that the
AArch32 and AArch64 registers match, which currently works only by
luck for KVM because we don't populate either of these ID registers
from the KVM vCPU and so they are both zero.
Clean this up so we have functions for finding the number
of breakpoints, watchpoints and context comparators which look
in the appropriate ID register.
This allows us to drop the "check that AArch64 and AArch32 agree
on the number of breakpoints etc" asserts:
* we no longer look at the AArch32 versions unless that's the
right place to be looking
* it's valid to have a CPU (eg AArch64-only) where they don't match
* we shouldn't have been asserting the validity of ID registers
in a codepath used with KVM anyway
Signed-off-by: Peter Maydell <address@hidden>
Reviewed-by: Richard Henderson <address@hidden>
Message-id: address@hidden
---
target/arm/cpu.h | 7 +++++++
target/arm/internals.h | 42 +++++++++++++++++++++++++++++++++++++++
target/arm/debug_helper.c | 6 +++---
target/arm/helper.c | 21 +++++---------------
4 files changed, 57 insertions(+), 19 deletions(-)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 98240224c0c..0f21b6ed803 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1840,6 +1840,13 @@ FIELD(ID_DFR0, MPROFDBG, 20, 4)
FIELD(ID_DFR0, PERFMON, 24, 4)
FIELD(ID_DFR0, TRACEFILT, 28, 4)
+FIELD(DBGDIDR, SE_IMP, 12, 1)
+FIELD(DBGDIDR, NSUHD_IMP, 14, 1)
+FIELD(DBGDIDR, VERSION, 16, 4)
+FIELD(DBGDIDR, CTX_CMPS, 20, 4)
+FIELD(DBGDIDR, BRPS, 24, 4)
+FIELD(DBGDIDR, WRPS, 28, 4)
+
FIELD(MVFR0, SIMDREG, 0, 4)
FIELD(MVFR0, FPSP, 4, 4)
FIELD(MVFR0, FPDP, 8, 4)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 31aaa0eff87..e07a7306c77 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -931,6 +931,48 @@ static inline uint32_t arm_debug_exception_fsr(CPUARMState
*env)
}
}
+/**
+ * arm_num_brps: Return number of implemented breakpoints.
+ * Note that the ID register BRPS field is "number of bps - 1",
+ * and we return the actual number of breakpoints.
+ */
+static inline int arm_num_brps(ARMCPU *cpu)
+{
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
+ return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) + 1;
+ } else {
+ return FIELD_EX32(cpu->dbgdidr, DBGDIDR, BRPS) + 1;
+ }
+}
+
+/**
+ * arm_num_wrps: Return number of implemented watchpoints.
+ * Note that the ID register WRPS field is "number of wps - 1",
+ * and we return the actual number of watchpoints.
+ */
+static inline int arm_num_wrps(ARMCPU *cpu)
+{
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
+ return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) + 1;
+ } else {
+ return FIELD_EX32(cpu->dbgdidr, DBGDIDR, WRPS) + 1;
+ }
+}
+
+/**
+ * arm_num_ctx_cmps: Return number of implemented context comparators.
+ * Note that the ID register CTX_CMPS field is "number of cmps - 1",
+ * and we return the actual number of comparators.
+ */
+static inline int arm_num_ctx_cmps(ARMCPU *cpu)
+{
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
+ return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) + 1;
+ } else {
+ return FIELD_EX32(cpu->dbgdidr, DBGDIDR, CTX_CMPS) + 1;
+ }
+}
+
/* Note make_memop_idx reserves 4 bits for mmu_idx, and MO_BSWAP is bit 3.
* Thus a TCGMemOpIdx, without any MO_ALIGN bits, fits in 8 bits.
*/
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index 2e3e90c6a57..2ff72d47d19 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -16,8 +16,8 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
{
CPUARMState *env = &cpu->env;
uint64_t bcr = env->cp15.dbgbcr[lbn];
- int brps = extract32(cpu->dbgdidr, 24, 4);
- int ctx_cmps = extract32(cpu->dbgdidr, 20, 4);
+ int brps = arm_num_brps(cpu);
+ int ctx_cmps = arm_num_ctx_cmps(cpu);
int bt;
uint32_t contextidr;
uint64_t hcr_el2;
@@ -29,7 +29,7 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
* case DBGWCR<n>_EL1.LBN must indicate that breakpoint).
* We choose the former.
*/
- if (lbn > brps || lbn < (brps - ctx_cmps)) {
+ if (lbn >= brps || lbn < (brps - ctx_cmps)) {
return false;
}
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 679f340c55f..87e71fb8c78 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6256,23 +6256,12 @@ static void define_debug_regs(ARMCPU *cpu)
};
/* 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);
+ brps = arm_num_brps(cpu);
+ wrps = arm_num_wrps(cpu);
+ ctx_cmps = arm_num_ctx_cmps(cpu);
assert(ctx_cmps <= brps);
- /* 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.
- */
- if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
- assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) == brps);
- assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) == wrps);
- assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS)
- == ctx_cmps);
- }
-
define_one_arm_cp_reg(cpu, &dbgdidr);
define_arm_cp_regs(cpu, debug_cp_reginfo);
@@ -6280,7 +6269,7 @@ static void define_debug_regs(ARMCPU *cpu)
define_arm_cp_regs(cpu, debug_lpae_cp_reginfo);
}
- for (i = 0; i < brps + 1; i++) {
+ for (i = 0; i < brps; i++) {
ARMCPRegInfo dbgregs[] = {
{ .name = "DBGBVR", .state = ARM_CP_STATE_BOTH,
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 4,
@@ -6299,7 +6288,7 @@ static void define_debug_regs(ARMCPU *cpu)
define_arm_cp_regs(cpu, dbgregs);
}
- for (i = 0; i < wrps + 1; i++) {
+ for (i = 0; i < wrps; i++) {
ARMCPRegInfo dbgregs[] = {
{ .name = "DBGWVR", .state = ARM_CP_STATE_BOTH,
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 6,
--
2.20.1
- [PULL 15/52] target/arm: Check aa32_pan in take_aarch32_exception(), not aa64_pan, (continued)
- [PULL 15/52] target/arm: Check aa32_pan in take_aarch32_exception(), not aa64_pan, Peter Maydell, 2020/02/21
- [PULL 13/52] target/arm: Split out aa64_va_parameter_tbi, aa64_va_parameter_tbid, Peter Maydell, 2020/02/21
- [PULL 14/52] target/arm: Add _aa32_ to isar_feature functions testing 32-bit ID registers, Peter Maydell, 2020/02/21
- [PULL 17/52] target/arm: Define and use any_predinv isar_feature test, Peter Maydell, 2020/02/21
- [PULL 16/52] target/arm: Add isar_feature_any_fp16 and document naming/usage conventions, Peter Maydell, 2020/02/21
- [PULL 20/52] target/arm: Use FIELD macros for clearing ID_DFR0 PERFMON field, Peter Maydell, 2020/02/21
- [PULL 18/52] target/arm: Factor out PMU register definitions, Peter Maydell, 2020/02/21
- [PULL 21/52] target/arm: Define an aa32_pmu_8_1 isar feature test function, Peter Maydell, 2020/02/21
- [PULL 22/52] target/arm: Add _aa64_ and _any_ versions of pmu_8_1 isar checks, Peter Maydell, 2020/02/21
- [PULL 19/52] target/arm: Add and use FIELD definitions for ID_AA64DFR0_EL1, Peter Maydell, 2020/02/21
- [PULL 23/52] target/arm: Stop assuming DBGDIDR always exists,
Peter Maydell <=
- [PULL 24/52] target/arm: Move DBGDIDR into ARMISARegisters, Peter Maydell, 2020/02/21
- [PULL 26/52] target/arm: Implement ARMv8.1-PMU extension, Peter Maydell, 2020/02/21
- [PULL 25/52] target/arm: Read debug-related ID registers from KVM, Peter Maydell, 2020/02/21
- [PULL 27/52] target/arm: Implement ARMv8.4-PMU extension, Peter Maydell, 2020/02/21
- [PULL 29/52] target/arm: Correct definition of PMCRDP, Peter Maydell, 2020/02/21
- [PULL 28/52] target/arm: Provide ARMv8.4-PMU in '-cpu max', Peter Maydell, 2020/02/21
- [PULL 30/52] target/arm: Correct handling of PMCR_EL0.LC bit, Peter Maydell, 2020/02/21
- [PULL 32/52] target/arm: Use isar_feature function for testing AA32HPD feature, Peter Maydell, 2020/02/21
- [PULL 33/52] target/arm: Use FIELD_EX32 for testing 32-bit fields, Peter Maydell, 2020/02/21
- [PULL 31/52] target/arm: Test correct register in aa32_pan and aa32_ats1e1 checks, Peter Maydell, 2020/02/21