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 "hw/i386/pc.h" 14 #include "hw/i386/ioapic_internal.h" 15 #include "hw/i386/apic_internal.h" 16 #include "sysemu/kvm.h" 17 18 /* PC Utility function */ 19 void kvm_pc_setup_irq_routing(bool pci_enabled) 20 { 21 KVMState *s = kvm_state; 22 int i; 23 24 if (kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) { 25 for (i = 0; i < 8; ++i) { 26 if (i == 2) { 27 continue; 28 } 29 kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_MASTER, i); 30 } 31 for (i = 8; i < 16; ++i) { 32 kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_SLAVE, i - 8); 33 } 34 if (pci_enabled) { 35 for (i = 0; i < 24; ++i) { 36 if (i == 0) { 37 kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, 2); 38 } else if (i != 2) { 39 kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, i); 40 } 41 } 42 } 43 kvm_irqchip_commit_routes(s); 44 } 45 } 46 47 void kvm_pc_gsi_handler(void *opaque, int n, int level) 48 { 49 GSIState *s = opaque; 50 51 if (n < ISA_NUM_IRQS) { 52 /* Kernel will forward to both PIC and IOAPIC */ 53 qemu_set_irq(s->i8259_irq[n], level); 54 } else { 55 qemu_set_irq(s->ioapic_irq[n], level); 56 } 57 } 58 59 typedef struct KVMIOAPICState KVMIOAPICState; 60 61 struct KVMIOAPICState { 62 IOAPICCommonState ioapic; 63 uint32_t kvm_gsi_base; 64 }; 65 66 static void kvm_ioapic_get(IOAPICCommonState *s) 67 { 68 struct kvm_irqchip chip; 69 struct kvm_ioapic_state *kioapic; 70 int ret, i; 71 72 chip.chip_id = KVM_IRQCHIP_IOAPIC; 73 ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, &chip); 74 if (ret < 0) { 75 fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); 76 abort(); 77 } 78 79 kioapic = &chip.chip.ioapic; 80 81 s->id = kioapic->id; 82 s->ioregsel = kioapic->ioregsel; 83 s->irr = kioapic->irr; 84 for (i = 0; i < IOAPIC_NUM_PINS; i++) { 85 s->ioredtbl[i] = kioapic->redirtbl[i].bits; 86 } 87 } 88 89 static void kvm_ioapic_put(IOAPICCommonState *s) 90 { 91 struct kvm_irqchip chip; 92 struct kvm_ioapic_state *kioapic; 93 int ret, i; 94 95 chip.chip_id = KVM_IRQCHIP_IOAPIC; 96 kioapic = &chip.chip.ioapic; 97 98 kioapic->id = s->id; 99 kioapic->ioregsel = s->ioregsel; 100 kioapic->base_address = s->busdev.mmio[0].addr; 101 kioapic->irr = s->irr; 102 for (i = 0; i < IOAPIC_NUM_PINS; i++) { 103 kioapic->redirtbl[i].bits = s->ioredtbl[i]; 104 } 105 106 ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, &chip); 107 if (ret < 0) { 108 fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); 109 abort(); 110 } 111 } 112 113 static void kvm_ioapic_reset(DeviceState *dev) 114 { 115 IOAPICCommonState *s = IOAPIC_COMMON(dev); 116 117 ioapic_reset_common(dev); 118 kvm_ioapic_put(s); 119 } 120 121 static void kvm_ioapic_set_irq(void *opaque, int irq, int level) 122 { 123 KVMIOAPICState *s = opaque; 124 int delivered; 125 126 delivered = kvm_set_irq(kvm_state, s->kvm_gsi_base + irq, level); 127 apic_report_irq_delivered(delivered); 128 } 129 130 static void kvm_ioapic_realize(DeviceState *dev, Error **errp) 131 { 132 IOAPICCommonState *s = IOAPIC_COMMON(dev); 133 134 memory_region_init_reservation(&s->io_memory, NULL, "kvm-ioapic", 0x1000); 135 136 qdev_init_gpio_in(dev, kvm_ioapic_set_irq, IOAPIC_NUM_PINS); 137 } 138 139 static Property kvm_ioapic_properties[] = { 140 DEFINE_PROP_UINT32("gsi_base", KVMIOAPICState, kvm_gsi_base, 0), 141 DEFINE_PROP_END_OF_LIST() 142 }; 143 144 static void kvm_ioapic_class_init(ObjectClass *klass, void *data) 145 { 146 IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass); 147 DeviceClass *dc = DEVICE_CLASS(klass); 148 149 k->realize = kvm_ioapic_realize; 150 k->pre_save = kvm_ioapic_get; 151 k->post_load = kvm_ioapic_put; 152 dc->reset = kvm_ioapic_reset; 153 dc->props = kvm_ioapic_properties; 154 } 155 156 static const TypeInfo kvm_ioapic_info = { 157 .name = "kvm-ioapic", 158 .parent = TYPE_IOAPIC_COMMON, 159 .instance_size = sizeof(KVMIOAPICState), 160 .class_init = kvm_ioapic_class_init, 161 }; 162 163 static void kvm_ioapic_register_types(void) 164 { 165 type_register_static(&kvm_ioapic_info); 166 } 167 168 type_init(kvm_ioapic_register_types) 169