static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri,
bool isread)
{
- /* Only accessible in EL0 if SCTLR.UCT is set (and only in AArch64,
- * but the AArch32 CTR has its own reginfo struct)
- */
- if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UCT)) {
- return CP_ACCESS_TRAP;
+ int cur_el = arm_current_el(env);
+
+ if (cur_el < 2) {
+ uint64_t hcr = arm_hcr_el2_eff(env);
+
+ if (cur_el == 0) {
+ if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
+ if (!(env->cp15.sctlr_el[2] & SCTLR_UCT)) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ } else {
+ if (!(env->cp15.sctlr_el[1] & SCTLR_UCT)) {
+ return CP_ACCESS_TRAP;
+ }
+ if (hcr & HCR_TID2) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ }
+ } else if (hcr & HCR_TID2) {
+ return CP_ACCESS_TRAP_EL2;
+ }
}
if (arm_current_el(env) < 2 && arm_hcr_el2_eff(env) & HCR_TID2) {