[PATCH 1/7] microblaze: exception: move privileged instruction exception out of v5 ifdef

The privileged instruction exception seems to have been introduced in microblaze v7.00 along with MMU support, so having it wrapped in MICROBLAZE_v5 ifdefs seems incorrect. Move it out of the ifdef, since all recent microblaze versions support it.
Signed-off-by: Ovidiu Panait ovidiu.panait@windriver.com ---
arch/microblaze/cpu/exception.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/microblaze/cpu/exception.c b/arch/microblaze/cpu/exception.c index e9476abedb..f60f1fc693 100644 --- a/arch/microblaze/cpu/exception.c +++ b/arch/microblaze/cpu/exception.c @@ -37,10 +37,10 @@ void _hw_exception_handler (void) case 0x5: puts("Divide by zero exception\n"); break; -#ifdef MICROBLAZE_V5 case 0x7: puts("Priviledged or stack protection violation exception\n"); break; +#ifdef MICROBLAZE_V5 case 0x1000: puts("Exception in delay slot\n"); break;

Also, rename it to XILINX_MICROBLAZE0_DELAY_SLOT_EXCEP, since it only covers delay slot exception support.
Signed-off-by: Ovidiu Panait ovidiu.panait@windriver.com ---
arch/microblaze/cpu/exception.c | 2 +- board/xilinx/microblaze-generic/Kconfig | 9 +++++++++ include/configs/microblaze-generic.h | 3 --- 3 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/arch/microblaze/cpu/exception.c b/arch/microblaze/cpu/exception.c index f60f1fc693..5601dde5b4 100644 --- a/arch/microblaze/cpu/exception.c +++ b/arch/microblaze/cpu/exception.c @@ -40,7 +40,7 @@ void _hw_exception_handler (void) case 0x7: puts("Priviledged or stack protection violation exception\n"); break; -#ifdef MICROBLAZE_V5 +#if CONFIG_IS_ENABLED(XILINX_MICROBLAZE0_DELAY_SLOT_EXCEP) case 0x1000: puts("Exception in delay slot\n"); break; diff --git a/board/xilinx/microblaze-generic/Kconfig b/board/xilinx/microblaze-generic/Kconfig index e31257d335..117b476f3f 100644 --- a/board/xilinx/microblaze-generic/Kconfig +++ b/board/xilinx/microblaze-generic/Kconfig @@ -47,6 +47,15 @@ config XILINX_MICROBLAZE0_USR_EXCEP the exception vector table. The user exception vector is located at C_BASE_VECTORS + 0x8 address.
+config XILINX_MICROBLAZE0_DELAY_SLOT_EXCEP + bool "MicroBlaze delay slot exception support" + default y + help + Enable this option if the MicroBlaze processor supports exceptions + caused by delay slot instructions (processor version >= v5.00). When + enabled, the hw exception handler will print a message indicating + whether the exception was triggered by a delay slot instruction. + config XILINX_MICROBLAZE0_VECTOR_BASE_ADDR hex "Location of MicroBlaze vectors" default 0x0 diff --git a/include/configs/microblaze-generic.h b/include/configs/microblaze-generic.h index ca749ed18a..fd5a9cf8b8 100644 --- a/include/configs/microblaze-generic.h +++ b/include/configs/microblaze-generic.h @@ -11,9 +11,6 @@ /* Microblaze is microblaze_0 */ #define XILINX_FSL_NUMBER 3
-/* MicroBlaze CPU */ -#define MICROBLAZE_V5 1 - #define CONFIG_SYS_BOOTM_LEN (64 * 1024 * 1024)
/* uart */

