1 /* 2 * KVM in-kernel PIC (i8259) 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 "hw/isa/i8259_internal.h" 15 #include "hw/intc/i8259.h" 16 #include "qemu/module.h" 17 #include "hw/i386/apic_internal.h" 18 #include "hw/irq.h" 19 #include "sysemu/kvm.h" 20 #include "qom/object.h" 21 22 #define TYPE_KVM_I8259 "kvm-i8259" 23 typedef struct KVMPICClass KVMPICClass; 24 #define KVM_PIC_CLASS(class) \ 25 OBJECT_CLASS_CHECK(KVMPICClass, (class), TYPE_KVM_I8259) 26 #define KVM_PIC_GET_CLASS(obj) \ 27 OBJECT_GET_CLASS(KVMPICClass, (obj), TYPE_KVM_I8259) 28 29 /** 30 * KVMPICClass: 31 * @parent_realize: The parent's realizefn. 32 */ 33 struct KVMPICClass { 34 PICCommonClass parent_class; 35 36 DeviceRealize parent_realize; 37 }; 38 39 static void kvm_pic_get(PICCommonState *s) 40 { 41 struct kvm_irqchip chip; 42 struct kvm_pic_state *kpic; 43 int ret; 44 45 chip.chip_id = s->master ? KVM_IRQCHIP_PIC_MASTER : KVM_IRQCHIP_PIC_SLAVE; 46 ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, &chip); 47 if (ret < 0) { 48 fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); 49 abort(); 50 } 51 52 kpic = &chip.chip.pic; 53 54 s->last_irr = kpic->last_irr; 55 s->irr = kpic->irr; 56 s->imr = kpic->imr; 57 s->isr = kpic->isr; 58 s->priority_add = kpic->priority_add; 59 s->irq_base = kpic->irq_base; 60 s->read_reg_select = kpic->read_reg_select; 61 s->poll = kpic->poll; 62 s->special_mask = kpic->special_mask; 63 s->init_state = kpic->init_state; 64 s->auto_eoi = kpic->auto_eoi; 65 s->rotate_on_auto_eoi = kpic->rotate_on_auto_eoi; 66 s->special_fully_nested_mode = kpic->special_fully_nested_mode; 67 s->init4 = kpic->init4; 68 s->elcr = kpic->elcr; 69 s->elcr_mask = kpic->elcr_mask; 70 } 71 72 static void kvm_pic_put(PICCommonState *s) 73 { 74 struct kvm_irqchip chip; 75 struct kvm_pic_state *kpic; 76 int ret; 77 78 chip.chip_id = s->master ? KVM_IRQCHIP_PIC_MASTER : KVM_IRQCHIP_PIC_SLAVE; 79 80 kpic = &chip.chip.pic; 81 82 kpic->last_irr = s->last_irr; 83 kpic->irr = s->irr; 84 kpic->imr = s->imr; 85 kpic->isr = s->isr; 86 kpic->priority_add = s->priority_add; 87 kpic->irq_base = s->irq_base; 88 kpic->read_reg_select = s->read_reg_select; 89 kpic->poll = s->poll; 90 kpic->special_mask = s->special_mask; 91 kpic->init_state = s->init_state; 92 kpic->auto_eoi = s->auto_eoi; 93 kpic->rotate_on_auto_eoi = s->rotate_on_auto_eoi; 94 kpic->special_fully_nested_mode = s->special_fully_nested_mode; 95 kpic->init4 = s->init4; 96 kpic->elcr = s->elcr; 97 kpic->elcr_mask = s->elcr_mask; 98 99 ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, &chip); 100 if (ret < 0) { 101 fprintf(stderr, "KVM_SET_IRQCHIP failed: %s\n", strerror(ret)); 102 abort(); 103 } 104 } 105 106 static void kvm_pic_reset(DeviceState *dev) 107 { 108 PICCommonState *s = PIC_COMMON(dev); 109 110 s->elcr = 0; 111 pic_reset_common(s); 112 113 kvm_pic_put(s); 114 } 115 116 static void kvm_pic_set_irq(void *opaque, int irq, int level) 117 { 118 int delivered; 119 120 pic_stat_update_irq(irq, level); 121 delivered = kvm_set_irq(kvm_state, irq, level); 122 apic_report_irq_delivered(delivered); 123 } 124 125 static void kvm_pic_realize(DeviceState *dev, Error **errp) 126 { 127 PICCommonState *s = PIC_COMMON(dev); 128 KVMPICClass *kpc = KVM_PIC_GET_CLASS(dev); 129 130 memory_region_init_io(&s->base_io, OBJECT(dev), NULL, NULL, "kvm-pic", 2); 131 memory_region_init_io(&s->elcr_io, OBJECT(dev), NULL, NULL, "kvm-elcr", 1); 132 133 kpc->parent_realize(dev, errp); 134 } 135 136 qemu_irq *kvm_i8259_init(ISABus *bus) 137 { 138 i8259_init_chip(TYPE_KVM_I8259, bus, true); 139 i8259_init_chip(TYPE_KVM_I8259, bus, false); 140 141 return qemu_allocate_irqs(kvm_pic_set_irq, NULL, ISA_NUM_IRQS); 142 } 143 144 static void kvm_i8259_class_init(ObjectClass *klass, void *data) 145 { 146 KVMPICClass *kpc = KVM_PIC_CLASS(klass); 147 PICCommonClass *k = PIC_COMMON_CLASS(klass); 148 DeviceClass *dc = DEVICE_CLASS(klass); 149 150 dc->reset = kvm_pic_reset; 151 device_class_set_parent_realize(dc, kvm_pic_realize, &kpc->parent_realize); 152 k->pre_save = kvm_pic_get; 153 k->post_load = kvm_pic_put; 154 } 155 156 static const TypeInfo kvm_i8259_info = { 157 .name = TYPE_KVM_I8259, 158 .parent = TYPE_PIC_COMMON, 159 .instance_size = sizeof(PICCommonState), 160 .class_init = kvm_i8259_class_init, 161 .class_size = sizeof(KVMPICClass), 162 }; 163 164 static void kvm_pic_register_types(void) 165 { 166 type_register_static(&kvm_i8259_info); 167 } 168 169 type_init(kvm_pic_register_types) 170