target-arm: Adjust debug ID registers per-CPU
Allow each CPU type to specify the value for the debug ID registers, by putting them in the ARMCPU struct, and use the resulting information to only expose the correct number of watchpoint and breakpoint registers for the CPU. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
This commit is contained in:
parent
10aae1049f
commit
48eb3ae64b
@ -148,6 +148,7 @@ typedef struct ARMCPU {
|
||||
uint64_t id_aa64isar1;
|
||||
uint64_t id_aa64mmfr0;
|
||||
uint64_t id_aa64mmfr1;
|
||||
uint32_t dbgdidr;
|
||||
uint32_t clidr;
|
||||
/* The elements of this array are the CCSIDR values for each cache,
|
||||
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
|
||||
|
@ -640,6 +640,7 @@ static void cortex_a8_initfn(Object *obj)
|
||||
cpu->id_isar2 = 0x21232031;
|
||||
cpu->id_isar3 = 0x11112131;
|
||||
cpu->id_isar4 = 0x00111142;
|
||||
cpu->dbgdidr = 0x15141000;
|
||||
cpu->clidr = (1 << 27) | (2 << 24) | 3;
|
||||
cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */
|
||||
cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */
|
||||
@ -712,6 +713,7 @@ static void cortex_a9_initfn(Object *obj)
|
||||
cpu->id_isar2 = 0x21232041;
|
||||
cpu->id_isar3 = 0x11112131;
|
||||
cpu->id_isar4 = 0x00111142;
|
||||
cpu->dbgdidr = 0x35141000;
|
||||
cpu->clidr = (1 << 27) | (1 << 24) | 3;
|
||||
cpu->ccsidr[0] = 0xe00fe015; /* 16k L1 dcache. */
|
||||
cpu->ccsidr[1] = 0x200fe015; /* 16k L1 icache. */
|
||||
@ -773,6 +775,7 @@ static void cortex_a15_initfn(Object *obj)
|
||||
cpu->id_isar2 = 0x21232041;
|
||||
cpu->id_isar3 = 0x11112131;
|
||||
cpu->id_isar4 = 0x10011142;
|
||||
cpu->dbgdidr = 0x3515f021;
|
||||
cpu->clidr = 0x0a200023;
|
||||
cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
|
||||
cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
|
||||
|
@ -127,6 +127,7 @@ static void aarch64_a57_initfn(Object *obj)
|
||||
cpu->id_aa64dfr0 = 0x10305106;
|
||||
cpu->id_aa64isar0 = 0x00010000;
|
||||
cpu->id_aa64mmfr0 = 0x00001124;
|
||||
cpu->dbgdidr = 0x3516d000;
|
||||
cpu->clidr = 0x0a200023;
|
||||
cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
|
||||
cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */
|
||||
|
@ -2186,12 +2186,6 @@ static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||
}
|
||||
|
||||
static const ARMCPRegInfo debug_cp_reginfo[] = {
|
||||
/* DBGDIDR: just RAZ. In particular this means the "debug architecture
|
||||
* version" bits will read as a reserved value, which should cause
|
||||
* Linux to not try to use the debug hardware.
|
||||
*/
|
||||
{ .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0,
|
||||
.access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
/* DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped
|
||||
* debug components. The AArch64 version of DBGDRAR is named MDRAR_EL1;
|
||||
* unlike DBGDRAR it is never accessible from EL0.
|
||||
@ -2233,14 +2227,32 @@ static void define_debug_regs(ARMCPU *cpu)
|
||||
* These are just dummy implementations for now.
|
||||
*/
|
||||
int i;
|
||||
int wrps, brps;
|
||||
ARMCPRegInfo dbgdidr = {
|
||||
.name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0,
|
||||
.access = PL0_R, .type = ARM_CP_CONST, .resetvalue = cpu->dbgdidr,
|
||||
};
|
||||
|
||||
brps = extract32(cpu->dbgdidr, 24, 4);
|
||||
wrps = extract32(cpu->dbgdidr, 28, 4);
|
||||
|
||||
/* 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(extract32(cpu->id_aa64dfr0, 12, 4) == brps);
|
||||
assert(extract32(cpu->id_aa64dfr0, 20, 4) == wrps);
|
||||
}
|
||||
|
||||
define_one_arm_cp_reg(cpu, &dbgdidr);
|
||||
define_arm_cp_regs(cpu, debug_cp_reginfo);
|
||||
|
||||
if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) {
|
||||
define_arm_cp_regs(cpu, debug_lpae_cp_reginfo);
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
for (i = 0; i < brps + 1; i++) {
|
||||
ARMCPRegInfo dbgregs[] = {
|
||||
{ .name = "DBGBVR", .state = ARM_CP_STATE_BOTH,
|
||||
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 4,
|
||||
@ -2250,6 +2262,13 @@ static void define_debug_regs(ARMCPU *cpu)
|
||||
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 5,
|
||||
.access = PL1_RW,
|
||||
.fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]) },
|
||||
REGINFO_SENTINEL
|
||||
};
|
||||
define_arm_cp_regs(cpu, dbgregs);
|
||||
}
|
||||
|
||||
for (i = 0; i < wrps + 1; i++) {
|
||||
ARMCPRegInfo dbgregs[] = {
|
||||
{ .name = "DBGWVR", .state = ARM_CP_STATE_BOTH,
|
||||
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 6,
|
||||
.access = PL1_RW,
|
||||
|
Loading…
Reference in New Issue
Block a user