]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
plat: Move paging initialization to a platform common location
authorSergiu Moga <sergiu.moga@protonmail.com>
Tue, 18 Apr 2023 10:13:59 +0000 (13:13 +0300)
committerUnikraft <monkey@unikraft.io>
Fri, 11 Aug 2023 10:18:45 +0000 (10:18 +0000)
Since the `paging_init` function of the x86 KVM subsystem is written
in a generic manner, it can be reused by other architectures or
platforms. Thus, move it to a platform generic location and rename
it with a more intuitive name to align it with the other function
declarations of `paging.c`.

Furthermore, only call `ukplat_pt_set_active` at the very end, to avoid
unnecessary `TLB` flushes.

Signed-off-by: Sergiu Moga <sergiu.moga@protonmail.com>
Reviewed-by: Michalis Pappas <michalis@unikraft.io>
Approved-by: Razvan Deaconescu <razvand@unikraft.io>
Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #848

include/uk/plat/paging.h
plat/common/paging.c
plat/kvm/x86/setup.c

index be95843efe0dda5dae46077496d276f937471aed..9203a5c724f5355e377892056c9a4fc9aaebd58a 100644 (file)
@@ -446,6 +446,14 @@ __vaddr_t ukplat_page_kmap(struct uk_pagetable *pt, __paddr_t paddr,
 void ukplat_page_kunmap(struct uk_pagetable *pt, __vaddr_t vaddr,
                        unsigned long pages, unsigned long flags);
 
+/**
+ * Initialize paging subsystem. This function is architecurally generic. It
+ * begins by assigning the free memory regions to the page frame allocator,
+ * unmapping the static boot page tables and finishes by mapping all the
+ * memory regions flagged as UKPLAT_MEMRF_MAP.
+ */
+int ukplat_paging_init(void);
+
 #ifdef __cplusplus
 }
 #endif
index 54064ab03d0c15f7f1e9bd73fa5d9a0819e2ec81..fb5cd9f613caeb4ee358faf7a8cbbf6cec29701e 100644 (file)
@@ -46,6 +46,8 @@
 #include <uk/assert.h>
 #include <uk/print.h>
 #include <uk/plat/paging.h>
+#include <uk/plat/common/sections.h>
+#include <uk/plat/common/bootinfo.h>
 #include <uk/falloc.h>
 
 #define __PLAT_CMN_ARCH_PAGING_H__
@@ -86,6 +88,7 @@ static unsigned int pg_page_largest_level = PAGE_LEVEL;
  * need a way to derive the struct pagetable pointer from the configured
  * HW page table base pointer.
  */
+static struct uk_pagetable kernel_pt;
 static struct uk_pagetable *pg_active_pt;
 
 struct uk_pagetable *ukplat_pt_get_active(void)
@@ -1418,3 +1421,101 @@ void ukplat_page_kunmap(struct uk_pagetable *pt, __vaddr_t vaddr,
 
        pgarch_kunmap(pt, vaddr, len);
 }
