aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnup Patel <anup.patel@linaro.org>2013-04-30 02:32:15 -0400
committerChristoffer Dall <christoffer.dall@linaro.org>2013-06-26 13:50:02 -0400
commit5ae7f87a56fab10b8f9b135a8377c144397293ca (patch)
tree9bb5b7bcc23d5f3d31783caccc499413678dcdf9
parent87d41fb4da6467622b7a87fd6afe8071abab6dae (diff)
ARM: KVM: Allow host virt timer irq to be different from guest timer virt irq
The arch_timer irq numbers (or PPI numbers) are implementation dependent, so the host virtual timer irq number can be different from guest virtual timer irq number. This patch ensures that host virtual timer irq number is read from DTB and guest virtual timer irq is determined based on vcpu target type. Signed-off-by: Anup Patel <anup.patel@linaro.org> Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org> Signed-off-by: Christoffer Dall <cdall@cs.columbia.edu>
-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) {