diff --git a/qemu/util/mmap-alloc.c b/qemu/util/mmap-alloc.c index 00b2d8cd..46b89c3c 100644 --- a/qemu/util/mmap-alloc.c +++ b/qemu/util/mmap-alloc.c @@ -12,17 +12,32 @@ #include "qemu/osdep.h" #include "qemu/mmap-alloc.h" +#include "qemu/host-utils.h" #include void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared) { - /* - * Note: this always allocates at least one extra page of virtual address - * space, even if size is already aligned. - */ - size_t total = size + align; - void *ptr = mmap(0, total, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - size_t offset = QEMU_ALIGN_UP((uintptr_t)ptr, align) - (uintptr_t)ptr; + /* + * Note: this always allocates at least one extra page of virtual address + * space, even if size is already aligned. + */ + size_t total = size + align; + #if defined(__powerpc64__) && defined(__linux__) + /* On ppc64 mappings in the same segment (aka slice) must share the same + * page size. Since we will be re-allocating part of this segment + * from the supplied fd, we should make sure to use the same page size, to + * this end we mmap the supplied fd. In this case, set MAP_NORESERVE to + * avoid allocating backing store memory. + * We do this unless we are using the system page size, in which case + * anonymous memory is OK. + */ + int anonfd = fd == -1 || qemu_fd_getpagesize(fd) == getpagesize() ? -1 : fd; + int flags = anonfd == -1 ? MAP_ANONYMOUS : MAP_NORESERVE; + void *ptr = mmap(0, total, PROT_NONE, flags | MAP_PRIVATE, anonfd, 0); + #else + void *ptr = mmap(0, total, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + #endif + size_t offset; void *ptr1; if (ptr == MAP_FAILED) { @@ -30,10 +45,11 @@ void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared) } /* Make sure align is a power of 2 */ - assert(!(align & (align - 1))); + assert(is_power_of_2(align)); /* Always align to host page size */ assert(align >= getpagesize()); + offset = QEMU_ALIGN_UP((uintptr_t)ptr, align) - (uintptr_t)ptr; ptr1 = mmap(ptr + offset, size, PROT_READ | PROT_WRITE, MAP_FIXED | (fd == -1 ? MAP_ANONYMOUS : 0) |