arm: semihosting: Support semihosting fallback on 32-bit ARM

Add support for a semihosting fallback on 32-bit ARM. The assembly is
lightly adapted from the irq return code, except there is no offset
since lr already points to the correct instruction. The C side is mostly
like ARM64, except we have fewer cases to deal with.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
This commit is contained in:
Sean Anderson 2023-10-27 16:40:15 -04:00 committed by Tom Rini
parent 6ef83ab6be
commit 47cfdb2192
3 changed files with 40 additions and 2 deletions

View file

@ -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);

View file

@ -275,6 +275,13 @@ software_interrupt:
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:

View file

@ -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