From debfa55f86fb8ca71979ab5726a2ba840385c648 Mon Sep 17 00:00:00 2001 From: marcan Date: Fri, 16 Jan 2009 08:53:57 +0100 Subject: [PATCH] Add exception handler. This one *does* work! --- Makefile | 3 +- exception.c | 87 +++++++++++++++++++++++++++++++++ exception.h | 7 +++ exception_asm.S | 124 ++++++++++++++++++++++++++++++++++++++++++++++++ main.c | 5 +- miniios.ld | 15 ++++++ start.S | 27 +++-------- 7 files changed, 244 insertions(+), 24 deletions(-) create mode 100644 exception.c create mode 100644 exception.h create mode 100644 exception_asm.S diff --git a/Makefile b/Makefile index e73ec02..72e5e7b 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,8 @@ MAKEBIN = python ../makebin.py TARGET = miniios.bin ELF = miniios.elf OBJECTS = start.o ipcstruct.o main.o ipc.o vsprintf.o string.o gecko.o memory.o memory_asm.o \ - utils_asm.o utils.o ff.o diskio.o sdhc.o powerpc_elf.o powerpc.o panic.o irq.o irq_asm.o + utils_asm.o utils.o ff.o diskio.o sdhc.o powerpc_elf.o powerpc.o panic.o irq.o irq_asm.o \ + exception.o exception_asm.o $(TARGET) : $(ELF) $(ELFLOADER) @echo "MAKEBIN $@" diff --git a/exception.c b/exception.c new file mode 100644 index 0000000..72c0e30 --- /dev/null +++ b/exception.c @@ -0,0 +1,87 @@ +#include "irq.h" +#include "hollywood.h" +#include "gecko.h" +#include "utils.h" +#include "ipc.h" +#include "memory.h" + +const char *exceptions[] = { + "RESET", "UNDEFINED", "SWI", "INSTR ABORT", "DATA ABORT", "RESERVED", "IRQ", "FIQ" +}; + +const char *aborts[] = { + "UNDEFINED", + "Alignment", + "UNDEFINED", + "Alignment", + "UNDEFINED", + "Translation", + "UNDEFINED", + "Translation", + "External abort", + "Domain", + "External abort", + "Domain", + "External abort on translation (first level)", + "Permission", + "External abort on translation (second level)", + "Permission" +}; + +u8 domvalid[] = {0,0,0,0,0,0,0,1,0,1,0,1,0,1,1,1}; + +void exc_setup_stack(void); + +void exception_initialize(void) +{ + exc_setup_stack(); + u32 cr = get_cr(); + cr |= 0x2; // Data alignment fault checking enable + set_cr(cr); +} + +void exc_handler(u32 type, u32 spsr, u32 *regs) +{ + gecko_printf("\nException %d (%s):\n", type, exceptions[type]); + + u32 pc; + + switch(type) { + case 3: + case 7: + pc = regs[15] - 4; + break; + case 4: + pc = regs[15] - 8; + break; + default: + pc = regs[15]; + break; + } + + gecko_printf("Registers (%p):\n", regs); + gecko_printf(" R0-R3: %08x %08x %08x %08x\n", regs[0], regs[1], regs[2], regs[3]); + gecko_printf(" R4-R7: %08x %08x %08x %08x\n", regs[4], regs[5], regs[6], regs[7]); + gecko_printf(" R8-R11: %08x %08x %08x %08x\n", regs[8], regs[9], regs[10], regs[11]); + gecko_printf("R12-R15: %08x %08x %08x %08x\n", regs[12], regs[13], regs[14], pc); + + gecko_printf("SPSR: %08x\n", spsr); + gecko_printf("CR: %08x\n", get_cr()); + gecko_printf("TTBR: %08x\n", get_ttbr()); + gecko_printf("DACR: %08x\n", get_dacr()); + + if(type == 3 || type == 4) { + u32 fsr; + if(type == 3) + fsr = get_ifsr(); + else + fsr = get_dfsr(); + gecko_printf("Abort type: %s\n", aborts[fsr&0xf]); + if(domvalid[fsr&0xf]) + gecko_printf("Domain: %d\n", (fsr>>4)&0xf); + if(type == 4) + gecko_printf("Address: 0x%08x\n", get_far()); + } + + panic(0xA3); +} diff --git a/exception.h b/exception.h new file mode 100644 index 0000000..0d7628d --- /dev/null +++ b/exception.h @@ -0,0 +1,7 @@ +#ifndef __EXCEPTION_H__ +#define __EXCEPTION_H__ + +void exception_initialize(void); + +#endif + diff --git a/exception_asm.S b/exception_asm.S new file mode 100644 index 0000000..20a34ee --- /dev/null +++ b/exception_asm.S @@ -0,0 +1,124 @@ +.globl v_undf +.globl v_swi +.globl v_instr_abrt +.globl v_data_abrt +.globl v_reserved +.globl v_fiq + +.globl exc_setup_stack +.extern __excstack_addr +.extern exc_handler + +exc_setup_stack: + mrs r0, cpsr + + @ Switch to FIQ mode + msr cpsr_c, #0xd1 + @ Setup exception stack + ldr sp, =__excstack_addr + + @ Switch to SVC mode + msr cpsr_c, #0xd3 + @ Setup exception stack + ldr sp, =__excstack_addr + + @ Switch to ABORT mode + msr cpsr_c, #0xd7 + @ Setup exception stack + ldr sp, =__excstack_addr + + @ Switch to UNDF mode + msr cpsr_c, #0xdb + @ Setup exception stack + ldr sp, =__excstack_addr + + @ Restore mode + msr cpsr_c, r0 + bx lr + +.pool + +v_undf: + stmfd sp!, {lr} + stmfd sp, {r0-lr}^ + sub sp, sp, #0x3c + mov r2, sp + mrs r1, spsr + mov r0, #1 + + blx exc_handler + + ldmfd sp!, {r0-r12} + add sp, sp, #8 + movs pc, lr + +v_swi: + stmfd sp!, {lr} + stmfd sp, {r0-lr}^ + sub sp, sp, #0x3c + mov r2, sp + mrs r1, spsr + mov r0, #2 + + blx exc_handler + + ldmfd sp!, {r0-r12} + add sp, sp, #8 + movs pc, lr + +v_instr_abrt: + stmfd sp!, {lr} + stmfd sp, {r0-lr}^ + sub sp, sp, #0x3c + mov r2, sp + mrs r1, spsr + mov r0, #3 + + blx exc_handler + + ldmfd sp!, {r0-r12} + add sp, sp, #8 + subs pc, lr, #4 + +v_data_abrt: + stmfd sp!, {lr} + stmfd sp, {r0-lr}^ + sub sp, sp, #0x3c + mov r2, sp + mrs r1, spsr + mov r0, #4 + + blx exc_handler + + ldmfd sp!, {r0-r12} + add sp, sp, #8 + subs pc, lr, #8 + +v_reserved: + stmfd sp!, {lr} + stmfd sp, {r0-lr}^ + sub sp, sp, #0x3c + mov r2, sp + mrs r1, spsr + mov r0, #5 + + blx exc_handler + + ldmfd sp!, {r0-r12} + add sp, sp, #8 + movs pc, lr + +v_fiq: + stmfd sp!, {lr} + stmfd sp, {r0-lr}^ + sub sp, sp, #0x3c + mov r2, sp + mrs r1, spsr + mov r0, #7 + + blx exc_handler + + ldmfd sp!, {r0-r12} + add sp, sp, #8 + subs pc, lr, #4 + diff --git a/main.c b/main.c index 40aaa9e..e26cae4 100644 --- a/main.c +++ b/main.c @@ -12,6 +12,7 @@ #include "powerpc_elf.h" #include "irq.h" #include "ipc.h" +#include "exception.h" void *vector; @@ -150,11 +151,11 @@ void *_main(void *base) gecko_init(); gecko_puts("MiniIOS v0.1 loading\n"); + gecko_puts("Initializing exceptions...\n"); + exception_initialize(); gecko_puts("Configuring caches and MMU...\n"); mem_initialize(); - - irq_initialize(); irq_enable(IRQ_TIMER); irq_enable(IRQ_NAND); diff --git a/miniios.ld b/miniios.ld index bef6158..40f7959 100644 --- a/miniios.ld +++ b/miniios.ld @@ -5,6 +5,7 @@ ENTRY(_start) __stack_size = 0x800; __irqstack_size = 0x100; +__excstack_size = 0x100; MEMORY { sram : ORIGIN = 0xffff0000, LENGTH = 64K @@ -103,14 +104,28 @@ SECTIONS . = . +__irqstack_size; . = ALIGN(64); __irqstack_addr = .; + __excstack_end = .; + . = . +__excstack_size; + . = ALIGN(64); + __excstack_addr = .; + } >sram2 + + .pagetable : + { + . = ALIGN(16384); + __page_table = .; + . = . + 16384; } >sram2 } +PROVIDE (__page_table = __page_table); PROVIDE (__stack_end = __stack_end); PROVIDE (__stack_addr = __stack_addr); PROVIDE (__irqstack_end = __irqstack_end); PROVIDE (__irqstack_addr = __irqstack_addr); +PROVIDE (__excstack_end = __excstack_end); +PROVIDE (__excstack_addr = __excstack_addr); PROVIDE (__bss_start = __bss_start); PROVIDE (__bss_end = __bss_end); PROVIDE (__bss2_start = __bss2_start); diff --git a/start.S b/start.S index db033cd..388cdb7 100644 --- a/start.S +++ b/start.S @@ -11,7 +11,13 @@ .globl _start .globl debug_output +.extern v_undf +.extern v_swi +.extern v_instr_abrt +.extern v_data_abrt +.extern v_reserved .extern v_irq +.extern v_fiq .section .init @@ -80,27 +86,6 @@ done_bss2: .pool -v_undf: - b v_undf - -v_swi: - b v_swi - -v_instr_abrt: - b v_instr_abrt - -v_data_abrt: - b v_data_abrt - -v_reserved: - b v_reserved - -#v_irq: -# b v_irq - -v_fiq: - b v_fiq - debug_output: @ load address of port mov r3, #0xd800000