]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
lib/uksglist: Make sure buffers are mapped
authorMarc Rittinghaus <marc.rittinghaus@unikraft.io>
Wed, 12 Apr 2023 12:55:03 +0000 (14:55 +0200)
committerUnikraft <monkey@unikraft.io>
Wed, 26 Apr 2023 10:28:33 +0000 (10:28 +0000)
With ukvmem and demand-paging enabled it can happen that buffers
supplied to the sglist are not fully backed by physical memory. In that
case the call to ukplat_virt_to_phys() fails, which expects a valid
mapping.

This commit adds a call to uk_vma_advise() to make sure the entire
buffer is backed by physical memory.

A future optimization should integrate the address translation and
backing with physical memory in a visitor pattern that traverses the
page tables only once instead of doing it one time for the advise and
then an extra time for each page of the buffer.

Signed-off-by: Marc Rittinghaus <marc.rittinghaus@unikraft.io>
Reviewed-by: Ioan-Teodor Teugea <teodor.teugea@gmail.com>
Reviewed-by: Razvan Deaconescu <razvand@unikraft.io>
Approved-by: Razvan Deaconescu <razvand@unikraft.io>
Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #834

lib/uksglist/sglist.c

index 65973d01897a050ac20296d3f68f5e6c46ec89d8..150de10a69ec0e7ba28ddd60cc0dfb2bd862df1d 100644 (file)
 #include <uk/alloc.h>
 #endif /* CONFIG_LIBUKALLOC */
 #include <uk/sglist.h>
+#ifdef CONFIG_LIBUKVMEM
+#include <uk/arch/paging.h>
+#include <uk/vmem.h>
+#endif /* CONFIG_LIBUKVMEM*/
 
 /*
  * Convenience macros to save the state of an sglist so it can be restored
@@ -125,9 +129,20 @@ static inline int _sglist_append_buf(struct uk_sglist *sg, void *buf,
        if (len == 0)
                return 0;
 
-       /* Do the first page.  It may have an offset. */
        vaddr = (__vaddr_t)buf;
        offset = page_off(vaddr);
+
+#ifdef CONFIG_LIBUKVMEM
+       /* Ensure the buffer is backed by physical memory */
+       error = uk_vma_advise(uk_vas_get_active(),
+                             PAGE_ALIGN_DOWN(vaddr),
+                             PAGE_ALIGN_UP(len + offset), UK_VMA_ADV_WILLNEED,
+                             UK_VMA_FLAG_UNINITIALIZED);
+       if (unlikely(error))
+               return error;
+#endif /* CONFIG_LIBUKVMEM */
+
+       /* Do the first page. It may have an offset. */
        paddr = ukplat_virt_to_phys((void *)vaddr);
        seglen = MIN(len, __PAGE_SIZE - offset);
        if (sg->sg_nseg == 0) {