summaryrefslogtreecommitdiff
path: root/virt/kvm
diff options
context:
space:
mode:
authorAnup Patel <anup.patel@linaro.org>2013-04-30 10:32:15 +0400
committerChristoffer Dall <christoffer.dall@linaro.org>2013-06-26 21:50:02 +0400
commit5ae7f87a56fab10b8f9b135a8377c144397293ca (patch)
tree9bb5b7bcc23d5f3d31783caccc499413678dcdf9 /virt/kvm
parent87d41fb4da6467622b7a87fd6afe8071abab6dae (diff)
downloadlinux-5ae7f87a56fab10b8f9b135a8377c144397293ca.tar.xz
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>
Diffstat (limited to 'virt/kvm')
-rw-r--r--virt/kvm/arm/arch_timer.c29
1 files changed, 20 insertions, 9 deletions
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 @@
static struct timecounter *timecounter;
static struct workqueue_struct *wqueue;
-static struct kvm_irq_level timer_irq = {
- .level = 1,
-};
+static unsigned int host_vtimer_irq;
static cycle_t kvm_phys_timer_read(void)
{
@@ -67,8 +65,8 @@ static void kvm_timer_inject_irq(struct kvm_vcpu *vcpu)
timer->cntv_ctl |= ARCH_TIMER_CTRL_IT_MASK;
kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
- vcpu->arch.timer_cpu.irq->irq,
- vcpu->arch.timer_cpu.irq->level);
+ timer->irq->irq,
+ timer->irq->level);
}
static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id)
@@ -156,6 +154,20 @@ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
timer_arm(timer, ns);
}
+void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
+ const struct kvm_irq_level *irq)
+{
+ struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+
+ /*
+ * The vcpu timer irq number cannot be determined in
+ * kvm_timer_vcpu_init() because it is called much before
+ * kvm_vcpu_set_target(). To handle this, we determine
+ * vcpu timer irq number when the vcpu is reset.
+ */
+ timer->irq = irq;
+}
+
void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
{
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
@@ -163,12 +175,11 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
INIT_WORK(&timer->expired, kvm_timer_inject_irq_work);
hrtimer_init(&timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
timer->timer.function = kvm_timer_expire;
- timer->irq = &timer_irq;
}
static void kvm_timer_init_interrupt(void *info)
{
- enable_percpu_irq(timer_irq.irq, 0);
+ enable_percpu_irq(host_vtimer_irq, 0);
}
@@ -182,7 +193,7 @@ static int kvm_timer_cpu_notify(struct notifier_block *self,
break;
case CPU_DYING:
case CPU_DYING_FROZEN:
- disable_percpu_irq(timer_irq.irq);
+ disable_percpu_irq(host_vtimer_irq);
break;
}
@@ -229,7 +240,7 @@ int kvm_timer_hyp_init(void)
goto out;
}
- timer_irq.irq = ppi;
+ host_vtimer_irq = ppi;
err = register_cpu_notifier(&kvm_timer_cpu_nb);
if (err) {