xen-mapcache.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. /*
  2. * Copyright (C) 2011 Citrix Ltd.
  3. *
  4. * This work is licensed under the terms of the GNU GPL, version 2. See
  5. * the COPYING file in the top-level directory.
  6. *
  7. * Contributions after 2012-01-13 are licensed under the terms of the
  8. * GNU GPL, version 2 or (at your option) any later version.
  9. */
  10. #include "qemu/osdep.h"
  11. #include "qemu/units.h"
  12. #include "qemu/error-report.h"
  13. #include <sys/resource.h>
  14. #include "hw/xen/xen-hvm-common.h"
  15. #include "hw/xen/xen_native.h"
  16. #include "qemu/bitmap.h"
  17. #include "system/runstate.h"
  18. #include "system/xen-mapcache.h"
  19. #include "trace.h"
  20. #include <xenevtchn.h>
  21. #include <xengnttab.h>
  22. #if HOST_LONG_BITS == 32
  23. # define MCACHE_MAX_SIZE (1UL<<31) /* 2GB Cap */
  24. #else
  25. # define MCACHE_MAX_SIZE (1UL<<35) /* 32GB Cap */
  26. #endif
  27. /* This is the size of the virtual address space reserve to QEMU that will not
  28. * be use by MapCache.
  29. * From empirical tests I observed that qemu use 75MB more than the
  30. * max_mcache_size.
  31. */
  32. #define NON_MCACHE_MEMORY_SIZE (80 * MiB)
  33. typedef struct MapCacheEntry {
  34. hwaddr paddr_index;
  35. uint8_t *vaddr_base;
  36. unsigned long *valid_mapping;
  37. uint32_t lock;
  38. #define XEN_MAPCACHE_ENTRY_DUMMY (1 << 0)
  39. #define XEN_MAPCACHE_ENTRY_GRANT (1 << 1)
  40. uint8_t flags;
  41. hwaddr size;
  42. struct MapCacheEntry *next;
  43. } MapCacheEntry;
  44. typedef struct MapCacheRev {
  45. uint8_t *vaddr_req;
  46. hwaddr paddr_index;
  47. hwaddr size;
  48. QTAILQ_ENTRY(MapCacheRev) next;
  49. bool dma;
  50. } MapCacheRev;
  51. typedef struct MapCache {
  52. MapCacheEntry *entry;
  53. unsigned long nr_buckets;
  54. QTAILQ_HEAD(, MapCacheRev) locked_entries;
  55. /* For most cases (>99.9%), the page address is the same. */
  56. MapCacheEntry *last_entry;
  57. unsigned long max_mcache_size;
  58. unsigned int bucket_shift;
  59. unsigned long bucket_size;
  60. phys_offset_to_gaddr_t phys_offset_to_gaddr;
  61. QemuMutex lock;
  62. void *opaque;
  63. } MapCache;
  64. static MapCache *mapcache;
  65. static MapCache *mapcache_grants_ro;
  66. static MapCache *mapcache_grants_rw;
  67. static xengnttab_handle *xen_region_gnttabdev;
  68. static inline void mapcache_lock(MapCache *mc)
  69. {
  70. qemu_mutex_lock(&mc->lock);
  71. }
  72. static inline void mapcache_unlock(MapCache *mc)
  73. {
  74. qemu_mutex_unlock(&mc->lock);
  75. }
  76. static inline int test_bits(int nr, int size, const unsigned long *addr)
  77. {
  78. unsigned long res = find_next_zero_bit(addr, size + nr, nr);
  79. if (res >= nr + size)
  80. return 1;
  81. else
  82. return 0;
  83. }
  84. static MapCache *xen_map_cache_init_single(phys_offset_to_gaddr_t f,
  85. void *opaque,
  86. unsigned int bucket_shift,
  87. unsigned long max_size)
  88. {
  89. unsigned long size;
  90. MapCache *mc;
  91. assert(bucket_shift >= XC_PAGE_SHIFT);
  92. mc = g_new0(MapCache, 1);
  93. mc->phys_offset_to_gaddr = f;
  94. mc->opaque = opaque;
  95. qemu_mutex_init(&mc->lock);
  96. QTAILQ_INIT(&mc->locked_entries);
  97. mc->bucket_shift = bucket_shift;
  98. mc->bucket_size = 1UL << bucket_shift;
  99. mc->max_mcache_size = max_size;
  100. mc->nr_buckets =
  101. (((mc->max_mcache_size >> XC_PAGE_SHIFT) +
  102. (1UL << (bucket_shift - XC_PAGE_SHIFT)) - 1) >>
  103. (bucket_shift - XC_PAGE_SHIFT));
  104. size = mc->nr_buckets * sizeof(MapCacheEntry);
  105. size = (size + XC_PAGE_SIZE - 1) & ~(XC_PAGE_SIZE - 1);
  106. trace_xen_map_cache_init(mc->nr_buckets, size);
  107. mc->entry = g_malloc0(size);
  108. return mc;
  109. }
  110. void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
  111. {
  112. struct rlimit rlimit_as;
  113. unsigned long max_mcache_size;
  114. unsigned int bucket_shift;
  115. xen_region_gnttabdev = xengnttab_open(NULL, 0);
  116. if (xen_region_gnttabdev == NULL) {
  117. error_report("mapcache: Failed to open gnttab device");
  118. exit(EXIT_FAILURE);
  119. }
  120. if (HOST_LONG_BITS == 32) {
  121. bucket_shift = 16;
  122. } else {
  123. bucket_shift = 20;
  124. }
  125. if (geteuid() == 0) {
  126. rlimit_as.rlim_cur = RLIM_INFINITY;
  127. rlimit_as.rlim_max = RLIM_INFINITY;
  128. max_mcache_size = MCACHE_MAX_SIZE;
  129. } else {
  130. getrlimit(RLIMIT_AS, &rlimit_as);
  131. rlimit_as.rlim_cur = rlimit_as.rlim_max;
  132. if (rlimit_as.rlim_max != RLIM_INFINITY) {
  133. warn_report("QEMU's maximum size of virtual"
  134. " memory is not infinity");
  135. }
  136. if (rlimit_as.rlim_max < MCACHE_MAX_SIZE + NON_MCACHE_MEMORY_SIZE) {
  137. max_mcache_size = rlimit_as.rlim_max - NON_MCACHE_MEMORY_SIZE;
  138. } else {
  139. max_mcache_size = MCACHE_MAX_SIZE;
  140. }
  141. }
  142. mapcache = xen_map_cache_init_single(f, opaque,
  143. bucket_shift,
  144. max_mcache_size);
  145. /*
  146. * Grant mappings must use XC_PAGE_SIZE granularity since we can't
  147. * map anything beyond the number of pages granted to us.
  148. */
  149. mapcache_grants_ro = xen_map_cache_init_single(f, opaque,
  150. XC_PAGE_SHIFT,
  151. max_mcache_size);
  152. mapcache_grants_rw = xen_map_cache_init_single(f, opaque,
  153. XC_PAGE_SHIFT,
  154. max_mcache_size);
  155. setrlimit(RLIMIT_AS, &rlimit_as);
  156. }
  157. static void xen_remap_bucket(MapCache *mc,
  158. MapCacheEntry *entry,
  159. void *vaddr,
  160. hwaddr size,
  161. hwaddr address_index,
  162. bool dummy,
  163. bool grant,
  164. bool is_write,
  165. ram_addr_t ram_offset)
  166. {
  167. uint8_t *vaddr_base;
  168. g_autofree uint32_t *refs = NULL;
  169. g_autofree xen_pfn_t *pfns = NULL;
  170. g_autofree int *err;
  171. unsigned int i;
  172. hwaddr nb_pfn = size >> XC_PAGE_SHIFT;
  173. trace_xen_remap_bucket(address_index);
  174. if (grant) {
  175. refs = g_new0(uint32_t, nb_pfn);
  176. } else {
  177. pfns = g_new0(xen_pfn_t, nb_pfn);
  178. }
  179. err = g_new0(int, nb_pfn);
  180. if (entry->vaddr_base != NULL) {
  181. if (!(entry->flags & XEN_MAPCACHE_ENTRY_DUMMY)) {
  182. ram_block_notify_remove(entry->vaddr_base, entry->size,
  183. entry->size);
  184. }
  185. /*
  186. * If an entry is being replaced by another mapping and we're using
  187. * MAP_FIXED flag for it - there is possibility of a race for vaddr
  188. * address with another thread doing an mmap call itself
  189. * (see man 2 mmap). To avoid that we skip explicit unmapping here
  190. * and allow the kernel to destroy the previous mappings by replacing
  191. * them in mmap call later.
  192. *
  193. * Non-identical replacements are not allowed therefore.
  194. */
  195. assert(!vaddr || (entry->vaddr_base == vaddr && entry->size == size));
  196. if (!vaddr && munmap(entry->vaddr_base, entry->size) != 0) {
  197. perror("unmap fails");
  198. exit(-1);
  199. }
  200. }
  201. g_free(entry->valid_mapping);
  202. entry->valid_mapping = NULL;
  203. if (grant) {
  204. hwaddr grant_base = address_index - (ram_offset >> XC_PAGE_SHIFT);
  205. for (i = 0; i < nb_pfn; i++) {
  206. refs[i] = grant_base + i;
  207. }
  208. } else {
  209. for (i = 0; i < nb_pfn; i++) {
  210. pfns[i] = (address_index << (mc->bucket_shift - XC_PAGE_SHIFT)) + i;
  211. }
  212. }
  213. entry->flags &= ~XEN_MAPCACHE_ENTRY_GRANT;
  214. if (!dummy) {
  215. if (grant) {
  216. int prot = PROT_READ;
  217. if (is_write) {
  218. prot |= PROT_WRITE;
  219. }
  220. entry->flags |= XEN_MAPCACHE_ENTRY_GRANT;
  221. assert(vaddr == NULL);
  222. vaddr_base = xengnttab_map_domain_grant_refs(xen_region_gnttabdev,
  223. nb_pfn,
  224. xen_domid, refs,
  225. prot);
  226. } else {
  227. /*
  228. * If the caller has requested the mapping at a specific address use
  229. * MAP_FIXED to make sure it's honored.
  230. *
  231. * We don't yet support upgrading mappings from RO to RW, to handle
  232. * models using ordinary address_space_rw(), foreign mappings ignore
  233. * is_write and are always mapped RW.
  234. */
  235. vaddr_base = xenforeignmemory_map2(xen_fmem, xen_domid, vaddr,
  236. PROT_READ | PROT_WRITE,
  237. vaddr ? MAP_FIXED : 0,
  238. nb_pfn, pfns, err);
  239. }
  240. if (vaddr_base == NULL) {
  241. perror(grant ? "xengnttab_map_domain_grant_refs"
  242. : "xenforeignmemory_map2");
  243. exit(-1);
  244. }
  245. } else {
  246. /*
  247. * We create dummy mappings where we are unable to create a foreign
  248. * mapping immediately due to certain circumstances (i.e. on resume now)
  249. */
  250. vaddr_base = mmap(vaddr, size, PROT_READ | PROT_WRITE,
  251. MAP_ANON | MAP_SHARED | (vaddr ? MAP_FIXED : 0),
  252. -1, 0);
  253. if (vaddr_base == MAP_FAILED) {
  254. perror("mmap");
  255. exit(-1);
  256. }
  257. }
  258. if (!(entry->flags & XEN_MAPCACHE_ENTRY_DUMMY)) {
  259. ram_block_notify_add(vaddr_base, size, size);
  260. }
  261. entry->vaddr_base = vaddr_base;
  262. entry->paddr_index = address_index;
  263. entry->size = size;
  264. entry->valid_mapping = g_new0(unsigned long,
  265. BITS_TO_LONGS(size >> XC_PAGE_SHIFT));
  266. if (dummy) {
  267. entry->flags |= XEN_MAPCACHE_ENTRY_DUMMY;
  268. } else {
  269. entry->flags &= ~(XEN_MAPCACHE_ENTRY_DUMMY);
  270. }
  271. bitmap_zero(entry->valid_mapping, nb_pfn);
  272. for (i = 0; i < nb_pfn; i++) {
  273. if (!err[i]) {
  274. bitmap_set(entry->valid_mapping, i, 1);
  275. }
  276. }
  277. }
  278. static uint8_t *xen_map_cache_unlocked(MapCache *mc,
  279. hwaddr phys_addr, hwaddr size,
  280. ram_addr_t ram_offset,
  281. uint8_t lock, bool dma,
  282. bool grant, bool is_write)
  283. {
  284. MapCacheEntry *entry, *pentry = NULL,
  285. *free_entry = NULL, *free_pentry = NULL;
  286. hwaddr address_index;
  287. hwaddr address_offset;
  288. hwaddr cache_size = size;
  289. hwaddr test_bit_size;
  290. bool translated G_GNUC_UNUSED = false;
  291. bool dummy = false;
  292. tryagain:
  293. address_index = phys_addr >> mc->bucket_shift;
  294. address_offset = phys_addr & (mc->bucket_size - 1);
  295. trace_xen_map_cache(phys_addr);
  296. /* test_bit_size is always a multiple of XC_PAGE_SIZE */
  297. if (size) {
  298. test_bit_size = size + (phys_addr & (XC_PAGE_SIZE - 1));
  299. if (test_bit_size % XC_PAGE_SIZE) {
  300. test_bit_size += XC_PAGE_SIZE - (test_bit_size % XC_PAGE_SIZE);
  301. }
  302. } else {
  303. test_bit_size = XC_PAGE_SIZE;
  304. }
  305. if (mc->last_entry != NULL &&
  306. mc->last_entry->paddr_index == address_index &&
  307. !lock && !size &&
  308. test_bits(address_offset >> XC_PAGE_SHIFT,
  309. test_bit_size >> XC_PAGE_SHIFT,
  310. mc->last_entry->valid_mapping)) {
  311. trace_xen_map_cache_return(
  312. mc->last_entry->vaddr_base + address_offset
  313. );
  314. return mc->last_entry->vaddr_base + address_offset;
  315. }
  316. /* size is always a multiple of mc->bucket_size */
  317. if (size) {
  318. cache_size = size + address_offset;
  319. if (cache_size % mc->bucket_size) {
  320. cache_size += mc->bucket_size - (cache_size % mc->bucket_size);
  321. }
  322. } else {
  323. cache_size = mc->bucket_size;
  324. }
  325. entry = &mc->entry[address_index % mc->nr_buckets];
  326. while (entry && (!entry->vaddr_base ||
  327. entry->paddr_index != address_index || entry->size != cache_size ||
  328. !test_bits(address_offset >> XC_PAGE_SHIFT,
  329. test_bit_size >> XC_PAGE_SHIFT,
  330. entry->valid_mapping))) {
  331. if (!free_entry && (!entry->lock || !entry->vaddr_base)) {
  332. free_entry = entry;
  333. free_pentry = pentry;
  334. }
  335. pentry = entry;
  336. entry = entry->next;
  337. }
  338. if (!entry && free_entry) {
  339. entry = free_entry;
  340. pentry = free_pentry;
  341. }
  342. if (!entry) {
  343. entry = g_new0(MapCacheEntry, 1);
  344. pentry->next = entry;
  345. xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
  346. grant, is_write, ram_offset);
  347. } else if (!entry->lock) {
  348. if (!entry->vaddr_base || entry->paddr_index != address_index ||
  349. entry->size != cache_size ||
  350. !test_bits(address_offset >> XC_PAGE_SHIFT,
  351. test_bit_size >> XC_PAGE_SHIFT,
  352. entry->valid_mapping)) {
  353. xen_remap_bucket(mc, entry, NULL, cache_size, address_index, dummy,
  354. grant, is_write, ram_offset);
  355. }
  356. }
  357. if(!test_bits(address_offset >> XC_PAGE_SHIFT,
  358. test_bit_size >> XC_PAGE_SHIFT,
  359. entry->valid_mapping)) {
  360. mc->last_entry = NULL;
  361. #ifdef XEN_COMPAT_PHYSMAP
  362. if (!translated && mc->phys_offset_to_gaddr) {
  363. phys_addr = mc->phys_offset_to_gaddr(phys_addr, size);
  364. translated = true;
  365. goto tryagain;
  366. }
  367. #endif
  368. if (!dummy && runstate_check(RUN_STATE_INMIGRATE)) {
  369. dummy = true;
  370. goto tryagain;
  371. }
  372. trace_xen_map_cache_return(NULL);
  373. return NULL;
  374. }
  375. mc->last_entry = entry;
  376. if (lock) {
  377. MapCacheRev *reventry = g_new0(MapCacheRev, 1);
  378. entry->lock++;
  379. if (entry->lock == 0) {
  380. error_report("mapcache entry lock overflow: "HWADDR_FMT_plx" -> %p",
  381. entry->paddr_index, entry->vaddr_base);
  382. abort();
  383. }
  384. reventry->dma = dma;
  385. reventry->vaddr_req = mc->last_entry->vaddr_base + address_offset;
  386. reventry->paddr_index = mc->last_entry->paddr_index;
  387. reventry->size = entry->size;
  388. QTAILQ_INSERT_HEAD(&mc->locked_entries, reventry, next);
  389. }
  390. trace_xen_map_cache_return(
  391. mc->last_entry->vaddr_base + address_offset
  392. );
  393. return mc->last_entry->vaddr_base + address_offset;
  394. }
  395. uint8_t *xen_map_cache(MemoryRegion *mr,
  396. hwaddr phys_addr, hwaddr size,
  397. ram_addr_t ram_addr_offset,
  398. uint8_t lock, bool dma,
  399. bool is_write)
  400. {
  401. bool grant = xen_mr_is_grants(mr);
  402. MapCache *mc = mapcache;
  403. uint8_t *p;
  404. if (grant) {
  405. mc = is_write ? mapcache_grants_rw : mapcache_grants_ro;
  406. }
  407. if (grant && !lock) {
  408. /*
  409. * Grants are only supported via address_space_map(). Anything
  410. * else is considered a user/guest error.
  411. *
  412. * QEMU generally doesn't expect these mappings to ever fail, so
  413. * if this happens we report an error message and abort().
  414. */
  415. error_report("Tried to access a grant reference without mapping it.");
  416. abort();
  417. }
  418. mapcache_lock(mc);
  419. p = xen_map_cache_unlocked(mc, phys_addr, size, ram_addr_offset,
  420. lock, dma, grant, is_write);
  421. mapcache_unlock(mc);
  422. return p;
  423. }
  424. static ram_addr_t xen_ram_addr_from_mapcache_single(MapCache *mc, void *ptr)
  425. {
  426. MapCacheEntry *entry = NULL;
  427. MapCacheRev *reventry;
  428. hwaddr paddr_index;
  429. hwaddr size;
  430. ram_addr_t raddr;
  431. int found = 0;
  432. mapcache_lock(mc);
  433. QTAILQ_FOREACH(reventry, &mc->locked_entries, next) {
  434. if (reventry->vaddr_req == ptr) {
  435. paddr_index = reventry->paddr_index;
  436. size = reventry->size;
  437. found = 1;
  438. break;
  439. }
  440. }
  441. if (!found) {
  442. trace_xen_ram_addr_from_mapcache_not_found(ptr);
  443. mapcache_unlock(mc);
  444. return RAM_ADDR_INVALID;
  445. }
  446. entry = &mc->entry[paddr_index % mc->nr_buckets];
  447. while (entry && (entry->paddr_index != paddr_index || entry->size != size)) {
  448. entry = entry->next;
  449. }
  450. if (!entry) {
  451. trace_xen_ram_addr_from_mapcache_not_in_cache(ptr);
  452. raddr = RAM_ADDR_INVALID;
  453. } else {
  454. raddr = (reventry->paddr_index << mc->bucket_shift) +
  455. ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
  456. }
  457. mapcache_unlock(mc);
  458. return raddr;
  459. }
  460. ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
  461. {
  462. ram_addr_t addr;
  463. addr = xen_ram_addr_from_mapcache_single(mapcache, ptr);
  464. if (addr == RAM_ADDR_INVALID) {
  465. addr = xen_ram_addr_from_mapcache_single(mapcache_grants_ro, ptr);
  466. }
  467. if (addr == RAM_ADDR_INVALID) {
  468. addr = xen_ram_addr_from_mapcache_single(mapcache_grants_rw, ptr);
  469. }
  470. return addr;
  471. }
  472. static void xen_invalidate_map_cache_entry_unlocked(MapCache *mc,
  473. uint8_t *buffer)
  474. {
  475. MapCacheEntry *entry = NULL, *pentry = NULL;
  476. MapCacheRev *reventry;
  477. hwaddr paddr_index;
  478. hwaddr size;
  479. int found = 0;
  480. int rc;
  481. QTAILQ_FOREACH(reventry, &mc->locked_entries, next) {
  482. if (reventry->vaddr_req == buffer) {
  483. paddr_index = reventry->paddr_index;
  484. size = reventry->size;
  485. found = 1;
  486. break;
  487. }
  488. }
  489. if (!found) {
  490. trace_xen_invalidate_map_cache_entry_unlocked_not_found(buffer);
  491. QTAILQ_FOREACH(reventry, &mc->locked_entries, next) {
  492. trace_xen_invalidate_map_cache_entry_unlocked_found(
  493. reventry->paddr_index,
  494. reventry->vaddr_req
  495. );
  496. }
  497. return;
  498. }
  499. QTAILQ_REMOVE(&mc->locked_entries, reventry, next);
  500. g_free(reventry);
  501. if (mc->last_entry != NULL &&
  502. mc->last_entry->paddr_index == paddr_index) {
  503. mc->last_entry = NULL;
  504. }
  505. entry = &mc->entry[paddr_index % mc->nr_buckets];
  506. while (entry && (entry->paddr_index != paddr_index || entry->size != size)) {
  507. pentry = entry;
  508. entry = entry->next;
  509. }
  510. if (!entry) {
  511. trace_xen_invalidate_map_cache_entry_unlocked_miss(buffer);
  512. return;
  513. }
  514. entry->lock--;
  515. if (entry->lock > 0) {
  516. return;
  517. }
  518. ram_block_notify_remove(entry->vaddr_base, entry->size, entry->size);
  519. if (entry->flags & XEN_MAPCACHE_ENTRY_GRANT) {
  520. rc = xengnttab_unmap(xen_region_gnttabdev, entry->vaddr_base,
  521. entry->size >> mc->bucket_shift);
  522. } else {
  523. rc = munmap(entry->vaddr_base, entry->size);
  524. }
  525. if (rc) {
  526. perror("unmap fails");
  527. exit(-1);
  528. }
  529. g_free(entry->valid_mapping);
  530. if (pentry) {
  531. pentry->next = entry->next;
  532. g_free(entry);
  533. } else {
  534. /*
  535. * Invalidate mapping but keep entry->next pointing to the rest
  536. * of the list.
  537. *
  538. * Note that lock is already zero here, otherwise we don't unmap.
  539. */
  540. entry->paddr_index = 0;
  541. entry->vaddr_base = NULL;
  542. entry->valid_mapping = NULL;
  543. entry->flags = 0;
  544. entry->size = 0;
  545. }
  546. }
  547. typedef struct XenMapCacheData {
  548. Coroutine *co;
  549. uint8_t *buffer;
  550. } XenMapCacheData;
  551. static void xen_invalidate_map_cache_entry_single(MapCache *mc, uint8_t *buffer)
  552. {
  553. mapcache_lock(mc);
  554. xen_invalidate_map_cache_entry_unlocked(mc, buffer);
  555. mapcache_unlock(mc);
  556. }
  557. static void xen_invalidate_map_cache_entry_all(uint8_t *buffer)
  558. {
  559. xen_invalidate_map_cache_entry_single(mapcache, buffer);
  560. xen_invalidate_map_cache_entry_single(mapcache_grants_ro, buffer);
  561. xen_invalidate_map_cache_entry_single(mapcache_grants_rw, buffer);
  562. }
  563. static void xen_invalidate_map_cache_entry_bh(void *opaque)
  564. {
  565. XenMapCacheData *data = opaque;
  566. xen_invalidate_map_cache_entry_all(data->buffer);
  567. aio_co_wake(data->co);
  568. }
  569. void coroutine_mixed_fn xen_invalidate_map_cache_entry(uint8_t *buffer)
  570. {
  571. if (qemu_in_coroutine()) {
  572. XenMapCacheData data = {
  573. .co = qemu_coroutine_self(),
  574. .buffer = buffer,
  575. };
  576. aio_bh_schedule_oneshot(qemu_get_current_aio_context(),
  577. xen_invalidate_map_cache_entry_bh, &data);
  578. qemu_coroutine_yield();
  579. } else {
  580. xen_invalidate_map_cache_entry_all(buffer);
  581. }
  582. }
  583. static void xen_invalidate_map_cache_single(MapCache *mc)
  584. {
  585. unsigned long i;
  586. MapCacheRev *reventry;
  587. mapcache_lock(mc);
  588. QTAILQ_FOREACH(reventry, &mc->locked_entries, next) {
  589. if (!reventry->dma) {
  590. continue;
  591. }
  592. trace_xen_invalidate_map_cache(reventry->paddr_index,
  593. reventry->vaddr_req);
  594. }
  595. for (i = 0; i < mc->nr_buckets; i++) {
  596. MapCacheEntry *entry = &mc->entry[i];
  597. if (entry->vaddr_base == NULL) {
  598. continue;
  599. }
  600. if (entry->lock > 0) {
  601. continue;
  602. }
  603. if (munmap(entry->vaddr_base, entry->size) != 0) {
  604. perror("unmap fails");
  605. exit(-1);
  606. }
  607. entry->paddr_index = 0;
  608. entry->vaddr_base = NULL;
  609. entry->size = 0;
  610. g_free(entry->valid_mapping);
  611. entry->valid_mapping = NULL;
  612. }
  613. mc->last_entry = NULL;
  614. mapcache_unlock(mc);
  615. }
  616. void xen_invalidate_map_cache(void)
  617. {
  618. /* Flush pending AIO before destroying the mapcache */
  619. bdrv_drain_all();
  620. xen_invalidate_map_cache_single(mapcache);
  621. }
  622. static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,
  623. hwaddr old_phys_addr,
  624. hwaddr new_phys_addr,
  625. hwaddr size)
  626. {
  627. MapCacheEntry *entry;
  628. hwaddr address_index, address_offset;
  629. hwaddr test_bit_size, cache_size = size;
  630. address_index = old_phys_addr >> mc->bucket_shift;
  631. address_offset = old_phys_addr & (mc->bucket_size - 1);
  632. assert(size);
  633. /* test_bit_size is always a multiple of XC_PAGE_SIZE */
  634. test_bit_size = size + (old_phys_addr & (XC_PAGE_SIZE - 1));
  635. if (test_bit_size % XC_PAGE_SIZE) {
  636. test_bit_size += XC_PAGE_SIZE - (test_bit_size % XC_PAGE_SIZE);
  637. }
  638. cache_size = size + address_offset;
  639. if (cache_size % mc->bucket_size) {
  640. cache_size += mc->bucket_size - (cache_size % mc->bucket_size);
  641. }
  642. entry = &mc->entry[address_index % mc->nr_buckets];
  643. while (entry && !(entry->paddr_index == address_index &&
  644. entry->size == cache_size)) {
  645. entry = entry->next;
  646. }
  647. if (!entry) {
  648. trace_xen_replace_cache_entry_unlocked(old_phys_addr);
  649. return NULL;
  650. }
  651. assert((entry->flags & XEN_MAPCACHE_ENTRY_GRANT) == 0);
  652. address_index = new_phys_addr >> mc->bucket_shift;
  653. address_offset = new_phys_addr & (mc->bucket_size - 1);
  654. trace_xen_replace_cache_entry_dummy(old_phys_addr, new_phys_addr);
  655. xen_remap_bucket(mc, entry, entry->vaddr_base,
  656. cache_size, address_index, false,
  657. false, false, old_phys_addr);
  658. if (!test_bits(address_offset >> XC_PAGE_SHIFT,
  659. test_bit_size >> XC_PAGE_SHIFT,
  660. entry->valid_mapping)) {
  661. trace_xen_replace_cache_entry_unlocked_could_not_update_entry(
  662. old_phys_addr
  663. );
  664. return NULL;
  665. }
  666. return entry->vaddr_base + address_offset;
  667. }
  668. uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr,
  669. hwaddr new_phys_addr,
  670. hwaddr size)
  671. {
  672. uint8_t *p;
  673. mapcache_lock(mapcache);
  674. p = xen_replace_cache_entry_unlocked(mapcache, old_phys_addr,
  675. new_phys_addr, size);
  676. mapcache_unlock(mapcache);
  677. return p;
  678. }