linux/arch/arm/kvm/arch_timer.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012 ARM Ltd.
   3 * Author: Marc Zyngier <marc.zyngier@arm.com>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, write to the Free Software
  16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 */
  18
  19#include <linux/cpu.h>
  20#include <linux/of_irq.h>
  21#include <linux/kvm.h>
  22#include <linux/kvm_host.h>
  23#include <linux/interrupt.h>
  24
  25#include <clocksource/arm_arch_timer.h>
  26#include <asm/arch_timer.h>
  27
  28#include <asm/kvm_vgic.h>
  29#include <asm/kvm_arch_timer.h>
  30
  31static struct timecounter *timecounter;
  32static struct workqueue_struct *wqueue;
  33static struct kvm_irq_level timer_irq = {
  34        .level  = 1,
  35};
  36
  37static cycle_t kvm_phys_timer_read(void)
  38{
  39        return timecounter->cc->read(timecounter->cc);
  40}
  41
  42static bool timer_is_armed(struct arch_timer_cpu *timer)
  43{
  44        return timer->armed;
  45}
  46
  47/* timer_arm: as in "arm the timer", not as in ARM the company */
  48static void timer_arm(struct arch_timer_cpu *timer, u64 ns)
  49{
  50        timer->armed = true;
  51        hrtimer_start(&timer->timer, ktime_add_ns(ktime_get(), ns),
  52                      HRTIMER_MODE_ABS);
  53}
  54
  55static void timer_disarm(struct arch_timer_cpu *timer)
  56{
  57        if (timer_is_armed(timer)) {
  58                hrtimer_cancel(&timer->timer);
  59                cancel_work_sync(&timer->expired);
  60                timer->armed = false;
  61        }
  62}
  63
  64static void kvm_timer_inject_irq(struct kvm_vcpu *vcpu)
  65{
  66        struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
  67
  68        timer->cntv_ctl |= ARCH_TIMER_CTRL_IT_MASK;
  69        kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
  70                            vcpu->arch.timer_cpu.irq->irq,
  71                            vcpu->arch.timer_cpu.irq->level);
  72}
  73
  74static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id)
  75{
  76        struct kvm_vcpu *vcpu = *(struct kvm_vcpu **)dev_id;
  77
  78        /*
  79         * We disable the timer in the world switch and let it be
  80         * handled by kvm_timer_sync_hwstate(). Getting a timer
  81         * interrupt at this point is a sure sign of some major
  82         * breakage.
  83         */
  84        pr_warn("Unexpected interrupt %d on vcpu %p\n", irq, vcpu);
  85        return IRQ_HANDLED;
  86}
  87
  88static void kvm_timer_inject_irq_work(struct work_struct *work)
  89{
  90        struct kvm_vcpu *vcpu;
  91
  92        vcpu = container_of(work, struct kvm_vcpu, arch.timer_cpu.expired);
  93        vcpu->arch.timer_cpu.armed = false;
  94        kvm_timer_inject_irq(vcpu);
  95}
  96
  97static enum hrtimer_restart kvm_timer_expire(struct hrtimer *hrt)
  98{
  99        struct arch_timer_cpu *timer;
 100        timer = container_of(hrt, struct arch_timer_cpu, timer);
 101        queue_work(wqueue, &timer->expired);
 102        return HRTIMER_NORESTART;
 103}
 104
 105/**
 106 * kvm_timer_flush_hwstate - prepare to move the virt timer to the cpu
 107 * @vcpu: The vcpu pointer
 108 *
 109 * Disarm any pending soft timers, since the world-switch code will write the
 110 * virtual timer state back to the physical CPU.
 111 */
 112void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 113{
 114        struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 115
 116        /*
 117         * We're about to run this vcpu again, so there is no need to
 118         * keep the background timer running, as we're about to
 119         * populate the CPU timer again.
 120         */
 121        timer_disarm(timer);
 122}
 123
 124/**
 125 * kvm_timer_sync_hwstate - sync timer state from cpu
 126 * @vcpu: The vcpu pointer
 127 *
 128 * Check if the virtual timer was armed and either schedule a corresponding
 129 * soft timer or inject directly if already expired.
 130 */
 131void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
 132{
 133        struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 134        cycle_t cval, now;
 135        u64 ns;
 136
 137        if ((timer->cntv_ctl & ARCH_TIMER_CTRL_IT_MASK) ||
 138                !(timer->cntv_ctl & ARCH_TIMER_CTRL_ENABLE))
 139                return;
 140
 141        cval = timer->cntv_cval;
 142        now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
 143
 144        BUG_ON(timer_is_armed(timer));
 145
 146        if (cval <= now) {
 147                /*
 148                 * Timer has already expired while we were not
 149                 * looking. Inject the interrupt and carry on.
 150                 */
 151                kvm_timer_inject_irq(vcpu);
 152                return;
 153        }
 154
 155        ns = cyclecounter_cyc2ns(timecounter->cc, cval - now);
 156        timer_arm(timer, ns);
 157}
 158
 159void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
 160{
 161        struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 162
 163        INIT_WORK(&timer->expired, kvm_timer_inject_irq_work);
 164        hrtimer_init(&timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
 165        timer->timer.function = kvm_timer_expire;
 166        timer->irq = &timer_irq;
 167}
 168
 169static void kvm_timer_init_interrupt(void *info)
 170{
 171        enable_percpu_irq(timer_irq.irq, 0);
 172}
 173
 174
 175static int kvm_timer_cpu_notify(struct notifier_block *self,
 176                                unsigned long action, void *cpu)
 177{
 178        switch (action) {
 179        case CPU_STARTING:
 180        case CPU_STARTING_FROZEN:
 181                kvm_timer_init_interrupt(NULL);
 182                break;
 183        case CPU_DYING:
 184        case CPU_DYING_FROZEN:
 185                disable_percpu_irq(timer_irq.irq);
 186                break;
 187        }
 188
 189        return NOTIFY_OK;
 190}
 191
 192static struct notifier_block kvm_timer_cpu_nb = {
 193        .notifier_call = kvm_timer_cpu_notify,
 194};
 195
 196static const struct of_device_id arch_timer_of_match[] = {
 197        { .compatible   = "arm,armv7-timer",    },
 198        {},
 199};
 200
 201int kvm_timer_hyp_init(void)
 202{
 203        struct device_node *np;
 204        unsigned int ppi;
 205        int err;
 206
 207        timecounter = arch_timer_get_timecounter();
 208        if (!timecounter)
 209                return -ENODEV;
 210
 211        np = of_find_matching_node(NULL, arch_timer_of_match);
 212        if (!np) {
 213                kvm_err("kvm_arch_timer: can't find DT node\n");
 214                return -ENODEV;
 215        }
 216
 217        ppi = irq_of_parse_and_map(np, 2);
 218        if (!ppi) {
 219                kvm_err("kvm_arch_timer: no virtual timer interrupt\n");
 220                err = -EINVAL;
 221                goto out;
 222        }
 223
 224        err = request_percpu_irq(ppi, kvm_arch_timer_handler,
 225                                 "kvm guest timer", kvm_get_running_vcpus());
 226        if (err) {
 227                kvm_err("kvm_arch_timer: can't request interrupt %d (%d)\n",
 228                        ppi, err);
 229                goto out;
 230        }
 231
 232        timer_irq.irq = ppi;
 233
 234        err = register_cpu_notifier(&kvm_timer_cpu_nb);
 235        if (err) {
 236                kvm_err("Cannot register timer CPU notifier\n");
 237                goto out_free;
 238        }
 239
 240        wqueue = create_singlethread_workqueue("kvm_arch_timer");
 241        if (!wqueue) {
 242                err = -ENOMEM;
 243                goto out_free;
 244        }
 245
 246        kvm_info("%s IRQ%d\n", np->name, ppi);
 247        on_each_cpu(kvm_timer_init_interrupt, NULL, 1);
 248
 249        goto out;
 250out_free:
 251        free_percpu_irq(ppi, kvm_get_running_vcpus());
 252out:
 253        of_node_put(np);
 254        return err;
 255}
 256
 257void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
 258{
 259        struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 260
 261        timer_disarm(timer);
 262}
 263
 264int kvm_timer_init(struct kvm *kvm)
 265{
 266        if (timecounter && wqueue) {
 267                kvm->arch.timer.cntvoff = kvm_phys_timer_read();
 268                kvm->arch.timer.enabled = 1;
 269        }
 270
 271        return 0;
 272}
 273