+
+static inline unsigned long bootinfo_to_page_attr(__u16 flags)
+{
+       unsigned long prot = 0;
+
+       if (flags & UKPLAT_MEMRF_READ)
+               prot |= PAGE_ATTR_PROT_READ;
+       if (flags & UKPLAT_MEMRF_WRITE)
+               prot |= PAGE_ATTR_PROT_WRITE;
+       if (flags & UKPLAT_MEMRF_EXECUTE)
+               prot |= PAGE_ATTR_PROT_EXEC;
+
+       return prot;
+}
+
+int ukplat_paging_init(void)
+{
+       struct ukplat_memregion_desc *mrd;
+       unsigned long prot;
+       __vaddr_t vaddr;
+       __paddr_t paddr;
+       __sz len;
+       int rc;
+
+       /* Initialize the frame allocator with the free physical memory
+        * regions supplied via the boot info. The new page table uses the
+        * one currently active.
+        */
+       rc = -ENOMEM; /* In case there is no region */
+       ukplat_memregion_foreach(&mrd, UKPLAT_MEMRT_FREE, 0, 0) {
+               paddr  = PAGE_ALIGN_UP(mrd->pbase);
+               len    = PAGE_ALIGN_DOWN(mrd->len - (paddr - mrd->pbase));
+
+               /* Not mapped */
+               mrd->vbase = __U64_MAX;
+               mrd->flags &= ~UKPLAT_MEMRF_PERMS;
+
+               if (unlikely(len == 0))
+                       continue;
+
+               if (!kernel_pt.fa) {
+                       rc = ukplat_pt_init(&kernel_pt, paddr, len);
+                       if (unlikely(rc))
+                               kernel_pt.fa = NULL;
+               } else {
+                       rc = ukplat_pt_add_mem(&kernel_pt, paddr, len);
+               }
+
+               /* We do not fail if we cannot add this memory region to the
+                * frame allocator. If the range is too small to hold the
+                * metadata, this is expected. Just ignore this error.
+                */
+               if (unlikely(rc && rc != -ENOMEM))
+                       uk_pr_err("Cannot add %12lx-%12lx to paging: %d\n",
+                                 paddr, paddr + len, rc);
+       }
+
+       if (unlikely(!kernel_pt.fa))
+               return rc;
+
+       /* Perform unmappings */
+       ukplat_memregion_foreach(&mrd, 0, UKPLAT_MEMRF_UNMAP,
+                                UKPLAT_MEMRF_UNMAP) {
+               UK_ASSERT(mrd->vbase != __U64_MAX);
+
+               vaddr = PAGE_ALIGN_DOWN(mrd->vbase);
+               len   = PAGE_ALIGN_UP(mrd->len + (mrd->vbase - vaddr));
+
+               rc = ukplat_page_unmap(&kernel_pt, vaddr,
+                                      len >> PAGE_SHIFT,
+                                      PAGE_FLAG_KEEP_FRAMES);
+               if (unlikely(rc))
+                       return rc;
+       }
+
+       /* Perform mappings */
+       ukplat_memregion_foreach(&mrd, 0, UKPLAT_MEMRF_MAP,
+                                UKPLAT_MEMRF_MAP) {
+               UK_ASSERT(mrd->vbase != __U64_MAX);
+
+               vaddr = PAGE_ALIGN_DOWN(mrd->vbase);
+               paddr = PAGE_ALIGN_DOWN(mrd->pbase);
+               len   = PAGE_ALIGN_UP(mrd->len + (mrd->vbase - vaddr));
+               prot  = bootinfo_to_page_attr(mrd->flags);
+
+               rc = ukplat_page_map(&kernel_pt, vaddr, paddr,
+                                    len >> PAGE_SHIFT, prot, 0);
+               if (unlikely(rc && rc != -EEXIST))
+                       return rc;
+       }
+
+       /* Activate page table */
+       rc = ukplat_pt_set_active(&kernel_pt);
+       if (unlikely(rc))
+               return rc;
+
+       return 0;
+}
index 03c6d436d313bdb463cadbe4eb3e3f009fb57f4c..0e23a06271b5b9c96bb4201e6a2241027302e61d 100644 (file)
 #define PLATFORM_MAX_MEM_ADDR 0x100000000 /* 4 GiB */
 
 #ifdef CONFIG_HAVE_PAGING
