linux/virt/kvm/ioapic.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 2001  MandrakeSoft S.A.
   3 *
   4 *    MandrakeSoft S.A.
   5 *    43, rue d'Aboukir
   6 *    75002 Paris - France
   7 *    http://www.linux-mandrake.com/
   8 *    http://www.mandrakesoft.com/
   9 *
  10 *  This library is free software; you can redistribute it and/or
  11 *  modify it under the terms of the GNU Lesser General Public
  12 *  License as published by the Free Software Foundation; either
  13 *  version 2 of the License, or (at your option) any later version.
  14 *
  15 *  This library is distributed in the hope that it will be useful,
  16 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18 *  Lesser General Public License for more details.
  19 *
  20 *  You should have received a copy of the GNU Lesser General Public
  21 *  License along with this library; if not, write to the Free Software
  22 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  23 *
  24 *  Yunhong Jiang <yunhong.jiang@intel.com>
  25 *  Yaozu (Eddie) Dong <eddie.dong@intel.com>
  26 *  Based on Xen 3.1 code.
  27 */
  28
  29#include <linux/kvm_host.h>
  30#include <linux/kvm.h>
  31#include <linux/mm.h>
  32#include <linux/highmem.h>
  33#include <linux/smp.h>
  34#include <linux/hrtimer.h>
  35#include <linux/io.h>
  36#include <asm/processor.h>
  37#include <asm/page.h>
  38#include <asm/current.h>
  39#include <trace/events/kvm.h>
  40
  41#include "ioapic.h"
  42#include "lapic.h"
  43#include "irq.h"
  44
  45#if 0
  46#define ioapic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg)
  47#else
  48#define ioapic_debug(fmt, arg...)
  49#endif
  50static int ioapic_deliver(struct kvm_ioapic *vioapic, int irq);
  51
  52static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
  53                                          unsigned long addr,
  54                                          unsigned long length)
  55{
  56        unsigned long result = 0;
  57
  58        switch (ioapic->ioregsel) {
  59        case IOAPIC_REG_VERSION:
  60                result = ((((IOAPIC_NUM_PINS - 1) & 0xff) << 16)
  61                          | (IOAPIC_VERSION_ID & 0xff));
  62                break;
  63
  64        case IOAPIC_REG_APIC_ID:
  65        case IOAPIC_REG_ARB_ID:
  66                result = ((ioapic->id & 0xf) << 24);
  67                break;
  68
  69        default:
  70                {
  71                        u32 redir_index = (ioapic->ioregsel - 0x10) >> 1;
  72                        u64 redir_content;
  73
  74                        ASSERT(redir_index < IOAPIC_NUM_PINS);
  75
  76                        redir_content = ioapic->redirtbl[redir_index].bits;
  77                        result = (ioapic->ioregsel & 0x1) ?
  78                            (redir_content >> 32) & 0xffffffff :
  79                            redir_content & 0xffffffff;
  80                        break;
  81                }
  82        }
  83
  84        return result;
  85}
  86
  87static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx)
  88{
  89        union kvm_ioapic_redirect_entry *pent;
  90        int injected = -1;
  91
  92        pent = &ioapic->redirtbl[idx];
  93
  94        if (!pent->fields.mask) {
  95                injected = ioapic_deliver(ioapic, idx);
  96                if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG)
  97                        pent->fields.remote_irr = 1;
  98        }
  99
 100        return injected;
 101}
 102
 103static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
 104{
 105        unsigned index;
 106        bool mask_before, mask_after;
 107        union kvm_ioapic_redirect_entry *e;
 108
 109        switch (ioapic->ioregsel) {
 110        case IOAPIC_REG_VERSION:
 111                /* Writes are ignored. */
 112                break;
 113
 114        case IOAPIC_REG_APIC_ID:
 115                ioapic->id = (val >> 24) & 0xf;
 116                break;
 117
 118        case IOAPIC_REG_ARB_ID:
 119                break;
 120
 121        default:
 122                index = (ioapic->ioregsel - 0x10) >> 1;
 123
 124                ioapic_debug("change redir index %x val %x\n", index, val);
 125                if (index >= IOAPIC_NUM_PINS)
 126                        return;
 127                e = &ioapic->redirtbl[index];
 128                mask_before = e->fields.mask;
 129                if (ioapic->ioregsel & 1) {
 130                        e->bits &= 0xffffffff;
 131                        e->bits |= (u64) val << 32;
 132                } else {
 133                        e->bits &= ~0xffffffffULL;
 134                        e->bits |= (u32) val;
 135                        e->fields.remote_irr = 0;
 136                }
 137                mask_after = e->fields.mask;
 138                if (mask_before != mask_after)
 139                        kvm_fire_mask_notifiers(ioapic->kvm, index, mask_after);
 140                if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG
 141                    && ioapic->irr & (1 << index))
 142                        ioapic_service(ioapic, index);
 143                break;
 144        }
 145}
 146
 147static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
 148{
 149        union kvm_ioapic_redirect_entry *entry = &ioapic->redirtbl[irq];
 150        struct kvm_lapic_irq irqe;
 151
 152        ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x "
 153                     "vector=%x trig_mode=%x\n",
 154                     entry->fields.dest, entry->fields.dest_mode,
 155                     entry->fields.delivery_mode, entry->fields.vector,
 156                     entry->fields.trig_mode);
 157
 158        irqe.dest_id = entry->fields.dest_id;
 159        irqe.vector = entry->fields.vector;
 160        irqe.dest_mode = entry->fields.dest_mode;
 161        irqe.trig_mode = entry->fields.trig_mode;
 162        irqe.delivery_mode = entry->fields.delivery_mode << 8;
 163        irqe.level = 1;
 164        irqe.shorthand = 0;
 165
 166#ifdef CONFIG_X86
 167        /* Always delivery PIT interrupt to vcpu 0 */
 168        if (irq == 0) {
 169                irqe.dest_mode = 0; /* Physical mode. */
 170                /* need to read apic_id from apic regiest since
 171                 * it can be rewritten */
 172                irqe.dest_id = ioapic->kvm->bsp_vcpu->vcpu_id;
 173        }
 174#endif
 175        return kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe);
 176}
 177
 178int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
 179{
 180        u32 old_irr = ioapic->irr;
 181        u32 mask = 1 << irq;
 182        union kvm_ioapic_redirect_entry entry;
 183        int ret = 1;
 184
 185        if (irq >= 0 && irq < IOAPIC_NUM_PINS) {
 186                entry = ioapic->redirtbl[irq];
 187                level ^= entry.fields.polarity;
 188                if (!level)
 189                        ioapic->irr &= ~mask;
 190                else {
 191                        int edge = (entry.fields.trig_mode == IOAPIC_EDGE_TRIG);
 192                        ioapic->irr |= mask;
 193                        if ((edge && old_irr != ioapic->irr) ||
 194                            (!edge && !entry.fields.remote_irr))
 195                                ret = ioapic_service(ioapic, irq);
 196                        else
 197                                ret = 0; /* report coalesced interrupt */
 198                }
 199                trace_kvm_ioapic_set_irq(entry.bits, irq, ret == 0);
 200        }
 201        return ret;
 202}
 203
 204static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int pin,
 205                                    int trigger_mode)
 206{
 207        union kvm_ioapic_redirect_entry *ent;
 208
 209        ent = &ioapic->redirtbl[pin];
 210
 211        kvm_notify_acked_irq(ioapic->kvm, KVM_IRQCHIP_IOAPIC, pin);
 212
 213        if (trigger_mode == IOAPIC_LEVEL_TRIG) {
 214                ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG);
 215                ent->fields.remote_irr = 0;
 216                if (!ent->fields.mask && (ioapic->irr & (1 << pin)))
 217                        ioapic_service(ioapic, pin);
 218        }
 219}
 220
 221void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode)
 222{
 223        struct kvm_ioapic *ioapic = kvm->arch.vioapic;
 224        int i;
 225
 226        for (i = 0; i < IOAPIC_NUM_PINS; i++)
 227                if (ioapic->redirtbl[i].fields.vector == vector)
 228                        __kvm_ioapic_update_eoi(ioapic, i, trigger_mode);
 229}
 230
 231static inline struct kvm_ioapic *to_ioapic(struct kvm_io_device *dev)
 232{
 233        return container_of(dev, struct kvm_ioapic, dev);
 234}
 235
 236static inline int ioapic_in_range(struct kvm_ioapic *ioapic, gpa_t addr)
 237{
 238        return ((addr >= ioapic->base_address &&
 239                 (addr < ioapic->base_address + IOAPIC_MEM_LENGTH)));
 240}
 241
 242static int ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len,
 243                            void *val)
 244{
 245        struct kvm_ioapic *ioapic = to_ioapic(this);
 246        u32 result;
 247        if (!ioapic_in_range(ioapic, addr))
 248                return -EOPNOTSUPP;
 249
 250        ioapic_debug("addr %lx\n", (unsigned long)addr);
 251        ASSERT(!(addr & 0xf));  /* check alignment */
 252
 253        mutex_lock(&ioapic->kvm->irq_lock);
 254        addr &= 0xff;
 255        switch (addr) {
 256        case IOAPIC_REG_SELECT:
 257                result = ioapic->ioregsel;
 258                break;
 259
 260        case IOAPIC_REG_WINDOW:
 261                result = ioapic_read_indirect(ioapic, addr, len);
 262                break;
 263
 264        default:
 265                result = 0;
 266                break;
 267        }
 268        switch (len) {
 269        case 8:
 270                *(u64 *) val = result;
 271                break;
 272        case 1:
 273        case 2:
 274        case 4:
 275                memcpy(val, (char *)&result, len);
 276                break;
 277        default:
 278                printk(KERN_WARNING "ioapic: wrong length %d\n", len);
 279        }
 280        mutex_unlock(&ioapic->kvm->irq_lock);
 281        return 0;
 282}
 283
 284static int ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len,
 285                             const void *val)
 286{
 287        struct kvm_ioapic *ioapic = to_ioapic(this);
 288        u32 data;
 289        if (!ioapic_in_range(ioapic, addr))
 290                return -EOPNOTSUPP;
 291
 292        ioapic_debug("ioapic_mmio_write addr=%p len=%d val=%p\n",
 293                     (void*)addr, len, val);
 294        ASSERT(!(addr & 0xf));  /* check alignment */
 295
 296        mutex_lock(&ioapic->kvm->irq_lock);
 297        if (len == 4 || len == 8)
 298                data = *(u32 *) val;
 299        else {
 300                printk(KERN_WARNING "ioapic: Unsupported size %d\n", len);
 301                goto unlock;
 302        }
 303
 304        addr &= 0xff;
 305        switch (addr) {
 306        case IOAPIC_REG_SELECT:
 307                ioapic->ioregsel = data;
 308                break;
 309
 310        case IOAPIC_REG_WINDOW:
 311                ioapic_write_indirect(ioapic, data);
 312                break;
 313#ifdef  CONFIG_IA64
 314        case IOAPIC_REG_EOI:
 315                kvm_ioapic_update_eoi(ioapic->kvm, data, IOAPIC_LEVEL_TRIG);
 316                break;
 317#endif
 318
 319        default:
 320                break;
 321        }
 322unlock:
 323        mutex_unlock(&ioapic->kvm->irq_lock);
 324        return 0;
 325}
 326
 327void kvm_ioapic_reset(struct kvm_ioapic *ioapic)
 328{
 329        int i;
 330
 331        for (i = 0; i < IOAPIC_NUM_PINS; i++)
 332                ioapic->redirtbl[i].fields.mask = 1;
 333        ioapic->base_address = IOAPIC_DEFAULT_BASE_ADDRESS;
 334        ioapic->ioregsel = 0;
 335        ioapic->irr = 0;
 336        ioapic->id = 0;
 337}
 338
 339static const struct kvm_io_device_ops ioapic_mmio_ops = {
 340        .read     = ioapic_mmio_read,
 341        .write    = ioapic_mmio_write,
 342};
 343
 344int kvm_ioapic_init(struct kvm *kvm)
 345{
 346        struct kvm_ioapic *ioapic;
 347        int ret;
 348
 349        ioapic = kzalloc(sizeof(struct kvm_ioapic), GFP_KERNEL);
 350        if (!ioapic)
 351                return -ENOMEM;
 352        kvm->arch.vioapic = ioapic;
 353        kvm_ioapic_reset(ioapic);
 354        kvm_iodevice_init(&ioapic->dev, &ioapic_mmio_ops);
 355        ioapic->kvm = kvm;
 356        ret = kvm_io_bus_register_dev(kvm, &kvm->mmio_bus, &ioapic->dev);
 357        if (ret < 0)
 358                kfree(ioapic);
 359
 360        return ret;
 361}
 362
 363