diff mbox series

[11/14] KVM: arm/arm64: timer: Rework data structures for multiple timers

Message ID 20190124140032.8588-12-christoffer.dall@arm.com (mailing list archive)
State New, archived
Headers show
Series KVM: arm/arm64: Various rework in preparation of nested virt support | expand

Commit Message

Christoffer Dall Jan. 24, 2019, 2 p.m. UTC
Prepare for having 4 timer data structures (2 for now).

Change loaded to an enum so that we know not just whether *some* state
is loaded on the CPU, but also *which* state is loaded.

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: Christoffer Dall <christoffer.dall@arm.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/kvm/arm_arch_timer.h | 44 ++++++++++++++-------------
 virt/kvm/arm/arch_timer.c    | 58 +++++++++++++++++++-----------------
 2 files changed, 54 insertions(+), 48 deletions(-)

Comments

Andre Przywara Feb. 18, 2019, 3:10 p.m. UTC | #1
On Thu, 24 Jan 2019 15:00:29 +0100
Christoffer Dall <christoffer.dall@arm.com> wrote:

Hi,

I already looked at most of these patches earlier, without finding
serious issues, but figured I would give those without any Reviewed-by:
or Acked-by: tags a closer look.
(This patch just carries a S-o-b: tag from Marc in the kvm-arm git repo.)

