2
0

smmu-common.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. /*
  2. * Copyright (C) 2014-2016 Broadcom Corporation
  3. * Copyright (c) 2017 Red Hat, Inc.
  4. * Written by Prem Mallappa, Eric Auger
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * Author: Prem Mallappa <pmallapp@broadcom.com>
  16. *
  17. */
  18. #include "qemu/osdep.h"
  19. #include "exec/address-spaces.h"
  20. #include "trace.h"
  21. #include "exec/target_page.h"
  22. #include "hw/core/cpu.h"
  23. #include "hw/qdev-properties.h"
  24. #include "qapi/error.h"
  25. #include "qemu/jhash.h"
  26. #include "qemu/module.h"
  27. #include "qemu/error-report.h"
  28. #include "hw/arm/smmu-common.h"
  29. #include "smmu-internal.h"
  30. /* IOTLB Management */
  31. inline void smmu_iotlb_inv_all(SMMUState *s)
  32. {
  33. trace_smmu_iotlb_inv_all();
  34. g_hash_table_remove_all(s->iotlb);
  35. }
  36. static gboolean smmu_hash_remove_by_asid(gpointer key, gpointer value,
  37. gpointer user_data)
  38. {
  39. uint16_t asid = *(uint16_t *)user_data;
  40. SMMUIOTLBKey *iotlb_key = (SMMUIOTLBKey *)key;
  41. return iotlb_key->asid == asid;
  42. }
  43. inline void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova)
  44. {
  45. SMMUIOTLBKey key = {.asid = asid, .iova = iova};
  46. trace_smmu_iotlb_inv_iova(asid, iova);
  47. g_hash_table_remove(s->iotlb, &key);
  48. }
  49. inline void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid)
  50. {
  51. trace_smmu_iotlb_inv_asid(asid);
  52. g_hash_table_foreach_remove(s->iotlb, smmu_hash_remove_by_asid, &asid);
  53. }
  54. /* VMSAv8-64 Translation */
  55. /**
  56. * get_pte - Get the content of a page table entry located at
  57. * @base_addr[@index]
  58. */
  59. static int get_pte(dma_addr_t baseaddr, uint32_t index, uint64_t *pte,
  60. SMMUPTWEventInfo *info)
  61. {
  62. int ret;
  63. dma_addr_t addr = baseaddr + index * sizeof(*pte);
  64. /* TODO: guarantee 64-bit single-copy atomicity */
  65. ret = dma_memory_read(&address_space_memory, addr,
  66. (uint8_t *)pte, sizeof(*pte));
  67. if (ret != MEMTX_OK) {
  68. info->type = SMMU_PTW_ERR_WALK_EABT;
  69. info->addr = addr;
  70. return -EINVAL;
  71. }
  72. trace_smmu_get_pte(baseaddr, index, addr, *pte);
  73. return 0;
  74. }
  75. /* VMSAv8-64 Translation Table Format Descriptor Decoding */
  76. /**
  77. * get_page_pte_address - returns the L3 descriptor output address,
  78. * ie. the page frame
  79. * ARM ARM spec: Figure D4-17 VMSAv8-64 level 3 descriptor format
  80. */
  81. static inline hwaddr get_page_pte_address(uint64_t pte, int granule_sz)
  82. {
  83. return PTE_ADDRESS(pte, granule_sz);
  84. }
  85. /**
  86. * get_table_pte_address - return table descriptor output address,
  87. * ie. address of next level table
  88. * ARM ARM Figure D4-16 VMSAv8-64 level0, level1, and level 2 descriptor formats
  89. */
  90. static inline hwaddr get_table_pte_address(uint64_t pte, int granule_sz)
  91. {
  92. return PTE_ADDRESS(pte, granule_sz);
  93. }
  94. /**
  95. * get_block_pte_address - return block descriptor output address and block size
  96. * ARM ARM Figure D4-16 VMSAv8-64 level0, level1, and level 2 descriptor formats
  97. */
  98. static inline hwaddr get_block_pte_address(uint64_t pte, int level,
  99. int granule_sz, uint64_t *bsz)
  100. {
  101. int n = level_shift(level, granule_sz);
  102. *bsz = 1ULL << n;
  103. return PTE_ADDRESS(pte, n);
  104. }
  105. SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova)
  106. {
  107. bool tbi = extract64(iova, 55, 1) ? TBI1(cfg->tbi) : TBI0(cfg->tbi);
  108. uint8_t tbi_byte = tbi * 8;
  109. if (cfg->tt[0].tsz &&
  110. !extract64(iova, 64 - cfg->tt[0].tsz, cfg->tt[0].tsz - tbi_byte)) {
  111. /* there is a ttbr0 region and we are in it (high bits all zero) */
  112. return &cfg->tt[0];
  113. } else if (cfg->tt[1].tsz &&
  114. !extract64(iova, 64 - cfg->tt[1].tsz, cfg->tt[1].tsz - tbi_byte)) {
  115. /* there is a ttbr1 region and we are in it (high bits all one) */
  116. return &cfg->tt[1];
  117. } else if (!cfg->tt[0].tsz) {
  118. /* ttbr0 region is "everything not in the ttbr1 region" */
  119. return &cfg->tt[0];
  120. } else if (!cfg->tt[1].tsz) {
  121. /* ttbr1 region is "everything not in the ttbr0 region" */
  122. return &cfg->tt[1];
  123. }
  124. /* in the gap between the two regions, this is a Translation fault */
  125. return NULL;
  126. }
  127. /**
  128. * smmu_ptw_64 - VMSAv8-64 Walk of the page tables for a given IOVA
  129. * @cfg: translation config
  130. * @iova: iova to translate
  131. * @perm: access type
  132. * @tlbe: IOMMUTLBEntry (out)
  133. * @info: handle to an error info
  134. *
  135. * Return 0 on success, < 0 on error. In case of error, @info is filled
  136. * and tlbe->perm is set to IOMMU_NONE.
  137. * Upon success, @tlbe is filled with translated_addr and entry
  138. * permission rights.
  139. */
  140. static int smmu_ptw_64(SMMUTransCfg *cfg,
  141. dma_addr_t iova, IOMMUAccessFlags perm,
  142. IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info)
  143. {
  144. dma_addr_t baseaddr, indexmask;
  145. int stage = cfg->stage;
  146. SMMUTransTableInfo *tt = select_tt(cfg, iova);
  147. uint8_t level, granule_sz, inputsize, stride;
  148. if (!tt || tt->disabled) {
  149. info->type = SMMU_PTW_ERR_TRANSLATION;
  150. goto error;
  151. }
  152. granule_sz = tt->granule_sz;
  153. stride = granule_sz - 3;
  154. inputsize = 64 - tt->tsz;
  155. level = 4 - (inputsize - 4) / stride;
  156. indexmask = (1ULL << (inputsize - (stride * (4 - level)))) - 1;
  157. baseaddr = extract64(tt->ttb, 0, 48);
  158. baseaddr &= ~indexmask;
  159. tlbe->iova = iova;
  160. tlbe->addr_mask = (1 << granule_sz) - 1;
  161. while (level <= 3) {
  162. uint64_t subpage_size = 1ULL << level_shift(level, granule_sz);
  163. uint64_t mask = subpage_size - 1;
  164. uint32_t offset = iova_level_offset(iova, inputsize, level, granule_sz);
  165. uint64_t pte;
  166. dma_addr_t pte_addr = baseaddr + offset * sizeof(pte);
  167. uint8_t ap;
  168. if (get_pte(baseaddr, offset, &pte, info)) {
  169. goto error;
  170. }
  171. trace_smmu_ptw_level(level, iova, subpage_size,
  172. baseaddr, offset, pte);
  173. if (is_invalid_pte(pte) || is_reserved_pte(pte, level)) {
  174. trace_smmu_ptw_invalid_pte(stage, level, baseaddr,
  175. pte_addr, offset, pte);
  176. info->type = SMMU_PTW_ERR_TRANSLATION;
  177. goto error;
  178. }
  179. if (is_page_pte(pte, level)) {
  180. uint64_t gpa = get_page_pte_address(pte, granule_sz);
  181. ap = PTE_AP(pte);
  182. if (is_permission_fault(ap, perm)) {
  183. info->type = SMMU_PTW_ERR_PERMISSION;
  184. goto error;
  185. }
  186. tlbe->translated_addr = gpa + (iova & mask);
  187. tlbe->perm = PTE_AP_TO_PERM(ap);
  188. trace_smmu_ptw_page_pte(stage, level, iova,
  189. baseaddr, pte_addr, pte, gpa);
  190. return 0;
  191. }
  192. if (is_block_pte(pte, level)) {
  193. uint64_t block_size;
  194. hwaddr gpa = get_block_pte_address(pte, level, granule_sz,
  195. &block_size);
  196. ap = PTE_AP(pte);
  197. if (is_permission_fault(ap, perm)) {
  198. info->type = SMMU_PTW_ERR_PERMISSION;
  199. goto error;
  200. }
  201. trace_smmu_ptw_block_pte(stage, level, baseaddr,
  202. pte_addr, pte, iova, gpa,
  203. block_size >> 20);
  204. tlbe->translated_addr = gpa + (iova & mask);
  205. tlbe->perm = PTE_AP_TO_PERM(ap);
  206. return 0;
  207. }
  208. /* table pte */
  209. ap = PTE_APTABLE(pte);
  210. if (is_permission_fault(ap, perm)) {
  211. info->type = SMMU_PTW_ERR_PERMISSION;
  212. goto error;
  213. }
  214. baseaddr = get_table_pte_address(pte, granule_sz);
  215. level++;
  216. }
  217. info->type = SMMU_PTW_ERR_TRANSLATION;
  218. error:
  219. tlbe->perm = IOMMU_NONE;
  220. return -EINVAL;
  221. }
  222. /**
  223. * smmu_ptw - Walk the page tables for an IOVA, according to @cfg
  224. *
  225. * @cfg: translation configuration
  226. * @iova: iova to translate
  227. * @perm: tentative access type
  228. * @tlbe: returned entry
  229. * @info: ptw event handle
  230. *
  231. * return 0 on success
  232. */
  233. inline int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
  234. IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info)
  235. {
  236. if (!cfg->aa64) {
  237. /*
  238. * This code path is not entered as we check this while decoding
  239. * the configuration data in the derived SMMU model.
  240. */
  241. g_assert_not_reached();
  242. }
  243. return smmu_ptw_64(cfg, iova, perm, tlbe, info);
  244. }
  245. /**
  246. * The bus number is used for lookup when SID based invalidation occurs.
  247. * In that case we lazily populate the SMMUPciBus array from the bus hash
  248. * table. At the time the SMMUPciBus is created (smmu_find_add_as), the bus
  249. * numbers may not be always initialized yet.
  250. */
  251. SMMUPciBus *smmu_find_smmu_pcibus(SMMUState *s, uint8_t bus_num)
  252. {
  253. SMMUPciBus *smmu_pci_bus = s->smmu_pcibus_by_bus_num[bus_num];
  254. if (!smmu_pci_bus) {
  255. GHashTableIter iter;
  256. g_hash_table_iter_init(&iter, s->smmu_pcibus_by_busptr);
  257. while (g_hash_table_iter_next(&iter, NULL, (void **)&smmu_pci_bus)) {
  258. if (pci_bus_num(smmu_pci_bus->bus) == bus_num) {
  259. s->smmu_pcibus_by_bus_num[bus_num] = smmu_pci_bus;
  260. return smmu_pci_bus;
  261. }
  262. }
  263. }
  264. return smmu_pci_bus;
  265. }
  266. static AddressSpace *smmu_find_add_as(PCIBus *bus, void *opaque, int devfn)
  267. {
  268. SMMUState *s = opaque;
  269. SMMUPciBus *sbus = g_hash_table_lookup(s->smmu_pcibus_by_busptr, bus);
  270. SMMUDevice *sdev;
  271. static unsigned int index;
  272. if (!sbus) {
  273. sbus = g_malloc0(sizeof(SMMUPciBus) +
  274. sizeof(SMMUDevice *) * SMMU_PCI_DEVFN_MAX);
  275. sbus->bus = bus;
  276. g_hash_table_insert(s->smmu_pcibus_by_busptr, bus, sbus);
  277. }
  278. sdev = sbus->pbdev[devfn];
  279. if (!sdev) {
  280. char *name = g_strdup_printf("%s-%d-%d", s->mrtypename, devfn, index++);
  281. sdev = sbus->pbdev[devfn] = g_new0(SMMUDevice, 1);
  282. sdev->smmu = s;
  283. sdev->bus = bus;
  284. sdev->devfn = devfn;
  285. memory_region_init_iommu(&sdev->iommu, sizeof(sdev->iommu),
  286. s->mrtypename,
  287. OBJECT(s), name, 1ULL << SMMU_MAX_VA_BITS);
  288. address_space_init(&sdev->as,
  289. MEMORY_REGION(&sdev->iommu), name);
  290. trace_smmu_add_mr(name);
  291. g_free(name);
  292. }
  293. return &sdev->as;
  294. }
  295. IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid)
  296. {
  297. uint8_t bus_n, devfn;
  298. SMMUPciBus *smmu_bus;
  299. SMMUDevice *smmu;
  300. bus_n = PCI_BUS_NUM(sid);
  301. smmu_bus = smmu_find_smmu_pcibus(s, bus_n);
  302. if (smmu_bus) {
  303. devfn = SMMU_PCI_DEVFN(sid);
  304. smmu = smmu_bus->pbdev[devfn];
  305. if (smmu) {
  306. return &smmu->iommu;
  307. }
  308. }
  309. return NULL;
  310. }
  311. static guint smmu_iotlb_key_hash(gconstpointer v)
  312. {
  313. SMMUIOTLBKey *key = (SMMUIOTLBKey *)v;
  314. uint32_t a, b, c;
  315. /* Jenkins hash */
  316. a = b = c = JHASH_INITVAL + sizeof(*key);
  317. a += key->asid;
  318. b += extract64(key->iova, 0, 32);
  319. c += extract64(key->iova, 32, 32);
  320. __jhash_mix(a, b, c);
  321. __jhash_final(a, b, c);
  322. return c;
  323. }
  324. static gboolean smmu_iotlb_key_equal(gconstpointer v1, gconstpointer v2)
  325. {
  326. const SMMUIOTLBKey *k1 = v1;
  327. const SMMUIOTLBKey *k2 = v2;
  328. return (k1->asid == k2->asid) && (k1->iova == k2->iova);
  329. }
  330. /* Unmap the whole notifier's range */
  331. static void smmu_unmap_notifier_range(IOMMUNotifier *n)
  332. {
  333. IOMMUTLBEntry entry;
  334. entry.target_as = &address_space_memory;
  335. entry.iova = n->start;
  336. entry.perm = IOMMU_NONE;
  337. entry.addr_mask = n->end - n->start;
  338. memory_region_notify_one(n, &entry);
  339. }
  340. /* Unmap all notifiers attached to @mr */
  341. inline void smmu_inv_notifiers_mr(IOMMUMemoryRegion *mr)
  342. {
  343. IOMMUNotifier *n;
  344. trace_smmu_inv_notifiers_mr(mr->parent_obj.name);
  345. IOMMU_NOTIFIER_FOREACH(n, mr) {
  346. smmu_unmap_notifier_range(n);
  347. }
  348. }
  349. /* Unmap all notifiers of all mr's */
  350. void smmu_inv_notifiers_all(SMMUState *s)
  351. {
  352. SMMUDevice *sdev;
  353. QLIST_FOREACH(sdev, &s->devices_with_notifiers, next) {
  354. smmu_inv_notifiers_mr(&sdev->iommu);
  355. }
  356. }
  357. static void smmu_base_realize(DeviceState *dev, Error **errp)
  358. {
  359. SMMUState *s = ARM_SMMU(dev);
  360. SMMUBaseClass *sbc = ARM_SMMU_GET_CLASS(dev);
  361. Error *local_err = NULL;
  362. sbc->parent_realize(dev, &local_err);
  363. if (local_err) {
  364. error_propagate(errp, local_err);
  365. return;
  366. }
  367. s->configs = g_hash_table_new_full(NULL, NULL, NULL, g_free);
  368. s->iotlb = g_hash_table_new_full(smmu_iotlb_key_hash, smmu_iotlb_key_equal,
  369. g_free, g_free);
  370. s->smmu_pcibus_by_busptr = g_hash_table_new(NULL, NULL);
  371. if (s->primary_bus) {
  372. pci_setup_iommu(s->primary_bus, smmu_find_add_as, s);
  373. } else {
  374. error_setg(errp, "SMMU is not attached to any PCI bus!");
  375. }
  376. }
  377. static void smmu_base_reset(DeviceState *dev)
  378. {
  379. SMMUState *s = ARM_SMMU(dev);
  380. g_hash_table_remove_all(s->configs);
  381. g_hash_table_remove_all(s->iotlb);
  382. }
  383. static Property smmu_dev_properties[] = {
  384. DEFINE_PROP_UINT8("bus_num", SMMUState, bus_num, 0),
  385. DEFINE_PROP_LINK("primary-bus", SMMUState, primary_bus, "PCI", PCIBus *),
  386. DEFINE_PROP_END_OF_LIST(),
  387. };
  388. static void smmu_base_class_init(ObjectClass *klass, void *data)
  389. {
  390. DeviceClass *dc = DEVICE_CLASS(klass);
  391. SMMUBaseClass *sbc = ARM_SMMU_CLASS(klass);
  392. dc->props = smmu_dev_properties;
  393. device_class_set_parent_realize(dc, smmu_base_realize,
  394. &sbc->parent_realize);
  395. dc->reset = smmu_base_reset;
  396. }
  397. static const TypeInfo smmu_base_info = {
  398. .name = TYPE_ARM_SMMU,
  399. .parent = TYPE_SYS_BUS_DEVICE,
  400. .instance_size = sizeof(SMMUState),
  401. .class_data = NULL,
  402. .class_size = sizeof(SMMUBaseClass),
  403. .class_init = smmu_base_class_init,
  404. .abstract = true,
  405. };
  406. static void smmu_base_register_types(void)
  407. {
  408. type_register_static(&smmu_base_info);
  409. }
  410. type_init(smmu_base_register_types)