Skip to content

Commit

Permalink
KVM: arm/arm64: Emulate the EL1 phys timer registers
Browse files Browse the repository at this point in the history
Emulate read and write operations to CNTP_TVAL, CNTP_CVAL and CNTP_CTL.
Now VMs are able to use the EL1 physical timer.

Signed-off-by: Jintack Lim <[email protected]>
Reviewed-by: Christoffer Dall <[email protected]>
Signed-off-by: Marc Zyngier <[email protected]>
  • Loading branch information
soccertack authored and Marc Zyngier committed Feb 8, 2017
1 parent c9a3c58 commit 7b6b463
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 4 deletions.
37 changes: 34 additions & 3 deletions arch/arm64/kvm/sys_regs.c
Original file line number Diff line number Diff line change
Expand Up @@ -824,23 +824,54 @@ static bool access_cntp_tval(struct kvm_vcpu *vcpu,
struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
kvm_inject_undefined(vcpu);
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
u64 now = kvm_phys_timer_read();

if (p->is_write)
ptimer->cnt_cval = p->regval + now;
else
p->regval = ptimer->cnt_cval - now;

return true;
}

static bool access_cntp_ctl(struct kvm_vcpu *vcpu,
struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
kvm_inject_undefined(vcpu);
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);

if (p->is_write) {
/* ISTATUS bit is read-only */
ptimer->cnt_ctl = p->regval & ~ARCH_TIMER_CTRL_IT_STAT;
} else {
u64 now = kvm_phys_timer_read();

p->regval = ptimer->cnt_ctl;
/*
* Set ISTATUS bit if it's expired.
* Note that according to ARMv8 ARM Issue A.k, ISTATUS bit is
* UNKNOWN when ENABLE bit is 0, so we chose to set ISTATUS bit
* regardless of ENABLE bit for our implementation convenience.
*/
if (ptimer->cnt_cval <= now)
p->regval |= ARCH_TIMER_CTRL_IT_STAT;
}

return true;
}

static bool access_cntp_cval(struct kvm_vcpu *vcpu,
struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
kvm_inject_undefined(vcpu);
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);

if (p->is_write)
ptimer->cnt_cval = p->regval;
else
p->regval = ptimer->cnt_cval;

return true;
}

Expand Down
2 changes: 2 additions & 0 deletions include/kvm/arm_arch_timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx);
void kvm_timer_schedule(struct kvm_vcpu *vcpu);
void kvm_timer_unschedule(struct kvm_vcpu *vcpu);

u64 kvm_phys_timer_read(void);

void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu);

void kvm_timer_init_vhe(void);
Expand Down
2 changes: 1 addition & 1 deletion virt/kvm/arm/arch_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
vcpu_vtimer(vcpu)->active_cleared_last = false;
}

static u64 kvm_phys_timer_read(void)
u64 kvm_phys_timer_read(void)
{
return timecounter->cc->read(timecounter->cc);
}
Expand Down

0 comments on commit 7b6b463

Please sign in to comment.