libpayload: Make it possible to install callbacks for particular exceptions.
To support a GDB stub, it will be necessary to trap various exceptions which will be used to implement breakpoints, single stepping, etc. BUG=None TEST=Built and booted on Link with hooks installed and saw that they triggered when exceptions occurred. Built and booted on nyan. BRANCH=None Original-Change-Id: Iab659365864a3055159a50b8f6e5c44290d3ba2b Original-Signed-off-by: Gabe Black <gabeblack@google.com> Original-Reviewed-on: https://chromium-review.googlesource.com/179602 Original-Reviewed-by: Gabe Black <gabeblack@chromium.org> Original-Tested-by: Gabe Black <gabeblack@chromium.org> Original-Commit-Queue: Gabe Black <gabeblack@chromium.org> (cherry picked from commit 8db0897b1ddad600e247cb4df147c757a8187626) Signed-off-by: Marc Jones <marc.jones@se-eng.com> Change-Id: I5e7f724b99988cd259909dd3bd01166fa52317ec Reviewed-on: http://review.coreboot.org/7656 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net> Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
@@ -29,19 +29,27 @@
|
||||
|
||||
#include <arch/cache.h>
|
||||
#include <arch/exception.h>
|
||||
#include <exception.h>
|
||||
#include <libpayload.h>
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t exception_stack[0x100] __attribute__((aligned(8)));
|
||||
uint8_t exception_stack[0x1000] __attribute__((aligned(8)));
|
||||
extern void *exception_stack_end;
|
||||
|
||||
void exception_undefined_instruction(uint32_t *);
|
||||
void exception_software_interrupt(uint32_t *);
|
||||
void exception_prefetch_abort(uint32_t *);
|
||||
void exception_data_abort(uint32_t *);
|
||||
void exception_not_used(uint32_t *);
|
||||
void exception_irq(uint32_t *);
|
||||
void exception_fiq(uint32_t *);
|
||||
struct exception_handler_info
|
||||
{
|
||||
const char *name;
|
||||
exception_hook hook;
|
||||
};
|
||||
|
||||
static struct exception_handler_info exceptions[EXC_COUNT] = {
|
||||
[EXC_UNDEF] = { "_undefined_instruction" },
|
||||
[EXC_SWI] = { "_software_interrupt" },
|
||||
[EXC_PABORT] = { "_prefetch_abort" },
|
||||
[EXC_DABORT] = { "_data_abort" },
|
||||
[EXC_IRQ] = { "_irq" },
|
||||
[EXC_FIQ] = { "_fiq" },
|
||||
};
|
||||
|
||||
static void dump_stack(uintptr_t addr, size_t bytes)
|
||||
{
|
||||
@@ -77,59 +85,25 @@ static void print_regs(uint32_t *regs)
|
||||
}
|
||||
}
|
||||
|
||||
void exception_undefined_instruction(uint32_t *regs)
|
||||
void exception_dispatch(struct exception_state *state, int idx);
|
||||
void exception_dispatch(struct exception_state *state, int idx)
|
||||
{
|
||||
printf("exception _undefined_instruction\n");
|
||||
print_regs(regs);
|
||||
dump_stack(regs[13], 512);
|
||||
halt();
|
||||
}
|
||||
if (idx >= EXC_COUNT) {
|
||||
printf("Bad exception index %d.\n", idx);
|
||||
} else {
|
||||
struct exception_handler_info *info = &exceptions[idx];
|
||||
if (info->hook) {
|
||||
info->hook(idx, state);
|
||||
return;
|
||||
}
|
||||
|
||||
void exception_software_interrupt(uint32_t *regs)
|
||||
{
|
||||
printf("exception _software_interrupt\n");
|
||||
print_regs(regs);
|
||||
dump_stack(regs[13], 512);
|
||||
halt();
|
||||
}
|
||||
|
||||
void exception_prefetch_abort(uint32_t *regs)
|
||||
{
|
||||
printf("exception _prefetch_abort\n");
|
||||
print_regs(regs);
|
||||
dump_stack(regs[13], 512);
|
||||
halt();
|
||||
}
|
||||
|
||||
void exception_data_abort(uint32_t *regs)
|
||||
{
|
||||
printf("exception _data_abort\n");
|
||||
print_regs(regs);
|
||||
dump_stack(regs[13], 512);
|
||||
halt();
|
||||
}
|
||||
|
||||
void exception_not_used(uint32_t *regs)
|
||||
{
|
||||
printf("exception _not_used\n");
|
||||
print_regs(regs);
|
||||
dump_stack(regs[13], 512);
|
||||
halt();
|
||||
}
|
||||
|
||||
void exception_irq(uint32_t *regs)
|
||||
{
|
||||
printf("exception _irq\n");
|
||||
print_regs(regs);
|
||||
dump_stack(regs[13], 512);
|
||||
halt();
|
||||
}
|
||||
|
||||
void exception_fiq(uint32_t *regs)
|
||||
{
|
||||
printf("exception _fiq\n");
|
||||
print_regs(regs);
|
||||
dump_stack(regs[13], 512);
|
||||
if (info->name)
|
||||
printf("exception %s\n", info->name);
|
||||
else
|
||||
printf("exception _not_used.\n");
|
||||
}
|
||||
print_regs(state->regs);
|
||||
dump_stack(state->regs[13], 512);
|
||||
halt();
|
||||
}
|
||||
|
||||
@@ -146,3 +120,9 @@ void exception_init(void)
|
||||
set_vbar((uintptr_t)exception_table);
|
||||
exception_stack_end = exception_stack + sizeof(exception_stack);
|
||||
}
|
||||
|
||||
void exception_install_hook(int type, exception_hook hook)
|
||||
{
|
||||
die_if(type >= EXC_COUNT, "Out of bounds exception index %d.\n", type);
|
||||
exceptions[type].hook = hook;
|
||||
}
|
||||
|
@@ -43,59 +43,51 @@ exception_table:
|
||||
b 8f
|
||||
|
||||
1:
|
||||
ldr sp, _not_used
|
||||
mov sp, $0
|
||||
b exception_common
|
||||
2:
|
||||
ldr sp, _undefined_instruction
|
||||
mov sp, $1
|
||||
b exception_common
|
||||
3:
|
||||
ldr sp, _software_interrupt
|
||||
mov sp, $2
|
||||
b exception_common
|
||||
4:
|
||||
ldr sp, _prefetch_abort
|
||||
mov sp, $3
|
||||
b exception_common
|
||||
5:
|
||||
ldr sp, _data_abort
|
||||
mov sp, $4
|
||||
b exception_common
|
||||
6:
|
||||
ldr sp, _not_used
|
||||
mov sp, $5
|
||||
b exception_common
|
||||
7:
|
||||
ldr sp, _irq
|
||||
mov sp, $6
|
||||
b exception_common
|
||||
8:
|
||||
ldr sp, _fiq
|
||||
mov sp, $7
|
||||
b exception_common
|
||||
|
||||
exception_common:
|
||||
str sp, exception_handler
|
||||
str sp, exception_idx
|
||||
ldr sp, exception_stack_end
|
||||
push { lr }
|
||||
stmfd sp, { sp, lr }^
|
||||
sub sp, sp, $8
|
||||
push { r0 - r12 }
|
||||
mov r0, sp
|
||||
mov lr, pc
|
||||
ldr pc, exception_handler
|
||||
ldr r1, exception_idx
|
||||
blx exception_dispatch
|
||||
pop { r0 - r12 }
|
||||
add sp, sp, $8
|
||||
ldmfd sp!, { pc }^
|
||||
|
||||
|
||||
.align 2
|
||||
_undefined_instruction: .word exception_undefined_instruction
|
||||
_software_interrupt: .word exception_software_interrupt
|
||||
_prefetch_abort: .word exception_prefetch_abort
|
||||
_data_abort: .word exception_data_abort
|
||||
_not_used: .word exception_not_used
|
||||
_irq: .word exception_irq
|
||||
_fiq: .word exception_fiq
|
||||
|
||||
.global exception_stack_end
|
||||
exception_stack_end:
|
||||
.word 0
|
||||
|
||||
exception_handler:
|
||||
exception_idx:
|
||||
.word 0
|
||||
|
||||
.thumb
|
||||
|
@@ -27,7 +27,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <arch/exception.h>
|
||||
#include <exception.h>
|
||||
#include <libpayload.h>
|
||||
|
||||
unsigned int main_argc; /**< The argc value to pass to main() */
|
||||
|
Reference in New Issue
Block a user