From aa29b21d62d298fadcfbc8e36d8d248fbb24b52d Mon Sep 17 00:00:00 2001 From: Chia-Wei Wang Date: Tue, 3 Aug 2021 10:50:09 +0800 Subject: [PATCH 01/18] arm: Fix option dependency with Kconfig language Use Kconfig 'depends on' instead of #if macro to express the option depdencies. Signed-off-by: Chia-Wei Wang --- arch/arm/Kconfig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c815ad461a..31ae2950ee 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -9,9 +9,9 @@ config ARM64 select PHYS_64BIT select SYS_CACHE_SHIFT_6 -if ARM64 config POSITION_INDEPENDENT bool "Generate position-independent pre-relocation code" + depends on ARM64 help U-Boot expects to be linked to a specific hard-coded address, and to be loaded to and run from that address. This option lifts that @@ -22,6 +22,7 @@ config POSITION_INDEPENDENT config INIT_SP_RELATIVE bool "Specify the early stack pointer relative to the .bss section" + depends on ARM64 default n if ARCH_QEMU default y if POSITION_INDEPENDENT help @@ -37,6 +38,7 @@ config INIT_SP_RELATIVE config SYS_INIT_SP_BSS_OFFSET int "Early stack offset from the .bss base address" + depends on ARM64 depends on INIT_SP_RELATIVE default 524288 help @@ -46,6 +48,7 @@ config SYS_INIT_SP_BSS_OFFSET do not overlap any appended DTB. config LINUX_KERNEL_IMAGE_HEADER + depends on ARM64 bool help Place a Linux kernel image header at the start of the U-Boot binary. @@ -54,14 +57,12 @@ config LINUX_KERNEL_IMAGE_HEADER image header reports the amount of memory (BSS and similar) that U-Boot needs to use, but which isn't part of the binary. -if LINUX_KERNEL_IMAGE_HEADER config LNX_KRNL_IMG_TEXT_OFFSET_BASE + depends on LINUX_KERNEL_IMAGE_HEADER hex help The value subtracted from CONFIG_SYS_TEXT_BASE to calculate the TEXT_OFFSET value written to the Linux kernel image header. -endif -endif config GICV2 bool From cd82f199852d88218e1f17f5ec07cdd9112a89c4 Mon Sep 17 00:00:00 2001 From: Chia-Wei Wang Date: Tue, 3 Aug 2021 10:50:10 +0800 Subject: [PATCH 02/18] armv7: Add Position Independent Execution support A U-Boot image could be loaded and executed at a different location than it was linked at. For example, Aspeed takes a stable release version of U-Boot image as the golden one for recovery purposes. When the primary storage such as flash is corrupted, the golden image would be loaded to any SRAM/DRAM address on demands through ethernet/UART/etc and run for rescue. To deal with this condition, the PIE is needed as there is only one signed, golden image, which could be however executed at different places. This patch adds the PIE support for ARMv7 platform. Signed-off-by: Chia-Wei Wang --- arch/arm/Kconfig | 2 +- arch/arm/cpu/armv7/start.S | 43 ++++++++++++++++++++++++++++++++++++++ arch/arm/lib/crt0.S | 11 ++++++++++ arch/arm/lib/relocate.S | 35 ++++++++++++++++++++++--------- 4 files changed, 80 insertions(+), 11 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 31ae2950ee..50efb5e2e2 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -11,7 +11,7 @@ config ARM64 config POSITION_INDEPENDENT bool "Generate position-independent pre-relocation code" - depends on ARM64 + depends on ARM64 || CPU_V7A help U-Boot expects to be linked to a specific hard-coded address, and to be loaded to and run from that address. This option lifts that diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S index 87329d26e1..698e15b8e1 100644 --- a/arch/arm/cpu/armv7/start.S +++ b/arch/arm/cpu/armv7/start.S @@ -39,6 +39,42 @@ reset: /* Allow the board to save important registers */ b save_boot_params save_boot_params_ret: +#ifdef CONFIG_POSITION_INDEPENDENT + /* + * Fix .rela.dyn relocations. This allows U-Boot to loaded to and + * executed at a different address than it was linked at. + */ +pie_fixup: + adr r0, reset /* r0 <- Runtime value of reset label */ + ldr r1, =reset /* r1 <- Linked value of reset label */ + subs r4, r0, r1 /* r4 <- Runtime-vs-link offset */ + beq pie_fixup_done + + adr r0, pie_fixup + ldr r1, _rel_dyn_start_ofs + add r2, r0, r1 /* r2 <- Runtime &__rel_dyn_start */ + ldr r1, _rel_dyn_end_ofs + add r3, r0, r1 /* r3 <- Runtime &__rel_dyn_end */ + +pie_fix_loop: + ldr r0, [r2] /* r0 <- Link location */ + ldr r1, [r2, #4] /* r1 <- fixup */ + cmp r1, #23 /* relative fixup? */ + bne pie_skip_reloc + + /* relative fix: increase location by offset */ + add r0, r4 + ldr r1, [r0] + add r1, r4 + str r1, [r0] + str r0, [r2] + add r2, #8 +pie_skip_reloc: + cmp r2, r3 + blo pie_fix_loop +pie_fixup_done: +#endif + #ifdef CONFIG_ARMV7_LPAE /* * check for Hypervisor support @@ -340,3 +376,10 @@ ENTRY(cpu_init_crit) b lowlevel_init @ go setup pll,mux,memory ENDPROC(cpu_init_crit) #endif + +#if CONFIG_POSITION_INDEPENDENT +_rel_dyn_start_ofs: + .word __rel_dyn_start - pie_fixup +_rel_dyn_end_ofs: + .word __rel_dyn_end - pie_fixup +#endif diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S index 46b6be21a8..956d258c9d 100644 --- a/arch/arm/lib/crt0.S +++ b/arch/arm/lib/crt0.S @@ -130,6 +130,14 @@ ENTRY(_main) ldr r9, [r9, #GD_NEW_GD] /* r9 <- gd->new_gd */ adr lr, here +#if defined(CONFIG_POSITION_INDEPENDENT) + adr r0, _main + ldr r1, _start_ofs + add r0, r1 + ldr r1, =CONFIG_SYS_TEXT_BASE + sub r1, r0 + add lr, r1 +#endif ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */ add lr, lr, r0 #if defined(CONFIG_CPU_V7M) @@ -180,3 +188,6 @@ here: #endif ENDPROC(_main) + +_start_ofs: + .word _start - _main diff --git a/arch/arm/lib/relocate.S b/arch/arm/lib/relocate.S index e5f7267be1..14b7f61c1a 100644 --- a/arch/arm/lib/relocate.S +++ b/arch/arm/lib/relocate.S @@ -78,22 +78,28 @@ ENDPROC(relocate_vectors) */ ENTRY(relocate_code) - ldr r1, =__image_copy_start /* r1 <- SRC &__image_copy_start */ - subs r4, r0, r1 /* r4 <- relocation offset */ - beq relocate_done /* skip relocation */ - ldr r2, =__image_copy_end /* r2 <- SRC &__image_copy_end */ - + adr r3, relocate_code + ldr r1, _image_copy_start_ofs + add r1, r3 /* r1 <- Run &__image_copy_start */ + subs r4, r0, r1 /* r4 <- Run to copy offset */ + beq relocate_done /* skip relocation */ + ldr r1, _image_copy_start_ofs + add r1, r3 /* r1 <- Run &__image_copy_start */ + ldr r2, _image_copy_end_ofs + add r2, r3 /* r2 <- Run &__image_copy_end */ copy_loop: - ldmia r1!, {r10-r11} /* copy from source address [r1] */ - stmia r0!, {r10-r11} /* copy to target address [r0] */ - cmp r1, r2 /* until source end address [r2] */ + ldmia r1!, {r10-r11} /* copy from source address [r1] */ + stmia r0!, {r10-r11} /* copy to target address [r0] */ + cmp r1, r2 /* until source end address [r2] */ blo copy_loop /* * fix .rel.dyn relocations */ - ldr r2, =__rel_dyn_start /* r2 <- SRC &__rel_dyn_start */ - ldr r3, =__rel_dyn_end /* r3 <- SRC &__rel_dyn_end */ + ldr r1, _rel_dyn_start_ofs + add r2, r1, r3 /* r2 <- Run &__rel_dyn_start */ + ldr r1, _rel_dyn_end_ofs + add r3, r1, r3 /* r3 <- Run &__rel_dyn_end */ fixloop: ldmia r2!, {r0-r1} /* (r0,r1) <- (SRC location,fixup) */ and r1, r1, #0xff @@ -129,3 +135,12 @@ relocate_done: #endif ENDPROC(relocate_code) + +_image_copy_start_ofs: + .word __image_copy_start - relocate_code +_image_copy_end_ofs: + .word __image_copy_end - relocate_code +_rel_dyn_start_ofs: + .word __rel_dyn_start - relocate_code +_rel_dyn_end_ofs: + .word __rel_dyn_end - relocate_code From 1eb006249e2fe84e889a89154d71a9cb0093eed8 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Tue, 3 Aug 2021 12:12:37 +0200 Subject: [PATCH 03/18] arm: mach-snapdragon: misc: Initialize eMMC if necessary At the moment U-Boot produces an empty MAC address (02:00:00:00:00:00) if the eMMC is not used by anything in U-Boot (e.g. with CONFIG_ENV_IS_NOWHERE=y instead of having the environment on eMMC). This happens because then there is nothing that actually initializes the eMMC and reads the "cid" that is later accessed. To fix this, call mmc_init() to ensure the eMMC is initialized. There is no functional difference if the eMMC is already initialized since then mmc_init() will just return without doing anything. Reviewed-by: Ramon Fried Signed-off-by: Stephan Gerhold --- arch/arm/mach-snapdragon/misc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/mach-snapdragon/misc.c b/arch/arm/mach-snapdragon/misc.c index 985625a548..fbd5f4d051 100644 --- a/arch/arm/mach-snapdragon/misc.c +++ b/arch/arm/mach-snapdragon/misc.c @@ -33,6 +33,9 @@ u32 msm_board_serial(void) if (!mmc_dev) return 0; + if (mmc_init(mmc_dev)) + return 0; + return UNSTUFF_BITS(mmc_dev->cid, 16, 32); } From 15dd9412027e06f8ce0046e7d8de84489a7f34cb Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Tue, 3 Aug 2021 12:12:38 +0200 Subject: [PATCH 04/18] arm: mach-snapdrgon: misc: Simplify msm_generate_mac_addr() The logic in msm_generate_mac_addr() was originally taken from the LK bootloader where the serial number is a string and must be parsed first. However, in U-Boot msm_board_serial() returns an u32 and msm_generate_mac_addr() has quite complicated code that will first print it as a hex string and then immediately parse it again. What this function actually does at the end is to put the serial number encoded as big endian (the order used for the hex string) into the u8 *mac. Use put_unaligned_be32() to do that with bit shifts instead of going through the string format. This should be slightly more efficient and cleaner but does not result in any functional difference. Cc: Ramon Fried Signed-off-by: Stephan Gerhold Reviewed-by: Ramon Fried --- arch/arm/mach-snapdragon/misc.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-snapdragon/misc.c b/arch/arm/mach-snapdragon/misc.c index fbd5f4d051..7d452f4529 100644 --- a/arch/arm/mach-snapdragon/misc.c +++ b/arch/arm/mach-snapdragon/misc.c @@ -9,6 +9,7 @@ #include #include #include +#include /* UNSTUFF_BITS macro taken from Linux Kernel: drivers/mmc/core/sd.c */ #define UNSTUFF_BITS(resp, start, size) \ @@ -41,16 +42,14 @@ u32 msm_board_serial(void) void msm_generate_mac_addr(u8 *mac) { - int i; - char sn[9]; - - snprintf(sn, 9, "%08x", msm_board_serial()); - - /* fill in the mac with serialno, use locally adminstrated pool */ + /* use locally adminstrated pool */ mac[0] = 0x02; - mac[1] = 00; - for (i = 3; i >= 0; i--) { - mac[i + 2] = hextoul(&sn[2 * i], NULL); - sn[2 * i] = 0; - } + mac[1] = 0x00; + + /* + * Put the 32-bit serial number in the last 32-bit of the MAC address. + * Use big endian order so it is consistent with the serial number + * written as a hexadecimal string, e.g. 0x1234abcd -> 02:00:12:34:ab:cd + */ + put_unaligned_be32(msm_board_serial(), &mac[2]); } From d9d8849183a11814d0b5675de922209b26b713db Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 6 Aug 2021 00:51:46 +0200 Subject: [PATCH 05/18] cmd/part: correct alignment of partition list When running 'part list' for an ISO partition the numbers are not under the labels. Correct the alignment of the ISO partition list. With the patch the output looks like: Part Start Sect x Size Type 1 3720 5024 512 U-Boot Signed-off-by: Heinrich Schuchardt --- disk/part_iso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/disk/part_iso.c b/disk/part_iso.c index 822f2c4d9f..1061f341d3 100644 --- a/disk/part_iso.c +++ b/disk/part_iso.c @@ -220,7 +220,7 @@ static void part_print_iso(struct blk_desc *dev_desc) printf("Part Start Sect x Size Type\n"); i=1; do { - printf(" %2d " LBAFU " " LBAFU " %6ld %.32s\n", + printf(" %2d %8" LBAFlength "u %8" LBAFlength "u %6ld %.32s\n", i, info.start, info.size, info.blksz, info.type); i++; } while (part_get_info_iso_verb(dev_desc, i, &info, 0) != -1); From c8291f53b0523cf1af24dae8a41720fa7e7d035a Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Tue, 17 Aug 2021 12:51:34 +0200 Subject: [PATCH 06/18] lib: add crc16.o if CONFIG_MMC_SPI_CRC_ON for SPL build CONFIG_MMC_SPI_CRC_ON needs the crc16 functions, but it was not included in an SPL build. For non-SPL builds, crc16.o is already added unconditionally. This also removes CONFIG_SPL_YMODEM_SUPPORT from the sifive board configs, which is only relevant for some ARM boards and was only set for its side effect of adding crc16.o. --- configs/sifive_unleashed_defconfig | 1 - configs/sifive_unmatched_defconfig | 1 - lib/Makefile | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/configs/sifive_unleashed_defconfig b/configs/sifive_unleashed_defconfig index cf50101281..be947be9a0 100644 --- a/configs/sifive_unleashed_defconfig +++ b/configs/sifive_unleashed_defconfig @@ -24,7 +24,6 @@ CONFIG_SPL_SEPARATE_BSS=y CONFIG_SPL_DM_SPI_FLASH=y CONFIG_SPL_DM_RESET=y CONFIG_SPL_SPI_LOAD=y -CONFIG_SPL_YMODEM_SUPPORT=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_SPL_CLK=y diff --git a/configs/sifive_unmatched_defconfig b/configs/sifive_unmatched_defconfig index 890d3a01b0..3d478ad3b9 100644 --- a/configs/sifive_unmatched_defconfig +++ b/configs/sifive_unmatched_defconfig @@ -23,7 +23,6 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_ID_EEPROM=y CONFIG_SPL_SEPARATE_BSS=y CONFIG_SPL_DM_RESET=y -CONFIG_SPL_YMODEM_SUPPORT=y CONFIG_CMD_EEPROM=y CONFIG_CMD_MEMINFO=y CONFIG_CMD_PWM=y diff --git a/lib/Makefile b/lib/Makefile index 8ba745faa0..2d29cdad1e 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -88,6 +88,7 @@ endif ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16.o obj-$(CONFIG_$(SPL_TPL_)HASH_SUPPORT) += crc16.o +obj-$(CONFIG_MMC_SPI_CRC_ON) += crc16.o obj-y += net_utils.o endif obj-$(CONFIG_ADDR_MAP) += addr_map.o From 99a2bd65f1662c25b05d2b2fe209a76862159b87 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 19 Aug 2021 22:15:25 +0900 Subject: [PATCH 07/18] Revert "configs: synquacer: Make U-Boot binary position independent" This reverts commit f7e16bb0c5362c9b01d7e6e96bf6c77fd6b3d89e, since the U-Boot doesn't boot if it is booted directly from SPI-NOR with CONFIG_POSITION_INDEPENDENT=y. Unless fixing this issue, it is better to revert this change. Signed-off-by: Masami Hiramatsu --- configs/synquacer_developerbox_defconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configs/synquacer_developerbox_defconfig b/configs/synquacer_developerbox_defconfig index 802f1819e3..a88856b272 100644 --- a/configs/synquacer_developerbox_defconfig +++ b/configs/synquacer_developerbox_defconfig @@ -1,7 +1,6 @@ CONFIG_ARM=y -CONFIG_POSITION_INDEPENDENT=y CONFIG_ARCH_SYNQUACER=y -CONFIG_SYS_TEXT_BASE=0x00000000 +CONFIG_SYS_TEXT_BASE=0x08200000 CONFIG_ENV_SIZE=0x30000 CONFIG_ENV_OFFSET=0x300000 CONFIG_ENV_SECT_SIZE=0x10000 From 53b40e8d54fcdb834e10e6538084517524b8401b Mon Sep 17 00:00:00 2001 From: Peter Hoyes Date: Thu, 19 Aug 2021 16:53:09 +0100 Subject: [PATCH 08/18] armv8: Disable pointer authentication traps for EL1 The use of ARMv8.3 pointer authentication (PAuth) is governed by fields in HCR_EL2, which trigger a 'trap to EL2' if not enabled. The reset value of these fields is 'architecturally unknown' so we must ensure that the fields are enabled (to disable the traps) if we are entering the kernel at EL1. The APK field disables PAuth instruction traps and the API field disables PAuth register traps Add code to disable the traps in armv8_switch_to_el1_m. Prior to doing so, it checks fields in the ID_AA64ISAR1_EL1 register to ensure pointer authentication is supported by the hardware. The runtime checks require a second temporary register, so add this to the EL1 transition macro signature and update 2 call sites. Signed-off-by: Peter Hoyes --- arch/arm/cpu/armv8/fsl-layerscape/spintable.S | 2 +- arch/arm/cpu/armv8/transition.S | 2 +- arch/arm/include/asm/macro.h | 11 +++++++++-- arch/arm/include/asm/system.h | 15 +++++++++++++++ 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/arch/arm/cpu/armv8/fsl-layerscape/spintable.S b/arch/arm/cpu/armv8/fsl-layerscape/spintable.S index 363ded03e6..d6bd188459 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/spintable.S +++ b/arch/arm/cpu/armv8/fsl-layerscape/spintable.S @@ -93,7 +93,7 @@ __secondary_boot_func: 4: #ifdef CONFIG_ARMV8_SWITCH_TO_EL1 switch_el x7, _dead_loop, 0f, _dead_loop -0: armv8_switch_to_el1_m x4, x6, x7 +0: armv8_switch_to_el1_m x4, x6, x7, x9 #else switch_el x7, 0f, _dead_loop, _dead_loop 0: armv8_switch_to_el2_m x4, x6, x7 diff --git a/arch/arm/cpu/armv8/transition.S b/arch/arm/cpu/armv8/transition.S index a31af4ffc8..9dbdff3a4f 100644 --- a/arch/arm/cpu/armv8/transition.S +++ b/arch/arm/cpu/armv8/transition.S @@ -40,7 +40,7 @@ ENTRY(armv8_switch_to_el1) * now, jump to the address saved in x4. */ br x4 -1: armv8_switch_to_el1_m x4, x5, x6 +1: armv8_switch_to_el1_m x4, x5, x6, x7 ENDPROC(armv8_switch_to_el1) .popsection diff --git a/arch/arm/include/asm/macro.h b/arch/arm/include/asm/macro.h index 485310d660..e1eefc283f 100644 --- a/arch/arm/include/asm/macro.h +++ b/arch/arm/include/asm/macro.h @@ -256,7 +256,7 @@ lr .req x30 * For loading 64-bit OS, x0 is physical address to the FDT blob. * They will be passed to the guest. */ -.macro armv8_switch_to_el1_m, ep, flag, tmp +.macro armv8_switch_to_el1_m, ep, flag, tmp, tmp2 /* Initialize Generic Timers */ mrs \tmp, cnthctl_el2 /* Enable EL1 access to timers */ @@ -306,7 +306,14 @@ lr .req x30 b.eq 1f /* Initialize HCR_EL2 */ - ldr \tmp, =(HCR_EL2_RW_AARCH64 | HCR_EL2_HCD_DIS) + /* Only disable PAuth traps if PAuth is supported */ + mrs \tmp, id_aa64isar1_el1 + ldr \tmp2, =(ID_AA64ISAR1_EL1_GPI | ID_AA64ISAR1_EL1_GPA | \ + ID_AA64ISAR1_EL1_API | ID_AA64ISAR1_EL1_APA) + tst \tmp, \tmp2 + mov \tmp2, #(HCR_EL2_RW_AARCH64 | HCR_EL2_HCD_DIS) + orr \tmp, \tmp2, #(HCR_EL2_APK | HCR_EL2_API) + csel \tmp, \tmp2, \tmp, eq msr hcr_el2, \tmp /* Return to the EL1_SP1 mode from EL2 */ diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 8b3a54e64c..77aa18909e 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -75,10 +75,25 @@ /* * HCR_EL2 bits definitions */ +#define HCR_EL2_API (1 << 41) /* Trap pointer authentication + instructions */ +#define HCR_EL2_APK (1 << 40) /* Trap pointer authentication + key access */ #define HCR_EL2_RW_AARCH64 (1 << 31) /* EL1 is AArch64 */ #define HCR_EL2_RW_AARCH32 (0 << 31) /* Lower levels are AArch32 */ #define HCR_EL2_HCD_DIS (1 << 29) /* Hypervisor Call disabled */ +/* + * ID_AA64ISAR1_EL1 bits definitions + */ +#define ID_AA64ISAR1_EL1_GPI (0xF << 28) /* Implementation-defined generic + code auth algorithm */ +#define ID_AA64ISAR1_EL1_GPA (0xF << 24) /* QARMA generic code auth + algorithm */ +#define ID_AA64ISAR1_EL1_API (0xF << 8) /* Implementation-defined address + auth algorithm */ +#define ID_AA64ISAR1_EL1_APA (0xF << 4) /* QARMA address auth algorithm */ + /* * ID_AA64PFR0_EL1 bits definitions */ From 37a757e227ccfc7d9eef82ab38f8500a832ea01b Mon Sep 17 00:00:00 2001 From: Peter Hoyes Date: Thu, 19 Aug 2021 16:53:10 +0100 Subject: [PATCH 09/18] armv8: Ensure EL1&0 VMSA is enabled On Armv8-R, the EL1&0 memory system architecture is configurable as a VMSA or PMSA, and resets to an "architecturally unknown" value. Add code to armv8_switch_to_el1_m which detects whether the MSA at EL1&0 is configurable using the id_aa64mmfr0_el1 register MSA fields. If it is we must ensure the VMSA is enabled so that a rich OS can boot. The MSA and MSA_FRAC fields are described in the Armv8-R architecture profile supplement (section G1.3.7): https://developer.arm.com/documentation/ddi0600/latest/ Signed-off-by: Peter Hoyes --- arch/arm/include/asm/macro.h | 17 +++++++++++++++++ arch/arm/include/asm/system.h | 24 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/arch/arm/include/asm/macro.h b/arch/arm/include/asm/macro.h index e1eefc283f..ecd8221c0d 100644 --- a/arch/arm/include/asm/macro.h +++ b/arch/arm/include/asm/macro.h @@ -316,6 +316,23 @@ lr .req x30 csel \tmp, \tmp2, \tmp, eq msr hcr_el2, \tmp + /* + * Detect whether the system has a configurable memory system + * architecture at EL1&0 + */ + mrs \tmp, id_aa64mmfr0_el1 + lsr \tmp, \tmp, #48 + and \tmp, \tmp, #((ID_AA64MMFR0_EL1_MSA_MASK | \ + ID_AA64MMFR0_EL1_MSA_FRAC_MASK) >> 48) + cmp \tmp, #((ID_AA64MMFR0_EL1_MSA_USE_FRAC | \ + ID_AA64MMFR0_EL1_MSA_FRAC_VMSA) >> 48) + bne 2f + + /* Ensure the EL1&0 VMSA is enabled */ + mov \tmp, #(VTCR_EL2_MSA) + msr vtcr_el2, \tmp +2: + /* Return to the EL1_SP1 mode from EL2 */ ldr \tmp, =(SPSR_EL_DEBUG_MASK | SPSR_EL_SERR_MASK |\ SPSR_EL_IRQ_MASK | SPSR_EL_FIQ_MASK |\ diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 77aa18909e..e4c11e830a 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -83,6 +83,30 @@ #define HCR_EL2_RW_AARCH32 (0 << 31) /* Lower levels are AArch32 */ #define HCR_EL2_HCD_DIS (1 << 29) /* Hypervisor Call disabled */ +/* + * VTCR_EL2 bits definitions + */ +#define VTCR_EL2_MSA (1 << 31) /* EL1&0 memory architecture */ + +/* + * ID_AA64MMFR0_EL1 bits definitions + */ +#define ID_AA64MMFR0_EL1_MSA_FRAC_MASK (0xFUL << 52) /* Memory system + architecture + frac */ +#define ID_AA64MMFR0_EL1_MSA_FRAC_VMSA (0x2UL << 52) /* EL1&0 supports + VMSA */ +#define ID_AA64MMFR0_EL1_MSA_FRAC_PMSA (0x1UL << 52) /* EL1&0 only + supports PMSA*/ +#define ID_AA64MMFR0_EL1_MSA_FRAC_NO_PMSA (0x0UL << 52) /* No PMSA + support */ +#define ID_AA64MMFR0_EL1_MSA_MASK (0xFUL << 48) /* Memory system + architecture */ +#define ID_AA64MMFR0_EL1_MSA_USE_FRAC (0xFUL << 48) /* Use MSA_FRAC */ +#define ID_AA64MMFR0_EL1_MSA_VMSA (0x0UL << 48) /* Memory system + architecture + is VMSA */ + /* * ID_AA64ISAR1_EL1 bits definitions */ From 2f5b7b74903f747581aa4d63f492da7cc77377bf Mon Sep 17 00:00:00 2001 From: Peter Hoyes Date: Thu, 19 Aug 2021 16:53:11 +0100 Subject: [PATCH 10/18] armv8: Add ARMv8 MPU configuration logic Armv8r64 is the first Armv8 platform that only has a PMSA at the current exception level. The architecture supplement for Armv8r64 describes new fields in ID_AA64MMFR0_EL1 which can be used to detect whether a VMSA or PMSA is present. These fields are RES0 on Armv8a. Add logic to read these fields and, for the protection of the memory used by U-Boot, initialize the MPU instead of the MMU during init, then clear the MPU regions before transition to the next stage. Provide a default (blank) MPU memory map, which can be overridden by board configurations. Signed-off-by: Peter Hoyes --- arch/arm/cpu/armv8/cache_v8.c | 96 +++++++++++++++++++++++++++++++- arch/arm/include/asm/armv8/mpu.h | 61 ++++++++++++++++++++ 2 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 arch/arm/include/asm/armv8/mpu.h diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index 3de18c7675..46625675bd 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -15,6 +15,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -365,6 +366,86 @@ __weak u64 get_page_table_size(void) return size; } +static void mpu_clear_regions(void) +{ + int i; + + for (i = 0; mpu_mem_map[i].end || mpu_mem_map[i].attrs; i++) { + setup_el2_mpu_region(i, 0, 0); + } +} + +static struct mpu_region default_mpu_mem_map[] = {{0,}}; +__weak struct mpu_region *mpu_mem_map = default_mpu_mem_map; + +static void mpu_setup(void) +{ + int i; + + if (current_el() != 2) { + panic("MPU configuration is only supported at EL2"); + } + + set_sctlr(get_sctlr() & ~(CR_M | CR_WXN)); + + asm volatile("msr MAIR_EL2, %0" : : "r" MEMORY_ATTRIBUTES); + + for (i = 0; mpu_mem_map[i].end || mpu_mem_map[i].attrs; i++) { + setup_el2_mpu_region(i, + PRBAR_ADDRESS(mpu_mem_map[i].start) + | PRBAR_OUTER_SH | PRBAR_AP_RW_ANY, + PRLAR_ADDRESS(mpu_mem_map[i].end) + | mpu_mem_map[i].attrs | PRLAR_EN_BIT + ); + } + + set_sctlr(get_sctlr() | CR_M); +} + +static bool el_has_mmu(void) +{ + uint64_t id_aa64mmfr0; + asm volatile("mrs %0, id_aa64mmfr0_el1" + : "=r" (id_aa64mmfr0) : : "cc"); + uint64_t msa = id_aa64mmfr0 & ID_AA64MMFR0_EL1_MSA_MASK; + uint64_t msa_frac = id_aa64mmfr0 & ID_AA64MMFR0_EL1_MSA_FRAC_MASK; + + switch (msa) { + case ID_AA64MMFR0_EL1_MSA_VMSA: + /* + * VMSA supported in all translation regimes. + * No support for PMSA. + */ + return true; + case ID_AA64MMFR0_EL1_MSA_USE_FRAC: + /* See MSA_frac for the supported MSAs. */ + switch (msa_frac) { + case ID_AA64MMFR0_EL1_MSA_FRAC_NO_PMSA: + /* + * PMSA not supported in any translation + * regime. + */ + return true; + case ID_AA64MMFR0_EL1_MSA_FRAC_VMSA: + /* + * PMSA supported in all translation + * regimes. No support for VMSA. + */ + case ID_AA64MMFR0_EL1_MSA_FRAC_PMSA: + /* + * PMSA supported in all translation + * regimes. + */ + return false; + default: + panic("Unsupported id_aa64mmfr0_el1 " \ + "MSA_frac value"); + } + default: + panic("Unsupported id_aa64mmfr0_el1 MSA value"); + } +} + void setup_pgtables(void) { int i; @@ -479,8 +560,13 @@ void dcache_enable(void) /* The data cache is not active unless the mmu is enabled */ if (!(get_sctlr() & CR_M)) { invalidate_dcache_all(); - __asm_invalidate_tlb_all(); - mmu_setup(); + + if (el_has_mmu()) { + __asm_invalidate_tlb_all(); + mmu_setup(); + } else { + mpu_setup(); + } } set_sctlr(get_sctlr() | CR_C); @@ -499,7 +585,11 @@ void dcache_disable(void) set_sctlr(sctlr & ~(CR_C|CR_M)); flush_dcache_all(); - __asm_invalidate_tlb_all(); + + if (el_has_mmu()) + __asm_invalidate_tlb_all(); + else + mpu_clear_regions(); } int dcache_status(void) diff --git a/arch/arm/include/asm/armv8/mpu.h b/arch/arm/include/asm/armv8/mpu.h new file mode 100644 index 0000000000..c6c8828325 --- /dev/null +++ b/arch/arm/include/asm/armv8/mpu.h @@ -0,0 +1,61 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + * + * (C) Copyright 2021 Arm Limited + */ + +#ifndef _ASM_ARMV8_MPU_H_ +#define _ASM_ARMV8_MPU_H_ + +#include +#include +#include + +#define PRSELR_EL2 S3_4_c6_c2_1 +#define PRBAR_EL2 S3_4_c6_c8_0 +#define PRLAR_EL2 S3_4_c6_c8_1 +#define MPUIR_EL2 S3_4_c0_c0_4 + +#define PRBAR_ADDRESS(addr) ((addr) & ~(0x3fULL)) + +/* Access permissions */ +#define PRBAR_AP(val) (((val) & 0x3) << 2) +#define PRBAR_AP_RW_HYP PRBAR_AP(0x0) +#define PRBAR_AP_RW_ANY PRBAR_AP(0x1) +#define PRBAR_AP_RO_HYP PRBAR_AP(0x2) +#define PRBAR_AP_RO_ANY PRBAR_AP(0x3) + +/* Shareability */ +#define PRBAR_SH(val) (((val) & 0x3) << 4) +#define PRBAR_NON_SH PRBAR_SH(0x0) +#define PRBAR_OUTER_SH PRBAR_SH(0x2) +#define PRBAR_INNER_SH PRBAR_SH(0x3) + +/* Memory attribute (MAIR idx) */ +#define PRLAR_ATTRIDX(val) (((val) & 0x7) << 1) +#define PRLAR_EN_BIT (0x1) +#define PRLAR_ADDRESS(addr) ((addr) & ~(0x3fULL)) + +#ifndef __ASSEMBLY__ + +static inline void setup_el2_mpu_region(uint8_t region, uint64_t base, uint64_t limit) +{ + asm volatile("msr " __stringify(PRSELR_EL2) ", %0" : : "r" (region)); + isb(); + asm volatile("msr " __stringify(PRBAR_EL2) ", %0" : : "r" (base)); + asm volatile("msr " __stringify(PRLAR_EL2) ", %0" : : "r" (limit)); + dsb(); + isb(); +} + +#endif + +struct mpu_region { + u64 start; + u64 end; + u64 attrs; +}; + +extern struct mpu_region *mpu_mem_map; + +#endif /* _ASM_ARMV8_MPU_H_ */ From b53bbca63bf42fe6d5174122e29e371691fe6dad Mon Sep 17 00:00:00 2001 From: Peter Hoyes Date: Thu, 19 Aug 2021 16:53:12 +0100 Subject: [PATCH 11/18] vexpress64: Add BASER_FVP vexpress board variant The BASER_FVP board variant is implemented on top of the BASE_FVP board config (which, in turn, is based on the Juno Versatile Express board config). They all share a similar memory map - for BASER_FVP the map is inverted from the BASE_FVP (https://developer.arm.com/documentation/100964/1114/Base-Platform/Base---memory/BaseR-Platform-memory-map) * Create new TARGET_VEXPRESS64_BASER_FVP target, which uses the same board config as BASE_FVP and JUNO * Adapt vexpress_aemv8a.h header file to support BASER_FVP (and rename to vexpress_aemv8.h) * Enable config to switch to EL1 for the BASER_FVP * Create vexpress_aemv8r defconfig * Provide an MPU memory map for the BASER_FVP For now, only single core boot is supported. Signed-off-by: Peter Hoyes [trini: Add MAINTAINERS, move BOOTCOMMAND to defconfig] Signed-off-by: Tom Rini --- arch/arm/Kconfig | 7 +++ board/armltd/vexpress64/Kconfig | 5 +- board/armltd/vexpress64/MAINTAINERS | 5 ++ board/armltd/vexpress64/vexpress64.c | 22 +++++++ configs/vexpress_aemv8r_defconfig | 19 ++++++ doc/README.semihosting | 2 +- .../{vexpress_aemv8a.h => vexpress_aemv8.h} | 58 ++++++++++++------- 7 files changed, 94 insertions(+), 24 deletions(-) create mode 100644 configs/vexpress_aemv8r_defconfig rename include/configs/{vexpress_aemv8a.h => vexpress_aemv8.h} (84%) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 50efb5e2e2..47f094514b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1185,6 +1185,13 @@ config TARGET_VEXPRESS64_BASE_FVP select PL01X_SERIAL select SEMIHOSTING +config TARGET_VEXPRESS64_BASER_FVP + bool "Support Versatile Express ARMv8r64 FVP BASE model" + select ARM64 + select DM + select DM_SERIAL + select PL01X_SERIAL + config TARGET_VEXPRESS64_JUNO bool "Support Versatile Express Juno Development Platform" select ARM64 diff --git a/board/armltd/vexpress64/Kconfig b/board/armltd/vexpress64/Kconfig index 1d13f542e6..1f0c7ad969 100644 --- a/board/armltd/vexpress64/Kconfig +++ b/board/armltd/vexpress64/Kconfig @@ -1,4 +1,5 @@ -if TARGET_VEXPRESS64_BASE_FVP || TARGET_VEXPRESS64_JUNO +if TARGET_VEXPRESS64_BASE_FVP || TARGET_VEXPRESS64_JUNO || \ + TARGET_VEXPRESS64_BASER_FVP config SYS_BOARD default "vexpress64" @@ -7,7 +8,7 @@ config SYS_VENDOR default "armltd" config SYS_CONFIG_NAME - default "vexpress_aemv8a" + default "vexpress_aemv8" config JUNO_DTB_PART string "NOR flash partition holding DTB" diff --git a/board/armltd/vexpress64/MAINTAINERS b/board/armltd/vexpress64/MAINTAINERS index 0ba044d7ff..875401ae1b 100644 --- a/board/armltd/vexpress64/MAINTAINERS +++ b/board/armltd/vexpress64/MAINTAINERS @@ -14,3 +14,8 @@ JUNO DEVELOPMENT PLATFORM BOARD M: Linus Walleij S: Maintained F: configs/vexpress_aemv8a_juno_defconfig + +VEXPRESS64 BASER_FVP +M: Peter Hoyes +S: Maintained +F: configs/vexpress_aemv8r_defconfig diff --git a/board/armltd/vexpress64/vexpress64.c b/board/armltd/vexpress64/vexpress64.c index 2e4260286b..eb4951d07c 100644 --- a/board/armltd/vexpress64/vexpress64.c +++ b/board/armltd/vexpress64/vexpress64.c @@ -18,6 +18,7 @@ #include #include "pcie.h" #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -54,6 +55,27 @@ static struct mm_region vexpress64_mem_map[] = { struct mm_region *mem_map = vexpress64_mem_map; +static struct mpu_region vexpress64_aemv8r_mem_map[] = { + { + .start = 0x0UL, + .end = 0x7fffffffUL, + .attrs = PRLAR_ATTRIDX(MT_NORMAL) + }, { + .start = 0x80000000UL, + .end = 0xffffffffUL, + .attrs = PRLAR_ATTRIDX(MT_DEVICE_NGNRNE) + }, { + .start = 0x100000000UL, + .end = 0xffffffffffUL, + .attrs = PRLAR_ATTRIDX(MT_NORMAL) + }, { + /* List terminator */ + 0, + } +}; + +struct mpu_region *mpu_mem_map = vexpress64_aemv8r_mem_map; + /* This function gets replaced by platforms supporting PCIe. * The replacement function, eg. on Juno, initialises the PCIe bus. */ diff --git a/configs/vexpress_aemv8r_defconfig b/configs/vexpress_aemv8r_defconfig new file mode 100644 index 0000000000..bb4d1e5645 --- /dev/null +++ b/configs/vexpress_aemv8r_defconfig @@ -0,0 +1,19 @@ +CONFIG_ARM=y +CONFIG_TARGET_VEXPRESS64_BASER_FVP=y +CONFIG_SYS_TEXT_BASE=0x00001000 +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_NR_DRAM_BANKS=2 +CONFIG_SYS_MEMTEST_START=0x80000000 +CONFIG_SYS_MEMTEST_END=0xff000000 +CONFIG_ENV_SIZE=0x40000 +CONFIG_ENV_SECT_SIZE=0x40000 +CONFIG_IDENT_STRING=" vexpress_aemv8r64" +CONFIG_DISTRO_DEFAULTS=y +CONFIG_BOOTDELAY=3 +CONFIG_USE_BOOTARGS=y +CONFIG_BOOTARGS="console=ttyAMA0 earlycon=pl011,0x9c090000 rootfstype=ext4 root=/dev/vda1 rw rootwait" +CONFIG_USE_BOOTCOMMAND=y +CONFIG_BOOTCOMMAND="fdt addr ${fdt_addr}; fdt resize; booti $kernel_addr - $fdt_addr" +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_SYS_PROMPT="VExpress64# " +CONFIG_OF_LIBFDT=y diff --git a/doc/README.semihosting b/doc/README.semihosting index c019999bed..f382d0131e 100644 --- a/doc/README.semihosting +++ b/doc/README.semihosting @@ -25,7 +25,7 @@ or turning on CONFIG_BASE_FVP for the more full featured model. Rather than create a new armv8 board similar to armltd/vexpress64, add semihosting calls to the existing one, enabled with CONFIG_SEMIHOSTING and CONFIG_BASE_FVP both set. Also reuse the existing board config file -vexpress_aemv8a.h but differentiate the two models by the presence or +vexpress_aemv8.h but differentiate the two models by the presence or absence of CONFIG_BASE_FVP. This change is tested and works on both the Foundation and Base fastmodel simulators. diff --git a/include/configs/vexpress_aemv8a.h b/include/configs/vexpress_aemv8.h similarity index 84% rename from include/configs/vexpress_aemv8a.h rename to include/configs/vexpress_aemv8.h index df22584d9a..3447f020d3 100644 --- a/include/configs/vexpress_aemv8a.h +++ b/include/configs/vexpress_aemv8.h @@ -10,30 +10,36 @@ #define CONFIG_REMAKE_ELF /* Link Definitions */ -#ifdef CONFIG_TARGET_VEXPRESS64_BASE_FVP +#ifdef CONFIG_TARGET_VEXPRESS64_JUNO +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x7fff0) +#else /* ATF loads u-boot here for BASE_FVP model */ #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x03f00000) -#elif CONFIG_TARGET_VEXPRESS64_JUNO -#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x7fff0) #endif #define CONFIG_SYS_BOOTM_LEN (64 << 20) /* Increase max gunzip size */ /* CS register bases for the original memory map. */ -#define V2M_PA_CS0 0x00000000 -#define V2M_PA_CS1 0x14000000 -#define V2M_PA_CS2 0x18000000 -#define V2M_PA_CS3 0x1c000000 -#define V2M_PA_CS4 0x0c000000 -#define V2M_PA_CS5 0x10000000 +#ifdef CONFIG_TARGET_VEXPRESS64_BASER_FVP +#define V2M_BASE 0x00000000 +#define V2M_PA_BASE 0x80000000 +#else +#define V2M_BASE 0x80000000 +#define V2M_PA_BASE 0x00000000 +#endif + +#define V2M_PA_CS0 (V2M_PA_BASE + 0x00000000) +#define V2M_PA_CS1 (V2M_PA_BASE + 0x14000000) +#define V2M_PA_CS2 (V2M_PA_BASE + 0x18000000) +#define V2M_PA_CS3 (V2M_PA_BASE + 0x1c000000) +#define V2M_PA_CS4 (V2M_PA_BASE + 0x0c000000) +#define V2M_PA_CS5 (V2M_PA_BASE + 0x10000000) #define V2M_PERIPH_OFFSET(x) (x << 16) #define V2M_SYSREGS (V2M_PA_CS3 + V2M_PERIPH_OFFSET(1)) #define V2M_SYSCTL (V2M_PA_CS3 + V2M_PERIPH_OFFSET(2)) #define V2M_SERIAL_BUS_PCI (V2M_PA_CS3 + V2M_PERIPH_OFFSET(3)) -#define V2M_BASE 0x80000000 - /* Common peripherals relative to CS7. */ #define V2M_AACI (V2M_PA_CS3 + V2M_PERIPH_OFFSET(4)) #define V2M_MMCI (V2M_PA_CS3 + V2M_PERIPH_OFFSET(5)) @@ -68,27 +74,27 @@ #define V2M_SYS_CFGSTAT (V2M_SYSREGS + 0x0a8) /* Generic Timer Definitions */ -#define COUNTER_FREQUENCY 24000000 /* 24MHz */ +#define COUNTER_FREQUENCY 100000000 /* 100MHz */ /* Generic Interrupt Controller Definitions */ #ifdef CONFIG_GICV3 -#define GICD_BASE (0x2f000000) -#define GICR_BASE (0x2f100000) +#define GICD_BASE (V2M_PA_BASE + 0x2f000000) +#define GICR_BASE (V2M_PA_BASE + 0x2f100000) #else -#ifdef CONFIG_TARGET_VEXPRESS64_BASE_FVP -#define GICD_BASE (0x2f000000) -#define GICC_BASE (0x2c000000) -#elif CONFIG_TARGET_VEXPRESS64_JUNO +#ifdef CONFIG_TARGET_VEXPRESS64_JUNO #define GICD_BASE (0x2C010000) #define GICC_BASE (0x2C02f000) +#else +#define GICD_BASE (V2M_PA_BASE + 0x2f000000) +#define GICC_BASE (V2M_PA_BASE + 0x2c000000) #endif #endif /* !CONFIG_GICV3 */ #ifndef CONFIG_TARGET_VEXPRESS64_JUNO /* The Vexpress64 simulators use SMSC91C111 */ #define CONFIG_SMC91111 1 -#define CONFIG_SMC91111_BASE (0x01A000000) +#define CONFIG_SMC91111_BASE (V2M_PA_BASE + 0x01A000000) #endif /* PL011 Serial Configuration */ @@ -113,7 +119,7 @@ #ifdef CONFIG_TARGET_VEXPRESS64_JUNO #define PHYS_SDRAM_2 (0x880000000) #define PHYS_SDRAM_2_SIZE 0x180000000 -#elif CONFIG_TARGET_VEXPRESS64_BASE_FVP && CONFIG_NR_DRAM_BANKS == 2 +#elif CONFIG_NR_DRAM_BANKS == 2 #define PHYS_SDRAM_2 (0x880000000) #define PHYS_SDRAM_2_SIZE 0x80000000 #endif @@ -200,6 +206,12 @@ " booti $kernel_addr - $fdt_addr; " \ "fi" #endif + +#elif CONFIG_TARGET_VEXPRESS64_BASER_FVP +#define CONFIG_EXTRA_ENV_SETTINGS \ + "kernel_addr=0x00800000\0" \ + "fdt_addr=0x03000000\0" \ + "boot_addr=0x0007f800\0" #endif /* Monitor Command Prompt */ @@ -213,7 +225,7 @@ /* Store environment at top of flash in the same location as blank.img */ /* in the Juno firmware. */ #else -#define CONFIG_SYS_FLASH_BASE 0x0C000000 +#define CONFIG_SYS_FLASH_BASE (V2M_PA_BASE + 0x0C000000) /* 256 x 256KiB sectors */ #define CONFIG_SYS_MAX_FLASH_SECT 256 /* Store environment at top of flash */ @@ -230,4 +242,8 @@ #define CONFIG_SYS_FLASH_EMPTY_INFO /* flinfo indicates empty blocks */ #define FLASH_MAX_SECTOR_SIZE 0x00040000 +#ifdef CONFIG_TARGET_VEXPRESS64_BASER_FVP +#define CONFIG_ARMV8_SWITCH_TO_EL1 +#endif + #endif /* __VEXPRESS_AEMV8A_H */ From 30e5a449e8c7739965757879bb17efbd3a8f0ee2 Mon Sep 17 00:00:00 2001 From: Peter Hoyes Date: Thu, 19 Aug 2021 16:53:13 +0100 Subject: [PATCH 12/18] arm: Use armv8_switch_to_el1 env to switch to EL1 Use the environment variable armv8_switch_to_el1 to determine whether to switch to EL1 at runtime. This is an alternative to the CONFIG_ARMV8_SWITCH_TO_EL1 compile-time option. The environment variable will be ineffective if the ARMV8_MULTIENTRY config is used. This is required by the Armv8r64 architecture, which must be able to boot at S-EL1 for Linux but may need to boot at other ELs for other systems. Signed-off-by: Peter Hoyes --- arch/arm/lib/bootm.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index f60ee3a7e6..ea9bfe7570 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -317,7 +317,6 @@ __weak void update_os_arch_secondary_cores(uint8_t os_arch) { } -#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 static void switch_to_el1(void) { if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) && @@ -332,7 +331,6 @@ static void switch_to_el1(void) ES_TO_AARCH64); } #endif -#endif /* Subcommand: GO */ static void boot_jump_linux(bootm_headers_t *images, int flag) @@ -359,21 +357,33 @@ static void boot_jump_linux(bootm_headers_t *images, int flag) update_os_arch_secondary_cores(images->os.arch); -#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 - armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0, - (u64)switch_to_el1, ES_TO_AARCH64); +#ifdef CONFIG_ARMV8_MULTIENTRY + int armv8_switch_to_el1 = -1; #else - if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) && - (images->os.arch == IH_ARCH_ARM)) - armv8_switch_to_el2(0, (u64)gd->bd->bi_arch_number, - (u64)images->ft_addr, 0, - (u64)images->ep, - ES_TO_AARCH32); - else - armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0, - images->ep, - ES_TO_AARCH64); + int armv8_switch_to_el1 = env_get_yesno("armv8_switch_to_el1"); #endif +#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 + if (armv8_switch_to_el1 == -1) { + armv8_switch_to_el1 = 1; + } +#endif + if (armv8_switch_to_el1 == 1) { + armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0, + (u64)switch_to_el1, ES_TO_AARCH64); + } else { + if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) && + (images->os.arch == IH_ARCH_ARM)) + armv8_switch_to_el2(0, + (u64)gd->bd->bi_arch_number, + (u64)images->ft_addr, 0, + (u64)images->ep, + ES_TO_AARCH32); + else + armv8_switch_to_el2((u64)images->ft_addr, + 0, 0, 0, + images->ep, + ES_TO_AARCH64); + } } #else unsigned long machid = gd->bd->bi_arch_number; From e0bd6f31ce41771964b64dc86dcd976c8bdb116a Mon Sep 17 00:00:00 2001 From: Peter Hoyes Date: Thu, 19 Aug 2021 16:53:14 +0100 Subject: [PATCH 13/18] doc: Add documentation for the Arm vexpress board configs Create a new documentation section for Arm Ltd boards with a sub-page for the vexpress board (FVP-A, FVP-R and Juno). Document how the armv8_switch_to_el1 environment variable can be used to switch between booting from S-EL2/S-EL1 at runtime on the BASER_FVP. Signed-off-by: Peter Hoyes --- doc/arch/arm64.rst | 3 +- doc/board/armltd/index.rst | 9 ++++++ doc/board/armltd/vexpress64.rst | 57 +++++++++++++++++++++++++++++++++ doc/board/index.rst | 1 + 4 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 doc/board/armltd/index.rst create mode 100644 doc/board/armltd/vexpress64.rst diff --git a/doc/arch/arm64.rst b/doc/arch/arm64.rst index 80498f6f6b..f20eb8f1b2 100644 --- a/doc/arch/arm64.rst +++ b/doc/arch/arm64.rst @@ -18,7 +18,8 @@ Notes classical firmware (like initial hardware setup, CPU errata workarounds or SMP bringup). U-Boot can be entered in EL2 when its main purpose is that of a boot loader. It can drop to lower exception levels before - entering the OS. + entering the OS. For ARMv8-R it is recommened to enter at S-EL2, as for this + architecture there is no S-EL3. 2. U-Boot for arm64 is compiled with AArch64-gcc. AArch64-gcc use rela relocation format, a tool(tools/relocate-rela) by Scott Wood diff --git a/doc/board/armltd/index.rst b/doc/board/armltd/index.rst new file mode 100644 index 0000000000..b6786c114f --- /dev/null +++ b/doc/board/armltd/index.rst @@ -0,0 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Arm Ltd +============= + +.. toctree:: + :maxdepth: 2 + + vexpress64.rst diff --git a/doc/board/armltd/vexpress64.rst b/doc/board/armltd/vexpress64.rst new file mode 100644 index 0000000000..37ef564110 --- /dev/null +++ b/doc/board/armltd/vexpress64.rst @@ -0,0 +1,57 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Arm Versatile Express +===================== + +The vexpress_* board configuration supports the following platforms: + + * FVP_Base_RevC-2xAEMvA + * FVP_BaseR_AEMv8R + * Juno development board + +Fixed Virtual Platforms +----------------------- + +The Fixed Virtual Platforms (FVP) are complete simulations of an Arm system, +including processor, memory and peripherals. They are set out in a "programmer's +view", which gives a comprehensive model on which to build and test software. + +The supported FVPs are available free of charge and can be downloaded from the +Arm developer site [1]_ (user registration might be required). + +Supported features: + + * GICv3 + * Generic timer + * PL011 UART + * SMC91111 network interface + +The default configuration assumes that U-Boot is boostrapped from the start of +the DRAM (address 0x80000000 for AEMvA; 0x00000000 for AEMv8R) using a suitable +bootloader. Alternatively, U-Boot can be launched directly by mapping the binary +to the same address (using the FVP's --data argument). + +The FVPs can be debugged using Arm Development Studio [2]_. + +FVP_BaseR +^^^^^^^^^ + +On Armv8r64 platforms (such as the FVP_BaseR), U-Boot runs at S-EL2, so +CONFIG_ARMV8_SWITCH_TO_EL1 is defined so that the next stage boots at S-EL1. If +S-EL2 is desired instead, the *armv8_switch_to_el1* environment variable is +available. This can be set to *n* to override the config flag and boot the next +stage at S-EL2 instead. + +Juno +---- + +The Juno development board is an open, vendor-neutral Armv8-A development +platform that supports an out-of-the-box Linux software package. A range of +plug-in expansion options enables hardware and software applications to be +developed and debugged. + +References +---------- + +.. [1] https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms +.. [2] https://developer.arm.com/tools-and-software/embedded/arm-development-studio diff --git a/doc/board/index.rst b/doc/board/index.rst index 8588e453d5..827f0866bd 100644 --- a/doc/board/index.rst +++ b/doc/board/index.rst @@ -10,6 +10,7 @@ Board-specific doc advantech/index AndesTech/index amlogic/index + armltd/index atmel/index congatec/index coreboot/index From f43312c974eaeb7301cb2638aa4ab05ed7ca4c44 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 21 Aug 2021 19:54:02 -0500 Subject: [PATCH 14/18] ARM: Prevent the compiler from using NEON registers For ARMv8-A, NEON is standard, so the compiler can use it even when no special target flags are provided. For example, it can use stores from NEON registers to zero-initialize large structures. GCC 11 decides to do this inside the DRAM init code for the Allwinner H6. However, GCC 11 has a bug where it generates misaligned NEON register stores even with -mstrict-align. Since the MMU is not enabled this early in SPL, the misaligned store causes an exception and breaks booting. Work around this issue by restricting the compiler to using GPRs only, not vector registers. This prevents any future surprises relating to NEON use as well. Signed-off-by: Samuel Holland Acked-by: Andre Przywara --- arch/arm/config.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/config.mk b/arch/arm/config.mk index b684d8b416..b107b1af27 100644 --- a/arch/arm/config.mk +++ b/arch/arm/config.mk @@ -25,6 +25,7 @@ endif PLATFORM_RELFLAGS += -fno-common -ffixed-r9 PLATFORM_RELFLAGS += $(call cc-option, -msoft-float) \ + $(call cc-option,-mgeneral-regs-only) \ $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) # LLVM support From 210985b5e5804a5102d34f278fd1f583634c8de4 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Sun, 22 Aug 2021 07:23:48 +0200 Subject: [PATCH 15/18] mailmap: Update e-mail for Jernej Skrabec Old address doesn't exist anymore. Map it to new one. Signed-off-by: Jernej Skrabec Acked-by: Andre Przywara --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index b76f02283c..3d15a09d1c 100644 --- a/.mailmap +++ b/.mailmap @@ -29,6 +29,7 @@ Jagan Teki Jagan Teki Jagan Teki Jagan Teki +Jernej Skrabec Igor Opaniuk Igor Opaniuk Markus Klotzbuecher From 2cb32607e187d1356a1468337fb4c95a689e9c82 Mon Sep 17 00:00:00 2001 From: Bharat Gooty Date: Mon, 23 Aug 2021 14:57:24 +0530 Subject: [PATCH 16/18] pci: iproc: fix compilation errors and warnings Signed-off-by: Bharat Gooty --- drivers/pci/pcie_iproc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/pci/pcie_iproc.c b/drivers/pci/pcie_iproc.c index 12ce9d525c..be03dcbd97 100644 --- a/drivers/pci/pcie_iproc.c +++ b/drivers/pci/pcie_iproc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright (C) 2020 Broadcom + * Copyright (C) 2020-2021 Broadcom * */ @@ -12,6 +12,7 @@ #include #include #include +#include #include #define EP_PERST_SOURCE_SELECT_SHIFT 2 @@ -884,7 +885,7 @@ static int iproc_pcie_map_ranges(struct udevice *dev) for (i = 0; i < hose->region_count; i++) { if (hose->regions[i].flags == PCI_REGION_MEM || hose->regions[i].flags == PCI_REGION_PREFETCH) { - debug("%d: bus_addr %p, axi_addr %p, size 0x%lx\n", + debug("%d: bus_addr %p, axi_addr %p, size 0x%llx\n", i, &hose->regions[i].bus_start, &hose->regions[i].phys_start, hose->regions[i].size); @@ -1049,7 +1050,7 @@ static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie) while (!pci_get_dma_regions(pcie->dev, ®ions, i)) { dev_dbg(pcie->dev, - "dma %d: bus_addr %#lx, axi_addr %#llx, size %#lx\n", + "dma %d: bus_addr %#llx, axi_addr %#llx, size %#llx\n", i, regions.bus_start, regions.phys_start, regions.size); /* Each range entry corresponds to an inbound mapping region */ From 7befc8490a008c332633e693f2adfab38d8d50f2 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Tue, 24 Aug 2021 00:55:39 +0300 Subject: [PATCH 17/18] psci: fix double declaration The prototype of psci_features() duplicated. Remove extra declaration. Fixed: e21e3ffdd1 ("psci: Fix warnings when compiling with W=1") Reported-by: Michael Scott Signed-off-by: Oleksandr Suvorov --- arch/arm/include/asm/system.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index e4c11e830a..1ec6237320 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -590,7 +590,6 @@ s32 psci_affinity_info(u32 function_id, u32 target_affinity, u32 psci_migrate_info_type(void); void psci_system_off(void); void psci_system_reset(void); -s32 psci_features(u32 function_id, u32 psci_fid); #endif #endif /* __ASSEMBLY__ */ From 6628813f9d400c49da4926f01833063a30151cdb Mon Sep 17 00:00:00 2001 From: Thibault Ferrante Date: Tue, 24 Aug 2021 17:29:50 +0200 Subject: [PATCH 18/18] tools: env: Handle shorter read calls On some cases, the actual number of bytes read can be shorter than what was requested. This can be handled gracefully by taking this difference into account instead of exiting. Signed-off-by: Thibault Ferrante --- tools/env/fw_env.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c index 2a61a5d6f0..e39c39e23a 100644 --- a/tools/env/fw_env.c +++ b/tools/env/fw_env.c @@ -951,21 +951,23 @@ static int flash_read_buf(int dev, int fd, void *buf, size_t count, DEVNAME(dev), strerror(errno)); return -1; } - if (rc != readlen) { - fprintf(stderr, - "Read error on %s: Attempted to read %zd bytes but got %d\n", - DEVNAME(dev), readlen, rc); - return -1; - } #ifdef DEBUG fprintf(stderr, "Read 0x%x bytes at 0x%llx on %s\n", rc, (unsigned long long)blockstart + block_seek, DEVNAME(dev)); #endif - processed += readlen; - readlen = min(blocklen, count - processed); - block_seek = 0; - blockstart += blocklen; + processed += rc; + if (rc != readlen) { + fprintf(stderr, + "Warning on %s: Attempted to read %zd bytes but got %d\n", + DEVNAME(dev), readlen, rc); + readlen -= rc; + block_seek += rc; + } else { + blockstart += blocklen; + readlen = min(blocklen, count - processed); + block_seek = 0; + } } return processed;