target/arm: Trap PMCR when MDCR_EL2.TPMCR is set
Trap PMCR_EL0 or PMCR accesses to EL2 when MDCR_EL2.TPMCR is set. Similar to MDCR_EL2.TPM, MDCR_EL2.TPMCR allows trapping EL0 and EL1 accesses to the PMCR register to EL2. Cc: qemu-stable@nongnu.org Signed-off-by: Smail AIDER <smail.aider@huawei.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20250811112143.1577055-2-smail.aider@huawei.com Message-Id: <20250722131925.2119169-1-smail.aider@huawei.com> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
376cdd7e9c
commit
186db6a73b
1 changed files with 26 additions and 8 deletions
|
|
@ -228,22 +228,27 @@ static bool event_supported(uint16_t number)
|
|||
return supported_event_map[number] != UNSUPPORTED_EVENT;
|
||||
}
|
||||
|
||||
static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
bool isread)
|
||||
static CPAccessResult do_pmreg_access(CPUARMState *env, bool is_pmcr)
|
||||
{
|
||||
/*
|
||||
* Performance monitor registers user accessibility is controlled
|
||||
* by PMUSERENR. MDCR_EL2.TPM and MDCR_EL3.TPM allow configurable
|
||||
* by PMUSERENR. MDCR_EL2.TPM/TPMCR and MDCR_EL3.TPM allow configurable
|
||||
* trapping to EL2 or EL3 for other accesses.
|
||||
*/
|
||||
int el = arm_current_el(env);
|
||||
uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
|
||||
|
||||
if (el == 0 && !(env->cp15.c9_pmuserenr & 1)) {
|
||||
return CP_ACCESS_TRAP_EL1;
|
||||
}
|
||||
if (el < 2 && (mdcr_el2 & MDCR_TPM)) {
|
||||
return CP_ACCESS_TRAP_EL2;
|
||||
if (el < 2) {
|
||||
uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
|
||||
|
||||
if (mdcr_el2 & MDCR_TPM) {
|
||||
return CP_ACCESS_TRAP_EL2;
|
||||
}
|
||||
if (is_pmcr && (mdcr_el2 & MDCR_TPMCR)) {
|
||||
return CP_ACCESS_TRAP_EL2;
|
||||
}
|
||||
}
|
||||
if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TPM)) {
|
||||
return CP_ACCESS_TRAP_EL3;
|
||||
|
|
@ -252,6 +257,19 @@ static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri,
|
|||
return CP_ACCESS_OK;
|
||||
}
|
||||
|
||||
static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
bool isread)
|
||||
{
|
||||
return do_pmreg_access(env, false);
|
||||
}
|
||||
|
||||
static CPAccessResult pmreg_access_pmcr(CPUARMState *env,
|
||||
const ARMCPRegInfo *ri,
|
||||
bool isread)
|
||||
{
|
||||
return do_pmreg_access(env, true);
|
||||
}
|
||||
|
||||
static CPAccessResult pmreg_access_xevcntr(CPUARMState *env,
|
||||
const ARMCPRegInfo *ri,
|
||||
bool isread)
|
||||
|
|
@ -1187,14 +1205,14 @@ void define_pm_cpregs(ARMCPU *cpu)
|
|||
.fgt = FGT_PMCR_EL0,
|
||||
.type = ARM_CP_IO | ARM_CP_ALIAS,
|
||||
.fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcr),
|
||||
.accessfn = pmreg_access,
|
||||
.accessfn = pmreg_access_pmcr,
|
||||
.readfn = pmcr_read, .raw_readfn = raw_read,
|
||||
.writefn = pmcr_write, .raw_writefn = raw_write,
|
||||
};
|
||||
const ARMCPRegInfo pmcr64 = {
|
||||
.name = "PMCR_EL0", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 0,
|
||||
.access = PL0_RW, .accessfn = pmreg_access,
|
||||
.access = PL0_RW, .accessfn = pmreg_access_pmcr,
|
||||
.fgt = FGT_PMCR_EL0,
|
||||
.type = ARM_CP_IO,
|
||||
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue