ioapic_common.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * IOAPIC emulation logic - common bits of emulated and KVM kernel model
  3. *
  4. * Copyright (c) 2004-2005 Fabrice Bellard
  5. * Copyright (c) 2009 Xiantao Zhang, Intel
  6. * Copyright (c) 2011 Jan Kiszka, Siemens AG
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #include "qemu/osdep.h"
  22. #include "qapi/error.h"
  23. #include "qemu/module.h"
  24. #include "migration/vmstate.h"
  25. #include "hw/intc/intc.h"
  26. #include "hw/intc/ioapic.h"
  27. #include "hw/intc/ioapic_internal.h"
  28. #include "hw/sysbus.h"
  29. /* ioapic_no count start from 0 to MAX_IOAPICS,
  30. * remove as static variable from ioapic_common_init.
  31. * now as a global variable, let child to increase the counter
  32. * then we can drop the 'instance_no' argument
  33. * and convert to our QOM's realize function
  34. */
  35. int ioapic_no;
  36. void ioapic_stat_update_irq(IOAPICCommonState *s, int irq, int level)
  37. {
  38. if (level != s->irq_level[irq]) {
  39. s->irq_level[irq] = level;
  40. if (level == 1) {
  41. s->irq_count[irq]++;
  42. }
  43. }
  44. }
  45. static bool ioapic_get_statistics(InterruptStatsProvider *obj,
  46. uint64_t **irq_counts,
  47. unsigned int *nb_irqs)
  48. {
  49. IOAPICCommonState *s = IOAPIC_COMMON(obj);
  50. *irq_counts = s->irq_count;
  51. *nb_irqs = IOAPIC_NUM_PINS;
  52. return true;
  53. }
  54. static void ioapic_irr_dump(GString *buf, const char *name, uint32_t bitmap)
  55. {
  56. int i;
  57. g_string_append_printf(buf, "%-10s ", name);
  58. if (bitmap == 0) {
  59. g_string_append_printf(buf, "(none)\n");
  60. return;
  61. }
  62. for (i = 0; i < IOAPIC_NUM_PINS; i++) {
  63. if (bitmap & (1 << i)) {
  64. g_string_append_printf(buf, "%-2u ", i);
  65. }
  66. }
  67. g_string_append_c(buf, '\n');
  68. }
  69. static void ioapic_print_redtbl(GString *buf, IOAPICCommonState *s)
  70. {
  71. static const char *delm_str[] = {
  72. "fixed", "lowest", "SMI", "...", "NMI", "INIT", "...", "extINT"};
  73. uint32_t remote_irr = 0;
  74. int i;
  75. g_string_append_printf(buf, "ioapic0: ver=0x%x id=0x%02x sel=0x%02x",
  76. s->version, s->id, s->ioregsel);
  77. if (s->ioregsel) {
  78. g_string_append_printf(buf, " (redir[%u])\n",
  79. (s->ioregsel - IOAPIC_REG_REDTBL_BASE) >> 1);
  80. } else {
  81. g_string_append_c(buf, '\n');
  82. }
  83. for (i = 0; i < IOAPIC_NUM_PINS; i++) {
  84. uint64_t entry = s->ioredtbl[i];
  85. uint32_t delm = (uint32_t)((entry & IOAPIC_LVT_DELIV_MODE) >>
  86. IOAPIC_LVT_DELIV_MODE_SHIFT);
  87. g_string_append_printf(buf, " pin %-2u 0x%016"PRIx64" dest=%"PRIx64
  88. " vec=%-3"PRIu64" %s %-5s %-6s %-6s %s\n",
  89. i, entry,
  90. (entry >> IOAPIC_LVT_DEST_SHIFT) &
  91. (entry & IOAPIC_LVT_DEST_MODE ? 0xff : 0xf),
  92. entry & IOAPIC_VECTOR_MASK,
  93. entry & IOAPIC_LVT_POLARITY
  94. ? "active-lo" : "active-hi",
  95. entry & IOAPIC_LVT_TRIGGER_MODE
  96. ? "level" : "edge",
  97. entry & IOAPIC_LVT_MASKED ? "masked" : "",
  98. delm_str[delm],
  99. entry & IOAPIC_LVT_DEST_MODE
  100. ? "logical" : "physical");
  101. remote_irr |= entry & IOAPIC_LVT_TRIGGER_MODE ?
  102. (entry & IOAPIC_LVT_REMOTE_IRR ? (1 << i) : 0) : 0;
  103. }
  104. ioapic_irr_dump(buf, " IRR", s->irr);
  105. ioapic_irr_dump(buf, " Remote IRR", remote_irr);
  106. }
  107. void ioapic_reset_common(DeviceState *dev)
  108. {
  109. IOAPICCommonState *s = IOAPIC_COMMON(dev);
  110. int i;
  111. s->id = 0;
  112. s->ioregsel = 0;
  113. s->irr = 0;
  114. for (i = 0; i < IOAPIC_NUM_PINS; i++) {
  115. s->ioredtbl[i] = 1 << IOAPIC_LVT_MASKED_SHIFT;
  116. }
  117. }
  118. static int ioapic_dispatch_pre_save(void *opaque)
  119. {
  120. IOAPICCommonState *s = IOAPIC_COMMON(opaque);
  121. IOAPICCommonClass *info = IOAPIC_COMMON_GET_CLASS(s);
  122. if (info->pre_save) {
  123. info->pre_save(s);
  124. }
  125. return 0;
  126. }
  127. static int ioapic_dispatch_post_load(void *opaque, int version_id)
  128. {
  129. IOAPICCommonState *s = IOAPIC_COMMON(opaque);
  130. IOAPICCommonClass *info = IOAPIC_COMMON_GET_CLASS(s);
  131. if (info->post_load) {
  132. info->post_load(s);
  133. }
  134. return 0;
  135. }
  136. static void ioapic_common_realize(DeviceState *dev, Error **errp)
  137. {
  138. ERRP_GUARD();
  139. IOAPICCommonState *s = IOAPIC_COMMON(dev);
  140. IOAPICCommonClass *info;
  141. if (ioapic_no >= MAX_IOAPICS) {
  142. error_setg(errp, "Only %d ioapics allowed", MAX_IOAPICS);
  143. return;
  144. }
  145. info = IOAPIC_COMMON_GET_CLASS(s);
  146. info->realize(dev, errp);
  147. if (*errp) {
  148. return;
  149. }
  150. sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->io_memory);
  151. ioapic_no++;
  152. }
  153. static void ioapic_print_info(InterruptStatsProvider *obj, GString *buf)
  154. {
  155. IOAPICCommonState *s = IOAPIC_COMMON(obj);
  156. ioapic_dispatch_pre_save(s);
  157. ioapic_print_redtbl(buf, s);
  158. }
  159. static const VMStateDescription vmstate_ioapic_common = {
  160. .name = "ioapic",
  161. .version_id = 3,
  162. .minimum_version_id = 1,
  163. .pre_save = ioapic_dispatch_pre_save,
  164. .post_load = ioapic_dispatch_post_load,
  165. .fields = (const VMStateField[]) {
  166. VMSTATE_UINT8(id, IOAPICCommonState),
  167. VMSTATE_UINT8(ioregsel, IOAPICCommonState),
  168. VMSTATE_UNUSED_V(2, 8), /* to account for qemu-kvm's v2 format */
  169. VMSTATE_UINT32_V(irr, IOAPICCommonState, 2),
  170. VMSTATE_UINT64_ARRAY(ioredtbl, IOAPICCommonState, IOAPIC_NUM_PINS),
  171. VMSTATE_END_OF_LIST()
  172. }
  173. };
  174. static void ioapic_common_class_init(ObjectClass *klass, void *data)
  175. {
  176. DeviceClass *dc = DEVICE_CLASS(klass);
  177. InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(klass);
  178. dc->realize = ioapic_common_realize;
  179. dc->vmsd = &vmstate_ioapic_common;
  180. ic->print_info = ioapic_print_info;
  181. ic->get_statistics = ioapic_get_statistics;
  182. }
  183. static const TypeInfo ioapic_common_type = {
  184. .name = TYPE_IOAPIC_COMMON,
  185. .parent = TYPE_SYS_BUS_DEVICE,
  186. .instance_size = sizeof(IOAPICCommonState),
  187. .class_size = sizeof(IOAPICCommonClass),
  188. .class_init = ioapic_common_class_init,
  189. .abstract = true,
  190. .interfaces = (InterfaceInfo[]) {
  191. { TYPE_INTERRUPT_STATS_PROVIDER },
  192. { }
  193. },
  194. };
  195. static void ioapic_common_register_types(void)
  196. {
  197. type_register_static(&ioapic_common_type);
  198. }
  199. type_init(ioapic_common_register_types)