xen_pt.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  1. /*
  2. * Copyright (c) 2007, Neocleus Corporation.
  3. * Copyright (c) 2007, Intel Corporation.
  4. *
  5. * This work is licensed under the terms of the GNU GPL, version 2. See
  6. * the COPYING file in the top-level directory.
  7. *
  8. * Alex Novik <alex@neocleus.com>
  9. * Allen Kay <allen.m.kay@intel.com>
  10. * Guy Zana <guy@neocleus.com>
  11. *
  12. * This file implements direct PCI assignment to a HVM guest
  13. */
  14. /*
  15. * Interrupt Disable policy:
  16. *
  17. * INTx interrupt:
  18. * Initialize(register_real_device)
  19. * Map INTx(xc_physdev_map_pirq):
  20. * <fail>
  21. * - Set real Interrupt Disable bit to '1'.
  22. * - Set machine_irq and assigned_device->machine_irq to '0'.
  23. * * Don't bind INTx.
  24. *
  25. * Bind INTx(xc_domain_bind_pt_pci_irq):
  26. * <fail>
  27. * - Set real Interrupt Disable bit to '1'.
  28. * - Unmap INTx.
  29. * - Decrement xen_pt_mapped_machine_irq[machine_irq]
  30. * - Set assigned_device->machine_irq to '0'.
  31. *
  32. * Write to Interrupt Disable bit by guest software(xen_pt_cmd_reg_write)
  33. * Write '0'
  34. * - Set real bit to '0' if assigned_device->machine_irq isn't '0'.
  35. *
  36. * Write '1'
  37. * - Set real bit to '1'.
  38. *
  39. * MSI interrupt:
  40. * Initialize MSI register(xen_pt_msi_setup, xen_pt_msi_update)
  41. * Bind MSI(xc_domain_update_msi_irq)
  42. * <fail>
  43. * - Unmap MSI.
  44. * - Set dev->msi->pirq to '-1'.
  45. *
  46. * MSI-X interrupt:
  47. * Initialize MSI-X register(xen_pt_msix_update_one)
  48. * Bind MSI-X(xc_domain_update_msi_irq)
  49. * <fail>
  50. * - Unmap MSI-X.
  51. * - Set entry->pirq to '-1'.
  52. */
  53. #include <sys/ioctl.h>
  54. #include "pci/pci.h"
  55. #include "xen.h"
  56. #include "xen_backend.h"
  57. #include "xen_pt.h"
  58. #include "qemu/range.h"
  59. #include "exec/address-spaces.h"
  60. #define XEN_PT_NR_IRQS (256)
  61. static uint8_t xen_pt_mapped_machine_irq[XEN_PT_NR_IRQS] = {0};
  62. void xen_pt_log(const PCIDevice *d, const char *f, ...)
  63. {
  64. va_list ap;
  65. va_start(ap, f);
  66. if (d) {
  67. fprintf(stderr, "[%02x:%02x.%d] ", pci_bus_num(d->bus),
  68. PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
  69. }
  70. vfprintf(stderr, f, ap);
  71. va_end(ap);
  72. }
  73. /* Config Space */
  74. static int xen_pt_pci_config_access_check(PCIDevice *d, uint32_t addr, int len)
  75. {
  76. /* check offset range */
  77. if (addr >= 0xFF) {
  78. XEN_PT_ERR(d, "Failed to access register with offset exceeding 0xFF. "
  79. "(addr: 0x%02x, len: %d)\n", addr, len);
  80. return -1;
  81. }
  82. /* check read size */
  83. if ((len != 1) && (len != 2) && (len != 4)) {
  84. XEN_PT_ERR(d, "Failed to access register with invalid access length. "
  85. "(addr: 0x%02x, len: %d)\n", addr, len);
  86. return -1;
  87. }
  88. /* check offset alignment */
  89. if (addr & (len - 1)) {
  90. XEN_PT_ERR(d, "Failed to access register with invalid access size "
  91. "alignment. (addr: 0x%02x, len: %d)\n", addr, len);
  92. return -1;
  93. }
  94. return 0;
  95. }
  96. int xen_pt_bar_offset_to_index(uint32_t offset)
  97. {
  98. int index = 0;
  99. /* check Exp ROM BAR */
  100. if (offset == PCI_ROM_ADDRESS) {
  101. return PCI_ROM_SLOT;
  102. }
  103. /* calculate BAR index */
  104. index = (offset - PCI_BASE_ADDRESS_0) >> 2;
  105. if (index >= PCI_NUM_REGIONS) {
  106. return -1;
  107. }
  108. return index;
  109. }
  110. static uint32_t xen_pt_pci_read_config(PCIDevice *d, uint32_t addr, int len)
  111. {
  112. XenPCIPassthroughState *s = DO_UPCAST(XenPCIPassthroughState, dev, d);
  113. uint32_t val = 0;
  114. XenPTRegGroup *reg_grp_entry = NULL;
  115. XenPTReg *reg_entry = NULL;
  116. int rc = 0;
  117. int emul_len = 0;
  118. uint32_t find_addr = addr;
  119. if (xen_pt_pci_config_access_check(d, addr, len)) {
  120. goto exit;
  121. }
  122. /* find register group entry */
  123. reg_grp_entry = xen_pt_find_reg_grp(s, addr);
  124. if (reg_grp_entry) {
  125. /* check 0-Hardwired register group */
  126. if (reg_grp_entry->reg_grp->grp_type == XEN_PT_GRP_TYPE_HARDWIRED) {
  127. /* no need to emulate, just return 0 */
  128. val = 0;
  129. goto exit;
  130. }
  131. }
  132. /* read I/O device register value */
  133. rc = xen_host_pci_get_block(&s->real_device, addr, (uint8_t *)&val, len);
  134. if (rc < 0) {
  135. XEN_PT_ERR(d, "pci_read_block failed. return value: %d.\n", rc);
  136. memset(&val, 0xff, len);
  137. }
  138. /* just return the I/O device register value for
  139. * passthrough type register group */
  140. if (reg_grp_entry == NULL) {
  141. goto exit;
  142. }
  143. /* adjust the read value to appropriate CFC-CFF window */
  144. val <<= (addr & 3) << 3;
  145. emul_len = len;
  146. /* loop around the guest requested size */
  147. while (emul_len > 0) {
  148. /* find register entry to be emulated */
  149. reg_entry = xen_pt_find_reg(reg_grp_entry, find_addr);
  150. if (reg_entry) {
  151. XenPTRegInfo *reg = reg_entry->reg;
  152. uint32_t real_offset = reg_grp_entry->base_offset + reg->offset;
  153. uint32_t valid_mask = 0xFFFFFFFF >> ((4 - emul_len) << 3);
  154. uint8_t *ptr_val = NULL;
  155. valid_mask <<= (find_addr - real_offset) << 3;
  156. ptr_val = (uint8_t *)&val + (real_offset & 3);
  157. /* do emulation based on register size */
  158. switch (reg->size) {
  159. case 1:
  160. if (reg->u.b.read) {
  161. rc = reg->u.b.read(s, reg_entry, ptr_val, valid_mask);
  162. }
  163. break;
  164. case 2:
  165. if (reg->u.w.read) {
  166. rc = reg->u.w.read(s, reg_entry,
  167. (uint16_t *)ptr_val, valid_mask);
  168. }
  169. break;
  170. case 4:
  171. if (reg->u.dw.read) {
  172. rc = reg->u.dw.read(s, reg_entry,
  173. (uint32_t *)ptr_val, valid_mask);
  174. }
  175. break;
  176. }
  177. if (rc < 0) {
  178. xen_shutdown_fatal_error("Internal error: Invalid read "
  179. "emulation. (%s, rc: %d)\n",
  180. __func__, rc);
  181. return 0;
  182. }
  183. /* calculate next address to find */
  184. emul_len -= reg->size;
  185. if (emul_len > 0) {
  186. find_addr = real_offset + reg->size;
  187. }
  188. } else {
  189. /* nothing to do with passthrough type register,
  190. * continue to find next byte */
  191. emul_len--;
  192. find_addr++;
  193. }
  194. }
  195. /* need to shift back before returning them to pci bus emulator */
  196. val >>= ((addr & 3) << 3);
  197. exit:
  198. XEN_PT_LOG_CONFIG(d, addr, val, len);
  199. return val;
  200. }
  201. static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr,
  202. uint32_t val, int len)
  203. {
  204. XenPCIPassthroughState *s = DO_UPCAST(XenPCIPassthroughState, dev, d);
  205. int index = 0;
  206. XenPTRegGroup *reg_grp_entry = NULL;
  207. int rc = 0;
  208. uint32_t read_val = 0;
  209. int emul_len = 0;
  210. XenPTReg *reg_entry = NULL;
  211. uint32_t find_addr = addr;
  212. XenPTRegInfo *reg = NULL;
  213. if (xen_pt_pci_config_access_check(d, addr, len)) {
  214. return;
  215. }
  216. XEN_PT_LOG_CONFIG(d, addr, val, len);
  217. /* check unused BAR register */
  218. index = xen_pt_bar_offset_to_index(addr);
  219. if ((index >= 0) && (val > 0 && val < XEN_PT_BAR_ALLF) &&
  220. (s->bases[index].bar_flag == XEN_PT_BAR_FLAG_UNUSED)) {
  221. XEN_PT_WARN(d, "Guest attempt to set address to unused Base Address "
  222. "Register. (addr: 0x%02x, len: %d)\n", addr, len);
  223. }
  224. /* find register group entry */
  225. reg_grp_entry = xen_pt_find_reg_grp(s, addr);
  226. if (reg_grp_entry) {
  227. /* check 0-Hardwired register group */
  228. if (reg_grp_entry->reg_grp->grp_type == XEN_PT_GRP_TYPE_HARDWIRED) {
  229. /* ignore silently */
  230. XEN_PT_WARN(d, "Access to 0-Hardwired register. "
  231. "(addr: 0x%02x, len: %d)\n", addr, len);
  232. return;
  233. }
  234. }
  235. rc = xen_host_pci_get_block(&s->real_device, addr,
  236. (uint8_t *)&read_val, len);
  237. if (rc < 0) {
  238. XEN_PT_ERR(d, "pci_read_block failed. return value: %d.\n", rc);
  239. memset(&read_val, 0xff, len);
  240. }
  241. /* pass directly to the real device for passthrough type register group */
  242. if (reg_grp_entry == NULL) {
  243. goto out;
  244. }
  245. memory_region_transaction_begin();
  246. pci_default_write_config(d, addr, val, len);
  247. /* adjust the read and write value to appropriate CFC-CFF window */
  248. read_val <<= (addr & 3) << 3;
  249. val <<= (addr & 3) << 3;
  250. emul_len = len;
  251. /* loop around the guest requested size */
  252. while (emul_len > 0) {
  253. /* find register entry to be emulated */
  254. reg_entry = xen_pt_find_reg(reg_grp_entry, find_addr);
  255. if (reg_entry) {
  256. reg = reg_entry->reg;
  257. uint32_t real_offset = reg_grp_entry->base_offset + reg->offset;
  258. uint32_t valid_mask = 0xFFFFFFFF >> ((4 - emul_len) << 3);
  259. uint8_t *ptr_val = NULL;
  260. valid_mask <<= (find_addr - real_offset) << 3;
  261. ptr_val = (uint8_t *)&val + (real_offset & 3);
  262. /* do emulation based on register size */
  263. switch (reg->size) {
  264. case 1:
  265. if (reg->u.b.write) {
  266. rc = reg->u.b.write(s, reg_entry, ptr_val,
  267. read_val >> ((real_offset & 3) << 3),
  268. valid_mask);
  269. }
  270. break;
  271. case 2:
  272. if (reg->u.w.write) {
  273. rc = reg->u.w.write(s, reg_entry, (uint16_t *)ptr_val,
  274. (read_val >> ((real_offset & 3) << 3)),
  275. valid_mask);
  276. }
  277. break;
  278. case 4:
  279. if (reg->u.dw.write) {
  280. rc = reg->u.dw.write(s, reg_entry, (uint32_t *)ptr_val,
  281. (read_val >> ((real_offset & 3) << 3)),
  282. valid_mask);
  283. }
  284. break;
  285. }
  286. if (rc < 0) {
  287. xen_shutdown_fatal_error("Internal error: Invalid write"
  288. " emulation. (%s, rc: %d)\n",
  289. __func__, rc);
  290. return;
  291. }
  292. /* calculate next address to find */
  293. emul_len -= reg->size;
  294. if (emul_len > 0) {
  295. find_addr = real_offset + reg->size;
  296. }
  297. } else {
  298. /* nothing to do with passthrough type register,
  299. * continue to find next byte */
  300. emul_len--;
  301. find_addr++;
  302. }
  303. }
  304. /* need to shift back before passing them to xen_host_pci_device */
  305. val >>= (addr & 3) << 3;
  306. memory_region_transaction_commit();
  307. out:
  308. if (!(reg && reg->no_wb)) {
  309. /* unknown regs are passed through */
  310. rc = xen_host_pci_set_block(&s->real_device, addr,
  311. (uint8_t *)&val, len);
  312. if (rc < 0) {
  313. XEN_PT_ERR(d, "pci_write_block failed. return value: %d.\n", rc);
  314. }
  315. }
  316. }
  317. /* register regions */
  318. static uint64_t xen_pt_bar_read(void *o, hwaddr addr,
  319. unsigned size)
  320. {
  321. PCIDevice *d = o;
  322. /* if this function is called, that probably means that there is a
  323. * misconfiguration of the IOMMU. */
  324. XEN_PT_ERR(d, "Should not read BAR through QEMU. @0x"TARGET_FMT_plx"\n",
  325. addr);
  326. return 0;
  327. }
  328. static void xen_pt_bar_write(void *o, hwaddr addr, uint64_t val,
  329. unsigned size)
  330. {
  331. PCIDevice *d = o;
  332. /* Same comment as xen_pt_bar_read function */
  333. XEN_PT_ERR(d, "Should not write BAR through QEMU. @0x"TARGET_FMT_plx"\n",
  334. addr);
  335. }
  336. static const MemoryRegionOps ops = {
  337. .endianness = DEVICE_NATIVE_ENDIAN,
  338. .read = xen_pt_bar_read,
  339. .write = xen_pt_bar_write,
  340. };
  341. static int xen_pt_register_regions(XenPCIPassthroughState *s)
  342. {
  343. int i = 0;
  344. XenHostPCIDevice *d = &s->real_device;
  345. /* Register PIO/MMIO BARs */
  346. for (i = 0; i < PCI_ROM_SLOT; i++) {
  347. XenHostPCIIORegion *r = &d->io_regions[i];
  348. uint8_t type;
  349. if (r->base_addr == 0 || r->size == 0) {
  350. continue;
  351. }
  352. s->bases[i].access.u = r->base_addr;
  353. if (r->type & XEN_HOST_PCI_REGION_TYPE_IO) {
  354. type = PCI_BASE_ADDRESS_SPACE_IO;
  355. } else {
  356. type = PCI_BASE_ADDRESS_SPACE_MEMORY;
  357. if (r->type & XEN_HOST_PCI_REGION_TYPE_PREFETCH) {
  358. type |= PCI_BASE_ADDRESS_MEM_PREFETCH;
  359. }
  360. if (r->type & XEN_HOST_PCI_REGION_TYPE_MEM_64) {
  361. type |= PCI_BASE_ADDRESS_MEM_TYPE_64;
  362. }
  363. }
  364. memory_region_init_io(&s->bar[i], &ops, &s->dev,
  365. "xen-pci-pt-bar", r->size);
  366. pci_register_bar(&s->dev, i, type, &s->bar[i]);
  367. XEN_PT_LOG(&s->dev, "IO region %i registered (size=0x%lx"PRIx64
  368. " base_addr=0x%lx"PRIx64" type: %#x)\n",
  369. i, r->size, r->base_addr, type);
  370. }
  371. /* Register expansion ROM address */
  372. if (d->rom.base_addr && d->rom.size) {
  373. uint32_t bar_data = 0;
  374. /* Re-set BAR reported by OS, otherwise ROM can't be read. */
  375. if (xen_host_pci_get_long(d, PCI_ROM_ADDRESS, &bar_data)) {
  376. return 0;
  377. }
  378. if ((bar_data & PCI_ROM_ADDRESS_MASK) == 0) {
  379. bar_data |= d->rom.base_addr & PCI_ROM_ADDRESS_MASK;
  380. xen_host_pci_set_long(d, PCI_ROM_ADDRESS, bar_data);
  381. }
  382. s->bases[PCI_ROM_SLOT].access.maddr = d->rom.base_addr;
  383. memory_region_init_rom_device(&s->rom, NULL, NULL,
  384. "xen-pci-pt-rom", d->rom.size);
  385. pci_register_bar(&s->dev, PCI_ROM_SLOT, PCI_BASE_ADDRESS_MEM_PREFETCH,
  386. &s->rom);
  387. XEN_PT_LOG(&s->dev, "Expansion ROM registered (size=0x%08"PRIx64
  388. " base_addr=0x%08"PRIx64")\n",
  389. d->rom.size, d->rom.base_addr);
  390. }
  391. return 0;
  392. }
  393. static void xen_pt_unregister_regions(XenPCIPassthroughState *s)
  394. {
  395. XenHostPCIDevice *d = &s->real_device;
  396. int i;
  397. for (i = 0; i < PCI_NUM_REGIONS - 1; i++) {
  398. XenHostPCIIORegion *r = &d->io_regions[i];
  399. if (r->base_addr == 0 || r->size == 0) {
  400. continue;
  401. }
  402. memory_region_destroy(&s->bar[i]);
  403. }
  404. if (d->rom.base_addr && d->rom.size) {
  405. memory_region_destroy(&s->rom);
  406. }
  407. }
  408. /* region mapping */
  409. static int xen_pt_bar_from_region(XenPCIPassthroughState *s, MemoryRegion *mr)
  410. {
  411. int i = 0;
  412. for (i = 0; i < PCI_NUM_REGIONS - 1; i++) {
  413. if (mr == &s->bar[i]) {
  414. return i;
  415. }
  416. }
  417. if (mr == &s->rom) {
  418. return PCI_ROM_SLOT;
  419. }
  420. return -1;
  421. }
  422. /*
  423. * This function checks if an io_region overlaps an io_region from another
  424. * device. The io_region to check is provided with (addr, size and type)
  425. * A callback can be provided and will be called for every region that is
  426. * overlapped.
  427. * The return value indicates if the region is overlappsed */
  428. struct CheckBarArgs {
  429. XenPCIPassthroughState *s;
  430. pcibus_t addr;
  431. pcibus_t size;
  432. uint8_t type;
  433. bool rc;
  434. };
  435. static void xen_pt_check_bar_overlap(PCIBus *bus, PCIDevice *d, void *opaque)
  436. {
  437. struct CheckBarArgs *arg = opaque;
  438. XenPCIPassthroughState *s = arg->s;
  439. uint8_t type = arg->type;
  440. int i;
  441. if (d->devfn == s->dev.devfn) {
  442. return;
  443. }
  444. /* xxx: This ignores bridges. */
  445. for (i = 0; i < PCI_NUM_REGIONS; i++) {
  446. const PCIIORegion *r = &d->io_regions[i];
  447. if (!r->size) {
  448. continue;
  449. }
  450. if ((type & PCI_BASE_ADDRESS_SPACE_IO)
  451. != (r->type & PCI_BASE_ADDRESS_SPACE_IO)) {
  452. continue;
  453. }
  454. if (ranges_overlap(arg->addr, arg->size, r->addr, r->size)) {
  455. XEN_PT_WARN(&s->dev,
  456. "Overlapped to device [%02x:%02x.%d] Region: %i"
  457. " (addr: %#"FMT_PCIBUS", len: %#"FMT_PCIBUS")\n",
  458. pci_bus_num(bus), PCI_SLOT(d->devfn),
  459. PCI_FUNC(d->devfn), i, r->addr, r->size);
  460. arg->rc = true;
  461. }
  462. }
  463. }
  464. static void xen_pt_region_update(XenPCIPassthroughState *s,
  465. MemoryRegionSection *sec, bool adding)
  466. {
  467. PCIDevice *d = &s->dev;
  468. MemoryRegion *mr = sec->mr;
  469. int bar = -1;
  470. int rc;
  471. int op = adding ? DPCI_ADD_MAPPING : DPCI_REMOVE_MAPPING;
  472. struct CheckBarArgs args = {
  473. .s = s,
  474. .addr = sec->offset_within_address_space,
  475. .size = sec->size,
  476. .rc = false,
  477. };
  478. bar = xen_pt_bar_from_region(s, mr);
  479. if (bar == -1 && (!s->msix || &s->msix->mmio != mr)) {
  480. return;
  481. }
  482. if (s->msix && &s->msix->mmio == mr) {
  483. if (adding) {
  484. s->msix->mmio_base_addr = sec->offset_within_address_space;
  485. rc = xen_pt_msix_update_remap(s, s->msix->bar_index);
  486. }
  487. return;
  488. }
  489. args.type = d->io_regions[bar].type;
  490. pci_for_each_device(d->bus, pci_bus_num(d->bus),
  491. xen_pt_check_bar_overlap, &args);
  492. if (args.rc) {
  493. XEN_PT_WARN(d, "Region: %d (addr: %#"FMT_PCIBUS
  494. ", len: %#"FMT_PCIBUS") is overlapped.\n",
  495. bar, sec->offset_within_address_space, sec->size);
  496. }
  497. if (d->io_regions[bar].type & PCI_BASE_ADDRESS_SPACE_IO) {
  498. uint32_t guest_port = sec->offset_within_address_space;
  499. uint32_t machine_port = s->bases[bar].access.pio_base;
  500. uint32_t size = sec->size;
  501. rc = xc_domain_ioport_mapping(xen_xc, xen_domid,
  502. guest_port, machine_port, size,
  503. op);
  504. if (rc) {
  505. XEN_PT_ERR(d, "%s ioport mapping failed! (rc: %i)\n",
  506. adding ? "create new" : "remove old", rc);
  507. }
  508. } else {
  509. pcibus_t guest_addr = sec->offset_within_address_space;
  510. pcibus_t machine_addr = s->bases[bar].access.maddr
  511. + sec->offset_within_region;
  512. pcibus_t size = sec->size;
  513. rc = xc_domain_memory_mapping(xen_xc, xen_domid,
  514. XEN_PFN(guest_addr + XC_PAGE_SIZE - 1),
  515. XEN_PFN(machine_addr + XC_PAGE_SIZE - 1),
  516. XEN_PFN(size + XC_PAGE_SIZE - 1),
  517. op);
  518. if (rc) {
  519. XEN_PT_ERR(d, "%s mem mapping failed! (rc: %i)\n",
  520. adding ? "create new" : "remove old", rc);
  521. }
  522. }
  523. }
  524. static void xen_pt_region_add(MemoryListener *l, MemoryRegionSection *sec)
  525. {
  526. XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState,
  527. memory_listener);
  528. xen_pt_region_update(s, sec, true);
  529. }
  530. static void xen_pt_region_del(MemoryListener *l, MemoryRegionSection *sec)
  531. {
  532. XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState,
  533. memory_listener);
  534. xen_pt_region_update(s, sec, false);
  535. }
  536. static void xen_pt_io_region_add(MemoryListener *l, MemoryRegionSection *sec)
  537. {
  538. XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState,
  539. io_listener);
  540. xen_pt_region_update(s, sec, true);
  541. }
  542. static void xen_pt_io_region_del(MemoryListener *l, MemoryRegionSection *sec)
  543. {
  544. XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState,
  545. io_listener);
  546. xen_pt_region_update(s, sec, false);
  547. }
  548. static const MemoryListener xen_pt_memory_listener = {
  549. .region_add = xen_pt_region_add,
  550. .region_del = xen_pt_region_del,
  551. .priority = 10,
  552. };
  553. static const MemoryListener xen_pt_io_listener = {
  554. .region_add = xen_pt_io_region_add,
  555. .region_del = xen_pt_io_region_del,
  556. .priority = 10,
  557. };
  558. /* init */
  559. static int xen_pt_initfn(PCIDevice *d)
  560. {
  561. XenPCIPassthroughState *s = DO_UPCAST(XenPCIPassthroughState, dev, d);
  562. int rc = 0;
  563. uint8_t machine_irq = 0;
  564. int pirq = XEN_PT_UNASSIGNED_PIRQ;
  565. /* register real device */
  566. XEN_PT_LOG(d, "Assigning real physical device %02x:%02x.%d"
  567. " to devfn %#x\n",
  568. s->hostaddr.bus, s->hostaddr.slot, s->hostaddr.function,
  569. s->dev.devfn);
  570. rc = xen_host_pci_device_get(&s->real_device,
  571. s->hostaddr.domain, s->hostaddr.bus,
  572. s->hostaddr.slot, s->hostaddr.function);
  573. if (rc) {
  574. XEN_PT_ERR(d, "Failed to \"open\" the real pci device. rc: %i\n", rc);
  575. return -1;
  576. }
  577. s->is_virtfn = s->real_device.is_virtfn;
  578. if (s->is_virtfn) {
  579. XEN_PT_LOG(d, "%04x:%02x:%02x.%d is a SR-IOV Virtual Function\n",
  580. s->real_device.domain, s->real_device.bus,
  581. s->real_device.dev, s->real_device.func);
  582. }
  583. /* Initialize virtualized PCI configuration (Extended 256 Bytes) */
  584. if (xen_host_pci_get_block(&s->real_device, 0, d->config,
  585. PCI_CONFIG_SPACE_SIZE) == -1) {
  586. xen_host_pci_device_put(&s->real_device);
  587. return -1;
  588. }
  589. s->memory_listener = xen_pt_memory_listener;
  590. s->io_listener = xen_pt_io_listener;
  591. /* Handle real device's MMIO/PIO BARs */
  592. xen_pt_register_regions(s);
  593. /* reinitialize each config register to be emulated */
  594. if (xen_pt_config_init(s)) {
  595. XEN_PT_ERR(d, "PCI Config space initialisation failed.\n");
  596. xen_host_pci_device_put(&s->real_device);
  597. return -1;
  598. }
  599. /* Bind interrupt */
  600. if (!s->dev.config[PCI_INTERRUPT_PIN]) {
  601. XEN_PT_LOG(d, "no pin interrupt\n");
  602. goto out;
  603. }
  604. machine_irq = s->real_device.irq;
  605. rc = xc_physdev_map_pirq(xen_xc, xen_domid, machine_irq, &pirq);
  606. if (rc < 0) {
  607. XEN_PT_ERR(d, "Mapping machine irq %u to pirq %i failed, (rc: %d)\n",
  608. machine_irq, pirq, rc);
  609. /* Disable PCI intx assertion (turn on bit10 of devctl) */
  610. xen_host_pci_set_word(&s->real_device,
  611. PCI_COMMAND,
  612. pci_get_word(s->dev.config + PCI_COMMAND)
  613. | PCI_COMMAND_INTX_DISABLE);
  614. machine_irq = 0;
  615. s->machine_irq = 0;
  616. } else {
  617. machine_irq = pirq;
  618. s->machine_irq = pirq;
  619. xen_pt_mapped_machine_irq[machine_irq]++;
  620. }
  621. /* bind machine_irq to device */
  622. if (machine_irq != 0) {
  623. uint8_t e_intx = xen_pt_pci_intx(s);
  624. rc = xc_domain_bind_pt_pci_irq(xen_xc, xen_domid, machine_irq,
  625. pci_bus_num(d->bus),
  626. PCI_SLOT(d->devfn),
  627. e_intx);
  628. if (rc < 0) {
  629. XEN_PT_ERR(d, "Binding of interrupt %i failed! (rc: %d)\n",
  630. e_intx, rc);
  631. /* Disable PCI intx assertion (turn on bit10 of devctl) */
  632. xen_host_pci_set_word(&s->real_device, PCI_COMMAND,
  633. *(uint16_t *)(&s->dev.config[PCI_COMMAND])
  634. | PCI_COMMAND_INTX_DISABLE);
  635. xen_pt_mapped_machine_irq[machine_irq]--;
  636. if (xen_pt_mapped_machine_irq[machine_irq] == 0) {
  637. if (xc_physdev_unmap_pirq(xen_xc, xen_domid, machine_irq)) {
  638. XEN_PT_ERR(d, "Unmapping of machine interrupt %i failed!"
  639. " (rc: %d)\n", machine_irq, rc);
  640. }
  641. }
  642. s->machine_irq = 0;
  643. }
  644. }
  645. out:
  646. memory_listener_register(&s->memory_listener, &address_space_memory);
  647. memory_listener_register(&s->io_listener, &address_space_io);
  648. XEN_PT_LOG(d, "Real physical device %02x:%02x.%d registered successfuly!\n",
  649. s->hostaddr.bus, s->hostaddr.slot, s->hostaddr.function);
  650. return 0;
  651. }
  652. static void xen_pt_unregister_device(PCIDevice *d)
  653. {
  654. XenPCIPassthroughState *s = DO_UPCAST(XenPCIPassthroughState, dev, d);
  655. uint8_t machine_irq = s->machine_irq;
  656. uint8_t intx = xen_pt_pci_intx(s);
  657. int rc;
  658. if (machine_irq) {
  659. rc = xc_domain_unbind_pt_irq(xen_xc, xen_domid, machine_irq,
  660. PT_IRQ_TYPE_PCI,
  661. pci_bus_num(d->bus),
  662. PCI_SLOT(s->dev.devfn),
  663. intx,
  664. 0 /* isa_irq */);
  665. if (rc < 0) {
  666. XEN_PT_ERR(d, "unbinding of interrupt INT%c failed."
  667. " (machine irq: %i, rc: %d)"
  668. " But bravely continuing on..\n",
  669. 'a' + intx, machine_irq, rc);
  670. }
  671. }
  672. if (s->msi) {
  673. xen_pt_msi_disable(s);
  674. }
  675. if (s->msix) {
  676. xen_pt_msix_disable(s);
  677. }
  678. if (machine_irq) {
  679. xen_pt_mapped_machine_irq[machine_irq]--;
  680. if (xen_pt_mapped_machine_irq[machine_irq] == 0) {
  681. rc = xc_physdev_unmap_pirq(xen_xc, xen_domid, machine_irq);
  682. if (rc < 0) {
  683. XEN_PT_ERR(d, "unmapping of interrupt %i failed. (rc: %d)"
  684. " But bravely continuing on..\n",
  685. machine_irq, rc);
  686. }
  687. }
  688. }
  689. /* delete all emulated config registers */
  690. xen_pt_config_delete(s);
  691. xen_pt_unregister_regions(s);
  692. memory_listener_unregister(&s->memory_listener);
  693. memory_listener_unregister(&s->io_listener);
  694. xen_host_pci_device_put(&s->real_device);
  695. }
  696. static Property xen_pci_passthrough_properties[] = {
  697. DEFINE_PROP_PCI_HOST_DEVADDR("hostaddr", XenPCIPassthroughState, hostaddr),
  698. DEFINE_PROP_END_OF_LIST(),
  699. };
  700. static void xen_pci_passthrough_class_init(ObjectClass *klass, void *data)
  701. {
  702. DeviceClass *dc = DEVICE_CLASS(klass);
  703. PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
  704. k->init = xen_pt_initfn;
  705. k->exit = xen_pt_unregister_device;
  706. k->config_read = xen_pt_pci_read_config;
  707. k->config_write = xen_pt_pci_write_config;
  708. dc->desc = "Assign an host PCI device with Xen";
  709. dc->props = xen_pci_passthrough_properties;
  710. };
  711. static const TypeInfo xen_pci_passthrough_info = {
  712. .name = "xen-pci-passthrough",
  713. .parent = TYPE_PCI_DEVICE,
  714. .instance_size = sizeof(XenPCIPassthroughState),
  715. .class_init = xen_pci_passthrough_class_init,
  716. };
  717. static void xen_pci_passthrough_register_types(void)
  718. {
  719. type_register_static(&xen_pci_passthrough_info);
  720. }
  721. type_init(xen_pci_passthrough_register_types)