target/arm: Implement HCR_EL2.TICAB,TOCU traps

For FEAT_EVT, the HCR_EL2.TICAB bit allows trapping of the ICIALLUIS
and IC IALLUIS cache maintenance instructions.

The HCR_EL2.TOCU bit traps all the other cache maintenance
instructions that operate to the point of unification:
 AArch64 IC IVAU, IC IALLU, DC CVAU
 AArch32 ICIMVAU, ICIALLU, DCCMVAU

The two trap bits between them cover all of the cache maintenance
instructions which must also check the HCR_TPU flag.  Turn the old
aa64_cacheop_pou_access() function into a helper function which takes
the set of HCR_EL2 flags to check as an argument, and call it from
new access_ticab() and access_tocu() functions as appropriate for
each cache op.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Peter Maydell 2022-12-14 14:27:09 +00:00
parent fe3ca86c46
commit 2d3ce4c6f3
1 changed files with 23 additions and 13 deletions

View File

@ -4273,9 +4273,7 @@ static CPAccessResult aa64_cacheop_poc_access(CPUARMState *env,
return CP_ACCESS_OK; return CP_ACCESS_OK;
} }
static CPAccessResult aa64_cacheop_pou_access(CPUARMState *env, static CPAccessResult do_cacheop_pou_access(CPUARMState *env, uint64_t hcrflags)
const ARMCPRegInfo *ri,
bool isread)
{ {
/* Cache invalidate/clean to Point of Unification... */ /* Cache invalidate/clean to Point of Unification... */
switch (arm_current_el(env)) { switch (arm_current_el(env)) {
@ -4286,8 +4284,8 @@ static CPAccessResult aa64_cacheop_pou_access(CPUARMState *env,
} }
/* fall through */ /* fall through */
case 1: case 1:
/* ... EL1 must trap to EL2 if HCR_EL2.TPU is set. */ /* ... EL1 must trap to EL2 if relevant HCR_EL2 flags are set. */
if (arm_hcr_el2_eff(env) & HCR_TPU) { if (arm_hcr_el2_eff(env) & hcrflags) {
return CP_ACCESS_TRAP_EL2; return CP_ACCESS_TRAP_EL2;
} }
break; break;
@ -4295,6 +4293,18 @@ static CPAccessResult aa64_cacheop_pou_access(CPUARMState *env,
return CP_ACCESS_OK; return CP_ACCESS_OK;
} }
static CPAccessResult access_ticab(CPUARMState *env, const ARMCPRegInfo *ri,
bool isread)
{
return do_cacheop_pou_access(env, HCR_TICAB | HCR_TPU);
}
static CPAccessResult access_tocu(CPUARMState *env, const ARMCPRegInfo *ri,
bool isread)
{
return do_cacheop_pou_access(env, HCR_TOCU | HCR_TPU);
}
/* See: D4.7.2 TLB maintenance requirements and the TLB maintenance instructions /* See: D4.7.2 TLB maintenance requirements and the TLB maintenance instructions
* Page D4-1736 (DDI0487A.b) * Page D4-1736 (DDI0487A.b)
*/ */
@ -4935,15 +4945,15 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
{ .name = "IC_IALLUIS", .state = ARM_CP_STATE_AA64, { .name = "IC_IALLUIS", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0, .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0,
.access = PL1_W, .type = ARM_CP_NOP, .access = PL1_W, .type = ARM_CP_NOP,
.accessfn = aa64_cacheop_pou_access }, .accessfn = access_ticab },
{ .name = "IC_IALLU", .state = ARM_CP_STATE_AA64, { .name = "IC_IALLU", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 0, .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 0,
.access = PL1_W, .type = ARM_CP_NOP, .access = PL1_W, .type = ARM_CP_NOP,
.accessfn = aa64_cacheop_pou_access }, .accessfn = access_tocu },
{ .name = "IC_IVAU", .state = ARM_CP_STATE_AA64, { .name = "IC_IVAU", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 5, .opc2 = 1, .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 5, .opc2 = 1,
.access = PL0_W, .type = ARM_CP_NOP, .access = PL0_W, .type = ARM_CP_NOP,
.accessfn = aa64_cacheop_pou_access }, .accessfn = access_tocu },
{ .name = "DC_IVAC", .state = ARM_CP_STATE_AA64, { .name = "DC_IVAC", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 1, .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 1,
.access = PL1_W, .accessfn = aa64_cacheop_poc_access, .access = PL1_W, .accessfn = aa64_cacheop_poc_access,
@ -4961,7 +4971,7 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
{ .name = "DC_CVAU", .state = ARM_CP_STATE_AA64, { .name = "DC_CVAU", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 11, .opc2 = 1, .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 11, .opc2 = 1,
.access = PL0_W, .type = ARM_CP_NOP, .access = PL0_W, .type = ARM_CP_NOP,
.accessfn = aa64_cacheop_pou_access }, .accessfn = access_tocu },
{ .name = "DC_CIVAC", .state = ARM_CP_STATE_AA64, { .name = "DC_CIVAC", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 14, .opc2 = 1, .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 14, .opc2 = 1,
.access = PL0_W, .type = ARM_CP_NOP, .access = PL0_W, .type = ARM_CP_NOP,
@ -5138,13 +5148,13 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
.writefn = tlbiipas2is_hyp_write }, .writefn = tlbiipas2is_hyp_write },
/* 32 bit cache operations */ /* 32 bit cache operations */
{ .name = "ICIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0, { .name = "ICIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0,
.type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_pou_access }, .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_ticab },
{ .name = "BPIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 6, { .name = "BPIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 6,
.type = ARM_CP_NOP, .access = PL1_W }, .type = ARM_CP_NOP, .access = PL1_W },
{ .name = "ICIALLU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 0, { .name = "ICIALLU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 0,
.type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_pou_access }, .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tocu },
{ .name = "ICIMVAU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 1, { .name = "ICIMVAU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 1,
.type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_pou_access }, .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tocu },
{ .name = "BPIALL", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 6, { .name = "BPIALL", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 6,
.type = ARM_CP_NOP, .access = PL1_W }, .type = ARM_CP_NOP, .access = PL1_W },
{ .name = "BPIMVA", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 7, { .name = "BPIMVA", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 7,
@ -5158,7 +5168,7 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
{ .name = "DCCSW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 2, { .name = "DCCSW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 2,
.type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw }, .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw },
{ .name = "DCCMVAU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 11, .opc2 = 1, { .name = "DCCMVAU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 11, .opc2 = 1,
.type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_pou_access }, .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tocu },
{ .name = "DCCIMVAC", .cp = 15, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 1, { .name = "DCCIMVAC", .cp = 15, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 1,
.type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_poc_access }, .type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_poc_access },
{ .name = "DCCISW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2, { .name = "DCCISW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2,