spapr_vio.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. /*
  2. * QEMU sPAPR VIO code
  3. *
  4. * Copyright (c) 2010 David Gibson, IBM Corporation <dwg@au1.ibm.com>
  5. * Based on the s390 virtio bus code:
  6. * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
  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 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 "hw.h"
  22. #include "sysemu/sysemu.h"
  23. #include "boards.h"
  24. #include "monitor/monitor.h"
  25. #include "loader.h"
  26. #include "elf.h"
  27. #include "hw/sysbus.h"
  28. #include "sysemu/kvm.h"
  29. #include "sysemu/device_tree.h"
  30. #include "kvm_ppc.h"
  31. #include "hw/spapr.h"
  32. #include "hw/spapr_vio.h"
  33. #include "hw/xics.h"
  34. #ifdef CONFIG_FDT
  35. #include <libfdt.h>
  36. #endif /* CONFIG_FDT */
  37. /* #define DEBUG_SPAPR */
  38. #ifdef DEBUG_SPAPR
  39. #define dprintf(fmt, ...) \
  40. do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
  41. #else
  42. #define dprintf(fmt, ...) \
  43. do { } while (0)
  44. #endif
  45. static Property spapr_vio_props[] = {
  46. DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, irq, 0), \
  47. DEFINE_PROP_END_OF_LIST(),
  48. };
  49. static const TypeInfo spapr_vio_bus_info = {
  50. .name = TYPE_SPAPR_VIO_BUS,
  51. .parent = TYPE_BUS,
  52. .instance_size = sizeof(VIOsPAPRBus),
  53. };
  54. VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
  55. {
  56. BusChild *kid;
  57. VIOsPAPRDevice *dev = NULL;
  58. QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
  59. dev = (VIOsPAPRDevice *)kid->child;
  60. if (dev->reg == reg) {
  61. return dev;
  62. }
  63. }
  64. return NULL;
  65. }
  66. static char *vio_format_dev_name(VIOsPAPRDevice *dev)
  67. {
  68. VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
  69. char *name;
  70. /* Device tree style name device@reg */
  71. name = g_strdup_printf("%s@%x", pc->dt_name, dev->reg);
  72. return name;
  73. }
  74. #ifdef CONFIG_FDT
  75. static int vio_make_devnode(VIOsPAPRDevice *dev,
  76. void *fdt)
  77. {
  78. VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
  79. int vdevice_off, node_off, ret;
  80. char *dt_name;
  81. vdevice_off = fdt_path_offset(fdt, "/vdevice");
  82. if (vdevice_off < 0) {
  83. return vdevice_off;
  84. }
  85. dt_name = vio_format_dev_name(dev);
  86. node_off = fdt_add_subnode(fdt, vdevice_off, dt_name);
  87. g_free(dt_name);
  88. if (node_off < 0) {
  89. return node_off;
  90. }
  91. ret = fdt_setprop_cell(fdt, node_off, "reg", dev->reg);
  92. if (ret < 0) {
  93. return ret;
  94. }
  95. if (pc->dt_type) {
  96. ret = fdt_setprop_string(fdt, node_off, "device_type",
  97. pc->dt_type);
  98. if (ret < 0) {
  99. return ret;
  100. }
  101. }
  102. if (pc->dt_compatible) {
  103. ret = fdt_setprop_string(fdt, node_off, "compatible",
  104. pc->dt_compatible);
  105. if (ret < 0) {
  106. return ret;
  107. }
  108. }
  109. if (dev->irq) {
  110. uint32_t ints_prop[] = {cpu_to_be32(dev->irq), 0};
  111. ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop,
  112. sizeof(ints_prop));
  113. if (ret < 0) {
  114. return ret;
  115. }
  116. }
  117. ret = spapr_tcet_dma_dt(fdt, node_off, "ibm,my-dma-window", dev->dma);
  118. if (ret < 0) {
  119. return ret;
  120. }
  121. if (pc->devnode) {
  122. ret = (pc->devnode)(dev, fdt, node_off);
  123. if (ret < 0) {
  124. return ret;
  125. }
  126. }
  127. return node_off;
  128. }
  129. #endif /* CONFIG_FDT */
  130. /*
  131. * CRQ handling
  132. */
  133. static target_ulong h_reg_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr,
  134. target_ulong opcode, target_ulong *args)
  135. {
  136. target_ulong reg = args[0];
  137. target_ulong queue_addr = args[1];
  138. target_ulong queue_len = args[2];
  139. VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
  140. if (!dev) {
  141. hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
  142. return H_PARAMETER;
  143. }
  144. /* We can't grok a queue size bigger than 256M for now */
  145. if (queue_len < 0x1000 || queue_len > 0x10000000) {
  146. hcall_dprintf("Queue size too small or too big (0x" TARGET_FMT_lx
  147. ")\n", queue_len);
  148. return H_PARAMETER;
  149. }
  150. /* Check queue alignment */
  151. if (queue_addr & 0xfff) {
  152. hcall_dprintf("Queue not aligned (0x" TARGET_FMT_lx ")\n", queue_addr);
  153. return H_PARAMETER;
  154. }
  155. /* Check if device supports CRQs */
  156. if (!dev->crq.SendFunc) {
  157. hcall_dprintf("Device does not support CRQ\n");
  158. return H_NOT_FOUND;
  159. }
  160. /* Already a queue ? */
  161. if (dev->crq.qsize) {
  162. hcall_dprintf("CRQ already registered\n");
  163. return H_RESOURCE;
  164. }
  165. dev->crq.qladdr = queue_addr;
  166. dev->crq.qsize = queue_len;
  167. dev->crq.qnext = 0;
  168. dprintf("CRQ for dev 0x" TARGET_FMT_lx " registered at 0x"
  169. TARGET_FMT_lx "/0x" TARGET_FMT_lx "\n",
  170. reg, queue_addr, queue_len);
  171. return H_SUCCESS;
  172. }
  173. static target_ulong free_crq(VIOsPAPRDevice *dev)
  174. {
  175. dev->crq.qladdr = 0;
  176. dev->crq.qsize = 0;
  177. dev->crq.qnext = 0;
  178. dprintf("CRQ for dev 0x%" PRIx32 " freed\n", dev->reg);
  179. return H_SUCCESS;
  180. }
  181. static target_ulong h_free_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr,
  182. target_ulong opcode, target_ulong *args)
  183. {
  184. target_ulong reg = args[0];
  185. VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
  186. if (!dev) {
  187. hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
  188. return H_PARAMETER;
  189. }
  190. return free_crq(dev);
  191. }
  192. static target_ulong h_send_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr,
  193. target_ulong opcode, target_ulong *args)
  194. {
  195. target_ulong reg = args[0];
  196. target_ulong msg_hi = args[1];
  197. target_ulong msg_lo = args[2];
  198. VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
  199. uint64_t crq_mangle[2];
  200. if (!dev) {
  201. hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
  202. return H_PARAMETER;
  203. }
  204. crq_mangle[0] = cpu_to_be64(msg_hi);
  205. crq_mangle[1] = cpu_to_be64(msg_lo);
  206. if (dev->crq.SendFunc) {
  207. return dev->crq.SendFunc(dev, (uint8_t *)crq_mangle);
  208. }
  209. return H_HARDWARE;
  210. }
  211. static target_ulong h_enable_crq(PowerPCCPU *cpu, sPAPREnvironment *spapr,
  212. target_ulong opcode, target_ulong *args)
  213. {
  214. target_ulong reg = args[0];
  215. VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
  216. if (!dev) {
  217. hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
  218. return H_PARAMETER;
  219. }
  220. return 0;
  221. }
  222. /* Returns negative error, 0 success, or positive: queue full */
  223. int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq)
  224. {
  225. int rc;
  226. uint8_t byte;
  227. if (!dev->crq.qsize) {
  228. fprintf(stderr, "spapr_vio_send_creq on uninitialized queue\n");
  229. return -1;
  230. }
  231. /* Maybe do a fast path for KVM just writing to the pages */
  232. rc = spapr_vio_dma_read(dev, dev->crq.qladdr + dev->crq.qnext, &byte, 1);
  233. if (rc) {
  234. return rc;
  235. }
  236. if (byte != 0) {
  237. return 1;
  238. }
  239. rc = spapr_vio_dma_write(dev, dev->crq.qladdr + dev->crq.qnext + 8,
  240. &crq[8], 8);
  241. if (rc) {
  242. return rc;
  243. }
  244. kvmppc_eieio();
  245. rc = spapr_vio_dma_write(dev, dev->crq.qladdr + dev->crq.qnext, crq, 8);
  246. if (rc) {
  247. return rc;
  248. }
  249. dev->crq.qnext = (dev->crq.qnext + 16) % dev->crq.qsize;
  250. if (dev->signal_state & 1) {
  251. qemu_irq_pulse(spapr_vio_qirq(dev));
  252. }
  253. return 0;
  254. }
  255. /* "quiesce" handling */
  256. static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev)
  257. {
  258. if (dev->dma) {
  259. spapr_tce_reset(dev->dma);
  260. }
  261. free_crq(dev);
  262. }
  263. static void rtas_set_tce_bypass(sPAPREnvironment *spapr, uint32_t token,
  264. uint32_t nargs, target_ulong args,
  265. uint32_t nret, target_ulong rets)
  266. {
  267. VIOsPAPRBus *bus = spapr->vio_bus;
  268. VIOsPAPRDevice *dev;
  269. uint32_t unit, enable;
  270. if (nargs != 2) {
  271. rtas_st(rets, 0, -3);
  272. return;
  273. }
  274. unit = rtas_ld(args, 0);
  275. enable = rtas_ld(args, 1);
  276. dev = spapr_vio_find_by_reg(bus, unit);
  277. if (!dev) {
  278. rtas_st(rets, 0, -3);
  279. return;
  280. }
  281. if (!dev->dma) {
  282. rtas_st(rets, 0, -3);
  283. return;
  284. }
  285. spapr_tce_set_bypass(dev->dma, !!enable);
  286. rtas_st(rets, 0, 0);
  287. }
  288. static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
  289. uint32_t nargs, target_ulong args,
  290. uint32_t nret, target_ulong rets)
  291. {
  292. VIOsPAPRBus *bus = spapr->vio_bus;
  293. BusChild *kid;
  294. VIOsPAPRDevice *dev = NULL;
  295. if (nargs != 0) {
  296. rtas_st(rets, 0, -3);
  297. return;
  298. }
  299. QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
  300. dev = (VIOsPAPRDevice *)kid->child;
  301. spapr_vio_quiesce_one(dev);
  302. }
  303. rtas_st(rets, 0, 0);
  304. }
  305. static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
  306. {
  307. VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
  308. BusChild *kid;
  309. VIOsPAPRDevice *other;
  310. /*
  311. * Check for a device other than the given one which is already
  312. * using the requested address. We have to open code this because
  313. * the given dev might already be in the list.
  314. */
  315. QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
  316. other = DO_UPCAST(VIOsPAPRDevice, qdev, kid->child);
  317. if (other != dev && other->reg == dev->reg) {
  318. return other;
  319. }
  320. }
  321. return 0;
  322. }
  323. static void spapr_vio_busdev_reset(DeviceState *qdev)
  324. {
  325. VIOsPAPRDevice *dev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
  326. VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
  327. /* Shut down the request queue and TCEs if necessary */
  328. spapr_vio_quiesce_one(dev);
  329. dev->signal_state = 0;
  330. if (pc->reset) {
  331. pc->reset(dev);
  332. }
  333. }
  334. static int spapr_vio_busdev_init(DeviceState *qdev)
  335. {
  336. VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
  337. VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
  338. char *id;
  339. if (dev->reg != -1) {
  340. /*
  341. * Explicitly assigned address, just verify that no-one else
  342. * is using it. other mechanism). We have to open code this
  343. * rather than using spapr_vio_find_by_reg() because sdev
  344. * itself is already in the list.
  345. */
  346. VIOsPAPRDevice *other = reg_conflict(dev);
  347. if (other) {
  348. fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n",
  349. object_get_typename(OBJECT(qdev)),
  350. object_get_typename(OBJECT(&other->qdev)),
  351. dev->reg);
  352. return -1;
  353. }
  354. } else {
  355. /* Need to assign an address */
  356. VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
  357. do {
  358. dev->reg = bus->next_reg++;
  359. } while (reg_conflict(dev));
  360. }
  361. /* Don't overwrite ids assigned on the command line */
  362. if (!dev->qdev.id) {
  363. id = vio_format_dev_name(dev);
  364. dev->qdev.id = id;
  365. }
  366. dev->irq = spapr_allocate_msi(dev->irq);
  367. if (!dev->irq) {
  368. return -1;
  369. }
  370. if (pc->rtce_window_size) {
  371. uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
  372. dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size);
  373. }
  374. return pc->init(dev);
  375. }
  376. static target_ulong h_vio_signal(PowerPCCPU *cpu, sPAPREnvironment *spapr,
  377. target_ulong opcode,
  378. target_ulong *args)
  379. {
  380. target_ulong reg = args[0];
  381. target_ulong mode = args[1];
  382. VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
  383. VIOsPAPRDeviceClass *pc;
  384. if (!dev) {
  385. return H_PARAMETER;
  386. }
  387. pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
  388. if (mode & ~pc->signal_mask) {
  389. return H_PARAMETER;
  390. }
  391. dev->signal_state = mode;
  392. return H_SUCCESS;
  393. }
  394. VIOsPAPRBus *spapr_vio_bus_init(void)
  395. {
  396. VIOsPAPRBus *bus;
  397. BusState *qbus;
  398. DeviceState *dev;
  399. /* Create bridge device */
  400. dev = qdev_create(NULL, "spapr-vio-bridge");
  401. qdev_init_nofail(dev);
  402. /* Create bus on bridge device */
  403. qbus = qbus_create(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio");
  404. bus = DO_UPCAST(VIOsPAPRBus, bus, qbus);
  405. bus->next_reg = 0x71000000;
  406. /* hcall-vio */
  407. spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);
  408. /* hcall-crq */
  409. spapr_register_hypercall(H_REG_CRQ, h_reg_crq);
  410. spapr_register_hypercall(H_FREE_CRQ, h_free_crq);
  411. spapr_register_hypercall(H_SEND_CRQ, h_send_crq);
  412. spapr_register_hypercall(H_ENABLE_CRQ, h_enable_crq);
  413. /* RTAS calls */
  414. spapr_rtas_register("ibm,set-tce-bypass", rtas_set_tce_bypass);
  415. spapr_rtas_register("quiesce", rtas_quiesce);
  416. return bus;
  417. }
  418. /* Represents sPAPR hcall VIO devices */
  419. static int spapr_vio_bridge_init(SysBusDevice *dev)
  420. {
  421. /* nothing */
  422. return 0;
  423. }
  424. static void spapr_vio_bridge_class_init(ObjectClass *klass, void *data)
  425. {
  426. DeviceClass *dc = DEVICE_CLASS(klass);
  427. SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
  428. k->init = spapr_vio_bridge_init;
  429. dc->no_user = 1;
  430. }
  431. static const TypeInfo spapr_vio_bridge_info = {
  432. .name = "spapr-vio-bridge",
  433. .parent = TYPE_SYS_BUS_DEVICE,
  434. .instance_size = sizeof(SysBusDevice),
  435. .class_init = spapr_vio_bridge_class_init,
  436. };
  437. static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
  438. {
  439. DeviceClass *k = DEVICE_CLASS(klass);
  440. k->init = spapr_vio_busdev_init;
  441. k->reset = spapr_vio_busdev_reset;
  442. k->bus_type = TYPE_SPAPR_VIO_BUS;
  443. k->props = spapr_vio_props;
  444. }
  445. static const TypeInfo spapr_vio_type_info = {
  446. .name = TYPE_VIO_SPAPR_DEVICE,
  447. .parent = TYPE_DEVICE,
  448. .instance_size = sizeof(VIOsPAPRDevice),
  449. .abstract = true,
  450. .class_size = sizeof(VIOsPAPRDeviceClass),
  451. .class_init = vio_spapr_device_class_init,
  452. };
  453. static void spapr_vio_register_types(void)
  454. {
  455. type_register_static(&spapr_vio_bus_info);
  456. type_register_static(&spapr_vio_bridge_info);
  457. type_register_static(&spapr_vio_type_info);
  458. }
  459. type_init(spapr_vio_register_types)
  460. #ifdef CONFIG_FDT
  461. static int compare_reg(const void *p1, const void *p2)
  462. {
  463. VIOsPAPRDevice const *dev1, *dev2;
  464. dev1 = (VIOsPAPRDevice *)*(DeviceState **)p1;
  465. dev2 = (VIOsPAPRDevice *)*(DeviceState **)p2;
  466. if (dev1->reg < dev2->reg) {
  467. return -1;
  468. }
  469. if (dev1->reg == dev2->reg) {
  470. return 0;
  471. }
  472. /* dev1->reg > dev2->reg */
  473. return 1;
  474. }
  475. int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt)
  476. {
  477. DeviceState *qdev, **qdevs;
  478. BusChild *kid;
  479. int i, num, ret = 0;
  480. /* Count qdevs on the bus list */
  481. num = 0;
  482. QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
  483. num++;
  484. }
  485. /* Copy out into an array of pointers */
  486. qdevs = g_malloc(sizeof(qdev) * num);
  487. num = 0;
  488. QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
  489. qdevs[num++] = kid->child;
  490. }
  491. /* Sort the array */
  492. qsort(qdevs, num, sizeof(qdev), compare_reg);
  493. /* Hack alert. Give the devices to libfdt in reverse order, we happen
  494. * to know that will mean they are in forward order in the tree. */
  495. for (i = num - 1; i >= 0; i--) {
  496. VIOsPAPRDevice *dev = (VIOsPAPRDevice *)(qdevs[i]);
  497. ret = vio_make_devnode(dev, fdt);
  498. if (ret < 0) {
  499. goto out;
  500. }
  501. }
  502. ret = 0;
  503. out:
  504. free(qdevs);
  505. return ret;
  506. }
  507. int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus)
  508. {
  509. VIOsPAPRDevice *dev;
  510. char *name, *path;
  511. int ret, offset;
  512. dev = spapr_vty_get_default(bus);
  513. if (!dev)
  514. return 0;
  515. offset = fdt_path_offset(fdt, "/chosen");
  516. if (offset < 0) {
  517. return offset;
  518. }
  519. name = vio_format_dev_name(dev);
  520. path = g_strdup_printf("/vdevice/%s", name);
  521. ret = fdt_setprop_string(fdt, offset, "linux,stdout-path", path);
  522. g_free(name);
  523. g_free(path);
  524. return ret;
  525. }
  526. #endif /* CONFIG_FDT */