> Prepare for having 4 timer data structures (2 for now).
> 
> Change loaded to an enum so that we know not just whether *some* state
> is loaded on the CPU, but also *which* state is loaded.
> 
> 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: Christoffer Dall <christoffer.dall@arm.com>
> Acked-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  include/kvm/arm_arch_timer.h | 44 ++++++++++++++-------------
>  virt/kvm/arm/arch_timer.c    | 58 +++++++++++++++++++-----------------
>  2 files changed, 54 insertions(+), 48 deletions(-)
> 
> diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
> index d26b7fde9935..d40fe57a2d0d 100644
> --- a/include/kvm/arm_arch_timer.h
> +++ b/include/kvm/arm_arch_timer.h
> @@ -36,6 +36,8 @@ enum kvm_arch_timer_regs {
>  };
>  
>  struct arch_timer_context {
> +	struct kvm_vcpu			*vcpu;
> +
>  	/* Registers: control register, timer value */
>  	u32				cnt_ctl;
>  	u64				cnt_cval;
> @@ -43,32 +45,34 @@ struct arch_timer_context {
>  	/* Timer 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 */
> -	u64			cntvoff;
> +	u64				cntvoff;
> +
> +	/* Emulated Timer (may be unused) */
> +	struct hrtimer			hrtimer;
> +};
> +
> +enum loaded_timer_state {
> +	TIMER_NOT_LOADED,
> +	TIMER_EL1_LOADED,

So this gets reverted in PATCH 13/14, and I don't see it reappearing in
the nv series later on.
Is that just needed for assigning the phys timer in the next patch, and
gets obsolete with the timer_map?
Or is this a rebase artefact and we don't actually need this?

The rest of the patch looks like valid transformations to me.

Cheers,
Andre.

>  };
>  
>  struct arch_timer_cpu {
> -	struct arch_timer_context	vtimer;
> -	struct arch_timer_context	ptimer;
> +	struct arch_timer_context timers[NR_KVM_TIMERS];
>  
>  	/* Background timer used when the guest is not running */
>  	struct hrtimer			bg_timer;
>  
> -	/* Physical timer emulation */
> -	struct hrtimer			phys_timer;
> -
>  	/* Is the timer enabled */
>  	bool			enabled;
> +
> +	/*
> +	 * We have multiple paths which can save/restore the timer state
> +	 * onto the hardware, and for nested virt the EL1 hardware timers can
> +	 * contain state from either the VM's EL1 timers or EL2 timers, so we
> +	 * need some way of keeping track of where the latest state is.
> +	 */
> +	enum loaded_timer_state loaded;
>  };
>  
>  int kvm_timer_hyp_init(bool);
> @@ -98,10 +102,10 @@ void kvm_timer_init_vhe(void);
>  
>  bool kvm_arch_timer_get_input_level(int vintid);
>  
> -#define vcpu_vtimer(v)	(&(v)->arch.timer_cpu.vtimer)
> -#define vcpu_ptimer(v)	(&(v)->arch.timer_cpu.ptimer)
> -#define vcpu_get_timer(v,t)					\
> -	(t == TIMER_VTIMER ? vcpu_vtimer(v) : vcpu_ptimer(v))
> +#define vcpu_timer(v)	(&(v)->arch.timer_cpu)
> +#define vcpu_get_timer(v,t)	(&vcpu_timer(v)->timers[(t)])
> +#define vcpu_vtimer(v)	(&(v)->arch.timer_cpu.timers[TIMER_VTIMER])
> +#define vcpu_ptimer(v)	(&(v)->arch.timer_cpu.timers[TIMER_PTIMER])
>  
>  u64 kvm_arm_timer_read_sysreg(struct kvm_vcpu *vcpu,
>  			      enum kvm_arch_timers tmr,
> diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
> index 9502bb91776b..8b0eca5fbad1 100644
> --- a/virt/kvm/arm/arch_timer.c
> +++ b/virt/kvm/arm/arch_timer.c
> @@ -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)
>  {
>  	struct arch_timer_context *ptimer;
> -	struct arch_timer_cpu *timer;
>  	struct kvm_vcpu *vcpu;
>  	u64 ns;
>  
> -	timer = container_of(hrt, struct arch_timer_cpu, phys_timer);
> -	vcpu = container_of(timer, struct kvm_vcpu, arch.timer_cpu);
> -	ptimer = vcpu_ptimer(vcpu);
> +	ptimer = container_of(hrt, struct arch_timer_context, hrtimer);
> +	vcpu = ptimer->vcpu;
>  
>  	/*
>  	 * 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)
>  
>  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;
>  
> -	if (timer_ctx->loaded) {
> +	if (timer->loaded == TIMER_EL1_LOADED) {
>  		u32 cnt_ctl;
>  
>  		/* 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,
>  /* Schedule the background timer for the emulated timer. */
>  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);
>  
>  	/*
> @@ -289,11 +287,11 @@ static void phys_timer_emulate(struct kvm_vcpu *vcpu)
>  	 * then we also don't need a soft timer.
>  	 */
>  	if (kvm_timer_should_fire(ptimer) || !kvm_timer_irq_can_fire(ptimer)) {
> -		soft_timer_cancel(&timer->phys_timer);
> +		soft_timer_cancel(&ptimer->hrtimer);
>  		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)
>   */
>  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 *ptimer = vcpu_ptimer(vcpu);
>  	bool level;
> @@ -329,13 +327,13 @@ static void kvm_timer_update_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);
>  	unsigned long flags;
>  
>  	local_irq_save(flags);
>  
> -	if (!vtimer->loaded)
> +	if (timer->loaded == TIMER_NOT_LOADED)
>  		goto out;
>  
>  	if (timer->enabled) {
> @@ -347,7 +345,7 @@ static void vtimer_save_state(struct kvm_vcpu *vcpu)
>  	write_sysreg_el0(0, cntv_ctl);
>  	isb();
>  
> -	vtimer->loaded = false;
> +	timer->loaded = TIMER_NOT_LOADED;
>  out:
>  	local_irq_restore(flags);
>  }
> @@ -359,7 +357,7 @@ static void vtimer_save_state(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 *ptimer = vcpu_ptimer(vcpu);
>  
> @@ -379,20 +377,20 @@ static void kvm_timer_blocking(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);
>  }
>  
>  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);
>  	unsigned long flags;
>  
>  	local_irq_save(flags);
>  
> -	if (vtimer->loaded)
> +	if (timer->loaded == TIMER_EL1_LOADED)
>  		goto out;
>  
>  	if (timer->enabled) {
> @@ -401,7 +399,7 @@ static void vtimer_restore_state(struct kvm_vcpu *vcpu)
>  		write_sysreg_el0(vtimer->cnt_ctl, cntv_ctl);
>  	}
>  
> -	vtimer->loaded = true;
> +	timer->loaded = TIMER_EL1_LOADED;
>  out:
>  	local_irq_restore(flags);
>  }
> @@ -462,7 +460,7 @@ static void kvm_timer_vcpu_load_nogic(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 *ptimer = vcpu_ptimer(vcpu);
>  
> @@ -507,7 +505,8 @@ bool kvm_timer_should_notify_user(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))
>  		return;
> @@ -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
>  	 * 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)))
>  		kvm_timer_blocking(vcpu);
> @@ -559,7 +558,7 @@ static void unmask_vtimer_irq_user(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))
>  		return;
> @@ -570,7 +569,7 @@ void kvm_timer_sync_hwstate(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 *ptimer = vcpu_ptimer(vcpu);
>  
> @@ -611,22 +610,25 @@ static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff)
>  
>  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 *ptimer = vcpu_ptimer(vcpu);
>  
>  	/* Synchronize cntvoff across all vtimers of a VM. */
>  	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);
>  	timer->bg_timer.function = kvm_bg_timer_expire;
>  
> -	hrtimer_init(&timer->phys_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
> -	timer->phys_timer.function = kvm_phys_timer_expire;
> +	hrtimer_init(&ptimer->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
> +	ptimer->hrtimer.function = kvm_phys_timer_expire;
>  
>  	vtimer->irq.irq = default_vtimer_irq.irq;
>  	ptimer->irq.irq = default_ptimer_irq.irq;
> +
> +	vtimer->vcpu = vcpu;
> +	ptimer->vcpu = vcpu;
>  }
>  
>  static void kvm_timer_init_interrupt(void *info)
> @@ -859,7 +861,7 @@ int kvm_timer_hyp_init(bool has_gic)
>  
>  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);
>  }
> @@ -903,7 +905,7 @@ bool kvm_arch_timer_get_input_level(int vintid)
>  
>  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);
>  	int ret;
>
Christoffer Dall Feb. 19, 2019, 12:27 p.m. UTC | #2
On Mon, Feb 18, 2019 at 03:10:16PM +0000, André Przywara wrote:
> On Thu, 24 Jan 2019 15:00:29 +0100
> Christoffer Dall <christoffer.dall@arm.com> wrote:
> 
> Hi,
> 
> I already looked at most of these patches earlier, without finding
> serious issues, but figured I would give those without any Reviewed-by:
> or Acked-by: tags a closer look.
> (This patch just carries a S-o-b: tag from Marc in the kvm-arm git repo.)
> 
> > Prepare for having 4 timer data structures (2 for now).
> > 
> > Change loaded to an enum so that we know not just whether *some* state
> > is loaded on the CPU, but also *which* state is loaded.
> > 
> > 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: Christoffer Dall <christoffer.dall@arm.com>
> > Acked-by: Marc Zyngier <marc.zyngier@arm.com>
> > ---
> >  include/kvm/arm_arch_timer.h | 44 ++++++++++++++-------------
> >  virt/kvm/arm/arch_timer.c    | 58 +++++++++++++++++++-----------------
> >  2 files changed, 54 insertions(+), 48 deletions(-)
> > 
> > diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
> > index d26b7fde9935..d40fe57a2d0d 100644
> > --- a/include/kvm/arm_arch_timer.h
> > +++ b/include/kvm/arm_arch_timer.h
> > @@ -36,6 +36,8 @@ enum kvm_arch_timer_regs {
> >  };
> >  
> >  struct arch_timer_context {
> > +	struct kvm_vcpu			*vcpu;
> > +
> >  	/* Registers: control register, timer value */
> >  	u32				cnt_ctl;
> >  	u64				cnt_cval;
> > @@ -43,32 +45,34 @@ struct arch_timer_context {
> >  	/* Timer 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 */
> > -	u64			cntvoff;
> > +	u64				cntvoff;
> > +
> > +	/* Emulated Timer (may be unused) */
> > +	struct hrtimer			hrtimer;
> > +};
> > +
> > +enum loaded_timer_state {
> > +	TIMER_NOT_LOADED,
> > +	TIMER_EL1_LOADED,
> 
> So this gets reverted in PATCH 13/14, and I don't see it reappearing in
> the nv series later on.
> Is that just needed for assigning the phys timer in the next patch, and
> gets obsolete with the timer_map?
> Or is this a rebase artefact and we don't actually need this?

I think this is a rebase problem and we could have optimized this out to
reduce the patch diff.  The end result is the same though.

> 
> The rest of the patch looks like valid transformations to me.
> 
Thanks for having a look.

    Christoffer
diff mbox series

Patch

diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index d26b7fde9935..d40fe57a2d0d 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -36,6 +36,8 @@  enum kvm_arch_timer_regs {
 };
 
 struct arch_timer_context {
+	struct kvm_vcpu			*vcpu;
+
 	/* Registers: control register, timer value */
 	u32				cnt_ctl;
 	u64				cnt_cval;
@@ -43,32 +45,34 @@  struct arch_timer_context {
 	/* Timer 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 */
-	u64			cntvoff;
+	u64				cntvoff;
+
+	/* Emulated Timer (may be unused) */
+	struct hrtimer			hrtimer;
+};
+
+enum loaded_timer_state {
+	TIMER_NOT_LOADED,
+	TIMER_EL1_LOADED,
 };
 
 struct arch_timer_cpu {
-	struct arch_timer_context	vtimer;
-	struct arch_timer_context	ptimer;
+	struct arch_timer_context timers[NR_KVM_TIMERS];
 
 	/* Background timer used when the guest is not running */
 	struct hrtimer			bg_timer;
 
-	/* Physical timer emulation */
-	struct hrtimer			phys_timer;
-
 	/* Is the timer enabled */
 	bool			enabled;
+
+	/*
+	 * We have multiple paths which can save/restore the timer state
+	 * onto the hardware, and for nested virt the EL1 hardware timers can
+	 * contain state from either the VM's EL1 timers or EL2 timers, so we
+	 * need some way of keeping track of where the latest state is.
+	 */
+	enum loaded_timer_state loaded;
 };
 
 int kvm_timer_hyp_init(bool);
@@ -98,10 +102,10 @@  void kvm_timer_init_vhe(void);
 
 bool kvm_arch_timer_get_input_level(int vintid);
 
-#define vcpu_vtimer(v)	(&(v)->arch.timer_cpu.vtimer)
-#define vcpu_ptimer(v)	(&(v)->arch.timer_cpu.ptimer)
-#define vcpu_get_timer(v,t)					\
-	(t == TIMER_VTIMER ? vcpu_vtimer(v) : vcpu_ptimer(v))
+#define vcpu_timer(v)	(&(v)->arch.timer_cpu)
+#define vcpu_get_timer(v,t)	(&vcpu_timer(v)->timers[(t)])
+#define vcpu_vtimer(v)	(&(v)->arch.timer_cpu.timers[TIMER_VTIMER])
+#define vcpu_ptimer(v)	(&(v)->arch.timer_cpu.timers[TIMER_PTIMER])
 
 u64 kvm_arm_timer_read_sysreg(struct kvm_vcpu *vcpu,
 			      enum kvm_arch_timers tmr,
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 9502bb91776b..8b0eca5fbad1 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -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)
 {
 	struct arch_timer_context *ptimer;
-	struct arch_timer_cpu *timer;
 	struct kvm_vcpu *vcpu;
 	u64 ns;
 
-	timer = container_of(hrt, struct arch_timer_cpu, phys_timer);
-	vcpu = container_of(timer, struct kvm_vcpu, arch.timer_cpu);
-	ptimer = vcpu_ptimer(vcpu);
+	ptimer = container_of(hrt, struct arch_timer_context, hrtimer);
+	vcpu = ptimer->vcpu;
 
 	/*
 	 * 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)
 
 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;
 
-	if (timer_ctx->loaded) {
+	if (timer->loaded == TIMER_EL1_LOADED) {
 		u32 cnt_ctl;
 
 		/* 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,
 /* Schedule the background timer for the emulated timer. */
 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);
 
 	/*
@@ -289,11 +287,11 @@  static void phys_timer_emulate(struct kvm_vcpu *vcpu)
 	 * then we also don't need a soft timer.
 	 */
 	if (kvm_timer_should_fire(ptimer) || !kvm_timer_irq_can_fire(ptimer)) {
-		soft_timer_cancel(&timer->phys_timer);
+		soft_timer_cancel(&ptimer->hrtimer);
 		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)
  */
 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 *ptimer = vcpu_ptimer(vcpu);
 	bool level;
@@ -329,13 +327,13 @@  static void kvm_timer_update_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);
 	unsigned long flags;
 
 	local_irq_save(flags);
 
-	if (!vtimer->loaded)
+	if (timer->loaded == TIMER_NOT_LOADED)
 		goto out;
 
 	if (timer->enabled) {
@@ -347,7 +345,7 @@  static void vtimer_save_state(struct kvm_vcpu *vcpu)
 	write_sysreg_el0(0, cntv_ctl);
 	isb();
 
-	vtimer->loaded = false;
+	timer->loaded = TIMER_NOT_LOADED;
 out:
 	local_irq_restore(flags);
 }
@@ -359,7 +357,7 @@  static void vtimer_save_state(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 *ptimer = vcpu_ptimer(vcpu);
 
@@ -379,20 +377,20 @@  static void kvm_timer_blocking(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);
 }
 
 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);
 	unsigned long flags;
 
 	local_irq_save(flags);
 
-	if (vtimer->loaded)
+	if (timer->loaded == TIMER_EL1_LOADED)
 		goto out;
 
 	if (timer->enabled) {
@@ -401,7 +399,7 @@  static void vtimer_restore_state(struct kvm_vcpu *vcpu)
 		write_sysreg_el0(vtimer->cnt_ctl, cntv_ctl);
 	}
 
-	vtimer->loaded = true;
+	timer->loaded = TIMER_EL1_LOADED;
 out:
 	local_irq_restore(flags);
 }
