]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
drivers/ukbus/platform: Add uk_bus_pf_devmap
authorMichalis Pappas <michalis@unikraft.io>
Wed, 20 Sep 2023 11:18:33 +0000 (13:18 +0200)
committerRazvan Deaconescu <razvand@unikraft.io>
Fri, 20 Oct 2023 16:35:55 +0000 (19:35 +0300)
Add `uk_bus_pf_devmap()` for mapping device regions. Because of the
current boot flow that initializes the vmmap API after the probing
the interrupt controller - which is required for bringing up secondary
cores - it is not possible to use uk_vma_map_dma() here, so we need to
resort to the low level paging API and map devices 1:1.

Signed-off-by: Michalis Pappas <michalis@unikraft.io>
Reviewed-by: Marco Schlumpp <marco@unikraft.io>
Reviewed-by: Rares Miculescu <miculescur@gmail.com>
Approved-by: Razvan Deaconescu <razvand@unikraft.io>
GitHub-Closes: #1116

drivers/ukbus/platform/exportsyms.uk
drivers/ukbus/platform/include/uk/bus/platform.h
drivers/ukbus/platform/platform_bus.c

index ae22b6a99bd5a518ce131d4b3c53c805c7fef7ee..0d7431d896a7acbc722fe652aa1cf4de0b9fc139 100644 (file)
@@ -1 +1,2 @@
 _pf_register_driver
+uk_bus_pf_devmap
index feea6b6c7f26e36b3d518d52f9623c066065361e..8e9f94b69adce4e17add0f48fd604b8efc3f18f6 100644 (file)
@@ -97,6 +97,19 @@ struct pf_device {
 };
 UK_TAILQ_HEAD(pf_device_list, struct pf_device);
 
+#if CONFIG_PAGING
+/**
+ * (Re)map device memory
+ *
+ * Maps a region with attributes suitable for device memory access.
+ * If the region is already mapped, it will be remapped unconditionally.
+ *
+ * @param base Base address of the region to map.
+ * @param size Region size. Must be page-aligned.
+ * @return virtual address
+ */
+__vaddr_t uk_bus_pf_devmap(__u64 base, __sz size);
+#endif /* CONFIG_PAGING */
 
 #define PF_REGISTER_DRIVER(b)                  \
        _PF_REGISTER_DRIVER(__LIBNAME__, b)
index abe4eb8f784ac794714aea017b18a0485e9d251f..d80db40e34cf14251331bdd3546063b59c82b989 100644 (file)
 #include <uk/bus/platform.h>
 #include <uk/plat/common/bootinfo.h>
 
+#if CONFIG_PAGING
+#include <uk/errptr.h>
+#include <uk/plat/paging.h>
+#endif /* CONFIG_PAGING */
+
 #if CONFIG_LIBUKBUS_PLATFORM_FDT
 #include <libfdt.h>
 #include <uk/ofw/fdt.h>
@@ -230,6 +235,45 @@ static int pf_init(struct uk_alloc *a)
        return 0;
 }
 
+#if CONFIG_PAGING
+__vaddr_t uk_bus_pf_devmap(__paddr_t base, __sz size)
+{
+       struct uk_pagetable *pt;
+       __vaddr_t vaddr, paddr;
+       unsigned long attr;
+       unsigned long pages;
+       int rc;
+
+       attr = PAGE_ATTR_PROT_RW;
+#ifdef CONFIG_ARCH_ARM_64
+       attr |= PAGE_ATTR_TYPE_DEVICE_nGnRnE;
+#endif /* CONFIG_ARCH_ARM_64 */
+
+       pages = ALIGN_UP(size, __PAGE_SIZE) >> PAGE_SHIFT;
+
+       pt = ukplat_pt_get_active();
+
+       paddr = ALIGN_DOWN(base, __PAGE_SIZE);
+       vaddr = ALIGN_DOWN(base, __PAGE_SIZE);
+
+       /* We can't use uk_vma_map_dma here as the vmem API is initialized
+        * way too late for the interrupt controller which is required for
+        * bringing up secondary cores.
+        */
+       rc = ukplat_page_map(pt, vaddr, paddr, pages, attr, 0);
+       if (!rc)
+               goto out;
+
+       if (rc == -EEXIST)
+               rc = ukplat_page_set_attr(pt, vaddr, pages, attr, 0);
+
+       if (unlikely(rc))
+               return (__vaddr_t)ERR2PTR(rc);
+out:
+       return (__vaddr_t)base;
+}
+#endif /* CONFIG_PAGING */
+
 void _pf_register_driver(struct pf_driver *drv)
 {
        UK_ASSERT(drv != NULL);