]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
plat/common: Implement `ukplat_bootinfo_fdt_setup`
authorSergiu Moga <sergiu.moga@protonmail.com>
Sun, 14 May 2023 15:21:55 +0000 (18:21 +0300)
committerUnikraft <monkey@unikraft.io>
Fri, 11 Aug 2023 10:18:44 +0000 (10:18 +0000)
Add a method that updates the `ukplat_bootinfo` structure with
relevant information extracted from a `Devicetree` passed as
argument.

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

plat/common/bootinfo_fdt.c [new file with mode: 0644]
plat/common/include/uk/plat/common/bootinfo.h
plat/kvm/Makefile.uk
plat/linuxu/Makefile.uk
plat/xen/Makefile.uk

diff --git a/plat/common/bootinfo_fdt.c b/plat/common/bootinfo_fdt.c
new file mode 100644 (file)
index 0000000..1435bb1
--- /dev/null
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/* Copyright (c) 2023, Unikraft GmbH and The Unikraft Authors.
+ * Licensed under the BSD-3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ */
+
+#include <uk/essentials.h>
+#include <uk/plat/common/bootinfo.h>
+#include <uk/plat/common/sections.h>
+#include <libfdt.h>
+
+#define ukplat_bootinfo_crash(s)               ukplat_crash()
+
+static void fdt_bootinfo_mem_mrd(struct ukplat_bootinfo *bi, void *fdtp)
+{
+       struct ukplat_memregion_desc mrd = {0};
+       int prop_len, prop_min_len;
+       __u64 mem_base, mem_sz;
+       int naddr, nsz, nmem;
+       const __u64 *regs;
+       int rc;
+
+       nmem = fdt_node_offset_by_prop_value(fdtp, -1, "device_type",
+                                            "memory", sizeof("memory"));
+       if (unlikely(nmem < 0))
+               ukplat_bootinfo_crash("No memory found in DTB");
+
+       naddr = fdt_address_cells(fdtp, nmem);
+       if (unlikely(naddr < 0 || naddr >= FDT_MAX_NCELLS))
+               ukplat_bootinfo_crash("Could not find proper address cells!");
+
+       nsz = fdt_size_cells(fdtp, nmem);
+       if (unlikely(nsz < 0 || nsz >= FDT_MAX_NCELLS))
+               ukplat_bootinfo_crash("Could not find proper size cells!");
+
+       /*
+        * The property must contain at least the start address
+        * and size, each of which is 8-bytes.
+        * For now, we only support one memory bank.
+        * TODO: Support more than one memory@ node/regs/ranges properties.
+        */
+       prop_len = 0;
+       prop_min_len = (int)sizeof(fdt32_t) * (naddr + nsz);
+       regs = fdt_getprop(fdtp, nmem, "reg", &prop_len);
+       if (unlikely(!regs || prop_len < prop_min_len))
+               ukplat_bootinfo_crash("Bad 'reg' property or more than one memory bank.");
+
+       mem_sz = fdt64_to_cpu(regs[1]);
+       mem_base = fdt64_to_cpu(regs[0]);
+       if (unlikely(!RANGE_CONTAIN(mem_base, mem_sz,
+                                   __BASE_ADDR, __END - __BASE_ADDR)))
+               ukplat_bootinfo_crash("Image outside of RAM");
+
+       /* Check that we are not placed at the top of the memory region */
+       mrd.len   = __BASE_ADDR - mem_base;
+       if (!mrd.len)
+               goto end_mrd;
+
+       mrd.vbase = (__vaddr_t)mem_base;
+       mrd.pbase = (__paddr_t)mem_base;
+       mrd.type  = UKPLAT_MEMRT_FREE;
+       mrd.flags = UKPLAT_MEMRF_READ | UKPLAT_MEMRF_WRITE;
+
+       rc = ukplat_memregion_list_insert(&bi->mrds, &mrd);
+       if (unlikely(rc < 0))
+               ukplat_bootinfo_crash("Could not add free memory descriptor");
+
+end_mrd:
+       /* Check that we are not placed at the end of the memory region */
+       mrd.len   = mem_base + mem_sz - __END;
+       if (!mrd.len)
+               return;
+
+       mrd.vbase = (__vaddr_t)__END;
+       mrd.pbase = (__paddr_t)__END;
+       mrd.type  = UKPLAT_MEMRT_FREE;
+       mrd.flags = UKPLAT_MEMRF_READ | UKPLAT_MEMRF_WRITE;
+
+       rc = ukplat_memregion_list_insert(&bi->mrds, &mrd);
+       if (unlikely(rc < 0))
+               ukplat_bootinfo_crash("Could not add free memory descriptor");
+}
+
+static void fdt_bootinfo_cmdl_mrd(struct ukplat_bootinfo *bi, void *fdtp)
+{
+       const void *fdt_cmdl;
+       int fdt_cmdl_len;
+       __sz cmdl_len;
+       int nchosen;
+       char *cmdl;
+
+       nchosen = fdt_path_offset(fdtp, "/chosen");
+       if (unlikely(!nchosen))
+               return;
+
+       fdt_cmdl = fdt_getprop(fdtp, nchosen, "bootargs", &fdt_cmdl_len);
+       if (unlikely(!fdt_cmdl || fdt_cmdl_len <= 0))
+               return;
+
+       cmdl = ukplat_memregion_alloc(fdt_cmdl_len + sizeof(CONFIG_UK_NAME) + 1,
+                                     UKPLAT_MEMRT_CMDLINE,
+                                     UKPLAT_MEMRF_READ |
+                                     UKPLAT_MEMRF_MAP);
+       if (unlikely(!cmdl))
+               ukplat_bootinfo_crash("Command-line alloc failed\n");
+
+       cmdl_len = sizeof(CONFIG_UK_NAME);
+       strncpy(cmdl, CONFIG_UK_NAME, cmdl_len);
+       cmdl[cmdl_len - 1] = ' ';
+       strncpy(cmdl + cmdl_len, fdt_cmdl, fdt_cmdl_len);
+       cmdl_len += fdt_cmdl_len;
+       cmdl[cmdl_len] = '\0';
+
+       bi->cmdline = (__u64)cmdl;
+       bi->cmdline_len = (__u64)cmdl_len;
+}
+
+static void fdt_bootinfo_fdt_mrd(struct ukplat_bootinfo *bi, void *fdtp)
+{
+       struct ukplat_memregion_desc mrd = {0};
+       int rc;
+
+       mrd.vbase = (__vaddr_t)fdtp;
+       mrd.pbase = (__paddr_t)fdtp;
+       mrd.len   = fdt_totalsize(fdtp);
+       mrd.type  = UKPLAT_MEMRT_DEVICETREE;
+       mrd.flags = UKPLAT_MEMRF_READ | UKPLAT_MEMRF_MAP;
+
+       rc = ukplat_memregion_list_insert(&bi->mrds, &mrd);
+       if (unlikely(rc < 0))
+               ukplat_bootinfo_crash("Could not insert DT memory descriptor");
+}
+
+void ukplat_bootinfo_fdt_setup(void *fdtp)
+{
+       struct ukplat_bootinfo *bi;
+
+       bi = ukplat_bootinfo_get();
+       if (unlikely(!bi))
+               ukplat_bootinfo_crash("Invalid bootinfo");
+
+       if (unlikely(fdt_check_header(fdtp)))
+               ukplat_bootinfo_crash("Invalid DTB");
+
+       fdt_bootinfo_fdt_mrd(bi, fdtp);
+       fdt_bootinfo_mem_mrd(bi, fdtp);
+       ukplat_memregion_list_coalesce(&bi->mrds);
+
+       /* We use this after coalescing/sorted because this calls
+        * `ukplat_memregion_alloc()` which would be unsafe to do so before
+        * knowing that the memory region descriptor list has been coalesced
+        * and sorted.
+        */
+       fdt_bootinfo_cmdl_mrd(bi, fdtp);
+
+       bi->dtb = (__u64)fdtp;
+}
index a841d39363a3edb7f246767c678e7ec2b4892069..87dc03917c70922be27313e29473ee3e4d4c5aa9 100644 (file)
@@ -86,4 +86,9 @@ void ukplat_bootinfo_set(struct ukplat_bootinfo *bi);
  */
 void ukplat_bootinfo_print(void);
 
+/**
+ * Given the pointer to the FDT, sets up the bootinfo structure based on it.
+ */
+void ukplat_bootinfo_fdt_setup(void *fdtp);
+
 #endif /* __PLAT_CMN_BOOTINFO_H__ */
index dc357a0634fa377f5e1bb1682945460686fa201e..2c6713cdca8b2be5a809132a600c01de4a9d557b 100644 (file)
@@ -58,8 +58,6 @@ endif
 ifeq ($(CONFIG_HAVE_SMP),y)
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(UK_PLAT_COMMON_BASE)/x86/acpi.c|common
 endif
-LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(UK_PLAT_COMMON_BASE)/bootinfo.c|common
-LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(UK_PLAT_COMMON_BASE)/bootinfo.lds.S|common
 ifeq ($(CONFIG_KVM_BOOT_PROTO_MULTIBOOT),y)
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/multiboot.S|x86
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/multiboot.c
@@ -112,8 +110,6 @@ LIBKVMPLAT_SRCS-$(CONFIG_FPSIMD)      += $(UK_PLAT_COMMON_BASE)/arm/fp_arm64.c|i
 ifeq ($(CONFIG_HAVE_SMP),y)
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(UK_PLAT_COMMON_BASE)/arm/lcpu_start.S
 endif
-LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(UK_PLAT_COMMON_BASE)/bootinfo.c|common
-LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(UK_PLAT_COMMON_BASE)/bootinfo.lds.S|common
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(LIBKVMPLAT_BASE)/arm/bpt64.S|arm
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(LIBKVMPLAT_BASE)/arm/entry64.S|isr
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(LIBKVMPLAT_BASE)/arm/exceptions.S|isr
@@ -131,6 +127,10 @@ LIBKVMPLAT_SRCS-y                          += $(UK_PLAT_COMMON_BASE)/lcpu.c|comm
 LIBKVMPLAT_SRCS-y                          += $(UK_PLAT_COMMON_BASE)/memory.c|common
 LIBKVMPLAT_SRCS-y                          += $(UK_PLAT_KVM_DEF_LDS)
 
