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