]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
plat: Integrate `ukplat_memregion` API's into `ARM64` builds
authorSergiu Moga <sergiu.moga@protonmail.com>
Sat, 8 Apr 2023 10:11:03 +0000 (13:11 +0300)
committerUnikraft <monkey@unikraft.io>
Fri, 11 Aug 2023 10:18:45 +0000 (10:18 +0000)
Rely on the generic `ukplat_memregion` API's for memory region
management and drop `_libkvmplat_cfg` usage in favor of the
`bootinfo` getters.

Now that `ukplat_memregion`'s are usable on `ARM64`, proper
paging support can be used instead of the overly-complicated
memory re-adjustment that was previously done in `_init_dtb_mem`.
Instead, we rely on `ukplat_memregion_alloc` for proper memory
region management.

Another important, notable change, is that of changing
`arm64_bpt_l0_pt0` to contain only one, unified, entry of `pte_fill`.
This reduced page permission granularity allows us further flexibility
in where the Kernel is placed so that we are truly position independent.
One may be right in saying that this looks not so secure, having all that
memory mapped with all permissions, however this is not as important when
the two existing possible use-cases are taken into consideration:
- Paging API is disabled and we will either way have wrong permissions
everywhere anyway
- Paging API is enabled and this area will be unmapped anyway and new
proper permissions will be used instead
Therefore, until the time comes when we manage to dynamically get rid
of the static boot page tables, we will align ARM with x86 and have the
static boot page tables all mapped with all permissions w.r.t. to
Kernel placement.

Furthermore, now that ARM64 can also use the heap base
`CONFIG_LIBUKBOOT_HEAP_BASE` configuration option, drop the x86
dependency.

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

lib/ukboot/Config.uk
plat/common/arm/time.c
plat/common/pci_ecam.c
plat/common/platform_bus.c
plat/drivers/virtio/virtio_mmio.c
plat/kvm/Makefile.uk
plat/kvm/arm/bpt64.S
plat/kvm/arm/entry64.S
plat/kvm/arm/intctrl.c
plat/kvm/arm/memory.c [deleted file]
plat/kvm/arm/setup.c

index 61647e5b4cb4a5cd72607d0d5c8ba71b1f9bc5e3..e49d48390c691a407c612612c5294b230f9a63a7 100644 (file)
@@ -127,9 +127,7 @@ if LIBUKBOOT
        default 0x400000000
        depends on HAVE_PAGING
        depends on !LIBUKBOOT_NOALLOC
-       # TODO: This is temporary until all platforms/archs supporting paging
-       # have switched to not initialize the heap in the platform.
-       depends on (ARCH_X86_64 && PLAT_KVM)
+       depends on PLAT_KVM
 
        choice LIBUKBOOT_INITSCHED
        prompt "Initialize scheduler"
index eaa2434618e7d9fb1dca47bcc3878ad48ff85328..ff346a39b2b43fe9a882acff10817aeccfae4484 100644 (file)
@@ -39,6 +39,7 @@
 #include <uk/bitops.h>
 #include <uk/plat/common/cpu.h>
 #include <uk/plat/common/sections.h>
+#include <uk/plat/common/bootinfo.h>
 #include <ofw/gic_fdt.h>
 #include <uk/plat/common/irq.h>
 #include <gic/gic.h>
@@ -51,6 +52,7 @@ static const char * const arch_timer_list[] = {
 };
 
 static uint32_t timer_irq;
