mirror of
https://github.com/AsahiLinux/u-boot
synced 2025-02-17 22:49:02 +00:00
Merge branch '2023-11-10-improve-semihosting-armv6' into next
To quote the author: This series has a few fixes for semihosting on ARMv6 and older CPUs. The first two patches address problems regarding the stack pointer and link register. U-Boot runs in supervisor mode, so taking a software interrupt will clobber sp/lr. I think we really should run in system mode, since it has separate sp/lr registers. To quote ARM DDI 0100I: > The remaining mode is System mode, which is not entered by any > exception and has exactly the same registers available as User mode. > However, it is a privileged mode and is therefore not subject to the > User mode restrictions. It is intended for use by operating system > tasks that need access to system resources, but wish to avoid using > the additional registers associated with the exception modes. Avoiding > such use ensures that the task state is not corrupted by the > occurrence of any exception. However, the processor mode has been supervisor for such a long time (since relocation got introduced) that I would rather not touch it.
This commit is contained in:
commit
3b6db6901f
4 changed files with 59 additions and 3 deletions
|
@ -22,6 +22,7 @@
|
|||
#include <cpu_func.h>
|
||||
#include <efi_loader.h>
|
||||
#include <irq_func.h>
|
||||
#include <semihosting.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <asm/proc-armv/ptrace.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
@ -135,6 +136,32 @@ static inline void fixup_pc(struct pt_regs *regs, int offset)
|
|||
regs->ARM_pc = pc | (regs->ARM_pc & PCMASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to "emulate" a semihosting call in the event that we don't have a
|
||||
* debugger attached.
|
||||
*/
|
||||
static bool smh_emulate_trap(struct pt_regs *regs)
|
||||
{
|
||||
if (regs->ARM_cpsr & T_BIT) {
|
||||
u16 *insn = (u16 *)(regs->ARM_pc - 2);
|
||||
|
||||
if (*insn != SMH_T32_SVC)
|
||||
return false;
|
||||
} else {
|
||||
u32 *insn = (u32 *)(regs->ARM_pc - 4);
|
||||
|
||||
if (*insn != SMH_A32_SVC)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Avoid future semihosting calls */
|
||||
disable_semihosting();
|
||||
|
||||
/* Just pretend the call failed */
|
||||
regs->ARM_r0 = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
void do_undefined_instruction (struct pt_regs *pt_regs)
|
||||
{
|
||||
efi_restore_gd();
|
||||
|
@ -147,6 +174,10 @@ void do_undefined_instruction (struct pt_regs *pt_regs)
|
|||
|
||||
void do_software_interrupt (struct pt_regs *pt_regs)
|
||||
{
|
||||
if (CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK) &&
|
||||
smh_emulate_trap(pt_regs))
|
||||
return;
|
||||
|
||||
efi_restore_gd();
|
||||
printf ("software interrupt\n");
|
||||
fixup_pc(pt_regs, -4);
|
||||
|
|
|
@ -18,11 +18,17 @@ ENTRY(smh_trap)
|
|||
#elif defined(CONFIG_SYS_THUMB_BUILD)
|
||||
svc #0xab
|
||||
#else
|
||||
#if CONFIG_SYS_ARM_ARCH < 7
|
||||
/* Before the ARMv7 exception model, svc (swi) clobbers lr */
|
||||
mov r2, lr
|
||||
#endif
|
||||
svc #0x123456
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARM64)
|
||||
ret
|
||||
#elif CONFIG_SYS_ARM_ARCH < 7
|
||||
bx r2
|
||||
#else
|
||||
bx lr
|
||||
#endif
|
||||
|
|
|
@ -240,6 +240,18 @@ IRQ_STACK_START_IN:
|
|||
movs pc, lr @ jump to next instruction & switch modes.
|
||||
.endm
|
||||
|
||||
.macro get_bad_stack_swi
|
||||
sub r13, r13, #4 @ space on current stack for scratch reg.
|
||||
str r0, [r13] @ save R0's value.
|
||||
ldr r0, IRQ_STACK_START_IN @ get data regions start
|
||||
str lr, [r0] @ save caller lr in position 0 of saved stack
|
||||
mrs lr, spsr @ get the spsr
|
||||
str lr, [r0, #4] @ save spsr in position 1 of saved stack
|
||||
ldr lr, [r0] @ restore lr
|
||||
ldr r0, [r13] @ restore r0
|
||||
add r13, r13, #4 @ pop stack entry
|
||||
.endm
|
||||
|
||||
.macro get_irq_stack @ setup IRQ stack
|
||||
ldr sp, IRQ_STACK_START
|
||||
.endm
|
||||
|
@ -260,9 +272,16 @@ undefined_instruction:
|
|||
|
||||
.align 5
|
||||
software_interrupt:
|
||||
get_bad_stack
|
||||
get_bad_stack_swi
|
||||
bad_save_user_regs
|
||||
bl do_software_interrupt
|
||||
#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
|
||||
ldmia sp, {r0 - lr}^ @ Calling r0 - lr
|
||||
mov r0, r0
|
||||
ldr lr, [sp, #S_PC] @ Get PC
|
||||
add sp, sp, #S_FRAME_SIZE
|
||||
movs pc, lr @ return & move spsr_svc into cpsr
|
||||
#endif
|
||||
|
||||
.align 5
|
||||
prefetch_abort:
|
||||
|
|
|
@ -100,7 +100,7 @@ config SEMIHOSTING
|
|||
|
||||
config SEMIHOSTING_FALLBACK
|
||||
bool "Recover gracefully when semihosting fails"
|
||||
depends on SEMIHOSTING && (ARM64 || RISCV)
|
||||
depends on SEMIHOSTING
|
||||
default y
|
||||
help
|
||||
Normally, if U-Boot makes a semihosting call and no debugger is
|
||||
|
@ -123,7 +123,7 @@ config SPL_SEMIHOSTING
|
|||
|
||||
config SPL_SEMIHOSTING_FALLBACK
|
||||
bool "Recover gracefully when semihosting fails in SPL"
|
||||
depends on SPL_SEMIHOSTING && (ARM64 || RISCV)
|
||||
depends on SPL_SEMIHOSTING
|
||||
select ARMV8_SPL_EXCEPTION_VECTORS if ARM64
|
||||
default y
|
||||
help
|
||||
|
|
Loading…
Add table
Reference in a new issue