The switch statement in _hw_exception_handler() only covers the rightmost 5 bits that encode the exception cause: switch (state & 0x1f) { ... }
For this reason, the "0x1000" case will never be reached, because the 13th bit was zeroed out. To fix this, move delay slot exception handling before the switch statement (delay slot (DS) bit in Exception Status Register is independent of the exception cause (EC)).
Signed-off-by: Ovidiu Panait ovidiu.panait@windriver.com ---
arch/microblaze/cpu/exception.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/microblaze/cpu/exception.c b/arch/microblaze/cpu/exception.c index 5601dde5b4..64d5fe4a80 100644 --- a/arch/microblaze/cpu/exception.c +++ b/arch/microblaze/cpu/exception.c @@ -21,6 +21,11 @@ void _hw_exception_handler (void) printf("Hardware exception at 0x%x address\n", address); R17(address); printf("Return address from exception 0x%x\n", address); + + if (CONFIG_IS_ENABLED(XILINX_MICROBLAZE0_DELAY_SLOT_EXCEP) && + (state & 0x1000)) + puts("Exception in delay slot\n"); + switch (state & 0x1f) { /* mask on exception cause */ case 0x1: puts("Unaligned data access exception\n"); @@ -40,11 +45,6 @@ void _hw_exception_handler (void) case 0x7: puts("Priviledged or stack protection violation exception\n"); break; -#if CONFIG_IS_ENABLED(XILINX_MICROBLAZE0_DELAY_SLOT_EXCEP) - case 0x1000: - puts("Exception in delay slot\n"); - break; -#endif default: puts("Undefined cause\n"); break;

According to the MicroBlaze reference manual (xilinx2021.2/ug984/page-37): """ If an exception is caused by an instruction in a delay slot (that is, ESR[DS]=1), the exception handler should return execution to the address stored in BTR instead of the normal exception return address stored in R17. """
Adjust the code to print the proper return address for delay slot exceptions.
Signed-off-by: Ovidiu Panait ovidiu.panait@windriver.com ---
arch/microblaze/cpu/exception.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/arch/microblaze/cpu/exception.c b/arch/microblaze/cpu/exception.c index 64d5fe4a80..f79e465e1f 100644 --- a/arch/microblaze/cpu/exception.c +++ b/arch/microblaze/cpu/exception.c @@ -20,11 +20,17 @@ void _hw_exception_handler (void) MFS(state, resr); printf("Hardware exception at 0x%x address\n", address); R17(address); - printf("Return address from exception 0x%x\n", address);
if (CONFIG_IS_ENABLED(XILINX_MICROBLAZE0_DELAY_SLOT_EXCEP) && - (state & 0x1000)) + (state & 0x1000)) { + /* + * For exceptions in delay slots, the return address is stored + * in the Branch Target Register (BTR), rather than R17. + */ + MFS(address, rbtr); + puts("Exception in delay slot\n"); + }
switch (state & 0x1f) { /* mask on exception cause */ case 0x1: @@ -49,6 +55,8 @@ void _hw_exception_handler (void) puts("Undefined cause\n"); break; } + + printf("Return address from exception 0x%x\n", address); printf("Unaligned %sword access\n", ((state & 0x800) ? "" : "half")); printf("Unaligned %s access\n", ((state & 0x400) ? "store" : "load")); printf("Register R%x\n", (state & 0x3E) >> 5);

The unaligned access messages are only valid in the case of an unaligned data access exception. Do not print them for other types of hw exceptions.
Signed-off-by: Ovidiu Panait ovidiu.panait@windriver.com ---
arch/microblaze/cpu/exception.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/arch/microblaze/cpu/exception.c b/arch/microblaze/cpu/exception.c index f79e465e1f..d37f04364a 100644 --- a/arch/microblaze/cpu/exception.c +++ b/arch/microblaze/cpu/exception.c @@ -35,6 +35,10 @@ void _hw_exception_handler (void) switch (state & 0x1f) { /* mask on exception cause */ case 0x1: puts("Unaligned data access exception\n"); + + printf("Unaligned %sword access\n", ((state & 0x800) ? "" : "half")); + printf("Unaligned %s access\n", ((state & 0x400) ? "store" : "load")); + printf("Register R%x\n", (state & 0x3E) >> 5); break; case 0x2: puts("Illegal op-code exception\n"); @@ -57,9 +61,6 @@ void _hw_exception_handler (void) }
printf("Return address from exception 0x%x\n", address); - printf("Unaligned %sword access\n", ((state & 0x800) ? "" : "half")); - printf("Unaligned %s access\n", ((state & 0x400) ? "store" : "load")); - printf("Register R%x\n", (state & 0x3E) >> 5); hang(); }

The correct mask for getting the source/destination register from ESR in the case of an unaligned access exception is 0x3E0. With this change, a dummy unaligned store produces the expected info: """
swi r5, r0, 0x111
... Hardware exception at 0x111 address Unaligned data access exception Unaligned word access Unaligned store access Register R5 Return address from exception 0x7f99dfc ### ERROR ### Please RESET the board ### """
Signed-off-by: Ovidiu Panait ovidiu.panait@windriver.com ---
arch/microblaze/cpu/exception.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/microblaze/cpu/exception.c b/arch/microblaze/cpu/exception.c index d37f04364a..d3640d3903 100644 --- a/arch/microblaze/cpu/exception.c +++ b/arch/microblaze/cpu/exception.c @@ -38,7 +38,7 @@ void _hw_exception_handler (void)
printf("Unaligned %sword access\n", ((state & 0x800) ? "" : "half")); printf("Unaligned %s access\n", ((state & 0x400) ? "store" : "load")); - printf("Register R%x\n", (state & 0x3E) >> 5); + printf("Register R%x\n", (state & 0x3E0) >> 5); break; case 0x2: puts("Illegal op-code exception\n");

