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"
#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>
};
static uint32_t timer_irq;
+static void *dtb;
void generic_timer_mask_irq(void)
{
* 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");
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).
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");
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");
#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>
__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
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;
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;
* 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) {
*/
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);
/* 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;
}
}
/* 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;
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;
/* 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;
__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,
- ®_base, ®_size);
+ fdt_get_address(dtb, gen_pci_fdt, 0,
+ ®_base, ®_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]);
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;
#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;
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");
#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>
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;
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,
- ®_base, ®_size);
+ fdt_get_address(dtb, fdt_vm, 0, ®_base, ®_size);
}
pfdev->base = reg_base;
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
* 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
/* 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)
#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;
+++ /dev/null
-/* 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;
-}
/* 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;
* 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) {
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;
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);
}