From patchwork Sat Mar 14 00:11:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Atish Patra X-Patchwork-Id: 243628 List-Id: U-Boot discussion From: atish.patra at wdc.com (Atish Patra) Date: Fri, 13 Mar 2020 17:11:29 -0700 Subject: [PATCH v2 1/4] riscv: Add boot hartid to Device tree In-Reply-To: <20200314001132.17393-1-atish.patra@wdc.com> References: <20200314001132.17393-1-atish.patra@wdc.com> Message-ID: <20200314001132.17393-2-atish.patra@wdc.com> Linux booting protocol mandates that register "a0" contains the hartid. However, U-boot can not pass the hartid via a0 during via standard UEFI protocol. DT nodes are commonly used to pass such information to the OS. Add a DT node under chosen node to indicate the boot hartid. EFI stub in Linux kernel will parse this node and pass it to the real kernel in "a0" before jumping to it. Signed-off-by: Atish Patra Reviewed-by: Rick Chen --- arch/riscv/lib/bootm.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c index fad16901c5f2..f927694ae32f 100644 --- a/arch/riscv/lib/bootm.c +++ b/arch/riscv/lib/bootm.c @@ -28,6 +28,28 @@ __weak void board_quiesce_devices(void) int arch_fixup_fdt(void *blob) { + u32 size; + int chosen_offset, err; + + size = fdt_totalsize(blob); + err = fdt_open_into(blob, blob, size + 32); + if (err < 0) { + printf("Device Tree can't be expanded to accommodate new node"); + return -1; + } + chosen_offset = fdt_path_offset(blob, "/chosen"); + if (chosen_offset < 0) { + err = fdt_add_subnode(blob, 0, "chosen"); + if (err < 0) { + printf("chosen node can not be added\n"); + return -1; + } + } + + /* Overwrite the boot-hartid as U-Boot is the last state BL */ + fdt_setprop_u32(blob, chosen_offset, "boot-hartid", + gd->arch.boot_hart); + return 0; } From patchwork Sat Mar 14 00:11:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Atish Patra X-Patchwork-Id: 243626 List-Id: U-Boot discussion From: atish.patra at wdc.com (Atish Patra) Date: Fri, 13 Mar 2020 17:11:30 -0700 Subject: [PATCH v2 2/4] cmd: bootefi: Parse reserved-memory node from DT In-Reply-To: <20200314001132.17393-1-atish.patra@wdc.com> References: <20200314001132.17393-1-atish.patra@wdc.com> Message-ID: <20200314001132.17393-3-atish.patra@wdc.com> Currently, bootefi only parses memory reservation block to setup EFI reserved memory mappings. However, it doesn't parse the reserved-memory[1] device tree node that also can contain the reserved memory regions. Add capability to parse reserved-memory node and update the EFI memory mappings accordingly. 1. /doc/device-tree-bindings/reserved-memory/reserved-memory.txt] Signed-off-by: Atish Patra Reviewed-by: Heinrich Schuchardt --- cmd/bootefi.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 24fc42ae898e..43b36fbacfcd 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -149,6 +149,20 @@ done: return ret; } +static void efi_reserve_memory(uint64_t addr, uint64_t size) +{ + uint64_t pages; + + /* Convert from sandbox address space. */ + addr = (uintptr_t)map_sysmem(addr, 0); + pages = efi_size_in_pages(size + (addr & EFI_PAGE_MASK)); + addr &= ~EFI_PAGE_MASK; + if (efi_add_memory_map(addr, pages, EFI_RESERVED_MEMORY_TYPE, + false) != EFI_SUCCESS) + printf("Reserved memory mapping failed addr %llx size %llx\n", + (unsigned long long)addr, (unsigned long long)size); +} + /** * efi_carve_out_dt_rsv() - Carve out DT reserved memory ranges * @@ -161,7 +175,8 @@ done: static void efi_carve_out_dt_rsv(void *fdt) { int nr_rsv, i; - uint64_t addr, size, pages; + uint64_t addr, size; + int nodeoffset, subnode; nr_rsv = fdt_num_mem_rsv(fdt); @@ -169,15 +184,24 @@ static void efi_carve_out_dt_rsv(void *fdt) for (i = 0; i < nr_rsv; i++) { if (fdt_get_mem_rsv(fdt, i, &addr, &size) != 0) continue; + efi_reserve_memory(addr, size); + } - /* Convert from sandbox address space. */ - addr = (uintptr_t)map_sysmem(addr, 0); - - pages = efi_size_in_pages(size + (addr & EFI_PAGE_MASK)); - addr &= ~EFI_PAGE_MASK; - if (efi_add_memory_map(addr, pages, EFI_RESERVED_MEMORY_TYPE, - false) != EFI_SUCCESS) - printf("FDT memrsv map %d: Failed to add to map\n", i); + /* process reserved-memory */ + nodeoffset = fdt_subnode_offset(fdt, 0, "reserved-memory"); + if (nodeoffset >= 0) { + subnode = fdt_first_subnode(fdt, nodeoffset); + while (subnode >= 0) { + /* check if this subnode has a reg property */ + addr = fdtdec_get_addr_size(fdt, subnode, "reg", + (fdt_size_t *)&size); + if (addr == FDT_ADDR_T_NONE) { + debug("failed to read address/size\n"); + continue; + } + efi_reserve_memory(addr, size); + subnode = fdt_next_subnode(fdt, subnode); + } } } From patchwork Sat Mar 14 00:11:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Atish Patra X-Patchwork-Id: 243629 List-Id: U-Boot discussion From: atish.patra at wdc.com (Atish Patra) Date: Fri, 13 Mar 2020 17:11:31 -0700 Subject: [PATCH v2 3/4] riscv: Provide a mechanism for riscv boards to parse reserved memory In-Reply-To: <20200314001132.17393-1-atish.patra@wdc.com> References: <20200314001132.17393-1-atish.patra@wdc.com> Message-ID: <20200314001132.17393-4-atish.patra@wdc.com> In RISC-V, M-mode software can reserve physical memory regions by setting appropriate physical memory protection (PMP) csr. As the PMP csr are accessible only in M-mode, S-mode U-Boot can not read this configuration directly. However, M-mode software can pass this information via reserved-memory node in device tree so that S-mode software can access this information. In U-boot, any board may use the DT in following ways. 1. OF_SEPARTE: It ignores the DT from previous stage and uses the DT from U-Boot sources. 2. OF_PRIOR_STATE: It reuses the DT from previous stage. For case 1: U-Boot needs to parse the reserved-memory node from the DT passed from the previous stage and update the DT in use. This patch provides a framework to do that from any RISC-V boards. Signed-off-by: Atish Patra --- arch/riscv/cpu/start.S | 1 + arch/riscv/include/asm/global_data.h | 1 + arch/riscv/include/asm/u-boot-riscv.h | 1 + arch/riscv/lib/asm-offsets.c | 1 + arch/riscv/lib/bootm.c | 37 +++++++++++++++++++++++++++ 5 files changed, 41 insertions(+) diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S index 6b3ff99c3882..0282685c2906 100644 --- a/arch/riscv/cpu/start.S +++ b/arch/riscv/cpu/start.S @@ -121,6 +121,7 @@ call_board_init_f_0: jal board_init_f_init_reserve + SREG s1, GD_FIRMWARE_FDT_ADDR(gp) /* save the boot hart id to global_data */ SREG tp, GD_BOOT_HART(gp) diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h index b74bd7e738bb..51ac8d1c98e2 100644 --- a/arch/riscv/include/asm/global_data.h +++ b/arch/riscv/include/asm/global_data.h @@ -15,6 +15,7 @@ /* Architecture-specific global data */ struct arch_global_data { long boot_hart; /* boot hart id */ + phys_addr_t firmware_fdt_addr; #ifdef CONFIG_SIFIVE_CLINT void __iomem *clint; /* clint base address */ #endif diff --git a/arch/riscv/include/asm/u-boot-riscv.h b/arch/riscv/include/asm/u-boot-riscv.h index 49febd588102..b7bea0ba184d 100644 --- a/arch/riscv/include/asm/u-boot-riscv.h +++ b/arch/riscv/include/asm/u-boot-riscv.h @@ -17,5 +17,6 @@ int cleanup_before_linux(void); /* board/.../... */ int board_init(void); void board_quiesce_devices(void); +int riscv_board_reserved_mem_fixup(void *fdt); #endif /* _U_BOOT_RISCV_H_ */ diff --git a/arch/riscv/lib/asm-offsets.c b/arch/riscv/lib/asm-offsets.c index 4fa4fd371473..7301c1b98e23 100644 --- a/arch/riscv/lib/asm-offsets.c +++ b/arch/riscv/lib/asm-offsets.c @@ -14,6 +14,7 @@ int main(void) { DEFINE(GD_BOOT_HART, offsetof(gd_t, arch.boot_hart)); + DEFINE(GD_FIRMWARE_FDT_ADDR, offsetof(gd_t, arch.firmware_fdt_addr)); #ifndef CONFIG_XIP DEFINE(GD_AVAILABLE_HARTS, offsetof(gd_t, arch.available_harts)); #endif diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c index f927694ae32f..3a4d0bf14c86 100644 --- a/arch/riscv/lib/bootm.c +++ b/arch/riscv/lib/bootm.c @@ -19,6 +19,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -26,6 +27,42 @@ __weak void board_quiesce_devices(void) { } +int riscv_board_reserved_mem_fixup(void *fdt) +{ + uint32_t phandle; + struct fdt_memory pmp_mem; + int err; + void *src_fdt_addr; + int offset, node; + phys_addr_t addr, size; + + src_fdt_addr = map_sysmem(gd->arch.firmware_fdt_addr, 0); + offset = fdt_path_offset(src_fdt_addr, "/reserved-memory"); + if (offset < 0) { + printf("No reserved memory region found in FDT\n"); + return offset; + } + + fdt_for_each_subnode(node, src_fdt_addr, offset) { + const char *name = fdt_get_name(src_fdt_addr, node, NULL); + + addr = fdtdec_get_addr_size(src_fdt_addr, node, "reg", &size); + if (addr == FDT_ADDR_T_NONE) { + debug("failed to read address/size for %s\n", name); + continue; + } + pmp_mem.start = addr; + pmp_mem.end = addr + size; + err = fdtdec_add_reserved_memory(fdt, name, &pmp_mem, &phandle); + if (err < 0) { + printf("failed to add reserved memory: %d\n", err); + return err; + } + } + + return 0; +} + int arch_fixup_fdt(void *blob) { u32 size; From patchwork Sat Mar 14 00:11:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Atish Patra X-Patchwork-Id: 243627 List-Id: U-Boot discussion From: atish.patra at wdc.com (Atish Patra) Date: Fri, 13 Mar 2020 17:11:32 -0700 Subject: [PATCH v2 4/4] riscv: Setup reserved-memory node for FU540 In-Reply-To: <20200314001132.17393-1-atish.patra@wdc.com> References: <20200314001132.17393-1-atish.patra@wdc.com> Message-ID: <20200314001132.17393-5-atish.patra@wdc.com> FU540 uses OF_SEPARATE instead of OF_PRIOR. Enable OF_BOARD_FIXUP to update the DT with reserved-memory node. Signed-off-by: Atish Patra --- board/sifive/fu540/fu540.c | 15 +++++++++++++++ configs/sifive_fu540_defconfig | 1 + 2 files changed, 16 insertions(+) diff --git a/board/sifive/fu540/fu540.c b/board/sifive/fu540/fu540.c index 47a20902517c..82b3a9c8e729 100644 --- a/board/sifive/fu540/fu540.c +++ b/board/sifive/fu540/fu540.c @@ -141,6 +141,21 @@ int misc_init_r(void) #endif +#ifdef CONFIG_OF_BOARD_FIXUP +int board_fix_fdt(void *fdt) +{ + int err; + + err = riscv_board_reserved_mem_fixup(fdt); + if (err < 0) { + printf("failed to fixup DT for reserved memory: %d\n", err); + return err; + } + + return 0; +} +#endif + int board_init(void) { /* For now nothing to do here. */ diff --git a/configs/sifive_fu540_defconfig b/configs/sifive_fu540_defconfig index 6d61e6c960ee..8fb3794cd578 100644 --- a/configs/sifive_fu540_defconfig +++ b/configs/sifive_fu540_defconfig @@ -12,3 +12,4 @@ CONFIG_DISPLAY_BOARDINFO=y CONFIG_DEFAULT_DEVICE_TREE="hifive-unleashed-a00" CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_DM_MTD=y +CONFIG_OF_BOARD_FIXUP=y