diff options
author | Tom Rini <trini@konsulko.com> | 2022-03-02 13:59:33 -0500 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2022-03-02 13:59:33 -0500 |
commit | 2dfdba4a5a48de33a3cedc908c183b86b6ff7bd5 (patch) | |
tree | da9d57e285034143ed1e9cd4dfc30577792275ad /cmd/arm/exception64.c | |
parent | f861ffa660dc47c4017c220b94d10a64439d46a7 (diff) | |
parent | 5ff4857d3569710c0f1ce1848f1e7486e3a4cfbe (diff) |
Merge branch '2022-03-02-armv8-fixes-and-cleanups' into next
To quote the author:
I was looking into the arm64 boot code lately and stumbled upon some
issues. Also Nishanth brought back memories of a lengthy debug session,
which was caused due to U-Boot keeping SErrors masked. As the resulting
patches are all somewhat related, I gathered this series here to address
those problems.
Patches 1 to 3 address exception handling issues, with the SError
enablement being the most prominent fix here.
Patch 4 cleans up asm/io.h. This was on the list before[1], but was
somehow lost when it was intercepted by a shorter version of itself.
Patches 5 and 6 clean up some unnecessarily complicated AArch64 assembly
code.
Diffstat (limited to 'cmd/arm/exception64.c')
-rw-r--r-- | cmd/arm/exception64.c | 64 |
1 files changed, 60 insertions, 4 deletions
diff --git a/cmd/arm/exception64.c b/cmd/arm/exception64.c index d5de50a0803..589a23115b0 100644 --- a/cmd/arm/exception64.c +++ b/cmd/arm/exception64.c @@ -7,19 +7,73 @@ #include <common.h> #include <command.h> +#include <linux/bitops.h> static int do_undefined(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { /* - * 0xe7f...f. is undefined in ARM mode - * 0xde.. is undefined in Thumb mode + * Instructions starting with the upper 16 bits all 0 are permanently + * undefined. The lower 16 bits can be used for some kind of immediate. + * --- ARMv8 ARM (ARM DDI 0487G.a C6.2.339: "UDF") */ - asm volatile (".word 0xe7f7defb\n"); + asm volatile (".word 0x00001234\n"); + + return CMD_RET_FAILURE; +} + +/* + * The ID_AA64MMFR2_EL1 register name is only know to binutils for ARMv8.2 + * and later architecture revisions. However the register is valid regardless + * of binutils architecture support or the core the code is running on, so + * just use the generic encoding. + */ +#define ID_AA64MMFR2_EL1 "S3_0_C0_C7_2" + +static int do_unaligned(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + uint64_t reg; + + /* + * The unaligned LDAR access below is only guaranteed to generate an + * alignment fault on cores not implementing FEAT_LSE2. To avoid false + * negatives, check this condition before we exectute LDAR. + */ + asm ("mrs %0, "ID_AA64MMFR2_EL1"\n" : "=r" (reg)); + if (reg & GENMASK(35, 32)) { + printf("unaligned access check only supported on pre-v8.4 cores\n"); + return CMD_RET_FAILURE; + } + + /* + * The load acquire instruction requires the data source to be + * naturally aligned, and will fault even if strict alignment fault + * checking is disabled (but only without FEAT_LSE2). + * --- ARMv8 ARM (ARM DDI 0487G.a B2.5.2: "Alignment of data accesses") + */ + asm volatile ( + "mov x1, sp\n\t" + "orr x1, x1, #3\n\t" + "ldar x0, [x1]\n" + ::: "x0", "x1" ); + + return CMD_RET_FAILURE; +} + +static int do_breakpoint(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + asm volatile ("brk #123\n"); + return CMD_RET_FAILURE; } static struct cmd_tbl cmd_sub[] = { + U_BOOT_CMD_MKENT(breakpoint, CONFIG_SYS_MAXARGS, 1, do_breakpoint, + "", ""), + U_BOOT_CMD_MKENT(unaligned, CONFIG_SYS_MAXARGS, 1, do_unaligned, + "", ""), U_BOOT_CMD_MKENT(undefined, CONFIG_SYS_MAXARGS, 1, do_undefined, "", ""), }; @@ -27,7 +81,9 @@ static struct cmd_tbl cmd_sub[] = { static char exception_help_text[] = "<ex>\n" " The following exceptions are available:\n" - " undefined - undefined instruction\n" + " breakpoint - breakpoint instruction exception\n" + " unaligned - unaligned LDAR data abort\n" + " undefined - undefined instruction exception\n" ; #include <exception.h> |