target/arm: Implement MDCR_EL2.TDCC and MDCR_EL3.TDCC traps
FEAT_FGT also implements an extra trap bit in the MDCR_EL2 and MDCR_EL3 registers: bit TDCC enables trapping of use of the Debug Comms Channel registers OSDTRRX_EL1, OSDTRTX_EL1, MDCCSR_EL0, MDCCINT_EL0, DBGDTR_EL0, DBGDTRRX_EL0 and DBGDTRTX_EL0 (and their AArch32 equivalents). This trapping is independent of whether fine-grained traps are enabled or not. Implement these extra traps. (We don't implement DBGDTR_EL0, DBGDTRRX_EL0 and DBGDTRTX_EL0.) Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Tested-by: Fuad Tabba <tabba@google.com> Message-id: 20230130182459.3309057-23-peter.maydell@linaro.org Message-id: 20230127175507.2895013-23-peter.maydell@linaro.org
This commit is contained in:
parent
34a8a07e57
commit
1748ef03c5
@ -599,6 +599,33 @@ static CPAccessResult access_tda(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
return CP_ACCESS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for traps to Debug Comms Channel registers. If FEAT_FGT
|
||||
* is implemented then these are controlled by MDCR_EL2.TDCC for
|
||||
* EL2 and MDCR_EL3.TDCC for EL3. They are also controlled by
|
||||
* the general debug access trap bits MDCR_EL2.TDA and MDCR_EL3.TDA.
|
||||
*/
|
||||
static CPAccessResult access_tdcc(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
bool isread)
|
||||
{
|
||||
int el = arm_current_el(env);
|
||||
uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
|
||||
bool mdcr_el2_tda = (mdcr_el2 & MDCR_TDA) || (mdcr_el2 & MDCR_TDE) ||
|
||||
(arm_hcr_el2_eff(env) & HCR_TGE);
|
||||
bool mdcr_el2_tdcc = cpu_isar_feature(aa64_fgt, env_archcpu(env)) &&
|
||||
(mdcr_el2 & MDCR_TDCC);
|
||||
bool mdcr_el3_tdcc = cpu_isar_feature(aa64_fgt, env_archcpu(env)) &&
|
||||
(env->cp15.mdcr_el3 & MDCR_TDCC);
|
||||
|
||||
if (el < 2 && (mdcr_el2_tda || mdcr_el2_tdcc)) {
|
||||
return CP_ACCESS_TRAP_EL2;
|
||||
}
|
||||
if (el < 3 && ((env->cp15.mdcr_el3 & MDCR_TDA) || mdcr_el3_tdcc)) {
|
||||
return CP_ACCESS_TRAP_EL3;
|
||||
}
|
||||
return CP_ACCESS_OK;
|
||||
}
|
||||
|
||||
static void oslar_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
uint64_t value)
|
||||
{
|
||||
@ -681,7 +708,7 @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
|
||||
*/
|
||||
{ .name = "MDCCSR_EL0", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 2, .opc1 = 3, .crn = 0, .crm = 1, .opc2 = 0,
|
||||
.access = PL0_R, .accessfn = access_tda,
|
||||
.access = PL0_R, .accessfn = access_tdcc,
|
||||
.type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
/*
|
||||
* OSDTRRX_EL1/OSDTRTX_EL1 are used for save and restore of DBGDTRRX_EL0.
|
||||
@ -689,11 +716,11 @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
|
||||
*/
|
||||
{ .name = "OSDTRRX_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14,
|
||||
.opc0 = 2, .opc1 = 0, .crn = 0, .crm = 0, .opc2 = 2,
|
||||
.access = PL1_RW, .accessfn = access_tda,
|
||||
.access = PL1_RW, .accessfn = access_tdcc,
|
||||
.type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
{ .name = "OSDTRTX_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14,
|
||||
.opc0 = 2, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2,
|
||||
.access = PL1_RW, .accessfn = access_tda,
|
||||
.access = PL1_RW, .accessfn = access_tdcc,
|
||||
.type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
/*
|
||||
* OSECCR_EL1 provides a mechanism for an operating system
|
||||
@ -757,7 +784,7 @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
|
||||
*/
|
||||
{ .name = "MDCCINT_EL1", .state = ARM_CP_STATE_BOTH,
|
||||
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
|
||||
.access = PL1_RW, .accessfn = access_tda,
|
||||
.access = PL1_RW, .accessfn = access_tdcc,
|
||||
.type = ARM_CP_NOP },
|
||||
/*
|
||||
* Dummy DBGCLAIM registers.
|
||||
|
Loading…
Reference in New Issue
Block a user