Skip to content

Commit

Permalink
target/arm: Don't implement *32_EL2 registers when EL1 is AArch64 only
Browse files Browse the repository at this point in the history
The system registers DBGVCR32_EL2, FPEXC32_EL2, DACR32_EL2 and
IFSR32_EL2 are present only to allow an AArch64 EL2 or EL3 to read
and write the contents of an AArch32-only system register.  The
architecture requires that they are present only when EL1 can be
AArch32, but we implement them unconditionally.  This was OK when all
our CPUs supported AArch32 EL1, but we have quite a lot of CPU models
now which only support AArch64 at EL1:
 a64fx
 cortex-a76
 cortex-a710
 neoverse-n1
 neoverse-n2
 neoverse-v1

Only define these registers for CPUs which allow AArch32 EL1.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20231121144605.3980419-1-peter.maydell@linaro.org
  • Loading branch information
pm215 committed Dec 19, 2023
1 parent 366bf10 commit c36a0d5
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 22 deletions.
23 changes: 15 additions & 8 deletions target/arm/debug_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -1026,14 +1026,6 @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
.cp = 14, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
.access = PL1_RW, .accessfn = access_tda,
.type = ARM_CP_NOP },
/*
* Dummy DBGVCR32_EL2 (which is only for a 64-bit hypervisor
* to save and restore a 32-bit guest's DBGVCR)
*/
{ .name = "DBGVCR32_EL2", .state = ARM_CP_STATE_AA64,
.opc0 = 2, .opc1 = 4, .crn = 0, .crm = 7, .opc2 = 0,
.access = PL2_RW, .accessfn = access_tda,
.type = ARM_CP_NOP | ARM_CP_EL3_NO_EL2_KEEP },
/*
* Dummy MDCCINT_EL1, since we don't implement the Debug Communications
* Channel but Linux may try to access this register. The 32-bit
Expand Down Expand Up @@ -1062,6 +1054,18 @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
.fieldoffset = offsetof(CPUARMState, cp15.dbgclaim) },
};

/* These are present only when EL1 supports AArch32 */
static const ARMCPRegInfo debug_aa32_el1_reginfo[] = {
/*
* Dummy DBGVCR32_EL2 (which is only for a 64-bit hypervisor
* to save and restore a 32-bit guest's DBGVCR)
*/
{ .name = "DBGVCR32_EL2", .state = ARM_CP_STATE_AA64,
.opc0 = 2, .opc1 = 4, .crn = 0, .crm = 7, .opc2 = 0,
.access = PL2_RW, .accessfn = access_tda,
.type = ARM_CP_NOP | ARM_CP_EL3_NO_EL2_KEEP },
};

static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
/* 64 bit access versions of the (dummy) debug registers */
{ .name = "DBGDRAR", .cp = 14, .crm = 1, .opc1 = 0,
Expand Down Expand Up @@ -1207,6 +1211,9 @@ void define_debug_regs(ARMCPU *cpu)
assert(ctx_cmps <= brps);

define_arm_cp_regs(cpu, debug_cp_reginfo);
if (cpu_isar_feature(aa64_aa32_el1, cpu)) {
define_arm_cp_regs(cpu, debug_aa32_el1_reginfo);
}

if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) {
define_arm_cp_regs(cpu, debug_lpae_cp_reginfo);
Expand Down
35 changes: 21 additions & 14 deletions target/arm/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -5698,20 +5698,6 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
.opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 0,
.type = ARM_CP_NO_RAW,
.access = PL1_RW, .readfn = spsel_read, .writefn = spsel_write },
{ .name = "FPEXC32_EL2", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 3, .opc2 = 0,
.access = PL2_RW,
.type = ARM_CP_ALIAS | ARM_CP_FPU | ARM_CP_EL3_NO_EL2_KEEP,
.fieldoffset = offsetof(CPUARMState, vfp.xregs[ARM_VFP_FPEXC]) },
{ .name = "DACR32_EL2", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 4, .crn = 3, .crm = 0, .opc2 = 0,
.access = PL2_RW, .resetvalue = 0, .type = ARM_CP_EL3_NO_EL2_KEEP,
.writefn = dacr_write, .raw_writefn = raw_write,
.fieldoffset = offsetof(CPUARMState, cp15.dacr32_el2) },
{ .name = "IFSR32_EL2", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 0, .opc2 = 1,
.access = PL2_RW, .resetvalue = 0, .type = ARM_CP_EL3_NO_EL2_KEEP,
.fieldoffset = offsetof(CPUARMState, cp15.ifsr32_el2) },
{ .name = "SPSR_IRQ", .state = ARM_CP_STATE_AA64,
.type = ARM_CP_ALIAS,
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 0,
Expand Down Expand Up @@ -5746,6 +5732,24 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
.fieldoffset = offsetoflow32(CPUARMState, cp15.mdcr_el3) },
};

/* These are present only when EL1 supports AArch32 */
static const ARMCPRegInfo v8_aa32_el1_reginfo[] = {
{ .name = "FPEXC32_EL2", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 3, .opc2 = 0,
.access = PL2_RW,
.type = ARM_CP_ALIAS | ARM_CP_FPU | ARM_CP_EL3_NO_EL2_KEEP,
.fieldoffset = offsetof(CPUARMState, vfp.xregs[ARM_VFP_FPEXC]) },
{ .name = "DACR32_EL2", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 4, .crn = 3, .crm = 0, .opc2 = 0,
.access = PL2_RW, .resetvalue = 0, .type = ARM_CP_EL3_NO_EL2_KEEP,
.writefn = dacr_write, .raw_writefn = raw_write,
.fieldoffset = offsetof(CPUARMState, cp15.dacr32_el2) },
{ .name = "IFSR32_EL2", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 0, .opc2 = 1,
.access = PL2_RW, .resetvalue = 0, .type = ARM_CP_EL3_NO_EL2_KEEP,
.fieldoffset = offsetof(CPUARMState, cp15.ifsr32_el2) },
};

static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask)
{
ARMCPU *cpu = env_archcpu(env);
Expand Down Expand Up @@ -8716,6 +8720,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
}
define_arm_cp_regs(cpu, v8_idregs);
define_arm_cp_regs(cpu, v8_cp_reginfo);
if (cpu_isar_feature(aa64_aa32_el1, cpu)) {
define_arm_cp_regs(cpu, v8_aa32_el1_reginfo);
}

for (i = 4; i < 16; i++) {
/*
Expand Down

0 comments on commit c36a0d5

Please sign in to comment.