Skip to content

Commit eb99baa

Browse files
davidhildenbrandmstsirkin
authored andcommitted
libvhost-user: Map shared RAM with MAP_NORESERVE to support virtio-mem with hugetlb
For fd-based shared memory, MAP_NORESERVE is only effective for hugetlb, otherwise it's ignored. Older Linux versions that didn't support reservation of huge pages ignored MAP_NORESERVE completely. The first client to mmap a hugetlb fd without MAP_NORESERVE will trigger reservation of huge pages for the whole mmapped range. There are two cases to consider: 1) QEMU mapped RAM without MAP_NORESERVE We're not dealing with a sparse mapping, huge pages for the whole range have already been reserved by QEMU. An additional mmap() without MAP_NORESERVE won't have any effect on the reservation. 2) QEMU mapped RAM with MAP_NORESERVE We're delaing with a sparse mapping, no huge pages should be reserved. Further mappings without MAP_NORESERVE should be avoided. For 1), it doesn't matter if we set MAP_NORESERVE or not, so we can simply set it. For 2), we'd be overriding QEMUs decision and trigger reservation of huge pages, which might just fail if there are not sufficient huge pages around. We must map with MAP_NORESERVE. This change is required to support virtio-mem with hugetlb: a virtio-mem device mapped into the guest physical memory corresponds to a sparse memory mapping and QEMU maps this memory with MAP_NORESERVE. Whenever memory in that sparse region will be accessed by the VM, QEMU populates huge pages for the affected range by preallocating memory and handling any preallocation errors gracefully. So let's map shared RAM with MAP_NORESERVE. As libvhost-user only supports Linux, there shouldn't be anything to take care of in regard of other OS support. Without this change, libvhost-user will fail mapping the region if there are currently not enough huge pages to perform the reservation: fv_panic: libvhost-user: region mmap error: Cannot allocate memory Cc: "Marc-André Lureau" <[email protected]> Cc: "Michael S. Tsirkin" <[email protected]> Cc: Paolo Bonzini <[email protected]> Cc: Raphael Norwitz <[email protected]> Cc: Stefan Hajnoczi <[email protected]> Cc: Dr. David Alan Gilbert <[email protected]> Signed-off-by: David Hildenbrand <[email protected]> Message-Id: <[email protected]> Acked-by: Raphael Norwitz <[email protected]>
1 parent 4fafedc commit eb99baa

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

subprojects/libvhost-user/libvhost-user.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -751,12 +751,12 @@ vu_add_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
751751
* accessing it before we userfault.
752752
*/
753753
mmap_addr = mmap(0, dev_region->size + dev_region->mmap_offset,
754-
PROT_NONE, MAP_SHARED,
754+
PROT_NONE, MAP_SHARED | MAP_NORESERVE,
755755
vmsg->fds[0], 0);
756756
} else {
757757
mmap_addr = mmap(0, dev_region->size + dev_region->mmap_offset,
758-
PROT_READ | PROT_WRITE, MAP_SHARED, vmsg->fds[0],
759-
0);
758+
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE,
759+
vmsg->fds[0], 0);
760760
}
761761

762762
if (mmap_addr == MAP_FAILED) {
@@ -920,7 +920,7 @@ vu_set_mem_table_exec_postcopy(VuDev *dev, VhostUserMsg *vmsg)
920920
* accessing it before we userfault
921921
*/
922922
mmap_addr = mmap(0, dev_region->size + dev_region->mmap_offset,
923-
PROT_NONE, MAP_SHARED,
923+
PROT_NONE, MAP_SHARED | MAP_NORESERVE,
924924
vmsg->fds[i], 0);
925925

926926
if (mmap_addr == MAP_FAILED) {
@@ -1007,7 +1007,7 @@ vu_set_mem_table_exec(VuDev *dev, VhostUserMsg *vmsg)
10071007
* mapped address has to be page aligned, and we use huge
10081008
* pages. */
10091009
mmap_addr = mmap(0, dev_region->size + dev_region->mmap_offset,
1010-
PROT_READ | PROT_WRITE, MAP_SHARED,
1010+
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE,
10111011
vmsg->fds[i], 0);
10121012

10131013
if (mmap_addr == MAP_FAILED) {

0 commit comments

Comments
 (0)