case HSR_CPREG32(CNTP_CTL):
case HSR_CPREG32(CNTP_TVAL):
if ( !vtimer_emulate(regs, hsr) )
- {
- dprintk(XENLOG_ERR,
- "failed emulation of 32-bit vtimer CP register access\n");
- domain_crash_synchronous();
- }
+ goto undef_cp15_32;
break;
case HSR_CPREG32(ACTLR):
if ( cp32.read )
cp32.op1, cp32.reg, cp32.crn, cp32.crm, cp32.op2, regs->pc);
gdprintk(XENLOG_ERR, "unhandled 32-bit CP15 access %#x\n",
hsr.bits & HSR_CP32_REGS_MASK);
+ undef_cp15_32:
inject_undef_exception(regs, hsr.len);
return;
}
{
case HSR_CPREG64(CNTPCT):
if ( !vtimer_emulate(regs, hsr) )
- {
- dprintk(XENLOG_ERR,
- "failed emulation of 64-bit vtimer CP register access\n");
- domain_crash_synchronous();
- }
+ goto undef_cp15_64;
break;
default:
{
cp64.op1, cp64.reg1, cp64.reg2, cp64.crm, regs->pc);
gdprintk(XENLOG_ERR, "unhandled 64-bit CP15 access %#x\n",
hsr.bits & HSR_CP64_REGS_MASK);
+ undef_cp15_64:
inject_undef_exception(regs, hsr.len);
return;
}
case HSR_SYSREG_CNTP_CTL_EL0:
case HSR_SYSREG_CNTP_TVAL_EL0:
if ( !vtimer_emulate(regs, hsr) )
- {
- dprintk(XENLOG_ERR,
- "failed emulation of 64-bit vtimer sysreg access\n");
- domain_crash_synchronous();
- }
+ goto undef_sysreg;
break;
case HSR_SYSREG_ICC_SGI1R_EL1:
if ( !vgic_emulate(regs, hsr) )
sysreg.reg, regs->pc);
gdprintk(XENLOG_ERR, "unhandled 64-bit sysreg access %#x\n",
hsr.bits & HSR_SYSREG_REGS_MASK);
-
- inject_undef_exception(regs, sysreg.len);
+ undef_sysreg:
+ inject_undef_exception(regs, hsr.sysreg.len);
return;
}
}
do_cp15_32(regs, hsr);
break;
case HSR_EC_CP15_64:
- if ( !is_32bit_domain(current->domain) )
- goto bad_trap;
+ BUG_ON(!psr_mode_is_32bit(regs->cpsr));
perfc_incr(trap_cp15_64);
do_cp15_64(regs, hsr);
break;
extern s_time_t ticks_to_ns(uint64_t ticks);
extern uint64_t ns_to_ticks(s_time_t ns);
+/*
+ * Check if regs is allowed access, user_gate is tail end of a
+ * CNTKCTL_EL1_ bit name which gates user access
+ */
+#define ACCESS_ALLOWED(regs, user_gate) \
+ ( !psr_mode_is_user(regs) || \
+ (READ_SYSREG(CNTKCTL_EL1) & CNTKCTL_EL1_##user_gate) )
+
static void phys_timer_expired(void *data)
{
struct vtimer *t = data;
return 0;
}
-static void vtimer_cntp_ctl(struct cpu_user_regs *regs, uint32_t *r, int read)
+static int vtimer_cntp_ctl(struct cpu_user_regs *regs, uint32_t *r, int read)
{
struct vcpu *v = current;
+
+ if ( !ACCESS_ALLOWED(regs, EL0PTEN) )
+ return 0;
+
if ( read )
{
*r = v->arch.phys_timer.ctl;
else
stop_timer(&v->arch.phys_timer.timer);
}
+ return 1;
}
-static void vtimer_cntp_tval(struct cpu_user_regs *regs, uint32_t *r, int read)
+static int vtimer_cntp_tval(struct cpu_user_regs *regs, uint32_t *r, int read)
{
struct vcpu *v = current;
s_time_t now;
+ if ( !ACCESS_ALLOWED(regs, EL0PTEN) )
+ return 0;
+
now = NOW() - v->domain->arch.phys_timer_base.offset;
if ( read )
v->domain->arch.phys_timer_base.offset);
}
}
+ return 1;
}
static int vtimer_cntpct(struct cpu_user_regs *regs, uint64_t *r, int read)
if ( read )
{
+ if ( !ACCESS_ALLOWED(regs, EL0PCTEN) )
+ return 0;
now = NOW() - v->domain->arch.phys_timer_base.offset;
ticks = ns_to_ticks(now);
*r = ticks;
switch ( hsr.bits & HSR_CP32_REGS_MASK )
{
case HSR_CPREG32(CNTP_CTL):
- vtimer_cntp_ctl(regs, r, cp32.read);
- return 1;
+ return vtimer_cntp_ctl(regs, r, cp32.read);
case HSR_CPREG32(CNTP_TVAL):
- vtimer_cntp_tval(regs, r, cp32.read);
- return 1;
+ return vtimer_cntp_tval(regs, r, cp32.read);
default:
return 0;
switch ( hsr.bits & HSR_CP64_REGS_MASK )
{
case HSR_CPREG64(CNTPCT):
- if (!vtimer_cntpct(regs, &x, cp64.read))
+ if ( !vtimer_cntpct(regs, &x, cp64.read) )
return 0;
if ( cp64.read )
switch ( hsr.bits & HSR_SYSREG_REGS_MASK )
{
case HSR_SYSREG_CNTP_CTL_EL0:
- vtimer_cntp_ctl(regs, &r, sysreg.read);
+ if ( !vtimer_cntp_ctl(regs, &r, sysreg.read) )
+ return 0;
if ( sysreg.read )
*x = r;
return 1;
case HSR_SYSREG_CNTP_TVAL_EL0:
- vtimer_cntp_tval(regs, &r, sysreg.read);
+ if ( !vtimer_cntp_tval(regs, &r, sysreg.read) )
+ return 0;
if ( sysreg.read )
*x = r;
return 1;
switch (hsr.ec) {
case HSR_EC_CP15_32:
- if ( !is_32bit_domain(current->domain) )
- return 0;
return vtimer_emulate_cp32(regs, hsr);
case HSR_EC_CP15_64:
- if ( !is_32bit_domain(current->domain) )
- return 0;
return vtimer_emulate_cp64(regs, hsr);
#ifdef CONFIG_ARM_64
case HSR_EC_SYSREG:
- if ( is_32bit_domain(current->domain) )
- return 0;
return vtimer_emulate_sysreg(regs, hsr);
#endif
default: