Commit 41ce82f6 authored by Marc Zyngier's avatar Marc Zyngier

KVM: arm64: timers: Move timer registers to the sys_regs file

Move the timer gsisters to the sysreg file. This will further help when
they are directly changed by a nesting hypervisor in the VNCR page.

This requires moving the initialisation of the timer struct so that some
of the helpers (such as arch_timer_ctx_index) can work correctly at an
early stage.
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parent 3c5ff0c6
...@@ -189,6 +189,12 @@ enum vcpu_sysreg { ...@@ -189,6 +189,12 @@ enum vcpu_sysreg {
SP_EL1, SP_EL1,
SPSR_EL1, SPSR_EL1,
CNTVOFF_EL2,
CNTV_CVAL_EL0,
CNTV_CTL_EL0,
CNTP_CVAL_EL0,
CNTP_CTL_EL0,
/* 32bit specific registers. Keep them at the end of the range */ /* 32bit specific registers. Keep them at the end of the range */
DACR32_EL2, /* Domain Access Control Register */ DACR32_EL2, /* Domain Access Control Register */
IFSR32_EL2, /* Instruction Fault Status Register */ IFSR32_EL2, /* Instruction Fault Status Register */
......
...@@ -51,6 +51,93 @@ static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu, ...@@ -51,6 +51,93 @@ static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu,
struct arch_timer_context *timer, struct arch_timer_context *timer,
enum kvm_arch_timer_regs treg); enum kvm_arch_timer_regs treg);
u32 timer_get_ctl(struct arch_timer_context *ctxt)
{
struct kvm_vcpu *vcpu = ctxt->vcpu;
switch(arch_timer_ctx_index(ctxt)) {
case TIMER_VTIMER:
return __vcpu_sys_reg(vcpu, CNTV_CTL_EL0);
case TIMER_PTIMER:
return __vcpu_sys_reg(vcpu, CNTP_CTL_EL0);
default:
WARN_ON(1);
return 0;
}
}
u64 timer_get_cval(struct arch_timer_context *ctxt)
{
struct kvm_vcpu *vcpu = ctxt->vcpu;
switch(arch_timer_ctx_index(ctxt)) {
case TIMER_VTIMER:
return __vcpu_sys_reg(vcpu, CNTV_CVAL_EL0);
case TIMER_PTIMER:
return __vcpu_sys_reg(vcpu, CNTP_CVAL_EL0);
default:
WARN_ON(1);
return 0;
}
}
static u64 timer_get_offset(struct arch_timer_context *ctxt)
{
struct kvm_vcpu *vcpu = ctxt->vcpu;
switch(arch_timer_ctx_index(ctxt)) {
case TIMER_VTIMER:
return __vcpu_sys_reg(vcpu, CNTVOFF_EL2);
default:
return 0;
}
}
static void timer_set_ctl(struct arch_timer_context *ctxt, u32 ctl)
{
struct kvm_vcpu *vcpu = ctxt->vcpu;
switch(arch_timer_ctx_index(ctxt)) {
case TIMER_VTIMER:
__vcpu_sys_reg(vcpu, CNTV_CTL_EL0) = ctl;
break;
case TIMER_PTIMER:
__vcpu_sys_reg(vcpu, CNTP_CTL_EL0) = ctl;
break;
default:
WARN_ON(1);
}
}
static void timer_set_cval(struct arch_timer_context *ctxt, u64 cval)
{
struct kvm_vcpu *vcpu = ctxt->vcpu;
switch(arch_timer_ctx_index(ctxt)) {
case TIMER_VTIMER:
__vcpu_sys_reg(vcpu, CNTV_CVAL_EL0) = cval;
break;
case TIMER_PTIMER:
__vcpu_sys_reg(vcpu, CNTP_CVAL_EL0) = cval;
break;
default:
WARN_ON(1);
}
}
static void timer_set_offset(struct arch_timer_context *ctxt, u64 offset)
{
struct kvm_vcpu *vcpu = ctxt->vcpu;
switch(arch_timer_ctx_index(ctxt)) {
case TIMER_VTIMER:
__vcpu_sys_reg(vcpu, CNTVOFF_EL2) = offset;
break;
default:
WARN(offset, "timer %ld\n", arch_timer_ctx_index(ctxt));
}
}
u64 kvm_phys_timer_read(void) u64 kvm_phys_timer_read(void)
{ {
return timecounter->cc->read(timecounter->cc); return timecounter->cc->read(timecounter->cc);
...@@ -124,8 +211,8 @@ static u64 kvm_timer_compute_delta(struct arch_timer_context *timer_ctx) ...@@ -124,8 +211,8 @@ static u64 kvm_timer_compute_delta(struct arch_timer_context *timer_ctx)
{ {
u64 cval, now; u64 cval, now;
cval = timer_ctx->cnt_cval; cval = timer_get_cval(timer_ctx);
now = kvm_phys_timer_read() - timer_ctx->cntvoff; now = kvm_phys_timer_read() - timer_get_offset(timer_ctx);
if (now < cval) { if (now < cval) {
u64 ns; u64 ns;
...@@ -144,8 +231,8 @@ static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx) ...@@ -144,8 +231,8 @@ static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx)
{ {
WARN_ON(timer_ctx && timer_ctx->loaded); WARN_ON(timer_ctx && timer_ctx->loaded);
return timer_ctx && return timer_ctx &&
!(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_IT_MASK) && ((timer_get_ctl(timer_ctx) &
(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_ENABLE); (ARCH_TIMER_CTRL_IT_MASK | ARCH_TIMER_CTRL_ENABLE)) == ARCH_TIMER_CTRL_ENABLE);
} }
/* /*
...@@ -256,8 +343,8 @@ static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx) ...@@ -256,8 +343,8 @@ static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx)
if (!kvm_timer_irq_can_fire(timer_ctx)) if (!kvm_timer_irq_can_fire(timer_ctx))
return false; return false;
cval = timer_ctx->cnt_cval; cval = timer_get_cval(timer_ctx);
now = kvm_phys_timer_read() - timer_ctx->cntvoff; now = kvm_phys_timer_read() - timer_get_offset(timer_ctx);
return cval <= now; return cval <= now;
} }
...@@ -350,8 +437,8 @@ static void timer_save_state(struct arch_timer_context *ctx) ...@@ -350,8 +437,8 @@ static void timer_save_state(struct arch_timer_context *ctx)
switch (index) { switch (index) {
case TIMER_VTIMER: case TIMER_VTIMER:
ctx->cnt_ctl = read_sysreg_el0(SYS_CNTV_CTL); timer_set_ctl(ctx, read_sysreg_el0(SYS_CNTV_CTL));
ctx->cnt_cval = read_sysreg_el0(SYS_CNTV_CVAL); timer_set_cval(ctx, read_sysreg_el0(SYS_CNTV_CVAL));
/* Disable the timer */ /* Disable the timer */
write_sysreg_el0(0, SYS_CNTV_CTL); write_sysreg_el0(0, SYS_CNTV_CTL);
...@@ -359,8 +446,8 @@ static void timer_save_state(struct arch_timer_context *ctx) ...@@ -359,8 +446,8 @@ static void timer_save_state(struct arch_timer_context *ctx)
break; break;
case TIMER_PTIMER: case TIMER_PTIMER:
ctx->cnt_ctl = read_sysreg_el0(SYS_CNTP_CTL); timer_set_ctl(ctx, read_sysreg_el0(SYS_CNTP_CTL));
ctx->cnt_cval = read_sysreg_el0(SYS_CNTP_CVAL); timer_set_cval(ctx, read_sysreg_el0(SYS_CNTP_CVAL));
/* Disable the timer */ /* Disable the timer */
write_sysreg_el0(0, SYS_CNTP_CTL); write_sysreg_el0(0, SYS_CNTP_CTL);
...@@ -429,14 +516,14 @@ static void timer_restore_state(struct arch_timer_context *ctx) ...@@ -429,14 +516,14 @@ static void timer_restore_state(struct arch_timer_context *ctx)
switch (index) { switch (index) {
case TIMER_VTIMER: case TIMER_VTIMER:
write_sysreg_el0(ctx->cnt_cval, SYS_CNTV_CVAL); write_sysreg_el0(timer_get_cval(ctx), SYS_CNTV_CVAL);
isb(); isb();
write_sysreg_el0(ctx->cnt_ctl, SYS_CNTV_CTL); write_sysreg_el0(timer_get_ctl(ctx), SYS_CNTV_CTL);
break; break;
case TIMER_PTIMER: case TIMER_PTIMER:
write_sysreg_el0(ctx->cnt_cval, SYS_CNTP_CVAL); write_sysreg_el0(timer_get_cval(ctx), SYS_CNTP_CVAL);
isb(); isb();
write_sysreg_el0(ctx->cnt_ctl, SYS_CNTP_CTL); write_sysreg_el0(timer_get_ctl(ctx), SYS_CNTP_CTL);
break; break;
case NR_KVM_TIMERS: case NR_KVM_TIMERS:
BUG(); BUG();
...@@ -528,7 +615,7 @@ void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu) ...@@ -528,7 +615,7 @@ void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu)
kvm_timer_vcpu_load_nogic(vcpu); kvm_timer_vcpu_load_nogic(vcpu);
} }
set_cntvoff(map.direct_vtimer->cntvoff); set_cntvoff(timer_get_offset(map.direct_vtimer));
kvm_timer_unblocking(vcpu); kvm_timer_unblocking(vcpu);
...@@ -639,8 +726,8 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu) ...@@ -639,8 +726,8 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu)
* resets the timer to be disabled and unmasked and is compliant with * resets the timer to be disabled and unmasked and is compliant with
* the ARMv7 architecture. * the ARMv7 architecture.
*/ */
vcpu_vtimer(vcpu)->cnt_ctl = 0; timer_set_ctl(vcpu_vtimer(vcpu), 0);
vcpu_ptimer(vcpu)->cnt_ctl = 0; timer_set_ctl(vcpu_ptimer(vcpu), 0);
if (timer->enabled) { if (timer->enabled) {
kvm_timer_update_irq(vcpu, false, vcpu_vtimer(vcpu)); kvm_timer_update_irq(vcpu, false, vcpu_vtimer(vcpu));
...@@ -668,13 +755,13 @@ static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff) ...@@ -668,13 +755,13 @@ static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff)
mutex_lock(&kvm->lock); mutex_lock(&kvm->lock);
kvm_for_each_vcpu(i, tmp, kvm) kvm_for_each_vcpu(i, tmp, kvm)
vcpu_vtimer(tmp)->cntvoff = cntvoff; timer_set_offset(vcpu_vtimer(tmp), cntvoff);
/* /*
* When called from the vcpu create path, the CPU being created is not * When called from the vcpu create path, the CPU being created is not
* included in the loop above, so we just set it here as well. * included in the loop above, so we just set it here as well.
*/ */
vcpu_vtimer(vcpu)->cntvoff = cntvoff; timer_set_offset(vcpu_vtimer(vcpu), cntvoff);
mutex_unlock(&kvm->lock); mutex_unlock(&kvm->lock);
} }
...@@ -684,9 +771,12 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) ...@@ -684,9 +771,12 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
vtimer->vcpu = vcpu;
ptimer->vcpu = vcpu;
/* Synchronize cntvoff across all vtimers of a VM. */ /* Synchronize cntvoff across all vtimers of a VM. */
update_vtimer_cntvoff(vcpu, kvm_phys_timer_read()); update_vtimer_cntvoff(vcpu, kvm_phys_timer_read());
ptimer->cntvoff = 0; timer_set_offset(ptimer, 0);
hrtimer_init(&timer->bg_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_HARD); hrtimer_init(&timer->bg_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_HARD);
timer->bg_timer.function = kvm_bg_timer_expire; timer->bg_timer.function = kvm_bg_timer_expire;
...@@ -704,9 +794,6 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) ...@@ -704,9 +794,6 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
vtimer->host_timer_irq_flags = host_vtimer_irq_flags; vtimer->host_timer_irq_flags = host_vtimer_irq_flags;
ptimer->host_timer_irq_flags = host_ptimer_irq_flags; ptimer->host_timer_irq_flags = host_ptimer_irq_flags;
vtimer->vcpu = vcpu;
ptimer->vcpu = vcpu;
} }
static void kvm_timer_init_interrupt(void *info) static void kvm_timer_init_interrupt(void *info)
...@@ -756,10 +843,12 @@ static u64 read_timer_ctl(struct arch_timer_context *timer) ...@@ -756,10 +843,12 @@ static u64 read_timer_ctl(struct arch_timer_context *timer)
* UNKNOWN when ENABLE bit is 0, so we chose to set ISTATUS bit * UNKNOWN when ENABLE bit is 0, so we chose to set ISTATUS bit
* regardless of ENABLE bit for our implementation convenience. * regardless of ENABLE bit for our implementation convenience.
*/ */
u32 ctl = timer_get_ctl(timer);
if (!kvm_timer_compute_delta(timer)) if (!kvm_timer_compute_delta(timer))
return timer->cnt_ctl | ARCH_TIMER_CTRL_IT_STAT; ctl |= ARCH_TIMER_CTRL_IT_STAT;
else
return timer->cnt_ctl; return ctl;
} }
u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid) u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
...@@ -795,8 +884,8 @@ static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu, ...@@ -795,8 +884,8 @@ static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu,
switch (treg) { switch (treg) {
case TIMER_REG_TVAL: case TIMER_REG_TVAL:
val = timer->cnt_cval - kvm_phys_timer_read() + timer->cntvoff; val = timer_get_cval(timer) - kvm_phys_timer_read() + timer_get_offset(timer);
val &= lower_32_bits(val); val = lower_32_bits(val);
break; break;
case TIMER_REG_CTL: case TIMER_REG_CTL:
...@@ -804,11 +893,11 @@ static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu, ...@@ -804,11 +893,11 @@ static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu,
break; break;
case TIMER_REG_CVAL: case TIMER_REG_CVAL:
val = timer->cnt_cval; val = timer_get_cval(timer);
break; break;
case TIMER_REG_CNT: case TIMER_REG_CNT:
val = kvm_phys_timer_read() - timer->cntvoff; val = kvm_phys_timer_read() - timer_get_offset(timer);
break; break;
default: default:
...@@ -842,15 +931,15 @@ static void kvm_arm_timer_write(struct kvm_vcpu *vcpu, ...@@ -842,15 +931,15 @@ static void kvm_arm_timer_write(struct kvm_vcpu *vcpu,
{ {
switch (treg) { switch (treg) {
case TIMER_REG_TVAL: case TIMER_REG_TVAL:
timer->cnt_cval = kvm_phys_timer_read() - timer->cntvoff + (s32)val; timer_set_cval(timer, kvm_phys_timer_read() - timer_get_offset(timer) + (s32)val);
break; break;
case TIMER_REG_CTL: case TIMER_REG_CTL:
timer->cnt_ctl = val & ~ARCH_TIMER_CTRL_IT_STAT; timer_set_ctl(timer, val & ~ARCH_TIMER_CTRL_IT_STAT);
break; break;
case TIMER_REG_CVAL: case TIMER_REG_CVAL:
timer->cnt_cval = val; timer_set_cval(timer, val);
break; break;
default: default:
......
...@@ -301,8 +301,8 @@ TRACE_EVENT(kvm_timer_save_state, ...@@ -301,8 +301,8 @@ TRACE_EVENT(kvm_timer_save_state,
), ),
TP_fast_assign( TP_fast_assign(
__entry->ctl = ctx->cnt_ctl; __entry->ctl = timer_get_ctl(ctx);
__entry->cval = ctx->cnt_cval; __entry->cval = timer_get_cval(ctx);
__entry->timer_idx = arch_timer_ctx_index(ctx); __entry->timer_idx = arch_timer_ctx_index(ctx);
), ),
...@@ -323,8 +323,8 @@ TRACE_EVENT(kvm_timer_restore_state, ...@@ -323,8 +323,8 @@ TRACE_EVENT(kvm_timer_restore_state,
), ),
TP_fast_assign( TP_fast_assign(
__entry->ctl = ctx->cnt_ctl; __entry->ctl = timer_get_ctl(ctx);
__entry->cval = ctx->cnt_cval; __entry->cval = timer_get_cval(ctx);
__entry->timer_idx = arch_timer_ctx_index(ctx); __entry->timer_idx = arch_timer_ctx_index(ctx);
), ),
......
...@@ -26,16 +26,9 @@ enum kvm_arch_timer_regs { ...@@ -26,16 +26,9 @@ enum kvm_arch_timer_regs {
struct arch_timer_context { struct arch_timer_context {
struct kvm_vcpu *vcpu; struct kvm_vcpu *vcpu;
/* Registers: control register, timer value */
u32 cnt_ctl;
u64 cnt_cval;
/* Timer IRQ */ /* Timer IRQ */
struct kvm_irq_level irq; struct kvm_irq_level irq;
/* Virtual offset */
u64 cntvoff;
/* Emulated Timer (may be unused) */ /* Emulated Timer (may be unused) */
struct hrtimer hrtimer; struct hrtimer hrtimer;
...@@ -109,4 +102,8 @@ void kvm_arm_timer_write_sysreg(struct kvm_vcpu *vcpu, ...@@ -109,4 +102,8 @@ void kvm_arm_timer_write_sysreg(struct kvm_vcpu *vcpu,
enum kvm_arch_timer_regs treg, enum kvm_arch_timer_regs treg,
u64 val); u64 val);
/* Needed for tracing */
u32 timer_get_ctl(struct arch_timer_context *ctxt);
u64 timer_get_cval(struct arch_timer_context *ctxt);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment