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