Skip to content

Commit fbb4aee

Browse files
soccertackMarc Zyngier
authored andcommitted
KVM: arm/arm64: Abstract virtual timer context into separate structure
Abstract virtual timer context into a separate structure and change all callers referring to timer registers, irq state and so on. No change in functionality. This is about to become very handy when adding the EL1 physical timer. Signed-off-by: Jintack Lim <jintack@cs.columbia.edu> Acked-by: Christoffer Dall <christoffer.dall@linaro.org> Acked-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
1 parent 0bdbf3b commit fbb4aee

3 files changed

Lines changed: 56 additions & 50 deletions

File tree

include/kvm/arm_arch_timer.h

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,20 @@ struct arch_timer_kvm {
2828
u64 cntvoff;
2929
};
3030

31-
struct arch_timer_cpu {
31+
struct arch_timer_context {
3232
/* Registers: control register, timer value */
33-
u32 cntv_ctl; /* Saved/restored */
34-
u64 cntv_cval; /* Saved/restored */
33+
u32 cnt_ctl;
34+
u64 cnt_cval;
35+
36+
/* Timer IRQ */
37+
struct kvm_irq_level irq;
38+
39+
/* Active IRQ state caching */
40+
bool active_cleared_last;
41+
};
3542

36-
/*
37-
* Anything that is not used directly from assembly code goes
38-
* here.
39-
*/
43+
struct arch_timer_cpu {
44+
struct arch_timer_context vtimer;
4045

4146
/* Background timer used when the guest is not running */
4247
struct hrtimer timer;
@@ -47,12 +52,6 @@ struct arch_timer_cpu {
4752
/* Background timer active */
4853
bool armed;
4954

50-
/* Timer IRQ */
51-
struct kvm_irq_level irq;
52-
53-
/* Active IRQ state caching */
54-
bool active_cleared_last;
55-
5655
/* Is the timer enabled */
5756
bool enabled;
5857
};
@@ -77,4 +76,6 @@ void kvm_timer_unschedule(struct kvm_vcpu *vcpu);
7776
void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu);
7877

7978
void kvm_timer_init_vhe(void);
79+
80+
#define vcpu_vtimer(v) (&(v)->arch.timer_cpu.vtimer)
8081
#endif

virt/kvm/arm/arch_timer.c

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ static u32 host_vtimer_irq_flags;
3737

3838
void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
3939
{
40-
vcpu->arch.timer_cpu.active_cleared_last = false;
40+
vcpu_vtimer(vcpu)->active_cleared_last = false;
4141
}
4242

4343
static u64 kvm_phys_timer_read(void)
@@ -102,7 +102,7 @@ static u64 kvm_timer_compute_delta(struct kvm_vcpu *vcpu)
102102
{
103103
u64 cval, now;
104104

105-
cval = vcpu->arch.timer_cpu.cntv_cval;
105+
cval = vcpu_vtimer(vcpu)->cnt_cval;
106106
now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
107107

108108
if (now < cval) {
@@ -144,21 +144,21 @@ static enum hrtimer_restart kvm_timer_expire(struct hrtimer *hrt)
144144

145145
static bool kvm_timer_irq_can_fire(struct kvm_vcpu *vcpu)
146146
{
147-
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
147+
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
148148

149-
return !(timer->cntv_ctl & ARCH_TIMER_CTRL_IT_MASK) &&
150-
(timer->cntv_ctl & ARCH_TIMER_CTRL_ENABLE);
149+
return !(vtimer->cnt_ctl & ARCH_TIMER_CTRL_IT_MASK) &&
150+
(vtimer->cnt_ctl & ARCH_TIMER_CTRL_ENABLE);
151151
}
152152

153153
bool kvm_timer_should_fire(struct kvm_vcpu *vcpu)
154154
{
155-
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
155+
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
156156
u64 cval, now;
157157

158158
if (!kvm_timer_irq_can_fire(vcpu))
159159
return false;
160160

161-
cval = timer->cntv_cval;
161+
cval = vtimer->cnt_cval;
162162
now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
163163

164164
return cval <= now;
@@ -167,18 +167,18 @@ bool kvm_timer_should_fire(struct kvm_vcpu *vcpu)
167167
static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
168168
{
169169
int ret;
170-
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
170+
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
171171

172172
BUG_ON(!vgic_initialized(vcpu->kvm));
173173

174-
timer->active_cleared_last = false;
175-
timer->irq.level = new_level;
176-
trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->irq.irq,
177-
timer->irq.level);
174+
vtimer->active_cleared_last = false;
175+
vtimer->irq.level = new_level;
176+
trace_kvm_timer_update_irq(vcpu->vcpu_id, vtimer->irq.irq,
177+
vtimer->irq.level);
178178

179179
ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
180-
timer->irq.irq,
181-
timer->irq.level);
180+
vtimer->irq.irq,
181+
vtimer->irq.level);
182182
WARN_ON(ret);
183183
}
184184

@@ -189,18 +189,19 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
189189
static int kvm_timer_update_state(struct kvm_vcpu *vcpu)
190190
{
191191
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
192+
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
192193

193194
/*
194195
* If userspace modified the timer registers via SET_ONE_REG before
195-
* the vgic was initialized, we mustn't set the timer->irq.level value
196+
* the vgic was initialized, we mustn't set the vtimer->irq.level value
196197
* because the guest would never see the interrupt. Instead wait
197198
* until we call this function from kvm_timer_flush_hwstate.
198199
*/
199200
if (!vgic_initialized(vcpu->kvm) || !timer->enabled)
200201
return -ENODEV;
201202

202-
if (kvm_timer_should_fire(vcpu) != timer->irq.level)
203-
kvm_timer_update_irq(vcpu, !timer->irq.level);
203+
if (kvm_timer_should_fire(vcpu) != vtimer->irq.level)
204+
kvm_timer_update_irq(vcpu, !vtimer->irq.level);
204205

205206
return 0;
206207
}
@@ -250,7 +251,7 @@ void kvm_timer_unschedule(struct kvm_vcpu *vcpu)
250251
*/
251252
void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
252253
{
253-
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
254+
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
254255
bool phys_active;
255256
int ret;
256257

@@ -274,8 +275,8 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
274275
* to ensure that hardware interrupts from the timer triggers a guest
275276
* exit.
276277
*/
277-
phys_active = timer->irq.level ||
278-
kvm_vgic_map_is_active(vcpu, timer->irq.irq);
278+
phys_active = vtimer->irq.level ||
279+
kvm_vgic_map_is_active(vcpu, vtimer->irq.irq);
279280

280281
/*
281282
* We want to avoid hitting the (re)distributor as much as
@@ -297,15 +298,15 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
297298
* - cached value is "active clear"
298299
* - value to be programmed is "active clear"
299300
*/
300-
if (timer->active_cleared_last && !phys_active)
301+
if (vtimer->active_cleared_last && !phys_active)
301302
return;
302303

303304
ret = irq_set_irqchip_state(host_vtimer_irq,
304305
IRQCHIP_STATE_ACTIVE,
305306
phys_active);
306307
WARN_ON(ret);
307308

308-
timer->active_cleared_last = !phys_active;
309+
vtimer->active_cleared_last = !phys_active;
309310
}
310311

311312
/**
@@ -331,23 +332,23 @@ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
331332
int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
332333
const struct kvm_irq_level *irq)
333334
{
334-
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
335+
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
335336

336337
/*
337338
* The vcpu timer irq number cannot be determined in
338339
* kvm_timer_vcpu_init() because it is called much before
339340
* kvm_vcpu_set_target(). To handle this, we determine
340341
* vcpu timer irq number when the vcpu is reset.
341342
*/
342-
timer->irq.irq = irq->irq;
343+
vtimer->irq.irq = irq->irq;
343344

344345
/*
345346
* The bits in CNTV_CTL are architecturally reset to UNKNOWN for ARMv8
346347
* and to 0 for ARMv7. We provide an implementation that always
347348
* resets the timer to be disabled and unmasked and is compliant with
348349
* the ARMv7 architecture.
349350
*/
350-
timer->cntv_ctl = 0;
351+
vtimer->cnt_ctl = 0;
351352
kvm_timer_update_state(vcpu);
352353

353354
return 0;
@@ -369,17 +370,17 @@ static void kvm_timer_init_interrupt(void *info)
369370

370371
int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
371372
{
372-
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
373+
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
373374

374375
switch (regid) {
375376
case KVM_REG_ARM_TIMER_CTL:
376-
timer->cntv_ctl = value;
377+
vtimer->cnt_ctl = value;
377378
break;
378379
case KVM_REG_ARM_TIMER_CNT:
379380
vcpu->kvm->arch.timer.cntvoff = kvm_phys_timer_read() - value;
380381
break;
381382
case KVM_REG_ARM_TIMER_CVAL:
382-
timer->cntv_cval = value;
383+
vtimer->cnt_cval = value;
383384
break;
384385
default:
385386
return -1;
@@ -391,15 +392,15 @@ int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
391392

392393
u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
393394
{
394-
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
395+
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
395396

396397
switch (regid) {
397398
case KVM_REG_ARM_TIMER_CTL:
398-
return timer->cntv_ctl;
399+
return vtimer->cnt_ctl;
399400
case KVM_REG_ARM_TIMER_CNT:
400401
return kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
401402
case KVM_REG_ARM_TIMER_CVAL:
402-
return timer->cntv_cval;
403+
return vtimer->cnt_cval;
403404
}
404405
return (u64)-1;
405406
}
@@ -463,14 +464,16 @@ int kvm_timer_hyp_init(void)
463464
void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
464465
{
465466
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
467+
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
466468

467469
timer_disarm(timer);
468-
kvm_vgic_unmap_phys_irq(vcpu, timer->irq.irq);
470+
kvm_vgic_unmap_phys_irq(vcpu, vtimer->irq.irq);
469471
}
470472

471473
int kvm_timer_enable(struct kvm_vcpu *vcpu)
472474
{
473475
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
476+
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
474477
struct irq_desc *desc;
475478
struct irq_data *data;
476479
int phys_irq;
@@ -498,7 +501,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
498501
* Tell the VGIC that the virtual interrupt is tied to a
499502
* physical interrupt. We do that once per VCPU.
500503
*/
501-
ret = kvm_vgic_map_phys_irq(vcpu, timer->irq.irq, phys_irq);
504+
ret = kvm_vgic_map_phys_irq(vcpu, vtimer->irq.irq, phys_irq);
502505
if (ret)
503506
return ret;
504507

virt/kvm/arm/hyp/timer-sr.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@
2525
void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu)
2626
{
2727
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
28+
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
2829
u64 val;
2930

3031
if (timer->enabled) {
31-
timer->cntv_ctl = read_sysreg_el0(cntv_ctl);
32-
timer->cntv_cval = read_sysreg_el0(cntv_cval);
32+
vtimer->cnt_ctl = read_sysreg_el0(cntv_ctl);
33+
vtimer->cnt_cval = read_sysreg_el0(cntv_cval);
3334
}
3435

3536
/* Disable the virtual timer */
@@ -54,6 +55,7 @@ void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu)
5455
{
5556
struct kvm *kvm = kern_hyp_va(vcpu->kvm);
5657
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
58+
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
5759
u64 val;
5860

5961
/* Those bits are already configured at boot on VHE-system */
@@ -70,8 +72,8 @@ void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu)
7072

7173
if (timer->enabled) {
7274
write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2);
73-
write_sysreg_el0(timer->cntv_cval, cntv_cval);
75+
write_sysreg_el0(vtimer->cnt_cval, cntv_cval);
7476
isb();
75-
write_sysreg_el0(timer->cntv_ctl, cntv_ctl);
77+
write_sysreg_el0(vtimer->cnt_ctl, cntv_ctl);
7678
}
7779
}

0 commit comments

Comments
 (0)