From 9fcc1f09502b20a73ec2fe314900cddcb20d26b4 Mon Sep 17 00:00:00 2001 From: Morten Delenk Date: Mon, 1 May 2017 13:39:55 +0000 Subject: [PATCH] fixed arm register saving/restoring 3ds9 is broken rn --- kernel/arch/arm/3ds9/start.cpp | 5 ++ kernel/arch/arm/3ds9/start.s | 5 ++ kernel/arch/arm/interrupt.cpp | 40 +++++++++++- kernel/arch/arm/sourcegen.py | 83 ++++++++++++++++-------- kernel/hw/3ds9/vectorinit/vectorinit.cpp | 2 +- 5 files changed, 105 insertions(+), 30 deletions(-) diff --git a/kernel/arch/arm/3ds9/start.cpp b/kernel/arch/arm/3ds9/start.cpp index cbdf47f..0399332 100644 --- a/kernel/arch/arm/3ds9/start.cpp +++ b/kernel/arch/arm/3ds9/start.cpp @@ -7,6 +7,11 @@ PICAfb term; void main(); extern "C" void start() { main(); } void drivers_init() { + term << "initing main tty\n"; setMainTTY(&term); --term; + term << "Initing vectors\n"; + initVectors(); + term << "trying svc\n"; + asm volatile("svc #0"); } diff --git a/kernel/arch/arm/3ds9/start.s b/kernel/arch/arm/3ds9/start.s index 364d193..905d01e 100644 --- a/kernel/arch/arm/3ds9/start.s +++ b/kernel/arch/arm/3ds9/start.s @@ -86,6 +86,11 @@ _start: orr r0, r0, #(1<<0) mcr p15, 0, r0, c1, c0, 0 */ + //Certain bootloaders put the interrupt vectors in ITCM. + //We don't want to mess with ITCM, so we put it back + mrc p15, 0, r0, c1, c0, 0 + orr r0, #(1<<13) + mcr p15, 0, r0, c1, c0, 0 //Start start blx start diff --git a/kernel/arch/arm/interrupt.cpp b/kernel/arch/arm/interrupt.cpp index d0acc1d..099add6 100644 --- a/kernel/arch/arm/interrupt.cpp +++ b/kernel/arch/arm/interrupt.cpp @@ -1,5 +1,5 @@ +#include "include/regs.h" #include -#include void print_regdump(cpu_state *state) { (*out << "r0: ").puti(state->r0); (*out << " r1: ").puti(state->r1); @@ -7,4 +7,42 @@ void print_regdump(cpu_state *state) { (*out << " r3: ").puti(state->r3); (*out << " r4: ").puti(state->r4); (*out << " r5: ").puti(state->r5); + (*out << " r6: ").puti(state->r6); + (*out << " r7: ").puti(state->r7); + (*out << " r8: ").puti(state->r8); + (*out << " r9: ").puti(state->r9); + (*out << " r10: ").puti(state->r10); + (*out << " r11: ").puti(state->r11); + (*out << " r12: ").puti(state->r12); + (*out << " pc: ").puti(state->pc); + *out << "\n"; +} +extern "C" cpu_state *handleINT(int number, cpu_state *state) { + *out << "Interrupt"; + out->puti(number); + *out << " occurred!\n"; + if (number != 4) { + out->setColor(Color::RED); + print_regdump(state); + *out << "KERNEL PANIC: Unhandled CPU exception\n"; + // for(;;); + } + switch (number) { + case 0: + case 1: + case 2: + case 3: + if (state->cpsr & 0x20) + state->returnAddr -= 2; + else + state->returnAddr -= 4; + } + return state; +} +extern "C" void panic2(char *msg, cpu_state *state) { + out->setColor(Color::RED); + *out << "KERNEL PANIC: " << msg << "\n"; + print_regdump(state); + for (;;) + ; } diff --git a/kernel/arch/arm/sourcegen.py b/kernel/arch/arm/sourcegen.py index e8abcbc..ceaa4e0 100644 --- a/kernel/arch/arm/sourcegen.py +++ b/kernel/arch/arm/sourcegen.py @@ -2,49 +2,74 @@ int_handler.write( """\ .arm .fpu vfpv2 +.section .bss +.space 4096 +exception_stack: +.section .text .global branch_macro branch_macro: ldr pc, [pc, #-4] //Load the next word into PC +.macro interrupt_handler intid + //Set to the correct stack + ldr sp, =exception_stack + push {r0-r12,lr} //Push registers + + //Get previous sp and lr + mrs r1, cpsr //Current mode + mrs r0, spsr //Previous mode + orr r0, #0xC0 //Disable interrupts in the previous mode + bic r0, #0x20 //enable ARM mode in there + + //If the mode is user, switch to system mode + and r2, r0, #0x1F + cmp r2, #0x10 + bne 1f + orr r0, #0x1F +1: + //Change mode + msr cpsr, r0 + mov r2, sp + mov r3, lr + //Switch back + msr cpsr, r1 + mrs r0, spsr + + //Push those registers + push {r0, r2, r3, lr} + + //Set argument 1 + ldr r0, =\intid + + //Jump to generic handler + blx intr_common_handler + + //pop the special registers + pop {r0, r3, r4, lr} + tst r0, #0x20 //Is code ARM or thumb? + beq 2f + orr lr, lr, #1 //Enable thumb mode on return# +2: + str lr, [sp, #0x34] //Set correct lr + ldmfd sp!, {r0-r12, pc}^ //Return back to original mode +.endm .global data_abort data_abort: - sub lr, #4 - push {r0-r12,lr} - ldr r0, =0 - blx intr_common_handler - pop {r0-r12,pc} + interrupt_handler 0 .global fast_irq fast_irq: - sub lr, #4 - push {r0-r12,lr} - ldr r0, =1 - blx intr_common_handler - pop {r0-r12,pc} + interrupt_handler 1 .global normal_irq normal_irq: - sub lr, #4 - push {r0-r12,lr} - ldr r0, =2 - blx intr_common_handler - pop {r0-r12,pc} + interrupt_handler 2 .global prefetch_abort prefetch_abort: - sub lr, #4 - push {r0-r12,lr} - ldr r0, =3 - blx intr_common_handler - pop {r0-r12,pc} + interrupt_handler 3 .global svc_call svc_call: - push {r0-r12,lr} - ldr r0, =4 - blx intr_common_handler - pop {r0-r12,pc} + interrupt_handler 4 .global undefined_op undefined_op: - push {r0-r12,lr} - ldr r0, =5 - blx intr_common_handler - pop {r0-r12,pc} + interrupt_handler 5 .extern handleINT intr_common_handler: @@ -81,6 +106,8 @@ if ("ENABLE_HARD" in config) and config["ENABLE_HARD"]: reg_struct.write(" uint32_t "+reg+";\n") for reg in ("d"+str(i) for i in range(16)): reg_struct.write(" double "+reg+";\n") +for reg in ["cpsr","sp","lr","returnAddr"]: + reg_struct.write(" uint32_t "+reg+";\n") for i in range(13): reg_struct.write(" uint32_t r"+str(i)+";\n") reg_struct.write(" uint32_t pc;\n};") diff --git a/kernel/hw/3ds9/vectorinit/vectorinit.cpp b/kernel/hw/3ds9/vectorinit/vectorinit.cpp index e424ae7..8ee9afe 100644 --- a/kernel/hw/3ds9/vectorinit/vectorinit.cpp +++ b/kernel/hw/3ds9/vectorinit/vectorinit.cpp @@ -9,7 +9,7 @@ void svc_call(); void undefined_op(); } void initVectors() { - uintptr_t *vectors = (uintptr_t *)0x08000000; + uintptr_t *vectors = (uintptr_t *)0x0800000; // branch_macro is a ldr pc, [pc,#-4], meaning it reads the following word as PC vectors[0] = branch_macro; vectors[1] = (uintptr_t)&normal_irq;