+static void *dtb;
 
 void generic_timer_mask_irq(void)
 {
@@ -78,7 +80,7 @@ uint32_t generic_timer_get_frequency(int fdt_timer)
        * by the firmware. A property in the DT (clock-frequency) has
        * been introduced to workaround those firmware.
        */
-       fdt_freq = fdt_getprop(_dtb, fdt_timer, "clock-frequency", &len);
+       fdt_freq = fdt_getprop(dtb, fdt_timer, "clock-frequency", &len);
        if (!fdt_freq || (len <= 0)) {
                uk_pr_info("No clock-frequency found, reading from register directly.\n");
 
@@ -112,6 +114,8 @@ void ukplat_time_init(void)
        uint32_t irq_type, hwirq;
        uint32_t trigger_type;
 
+       dtb = (void *)ukplat_bootinfo_get()->dtb;
+
        /*
         * Monotonic time begins at boot_ticks (first read of counter
         * before calibration).
@@ -119,7 +123,7 @@ void ukplat_time_init(void)
        generic_timer_update_boot_ticks();
 
        /* Currently, we only support 1 timer per system */
-       fdt_timer = fdt_node_offset_by_compatible_list(_dtb, -1,
+       fdt_timer = fdt_node_offset_by_compatible_list(dtb, -1,
                                                       arch_timer_list);
        if (fdt_timer < 0)
                UK_CRASH("Could not find arch timer!\n");
@@ -128,7 +132,7 @@ void ukplat_time_init(void)
        if (rc < 0)
                UK_CRASH("Failed to initialize platform time\n");
 
-       rc = gic_get_irq_from_dtb(_dtb, fdt_timer, 2, &irq_type, &hwirq,
+       rc = gic_get_irq_from_dtb(dtb, fdt_timer, 2, &irq_type, &hwirq,
                                  &trigger_type);
        if (rc < 0)
                UK_CRASH("Failed to find IRQ number from DTB\n");
index f4a61fadcb1e7a0a9ea07715ca9deda19a40f301..2b05003c63a4a87659b604ecad99d643c248e1fb 100644 (file)
@@ -36,8 +36,8 @@
 #include <uk/list.h>
 #include <uk/alloc.h>
 #include <uk/print.h>
-#include <kvm/config.h>
 #include <uk/plat/common/cpu.h>
+#include <uk/plat/common/bootinfo.h>
 #include <libfdt_env.h>
 #include <ofw/fdt.h>
 #include <libfdt.h>
@@ -66,8 +66,7 @@ struct pci_range {
        __u32 flags;
 };
 
-#define fdt_start (_libkvmplat_cfg.dtb)
-
+static void *dtb;
 static int gen_pci_fdt; // start offset of pci-ecam in fdt
 /*
  * Function to implement the pci_ops ->map_bus method
@@ -165,9 +164,9 @@ static int gen_pci_parser_range(struct pci_range_parser *parser, int offset)
        const int na = 3, ns = 2;
        int rlen;
 
-       parser->pna = fdt_address_cells(fdt_start, offset);
+       parser->pna = fdt_address_cells(dtb, offset);
        parser->np = parser->pna + na + ns;
-       parser->range = fdt_getprop(fdt_start, offset, "ranges", &rlen);
+       parser->range = fdt_getprop(dtb, offset, "ranges", &rlen);
        if (parser->range == NULL)
                return -ENOENT;
 
@@ -190,8 +189,8 @@ struct pci_range *pci_range_parser_one(struct pci_range_parser *parser,
        range->pci_space = fdt32_to_cpu(*parser->range);
        range->flags = pci_get_flags(parser->range);
        range->pci_addr = fdt_reg_read_number(parser->range + 1, ns);
-       range->cpu_addr = fdt_translate_address_by_ranges(fdt_start, offset,
-                               parser->range + na);
+       range->cpu_addr = fdt_translate_address_by_ranges(dtb, offset,
+                                                         parser->range + na);
        range->size = fdt_reg_read_number(parser->range + parser->pna + na, ns);
 
        parser->range += parser->np;
@@ -241,10 +240,10 @@ int gen_pci_irq_parse(const fdt32_t *addr, struct fdt_phandle_args *out_irq)
         * is none, we are nice and just walk up the tree
         */
        do {
-               prop = fdt_getprop(fdt_start, ipar, "#interrupt-cells", &plen);
+               prop = fdt_getprop(dtb, ipar, "#interrupt-cells", &plen);
                if (prop != NULL)
                        break;
-               ipar = irq_find_parent(fdt_start, ipar);
+               ipar = irq_find_parent(dtb, ipar);
        } while (ipar >= 0);
 
        if (ipar < 0) {
@@ -263,8 +262,8 @@ int gen_pci_irq_parse(const fdt32_t *addr, struct fdt_phandle_args *out_irq)
         */
        old = ipar;
        do {
-               tmp = fdt_getprop(fdt_start, old, "#address-cells", NULL);
-               tnode = fdt_parent_offset(fdt_start, old);
+               tmp = fdt_getprop(dtb, old, "#address-cells", NULL);
+               tnode = fdt_parent_offset(dtb, old);
                old = tnode;
        } while (old >= 0 && tmp == NULL);
 
@@ -283,7 +282,8 @@ int gen_pci_irq_parse(const fdt32_t *addr, struct fdt_phandle_args *out_irq)
                /* Now check if cursor is an interrupt-controller and if it is
                 * then we are done
                 */
-               if (fdt_prop_read_bool(fdt_start, ipar, "interrupt-controller")) {
+               if (fdt_prop_read_bool(dtb, ipar,
+                                      "interrupt-controller")) {
                        uk_pr_info(" -> got it !\n");
                        return 0;
                }
@@ -298,17 +298,18 @@ int gen_pci_irq_parse(const fdt32_t *addr, struct fdt_phandle_args *out_irq)
                }
 
                /* Now look for an interrupt-map */
-               imap = fdt_getprop(fdt_start, ipar, "interrupt-map", &imaplen);
+               imap = fdt_getprop(dtb, ipar, "interrupt-map", &imaplen);
                /* No interrupt map, check for an interrupt parent */
                if (imap == NULL) {
                        uk_pr_info(" -> no map, getting parent\n");
-                       newpar = irq_find_parent(fdt_start, ipar);
+                       newpar = irq_find_parent(dtb, ipar);
                        goto skiplevel;
                }
                imaplen /= sizeof(__u32);
 
                /* Look for a mask */
-               imask = fdt_getprop(fdt_start, ipar, "interrupt-map-mask", NULL);
+               imask = fdt_getprop(dtb, ipar,
+                                   "interrupt-map-mask", NULL);
                if (!imask)
                        imask = dummy_imask;
 
@@ -323,7 +324,7 @@ int gen_pci_irq_parse(const fdt32_t *addr, struct fdt_phandle_args *out_irq)
                        uk_pr_info(" -> match=%d (imaplen=%d)\n", match, imaplen);
 
                        /* Get the interrupt parent */
-                       newpar = fdt_node_offset_by_phandle(fdt_start, fdt32_to_cpu(*imap));
+                       newpar = fdt_node_offset_by_phandle(dtb, fdt32_to_cpu(*imap));
                        imap++;
                        --imaplen;
 
@@ -336,16 +337,16 @@ int gen_pci_irq_parse(const fdt32_t *addr, struct fdt_phandle_args *out_irq)
                        /* Get #interrupt-cells and #address-cells of new
                         * parent
                         */
-                       prop = fdt_getprop(fdt_start, newpar, "#interrupt-cells",
-                                                &plen);
+                       prop = fdt_getprop(dtb, newpar, "#interrupt-cells",
+                                          &plen);
                        if (prop == NULL) {
                                uk_pr_info(" -> parent lacks #interrupt-cells!\n");
                                goto fail;
                        }
                        newintsize = fdt32_to_cpu(prop[0]);
 
-                       prop = fdt_getprop(fdt_start, newpar, "#address-cells",
-                                                &plen);
+                       prop = fdt_getprop(dtb, newpar, "#address-cells",
+                                          &plen);
                        if (prop == NULL) {
                                uk_pr_info(" -> parent lacks #address-cells!\n");
                                goto fail;
@@ -404,24 +405,26 @@ static int gen_pci_probe(struct pf_device *pfdev __unused)
        __u64 reg_size;
        struct pci_range range;
        struct pci_range_parser parser;
+       const char *comp;
        int err;
 
+       dtb = (void *)ukplat_bootinfo_get()->dtb;
        /* 1.Get the base and size of config space */
-       gen_pci_fdt = fdt_node_offset_by_compatible(fdt_start, -1,
-                                               gen_pci_match_table[0].compatible);
+       comp = gen_pci_match_table[0].compatible;
+       gen_pci_fdt = fdt_node_offset_by_compatible(dtb, -1, comp);
        if (gen_pci_fdt < 0) {
                uk_pr_info("Error in searching pci controller in fdt\n");
                goto error_exit;
        } else {
-               prop = fdt_getprop(fdt_start, gen_pci_fdt, "reg", &prop_len);
+               prop = fdt_getprop(dtb, gen_pci_fdt, "reg", &prop_len);
                if (!prop) {
                        uk_pr_err("reg of device not found in fdt\n");
                        goto error_exit;
                }
 
                /* Get the base addr and the size */
-               fdt_get_address(fdt_start, gen_pci_fdt, 0,
-                                       &reg_base, &reg_size);
+               fdt_get_address(dtb, gen_pci_fdt, 0,
+                               &reg_base, &reg_size);
                reg_base = fdt32_to_cpu(prop[0]);
                reg_base = reg_base << 32 | fdt32_to_cpu(prop[1]);
                reg_size = fdt32_to_cpu(prop[2]);
@@ -434,7 +437,7 @@ static int gen_pci_probe(struct pf_device *pfdev __unused)
                                reg_base, reg_size);
 
        /* 2.Get the bus range of pci controller */
-       prop = fdt_getprop(fdt_start, gen_pci_fdt, "bus-range", &prop_len);
+       prop = fdt_getprop(dtb, gen_pci_fdt, "bus-range", &prop_len);
        if (!prop) {
                uk_pr_err("bus-range of device not found in fdt\n");
                goto error_exit;
index 1fbf559d4e1797ff242a56714573da800c6ace53..c34a32931b38313edb732fce019219bf8424dc86 100644 (file)
 
 #include <string.h>
 #include <uk/print.h>
+#include <uk/plat/memory.h>
 #include <uk/plat/common/cpu.h>
 #include <platform_bus.h>
 #include <libfdt.h>
-#include <kvm/config.h>
 #include <gic/gic-v2.h>
 #include <ofw/fdt.h>
+#include <uk/plat/common/bootinfo.h>
 
-#define fdt_start (_libkvmplat_cfg.dtb)
+static void *dtb;
 
 struct pf_bus_handler {
        struct uk_bus b;
@@ -140,9 +141,11 @@ static int pf_probe(void)
 
        uk_pr_info("Probe PF\n");
 
+       dtb = (void *)ukplat_bootinfo_get()->dtb;
+
        /* Search all the platform bus devices provided by fdt */
        do {
-               fdt_pf = fdt_node_offset_idx_by_compatible_list(_libkvmplat_cfg.dtb,
+               fdt_pf = fdt_node_offset_idx_by_compatible_list(dtb,
                                                fdt_pf, pf_device_compatible_list, &idx);
                if (fdt_pf < 0) {
                        uk_pr_info("End of searching platform devices\n");
index 66802f00472d028cb14749255b5387ece9055eca..969605be23a273d529f83d0028593e996d518c7c 100644 (file)
@@ -42,7 +42,7 @@
 #include <uk/bitops.h>
 #include <libfdt.h>
 #include <ofw/fdt.h>
-#include <kvm/config.h>
+#include <uk/plat/common/bootinfo.h>
 
 #include <platform_bus.h>
 #include <virtio/virtio_config.h>
@@ -400,12 +400,14 @@ static int virtio_mmio_probe(struct pf_device *pfdev)
        int fdt_vm = pfdev->fdt_offset;
        __u64 reg_base;
        __u64 reg_size;
+       void *dtb;
 
+       dtb = (void *)ukplat_bootinfo_get()->dtb;
        if (fdt_vm == -FDT_ERR_NOTFOUND) {
                uk_pr_info("device not found in fdt\n");
                goto error_exit;
        } else {
-               prop = fdt_getprop(_libkvmplat_cfg.dtb, fdt_vm, "interrupts", &prop_len);
+               prop = fdt_getprop(dtb, fdt_vm, "interrupts", &prop_len);
                if (!prop) {
                        uk_pr_err("irq of device not found in fdt\n");
                        goto error_exit;
@@ -414,15 +416,14 @@ static int virtio_mmio_probe(struct pf_device *pfdev)
                type = fdt32_to_cpu(prop[0]);
                hwirq = fdt32_to_cpu(prop[1]);
 
-               prop = fdt_getprop(_libkvmplat_cfg.dtb, fdt_vm, "reg", &prop_len);
+               prop = fdt_getprop(dtb, fdt_vm, "reg", &prop_len);
                if (!prop) {
                        uk_pr_err("reg of device not found in fdt\n");
                        goto error_exit;
                }
 
                /* only care about base addr, ignore the size */
-               fdt_get_address(_libkvmplat_cfg.dtb, fdt_vm, 0,
-                                       &reg_base, &reg_size);
+               fdt_get_address(dtb, fdt_vm, 0, &reg_base, &reg_size);
        }
 
        pfdev->base = reg_base;
index 2c6713cdca8b2be5a809132a600c01de4a9d557b..144239531257523e289d8c57bc631d916ccd6ef6 100644 (file)
@@ -117,10 +117,9 @@ LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(LIBKVMPLAT_BASE)/arm/pagetable64.S|is
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(LIBKVMPLAT_BASE)/arm/setup.c
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(LIBKVMPLAT_BASE)/arm/lcpu.c
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(LIBKVMPLAT_BASE)/arm/intctrl.c
-LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += $(LIBKVMPLAT_BASE)/arm/memory.c
 
 LIBKVMPLAT_SRCS-y                          += $(LIBKVMPLAT_BASE)/shutdown.c
-LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64)      += $(LIBKVMPLAT_BASE)/memory.c
+LIBKVMPLAT_SRCS-y                          += $(LIBKVMPLAT_BASE)/memory.c
 LIBKVMPLAT_SRCS-y                          += $(LIBKVMPLAT_BASE)/irq.c
 LIBKVMPLAT_SRCS-y                          += $(LIBKVMPLAT_BASE)/io.c
 LIBKVMPLAT_SRCS-y                          += $(UK_PLAT_COMMON_BASE)/lcpu.c|common
index ffe252c5b7a9ed3abfaad1358c45830eec62ad53..f286288dba769c7a1be96e487d1e4a387ca5b93d 100644 (file)
@@ -203,6 +203,6 @@ arm64_bpt_l1_pt1:
  * 0x0000000040000000 - 0x00000000401fffff     Kernel  @ 1GiB
  */
 .align 12
+.globl arm64_bpt_l0_pt0
 arm64_bpt_l0_pt0:
-       pte_fill        0x0000000040000000, 256, 0, PTE_PAGE_NORMAL_RO
-       pte_fill        0x0000000040100000, 256, 0, PTE_PAGE_NORMAL_RWX
+       pte_fill        0x0000000040000000, 512, 0, PTE_PAGE_NORMAL_RWX
index abf2c01dcc80bbeae8976289c666435c5cbd417e..01ff3dab99d8182e11931093f5daa7559b363787 100644 (file)
@@ -100,7 +100,9 @@ ENTRY(_libkvmplat_entry)
 
        /* Load dtb address to x0 as a parameter */
        ur_ldr  x0, _dtb
+       bl ukplat_bootinfo_fdt_setup
 
-       b _libkvmplat_start
+       bl ukplat_bootinfo_get
+       b _ukplat_entry
 END(_libkvmplat_entry)
 
index 3e8167525f21cd2767a1644cb20501abaafd1d58..9d259702bc5f0842bff256ec655300690a9bde3e 100644 (file)
 #include <arm/cpu.h>
 #include <arm/irq.h>
 #include <gic/gic.h>
-#include <kvm/config.h>
 #include <uk/essentials.h>
+#include <uk/plat/common/bootinfo.h>
 
 /** Corresponding driver for GIC present on the hardware */
 struct _gic_dev *gic;
 
 void intctrl_init(void)
 {
+       void *dtb;
        int rc;
 
+       dtb = (void *)ukplat_bootinfo_get()->dtb;
+
        /* Initialize GIC from DTB */
-       rc = _dtb_init_gic(_libkvmplat_cfg.dtb, &gic);
+       rc = _dtb_init_gic(dtb, &gic);
        if (unlikely(rc))
                goto EXIT_ERR;
 
diff --git a/plat/kvm/arm/memory.c b/plat/kvm/arm/memory.c
deleted file mode 100644 (file)
index 4b923e9..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/* SPDX-License-Identifier: ISC */
-/* Copyright (c) 2015, IBM
- *           (c) 2017, NEC Europe Ltd.
- * Author(s): Dan Williams <djwillia@us.ibm.com>
- *            Simon Kuenzer <simon.kuenzer@neclab.eu>
- *
- * Permission to use, copy, modify, and/or distribute this software
- * for any purpose with or without fee is hereby granted, provided
- * that the above copyright notice and this permission notice appear
- * in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
- * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <string.h>
-#include <uk/plat/common/sections.h>
-#include <sys/types.h>
-#include <uk/plat/memory.h>
-#include <uk/assert.h>
-#include <kvm/config.h>
-
-int ukplat_memregion_count(void)
-{
-       return (9
-               + ((_libkvmplat_cfg.initrd.len > 0) ? 1 : 0)
-               + ((_libkvmplat_cfg.heap2.len  > 0) ? 1 : 0));
-}
-
-int ukplat_memregion_get(int i, struct ukplat_memregion_desc **m)
-{
-       static struct ukplat_memregion_desc mrd[11];
-
-       UK_ASSERT(m);
-
-       switch (i) {
-       case 0: /* text */
-               mrd[i].pbase = __TEXT;
-               mrd[i].vbase = __TEXT;
-               mrd[i].len   = __ETEXT - __TEXT;
-               mrd[i].type  = UKPLAT_MEMRT_KERNEL;
-               mrd[i].flags = UKPLAT_MEMRF_READ | UKPLAT_MEMRF_EXECUTE;
-#if CONFIG_UKPLAT_MEMRNAME
-               strncpy(mrd[i].name, "text", sizeof(mrd[i].name) - 1);
-#endif
-               *m = &mrd[i];
-               break;
-       case 1: /* eh_frame */
-               mrd[i].pbase = __EH_FRAME_START;
-               mrd[i].vbase = __EH_FRAME_START;
-               mrd[i].len   = __EH_FRAME_END - __EH_FRAME_START;
-               mrd[i].type  = UKPLAT_MEMRT_KERNEL;
-               mrd[i].flags = UKPLAT_MEMRF_READ;
-#if CONFIG_UKPLAT_MEMRNAME
-               strncpy(mrd[i].name, "eh_frame", sizeof(mrd[i].name) - 1);
-#endif
-               *m = &mrd[i];
-               break;
-       case 2: /* eh_frame_hdr */
-               mrd[i].pbase = __EH_FRAME_HDR_START;
-               mrd[i].vbase = __EH_FRAME_HDR_START;
-               mrd[i].len   = __EH_FRAME_HDR_END - __EH_FRAME_HDR_START;
-               mrd[i].type  = UKPLAT_MEMRT_KERNEL;
-               mrd[i].flags = UKPLAT_MEMRF_READ;
-#if CONFIG_UKPLAT_MEMRNAME
-               strncpy(mrd[i].name, "eh_frame_hdr", sizeof(mrd[i].name) - 1);
-#endif
-               *m = &mrd[i];
-               break;
-               break;
-       case 3: /* rodata */
-               mrd[i].pbase = __RODATA;
-               mrd[i].vbase = __RODATA;
-               mrd[i].len   = __ERODATA - __RODATA;
-               mrd[i].type  = UKPLAT_MEMRT_KERNEL;
-               mrd[i].flags = UKPLAT_MEMRF_READ;
-#if CONFIG_UKPLAT_MEMRNAME
-               strncpy(mrd[i].name, "rodata", sizeof(mrd[i].name) - 1);
-#endif
-               *m = &mrd[i];
-               break;
-       case 4: /* ctors */
-               mrd[i].pbase = __CTORS;
-               mrd[i].vbase = __CTORS;
-               mrd[i].len   = __ECTORS - __CTORS;
-               mrd[i].type  = UKPLAT_MEMRT_KERNEL;
-               mrd[i].flags = UKPLAT_MEMRF_READ;
-#if CONFIG_UKPLAT_MEMRNAME
-               strncpy(mrd[i].name, "ctors", sizeof(mrd[i].name) - 1);
-#endif
-               *m = &mrd[i];
-               break;
-       case 5: /* data */
-               mrd[i].pbase = __DATA;
-               mrd[i].vbase = __DATA;
-               mrd[i].len   = __EDATA - __DATA;
-               mrd[i].type  = UKPLAT_MEMRT_KERNEL;
-               mrd[i].flags = UKPLAT_MEMRF_READ | UKPLAT_MEMRF_WRITE;
-#if CONFIG_UKPLAT_MEMRNAME
-               strncpy(mrd[i].name, "data", sizeof(mrd[i].name) - 1);
-#endif
-               *m = &mrd[i];
-               break;
-       case 6: /* bss */
-               mrd[i].pbase = __BSS_START;
-               mrd[i].len   = __END - __BSS_START;
-               mrd[i].type  = UKPLAT_MEMRT_KERNEL;
-               mrd[i].flags = UKPLAT_MEMRF_READ | UKPLAT_MEMRF_WRITE;
-#if CONFIG_UKPLAT_MEMRNAME
-               strncpy(mrd[i].name, "bss", sizeof(mrd[i].name) - 1);
-#endif
-               *m = &mrd[i];
-               break;
-       case 7: /* heap */
-               mrd[i].pbase = _libkvmplat_cfg.heap.start;
-               mrd[i].vbase = _libkvmplat_cfg.heap.start;
-               mrd[i].len   = _libkvmplat_cfg.heap.len;
-               mrd[i].type  = UKPLAT_MEMRT_FREE;
-               mrd[i].flags = 0;
-#if CONFIG_UKPLAT_MEMRNAME
-               strncpy(mrd[i].name, "heap", sizeof(mrd[i].name) - 1);
-#endif
-               *m = &mrd[i];
-               break;
-       case 8: /* stack */
-               mrd[i].pbase = _libkvmplat_cfg.bstack.start;
-               mrd[i].vbase = _libkvmplat_cfg.bstack.start;
-               mrd[i].len   = _libkvmplat_cfg.bstack.len;
-               mrd[i].type  = UKPLAT_MEMRT_STACK;
-               mrd[i].flags = UKPLAT_MEMRF_READ | UKPLAT_MEMRF_WRITE;
-#if CONFIG_UKPLAT_MEMRNAME
-               strncpy(mrd[i].name, "bstack", sizeof(mrd[i].name) - 1);
-#endif
-               *m = &mrd[i];
-               break;
-       case 9: /* initrd */
-               if (_libkvmplat_cfg.initrd.len) {
-                       mrd[i].pbase = _libkvmplat_cfg.initrd.start;
-                       mrd[i].vbase = _libkvmplat_cfg.initrd.start;
-                       mrd[i].len   = _libkvmplat_cfg.initrd.len;
-                       mrd[i].type  = UKPLAT_MEMRT_INITRD;
-                       mrd[i].flags = UKPLAT_MEMRF_READ | UKPLAT_MEMRF_WRITE;
-#if CONFIG_UKPLAT_MEMRNAME
-                       strncpy(mrd[i].name, "initrd", sizeof(mrd[i].name) - 1);
-#endif
-                       *m = &mrd[i];
-                       break;
-               }
-               /* fall-through */
-       case 10: /* heap2
-                 * NOTE: heap2 could only exist if initrd was there,
-                 * otherwise we fall through
-                 */
-               if (_libkvmplat_cfg.initrd.len && _libkvmplat_cfg.heap2.len) {
-                       mrd[i].pbase = _libkvmplat_cfg.heap2.start;
-                       mrd[i].vbase = _libkvmplat_cfg.heap2.start;
-                       mrd[i].len   = _libkvmplat_cfg.heap2.len;
-                       mrd[i].type  = UKPLAT_MEMRT_FREE;
-                       mrd[i].flags = 0;
-#if CONFIG_UKPLAT_MEMRNAME
-                       strncpy(mrd[i].name, "heap", sizeof(mrd[i].name) - 1);
-#endif
-                       *m = &mrd[i];
-                       break;
-               }
-               /* fall-through */
-       default:
-               return -1;
-       }
-
-       return 0;
-}
-
-int _ukplat_mem_mappings_init(void)
-{
-       return 0;
-}
index 6cd8b671fa2011e4d7e9814f7b89e63ffdce0e05..a4821d03000ce2c9667bf95450faf3116887de40 100644 (file)
@@ -1,8 +1,10 @@
 /* SPDX-License-Identifier: ISC */
 /*
  * Authors: Wei Chen <Wei.Chen@arm.com>
+ *          Sergiu Moga <sergiu.moga@protonmail.com>
  *
  * Copyright (c) 2018 Arm Ltd.
+ * Copyright (c) 2023 University Politehnica of Bucharest.
  *
  * Permission to use, copy, modify, and/or distribute this software
  * for any purpose with or without fee is hereby granted, provided
 #include <uk/config.h>
 #include <libfdt.h>
 #include <uk/plat/common/sections.h>
+#include <uk/plat/common/bootinfo.h>
+#include <uk/plat/lcpu.h>
+#include <uk/plat/common/lcpu.h>
 #include <uart/pl011.h>
 #ifdef CONFIG_RTC_PL031
 #include <rtc/pl031.h>
 #endif /* CONFIG_RTC_PL031 */
-#include <kvm/config.h>
 #include <uk/assert.h>
 #include <kvm/intctrl.h>
 #include <arm/cpu.h>
 #include <arm/arm64/cpu.h>
 #include <arm/smccc.h>
 #include <uk/arch/limits.h>
-#include <uk/arch/paging.h>
 
 #ifdef CONFIG_ARM64_FEAT_PAUTH
 #include <arm/arm64/pauth.h>
 #include <uk/arch/memtag.h>
 #endif /* CONFIG_HAVE_MEMTAG */
 
-#ifdef CONFIG_PAGING
-#include <uk/plat/paging.h>
-#include <uk/plat/common/w_xor_x.h>
-#include <uk/falloc.h>
-
-struct uk_pagetable kernel_pt;
-#endif /* CONFIG_PAGING */
-
-struct kvmplat_config _libkvmplat_cfg = { 0 };
-
-#define MAX_CMDLINE_SIZE 1024
-static char cmdline[MAX_CMDLINE_SIZE];
-static const char *appname = CONFIG_UK_NAME;
-
 smccc_conduit_fn_t smccc_psci_call;
 
-#define _libkvmplat_newstack(sp) ({                            \
-       __asm__ __volatile__("mov sp, %0\n" ::"r" (sp));        \
-})
-
-static void _init_dtb(void *dtb_pointer)
-{
-       int ret;
-
-       if ((ret = fdt_check_header(dtb_pointer)))
-               UK_CRASH("Invalid DTB: %s\n", fdt_strerror(ret));
-
-       _libkvmplat_cfg.dtb = dtb_pointer;
-       uk_pr_info("Found device tree on: %p\n", dtb_pointer);
-}
-
-static void _dtb_get_psci_method(void)
+static void _dtb_get_psci_method(void *fdt)
 {
        int fdtpsci, len;
        const char *fdtmethod;
@@ -82,10 +56,10 @@ static void _dtb_get_psci_method(void)
         * We just support PSCI-0.2 and PSCI-1.0, the PSCI-0.1 would not
         * be supported.
         */
-       fdtpsci = fdt_node_offset_by_compatible(_libkvmplat_cfg.dtb,
-                                               -1, "arm,psci-1.0");
+       fdtpsci = fdt_node_offset_by_compatible(fdt, -1,
+                                               "arm,psci-1.0");
        if (fdtpsci < 0)
-               fdtpsci = fdt_node_offset_by_compatible(_libkvmplat_cfg.dtb,
+               fdtpsci = fdt_node_offset_by_compatible(fdt,
                                                        -1, "arm,psci-0.2");
 
        if (fdtpsci < 0) {
@@ -93,7 +67,7 @@ static void _dtb_get_psci_method(void)
                goto enomethod;
        }
 
-       fdtmethod = fdt_getprop(_libkvmplat_cfg.dtb, fdtpsci, "method", &len);
+       fdtmethod = fdt_getprop(fdt, fdtpsci, "method", &len);
        if (!fdtmethod || (len <= 0)) {
                uk_pr_info("No PSCI method found\n");
                goto enomethod;
@@ -116,252 +90,117 @@ enomethod:
        smccc_psci_call = NULL;
 }
 
-static void _init_dtb_mem(void)
+static char *cmdline;
+static __sz cmdline_len;
+
+static inline int cmdline_init(struct ukplat_bootinfo *bi)
 {
-       int fdt_mem, prop_len = 0, prop_min_len;
-       int naddr, nsize;
-       const uint64_t *regs;
-       uint64_t mem_base, mem_size, max_addr;
-
-       /* search for assigned VM memory in DTB */
-       if (fdt_num_mem_rsv(_libkvmplat_cfg.dtb) != 0)
-               uk_pr_warn("Reserved memory is not supported\n");
-
-       fdt_mem = fdt_node_offset_by_prop_value(_libkvmplat_cfg.dtb, -1,
-                                               "device_type",
-                                               "memory", sizeof("memory"));
-       if (fdt_mem < 0) {
-               uk_pr_warn("No memory found in DTB\n");
-               return;
+       char *cmdl;
+
+       if (bi->cmdline_len) {
+               cmdl = (char *)bi->cmdline;
+               cmdline_len = bi->cmdline_len;
+       } else {
+               cmdl = CONFIG_UK_NAME;
+               cmdline_len = sizeof(CONFIG_UK_NAME) - 1;
        }
 
-       naddr = fdt_address_cells(_libkvmplat_cfg.dtb, fdt_mem);
-       if (naddr < 0 || naddr >= FDT_MAX_NCELLS)
-               UK_CRASH("Could not find proper address cells!\n");
-
-       nsize = fdt_size_cells(_libkvmplat_cfg.dtb, fdt_mem);
-       if (nsize < 0 || nsize >= FDT_MAX_NCELLS)
-               UK_CRASH("Could not find proper size cells!\n");
-
-       /*
-        * QEMU will always provide us at least one bank of memory.
-        * unikraft will use the first bank for the time-being.
+       /* This is not the original command-line, but one that will be thrashed
+        * by `ukplat_entry_argp` to obtain argc/argv. So mark it as a kernel
+        * resource instead.
         */
-       regs = fdt_getprop(_libkvmplat_cfg.dtb, fdt_mem, "reg", &prop_len);
+       cmdline = ukplat_memregion_alloc(cmdline_len + 1, UKPLAT_MEMRT_KERNEL,
+                                        UKPLAT_MEMRF_READ |
+                                        UKPLAT_MEMRF_WRITE |
+                                        UKPLAT_MEMRF_MAP);
+       if (unlikely(!cmdline))
+               return -ENOMEM;
 
-       /*
-        * The property must contain at least the start address
-        * and size, each of which is 8-bytes.
-        */
-       prop_min_len = (int)sizeof(fdt32_t) * (naddr + nsize);
-       if (regs == NULL || prop_len < prop_min_len)
-               UK_CRASH("Bad 'reg' property: %p %d\n", regs, prop_len);
-
-       /* If we have more than one memory bank, give a warning messasge */
-       if (prop_len > prop_min_len)
-               uk_pr_warn("Currently, we support only one memory bank!\n");
-
-       mem_base = fdt64_to_cpu(regs[0]);
-       mem_size = fdt64_to_cpu(regs[1]);
-       if (mem_base > __TEXT)
-               UK_CRASH("Fatal: Image outside of RAM\n");
-
-       max_addr = mem_base + mem_size;
-
-       /* AArch64 require stack be 16-bytes alignment by default */
-       _libkvmplat_cfg.bstack.end   = ALIGN_DOWN(max_addr,
-                                                 __STACK_ALIGN_SIZE);
-       _libkvmplat_cfg.bstack.len   = ALIGN_UP(__STACK_SIZE,
-                                               __STACK_ALIGN_SIZE);
-       _libkvmplat_cfg.bstack.start = _libkvmplat_cfg.bstack.end
-                                      - _libkvmplat_cfg.bstack.len;
-
-       _libkvmplat_cfg.heap.start = PAGE_ALIGN_DOWN((uintptr_t)__END);
-       _libkvmplat_cfg.heap.end   = _libkvmplat_cfg.bstack.start;
-       _libkvmplat_cfg.heap.len   = _libkvmplat_cfg.heap.end
-                                    - _libkvmplat_cfg.heap.start;
-
-       if (_libkvmplat_cfg.heap.start > _libkvmplat_cfg.heap.end)
-               UK_CRASH("Not enough memory, giving up...\n");
-}
-
-static void _dtb_get_cmdline(char *cmdline, size_t maxlen)
-{
-       int fdtchosen, len;
-       const char *fdtcmdline;
-
-       /* TODO: Proper error handling */
-       fdtchosen = fdt_path_offset(_libkvmplat_cfg.dtb, "/chosen");
-       if (!fdtchosen)
-               goto enocmdl;
-       fdtcmdline = fdt_getprop(_libkvmplat_cfg.dtb, fdtchosen, "bootargs",
-                                &len);
-       if (!fdtcmdline || (len <= 0))
-               goto enocmdl;
-
-       if (likely(maxlen >= (unsigned int)len))
-               maxlen = len;
-       else
-               uk_pr_err("Command line too long, truncated\n");
-
-       strncpy(cmdline, fdtcmdline, maxlen);
-       /* ensure null termination */
-       cmdline[maxlen - 1] = '\0';
-
-       uk_pr_info("Command line: %s\n", cmdline);
-       return;
+       memcpy(cmdline, cmdl, cmdline_len);
+       cmdline[cmdline_len] = 0;
 
-enocmdl:
-       uk_pr_info("No command line found\n");
+       return 0;
 }
 
-#ifdef CONFIG_PAGING
-
-int _init_paging(void)
+static void __noreturn _ukplat_entry2(void)
 {
-       int rc;
-       uint64_t start;
-       uint64_t len;
-       unsigned long frames;
-       unsigned long attr;
-       __sz free_memory, res_memory;
-
-       /* Assign all available memory beyond the boot stack
-        * to the frame allocator.
-        */
-       start = ALIGN_UP(__END + __STACK_SIZE, PAGE_SIZE);
-       len   = _libkvmplat_cfg.bstack.end - start;
-
-       rc = ukplat_pt_init(&kernel_pt, start, len);
-       if (unlikely(rc))
-               return rc;
+       ukplat_entry_argp(NULL, cmdline, cmdline_len);
 
-       /* Switch to the new page tables */
-       rc = ukplat_pt_set_active(&kernel_pt);
-       if (unlikely(rc))
-               return rc;
-
-       /* Unmap all available memory */
-       rc = ukplat_page_unmap(&kernel_pt, start, len >> PAGE_SHIFT,
-                              PAGE_FLAG_KEEP_FRAMES);
-       if (unlikely(rc))
-               return rc;
-
-       /* Reserve memory for the new pagetables that will be created
-        * by the frame allocator for new mappings. Assume the worst
-        * case, that is page size.
-        */
-       free_memory = len;
-       frames = free_memory >> PAGE_SHIFT;
-
-       res_memory = _libkvmplat_cfg.bstack.len;        /* boot stack */
-       res_memory += PT_PAGES(frames) << PAGE_SHIFT;   /* page tables */
-
-       /* Map the heap after the boot stack */
-       _libkvmplat_cfg.heap.start = start;
-       _libkvmplat_cfg.heap.end   = _libkvmplat_cfg.heap.start +
-                                    free_memory - res_memory;
-
-       _libkvmplat_cfg.heap.len   = _libkvmplat_cfg.heap.end -
-                                    _libkvmplat_cfg.heap.start;
-
-       frames = _libkvmplat_cfg.heap.len >> PAGE_SHIFT;
-       attr = PAGE_ATTR_PROT_RW | PAGE_ATTR_TYPE_NORMAL_WB_TAGGED;
-       rc = ukplat_page_map(&kernel_pt, _libkvmplat_cfg.heap.start,
-                            __PADDR_ANY, frames, attr, 0);
-       if (unlikely(rc))
-               return rc;
-
-       /* Map the stack right after the heap */
-       _libkvmplat_cfg.bstack.start = _libkvmplat_cfg.heap.end;
-       _libkvmplat_cfg.bstack.end   = _libkvmplat_cfg.heap.end +
-                                      _libkvmplat_cfg.bstack.len;
-
-       frames = _libkvmplat_cfg.bstack.len >> PAGE_SHIFT;
-       rc = ukplat_page_map(&kernel_pt, _libkvmplat_cfg.bstack.start,
-                            __PADDR_ANY, frames, PAGE_ATTR_PROT_RW, 0);
-       if (unlikely(rc))
-               return rc;
-
-       return 0;
+       ukplat_lcpu_halt();
 }
-#endif /* CONFIG_PAGING */
 
-void __no_pauth _libkvmplat_start(void *dtb_pointer)
+void __no_pauth _ukplat_entry(struct ukplat_bootinfo *bi)
 {
-       int ret;
+       void *bstack;
+       void *fdt;
+       int rc;
 
-       _init_dtb(dtb_pointer);
+       fdt = (void *)bi->dtb;
 
-       pl011_console_init(dtb_pointer);
+       pl011_console_init(fdt);
 
-       uk_pr_info("Entering from KVM (arm64)...\n");
+       rc = cmdline_init(bi);
+       if (unlikely(rc < 0))
+               UK_CRASH("Failed to initialize command-line\n");
 
-       /* Get command line from DTB */
-       _dtb_get_cmdline(cmdline, sizeof(cmdline));
+       /* Allocate boot stack */
+       bstack = ukplat_memregion_alloc(__STACK_SIZE, UKPLAT_MEMRT_STACK,
+                                       UKPLAT_MEMRF_READ |
+                                       UKPLAT_MEMRF_WRITE |
+                                       UKPLAT_MEMRF_MAP);
+       if (unlikely(!bstack))
+               UK_CRASH("Boot stack alloc failed\n");
+       bstack = (void *)((__uptr)bstack + __STACK_SIZE);
 
        /* Get PSCI method from DTB */
-       _dtb_get_psci_method();
+       _dtb_get_psci_method(fdt);
 
-       /* Initialize memory from DTB */
-       _init_dtb_mem();
-
-#ifdef CONFIG_PAGING
        /* Initialize paging */
-       ret = _init_paging();
-       if (unlikely(ret))
-               UK_CRASH("Could not initialize paging (%d)\n", ret);
-#ifdef CONFIG_ENFORCE_W_XOR_X
+       rc = ukplat_mem_init();
+       if (unlikely(rc))
+               UK_CRASH("Could not initialize paging (%d)\n", rc);
+
+#if defined(CONFIG_ENFORCE_W_XOR_X) && defined(CONFIG_PAGING)
        enforce_w_xor_x();
-#endif /* CONFIG_ENFORCE_W_XOR_X */
-#endif /* CONFIG_PAGING */
+#endif /* CONFIG_ENFORCE_W_XOR_X && CONFIG_PAGING */
 
 #ifdef CONFIG_ARM64_FEAT_PAUTH
-       ret = ukplat_pauth_init();
-       if (unlikely(ret))
-               UK_CRASH("Could not initialize PAuth (%d)\n", ret);
+       rc = ukplat_pauth_init();
+       if (unlikely(rc))
+               UK_CRASH("Could not initialize PAuth (%d)\n", rc);
 #endif /* CONFIG_ARM64_FEAT_PAUTH */
 
 #ifdef CONFIG_HAVE_MEMTAG
-       ret = ukarch_memtag_init();
-       if (unlikely(ret))
-               UK_CRASH("Could not initialize MTE (%d)\n", ret);
+       rc = ukarch_memtag_init();
+       if (unlikely(rc))
+               UK_CRASH("Could not initialize MTE (%d)\n", rc);
 #endif /* CONFIG_HAVE_MEMTAG */
 
 #ifdef CONFIG_RTC_PL031
        /* Initialize RTC */
-       pl031_init_rtc(dtb_pointer);
+       pl031_init_rtc(fdt);
 #endif /* CONFIG_RTC_PL031 */
 
        /* Initialize interrupt controller */
        intctrl_init();
 
        /* Initialize logical boot CPU */
-       ret = lcpu_init(lcpu_get_bsp());
-       if (unlikely(ret))
-               UK_CRASH("Failed to initialize bootstrapping CPU: %d\n", ret);
+       rc = lcpu_init(lcpu_get_bsp());
+       if (unlikely(rc))
+               UK_CRASH("Failed to initialize bootstrapping CPU: %d\n", rc);
 
 #ifdef CONFIG_HAVE_SMP
-       ret = lcpu_mp_init(CONFIG_UKPLAT_LCPU_RUN_IRQ,
-                          CONFIG_UKPLAT_LCPU_WAKEUP_IRQ,
-                          _libkvmplat_cfg.dtb);
-       if (unlikely(ret))
-               UK_CRASH("SMP initialization failed: %d.\n", ret);
+       rc = lcpu_mp_init(CONFIG_UKPLAT_LCPU_RUN_IRQ,
+                         CONFIG_UKPLAT_LCPU_WAKEUP_IRQ,
+                         fdt);
+       if (unlikely(rc))
+               UK_CRASH("SMP initialization failed: %d.\n", rc);
 #endif /* CONFIG_HAVE_SMP */
 
-       uk_pr_info("     heap start: %p\n",
-                  (void *) _libkvmplat_cfg.heap.start);
-       uk_pr_info("      stack top: %p\n",
-                  (void *) _libkvmplat_cfg.bstack.start);
-
        /*
         * Switch away from the bootstrap stack as early as possible.
         */
-       uk_pr_info("Switch from bootstrap stack to stack @%p\n",
-                  (void *) _libkvmplat_cfg.bstack.end);
-
-       _libkvmplat_newstack(_libkvmplat_cfg.bstack.end);
+       uk_pr_info("Switch from bootstrap stack to stack @%p\n", bstack);
 
-       ukplat_entry_argp(DECONST(char *, appname),
-                         (char *)cmdline, strlen(cmdline));
+       lcpu_arch_jump_to(bstack, _ukplat_entry2);
 }