-/* Initial page table struct used for paging API to absorb statically defined
- * startup page table.
- */
-static struct uk_pagetable kernel_pt;
-
-static inline unsigned long bootinfo_to_page_attr(__u16 flags)
-{
-       unsigned long prot = 0;
-
-       if (flags & UKPLAT_MEMRF_READ)
-               prot |= PAGE_ATTR_PROT_READ;
-       if (flags & UKPLAT_MEMRF_WRITE)
-               prot |= PAGE_ATTR_PROT_WRITE;
-       if (flags & UKPLAT_MEMRF_EXECUTE)
-               prot |= PAGE_ATTR_PROT_EXEC;
-
-       return prot;
-}
-
-static int paging_init(void)
-{
-       struct ukplat_memregion_desc *mrd;
-       __sz len;
-       __vaddr_t vaddr;
-       __paddr_t paddr;
-       unsigned long prot;
-       int rc;
-
-       /* Initialize the frame allocator with the free physical memory
-        * regions supplied via the boot info. The new page table uses the
-        * one currently active.
-        */
-       rc = -ENOMEM; /* In case there is no region */
-       ukplat_memregion_foreach(&mrd, UKPLAT_MEMRT_FREE, 0, 0) {
-               paddr  = PAGE_ALIGN_UP(mrd->pbase);
-               len    = PAGE_ALIGN_DOWN(mrd->len - (paddr - mrd->pbase));
-
-               /* Not mapped */
-               mrd->vbase = __U64_MAX;
-               mrd->flags &= ~UKPLAT_MEMRF_PERMS;
-
-               if (unlikely(len == 0))
-                       continue;
-
-               if (!kernel_pt.fa) {
-                       rc = ukplat_pt_init(&kernel_pt, paddr, len);
-                       if (unlikely(rc))
-                               kernel_pt.fa = NULL;
-               } else {
-                       rc = ukplat_pt_add_mem(&kernel_pt, paddr, len);
-               }
-
-               /* We do not fail if we cannot add this memory region to the
-                * frame allocator. If the range is too small to hold the
-                * metadata, this is expected. Just ignore this error.
-                */
-               if (unlikely(rc && rc != -ENOMEM))
-                       uk_pr_err("Cannot add %12lx-%12lx to paging: %d\n",
-                                 paddr, paddr + len, rc);
-       }
-
-       if (unlikely(!kernel_pt.fa))
-               return rc;
-
-       /* Activate page table */
-       rc = ukplat_pt_set_active(&kernel_pt);
-       if (unlikely(rc))
-               return rc;
-
-       /* Perform unmappings */
-       ukplat_memregion_foreach(&mrd, 0, UKPLAT_MEMRF_UNMAP,
-                                UKPLAT_MEMRF_UNMAP) {
-               UK_ASSERT(mrd->vbase != __U64_MAX);
-
-               vaddr = PAGE_ALIGN_DOWN(mrd->vbase);
-               len   = PAGE_ALIGN_UP(mrd->len + (mrd->vbase - vaddr));
-
-               rc = ukplat_page_unmap(&kernel_pt, vaddr,
-                                      len >> PAGE_SHIFT,
-                                      PAGE_FLAG_KEEP_FRAMES);
-               if (unlikely(rc))
-                       return rc;
-       }
-
-       /* Perform mappings */
-       ukplat_memregion_foreach(&mrd, 0, UKPLAT_MEMRF_MAP,
-                                UKPLAT_MEMRF_MAP) {
-               UK_ASSERT(mrd->vbase != __U64_MAX);
-
-               vaddr = PAGE_ALIGN_DOWN(mrd->vbase);
-               paddr = PAGE_ALIGN_DOWN(mrd->pbase);
-               len   = PAGE_ALIGN_UP(mrd->len + (mrd->vbase - vaddr));
-               prot  = bootinfo_to_page_attr(mrd->flags);
-
-               rc = ukplat_page_map(&kernel_pt, vaddr, paddr,
-                                    len >> PAGE_SHIFT, prot, 0);
-               /* Unmappings are currently not performed on the low-mem.
-                * Ignore any errors caused by already existing mappings.
-                */
-               if (unlikely(rc && rc != -EEXIST))
-                       return rc;
-       }
-
-       return 0;
-}
-
 static int mem_init(struct ukplat_bootinfo *bi)
 {
        int rc;
@@ -158,7 +52,7 @@ static int mem_init(struct ukplat_bootinfo *bi)
        if (unlikely(rc < 0))
                return rc;
 
-       return paging_init();
+       return ukplat_paging_init();
 }
 #else /* CONFIG_HAVE_PAGING */
 static int mem_init(struct ukplat_bootinfo *bi)