xen: arm: handle accesses to CNTP_CVAL_EL0

All OSes we have run on top of Xen use CNTP_TVAL_EL0 but for
completeness we really should handle CVAL too.

In vtimer_emulate_cp64 pull the propagation of the 64-bit result into
two 32-bit registers out of the switch to avoid duplicating for every
register. We also need to initialise x now since previously the only
register implemented register was R/O.

While adding HSR_SYSREG_CNTP_CVAL_EL0 also move
HSR_SYSREG_CNTP_CTL_EL0 so it is sorted correctly.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Reviewed-by: Julien Grall <julien.grall@linaro.org>
This commit is contained in:
Ian Campbell committed 2015-03-31 09:42:18 +01:00
1 parent d306211e21
commit 9cfa8ebe2e
3 files changed
+45 -8

No files matched your search

+2
View File
@@ -1658,6 +1658,7 @@ static void do_cp15_64(struct cpu_user_regs *regs,
switch ( hsr.bits & HSR_CP64_REGS_MASK )
{
case HSR_CPREG64(CNTPCT):
case HSR_CPREG64(CNTP_CVAL):
if ( !vtimer_emulate(regs, hsr) )
goto undef_cp15_64;
break;
@@ -1829,6 +1830,7 @@ static void do_sysreg(struct cpu_user_regs *regs,
break;
case HSR_SYSREG_CNTP_CTL_EL0:
case HSR_SYSREG_CNTP_TVAL_EL0:
case HSR_SYSREG_CNTP_CVAL_EL0:
if ( !vtimer_emulate(regs, hsr) )
goto undef_sysreg;
break;
+41 -7
View File
@@ -219,6 +219,30 @@ static int vtimer_cntp_tval(struct cpu_user_regs *regs, uint32_t *r, int read)
return 1;
}
static int vtimer_cntp_cval(struct cpu_user_regs *regs, uint64_t *r, int read)
{
struct vcpu *v = current;
if ( !ACCESS_ALLOWED(regs, EL0PTEN) )
return 0;
if ( read )
{
*r = ns_to_ticks(v->arch.phys_timer.cval);
}
else
{
v->arch.phys_timer.cval = ticks_to_ns(*r);
if ( v->arch.phys_timer.ctl & CNTx_CTL_ENABLE )
{
v->arch.phys_timer.ctl &= ~CNTx_CTL_PENDING;
set_timer(&v->arch.phys_timer.timer,
v->arch.phys_timer.cval +
v->domain->arch.phys_timer_base.offset);
}
}
return 1;
}
static int vtimer_cntpct(struct cpu_user_regs *regs, uint64_t *r, int read)
{
struct vcpu *v = current;
@@ -270,7 +294,7 @@ static int vtimer_emulate_cp64(struct cpu_user_regs *regs, union hsr hsr)
struct hsr_cp64 cp64 = hsr.cp64;
uint32_t *r1 = (uint32_t *)select_user_reg(regs, cp64.reg1);
uint32_t *r2 = (uint32_t *)select_user_reg(regs, cp64.reg2);
uint64_t x;
uint64_t x = (uint64_t)(*r1) | ((uint64_t)(*r2) << 32);
if ( cp64.read )
perfc_incr(vtimer_cp64_reads);
@@ -282,17 +306,24 @@ static int vtimer_emulate_cp64(struct cpu_user_regs *regs, union hsr hsr)
case HSR_CPREG64(CNTPCT):
if ( !vtimer_cntpct(regs, &x, cp64.read) )
return 0;
break;
if ( cp64.read )
{
*r1 = (uint32_t)(x & 0xffffffff);
*r2 = (uint32_t)(x >> 32);
}
return 1;
case HSR_CPREG64(CNTP_CVAL):
if ( !vtimer_cntp_cval(regs, &x, cp64.read) )
return 0;
break;
default:
return 0;
}
if ( cp64.read )
{
*r1 = (uint32_t)(x & 0xffffffff);
*r2 = (uint32_t)(x >> 32);
}
return 1;
}
#ifdef CONFIG_ARM_64
@@ -322,6 +353,9 @@ static int vtimer_emulate_sysreg(struct cpu_user_regs *regs, union hsr hsr)
*x = r;
return 1;
case HSR_SYSREG_CNTP_CVAL_EL0:
return vtimer_cntp_cval(regs, x, sysreg.read);
case HSR_SYSREG_CNTPCT_EL0:
return vtimer_cntpct(regs, x, sysreg.read);
+2 -1
View File
@@ -100,8 +100,9 @@
#define HSR_SYSREG_PMOVSSET_EL0 HSR_SYSREG(3,3,c9,c14,3)
#define HSR_SYSREG_CNTPCT_EL0 HSR_SYSREG(3,3,c14,c0,0)
#define HSR_SYSREG_CNTP_CTL_EL0 HSR_SYSREG(3,3,c14,c2,1)
#define HSR_SYSREG_CNTP_TVAL_EL0 HSR_SYSREG(3,3,c14,c2,0)
#define HSR_SYSREG_CNTP_CTL_EL0 HSR_SYSREG(3,3,c14,c2,1)
#define HSR_SYSREG_CNTP_CVAL_EL0 HSR_SYSREG(3,3,c14,c2,2)
/*
* GIC System register assembly aliases picked from kernel
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.