static void handle_raz_wi(struct cpu_user_regs *regs,
register_t *reg,
bool_t read,
- const union hsr hsr)
+ const union hsr hsr,
+ int min_el)
{
+ ASSERT((min_el == 0) || (min_el == 1));
+
+ if ( min_el > 0 && psr_mode_is_user(regs) )
+ return inject_undef_exception(regs, hsr);
+
if ( read )
*reg = 0;
/* else: write ignored */
static void handle_wo_wi(struct cpu_user_regs *regs,
register_t *reg,
bool_t read,
- const union hsr hsr)
+ const union hsr hsr,
+ int min_el)
{
+ ASSERT((min_el == 0) || (min_el == 1));
+
+ if ( min_el > 0 && psr_mode_is_user(regs) )
+ return inject_undef_exception(regs, hsr);
+
if ( read )
return inject_undef_exception(regs, hsr);
/* else: ignore */
static void handle_ro_raz(struct cpu_user_regs *regs,
register_t *reg,
bool_t read,
- const union hsr hsr)
+ const union hsr hsr,
+ int min_el)
{
+ ASSERT((min_el == 0) || (min_el == 1));
+
+ if ( min_el > 0 && psr_mode_is_user(regs) )
+ return inject_undef_exception(regs, hsr);
+
if ( !read )
return inject_undef_exception(regs, hsr);
/* else: raz */
*/
case HSR_CPREG32(PMUSERENR):
/* RO at EL0. RAZ/WI at EL1 */
- if ( psr_mode_is_user(regs) && !hsr.cp32.read )
- return inject_undef_exception(regs, hsr);
- return handle_raz_wi(regs, r, cp32.read, hsr);
+ if ( psr_mode_is_user(regs) )
+ return handle_ro_raz(regs, r, cp32.read, hsr, 0);
+ else
+ return handle_raz_wi(regs, r, cp32.read, hsr, 1);
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) )
- return inject_undef_exception(regs, hsr);
- return handle_raz_wi(regs, r, cp32.read, hsr);
+ return handle_raz_wi(regs, r, cp32.read, hsr, 1);
case HSR_CPREG32(PMCR):
case HSR_CPREG32(PMCNTENSET):
case HSR_CPREG32(PMCNTENCLR):
* Accessible at EL0 only if PMUSERENR_EL0.EN is set. We
* emulate that register as 0 above.
*/
- if ( psr_mode_is_user(regs) )
- return inject_undef_exception(regs, hsr);
- return handle_raz_wi(regs, r, cp32.read, hsr);
+ return handle_raz_wi(regs, r, cp32.read, hsr, 1);
default:
gdprintk(XENLOG_ERR,
* Read-only register. Accessible by EL0 if DBGDSCRext.UDCCdis
* is set to 0, which we emulated below.
*/
- return handle_ro_raz(regs, r, cp32.read, hsr);
+ return handle_ro_raz(regs, r, cp32.read, hsr, 1);
case HSR_CPREG32(DBGDSCREXT):
- if ( usr_mode(regs) )
- return inject_undef_exception(regs, hsr);
-
/*
* Implement debug status and control register as RAZ/WI.
* The OS won't use Hardware debug if MDBGen not set.
*/
- return handle_raz_wi(regs, r, cp32.read, hsr);
+ return handle_raz_wi(regs, r, cp32.read, hsr, 1);
case HSR_CPREG32(DBGVCR):
case HSR_CPREG32(DBGBVR0):
case HSR_CPREG32(DBGBVR1):
case HSR_CPREG32(DBGBCR1):
case HSR_CPREG32(DBGOSDLR):
- if ( usr_mode(regs) )
- return inject_undef_exception(regs, hsr);
- return handle_raz_wi(regs, r, cp32.read, hsr);
+ return handle_raz_wi(regs, r, cp32.read, hsr, 1);
case HSR_CPREG32(DBGOSLAR):
- if ( usr_mode(regs) )
- return inject_undef_exception(regs, hsr);
- return handle_wo_wi(regs, r, cp32.read, hsr);
+ return handle_wo_wi(regs, r, cp32.read, hsr, 1);
default:
gdprintk(XENLOG_ERR,
"%s p14, %d, r%d, cr%d, cr%d, %d @ 0x%"PRIregister"\n",
* Accessible from EL1 only, but if EL0 trap happens handle as
* undef.
*/
- if ( psr_mode_is_user(regs) )
- return inject_undef_exception(regs, hsr);
- return handle_raz_wi(regs, x, hsr.sysreg.read, hsr);
+ return handle_raz_wi(regs, x, hsr.sysreg.read, hsr, 1);
case HSR_SYSREG_MDCCSR_EL0:
/*
* Accessible at EL0 only if MDSCR_EL1.TDCC is set to 0. We emulate that
* register as RAZ/WI above. So RO at both EL0 and EL1.
*/
- return handle_ro_raz(regs, x, hsr.sysreg.read, hsr);
+ return handle_ro_raz(regs, x, hsr.sysreg.read, hsr, 0);
/* - Perf monitors */
case HSR_SYSREG_PMUSERENR_EL0:
/* RO at EL0. RAZ/WI at EL1 */
- if ( psr_mode_is_user(regs) && !hsr.sysreg.read )
- return inject_undef_exception(regs, hsr);
- return handle_raz_wi(regs, x, hsr.sysreg.read, hsr);
+ if ( psr_mode_is_user(regs) )
+ return handle_ro_raz(regs, x, hsr.sysreg.read, hsr, 0);
+ else
+ return handle_raz_wi(regs, x, hsr.sysreg.read, hsr, 1);
case HSR_SYSREG_PMCR_EL0:
case HSR_SYSREG_PMCNTENSET_EL0:
case HSR_SYSREG_PMCNTENCLR_EL0:
* Accessible at EL0 only if PMUSERENR_EL0.EN is set. We
* emulate that register as 0 above.
*/
- if ( psr_mode_is_user(regs) )
- return inject_undef_exception(regs, hsr);
- return handle_raz_wi(regs, x, hsr.sysreg.read, hsr);
+ return handle_raz_wi(regs, x, hsr.sysreg.read, hsr, 1);
/* Write only, Write ignore registers: */
case HSR_SYSREG_OSLAR_EL1:
- return handle_wo_wi(regs, x, hsr.sysreg.read, hsr);
+ return handle_wo_wi(regs, x, hsr.sysreg.read, hsr, 1);
case HSR_SYSREG_CNTP_CTL_EL0:
case HSR_SYSREG_CNTP_TVAL_EL0: