virtio-iommu.c 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291
  1. /*
  2. * virtio-iommu device
  3. *
  4. * Copyright (c) 2020 Red Hat, Inc.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms and conditions of the GNU General Public License,
  8. * version 2 or later, as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along with
  16. * this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. #include "qemu/osdep.h"
  20. #include "qemu/log.h"
  21. #include "qemu/iov.h"
  22. #include "hw/qdev-properties.h"
  23. #include "hw/virtio/virtio.h"
  24. #include "sysemu/kvm.h"
  25. #include "sysemu/reset.h"
  26. #include "qapi/error.h"
  27. #include "qemu/error-report.h"
  28. #include "trace.h"
  29. #include "standard-headers/linux/virtio_ids.h"
  30. #include "hw/virtio/virtio-bus.h"
  31. #include "hw/virtio/virtio-access.h"
  32. #include "hw/virtio/virtio-iommu.h"
  33. #include "hw/pci/pci_bus.h"
  34. #include "hw/pci/pci.h"
  35. /* Max size */
  36. #define VIOMMU_DEFAULT_QUEUE_SIZE 256
  37. #define VIOMMU_PROBE_SIZE 512
  38. typedef struct VirtIOIOMMUDomain {
  39. uint32_t id;
  40. bool bypass;
  41. GTree *mappings;
  42. QLIST_HEAD(, VirtIOIOMMUEndpoint) endpoint_list;
  43. } VirtIOIOMMUDomain;
  44. typedef struct VirtIOIOMMUEndpoint {
  45. uint32_t id;
  46. VirtIOIOMMUDomain *domain;
  47. IOMMUMemoryRegion *iommu_mr;
  48. QLIST_ENTRY(VirtIOIOMMUEndpoint) next;
  49. } VirtIOIOMMUEndpoint;
  50. typedef struct VirtIOIOMMUInterval {
  51. uint64_t low;
  52. uint64_t high;
  53. } VirtIOIOMMUInterval;
  54. typedef struct VirtIOIOMMUMapping {
  55. uint64_t phys_addr;
  56. uint32_t flags;
  57. } VirtIOIOMMUMapping;
  58. static inline uint16_t virtio_iommu_get_bdf(IOMMUDevice *dev)
  59. {
  60. return PCI_BUILD_BDF(pci_bus_num(dev->bus), dev->devfn);
  61. }
  62. /**
  63. * The bus number is used for lookup when SID based operations occur.
  64. * In that case we lazily populate the IOMMUPciBus array from the bus hash
  65. * table. At the time the IOMMUPciBus is created (iommu_find_add_as), the bus
  66. * numbers may not be always initialized yet.
  67. */
  68. static IOMMUPciBus *iommu_find_iommu_pcibus(VirtIOIOMMU *s, uint8_t bus_num)
  69. {
  70. IOMMUPciBus *iommu_pci_bus = s->iommu_pcibus_by_bus_num[bus_num];
  71. if (!iommu_pci_bus) {
  72. GHashTableIter iter;
  73. g_hash_table_iter_init(&iter, s->as_by_busptr);
  74. while (g_hash_table_iter_next(&iter, NULL, (void **)&iommu_pci_bus)) {
  75. if (pci_bus_num(iommu_pci_bus->bus) == bus_num) {
  76. s->iommu_pcibus_by_bus_num[bus_num] = iommu_pci_bus;
  77. return iommu_pci_bus;
  78. }
  79. }
  80. return NULL;
  81. }
  82. return iommu_pci_bus;
  83. }
  84. static IOMMUMemoryRegion *virtio_iommu_mr(VirtIOIOMMU *s, uint32_t sid)
  85. {
  86. uint8_t bus_n, devfn;
  87. IOMMUPciBus *iommu_pci_bus;
  88. IOMMUDevice *dev;
  89. bus_n = PCI_BUS_NUM(sid);
  90. iommu_pci_bus = iommu_find_iommu_pcibus(s, bus_n);
  91. if (iommu_pci_bus) {
  92. devfn = sid & (PCI_DEVFN_MAX - 1);
  93. dev = iommu_pci_bus->pbdev[devfn];
  94. if (dev) {
  95. return &dev->iommu_mr;
  96. }
  97. }
  98. return NULL;
  99. }
  100. static gint interval_cmp(gconstpointer a, gconstpointer b, gpointer user_data)
  101. {
  102. VirtIOIOMMUInterval *inta = (VirtIOIOMMUInterval *)a;
  103. VirtIOIOMMUInterval *intb = (VirtIOIOMMUInterval *)b;
  104. if (inta->high < intb->low) {
  105. return -1;
  106. } else if (intb->high < inta->low) {
  107. return 1;
  108. } else {
  109. return 0;
  110. }
  111. }
  112. static void virtio_iommu_notify_map(IOMMUMemoryRegion *mr, hwaddr virt_start,
  113. hwaddr virt_end, hwaddr paddr,
  114. uint32_t flags)
  115. {
  116. IOMMUTLBEvent event;
  117. IOMMUAccessFlags perm = IOMMU_ACCESS_FLAG(flags & VIRTIO_IOMMU_MAP_F_READ,
  118. flags & VIRTIO_IOMMU_MAP_F_WRITE);
  119. if (!(mr->iommu_notify_flags & IOMMU_NOTIFIER_MAP) ||
  120. (flags & VIRTIO_IOMMU_MAP_F_MMIO) || !perm) {
  121. return;
  122. }
  123. trace_virtio_iommu_notify_map(mr->parent_obj.name, virt_start, virt_end,
  124. paddr, perm);
  125. event.type = IOMMU_NOTIFIER_MAP;
  126. event.entry.target_as = &address_space_memory;
  127. event.entry.addr_mask = virt_end - virt_start;
  128. event.entry.iova = virt_start;
  129. event.entry.perm = perm;
  130. event.entry.translated_addr = paddr;
  131. memory_region_notify_iommu(mr, 0, event);
  132. }
  133. static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start,
  134. hwaddr virt_end)
  135. {
  136. IOMMUTLBEvent event;
  137. uint64_t delta = virt_end - virt_start;
  138. if (!(mr->iommu_notify_flags & IOMMU_NOTIFIER_UNMAP)) {
  139. return;
  140. }
  141. trace_virtio_iommu_notify_unmap(mr->parent_obj.name, virt_start, virt_end);
  142. event.type = IOMMU_NOTIFIER_UNMAP;
  143. event.entry.target_as = &address_space_memory;
  144. event.entry.perm = IOMMU_NONE;
  145. event.entry.translated_addr = 0;
  146. event.entry.addr_mask = delta;
  147. event.entry.iova = virt_start;
  148. if (delta == UINT64_MAX) {
  149. memory_region_notify_iommu(mr, 0, event);
  150. }
  151. while (virt_start != virt_end + 1) {
  152. uint64_t mask = dma_aligned_pow2_mask(virt_start, virt_end, 64);
  153. event.entry.addr_mask = mask;
  154. event.entry.iova = virt_start;
  155. memory_region_notify_iommu(mr, 0, event);
  156. virt_start += mask + 1;
  157. }
  158. }
  159. static gboolean virtio_iommu_notify_unmap_cb(gpointer key, gpointer value,
  160. gpointer data)
  161. {
  162. VirtIOIOMMUInterval *interval = (VirtIOIOMMUInterval *) key;
  163. IOMMUMemoryRegion *mr = (IOMMUMemoryRegion *) data;
  164. virtio_iommu_notify_unmap(mr, interval->low, interval->high);
  165. return false;
  166. }
  167. static gboolean virtio_iommu_notify_map_cb(gpointer key, gpointer value,
  168. gpointer data)
  169. {
  170. VirtIOIOMMUMapping *mapping = (VirtIOIOMMUMapping *) value;
  171. VirtIOIOMMUInterval *interval = (VirtIOIOMMUInterval *) key;
  172. IOMMUMemoryRegion *mr = (IOMMUMemoryRegion *) data;
  173. virtio_iommu_notify_map(mr, interval->low, interval->high,
  174. mapping->phys_addr, mapping->flags);
  175. return false;
  176. }
  177. static void virtio_iommu_detach_endpoint_from_domain(VirtIOIOMMUEndpoint *ep)
  178. {
  179. VirtIOIOMMUDomain *domain = ep->domain;
  180. if (!ep->domain) {
  181. return;
  182. }
  183. g_tree_foreach(domain->mappings, virtio_iommu_notify_unmap_cb,
  184. ep->iommu_mr);
  185. QLIST_REMOVE(ep, next);
  186. ep->domain = NULL;
  187. }
  188. static VirtIOIOMMUEndpoint *virtio_iommu_get_endpoint(VirtIOIOMMU *s,
  189. uint32_t ep_id)
  190. {
  191. VirtIOIOMMUEndpoint *ep;
  192. IOMMUMemoryRegion *mr;
  193. ep = g_tree_lookup(s->endpoints, GUINT_TO_POINTER(ep_id));
  194. if (ep) {
  195. return ep;
  196. }
  197. mr = virtio_iommu_mr(s, ep_id);
  198. if (!mr) {
  199. return NULL;
  200. }
  201. ep = g_malloc0(sizeof(*ep));
  202. ep->id = ep_id;
  203. ep->iommu_mr = mr;
  204. trace_virtio_iommu_get_endpoint(ep_id);
  205. g_tree_insert(s->endpoints, GUINT_TO_POINTER(ep_id), ep);
  206. return ep;
  207. }
  208. static void virtio_iommu_put_endpoint(gpointer data)
  209. {
  210. VirtIOIOMMUEndpoint *ep = (VirtIOIOMMUEndpoint *)data;
  211. if (ep->domain) {
  212. virtio_iommu_detach_endpoint_from_domain(ep);
  213. }
  214. trace_virtio_iommu_put_endpoint(ep->id);
  215. g_free(ep);
  216. }
  217. static VirtIOIOMMUDomain *virtio_iommu_get_domain(VirtIOIOMMU *s,
  218. uint32_t domain_id,
  219. bool bypass)
  220. {
  221. VirtIOIOMMUDomain *domain;
  222. domain = g_tree_lookup(s->domains, GUINT_TO_POINTER(domain_id));
  223. if (domain) {
  224. if (domain->bypass != bypass) {
  225. return NULL;
  226. }
  227. return domain;
  228. }
  229. domain = g_malloc0(sizeof(*domain));
  230. domain->id = domain_id;
  231. domain->mappings = g_tree_new_full((GCompareDataFunc)interval_cmp,
  232. NULL, (GDestroyNotify)g_free,
  233. (GDestroyNotify)g_free);
  234. domain->bypass = bypass;
  235. g_tree_insert(s->domains, GUINT_TO_POINTER(domain_id), domain);
  236. QLIST_INIT(&domain->endpoint_list);
  237. trace_virtio_iommu_get_domain(domain_id);
  238. return domain;
  239. }
  240. static void virtio_iommu_put_domain(gpointer data)
  241. {
  242. VirtIOIOMMUDomain *domain = (VirtIOIOMMUDomain *)data;
  243. VirtIOIOMMUEndpoint *iter, *tmp;
  244. QLIST_FOREACH_SAFE(iter, &domain->endpoint_list, next, tmp) {
  245. virtio_iommu_detach_endpoint_from_domain(iter);
  246. }
  247. g_tree_destroy(domain->mappings);
  248. trace_virtio_iommu_put_domain(domain->id);
  249. g_free(domain);
  250. }
  251. static AddressSpace *virtio_iommu_find_add_as(PCIBus *bus, void *opaque,
  252. int devfn)
  253. {
  254. VirtIOIOMMU *s = opaque;
  255. IOMMUPciBus *sbus = g_hash_table_lookup(s->as_by_busptr, bus);
  256. static uint32_t mr_index;
  257. IOMMUDevice *sdev;
  258. if (!sbus) {
  259. sbus = g_malloc0(sizeof(IOMMUPciBus) +
  260. sizeof(IOMMUDevice *) * PCI_DEVFN_MAX);
  261. sbus->bus = bus;
  262. g_hash_table_insert(s->as_by_busptr, bus, sbus);
  263. }
  264. sdev = sbus->pbdev[devfn];
  265. if (!sdev) {
  266. char *name = g_strdup_printf("%s-%d-%d",
  267. TYPE_VIRTIO_IOMMU_MEMORY_REGION,
  268. mr_index++, devfn);
  269. sdev = sbus->pbdev[devfn] = g_new0(IOMMUDevice, 1);
  270. sdev->viommu = s;
  271. sdev->bus = bus;
  272. sdev->devfn = devfn;
  273. trace_virtio_iommu_init_iommu_mr(name);
  274. memory_region_init_iommu(&sdev->iommu_mr, sizeof(sdev->iommu_mr),
  275. TYPE_VIRTIO_IOMMU_MEMORY_REGION,
  276. OBJECT(s), name,
  277. UINT64_MAX);
  278. address_space_init(&sdev->as,
  279. MEMORY_REGION(&sdev->iommu_mr), TYPE_VIRTIO_IOMMU);
  280. g_free(name);
  281. }
  282. return &sdev->as;
  283. }
  284. static int virtio_iommu_attach(VirtIOIOMMU *s,
  285. struct virtio_iommu_req_attach *req)
  286. {
  287. uint32_t domain_id = le32_to_cpu(req->domain);
  288. uint32_t ep_id = le32_to_cpu(req->endpoint);
  289. uint32_t flags = le32_to_cpu(req->flags);
  290. VirtIOIOMMUDomain *domain;
  291. VirtIOIOMMUEndpoint *ep;
  292. trace_virtio_iommu_attach(domain_id, ep_id);
  293. if (flags & ~VIRTIO_IOMMU_ATTACH_F_BYPASS) {
  294. return VIRTIO_IOMMU_S_INVAL;
  295. }
  296. ep = virtio_iommu_get_endpoint(s, ep_id);
  297. if (!ep) {
  298. return VIRTIO_IOMMU_S_NOENT;
  299. }
  300. if (ep->domain) {
  301. VirtIOIOMMUDomain *previous_domain = ep->domain;
  302. /*
  303. * the device is already attached to a domain,
  304. * detach it first
  305. */
  306. virtio_iommu_detach_endpoint_from_domain(ep);
  307. if (QLIST_EMPTY(&previous_domain->endpoint_list)) {
  308. g_tree_remove(s->domains, GUINT_TO_POINTER(previous_domain->id));
  309. }
  310. }
  311. domain = virtio_iommu_get_domain(s, domain_id,
  312. flags & VIRTIO_IOMMU_ATTACH_F_BYPASS);
  313. if (!domain) {
  314. /* Incompatible bypass flag */
  315. return VIRTIO_IOMMU_S_INVAL;
  316. }
  317. QLIST_INSERT_HEAD(&domain->endpoint_list, ep, next);
  318. ep->domain = domain;
  319. /* Replay domain mappings on the associated memory region */
  320. g_tree_foreach(domain->mappings, virtio_iommu_notify_map_cb,
  321. ep->iommu_mr);
  322. return VIRTIO_IOMMU_S_OK;
  323. }
  324. static int virtio_iommu_detach(VirtIOIOMMU *s,
  325. struct virtio_iommu_req_detach *req)
  326. {
  327. uint32_t domain_id = le32_to_cpu(req->domain);
  328. uint32_t ep_id = le32_to_cpu(req->endpoint);
  329. VirtIOIOMMUDomain *domain;
  330. VirtIOIOMMUEndpoint *ep;
  331. trace_virtio_iommu_detach(domain_id, ep_id);
  332. ep = g_tree_lookup(s->endpoints, GUINT_TO_POINTER(ep_id));
  333. if (!ep) {
  334. return VIRTIO_IOMMU_S_NOENT;
  335. }
  336. domain = ep->domain;
  337. if (!domain || domain->id != domain_id) {
  338. return VIRTIO_IOMMU_S_INVAL;
  339. }
  340. virtio_iommu_detach_endpoint_from_domain(ep);
  341. if (QLIST_EMPTY(&domain->endpoint_list)) {
  342. g_tree_remove(s->domains, GUINT_TO_POINTER(domain->id));
  343. }
  344. return VIRTIO_IOMMU_S_OK;
  345. }
  346. static int virtio_iommu_map(VirtIOIOMMU *s,
  347. struct virtio_iommu_req_map *req)
  348. {
  349. uint32_t domain_id = le32_to_cpu(req->domain);
  350. uint64_t phys_start = le64_to_cpu(req->phys_start);
  351. uint64_t virt_start = le64_to_cpu(req->virt_start);
  352. uint64_t virt_end = le64_to_cpu(req->virt_end);
  353. uint32_t flags = le32_to_cpu(req->flags);
  354. VirtIOIOMMUDomain *domain;
  355. VirtIOIOMMUInterval *interval;
  356. VirtIOIOMMUMapping *mapping;
  357. VirtIOIOMMUEndpoint *ep;
  358. if (flags & ~VIRTIO_IOMMU_MAP_F_MASK) {
  359. return VIRTIO_IOMMU_S_INVAL;
  360. }
  361. domain = g_tree_lookup(s->domains, GUINT_TO_POINTER(domain_id));
  362. if (!domain) {
  363. return VIRTIO_IOMMU_S_NOENT;
  364. }
  365. if (domain->bypass) {
  366. return VIRTIO_IOMMU_S_INVAL;
  367. }
  368. interval = g_malloc0(sizeof(*interval));
  369. interval->low = virt_start;
  370. interval->high = virt_end;
  371. mapping = g_tree_lookup(domain->mappings, (gpointer)interval);
  372. if (mapping) {
  373. g_free(interval);
  374. return VIRTIO_IOMMU_S_INVAL;
  375. }
  376. trace_virtio_iommu_map(domain_id, virt_start, virt_end, phys_start, flags);
  377. mapping = g_malloc0(sizeof(*mapping));
  378. mapping->phys_addr = phys_start;
  379. mapping->flags = flags;
  380. g_tree_insert(domain->mappings, interval, mapping);
  381. QLIST_FOREACH(ep, &domain->endpoint_list, next) {
  382. virtio_iommu_notify_map(ep->iommu_mr, virt_start, virt_end, phys_start,
  383. flags);
  384. }
  385. return VIRTIO_IOMMU_S_OK;
  386. }
  387. static int virtio_iommu_unmap(VirtIOIOMMU *s,
  388. struct virtio_iommu_req_unmap *req)
  389. {
  390. uint32_t domain_id = le32_to_cpu(req->domain);
  391. uint64_t virt_start = le64_to_cpu(req->virt_start);
  392. uint64_t virt_end = le64_to_cpu(req->virt_end);
  393. VirtIOIOMMUMapping *iter_val;
  394. VirtIOIOMMUInterval interval, *iter_key;
  395. VirtIOIOMMUDomain *domain;
  396. VirtIOIOMMUEndpoint *ep;
  397. int ret = VIRTIO_IOMMU_S_OK;
  398. trace_virtio_iommu_unmap(domain_id, virt_start, virt_end);
  399. domain = g_tree_lookup(s->domains, GUINT_TO_POINTER(domain_id));
  400. if (!domain) {
  401. return VIRTIO_IOMMU_S_NOENT;
  402. }
  403. if (domain->bypass) {
  404. return VIRTIO_IOMMU_S_INVAL;
  405. }
  406. interval.low = virt_start;
  407. interval.high = virt_end;
  408. while (g_tree_lookup_extended(domain->mappings, &interval,
  409. (void **)&iter_key, (void**)&iter_val)) {
  410. uint64_t current_low = iter_key->low;
  411. uint64_t current_high = iter_key->high;
  412. if (interval.low <= current_low && interval.high >= current_high) {
  413. QLIST_FOREACH(ep, &domain->endpoint_list, next) {
  414. virtio_iommu_notify_unmap(ep->iommu_mr, current_low,
  415. current_high);
  416. }
  417. g_tree_remove(domain->mappings, iter_key);
  418. trace_virtio_iommu_unmap_done(domain_id, current_low, current_high);
  419. } else {
  420. ret = VIRTIO_IOMMU_S_RANGE;
  421. break;
  422. }
  423. }
  424. return ret;
  425. }
  426. static ssize_t virtio_iommu_fill_resv_mem_prop(VirtIOIOMMU *s, uint32_t ep,
  427. uint8_t *buf, size_t free)
  428. {
  429. struct virtio_iommu_probe_resv_mem prop = {};
  430. size_t size = sizeof(prop), length = size - sizeof(prop.head), total;
  431. int i;
  432. total = size * s->nb_reserved_regions;
  433. if (total > free) {
  434. return -ENOSPC;
  435. }
  436. for (i = 0; i < s->nb_reserved_regions; i++) {
  437. unsigned subtype = s->reserved_regions[i].type;
  438. assert(subtype == VIRTIO_IOMMU_RESV_MEM_T_RESERVED ||
  439. subtype == VIRTIO_IOMMU_RESV_MEM_T_MSI);
  440. prop.head.type = cpu_to_le16(VIRTIO_IOMMU_PROBE_T_RESV_MEM);
  441. prop.head.length = cpu_to_le16(length);
  442. prop.subtype = subtype;
  443. prop.start = cpu_to_le64(s->reserved_regions[i].low);
  444. prop.end = cpu_to_le64(s->reserved_regions[i].high);
  445. memcpy(buf, &prop, size);
  446. trace_virtio_iommu_fill_resv_property(ep, prop.subtype,
  447. prop.start, prop.end);
  448. buf += size;
  449. }
  450. return total;
  451. }
  452. /**
  453. * virtio_iommu_probe - Fill the probe request buffer with
  454. * the properties the device is able to return
  455. */
  456. static int virtio_iommu_probe(VirtIOIOMMU *s,
  457. struct virtio_iommu_req_probe *req,
  458. uint8_t *buf)
  459. {
  460. uint32_t ep_id = le32_to_cpu(req->endpoint);
  461. size_t free = VIOMMU_PROBE_SIZE;
  462. ssize_t count;
  463. if (!virtio_iommu_mr(s, ep_id)) {
  464. return VIRTIO_IOMMU_S_NOENT;
  465. }
  466. count = virtio_iommu_fill_resv_mem_prop(s, ep_id, buf, free);
  467. if (count < 0) {
  468. return VIRTIO_IOMMU_S_INVAL;
  469. }
  470. buf += count;
  471. free -= count;
  472. return VIRTIO_IOMMU_S_OK;
  473. }
  474. static int virtio_iommu_iov_to_req(struct iovec *iov,
  475. unsigned int iov_cnt,
  476. void *req, size_t req_sz)
  477. {
  478. size_t sz, payload_sz = req_sz - sizeof(struct virtio_iommu_req_tail);
  479. sz = iov_to_buf(iov, iov_cnt, 0, req, payload_sz);
  480. if (unlikely(sz != payload_sz)) {
  481. return VIRTIO_IOMMU_S_INVAL;
  482. }
  483. return 0;
  484. }
  485. #define virtio_iommu_handle_req(__req) \
  486. static int virtio_iommu_handle_ ## __req(VirtIOIOMMU *s, \
  487. struct iovec *iov, \
  488. unsigned int iov_cnt) \
  489. { \
  490. struct virtio_iommu_req_ ## __req req; \
  491. int ret = virtio_iommu_iov_to_req(iov, iov_cnt, &req, sizeof(req)); \
  492. \
  493. return ret ? ret : virtio_iommu_ ## __req(s, &req); \
  494. }
  495. virtio_iommu_handle_req(attach)
  496. virtio_iommu_handle_req(detach)
  497. virtio_iommu_handle_req(map)
  498. virtio_iommu_handle_req(unmap)
  499. static int virtio_iommu_handle_probe(VirtIOIOMMU *s,
  500. struct iovec *iov,
  501. unsigned int iov_cnt,
  502. uint8_t *buf)
  503. {
  504. struct virtio_iommu_req_probe req;
  505. int ret = virtio_iommu_iov_to_req(iov, iov_cnt, &req, sizeof(req));
  506. return ret ? ret : virtio_iommu_probe(s, &req, buf);
  507. }
  508. static void virtio_iommu_handle_command(VirtIODevice *vdev, VirtQueue *vq)
  509. {
  510. VirtIOIOMMU *s = VIRTIO_IOMMU(vdev);
  511. struct virtio_iommu_req_head head;
  512. struct virtio_iommu_req_tail tail = {};
  513. size_t output_size = sizeof(tail), sz;
  514. VirtQueueElement *elem;
  515. unsigned int iov_cnt;
  516. struct iovec *iov;
  517. void *buf = NULL;
  518. for (;;) {
  519. elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
  520. if (!elem) {
  521. return;
  522. }
  523. if (iov_size(elem->in_sg, elem->in_num) < sizeof(tail) ||
  524. iov_size(elem->out_sg, elem->out_num) < sizeof(head)) {
  525. virtio_error(vdev, "virtio-iommu bad head/tail size");
  526. virtqueue_detach_element(vq, elem, 0);
  527. g_free(elem);
  528. break;
  529. }
  530. iov_cnt = elem->out_num;
  531. iov = elem->out_sg;
  532. sz = iov_to_buf(iov, iov_cnt, 0, &head, sizeof(head));
  533. if (unlikely(sz != sizeof(head))) {
  534. tail.status = VIRTIO_IOMMU_S_DEVERR;
  535. goto out;
  536. }
  537. qemu_mutex_lock(&s->mutex);
  538. switch (head.type) {
  539. case VIRTIO_IOMMU_T_ATTACH:
  540. tail.status = virtio_iommu_handle_attach(s, iov, iov_cnt);
  541. break;
  542. case VIRTIO_IOMMU_T_DETACH:
  543. tail.status = virtio_iommu_handle_detach(s, iov, iov_cnt);
  544. break;
  545. case VIRTIO_IOMMU_T_MAP:
  546. tail.status = virtio_iommu_handle_map(s, iov, iov_cnt);
  547. break;
  548. case VIRTIO_IOMMU_T_UNMAP:
  549. tail.status = virtio_iommu_handle_unmap(s, iov, iov_cnt);
  550. break;
  551. case VIRTIO_IOMMU_T_PROBE:
  552. {
  553. struct virtio_iommu_req_tail *ptail;
  554. output_size = s->config.probe_size + sizeof(tail);
  555. buf = g_malloc0(output_size);
  556. ptail = (struct virtio_iommu_req_tail *)
  557. (buf + s->config.probe_size);
  558. ptail->status = virtio_iommu_handle_probe(s, iov, iov_cnt, buf);
  559. break;
  560. }
  561. default:
  562. tail.status = VIRTIO_IOMMU_S_UNSUPP;
  563. }
  564. qemu_mutex_unlock(&s->mutex);
  565. out:
  566. sz = iov_from_buf(elem->in_sg, elem->in_num, 0,
  567. buf ? buf : &tail, output_size);
  568. assert(sz == output_size);
  569. virtqueue_push(vq, elem, sz);
  570. virtio_notify(vdev, vq);
  571. g_free(elem);
  572. g_free(buf);
  573. }
  574. }
  575. static void virtio_iommu_report_fault(VirtIOIOMMU *viommu, uint8_t reason,
  576. int flags, uint32_t endpoint,
  577. uint64_t address)
  578. {
  579. VirtIODevice *vdev = &viommu->parent_obj;
  580. VirtQueue *vq = viommu->event_vq;
  581. struct virtio_iommu_fault fault;
  582. VirtQueueElement *elem;
  583. size_t sz;
  584. memset(&fault, 0, sizeof(fault));
  585. fault.reason = reason;
  586. fault.flags = cpu_to_le32(flags);
  587. fault.endpoint = cpu_to_le32(endpoint);
  588. fault.address = cpu_to_le64(address);
  589. elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
  590. if (!elem) {
  591. error_report_once(
  592. "no buffer available in event queue to report event");
  593. return;
  594. }
  595. if (iov_size(elem->in_sg, elem->in_num) < sizeof(fault)) {
  596. virtio_error(vdev, "error buffer of wrong size");
  597. virtqueue_detach_element(vq, elem, 0);
  598. g_free(elem);
  599. return;
  600. }
  601. sz = iov_from_buf(elem->in_sg, elem->in_num, 0,
  602. &fault, sizeof(fault));
  603. assert(sz == sizeof(fault));
  604. trace_virtio_iommu_report_fault(reason, flags, endpoint, address);
  605. virtqueue_push(vq, elem, sz);
  606. virtio_notify(vdev, vq);
  607. g_free(elem);
  608. }
  609. static IOMMUTLBEntry virtio_iommu_translate(IOMMUMemoryRegion *mr, hwaddr addr,
  610. IOMMUAccessFlags flag,
  611. int iommu_idx)
  612. {
  613. IOMMUDevice *sdev = container_of(mr, IOMMUDevice, iommu_mr);
  614. VirtIOIOMMUInterval interval, *mapping_key;
  615. VirtIOIOMMUMapping *mapping_value;
  616. VirtIOIOMMU *s = sdev->viommu;
  617. bool read_fault, write_fault;
  618. VirtIOIOMMUEndpoint *ep;
  619. uint32_t sid, flags;
  620. bool bypass_allowed;
  621. bool found;
  622. int i;
  623. interval.low = addr;
  624. interval.high = addr + 1;
  625. IOMMUTLBEntry entry = {
  626. .target_as = &address_space_memory,
  627. .iova = addr,
  628. .translated_addr = addr,
  629. .addr_mask = (1 << ctz32(s->config.page_size_mask)) - 1,
  630. .perm = IOMMU_NONE,
  631. };
  632. bypass_allowed = s->config.bypass;
  633. sid = virtio_iommu_get_bdf(sdev);
  634. trace_virtio_iommu_translate(mr->parent_obj.name, sid, addr, flag);
  635. qemu_mutex_lock(&s->mutex);
  636. ep = g_tree_lookup(s->endpoints, GUINT_TO_POINTER(sid));
  637. if (!ep) {
  638. if (!bypass_allowed) {
  639. error_report_once("%s sid=%d is not known!!", __func__, sid);
  640. virtio_iommu_report_fault(s, VIRTIO_IOMMU_FAULT_R_UNKNOWN,
  641. VIRTIO_IOMMU_FAULT_F_ADDRESS,
  642. sid, addr);
  643. } else {
  644. entry.perm = flag;
  645. }
  646. goto unlock;
  647. }
  648. for (i = 0; i < s->nb_reserved_regions; i++) {
  649. ReservedRegion *reg = &s->reserved_regions[i];
  650. if (addr >= reg->low && addr <= reg->high) {
  651. switch (reg->type) {
  652. case VIRTIO_IOMMU_RESV_MEM_T_MSI:
  653. entry.perm = flag;
  654. break;
  655. case VIRTIO_IOMMU_RESV_MEM_T_RESERVED:
  656. default:
  657. virtio_iommu_report_fault(s, VIRTIO_IOMMU_FAULT_R_MAPPING,
  658. VIRTIO_IOMMU_FAULT_F_ADDRESS,
  659. sid, addr);
  660. break;
  661. }
  662. goto unlock;
  663. }
  664. }
  665. if (!ep->domain) {
  666. if (!bypass_allowed) {
  667. error_report_once("%s %02x:%02x.%01x not attached to any domain",
  668. __func__, PCI_BUS_NUM(sid),
  669. PCI_SLOT(sid), PCI_FUNC(sid));
  670. virtio_iommu_report_fault(s, VIRTIO_IOMMU_FAULT_R_DOMAIN,
  671. VIRTIO_IOMMU_FAULT_F_ADDRESS,
  672. sid, addr);
  673. } else {
  674. entry.perm = flag;
  675. }
  676. goto unlock;
  677. } else if (ep->domain->bypass) {
  678. entry.perm = flag;
  679. goto unlock;
  680. }
  681. found = g_tree_lookup_extended(ep->domain->mappings, (gpointer)(&interval),
  682. (void **)&mapping_key,
  683. (void **)&mapping_value);
  684. if (!found) {
  685. error_report_once("%s no mapping for 0x%"PRIx64" for sid=%d",
  686. __func__, addr, sid);
  687. virtio_iommu_report_fault(s, VIRTIO_IOMMU_FAULT_R_MAPPING,
  688. VIRTIO_IOMMU_FAULT_F_ADDRESS,
  689. sid, addr);
  690. goto unlock;
  691. }
  692. read_fault = (flag & IOMMU_RO) &&
  693. !(mapping_value->flags & VIRTIO_IOMMU_MAP_F_READ);
  694. write_fault = (flag & IOMMU_WO) &&
  695. !(mapping_value->flags & VIRTIO_IOMMU_MAP_F_WRITE);
  696. flags = read_fault ? VIRTIO_IOMMU_FAULT_F_READ : 0;
  697. flags |= write_fault ? VIRTIO_IOMMU_FAULT_F_WRITE : 0;
  698. if (flags) {
  699. error_report_once("%s permission error on 0x%"PRIx64"(%d): allowed=%d",
  700. __func__, addr, flag, mapping_value->flags);
  701. flags |= VIRTIO_IOMMU_FAULT_F_ADDRESS;
  702. virtio_iommu_report_fault(s, VIRTIO_IOMMU_FAULT_R_MAPPING,
  703. flags | VIRTIO_IOMMU_FAULT_F_ADDRESS,
  704. sid, addr);
  705. goto unlock;
  706. }
  707. entry.translated_addr = addr - mapping_key->low + mapping_value->phys_addr;
  708. entry.perm = flag;
  709. trace_virtio_iommu_translate_out(addr, entry.translated_addr, sid);
  710. unlock:
  711. qemu_mutex_unlock(&s->mutex);
  712. return entry;
  713. }
  714. static void virtio_iommu_get_config(VirtIODevice *vdev, uint8_t *config_data)
  715. {
  716. VirtIOIOMMU *dev = VIRTIO_IOMMU(vdev);
  717. struct virtio_iommu_config *dev_config = &dev->config;
  718. struct virtio_iommu_config *out_config = (void *)config_data;
  719. out_config->page_size_mask = cpu_to_le64(dev_config->page_size_mask);
  720. out_config->input_range.start = cpu_to_le64(dev_config->input_range.start);
  721. out_config->input_range.end = cpu_to_le64(dev_config->input_range.end);
  722. out_config->domain_range.start = cpu_to_le32(dev_config->domain_range.start);
  723. out_config->domain_range.end = cpu_to_le32(dev_config->domain_range.end);
  724. out_config->probe_size = cpu_to_le32(dev_config->probe_size);
  725. out_config->bypass = dev_config->bypass;
  726. trace_virtio_iommu_get_config(dev_config->page_size_mask,
  727. dev_config->input_range.start,
  728. dev_config->input_range.end,
  729. dev_config->domain_range.start,
  730. dev_config->domain_range.end,
  731. dev_config->probe_size,
  732. dev_config->bypass);
  733. }
  734. static void virtio_iommu_set_config(VirtIODevice *vdev,
  735. const uint8_t *config_data)
  736. {
  737. VirtIOIOMMU *dev = VIRTIO_IOMMU(vdev);
  738. struct virtio_iommu_config *dev_config = &dev->config;
  739. const struct virtio_iommu_config *in_config = (void *)config_data;
  740. if (in_config->bypass != dev_config->bypass) {
  741. if (!virtio_vdev_has_feature(vdev, VIRTIO_IOMMU_F_BYPASS_CONFIG)) {
  742. virtio_error(vdev, "cannot set config.bypass");
  743. return;
  744. } else if (in_config->bypass != 0 && in_config->bypass != 1) {
  745. virtio_error(vdev, "invalid config.bypass value '%u'",
  746. in_config->bypass);
  747. return;
  748. }
  749. dev_config->bypass = in_config->bypass;
  750. }
  751. trace_virtio_iommu_set_config(in_config->bypass);
  752. }
  753. static uint64_t virtio_iommu_get_features(VirtIODevice *vdev, uint64_t f,
  754. Error **errp)
  755. {
  756. VirtIOIOMMU *dev = VIRTIO_IOMMU(vdev);
  757. f |= dev->features;
  758. trace_virtio_iommu_get_features(f);
  759. return f;
  760. }
  761. static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data)
  762. {
  763. guint ua = GPOINTER_TO_UINT(a);
  764. guint ub = GPOINTER_TO_UINT(b);
  765. return (ua > ub) - (ua < ub);
  766. }
  767. static gboolean virtio_iommu_remap(gpointer key, gpointer value, gpointer data)
  768. {
  769. VirtIOIOMMUMapping *mapping = (VirtIOIOMMUMapping *) value;
  770. VirtIOIOMMUInterval *interval = (VirtIOIOMMUInterval *) key;
  771. IOMMUMemoryRegion *mr = (IOMMUMemoryRegion *) data;
  772. trace_virtio_iommu_remap(mr->parent_obj.name, interval->low, interval->high,
  773. mapping->phys_addr);
  774. virtio_iommu_notify_map(mr, interval->low, interval->high,
  775. mapping->phys_addr, mapping->flags);
  776. return false;
  777. }
  778. static void virtio_iommu_replay(IOMMUMemoryRegion *mr, IOMMUNotifier *n)
  779. {
  780. IOMMUDevice *sdev = container_of(mr, IOMMUDevice, iommu_mr);
  781. VirtIOIOMMU *s = sdev->viommu;
  782. uint32_t sid;
  783. VirtIOIOMMUEndpoint *ep;
  784. sid = virtio_iommu_get_bdf(sdev);
  785. qemu_mutex_lock(&s->mutex);
  786. if (!s->endpoints) {
  787. goto unlock;
  788. }
  789. ep = g_tree_lookup(s->endpoints, GUINT_TO_POINTER(sid));
  790. if (!ep || !ep->domain) {
  791. goto unlock;
  792. }
  793. g_tree_foreach(ep->domain->mappings, virtio_iommu_remap, mr);
  794. unlock:
  795. qemu_mutex_unlock(&s->mutex);
  796. }
  797. static int virtio_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu_mr,
  798. IOMMUNotifierFlag old,
  799. IOMMUNotifierFlag new,
  800. Error **errp)
  801. {
  802. if (new & IOMMU_NOTIFIER_DEVIOTLB_UNMAP) {
  803. error_setg(errp, "Virtio-iommu does not support dev-iotlb yet");
  804. return -EINVAL;
  805. }
  806. if (old == IOMMU_NOTIFIER_NONE) {
  807. trace_virtio_iommu_notify_flag_add(iommu_mr->parent_obj.name);
  808. } else if (new == IOMMU_NOTIFIER_NONE) {
  809. trace_virtio_iommu_notify_flag_del(iommu_mr->parent_obj.name);
  810. }
  811. return 0;
  812. }
  813. /*
  814. * The default mask (TARGET_PAGE_MASK) is the smallest supported guest granule,
  815. * for example 0xfffffffffffff000. When an assigned device has page size
  816. * restrictions due to the hardware IOMMU configuration, apply this restriction
  817. * to the mask.
  818. */
  819. static int virtio_iommu_set_page_size_mask(IOMMUMemoryRegion *mr,
  820. uint64_t new_mask,
  821. Error **errp)
  822. {
  823. IOMMUDevice *sdev = container_of(mr, IOMMUDevice, iommu_mr);
  824. VirtIOIOMMU *s = sdev->viommu;
  825. uint64_t cur_mask = s->config.page_size_mask;
  826. trace_virtio_iommu_set_page_size_mask(mr->parent_obj.name, cur_mask,
  827. new_mask);
  828. if ((cur_mask & new_mask) == 0) {
  829. error_setg(errp, "virtio-iommu page mask 0x%"PRIx64
  830. " is incompatible with mask 0x%"PRIx64, cur_mask, new_mask);
  831. return -1;
  832. }
  833. /*
  834. * After the machine is finalized, we can't change the mask anymore. If by
  835. * chance the hotplugged device supports the same granule, we can still
  836. * accept it. Having a different masks is possible but the guest will use
  837. * sub-optimal block sizes, so warn about it.
  838. */
  839. if (phase_check(PHASE_MACHINE_READY)) {
  840. int new_granule = ctz64(new_mask);
  841. int cur_granule = ctz64(cur_mask);
  842. if (new_granule != cur_granule) {
  843. error_setg(errp, "virtio-iommu page mask 0x%"PRIx64
  844. " is incompatible with mask 0x%"PRIx64, cur_mask,
  845. new_mask);
  846. return -1;
  847. } else if (new_mask != cur_mask) {
  848. warn_report("virtio-iommu page mask 0x%"PRIx64
  849. " does not match 0x%"PRIx64, cur_mask, new_mask);
  850. }
  851. return 0;
  852. }
  853. s->config.page_size_mask &= new_mask;
  854. return 0;
  855. }
  856. static void virtio_iommu_system_reset(void *opaque)
  857. {
  858. VirtIOIOMMU *s = opaque;
  859. trace_virtio_iommu_system_reset();
  860. /*
  861. * config.bypass is sticky across device reset, but should be restored on
  862. * system reset
  863. */
  864. s->config.bypass = s->boot_bypass;
  865. }
  866. static void virtio_iommu_device_realize(DeviceState *dev, Error **errp)
  867. {
  868. VirtIODevice *vdev = VIRTIO_DEVICE(dev);
  869. VirtIOIOMMU *s = VIRTIO_IOMMU(dev);
  870. virtio_init(vdev, "virtio-iommu", VIRTIO_ID_IOMMU,
  871. sizeof(struct virtio_iommu_config));
  872. memset(s->iommu_pcibus_by_bus_num, 0, sizeof(s->iommu_pcibus_by_bus_num));
  873. s->req_vq = virtio_add_queue(vdev, VIOMMU_DEFAULT_QUEUE_SIZE,
  874. virtio_iommu_handle_command);
  875. s->event_vq = virtio_add_queue(vdev, VIOMMU_DEFAULT_QUEUE_SIZE, NULL);
  876. s->config.page_size_mask = TARGET_PAGE_MASK;
  877. s->config.input_range.end = UINT64_MAX;
  878. s->config.domain_range.end = UINT32_MAX;
  879. s->config.probe_size = VIOMMU_PROBE_SIZE;
  880. virtio_add_feature(&s->features, VIRTIO_RING_F_EVENT_IDX);
  881. virtio_add_feature(&s->features, VIRTIO_RING_F_INDIRECT_DESC);
  882. virtio_add_feature(&s->features, VIRTIO_F_VERSION_1);
  883. virtio_add_feature(&s->features, VIRTIO_IOMMU_F_INPUT_RANGE);
  884. virtio_add_feature(&s->features, VIRTIO_IOMMU_F_DOMAIN_RANGE);
  885. virtio_add_feature(&s->features, VIRTIO_IOMMU_F_MAP_UNMAP);
  886. virtio_add_feature(&s->features, VIRTIO_IOMMU_F_MMIO);
  887. virtio_add_feature(&s->features, VIRTIO_IOMMU_F_PROBE);
  888. virtio_add_feature(&s->features, VIRTIO_IOMMU_F_BYPASS_CONFIG);
  889. qemu_mutex_init(&s->mutex);
  890. s->as_by_busptr = g_hash_table_new_full(NULL, NULL, NULL, g_free);
  891. if (s->primary_bus) {
  892. pci_setup_iommu(s->primary_bus, virtio_iommu_find_add_as, s);
  893. } else {
  894. error_setg(errp, "VIRTIO-IOMMU is not attached to any PCI bus!");
  895. }
  896. qemu_register_reset(virtio_iommu_system_reset, s);
  897. }
  898. static void virtio_iommu_device_unrealize(DeviceState *dev)
  899. {
  900. VirtIODevice *vdev = VIRTIO_DEVICE(dev);
  901. VirtIOIOMMU *s = VIRTIO_IOMMU(dev);
  902. qemu_unregister_reset(virtio_iommu_system_reset, s);
  903. g_hash_table_destroy(s->as_by_busptr);
  904. if (s->domains) {
  905. g_tree_destroy(s->domains);
  906. }
  907. if (s->endpoints) {
  908. g_tree_destroy(s->endpoints);
  909. }
  910. virtio_delete_queue(s->req_vq);
  911. virtio_delete_queue(s->event_vq);
  912. virtio_cleanup(vdev);
  913. }
  914. static void virtio_iommu_device_reset(VirtIODevice *vdev)
  915. {
  916. VirtIOIOMMU *s = VIRTIO_IOMMU(vdev);
  917. trace_virtio_iommu_device_reset();
  918. if (s->domains) {
  919. g_tree_destroy(s->domains);
  920. }
  921. if (s->endpoints) {
  922. g_tree_destroy(s->endpoints);
  923. }
  924. s->domains = g_tree_new_full((GCompareDataFunc)int_cmp,
  925. NULL, NULL, virtio_iommu_put_domain);
  926. s->endpoints = g_tree_new_full((GCompareDataFunc)int_cmp,
  927. NULL, NULL, virtio_iommu_put_endpoint);
  928. }
  929. static void virtio_iommu_set_status(VirtIODevice *vdev, uint8_t status)
  930. {
  931. trace_virtio_iommu_device_status(status);
  932. }
  933. static void virtio_iommu_instance_init(Object *obj)
  934. {
  935. }
  936. #define VMSTATE_INTERVAL \
  937. { \
  938. .name = "interval", \
  939. .version_id = 1, \
  940. .minimum_version_id = 1, \
  941. .fields = (VMStateField[]) { \
  942. VMSTATE_UINT64(low, VirtIOIOMMUInterval), \
  943. VMSTATE_UINT64(high, VirtIOIOMMUInterval), \
  944. VMSTATE_END_OF_LIST() \
  945. } \
  946. }
  947. #define VMSTATE_MAPPING \
  948. { \
  949. .name = "mapping", \
  950. .version_id = 1, \
  951. .minimum_version_id = 1, \
  952. .fields = (VMStateField[]) { \
  953. VMSTATE_UINT64(phys_addr, VirtIOIOMMUMapping),\
  954. VMSTATE_UINT32(flags, VirtIOIOMMUMapping), \
  955. VMSTATE_END_OF_LIST() \
  956. }, \
  957. }
  958. static const VMStateDescription vmstate_interval_mapping[2] = {
  959. VMSTATE_MAPPING, /* value */
  960. VMSTATE_INTERVAL /* key */
  961. };
  962. static int domain_preload(void *opaque)
  963. {
  964. VirtIOIOMMUDomain *domain = opaque;
  965. domain->mappings = g_tree_new_full((GCompareDataFunc)interval_cmp,
  966. NULL, g_free, g_free);
  967. return 0;
  968. }
  969. static const VMStateDescription vmstate_endpoint = {
  970. .name = "endpoint",
  971. .version_id = 1,
  972. .minimum_version_id = 1,
  973. .fields = (VMStateField[]) {
  974. VMSTATE_UINT32(id, VirtIOIOMMUEndpoint),
  975. VMSTATE_END_OF_LIST()
  976. }
  977. };
  978. static const VMStateDescription vmstate_domain = {
  979. .name = "domain",
  980. .version_id = 2,
  981. .minimum_version_id = 2,
  982. .pre_load = domain_preload,
  983. .fields = (VMStateField[]) {
  984. VMSTATE_UINT32(id, VirtIOIOMMUDomain),
  985. VMSTATE_GTREE_V(mappings, VirtIOIOMMUDomain, 1,
  986. vmstate_interval_mapping,
  987. VirtIOIOMMUInterval, VirtIOIOMMUMapping),
  988. VMSTATE_QLIST_V(endpoint_list, VirtIOIOMMUDomain, 1,
  989. vmstate_endpoint, VirtIOIOMMUEndpoint, next),
  990. VMSTATE_BOOL_V(bypass, VirtIOIOMMUDomain, 2),
  991. VMSTATE_END_OF_LIST()
  992. }
  993. };
  994. static gboolean reconstruct_endpoints(gpointer key, gpointer value,
  995. gpointer data)
  996. {
  997. VirtIOIOMMU *s = (VirtIOIOMMU *)data;
  998. VirtIOIOMMUDomain *d = (VirtIOIOMMUDomain *)value;
  999. VirtIOIOMMUEndpoint *iter;
  1000. IOMMUMemoryRegion *mr;
  1001. QLIST_FOREACH(iter, &d->endpoint_list, next) {
  1002. mr = virtio_iommu_mr(s, iter->id);
  1003. assert(mr);
  1004. iter->domain = d;
  1005. iter->iommu_mr = mr;
  1006. g_tree_insert(s->endpoints, GUINT_TO_POINTER(iter->id), iter);
  1007. }
  1008. return false; /* continue the domain traversal */
  1009. }
  1010. static int iommu_post_load(void *opaque, int version_id)
  1011. {
  1012. VirtIOIOMMU *s = opaque;
  1013. g_tree_foreach(s->domains, reconstruct_endpoints, s);
  1014. return 0;
  1015. }
  1016. static const VMStateDescription vmstate_virtio_iommu_device = {
  1017. .name = "virtio-iommu-device",
  1018. .minimum_version_id = 2,
  1019. .version_id = 2,
  1020. .post_load = iommu_post_load,
  1021. .fields = (VMStateField[]) {
  1022. VMSTATE_GTREE_DIRECT_KEY_V(domains, VirtIOIOMMU, 2,
  1023. &vmstate_domain, VirtIOIOMMUDomain),
  1024. VMSTATE_UINT8_V(config.bypass, VirtIOIOMMU, 2),
  1025. VMSTATE_END_OF_LIST()
  1026. },
  1027. };
  1028. static const VMStateDescription vmstate_virtio_iommu = {
  1029. .name = "virtio-iommu",
  1030. .minimum_version_id = 2,
  1031. .priority = MIG_PRI_IOMMU,
  1032. .version_id = 2,
  1033. .fields = (VMStateField[]) {
  1034. VMSTATE_VIRTIO_DEVICE,
  1035. VMSTATE_END_OF_LIST()
  1036. },
  1037. };
  1038. static Property virtio_iommu_properties[] = {
  1039. DEFINE_PROP_LINK("primary-bus", VirtIOIOMMU, primary_bus, "PCI", PCIBus *),
  1040. DEFINE_PROP_BOOL("boot-bypass", VirtIOIOMMU, boot_bypass, true),
  1041. DEFINE_PROP_END_OF_LIST(),
  1042. };
  1043. static void virtio_iommu_class_init(ObjectClass *klass, void *data)
  1044. {
  1045. DeviceClass *dc = DEVICE_CLASS(klass);
  1046. VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
  1047. device_class_set_props(dc, virtio_iommu_properties);
  1048. dc->vmsd = &vmstate_virtio_iommu;
  1049. set_bit(DEVICE_CATEGORY_MISC, dc->categories);
  1050. vdc->realize = virtio_iommu_device_realize;
  1051. vdc->unrealize = virtio_iommu_device_unrealize;
  1052. vdc->reset = virtio_iommu_device_reset;
  1053. vdc->get_config = virtio_iommu_get_config;
  1054. vdc->set_config = virtio_iommu_set_config;
  1055. vdc->get_features = virtio_iommu_get_features;
  1056. vdc->set_status = virtio_iommu_set_status;
  1057. vdc->vmsd = &vmstate_virtio_iommu_device;
  1058. }
  1059. static void virtio_iommu_memory_region_class_init(ObjectClass *klass,
  1060. void *data)
  1061. {
  1062. IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
  1063. imrc->translate = virtio_iommu_translate;
  1064. imrc->replay = virtio_iommu_replay;
  1065. imrc->notify_flag_changed = virtio_iommu_notify_flag_changed;
  1066. imrc->iommu_set_page_size_mask = virtio_iommu_set_page_size_mask;
  1067. }
  1068. static const TypeInfo virtio_iommu_info = {
  1069. .name = TYPE_VIRTIO_IOMMU,
  1070. .parent = TYPE_VIRTIO_DEVICE,
  1071. .instance_size = sizeof(VirtIOIOMMU),
  1072. .instance_init = virtio_iommu_instance_init,
  1073. .class_init = virtio_iommu_class_init,
  1074. };
  1075. static const TypeInfo virtio_iommu_memory_region_info = {
  1076. .parent = TYPE_IOMMU_MEMORY_REGION,
  1077. .name = TYPE_VIRTIO_IOMMU_MEMORY_REGION,
  1078. .class_init = virtio_iommu_memory_region_class_init,
  1079. };
  1080. static void virtio_register_types(void)
  1081. {
  1082. type_register_static(&virtio_iommu_info);
  1083. type_register_static(&virtio_iommu_memory_region_info);
  1084. }
  1085. type_init(virtio_register_types)