A user exception is triggered by inserting a bralid/brki jump to "C_BASE_VECTORS+0x8" in the software flow. Because u-boot microblaze code does not deal with MMU-related features such as user-mode/privileged-mode separation, there are no code sequences that call into the user exception handler.
It seems there is no real usecase for having user exception support in u-boot, so drop the code that installs the nop handler.
Signed-off-by: Ovidiu Panait ovidiu.panait@windriver.com ---
arch/microblaze/cpu/exception.c | 8 ----- arch/microblaze/cpu/start.S | 40 ++----------------------- board/xilinx/microblaze-generic/Kconfig | 9 ------ 3 files changed, 3 insertions(+), 54 deletions(-)
diff --git a/arch/microblaze/cpu/exception.c b/arch/microblaze/cpu/exception.c index d3640d3903..1f7c44d1f3 100644 --- a/arch/microblaze/cpu/exception.c +++ b/arch/microblaze/cpu/exception.c @@ -63,11 +63,3 @@ void _hw_exception_handler (void) printf("Return address from exception 0x%x\n", address); hang(); } - -#if CONFIG_IS_ENABLED(XILINX_MICROBLAZE0_USR_EXCEP) -void _exception_handler (void) -{ - puts("User vector_exception\n"); - hang(); -} -#endif diff --git a/arch/microblaze/cpu/start.S b/arch/microblaze/cpu/start.S index 645f7cb038..0ea0b78da9 100644 --- a/arch/microblaze/cpu/start.S +++ b/arch/microblaze/cpu/start.S @@ -97,9 +97,9 @@ clear_bss: * r5 - relocation offset (zero when setting up vectors before * relocation, and gd->reloc_off when setting up vectors after * relocation) - * - the relocation offset is added to the _exception_handler, - * _interrupt_handler and _hw_exception_handler symbols to reflect the - * post-relocation memory addresses + * - the relocation offset is added to the _interrupt_handler and + * _hw_exception_handler symbols to reflect the post-relocation memory + * addresses * * Reserve registers: * r10: Stores little/big endian offset for vectors @@ -149,40 +149,6 @@ __setup_exceptions: rsubi r8, r10, 0x6 sh r6, r4, r8
-#if CONFIG_IS_ENABLED(XILINX_MICROBLAZE0_USR_EXCEP) - /* user_vector_exception */ - swi r2, r4, 0x8 /* user vector exception - imm opcode */ - swi r3, r4, 0xC /* user vector exception - brai opcode */ - - addik r6, r5, _exception_handler - sw r6, r1, r0 - /* - * BIG ENDIAN memory map for user exception - * 0x8: 0xB000XXXX - * 0xC: 0xB808XXXX - * - * then it is necessary to count address for storing the most significant - * 16bits from _exception_handler address and copy it to - * 0xa address. Big endian use offset in r10=0 that's why is it just - * 0xa address. The same is done for the least significant 16 bits - * for 0xe address. - * - * LITTLE ENDIAN memory map for user exception - * 0x8: 0xXXXX00B0 - * 0xC: 0xXXXX08B8 - * - * Offset is for little endian setup to 0x2. rsubi instruction decrease - * address value to ensure that points to proper place which is - * 0x8 for the most significant 16 bits and - * 0xC for the least significant 16 bits - */ - lhu r7, r1, r10 - rsubi r8, r10, 0xa - sh r7, r4, r8 - rsubi r8, r10, 0xe - sh r6, r4, r8 -#endif - /* interrupt_handler */ swi r2, r4, 0x10 /* interrupt - imm opcode */ swi r3, r4, 0x14 /* interrupt - brai opcode */ diff --git a/board/xilinx/microblaze-generic/Kconfig b/board/xilinx/microblaze-generic/Kconfig index 117b476f3f..a0af2e9abd 100644 --- a/board/xilinx/microblaze-generic/Kconfig +++ b/board/xilinx/microblaze-generic/Kconfig @@ -38,15 +38,6 @@ config XILINX_MICROBLAZE0_HW_VER string "Core version number" default "7.10.d"
-config XILINX_MICROBLAZE0_USR_EXCEP - bool "MicroBlaze user exception support" - default y - help - Enable this option in order to install the user exception handler - (_exception_handler routine from arch/microblaze/cpu/exception.c) in - the exception vector table. The user exception vector is located at - C_BASE_VECTORS + 0x8 address. - config XILINX_MICROBLAZE0_DELAY_SLOT_EXCEP bool "MicroBlaze delay slot exception support" default y

On 2/13/22 09:09, Ovidiu Panait wrote:
A user exception is triggered by inserting a bralid/brki jump to "C_BASE_VECTORS+0x8" in the software flow. Because u-boot microblaze code does not deal with MMU-related features such as user-mode/privileged-mode separation, there are no code sequences that call into the user exception handler.
It seems there is no real usecase for having user exception support in u-boot, so drop the code that installs the nop handler.
U-Boot still supports to run user code on the top of u-boot which doesn't need to handle these kind of exceptions. That's why it is good to jump to this code and let you know about it.
M

Hi Michal,
On 2/15/22 14:16, Michal Simek wrote:
[Please note: This e-mail is from an EXTERNAL e-mail address]
On 2/13/22 09:09, Ovidiu Panait wrote:
A user exception is triggered by inserting a bralid/brki jump to "C_BASE_VECTORS+0x8" in the software flow. Because u-boot microblaze code does not deal with MMU-related features such as user-mode/privileged-mode separation, there are no code sequences that call into the user exception handler.
It seems there is no real usecase for having user exception support in u-boot, so drop the code that installs the nop handler.
U-Boot still supports to run user code on the top of u-boot which doesn't need to handle these kind of exceptions. That's why it is good to jump to this code and let you know about it.
Thanks for the feedback, this patch should just be ignored then.
The rest of this series I think it's still a good addition to the microblaze exception code.
Ovidiu
M
participants (2)
-
Michal Simek
-
Ovidiu Panait