+LIBKVMPLAT_SRCS-y               += $(UK_PLAT_COMMON_BASE)/bootinfo.c|common
+LIBKVMPLAT_SRCS-$(CONFIG_LIBFDT) += $(UK_PLAT_COMMON_BASE)/bootinfo_fdt.c|common
+LIBKVMPLAT_SRCS-y               += $(UK_PLAT_COMMON_BASE)/bootinfo.lds.S|common
+
 ##
 ## PCI library definitions
 ##
index 9e2e1b8eaa18c516f410acddb3b6b144eb5d5c75..1ca8ddc71a18ed0309dafcf8181141342b9819b6 100644 (file)
@@ -40,8 +40,10 @@ LIBLINUXUPLAT_SRCS-y              += $(LIBLINUXUPLAT_BASE)/time.c
 LIBLINUXUPLAT_SRCS-y              += $(UK_PLAT_COMMON_BASE)/lcpu.c|common
 LIBLINUXUPLAT_SRCS-y              += $(UK_PLAT_COMMON_BASE)/memory.c|common
 LIBLINUXUPLAT_SRCS-y              += $(UK_PLAT_COMMON_BASE)/tls.c|common
-LIBLINUXUPLAT_SRCS-y              += $(UK_PLAT_COMMON_BASE)/bootinfo.c|common
-LIBLINUXUPLAT_SRCS-y              += $(UK_PLAT_COMMON_BASE)/bootinfo.lds.S|common
+
+LIBLINUXUPLAT_SRCS-y                 += $(UK_PLAT_COMMON_BASE)/bootinfo.c|common
+LIBLINUXUPLAT_SRCS-$(CONFIG_LIBFDT)  += $(UK_PLAT_COMMON_BASE)/bootinfo_fdt.c|common
+LIBLINUXUPLAT_SRCS-y                 += $(UK_PLAT_COMMON_BASE)/bootinfo.lds.S|common
 
 LIBLINUXUPLAT_SRCS-y              += $(LIBLINUXUPLAT_BASE)/io.c
 LIBLINUXUPLAT_SRCS-$(CONFIG_TAP_NET) += $(LIBLINUXUPLAT_BASE)/tap_io.c
index 56ea437f04f09f38a53d638f6d5636d1df48e208..63b4a62f683b46a87483f8028058d6e3ede25662 100644 (file)
@@ -50,8 +50,10 @@ LIBXENPLAT_SRCS-y              += $(LIBXENPLAT_BASE)/io.c
 LIBXENPLAT_SRCS-y              += $(UK_PLAT_COMMON_BASE)/lcpu.c|common
 LIBXENPLAT_SRCS-y              += $(UK_PLAT_COMMON_BASE)/memory.c|common
 LIBXENPLAT_SRCS-y              += $(UK_PLAT_COMMON_BASE)/tls.c|common
-LIBXENPLAT_SRCS-y              += $(UK_PLAT_COMMON_BASE)/bootinfo.c|common
-LIBXENPLAT_SRCS-y              += $(UK_PLAT_COMMON_BASE)/bootinfo.lds.S|common
+
+LIBXENPLAT_SRCS-y                += $(UK_PLAT_COMMON_BASE)/bootinfo.c|common
+LIBXENPLAT_SRCS-$(CONFIG_LIBFDT) += $(UK_PLAT_COMMON_BASE)/bootinfo_fdt.c|common
+LIBXENPLAT_SRCS-y                += $(UK_PLAT_COMMON_BASE)/bootinfo.lds.S|common
 
 LIBXENPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(UK_PLAT_COMMON_BASE)/x86/trace.c|common
 LIBXENPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(UK_PLAT_COMMON_BASE)/x86/traps.c|common