riscv: Provide a mechanism to fix DT for reserved memory
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. This patch provides a framework to copy to the reserved-memory node from one DT to another. This will be used to update the DT used by U-Boot and the DT passed to the next stage OS. Signed-off-by: Atish Patra <atish.patra@wdc.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> Tested-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
		
							parent
							
								
									f614753c4b
								
							
						
					
					
						commit
						d4ea649f17
					
				|  | @ -119,6 +119,7 @@ call_board_init_f_0: | ||||||
| 
 | 
 | ||||||
| 	jal	board_init_f_init_reserve | 	jal	board_init_f_init_reserve | ||||||
| 
 | 
 | ||||||
|  | 	SREG	s1, GD_FIRMWARE_FDT_ADDR(gp) | ||||||
| 	/* save the boot hart id to global_data */ | 	/* save the boot hart id to global_data */ | ||||||
| 	SREG	tp, GD_BOOT_HART(gp) | 	SREG	tp, GD_BOOT_HART(gp) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -15,6 +15,7 @@ | ||||||
| /* Architecture-specific global data */ | /* Architecture-specific global data */ | ||||||
| struct arch_global_data { | struct arch_global_data { | ||||||
| 	long boot_hart;		/* boot hart id */ | 	long boot_hart;		/* boot hart id */ | ||||||
|  | 	phys_addr_t firmware_fdt_addr; | ||||||
| #ifdef CONFIG_SIFIVE_CLINT | #ifdef CONFIG_SIFIVE_CLINT | ||||||
| 	void __iomem *clint;	/* clint base address */ | 	void __iomem *clint;	/* clint base address */ | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -17,5 +17,7 @@ int cleanup_before_linux(void); | ||||||
| /* board/.../... */ | /* board/.../... */ | ||||||
| int board_init(void); | int board_init(void); | ||||||
| void board_quiesce_devices(void); | void board_quiesce_devices(void); | ||||||
|  | int riscv_board_reserved_mem_fixup(void *fdt); | ||||||
|  | int riscv_fdt_copy_resv_mem_node(const void *src_fdt, void *dest_fdt); | ||||||
| 
 | 
 | ||||||
| #endif	/* _U_BOOT_RISCV_H_ */ | #endif	/* _U_BOOT_RISCV_H_ */ | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ obj-y	+= reset.o | ||||||
| obj-y   += setjmp.o | obj-y   += setjmp.o | ||||||
| obj-$(CONFIG_$(SPL_)SMP) += smp.o | obj-$(CONFIG_$(SPL_)SMP) += smp.o | ||||||
| obj-$(CONFIG_SPL_BUILD)	+= spl.o | obj-$(CONFIG_SPL_BUILD)	+= spl.o | ||||||
|  | obj-y   += fdt_fixup.o | ||||||
| 
 | 
 | ||||||
| # For building EFI apps
 | # For building EFI apps
 | ||||||
| CFLAGS_$(EFI_CRT0) := $(CFLAGS_EFI) | CFLAGS_$(EFI_CRT0) := $(CFLAGS_EFI) | ||||||
|  |  | ||||||
|  | @ -14,6 +14,7 @@ | ||||||
| int main(void) | int main(void) | ||||||
| { | { | ||||||
| 	DEFINE(GD_BOOT_HART, offsetof(gd_t, arch.boot_hart)); | 	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 | #ifndef CONFIG_XIP | ||||||
| 	DEFINE(GD_AVAILABLE_HARTS, offsetof(gd_t, arch.available_harts)); | 	DEFINE(GD_AVAILABLE_HARTS, offsetof(gd_t, arch.available_harts)); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -0,0 +1,102 @@ | ||||||
|  | // SPDX-License-Identifier: GPL-2.0+
 | ||||||
|  | /*
 | ||||||
|  |  * Copyright (c) 2020 Western Digital Corporation or its affiliates | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <common.h> | ||||||
|  | #include <fdt_support.h> | ||||||
|  | #include <mapmem.h> | ||||||
|  | 
 | ||||||
|  | DECLARE_GLOBAL_DATA_PTR; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * riscv_fdt_copy_resv_mem_node() - Copy reserve memory node entry | ||||||
|  |  * @src: Pointer to the source device tree from which reserved memory node | ||||||
|  |  *	 needs to be copied. | ||||||
|  |  * @dst: Pointer to the destination device tree to which reserved memory node | ||||||
|  |  *	 needs to be copied. | ||||||
|  |  * | ||||||
|  |  * Return: 0 on success or if source doesn't have reserved memory node. | ||||||
|  |  *	   Error if copy process failed. | ||||||
|  |  */ | ||||||
|  | int riscv_fdt_copy_resv_mem_node(const void *src, void *dst) | ||||||
|  | { | ||||||
|  | 	u32 phandle; | ||||||
|  | 	struct fdt_memory pmp_mem; | ||||||
|  | 	fdt_addr_t addr; | ||||||
|  | 	fdt_size_t size; | ||||||
|  | 	int offset, node, err, rmem_offset; | ||||||
|  | 	bool nomap = true; | ||||||
|  | 	char basename[32] = {0}; | ||||||
|  | 	int bname_len; | ||||||
|  | 	int max_len = sizeof(basename); | ||||||
|  | 	const char *name; | ||||||
|  | 	char *temp; | ||||||
|  | 
 | ||||||
|  | 	offset = fdt_path_offset(src, "/reserved-memory"); | ||||||
|  | 	if (offset < 0) { | ||||||
|  | 		printf("No reserved memory region found in source FDT\n"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	fdt_for_each_subnode(node, src, offset) { | ||||||
|  | 		name = fdt_get_name(src, node, NULL); | ||||||
|  | 
 | ||||||
|  | 		addr = fdtdec_get_addr_size_auto_noparent(src, node, | ||||||
|  | 							  "reg", 0, &size, | ||||||
|  | 							  false); | ||||||
|  | 		if (addr == FDT_ADDR_T_NONE) { | ||||||
|  | 			debug("failed to read address/size for %s\n", name); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		strncpy(basename, name, max_len); | ||||||
|  | 		temp = strchr(basename, '@'); | ||||||
|  | 		if (temp) { | ||||||
|  | 			bname_len = strnlen(basename, max_len) - strnlen(temp, | ||||||
|  | 								       max_len); | ||||||
|  | 			*(basename + bname_len) = '\0'; | ||||||
|  | 		} | ||||||
|  | 		pmp_mem.start = addr; | ||||||
|  | 		pmp_mem.end = addr + size - 1; | ||||||
|  | 		err = fdtdec_add_reserved_memory(dst, basename, &pmp_mem, | ||||||
|  | 						 &phandle); | ||||||
|  | 		if (err < 0) { | ||||||
|  | 			printf("failed to add reserved memory: %d\n", err); | ||||||
|  | 			return err; | ||||||
|  | 		} | ||||||
|  | 		if (!fdt_getprop(src, node, "no-map", NULL)) | ||||||
|  | 			nomap = false; | ||||||
|  | 		if (nomap) { | ||||||
|  | 			rmem_offset = fdt_node_offset_by_phandle(dst, phandle); | ||||||
|  | 			fdt_setprop_empty(dst, rmem_offset, "no-map"); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * riscv_board_reserved_mem_fixup() - Fix up reserved memory node for a board | ||||||
|  |  * @fdt: Pointer to the device tree in which reserved memory node needs to be | ||||||
|  |  *	 added. | ||||||
|  |  * | ||||||
|  |  * In RISC-V, any board compiled with OF_SEPARATE needs to copy the reserved | ||||||
|  |  * memory node from the device tree provided by the firmware to the device tree | ||||||
|  |  * used by U-Boot. This is a common function that individual board fixup | ||||||
|  |  * functions can invoke. | ||||||
|  |  * | ||||||
|  |  * Return: 0 on success or error otherwise. | ||||||
|  |  */ | ||||||
|  | int riscv_board_reserved_mem_fixup(void *fdt) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 	void *src_fdt_addr; | ||||||
|  | 
 | ||||||
|  | 	src_fdt_addr = map_sysmem(gd->arch.firmware_fdt_addr, 0); | ||||||
|  | 	err = riscv_fdt_copy_resv_mem_node(src_fdt_addr, fdt); | ||||||
|  | 	if (err < 0) | ||||||
|  | 		return err; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue