qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

ioapic.c (4299B)


      1 /*
      2  * KVM in-kernel IOPIC support
      3  *
      4  * Copyright (c) 2011 Siemens AG
      5  *
      6  * Authors:
      7  *  Jan Kiszka          <jan.kiszka@siemens.com>
      8  *
      9  * This work is licensed under the terms of the GNU GPL version 2.
     10  * See the COPYING file in the top-level directory.
     11  */
     12 
     13 #include "qemu/osdep.h"
     14 #include "monitor/monitor.h"
     15 #include "hw/i386/x86.h"
     16 #include "hw/qdev-properties.h"
     17 #include "hw/i386/ioapic_internal.h"
     18 #include "hw/i386/apic_internal.h"
     19 #include "sysemu/kvm.h"
     20 
     21 /* PC Utility function */
     22 void kvm_pc_setup_irq_routing(bool pci_enabled)
     23 {
     24     KVMState *s = kvm_state;
     25     int i;
     26 
     27     assert(kvm_has_gsi_routing());
     28     for (i = 0; i < 8; ++i) {
     29         if (i == 2) {
     30             continue;
     31         }
     32         kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_MASTER, i);
     33     }
     34     for (i = 8; i < 16; ++i) {
     35         kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_SLAVE, i - 8);
     36     }
     37     if (pci_enabled) {
     38         for (i = 0; i < 24; ++i) {
     39             if (i == 0) {
     40                 kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, 2);
     41             } else if (i != 2) {
     42                 kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, i);
     43             }
     44         }
     45     }
     46     kvm_irqchip_commit_routes(s);
     47 }
     48 
     49 typedef struct KVMIOAPICState KVMIOAPICState;
     50 
     51 struct KVMIOAPICState {
     52     IOAPICCommonState ioapic;
     53     uint32_t kvm_gsi_base;
     54 };
     55 
     56 static void kvm_ioapic_get(IOAPICCommonState *s)
     57 {
     58     struct kvm_irqchip chip;
     59     struct kvm_ioapic_state *kioapic;
     60     int ret, i;
     61 
     62     chip.chip_id = KVM_IRQCHIP_IOAPIC;
     63     ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, &chip);
     64     if (ret < 0) {
     65         fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(-ret));
     66         abort();
     67     }
     68 
     69     kioapic = &chip.chip.ioapic;
     70 
     71     s->id = kioapic->id;
     72     s->ioregsel = kioapic->ioregsel;
     73     s->irr = kioapic->irr;
     74     for (i = 0; i < IOAPIC_NUM_PINS; i++) {
     75         s->ioredtbl[i] = kioapic->redirtbl[i].bits;
     76     }
     77 }
     78 
     79 static void kvm_ioapic_put(IOAPICCommonState *s)
     80 {
     81     struct kvm_irqchip chip;
     82     struct kvm_ioapic_state *kioapic;
     83     int ret, i;
     84 
     85     chip.chip_id = KVM_IRQCHIP_IOAPIC;
     86     kioapic = &chip.chip.ioapic;
     87 
     88     kioapic->id = s->id;
     89     kioapic->ioregsel = s->ioregsel;
     90     kioapic->base_address = s->busdev.mmio[0].addr;
     91     kioapic->irr = s->irr;
     92     for (i = 0; i < IOAPIC_NUM_PINS; i++) {
     93         kioapic->redirtbl[i].bits = s->ioredtbl[i];
     94     }
     95 
     96     ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, &chip);
     97     if (ret < 0) {
     98         fprintf(stderr, "KVM_SET_IRQCHIP failed: %s\n", strerror(-ret));
     99         abort();
    100     }
    101 }
    102 
    103 static void kvm_ioapic_reset(DeviceState *dev)
    104 {
    105     IOAPICCommonState *s = IOAPIC_COMMON(dev);
    106 
    107     ioapic_reset_common(dev);
    108     kvm_ioapic_put(s);
    109 }
    110 
    111 static void kvm_ioapic_set_irq(void *opaque, int irq, int level)
    112 {
    113     KVMIOAPICState *s = opaque;
    114     IOAPICCommonState *common = IOAPIC_COMMON(s);
    115     int delivered;
    116 
    117     ioapic_stat_update_irq(common, irq, level);
    118     delivered = kvm_set_irq(kvm_state, s->kvm_gsi_base + irq, level);
    119     apic_report_irq_delivered(delivered);
    120 }
    121 
    122 static void kvm_ioapic_realize(DeviceState *dev, Error **errp)
    123 {
    124     IOAPICCommonState *s = IOAPIC_COMMON(dev);
    125 
    126     memory_region_init_io(&s->io_memory, OBJECT(dev), NULL, NULL, "kvm-ioapic", 0x1000);
    127     /*
    128      * KVM ioapic only supports 0x11 now. This will only be used when
    129      * we want to dump ioapic version.
    130      */
    131     s->version = 0x11;
    132 
    133     qdev_init_gpio_in(dev, kvm_ioapic_set_irq, IOAPIC_NUM_PINS);
    134 }
    135 
    136 static Property kvm_ioapic_properties[] = {
    137     DEFINE_PROP_UINT32("gsi_base", KVMIOAPICState, kvm_gsi_base, 0),
    138     DEFINE_PROP_END_OF_LIST()
    139 };
    140 
    141 static void kvm_ioapic_class_init(ObjectClass *klass, void *data)
    142 {
    143     IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass);
    144     DeviceClass *dc = DEVICE_CLASS(klass);
    145 
    146     k->realize   = kvm_ioapic_realize;
    147     k->pre_save  = kvm_ioapic_get;
    148     k->post_load = kvm_ioapic_put;
    149     dc->reset    = kvm_ioapic_reset;
    150     device_class_set_props(dc, kvm_ioapic_properties);
    151 }
    152 
    153 static const TypeInfo kvm_ioapic_info = {
    154     .name  = TYPE_KVM_IOAPIC,
    155     .parent = TYPE_IOAPIC_COMMON,
    156     .instance_size = sizeof(KVMIOAPICState),
    157     .class_init = kvm_ioapic_class_init,
    158 };
    159 
    160 static void kvm_ioapic_register_types(void)
    161 {
    162     type_register_static(&kvm_ioapic_info);
    163 }
    164 
    165 type_init(kvm_ioapic_register_types)