Commit e604dd5d authored by Christoffer Dall's avatar Christoffer Dall Committed by Marc Zyngier

KVM: arm/arm64: timer: Rework data structures for multiple timers

Prepare for having 4 timer data structures (2 for now).

Move loaded to the cpu data structure and not the individual timer
structure, in preparation for assigning the EL1 phys timer as well.
Signed-off-by: default avatarChristoffer Dall <christoffer.dall@arm.com>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
parent 84135d3d
...@@ -36,6 +36,8 @@ enum kvm_arch_timer_regs { ...@@ -36,6 +36,8 @@ enum kvm_arch_timer_regs {
}; };
struct arch_timer_context { struct arch_timer_context {
struct kvm_vcpu *vcpu;
/* Registers: control register, timer value */ /* Registers: control register, timer value */
u32 cnt_ctl; u32 cnt_ctl;
u64 cnt_cval; u64 cnt_cval;
...@@ -43,32 +45,31 @@ struct arch_timer_context { ...@@ -43,32 +45,31 @@ struct arch_timer_context {
/* Timer IRQ */ /* Timer IRQ */
struct kvm_irq_level irq; struct kvm_irq_level irq;
/*
* We have multiple paths which can save/restore the timer state
* onto the hardware, so we need some way of keeping track of
* where the latest state is.
*
* loaded == true: State is loaded on the hardware registers.
* loaded == false: State is stored in memory.
*/
bool loaded;
/* Virtual offset */ /* Virtual offset */
u64 cntvoff; u64 cntvoff;
/* Emulated Timer (may be unused) */
struct hrtimer hrtimer;
}; };
struct arch_timer_cpu { struct arch_timer_cpu {
struct arch_timer_context vtimer; struct arch_timer_context timers[NR_KVM_TIMERS];
struct arch_timer_context ptimer;
/* Background timer used when the guest is not running */ /* Background timer used when the guest is not running */
struct hrtimer bg_timer; struct hrtimer bg_timer;
/* Physical timer emulation */
struct hrtimer phys_timer;
/* Is the timer enabled */ /* Is the timer enabled */
bool enabled; bool enabled;
/*
* We have multiple paths which can save/restore the timer state
* onto the hardware, so we need some way of keeping track of
* where the latest state is.
*
* loaded == true: State is loaded on the hardware registers.
* loaded == false: State is stored in memory.
*/
bool loaded;
}; };
int kvm_timer_hyp_init(bool); int kvm_timer_hyp_init(bool);
...@@ -98,10 +99,10 @@ void kvm_timer_init_vhe(void); ...@@ -98,10 +99,10 @@ void kvm_timer_init_vhe(void);
bool kvm_arch_timer_get_input_level(int vintid); bool kvm_arch_timer_get_input_level(int vintid);
#define vcpu_vtimer(v) (&(v)->arch.timer_cpu.vtimer) #define vcpu_timer(v) (&(v)->arch.timer_cpu)
#define vcpu_ptimer(v) (&(v)->arch.timer_cpu.ptimer) #define vcpu_get_timer(v,t) (&vcpu_timer(v)->timers[(t)])
#define vcpu_get_timer(v,t) \ #define vcpu_vtimer(v) (&(v)->arch.timer_cpu.timers[TIMER_VTIMER])
(t == TIMER_VTIMER ? vcpu_vtimer(v) : vcpu_ptimer(v)) #define vcpu_ptimer(v) (&(v)->arch.timer_cpu.timers[TIMER_PTIMER])
u64 kvm_arm_timer_read_sysreg(struct kvm_vcpu *vcpu, u64 kvm_arm_timer_read_sysreg(struct kvm_vcpu *vcpu,
enum kvm_arch_timers tmr, enum kvm_arch_timers tmr,
......
...@@ -184,13 +184,11 @@ static enum hrtimer_restart kvm_bg_timer_expire(struct hrtimer *hrt) ...@@ -184,13 +184,11 @@ static enum hrtimer_restart kvm_bg_timer_expire(struct hrtimer *hrt)
static enum hrtimer_restart kvm_phys_timer_expire(struct hrtimer *hrt) static enum hrtimer_restart kvm_phys_timer_expire(struct hrtimer *hrt)
{ {
struct arch_timer_context *ptimer; struct arch_timer_context *ptimer;
struct arch_timer_cpu *timer;
struct kvm_vcpu *vcpu; struct kvm_vcpu *vcpu;
u64 ns; u64 ns;
timer = container_of(hrt, struct arch_timer_cpu, phys_timer); ptimer = container_of(hrt, struct arch_timer_context, hrtimer);
vcpu = container_of(timer, struct kvm_vcpu, arch.timer_cpu); vcpu = ptimer->vcpu;
ptimer = vcpu_ptimer(vcpu);
/* /*
* Check that the timer has really expired from the guest's * Check that the timer has really expired from the guest's
...@@ -209,9 +207,10 @@ static enum hrtimer_restart kvm_phys_timer_expire(struct hrtimer *hrt) ...@@ -209,9 +207,10 @@ static enum hrtimer_restart kvm_phys_timer_expire(struct hrtimer *hrt)
static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx) static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx)
{ {
struct arch_timer_cpu *timer = vcpu_timer(timer_ctx->vcpu);
u64 cval, now; u64 cval, now;
if (timer_ctx->loaded) { if (timer->loaded) {
u32 cnt_ctl; u32 cnt_ctl;
/* Only the virtual timer can be loaded so far */ /* Only the virtual timer can be loaded so far */
...@@ -280,7 +279,6 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level, ...@@ -280,7 +279,6 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
/* Schedule the background timer for the emulated timer. */ /* Schedule the background timer for the emulated timer. */
static void phys_timer_emulate(struct kvm_vcpu *vcpu) static void phys_timer_emulate(struct kvm_vcpu *vcpu)
{ {
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
/* /*
...@@ -289,11 +287,11 @@ static void phys_timer_emulate(struct kvm_vcpu *vcpu) ...@@ -289,11 +287,11 @@ static void phys_timer_emulate(struct kvm_vcpu *vcpu)
* then we also don't need a soft timer. * then we also don't need a soft timer.
*/ */
if (kvm_timer_should_fire(ptimer) || !kvm_timer_irq_can_fire(ptimer)) { if (kvm_timer_should_fire(ptimer) || !kvm_timer_irq_can_fire(ptimer)) {
soft_timer_cancel(&timer->phys_timer); soft_timer_cancel(&ptimer->hrtimer);
return; return;
} }
soft_timer_start(&timer->phys_timer, kvm_timer_compute_delta(ptimer)); soft_timer_start(&ptimer->hrtimer, kvm_timer_compute_delta(ptimer));
} }
/* /*
...@@ -303,7 +301,7 @@ static void phys_timer_emulate(struct kvm_vcpu *vcpu) ...@@ -303,7 +301,7 @@ static void phys_timer_emulate(struct kvm_vcpu *vcpu)
*/ */
static void kvm_timer_update_state(struct kvm_vcpu *vcpu) static void kvm_timer_update_state(struct kvm_vcpu *vcpu)
{ {
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; struct arch_timer_cpu *timer = vcpu_timer(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);
bool level; bool level;
...@@ -329,13 +327,13 @@ static void kvm_timer_update_state(struct kvm_vcpu *vcpu) ...@@ -329,13 +327,13 @@ static void kvm_timer_update_state(struct kvm_vcpu *vcpu)
static void vtimer_save_state(struct kvm_vcpu *vcpu) static void vtimer_save_state(struct kvm_vcpu *vcpu)
{ {
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; struct arch_timer_cpu *timer = vcpu_timer(vcpu);
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
if (!vtimer->loaded) if (!timer->loaded)
goto out; goto out;
if (timer->enabled) { if (timer->enabled) {
...@@ -347,7 +345,7 @@ static void vtimer_save_state(struct kvm_vcpu *vcpu) ...@@ -347,7 +345,7 @@ static void vtimer_save_state(struct kvm_vcpu *vcpu)
write_sysreg_el0(0, cntv_ctl); write_sysreg_el0(0, cntv_ctl);
isb(); isb();
vtimer->loaded = false; timer->loaded = false;
out: out:
local_irq_restore(flags); local_irq_restore(flags);
} }
...@@ -359,7 +357,7 @@ static void vtimer_save_state(struct kvm_vcpu *vcpu) ...@@ -359,7 +357,7 @@ static void vtimer_save_state(struct kvm_vcpu *vcpu)
*/ */
static void kvm_timer_blocking(struct kvm_vcpu *vcpu) static void kvm_timer_blocking(struct kvm_vcpu *vcpu)
{ {
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; struct arch_timer_cpu *timer = vcpu_timer(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);
...@@ -379,20 +377,20 @@ static void kvm_timer_blocking(struct kvm_vcpu *vcpu) ...@@ -379,20 +377,20 @@ static void kvm_timer_blocking(struct kvm_vcpu *vcpu)
static void kvm_timer_unblocking(struct kvm_vcpu *vcpu) static void kvm_timer_unblocking(struct kvm_vcpu *vcpu)
{ {
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; struct arch_timer_cpu *timer = vcpu_timer(vcpu);
soft_timer_cancel(&timer->bg_timer); soft_timer_cancel(&timer->bg_timer);
} }
static void vtimer_restore_state(struct kvm_vcpu *vcpu) static void vtimer_restore_state(struct kvm_vcpu *vcpu)
{ {
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; struct arch_timer_cpu *timer = vcpu_timer(vcpu);
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
if (vtimer->loaded) if (timer->loaded)
goto out; goto out;
if (timer->enabled) { if (timer->enabled) {
...@@ -401,7 +399,7 @@ static void vtimer_restore_state(struct kvm_vcpu *vcpu) ...@@ -401,7 +399,7 @@ static void vtimer_restore_state(struct kvm_vcpu *vcpu)
write_sysreg_el0(vtimer->cnt_ctl, cntv_ctl); write_sysreg_el0(vtimer->cnt_ctl, cntv_ctl);
} }
vtimer->loaded = true; timer->loaded = true;
out: out:
local_irq_restore(flags); local_irq_restore(flags);
} }
...@@ -462,7 +460,7 @@ static void kvm_timer_vcpu_load_nogic(struct kvm_vcpu *vcpu) ...@@ -462,7 +460,7 @@ static void kvm_timer_vcpu_load_nogic(struct kvm_vcpu *vcpu)
void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu) void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu)
{ {
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; struct arch_timer_cpu *timer = vcpu_timer(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);
...@@ -507,7 +505,8 @@ bool kvm_timer_should_notify_user(struct kvm_vcpu *vcpu) ...@@ -507,7 +505,8 @@ bool kvm_timer_should_notify_user(struct kvm_vcpu *vcpu)
void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu) void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
{ {
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; struct arch_timer_cpu *timer = vcpu_timer(vcpu);
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
if (unlikely(!timer->enabled)) if (unlikely(!timer->enabled))
return; return;
...@@ -523,7 +522,7 @@ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu) ...@@ -523,7 +522,7 @@ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
* In any case, we re-schedule the hrtimer for the physical timer when * In any case, we re-schedule the hrtimer for the physical timer when
* coming back to the VCPU thread in kvm_timer_vcpu_load(). * coming back to the VCPU thread in kvm_timer_vcpu_load().
*/ */
soft_timer_cancel(&timer->phys_timer); soft_timer_cancel(&ptimer->hrtimer);
if (swait_active(kvm_arch_vcpu_wq(vcpu))) if (swait_active(kvm_arch_vcpu_wq(vcpu)))
kvm_timer_blocking(vcpu); kvm_timer_blocking(vcpu);
...@@ -559,7 +558,7 @@ static void unmask_vtimer_irq_user(struct kvm_vcpu *vcpu) ...@@ -559,7 +558,7 @@ static void unmask_vtimer_irq_user(struct kvm_vcpu *vcpu)
void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu) void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
{ {
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; struct arch_timer_cpu *timer = vcpu_timer(vcpu);
if (unlikely(!timer->enabled)) if (unlikely(!timer->enabled))
return; return;
...@@ -570,7 +569,7 @@ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu) ...@@ -570,7 +569,7 @@ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu) int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu)
{ {
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; struct arch_timer_cpu *timer = vcpu_timer(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);
...@@ -611,22 +610,25 @@ static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff) ...@@ -611,22 +610,25 @@ static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff)
void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
{ {
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; struct arch_timer_cpu *timer = vcpu_timer(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);
/* 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());
vcpu_ptimer(vcpu)->cntvoff = 0; ptimer->cntvoff = 0;
hrtimer_init(&timer->bg_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); hrtimer_init(&timer->bg_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
timer->bg_timer.function = kvm_bg_timer_expire; timer->bg_timer.function = kvm_bg_timer_expire;
hrtimer_init(&timer->phys_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); hrtimer_init(&ptimer->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
timer->phys_timer.function = kvm_phys_timer_expire; ptimer->hrtimer.function = kvm_phys_timer_expire;
vtimer->irq.irq = default_vtimer_irq.irq; vtimer->irq.irq = default_vtimer_irq.irq;
ptimer->irq.irq = default_ptimer_irq.irq; ptimer->irq.irq = default_ptimer_irq.irq;
vtimer->vcpu = vcpu;
ptimer->vcpu = vcpu;
} }
static void kvm_timer_init_interrupt(void *info) static void kvm_timer_init_interrupt(void *info)
...@@ -860,7 +862,7 @@ int kvm_timer_hyp_init(bool has_gic) ...@@ -860,7 +862,7 @@ int kvm_timer_hyp_init(bool has_gic)
void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu) void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
{ {
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; struct arch_timer_cpu *timer = vcpu_timer(vcpu);
soft_timer_cancel(&timer->bg_timer); soft_timer_cancel(&timer->bg_timer);
} }
...@@ -904,7 +906,7 @@ bool kvm_arch_timer_get_input_level(int vintid) ...@@ -904,7 +906,7 @@ bool kvm_arch_timer_get_input_level(int vintid)
int kvm_timer_enable(struct kvm_vcpu *vcpu) int kvm_timer_enable(struct kvm_vcpu *vcpu)
{ {
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; struct arch_timer_cpu *timer = vcpu_timer(vcpu);
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
int ret; int ret;
......
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