[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v5 09/15] xen: arm: Handle CP15 register traps from userspace
Previously userspace access to PM* would have been incorrectly (but benignly) implemented as RAZ/WI when running on a 32-bit kernel and would cause a hypervisor exception (host crash) when running a 64-bit kernel (this was already solved via the fix to XSA-102). PMINTENSET, PMINTENCLR are EL1 only, but it is not clear whether attempts to access from EL0 will trap to EL1 or EL2, be conservative and handle EL0 access with an undef injection. ACTLR is EL1 only and the ARM ARM states that HCR_EL2.TACR causes accesses from EL1 to trap. However remain conservative even here and handle accesses from EL0 by injecting an undef injection. PMUSERENR is R/O at EL0 and we implement as RAZ/WI at EL1 as before. The remaining PM* registers are accessible to EL0 only if PMUSERENR_EL0.EN is set, since we emulate this as RAZ/WI the bit is never set so we inject a trap on attempted access. We weren't previously handling PMCCNTR. HSR_EC_CP15_32 should never be seen from a 64-bit guest, so BUG_ON if that occurs. Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx> Reviewed-by: Julien Grall <julien.grall@xxxxxxxxxx> --- v4: - Handle the possibility of PMINTEN{SET,CLR}_EL1, ACTLR trapping from EL0 as well, by injecting an undef. - No longer handle/mention CLIDR, CCSIDR, DCCISW. --- xen/arch/arm/traps.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index d296f50..c81eaa3 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -1570,6 +1570,8 @@ static void do_cp15_32(struct cpu_user_regs *regs, goto undef_cp15_32; break; case HSR_CPREG32(ACTLR): + if ( psr_mode_is_user(regs) ) + goto undef_cp15_32; if ( cp32.read ) *r = v->arch.actlr; break; @@ -1582,6 +1584,18 @@ static void do_cp15_32(struct cpu_user_regs *regs, * always support PMCCNTR (the cyle counter): we just RAZ/WI for all * PM register, which doesn't crash the kernel at least */ + case HSR_CPREG32(PMUSERENR): + /* RO at EL0. RAZ/WI at EL1 */ + if ( psr_mode_is_user(regs) && !hsr.cp32.read ) + goto undef_cp15_32; + goto cp15_32_raz_wi; + + case HSR_CPREG32(PMINTENSET): + case HSR_CPREG32(PMINTENCLR): + /* EL1 only, however MDCR_EL2.TPM==1 means EL0 may trap here also. */ + if ( psr_mode_is_user(regs) ) + goto undef_cp15_32; + goto cp15_32_raz_wi; case HSR_CPREG32(PMCR): case HSR_CPREG32(PMCNTENSET): case HSR_CPREG32(PMCNTENCLR): @@ -1593,12 +1607,17 @@ static void do_cp15_32(struct cpu_user_regs *regs, case HSR_CPREG32(PMCCNTR): case HSR_CPREG32(PMXEVTYPER): case HSR_CPREG32(PMXEVCNTR): - case HSR_CPREG32(PMUSERENR): - case HSR_CPREG32(PMINTENSET): - case HSR_CPREG32(PMINTENCLR): case HSR_CPREG32(PMOVSSET): + /* + * Accessible at EL0 only if PMUSERENR_EL0.EN is set. We + * emulate that register as 0 above. + */ + if ( psr_mode_is_user(regs) ) + goto undef_cp15_32; + cp15_32_raz_wi: if ( cp32.read ) *r = 0; + /* else: write ignored */ break; default: @@ -2003,8 +2022,7 @@ asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs) advance_pc(regs, hsr); break; case HSR_EC_CP15_32: - if ( !is_32bit_domain(current->domain) ) - goto bad_trap; + BUG_ON(!psr_mode_is_32bit(regs->cpsr)); perfc_incr(trap_cp15_32); do_cp15_32(regs, hsr); break; -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |