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/cache.h>
 | 
				
			||||||
#include <arch/exception.h>
 | 
					#include <arch/exception.h>
 | 
				
			||||||
 | 
					#include <exception.h>
 | 
				
			||||||
#include <libpayload.h>
 | 
					#include <libpayload.h>
 | 
				
			||||||
#include <stdint.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;
 | 
					extern void *exception_stack_end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void exception_undefined_instruction(uint32_t *);
 | 
					struct exception_handler_info
 | 
				
			||||||
void exception_software_interrupt(uint32_t *);
 | 
					{
 | 
				
			||||||
void exception_prefetch_abort(uint32_t *);
 | 
						const char *name;
 | 
				
			||||||
void exception_data_abort(uint32_t *);
 | 
						exception_hook hook;
 | 
				
			||||||
void exception_not_used(uint32_t *);
 | 
					};
 | 
				
			||||||
void exception_irq(uint32_t *);
 | 
					
 | 
				
			||||||
void exception_fiq(uint32_t *);
 | 
					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)
 | 
					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");
 | 
						if (idx >= EXC_COUNT) {
 | 
				
			||||||
	print_regs(regs);
 | 
							printf("Bad exception index %d.\n", idx);
 | 
				
			||||||
	dump_stack(regs[13], 512);
 | 
						} else {
 | 
				
			||||||
	halt();
 | 
							struct exception_handler_info *info = &exceptions[idx];
 | 
				
			||||||
}
 | 
							if (info->hook) {
 | 
				
			||||||
 | 
								info->hook(idx, state);
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void exception_software_interrupt(uint32_t *regs)
 | 
							if (info->name)
 | 
				
			||||||
{
 | 
								printf("exception %s\n", info->name);
 | 
				
			||||||
	printf("exception _software_interrupt\n");
 | 
							else
 | 
				
			||||||
	print_regs(regs);
 | 
								printf("exception _not_used.\n");
 | 
				
			||||||
	dump_stack(regs[13], 512);
 | 
						}
 | 
				
			||||||
	halt();
 | 
						print_regs(state->regs);
 | 
				
			||||||
}
 | 
						dump_stack(state->regs[13], 512);
 | 
				
			||||||
 | 
					 | 
				
			||||||
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);
 | 
					 | 
				
			||||||
	halt();
 | 
						halt();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -146,3 +120,9 @@ void exception_init(void)
 | 
				
			|||||||
	set_vbar((uintptr_t)exception_table);
 | 
						set_vbar((uintptr_t)exception_table);
 | 
				
			||||||
	exception_stack_end = exception_stack + sizeof(exception_stack);
 | 
						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
 | 
						b	8f
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1:
 | 
					1:
 | 
				
			||||||
	ldr	sp, _not_used
 | 
						mov	sp, $0
 | 
				
			||||||
	b	exception_common
 | 
						b	exception_common
 | 
				
			||||||
2:
 | 
					2:
 | 
				
			||||||
	ldr	sp, _undefined_instruction
 | 
						mov	sp, $1
 | 
				
			||||||
	b	exception_common
 | 
						b	exception_common
 | 
				
			||||||
3:
 | 
					3:
 | 
				
			||||||
	ldr	sp, _software_interrupt
 | 
						mov	sp, $2
 | 
				
			||||||
	b	exception_common
 | 
						b	exception_common
 | 
				
			||||||
4:
 | 
					4:
 | 
				
			||||||
	ldr	sp, _prefetch_abort
 | 
						mov	sp, $3
 | 
				
			||||||
	b	exception_common
 | 
						b	exception_common
 | 
				
			||||||
5:
 | 
					5:
 | 
				
			||||||
	ldr	sp, _data_abort
 | 
						mov	sp, $4
 | 
				
			||||||
	b	exception_common
 | 
						b	exception_common
 | 
				
			||||||
6:
 | 
					6:
 | 
				
			||||||
	ldr	sp, _not_used
 | 
						mov	sp, $5
 | 
				
			||||||
	b	exception_common
 | 
						b	exception_common
 | 
				
			||||||
7:
 | 
					7:
 | 
				
			||||||
	ldr	sp, _irq
 | 
						mov	sp, $6
 | 
				
			||||||
	b	exception_common
 | 
						b	exception_common
 | 
				
			||||||
8:
 | 
					8:
 | 
				
			||||||
	ldr	sp, _fiq
 | 
						mov	sp, $7
 | 
				
			||||||
	b	exception_common
 | 
						b	exception_common
 | 
				
			||||||
 | 
					
 | 
				
			||||||
exception_common:
 | 
					exception_common:
 | 
				
			||||||
	str	sp, exception_handler
 | 
						str	sp, exception_idx
 | 
				
			||||||
	ldr	sp, exception_stack_end
 | 
						ldr	sp, exception_stack_end
 | 
				
			||||||
	push	{ lr }
 | 
						push	{ lr }
 | 
				
			||||||
	stmfd	sp, { sp, lr }^
 | 
						stmfd	sp, { sp, lr }^
 | 
				
			||||||
	sub	sp, sp, $8
 | 
						sub	sp, sp, $8
 | 
				
			||||||
	push	{ r0 - r12 }
 | 
						push	{ r0 - r12 }
 | 
				
			||||||
	mov	r0, sp
 | 
						mov	r0, sp
 | 
				
			||||||
	mov	lr, pc
 | 
						ldr	r1, exception_idx
 | 
				
			||||||
	ldr	pc, exception_handler
 | 
						blx	exception_dispatch
 | 
				
			||||||
	pop	{ r0 - r12 }
 | 
						pop	{ r0 - r12 }
 | 
				
			||||||
	add	sp, sp, $8
 | 
						add	sp, sp, $8
 | 
				
			||||||
	ldmfd	sp!, { pc }^
 | 
						ldmfd	sp!, { pc }^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.align 2
 | 
						.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
 | 
						.global exception_stack_end
 | 
				
			||||||
exception_stack_end:
 | 
					exception_stack_end:
 | 
				
			||||||
	.word 0
 | 
						.word 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
exception_handler:
 | 
					exception_idx:
 | 
				
			||||||
	.word 0
 | 
						.word 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.thumb
 | 
						.thumb
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,7 +27,7 @@
 | 
				
			|||||||
 * SUCH DAMAGE.
 | 
					 * SUCH DAMAGE.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <arch/exception.h>
 | 
					#include <exception.h>
 | 
				
			||||||
#include <libpayload.h>
 | 
					#include <libpayload.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unsigned int main_argc;    /**< The argc value to pass to main() */
 | 
					unsigned int main_argc;    /**< The argc value to pass to main() */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,39 +27,27 @@
 | 
				
			|||||||
 * SUCH DAMAGE.
 | 
					 * SUCH DAMAGE.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <arch/exception.h>
 | 
				
			||||||
#include <exception.h>
 | 
					#include <exception.h>
 | 
				
			||||||
#include <libpayload.h>
 | 
					#include <libpayload.h>
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint8_t exception_stack[0x1000] __attribute__((aligned(8)));
 | 
					uint8_t exception_stack[0x1000] __attribute__((aligned(8)));
 | 
				
			||||||
extern void *exception_stack_end;
 | 
					extern void *exception_stack_end;
 | 
				
			||||||
 | 
					extern struct exception_handler_state *exception_handler_state_handoff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct exception_state
 | 
					struct exception_handler_state
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u32 eax;
 | 
						struct exception_state regs;
 | 
				
			||||||
	u32 ecx;
 | 
					 | 
				
			||||||
	u32 edx;
 | 
					 | 
				
			||||||
	u32 ebx;
 | 
					 | 
				
			||||||
	u32 esp;
 | 
					 | 
				
			||||||
	u32 ebp;
 | 
					 | 
				
			||||||
	u32 esi;
 | 
					 | 
				
			||||||
	u32 edi;
 | 
					 | 
				
			||||||
	u32 eip;
 | 
					 | 
				
			||||||
	u32 eflags;
 | 
					 | 
				
			||||||
	u32 cs;
 | 
					 | 
				
			||||||
	u32 ss;
 | 
					 | 
				
			||||||
	u32 ds;
 | 
					 | 
				
			||||||
	u32 es;
 | 
					 | 
				
			||||||
	u32 fs;
 | 
					 | 
				
			||||||
	u32 gs;
 | 
					 | 
				
			||||||
	u32 error_code;
 | 
						u32 error_code;
 | 
				
			||||||
	u32 vector;
 | 
						u32 vector;
 | 
				
			||||||
} __attribute__((packed));
 | 
					} __attribute__((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct exception_info
 | 
					struct exception_handler_info
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char *name;
 | 
						const char *name;
 | 
				
			||||||
	void (*error_code_printer)(u32 code);
 | 
						void (*error_code_printer)(u32 code);
 | 
				
			||||||
 | 
						exception_hook hook;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void print_segment_error_code(u32 code)
 | 
					static void print_segment_error_code(u32 code)
 | 
				
			||||||
@@ -105,33 +93,33 @@ static void print_raw_error_code(u32 code)
 | 
				
			|||||||
	printf("%#x", code);
 | 
						printf("%#x", code);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct exception_info exceptions[] = {
 | 
					static struct exception_handler_info exceptions[EXC_COUNT] = {
 | 
				
			||||||
	[0] =  { .name = "divide by zero" },
 | 
						[EXC_DE] =  { .name = "divide by zero" },
 | 
				
			||||||
	[1] =  { .name = "debug" },
 | 
						[EXC_DB] =  { .name = "debug" },
 | 
				
			||||||
	[2] =  { .name = "non-maskable-interrupt" },
 | 
						[EXC_NMI] =  { .name = "non-maskable-interrupt" },
 | 
				
			||||||
	[3] =  { .name = "breakpoint" },
 | 
						[EXC_BP] =  { .name = "breakpoint" },
 | 
				
			||||||
	[4] =  { .name = "overflow" },
 | 
						[EXC_OF] =  { .name = "overflow" },
 | 
				
			||||||
	[5] =  { .name = "bound range" },
 | 
						[EXC_BR] =  { .name = "bound range" },
 | 
				
			||||||
	[6] =  { .name = "invalid opcode" },
 | 
						[EXC_UD] =  { .name = "invalid opcode" },
 | 
				
			||||||
	[7] =  { .name = "device not available" },
 | 
						[EXC_NM] =  { .name = "device not available" },
 | 
				
			||||||
	[8] =  { .name = "double fault",
 | 
						[EXC_DF] =  { .name = "double fault",
 | 
				
			||||||
		      .error_code_printer = &print_raw_error_code },
 | 
							      .error_code_printer = &print_raw_error_code },
 | 
				
			||||||
	[10] = { .name = "invalid tss",
 | 
						[EXC_TS] = { .name = "invalid tss",
 | 
				
			||||||
		     .error_code_printer = &print_segment_error_code },
 | 
							     .error_code_printer = &print_segment_error_code },
 | 
				
			||||||
	[11] = { .name = "segment not present",
 | 
						[EXC_NP] = { .name = "segment not present",
 | 
				
			||||||
		     .error_code_printer = &print_segment_error_code },
 | 
							     .error_code_printer = &print_segment_error_code },
 | 
				
			||||||
	[12] = { .name = "stack",
 | 
						[EXC_SS] = { .name = "stack",
 | 
				
			||||||
		     .error_code_printer = &print_segment_error_code },
 | 
							     .error_code_printer = &print_segment_error_code },
 | 
				
			||||||
	[13] = { .name = "general protection",
 | 
						[EXC_GP] = { .name = "general protection",
 | 
				
			||||||
		     .error_code_printer = &print_segment_error_code },
 | 
							     .error_code_printer = &print_segment_error_code },
 | 
				
			||||||
	[14] = { .name = "page fault",
 | 
						[EXC_PF] = { .name = "page fault",
 | 
				
			||||||
		     .error_code_printer = &print_page_fault_error_code },
 | 
							     .error_code_printer = &print_page_fault_error_code },
 | 
				
			||||||
	[16] = { .name = "x87 floating point" },
 | 
						[EXC_MF] = { .name = "x87 floating point" },
 | 
				
			||||||
	[17] = { .name = "alignment check",
 | 
						[EXC_AC] = { .name = "alignment check",
 | 
				
			||||||
		     .error_code_printer = &print_raw_error_code },
 | 
							     .error_code_printer = &print_raw_error_code },
 | 
				
			||||||
	[18] = { .name = "machine check" },
 | 
						[EXC_MC] = { .name = "machine check" },
 | 
				
			||||||
	[19] = { .name = "SIMD floating point" },
 | 
						[EXC_XF] = { .name = "SIMD floating point" },
 | 
				
			||||||
	[30] = { .name = "security",
 | 
						[EXC_SX] = { .name = "security",
 | 
				
			||||||
		     .error_code_printer = &print_raw_error_code },
 | 
							     .error_code_printer = &print_raw_error_code },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -150,16 +138,9 @@ static void dump_stack(uintptr_t addr, size_t bytes)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void exception_handler(void);
 | 
					static void dump_exception_state(struct exception_handler_state *state,
 | 
				
			||||||
void exception_handler(void)
 | 
									 struct exception_handler_info *info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct exception_state *state =
 | 
					 | 
				
			||||||
		(void *)((u8 *)exception_stack_end - sizeof(*state));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct exception_info *info = NULL;
 | 
					 | 
				
			||||||
	if (state->vector < ARRAY_SIZE(exceptions))
 | 
					 | 
				
			||||||
		info = &exceptions[state->vector];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (info)
 | 
						if (info)
 | 
				
			||||||
		printf("Exception %d (%s)\n", state->vector, info->name);
 | 
							printf("Exception %d (%s)\n", state->vector, info->name);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
@@ -169,31 +150,50 @@ void exception_handler(void)
 | 
				
			|||||||
		info->error_code_printer(state->error_code);
 | 
							info->error_code_printer(state->error_code);
 | 
				
			||||||
		printf("\n");
 | 
							printf("\n");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	printf("EIP:    0x%08x\n", state->eip);
 | 
						printf("EIP:    0x%08x\n", state->regs.eip);
 | 
				
			||||||
	printf("CS:     0x%04x\n", state->cs);
 | 
						printf("CS:     0x%04x\n", state->regs.cs);
 | 
				
			||||||
	printf("EFLAGS: 0x%08x\n", state->eflags);
 | 
						printf("EFLAGS: 0x%08x\n", state->regs.eflags);
 | 
				
			||||||
	printf("EAX:    0x%08x\n", state->eax);
 | 
						printf("EAX:    0x%08x\n", state->regs.eax);
 | 
				
			||||||
	printf("ECX:    0x%08x\n", state->ecx);
 | 
						printf("ECX:    0x%08x\n", state->regs.ecx);
 | 
				
			||||||
	printf("EDX:    0x%08x\n", state->edx);
 | 
						printf("EDX:    0x%08x\n", state->regs.edx);
 | 
				
			||||||
	printf("EBX:    0x%08x\n", state->ebx);
 | 
						printf("EBX:    0x%08x\n", state->regs.ebx);
 | 
				
			||||||
	printf("ESP:    0x%08x\n", state->esp);
 | 
						printf("ESP:    0x%08x\n", state->regs.esp);
 | 
				
			||||||
	printf("EBP:    0x%08x\n", state->ebp);
 | 
						printf("EBP:    0x%08x\n", state->regs.ebp);
 | 
				
			||||||
	printf("ESI:    0x%08x\n", state->esi);
 | 
						printf("ESI:    0x%08x\n", state->regs.esi);
 | 
				
			||||||
	printf("EDI:    0x%08x\n", state->edi);
 | 
						printf("EDI:    0x%08x\n", state->regs.edi);
 | 
				
			||||||
	printf("DS:     0x%04x\n", state->ds);
 | 
						printf("DS:     0x%04x\n", state->regs.ds);
 | 
				
			||||||
	printf("ES:     0x%04x\n", state->es);
 | 
						printf("ES:     0x%04x\n", state->regs.es);
 | 
				
			||||||
	printf("SS:     0x%04x\n", state->ss);
 | 
						printf("SS:     0x%04x\n", state->regs.ss);
 | 
				
			||||||
	printf("FS:     0x%04x\n", state->fs);
 | 
						printf("FS:     0x%04x\n", state->regs.fs);
 | 
				
			||||||
	printf("GS:     0x%04x\n", state->gs);
 | 
						printf("GS:     0x%04x\n", state->regs.gs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
	dump_stack(state->esp, 512);
 | 
					
 | 
				
			||||||
 | 
					void exception_dispatch(void)
 | 
				
			||||||
	halt();
 | 
					{
 | 
				
			||||||
 | 
						struct exception_handler_state *state =
 | 
				
			||||||
 | 
							exception_handler_state_handoff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct exception_handler_info *info = NULL;
 | 
				
			||||||
 | 
						if (state->vector < EXC_COUNT)
 | 
				
			||||||
 | 
							info = &exceptions[state->vector];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info && info->hook) {
 | 
				
			||||||
 | 
							info->hook(state->vector, &state->regs);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							dump_exception_state(state, info);
 | 
				
			||||||
 | 
							dump_stack(state->regs.esp, 512);
 | 
				
			||||||
 | 
							halt();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void exception_init_asm(void);
 | 
					 | 
				
			||||||
void exception_init(void)
 | 
					void exception_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	exception_stack_end = exception_stack + sizeof(exception_stack);
 | 
						exception_stack_end = exception_stack + sizeof(exception_stack);
 | 
				
			||||||
	exception_init_asm();
 | 
						exception_init_asm();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void exception_install_hook(int type, exception_hook hook)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						die_if(type >= EXC_COUNT, "Out of bound exception type %d.\n", type);
 | 
				
			||||||
 | 
						exceptions[type].hook = hook;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,6 +31,9 @@
 | 
				
			|||||||
	.global exception_stack_end
 | 
						.global exception_stack_end
 | 
				
			||||||
exception_stack_end:
 | 
					exception_stack_end:
 | 
				
			||||||
	.long 0
 | 
						.long 0
 | 
				
			||||||
 | 
						.global exception_handler_state_handoff
 | 
				
			||||||
 | 
					exception_handler_state_handoff:
 | 
				
			||||||
 | 
						.long 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Some temporary variables which are used while saving exception state. */
 | 
					/* Some temporary variables which are used while saving exception state. */
 | 
				
			||||||
vector:
 | 
					vector:
 | 
				
			||||||
@@ -134,11 +137,13 @@ exception_common:
 | 
				
			|||||||
	pushl	old_eax
 | 
						pushl	old_eax
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Call the C exception handler. It will find the exception state on
 | 
						 * Call the C exception handler. It will find the exception state
 | 
				
			||||||
	 * the exception stack. Not passing parameters means we don't have to
 | 
						 * using the exception_handler_state_handoff global pointer. Not
 | 
				
			||||||
	 * worry about what ABI is being used.
 | 
						 * passing parameters means we don't have to worry about what ABI
 | 
				
			||||||
 | 
						 * is being used.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	call	exception_handler
 | 
						mov	%esp, exception_handler_state_handoff
 | 
				
			||||||
 | 
						call	exception_dispatch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Restore state from the exception state structure, including any
 | 
						 * Restore state from the exception state structure, including any
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,9 +30,23 @@
 | 
				
			|||||||
#ifndef _ARCH_EXCEPTION_H
 | 
					#ifndef _ARCH_EXCEPTION_H
 | 
				
			||||||
#define _ARCH_EXCEPTION_H
 | 
					#define _ARCH_EXCEPTION_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <exception.h>
 | 
					 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void set_vbar(uint32_t vbar);
 | 
					void set_vbar(uint32_t vbar);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct exception_state
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t regs[16];
 | 
				
			||||||
 | 
					} __attribute__((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						EXC_UNDEF = 1,
 | 
				
			||||||
 | 
						EXC_SWI = 2,
 | 
				
			||||||
 | 
						EXC_PABORT = 3,
 | 
				
			||||||
 | 
						EXC_DABORT = 4,
 | 
				
			||||||
 | 
						EXC_IRQ = 6,
 | 
				
			||||||
 | 
						EXC_FIQ = 7,
 | 
				
			||||||
 | 
						EXC_COUNT
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,8 +30,11 @@
 | 
				
			|||||||
#ifndef _EXCEPTION_H
 | 
					#ifndef _EXCEPTION_H
 | 
				
			||||||
#define _EXCEPTION_H
 | 
					#define _EXCEPTION_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <arch/exception.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef void (*exception_hook)(int type, struct exception_state *state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void exception_init(void);
 | 
					void exception_init(void);
 | 
				
			||||||
 | 
					void exception_install_hook(int type, exception_hook hook);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										81
									
								
								payloads/libpayload/include/x86/arch/exception.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								payloads/libpayload/include/x86/arch/exception.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is part of the libpayload project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright 2013 Google Inc.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 * 1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *    notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 * 2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *    notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *    documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 * 3. The name of the author may not be used to endorse or promote products
 | 
				
			||||||
 | 
					 *    derived from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 | 
				
			||||||
 | 
					 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 | 
				
			||||||
 | 
					 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
				
			||||||
 | 
					 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
				
			||||||
 | 
					 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
				
			||||||
 | 
					 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
				
			||||||
 | 
					 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
				
			||||||
 | 
					 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
				
			||||||
 | 
					 * SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _ARCH_EXCEPTION_H
 | 
				
			||||||
 | 
					#define _ARCH_EXCEPTION_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void exception_dispatch(void);
 | 
				
			||||||
 | 
					void exception_init_asm(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct exception_state
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t eax;
 | 
				
			||||||
 | 
						uint32_t ecx;
 | 
				
			||||||
 | 
						uint32_t edx;
 | 
				
			||||||
 | 
						uint32_t ebx;
 | 
				
			||||||
 | 
						uint32_t esp;
 | 
				
			||||||
 | 
						uint32_t ebp;
 | 
				
			||||||
 | 
						uint32_t esi;
 | 
				
			||||||
 | 
						uint32_t edi;
 | 
				
			||||||
 | 
						uint32_t eip;
 | 
				
			||||||
 | 
						uint32_t eflags;
 | 
				
			||||||
 | 
						uint32_t cs;
 | 
				
			||||||
 | 
						uint32_t ss;
 | 
				
			||||||
 | 
						uint32_t ds;
 | 
				
			||||||
 | 
						uint32_t es;
 | 
				
			||||||
 | 
						uint32_t fs;
 | 
				
			||||||
 | 
						uint32_t gs;
 | 
				
			||||||
 | 
					} __attribute__((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						EXC_DE = 0, /* Divide by zero */
 | 
				
			||||||
 | 
						EXC_DB = 1, /* Debug */
 | 
				
			||||||
 | 
						EXC_NMI = 2, /* Non maskable interrupt */
 | 
				
			||||||
 | 
						EXC_BP = 3, /* Breakpoint */
 | 
				
			||||||
 | 
						EXC_OF = 4, /* Overflow */
 | 
				
			||||||
 | 
						EXC_BR = 5, /* Bound range */
 | 
				
			||||||
 | 
						EXC_UD = 6, /* Invalid opcode */
 | 
				
			||||||
 | 
						EXC_NM = 7, /* Device not available */
 | 
				
			||||||
 | 
						EXC_DF = 8, /* Double fault */
 | 
				
			||||||
 | 
						EXC_TS = 10, /* Invalid TSS */
 | 
				
			||||||
 | 
						EXC_NP = 11, /* Segment not present */
 | 
				
			||||||
 | 
						EXC_SS = 12, /* Stack */
 | 
				
			||||||
 | 
						EXC_GP = 13, /* General protection */
 | 
				
			||||||
 | 
						EXC_PF = 14, /* Page fault */
 | 
				
			||||||
 | 
						EXC_MF = 16, /* x87 floating point */
 | 
				
			||||||
 | 
						EXC_AC = 17, /* Alignment check */
 | 
				
			||||||
 | 
						EXC_MC = 18, /* Machine check */
 | 
				
			||||||
 | 
						EXC_XF = 19, /* SIMD floating point */
 | 
				
			||||||
 | 
						EXC_SX = 30, /* Security */
 | 
				
			||||||
 | 
						EXC_COUNT
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
		Reference in New Issue
	
	Block a user