aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/kvm/reset.c12
-rw-r--r--include/kvm/arm_arch_timer.h4
-rw-r--r--virt/kvm/arm/arch_timer.c29
3 files changed, 36 insertions, 9 deletions
diff --git a/arch/arm/kvm/reset.c b/arch/arm/kvm/reset.c
index b80256b554cd..b7840e7aa452 100644
--- a/arch/arm/kvm/reset.c
+++ b/arch/arm/kvm/reset.c
@@ -27,6 +27,8 @@
27#include <asm/kvm_arm.h> 27#include <asm/kvm_arm.h>
28#include <asm/kvm_coproc.h> 28#include <asm/kvm_coproc.h>
29 29
30#include <kvm/arm_arch_timer.h>
31
30/****************************************************************************** 32/******************************************************************************
31 * Cortex-A15 Reset Values 33 * Cortex-A15 Reset Values
32 */ 34 */
@@ -37,6 +39,11 @@ static struct kvm_regs a15_regs_reset = {
37 .usr_regs.ARM_cpsr = SVC_MODE | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT, 39 .usr_regs.ARM_cpsr = SVC_MODE | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT,
38}; 40};
39 41
42static const struct kvm_irq_level a15_vtimer_irq = {
43 .irq = 27,
44 .level = 1,
45};
46
40 47
41/******************************************************************************* 48/*******************************************************************************
42 * Exported reset function 49 * Exported reset function
@@ -52,6 +59,7 @@ static struct kvm_regs a15_regs_reset = {
52int kvm_reset_vcpu(struct kvm_vcpu *vcpu) 59int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
53{ 60{
54 struct kvm_regs *cpu_reset; 61 struct kvm_regs *cpu_reset;
62 const struct kvm_irq_level *cpu_vtimer_irq;
55 63
56 switch (vcpu->arch.target) { 64 switch (vcpu->arch.target) {
57 case KVM_ARM_TARGET_CORTEX_A15: 65 case KVM_ARM_TARGET_CORTEX_A15:
@@ -59,6 +67,7 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
59 return -EINVAL; 67 return -EINVAL;
60 cpu_reset = &a15_regs_reset; 68 cpu_reset = &a15_regs_reset;
61 vcpu->arch.midr = read_cpuid_id(); 69 vcpu->arch.midr = read_cpuid_id();
70 cpu_vtimer_irq = &a15_vtimer_irq;
62 break; 71 break;
63 default: 72 default:
64 return -ENODEV; 73 return -ENODEV;
@@ -70,5 +79,8 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
70 /* Reset CP15 registers */ 79 /* Reset CP15 registers */
71 kvm_reset_coprocs(vcpu); 80 kvm_reset_coprocs(vcpu);
72 81
82 /* Reset arch_timer context */
83 kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
84
73 return 0; 85 return 0;
74} 86}
diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index 68cb9e1dfb81..6d9aeddc09bf 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -61,6 +61,8 @@ struct arch_timer_cpu {
61#ifdef CONFIG_KVM_ARM_TIMER 61#ifdef CONFIG_KVM_ARM_TIMER
62int kvm_timer_hyp_init(void); 62int kvm_timer_hyp_init(void);
63int kvm_timer_init(struct kvm *kvm); 63int kvm_timer_init(struct kvm *kvm);
64void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
65 const struct kvm_irq_level *irq);
64void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu); 66void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu);
65void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu); 67void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu);
66void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu); 68void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu);
@@ -76,6 +78,8 @@ static inline int kvm_timer_init(struct kvm *kvm)
76 return 0; 78 return 0;
77} 79}
78 80
81static inline void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
82 const struct kvm_irq_level *irq) {}
79static inline void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) {} 83static inline void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) {}
80static inline void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu) {} 84static inline void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu) {}
81static inline void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu) {} 85static inline void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu) {}
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 2d00b2925780..af4583e2c185 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -30,9 +30,7 @@
30 30
31static struct timecounter *timecounter; 31static struct timecounter *timecounter;
32static struct workqueue_struct *wqueue; 32static struct workqueue_struct *wqueue;
33static struct kvm_irq_level timer_irq = { 33static unsigned int host_vtimer_irq;
34 .level = 1,
35};
36 34
37static cycle_t kvm_phys_timer_read(void) 35static cycle_t kvm_phys_timer_read(void)
38{ 36{
@@ -67,8 +65,8 @@ static void kvm_timer_inject_irq(struct kvm_vcpu *vcpu)
67 65
68 timer->cntv_ctl |= ARCH_TIMER_CTRL_IT_MASK; 66 timer->cntv_ctl |= ARCH_TIMER_CTRL_IT_MASK;
69 kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id, 67 kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
70 vcpu->arch.timer_cpu.irq->irq, 68 timer->irq->irq,
71 vcpu->arch.timer_cpu.irq->level); 69 timer->irq->level);
72} 70}
73 71
74static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id) 72static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id)
@@ -156,6 +154,20 @@ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
156 timer_arm(timer, ns); 154 timer_arm(timer, ns);
157} 155}
158 156
157void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
158 const struct kvm_irq_level *irq)
159{
160 struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
161
162 /*
163 * The vcpu timer irq number cannot be determined in
164 * kvm_timer_vcpu_init() because it is called much before
165 * kvm_vcpu_set_target(). To handle this, we determine
166 * vcpu timer irq number when the vcpu is reset.
167 */
168 timer->irq = irq;
169}
170
159void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) 171void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
160{ 172{
161 struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; 173 struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
@@ -163,12 +175,11 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
163 INIT_WORK(&timer->expired, kvm_timer_inject_irq_work); 175 INIT_WORK(&timer->expired, kvm_timer_inject_irq_work);
164 hrtimer_init(&timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); 176 hrtimer_init(&timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
165 timer->timer.function = kvm_timer_expire; 177 timer->timer.function = kvm_timer_expire;
166 timer->irq = &timer_irq;
167} 178}
168 179
169static void kvm_timer_init_interrupt(void *info) 180static void kvm_timer_init_interrupt(void *info)
170{ 181{
171 enable_percpu_irq(timer_irq.irq, 0); 182 enable_percpu_irq(host_vtimer_irq, 0);
172} 183}
173 184
174 185
@@ -182,7 +193,7 @@ static int kvm_timer_cpu_notify(struct notifier_block *self,
182 break; 193 break;
183 case CPU_DYING: 194 case CPU_DYING:
184 case CPU_DYING_FROZEN: 195 case CPU_DYING_FROZEN:
185 disable_percpu_irq(timer_irq.irq); 196 disable_percpu_irq(host_vtimer_irq);
186 break; 197 break;
187 } 198 }
188 199
@@ -229,7 +240,7 @@ int kvm_timer_hyp_init(void)
229 goto out; 240 goto out;
230 } 241 }
231 242
232 timer_irq.irq = ppi; 243 host_vtimer_irq = ppi;
233 244
234 err = register_cpu_notifier(&kvm_timer_cpu_nb); 245 err = register_cpu_notifier(&kvm_timer_cpu_nb);
235 if (err) { 246 if (err) {