openpic_kvm.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /*
  2. * KVM in-kernel OpenPIC
  3. *
  4. * Copyright 2013 Freescale Semiconductor, Inc.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "qemu/osdep.h"
  25. #include "qapi/error.h"
  26. #include <sys/ioctl.h>
  27. #include "hw/ppc/openpic.h"
  28. #include "hw/ppc/openpic_kvm.h"
  29. #include "hw/pci/msi.h"
  30. #include "hw/qdev-properties.h"
  31. #include "hw/sysbus.h"
  32. #include "sysemu/kvm.h"
  33. #include "qemu/log.h"
  34. #include "qemu/module.h"
  35. #include "qom/object.h"
  36. #define GCR_RESET 0x80000000
  37. OBJECT_DECLARE_SIMPLE_TYPE(KVMOpenPICState, KVM_OPENPIC)
  38. struct KVMOpenPICState {
  39. /*< private >*/
  40. SysBusDevice parent_obj;
  41. /*< public >*/
  42. MemoryRegion mem;
  43. MemoryListener mem_listener;
  44. uint32_t fd;
  45. uint32_t model;
  46. hwaddr mapped;
  47. };
  48. static void kvm_openpic_set_irq(void *opaque, int n_IRQ, int level)
  49. {
  50. kvm_set_irq(kvm_state, n_IRQ, level);
  51. }
  52. static void kvm_openpic_write(void *opaque, hwaddr addr, uint64_t val,
  53. unsigned size)
  54. {
  55. KVMOpenPICState *opp = opaque;
  56. struct kvm_device_attr attr;
  57. uint32_t val32 = val;
  58. int ret;
  59. attr.group = KVM_DEV_MPIC_GRP_REGISTER;
  60. attr.attr = addr;
  61. attr.addr = (uint64_t)(unsigned long)&val32;
  62. ret = ioctl(opp->fd, KVM_SET_DEVICE_ATTR, &attr);
  63. if (ret < 0) {
  64. qemu_log_mask(LOG_UNIMP, "%s: %s %" PRIx64 "\n", __func__,
  65. strerror(errno), attr.attr);
  66. }
  67. }
  68. static void kvm_openpic_reset(DeviceState *d)
  69. {
  70. KVMOpenPICState *opp = KVM_OPENPIC(d);
  71. /* Trigger the GCR.RESET bit to reset the PIC */
  72. kvm_openpic_write(opp, 0x1020, GCR_RESET, sizeof(uint32_t));
  73. }
  74. static uint64_t kvm_openpic_read(void *opaque, hwaddr addr, unsigned size)
  75. {
  76. KVMOpenPICState *opp = opaque;
  77. struct kvm_device_attr attr;
  78. uint32_t val = 0xdeadbeef;
  79. int ret;
  80. attr.group = KVM_DEV_MPIC_GRP_REGISTER;
  81. attr.attr = addr;
  82. attr.addr = (uint64_t)(unsigned long)&val;
  83. ret = ioctl(opp->fd, KVM_GET_DEVICE_ATTR, &attr);
  84. if (ret < 0) {
  85. qemu_log_mask(LOG_UNIMP, "%s: %s %" PRIx64 "\n", __func__,
  86. strerror(errno), attr.attr);
  87. return 0;
  88. }
  89. return val;
  90. }
  91. static const MemoryRegionOps kvm_openpic_mem_ops = {
  92. .write = kvm_openpic_write,
  93. .read = kvm_openpic_read,
  94. .endianness = DEVICE_BIG_ENDIAN,
  95. .impl = {
  96. .min_access_size = 4,
  97. .max_access_size = 4,
  98. },
  99. };
  100. static void kvm_openpic_region_add(MemoryListener *listener,
  101. MemoryRegionSection *section)
  102. {
  103. KVMOpenPICState *opp = container_of(listener, KVMOpenPICState,
  104. mem_listener);
  105. struct kvm_device_attr attr;
  106. uint64_t reg_base;
  107. int ret;
  108. /* Ignore events on regions that are not us */
  109. if (section->mr != &opp->mem) {
  110. return;
  111. }
  112. if (opp->mapped) {
  113. /*
  114. * We can only map the MPIC once. Since we are already mapped,
  115. * the best we can do is ignore new maps.
  116. */
  117. return;
  118. }
  119. reg_base = section->offset_within_address_space;
  120. opp->mapped = reg_base;
  121. attr.group = KVM_DEV_MPIC_GRP_MISC;
  122. attr.attr = KVM_DEV_MPIC_BASE_ADDR;
  123. attr.addr = (uint64_t)(unsigned long)&reg_base;
  124. ret = ioctl(opp->fd, KVM_SET_DEVICE_ATTR, &attr);
  125. if (ret < 0) {
  126. fprintf(stderr, "%s: %s %" PRIx64 "\n", __func__,
  127. strerror(errno), reg_base);
  128. }
  129. }
  130. static void kvm_openpic_region_del(MemoryListener *listener,
  131. MemoryRegionSection *section)
  132. {
  133. KVMOpenPICState *opp = container_of(listener, KVMOpenPICState,
  134. mem_listener);
  135. struct kvm_device_attr attr;
  136. uint64_t reg_base = 0;
  137. int ret;
  138. /* Ignore events on regions that are not us */
  139. if (section->mr != &opp->mem) {
  140. return;
  141. }
  142. if (section->offset_within_address_space != opp->mapped) {
  143. /*
  144. * We can only map the MPIC once. This mapping was a secondary
  145. * one that we couldn't fulfill. Ignore it.
  146. */
  147. return;
  148. }
  149. opp->mapped = 0;
  150. attr.group = KVM_DEV_MPIC_GRP_MISC;
  151. attr.attr = KVM_DEV_MPIC_BASE_ADDR;
  152. attr.addr = (uint64_t)(unsigned long)&reg_base;
  153. ret = ioctl(opp->fd, KVM_SET_DEVICE_ATTR, &attr);
  154. if (ret < 0) {
  155. fprintf(stderr, "%s: %s %" PRIx64 "\n", __func__,
  156. strerror(errno), reg_base);
  157. }
  158. }
  159. static void kvm_openpic_init(Object *obj)
  160. {
  161. KVMOpenPICState *opp = KVM_OPENPIC(obj);
  162. memory_region_init_io(&opp->mem, OBJECT(opp), &kvm_openpic_mem_ops, opp,
  163. "kvm-openpic", 0x40000);
  164. }
  165. static void kvm_openpic_realize(DeviceState *dev, Error **errp)
  166. {
  167. SysBusDevice *d = SYS_BUS_DEVICE(dev);
  168. KVMOpenPICState *opp = KVM_OPENPIC(dev);
  169. KVMState *s = kvm_state;
  170. int kvm_openpic_model;
  171. struct kvm_create_device cd = {0};
  172. int ret, i;
  173. if (!kvm_check_extension(s, KVM_CAP_DEVICE_CTRL)) {
  174. error_setg(errp, "Kernel is lacking Device Control API");
  175. return;
  176. }
  177. switch (opp->model) {
  178. case OPENPIC_MODEL_FSL_MPIC_20:
  179. kvm_openpic_model = KVM_DEV_TYPE_FSL_MPIC_20;
  180. break;
  181. case OPENPIC_MODEL_FSL_MPIC_42:
  182. kvm_openpic_model = KVM_DEV_TYPE_FSL_MPIC_42;
  183. break;
  184. default:
  185. error_setg(errp, "Unsupported OpenPIC model %" PRIu32, opp->model);
  186. return;
  187. }
  188. cd.type = kvm_openpic_model;
  189. ret = kvm_vm_ioctl(s, KVM_CREATE_DEVICE, &cd);
  190. if (ret < 0) {
  191. error_setg(errp, "Can't create device %d: %s",
  192. cd.type, strerror(errno));
  193. return;
  194. }
  195. opp->fd = cd.fd;
  196. sysbus_init_mmio(d, &opp->mem);
  197. qdev_init_gpio_in(dev, kvm_openpic_set_irq, OPENPIC_MAX_IRQ);
  198. opp->mem_listener.region_add = kvm_openpic_region_add;
  199. opp->mem_listener.region_del = kvm_openpic_region_del;
  200. opp->mem_listener.name = "openpic-kvm";
  201. memory_listener_register(&opp->mem_listener, &address_space_memory);
  202. /* indicate pic capabilities */
  203. msi_nonbroken = true;
  204. kvm_kernel_irqchip = true;
  205. kvm_async_interrupts_allowed = true;
  206. /* set up irq routing */
  207. kvm_init_irq_routing(kvm_state);
  208. for (i = 0; i < 256; ++i) {
  209. kvm_irqchip_add_irq_route(kvm_state, i, 0, i);
  210. }
  211. kvm_msi_via_irqfd_allowed = true;
  212. kvm_gsi_routing_allowed = true;
  213. kvm_irqchip_commit_routes(s);
  214. }
  215. int kvm_openpic_connect_vcpu(DeviceState *d, CPUState *cs)
  216. {
  217. KVMOpenPICState *opp = KVM_OPENPIC(d);
  218. return kvm_vcpu_enable_cap(cs, KVM_CAP_IRQ_MPIC, 0, opp->fd,
  219. kvm_arch_vcpu_id(cs));
  220. }
  221. static Property kvm_openpic_properties[] = {
  222. DEFINE_PROP_UINT32("model", KVMOpenPICState, model,
  223. OPENPIC_MODEL_FSL_MPIC_20),
  224. DEFINE_PROP_END_OF_LIST(),
  225. };
  226. static void kvm_openpic_class_init(ObjectClass *oc, void *data)
  227. {
  228. DeviceClass *dc = DEVICE_CLASS(oc);
  229. dc->realize = kvm_openpic_realize;
  230. device_class_set_props(dc, kvm_openpic_properties);
  231. dc->reset = kvm_openpic_reset;
  232. set_bit(DEVICE_CATEGORY_MISC, dc->categories);
  233. }
  234. static const TypeInfo kvm_openpic_info = {
  235. .name = TYPE_KVM_OPENPIC,
  236. .parent = TYPE_SYS_BUS_DEVICE,
  237. .instance_size = sizeof(KVMOpenPICState),
  238. .instance_init = kvm_openpic_init,
  239. .class_init = kvm_openpic_class_init,
  240. };
  241. static void kvm_openpic_register_types(void)
  242. {
  243. type_register_static(&kvm_openpic_info);
  244. }
  245. type_init(kvm_openpic_register_types)