@@ -462,7 +460,7 @@  static void kvm_timer_vcpu_load_nogic(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 *ptimer = vcpu_ptimer(vcpu);
 
@@ -507,7 +505,8 @@  bool kvm_timer_should_notify_user(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))
 		return;
@@ -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
 	 * 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)))
 		kvm_timer_blocking(vcpu);
@@ -559,7 +558,7 @@  static void unmask_vtimer_irq_user(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))
 		return;
@@ -570,7 +569,7 @@  void kvm_timer_sync_hwstate(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 *ptimer = vcpu_ptimer(vcpu);
 
@@ -611,22 +610,25 @@  static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff)
 
 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 *ptimer = vcpu_ptimer(vcpu);
 
 	/* Synchronize cntvoff across all vtimers of a VM. */
 	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);
 	timer->bg_timer.function = kvm_bg_timer_expire;
 
-	hrtimer_init(&timer->phys_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
-	timer->phys_timer.function = kvm_phys_timer_expire;
+	hrtimer_init(&ptimer->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+	ptimer->hrtimer.function = kvm_phys_timer_expire;
 
 	vtimer->irq.irq = default_vtimer_irq.irq;
 	ptimer->irq.irq = default_ptimer_irq.irq;
+
+	vtimer->vcpu = vcpu;
+	ptimer->vcpu = vcpu;
 }
 
 static void kvm_timer_init_interrupt(void *info)
@@ -859,7 +861,7 @@  int kvm_timer_hyp_init(bool has_gic)
 
 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);
 }
@@ -903,7 +905,7 @@  bool kvm_arch_timer_get_input_level(int vintid)
 
 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);
 	int ret;