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