2
0

ioapic.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /*
  2. * ioapic.c IOAPIC emulation logic
  3. *
  4. * Copyright (c) 2004-2005 Fabrice Bellard
  5. *
  6. * Split the ioapic logic from apic.c
  7. * Xiantao Zhang <xiantao.zhang@intel.com>
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2 of the License, or (at your option) any later version.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  21. */
  22. #include "hw.h"
  23. #include "pc.h"
  24. #include "apic.h"
  25. #include "ioapic.h"
  26. #include "qemu-timer.h"
  27. #include "host-utils.h"
  28. #include "sysbus.h"
  29. //#define DEBUG_IOAPIC
  30. #ifdef DEBUG_IOAPIC
  31. #define DPRINTF(fmt, ...) \
  32. do { printf("ioapic: " fmt , ## __VA_ARGS__); } while (0)
  33. #else
  34. #define DPRINTF(fmt, ...)
  35. #endif
  36. #define MAX_IOAPICS 1
  37. #define IOAPIC_VERSION 0x11
  38. #define IOAPIC_LVT_DEST_SHIFT 56
  39. #define IOAPIC_LVT_MASKED_SHIFT 16
  40. #define IOAPIC_LVT_TRIGGER_MODE_SHIFT 15
  41. #define IOAPIC_LVT_REMOTE_IRR_SHIFT 14
  42. #define IOAPIC_LVT_POLARITY_SHIFT 13
  43. #define IOAPIC_LVT_DELIV_STATUS_SHIFT 12
  44. #define IOAPIC_LVT_DEST_MODE_SHIFT 11
  45. #define IOAPIC_LVT_DELIV_MODE_SHIFT 8
  46. #define IOAPIC_LVT_MASKED (1 << IOAPIC_LVT_MASKED_SHIFT)
  47. #define IOAPIC_LVT_REMOTE_IRR (1 << IOAPIC_LVT_REMOTE_IRR_SHIFT)
  48. #define IOAPIC_TRIGGER_EDGE 0
  49. #define IOAPIC_TRIGGER_LEVEL 1
  50. /*io{apic,sapic} delivery mode*/
  51. #define IOAPIC_DM_FIXED 0x0
  52. #define IOAPIC_DM_LOWEST_PRIORITY 0x1
  53. #define IOAPIC_DM_PMI 0x2
  54. #define IOAPIC_DM_NMI 0x4
  55. #define IOAPIC_DM_INIT 0x5
  56. #define IOAPIC_DM_SIPI 0x6
  57. #define IOAPIC_DM_EXTINT 0x7
  58. #define IOAPIC_DM_MASK 0x7
  59. #define IOAPIC_VECTOR_MASK 0xff
  60. #define IOAPIC_IOREGSEL 0x00
  61. #define IOAPIC_IOWIN 0x10
  62. #define IOAPIC_REG_ID 0x00
  63. #define IOAPIC_REG_VER 0x01
  64. #define IOAPIC_REG_ARB 0x02
  65. #define IOAPIC_REG_REDTBL_BASE 0x10
  66. #define IOAPIC_ID 0x00
  67. #define IOAPIC_ID_SHIFT 24
  68. #define IOAPIC_ID_MASK 0xf
  69. #define IOAPIC_VER_ENTRIES_SHIFT 16
  70. typedef struct IOAPICState IOAPICState;
  71. struct IOAPICState {
  72. SysBusDevice busdev;
  73. uint8_t id;
  74. uint8_t ioregsel;
  75. uint32_t irr;
  76. uint64_t ioredtbl[IOAPIC_NUM_PINS];
  77. };
  78. static IOAPICState *ioapics[MAX_IOAPICS];
  79. static void ioapic_service(IOAPICState *s)
  80. {
  81. uint8_t i;
  82. uint8_t trig_mode;
  83. uint8_t vector;
  84. uint8_t delivery_mode;
  85. uint32_t mask;
  86. uint64_t entry;
  87. uint8_t dest;
  88. uint8_t dest_mode;
  89. for (i = 0; i < IOAPIC_NUM_PINS; i++) {
  90. mask = 1 << i;
  91. if (s->irr & mask) {
  92. entry = s->ioredtbl[i];
  93. if (!(entry & IOAPIC_LVT_MASKED)) {
  94. trig_mode = ((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1);
  95. dest = entry >> IOAPIC_LVT_DEST_SHIFT;
  96. dest_mode = (entry >> IOAPIC_LVT_DEST_MODE_SHIFT) & 1;
  97. delivery_mode =
  98. (entry >> IOAPIC_LVT_DELIV_MODE_SHIFT) & IOAPIC_DM_MASK;
  99. if (trig_mode == IOAPIC_TRIGGER_EDGE) {
  100. s->irr &= ~mask;
  101. } else {
  102. s->ioredtbl[i] |= IOAPIC_LVT_REMOTE_IRR;
  103. }
  104. if (delivery_mode == IOAPIC_DM_EXTINT) {
  105. vector = pic_read_irq(isa_pic);
  106. } else {
  107. vector = entry & IOAPIC_VECTOR_MASK;
  108. }
  109. apic_deliver_irq(dest, dest_mode, delivery_mode,
  110. vector, trig_mode);
  111. }
  112. }
  113. }
  114. }
  115. static void ioapic_set_irq(void *opaque, int vector, int level)
  116. {
  117. IOAPICState *s = opaque;
  118. /* ISA IRQs map to GSI 1-1 except for IRQ0 which maps
  119. * to GSI 2. GSI maps to ioapic 1-1. This is not
  120. * the cleanest way of doing it but it should work. */
  121. DPRINTF("%s: %s vec %x\n", __func__, level ? "raise" : "lower", vector);
  122. if (vector == 0) {
  123. vector = 2;
  124. }
  125. if (vector >= 0 && vector < IOAPIC_NUM_PINS) {
  126. uint32_t mask = 1 << vector;
  127. uint64_t entry = s->ioredtbl[vector];
  128. if (entry & (1 << IOAPIC_LVT_POLARITY_SHIFT)) {
  129. level = !level;
  130. }
  131. if (((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1) ==
  132. IOAPIC_TRIGGER_LEVEL) {
  133. /* level triggered */
  134. if (level) {
  135. s->irr |= mask;
  136. ioapic_service(s);
  137. } else {
  138. s->irr &= ~mask;
  139. }
  140. } else {
  141. /* According to the 82093AA manual, we must ignore edge requests
  142. * if the input pin is masked. */
  143. if (level && !(entry & IOAPIC_LVT_MASKED)) {
  144. s->irr |= mask;
  145. ioapic_service(s);
  146. }
  147. }
  148. }
  149. }
  150. void ioapic_eoi_broadcast(int vector)
  151. {
  152. IOAPICState *s;
  153. uint64_t entry;
  154. int i, n;
  155. for (i = 0; i < MAX_IOAPICS; i++) {
  156. s = ioapics[i];
  157. if (!s) {
  158. continue;
  159. }
  160. for (n = 0; n < IOAPIC_NUM_PINS; n++) {
  161. entry = s->ioredtbl[n];
  162. if ((entry & IOAPIC_LVT_REMOTE_IRR)
  163. && (entry & IOAPIC_VECTOR_MASK) == vector) {
  164. s->ioredtbl[n] = entry & ~IOAPIC_LVT_REMOTE_IRR;
  165. if (!(entry & IOAPIC_LVT_MASKED) && (s->irr & (1 << n))) {
  166. ioapic_service(s);
  167. }
  168. }
  169. }
  170. }
  171. }
  172. static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
  173. {
  174. IOAPICState *s = opaque;
  175. int index;
  176. uint32_t val = 0;
  177. switch (addr & 0xff) {
  178. case IOAPIC_IOREGSEL:
  179. val = s->ioregsel;
  180. break;
  181. case IOAPIC_IOWIN:
  182. switch (s->ioregsel) {
  183. case IOAPIC_REG_ID:
  184. val = s->id << IOAPIC_ID_SHIFT;
  185. break;
  186. case IOAPIC_REG_VER:
  187. val = IOAPIC_VERSION |
  188. ((IOAPIC_NUM_PINS - 1) << IOAPIC_VER_ENTRIES_SHIFT);
  189. break;
  190. case IOAPIC_REG_ARB:
  191. val = 0;
  192. break;
  193. default:
  194. index = (s->ioregsel - IOAPIC_REG_REDTBL_BASE) >> 1;
  195. if (index >= 0 && index < IOAPIC_NUM_PINS) {
  196. if (s->ioregsel & 1) {
  197. val = s->ioredtbl[index] >> 32;
  198. } else {
  199. val = s->ioredtbl[index] & 0xffffffff;
  200. }
  201. }
  202. }
  203. DPRINTF("read: %08x = %08x\n", s->ioregsel, val);
  204. break;
  205. }
  206. return val;
  207. }
  208. static void
  209. ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  210. {
  211. IOAPICState *s = opaque;
  212. int index;
  213. switch (addr & 0xff) {
  214. case IOAPIC_IOREGSEL:
  215. s->ioregsel = val;
  216. break;
  217. case IOAPIC_IOWIN:
  218. DPRINTF("write: %08x = %08x\n", s->ioregsel, val);
  219. switch (s->ioregsel) {
  220. case IOAPIC_REG_ID:
  221. s->id = (val >> IOAPIC_ID_SHIFT) & IOAPIC_ID_MASK;
  222. break;
  223. case IOAPIC_REG_VER:
  224. case IOAPIC_REG_ARB:
  225. break;
  226. default:
  227. index = (s->ioregsel - IOAPIC_REG_REDTBL_BASE) >> 1;
  228. if (index >= 0 && index < IOAPIC_NUM_PINS) {
  229. if (s->ioregsel & 1) {
  230. s->ioredtbl[index] &= 0xffffffff;
  231. s->ioredtbl[index] |= (uint64_t)val << 32;
  232. } else {
  233. s->ioredtbl[index] &= ~0xffffffffULL;
  234. s->ioredtbl[index] |= val;
  235. }
  236. ioapic_service(s);
  237. }
  238. }
  239. break;
  240. }
  241. }
  242. static int ioapic_post_load(void *opaque, int version_id)
  243. {
  244. IOAPICState *s = opaque;
  245. if (version_id == 1) {
  246. /* set sane value */
  247. s->irr = 0;
  248. }
  249. return 0;
  250. }
  251. static const VMStateDescription vmstate_ioapic = {
  252. .name = "ioapic",
  253. .version_id = 3,
  254. .post_load = ioapic_post_load,
  255. .minimum_version_id = 1,
  256. .minimum_version_id_old = 1,
  257. .fields = (VMStateField[]) {
  258. VMSTATE_UINT8(id, IOAPICState),
  259. VMSTATE_UINT8(ioregsel, IOAPICState),
  260. VMSTATE_UNUSED_V(2, 8), /* to account for qemu-kvm's v2 format */
  261. VMSTATE_UINT32_V(irr, IOAPICState, 2),
  262. VMSTATE_UINT64_ARRAY(ioredtbl, IOAPICState, IOAPIC_NUM_PINS),
  263. VMSTATE_END_OF_LIST()
  264. }
  265. };
  266. static void ioapic_reset(DeviceState *d)
  267. {
  268. IOAPICState *s = DO_UPCAST(IOAPICState, busdev.qdev, d);
  269. int i;
  270. s->id = 0;
  271. s->ioregsel = 0;
  272. s->irr = 0;
  273. for (i = 0; i < IOAPIC_NUM_PINS; i++) {
  274. s->ioredtbl[i] = 1 << IOAPIC_LVT_MASKED_SHIFT;
  275. }
  276. }
  277. static CPUReadMemoryFunc * const ioapic_mem_read[3] = {
  278. ioapic_mem_readl,
  279. ioapic_mem_readl,
  280. ioapic_mem_readl,
  281. };
  282. static CPUWriteMemoryFunc * const ioapic_mem_write[3] = {
  283. ioapic_mem_writel,
  284. ioapic_mem_writel,
  285. ioapic_mem_writel,
  286. };
  287. static int ioapic_init1(SysBusDevice *dev)
  288. {
  289. IOAPICState *s = FROM_SYSBUS(IOAPICState, dev);
  290. int io_memory;
  291. static int ioapic_no;
  292. if (ioapic_no >= MAX_IOAPICS) {
  293. return -1;
  294. }
  295. io_memory = cpu_register_io_memory(ioapic_mem_read,
  296. ioapic_mem_write, s,
  297. DEVICE_NATIVE_ENDIAN);
  298. sysbus_init_mmio(dev, 0x1000, io_memory);
  299. qdev_init_gpio_in(&dev->qdev, ioapic_set_irq, IOAPIC_NUM_PINS);
  300. ioapics[ioapic_no++] = s;
  301. return 0;
  302. }
  303. static SysBusDeviceInfo ioapic_info = {
  304. .init = ioapic_init1,
  305. .qdev.name = "ioapic",
  306. .qdev.size = sizeof(IOAPICState),
  307. .qdev.vmsd = &vmstate_ioapic,
  308. .qdev.reset = ioapic_reset,
  309. .qdev.no_user = 1,
  310. };
  311. static void ioapic_register_devices(void)
  312. {
  313. sysbus_register_withprop(&ioapic_info);
  314. }
  315. device_init(ioapic_register_devices)