forked from Mirror/GodMode9
- enable the VFP on the ARM11
- stopped using the ITCM as the interrupt vector table - removed dead Thumb code handler in interrupt handling - added basic memory protection flags
This commit is contained in:
parent
8b098fa91a
commit
ca7944ce04
@ -5,7 +5,7 @@ TARGET := $(shell basename $(CURDIR))
|
||||
SOURCE := source
|
||||
BUILD := build
|
||||
|
||||
SUBARCH := -D$(PROCESSOR) -mcpu=mpcore -mtune=mpcore -mfloat-abi=soft -marm
|
||||
SUBARCH := -D$(PROCESSOR) -marm -march=armv6k -mtune=mpcore -mfloat-abi=hard -mfpu=vfpv2 -mtp=soft
|
||||
INCDIRS := source
|
||||
INCLUDE := $(foreach dir,$(INCDIRS),-I"$(shell pwd)/$(dir)")
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
.global __boot
|
||||
__boot:
|
||||
cpsid aif, #SR_SVC_MODE
|
||||
clrex
|
||||
|
||||
@ Writeback and invalidate all DCache
|
||||
@ Invalidate all caches
|
||||
@ -44,6 +45,18 @@ __boot:
|
||||
mcr p15, 0, r1, c1, c0, 1
|
||||
mcr p15, 0, r2, c1, c0, 2
|
||||
|
||||
@ VFPv2 init
|
||||
@ https://github.com/derrekr/fastboot3DS/blob/f63c967369451b1fd0078e649cf0010fe10a62fd/source/arm11/start.s#L195
|
||||
mov r0, #0
|
||||
mov r1, #0xF00000 @ Give full access to cp10/11 in user and privileged mode
|
||||
mov r2, #0x40000000 @ Clear exception bits and enable VFP11
|
||||
mov r3, #0x3C00000 @ Round towards zero (RZ) mode, flush-to-zero mode, default NaN mode
|
||||
mcr p15, 0, r1, c1, c0, 2 @ Write Coprocessor Access Control Register
|
||||
mcr p15, 0, r0, c7, c5, 4 @ Flush Prefetch Buffer
|
||||
fmxr fpexc, r2 @ Write Floating-point exception register
|
||||
fmxr fpscr, r3 @ Write Floating-Point Status and Control Register
|
||||
|
||||
|
||||
@ Get CPU ID
|
||||
mrc p15, 0, r12, c0, c0, 5
|
||||
ands r12, r12, #3
|
||||
|
@ -5,7 +5,7 @@ TARGET := $(shell basename $(CURDIR))
|
||||
SOURCE := source
|
||||
BUILD := build
|
||||
|
||||
SUBARCH := -D$(PROCESSOR) -mcpu=arm946e-s -mtune=arm946e-s -mfloat-abi=soft -mno-thumb-interwork -marm
|
||||
SUBARCH := -D$(PROCESSOR) -marm -march=armv5te -mtune=arm946e-s -mfloat-abi=soft -mno-thumb-interwork
|
||||
INCDIRS := source source/common source/filesys source/crypto source/fatfs source/nand source/virtual source/game source/gamecart source/lodepng source/qrcodegen source/system source/utils
|
||||
INCLUDE := $(foreach dir,$(INCDIRS),-I"$(shell pwd)/$(dir)")
|
||||
|
||||
|
47
arm9/link.ld
47
arm9/link.ld
@ -2,19 +2,46 @@ OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(_start)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
AHBWRAM (RWX) : ORIGIN = 0x08006000, LENGTH = 512K
|
||||
VECTORS (RX) : ORIGIN = 0x08000000, LENGTH = 64
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x08006000;
|
||||
__start__ = ABSOLUTE(.);
|
||||
|
||||
.text.start : ALIGN(4) { *(.text.start) }
|
||||
.text : ALIGN(4) { *(.text*) }
|
||||
.rodata : ALIGN(4) { *(.rodata*) }
|
||||
.data : ALIGN(4) { *(.data*) }
|
||||
.bss : ALIGN(4) { __bss_start = .; *(.bss* COMMON); __bss_end = .;}
|
||||
|
||||
.vectors : ALIGN(4) {
|
||||
__vectors_lma = LOADADDR(.vectors);
|
||||
__vectors_vma = ABSOLUTE(.);
|
||||
KEEP(*(.vectors));
|
||||
. = ALIGN(4);
|
||||
__vectors_len = ABSOLUTE(.) - __vectors_vma;
|
||||
} >VECTORS AT>AHBWRAM
|
||||
|
||||
.text : ALIGN(4) {
|
||||
__text_s = ABSOLUTE(.);
|
||||
*(.text.start);
|
||||
*(.text*);
|
||||
. = ALIGN(4);
|
||||
__text_e = ABSOLUTE(.);
|
||||
} >AHBWRAM
|
||||
|
||||
.rodata : ALIGN(4) {
|
||||
*(.rodata*);
|
||||
. = ALIGN(4);
|
||||
} >AHBWRAM
|
||||
|
||||
.data : ALIGN(4) {
|
||||
*(.data*);
|
||||
. = ALIGN(4);
|
||||
} >AHBWRAM
|
||||
|
||||
.bss : ALIGN(4) {
|
||||
__bss_start = .;
|
||||
*(.bss*);
|
||||
. = ALIGN(4);
|
||||
__bss_end = .;
|
||||
} >AHBWRAM
|
||||
|
||||
__end__ = ABSOLUTE(.);
|
||||
__code_size__ = __end__ - __start__;
|
||||
}
|
||||
|
@ -32,18 +32,18 @@ _start:
|
||||
ldr r0, =BRF_INVALIDATE_ICACHE
|
||||
blx r0 @ Invalidate Instruction Cache
|
||||
|
||||
@ Disable caches / DTCM / MPU
|
||||
ldr r1, =(CR_MPU | CR_CACHES | CR_DTCM | CR_TCM_LOAD)
|
||||
ldr r2, =(CR_ITCM)
|
||||
@ Disable caches / TCMs / MPU
|
||||
ldr r1, =(CR_MPU | CR_CACHES | CR_DTCM | CR_ITCM | CR_TCM_LOAD)
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
bic r0, r1
|
||||
orr r0, r2
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
@ Give full access to defined memory regions
|
||||
ldr r0, =0x33333333
|
||||
mcr p15, 0, r0, c5, c0, 2 @ write data access
|
||||
mcr p15, 0, r0, c5, c0, 3 @ write instruction access
|
||||
@ Set access permissions
|
||||
ldr r0, =0x11111115 @ RO data access for BootROM, RW otherwise
|
||||
ldr r1, =0x00505005 @ Can only execute code from ARM9 RAM, FCRAM and BootROM
|
||||
|
||||
mcr p15, 0, r0, c5, c0, 2
|
||||
mcr p15, 0, r1, c5, c0, 3
|
||||
|
||||
@ Set MPU regions and cache settings
|
||||
ldr r0, =__mpu_regions
|
||||
@ -64,15 +64,12 @@ _start:
|
||||
mcr p15, 0, r0, c2, c0, 0 @ Data cacheable
|
||||
mcr p15, 0, r0, c2, c0, 1 @ Inst cacheable
|
||||
|
||||
@ Enable DTCM
|
||||
@ Configure TCMs
|
||||
ldr r0, =0x3000800A
|
||||
mcr p15, 0, r0, c9, c1, 0 @ set the DTCM Region Register
|
||||
ldr r1, =0x00000024
|
||||
mcr p15, 0, r0, c9, c1, 0 @ DTCM
|
||||
mcr p15, 0, r1, c9, c1, 1 @ ITCM
|
||||
|
||||
@ Fix SDMC mounting
|
||||
@ (this is done in sdmmc.c instead)
|
||||
@ mov r0, #0x10000000
|
||||
@ mov r1, #0x340
|
||||
@ strh r1, [r0, #0x20]
|
||||
|
||||
@ Setup heap
|
||||
ldr r0, =fake_heap_start
|
||||
@ -84,18 +81,18 @@ _start:
|
||||
str r1, [r0]
|
||||
|
||||
@ Install exception handlers
|
||||
ldr r0, =XRQ_Start
|
||||
ldr r1, =XRQ_End
|
||||
ldr r2, =0x00000000
|
||||
ldr r0, =__vectors_lma
|
||||
ldr r1, =__vectors_len
|
||||
ldr r2, =XRQ_Start
|
||||
add r1, r0, r1
|
||||
.LXRQ_Install:
|
||||
cmp r0, r1
|
||||
ldrlo r3, [r0], #4
|
||||
strlo r3, [r2], #4
|
||||
blo .LXRQ_Install
|
||||
|
||||
@ Enable caches / DTCM / select low exception vectors
|
||||
ldr r1, =(CR_ALT_VECTORS | CR_V4TLD)
|
||||
ldr r2, =(CR_MPU | CR_CACHES | CR_DTCM)
|
||||
@ Enable caches / TCMs / select high exception vectors
|
||||
ldr r2, =(CR_MPU | CR_CACHES | CR_ITCM | CR_DTCM | CR_ALT_VECTORS)
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
bic r0, r1
|
||||
orr r0, r2
|
||||
@ -162,7 +159,7 @@ _start:
|
||||
__mpu_regions:
|
||||
.word 0xFFFF001F @ FFFF0000 64k | bootrom (unprotected / protected)
|
||||
.word 0x3000801B @ 30008000 16k | dtcm
|
||||
.word 0x00000035 @ 00000000 128M | itcm (+ mirrors)
|
||||
.word 0x01FF8035 @ 01FF8000 32k | itcm (+ mirrors)
|
||||
.word 0x08000029 @ 08000000 2M | arm9 mem (O3DS / N3DS)
|
||||
.word 0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB)
|
||||
.word 0x20000037 @ 20000000 256M | fcram (O3DS / N3DS)
|
||||
|
@ -15,23 +15,45 @@
|
||||
|
||||
#include <arm.h>
|
||||
|
||||
#define PC_DUMPRAD (0x30)
|
||||
#define SP_DUMPLEN (0x60)
|
||||
#define PC_DUMPRAD (0x40)
|
||||
#define SP_DUMPLEN (0x30)
|
||||
extern u32 __text_s, __text_e;
|
||||
|
||||
static bool sp_dumpable(u32 sp, u32 *sp_lower, u32 *sp_upper)
|
||||
{
|
||||
if ((sp >= __STACK_TOP) || (sp < (__STACK_TOP - __STACK_LEN)))
|
||||
return false;
|
||||
*sp_lower = sp;
|
||||
*sp_upper = min(sp + SP_DUMPLEN, __STACK_TOP);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool pc_dumpable(u32 pc, u32 *pc_lower, u32 *pc_upper)
|
||||
{
|
||||
u32 code_start = (u32)(&__text_s), code_end = (u32)(&__text_e);
|
||||
|
||||
if ((pc >= code_end) || (pc < code_start))
|
||||
return false;
|
||||
|
||||
*pc_lower = max(pc - PC_DUMPRAD, code_start);
|
||||
*pc_upper = min(pc + PC_DUMPRAD, code_end);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define XRQ_DUMPDATAFUNC(type, size) \
|
||||
int XRQ_DumpData_##type(char *b, u32 s, u32 e) \
|
||||
static unsigned XRQ_DumpData_##type(char *b, u32 s, u32 e) \
|
||||
{ \
|
||||
char *c = b; \
|
||||
while(s<e) { \
|
||||
b+=sprintf(b, "%08lX: ",s); \
|
||||
type *dl = (type*)s; \
|
||||
for (u32 i=0; i<(16/((size)/2)); i++) { \
|
||||
for (u32 i = 0; i < (16 / sizeof(type)); i++) { \
|
||||
b+=sprintf(b, "%0" #size "lX ", (u32)dl[i]); \
|
||||
} \
|
||||
b+=sprintf(b, "\n"); \
|
||||
s+=16; \
|
||||
} \
|
||||
return (int)(b-c); \
|
||||
return (unsigned)(b-c); \
|
||||
}
|
||||
XRQ_DUMPDATAFUNC(u8, 2)
|
||||
XRQ_DUMPDATAFUNC(u16, 4)
|
||||
@ -46,7 +68,7 @@ const char *XRQ_Name[] = {
|
||||
|
||||
void XRQ_DumpRegisters(u32 xrq, u32 *regs)
|
||||
{
|
||||
u32 sp, st, pc;
|
||||
u32 sp, sp_lower, sp_upper, pc, pc_lower, pc_upper;
|
||||
char dumpstr[2048], *wstr = dumpstr;
|
||||
|
||||
DsTime dstime;
|
||||
@ -75,25 +97,26 @@ void XRQ_DumpRegisters(u32 xrq, u32 *regs)
|
||||
ClearScreen(MAIN_SCREEN, COLOR_STD_BG);
|
||||
DrawStringF(MAIN_SCREEN, draw_x, draw_y, COLOR_STD_FONT, COLOR_STD_BG, dumpstr);
|
||||
|
||||
|
||||
/* Dump STACK */
|
||||
sp = regs[13] & ~0xF;
|
||||
st = __STACK_TOP;
|
||||
wstr += sprintf(wstr, "Stack dump:\n");
|
||||
wstr += XRQ_DumpData_u8(wstr, sp, min(sp+SP_DUMPLEN, st));
|
||||
if (sp_dumpable(sp, &sp_lower, &sp_upper)) {
|
||||
wstr += sprintf(wstr, "Stack:\n");
|
||||
wstr += XRQ_DumpData_u8(wstr, sp_lower, sp_upper);
|
||||
wstr += sprintf(wstr, "\n");
|
||||
}
|
||||
|
||||
|
||||
/* Dump TEXT */
|
||||
/* Dump CODE */
|
||||
pc = regs[15] & ~0xF;
|
||||
wstr += sprintf(wstr, "Code dump:\n");
|
||||
if (regs[16] & SR_THUMB) {
|
||||
if (pc_dumpable(pc, &pc_lower, &pc_upper)) {
|
||||
wstr += sprintf(wstr, "Code:\n");
|
||||
wstr += XRQ_DumpData_u32(wstr, pc_lower, pc_upper);
|
||||
/*if (regs[16] & SR_THUMB) { // no need to take Thumb code into account
|
||||
wstr += XRQ_DumpData_u16(wstr, pc-PC_DUMPRAD, pc+PC_DUMPRAD);
|
||||
} else {
|
||||
wstr += XRQ_DumpData_u32(wstr, pc-PC_DUMPRAD, pc+PC_DUMPRAD);
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
/* Draw QR Code */
|
||||
u8 qrcode[qrcodegen_BUFFER_LEN_MAX];
|
||||
u8 temp[qrcodegen_BUFFER_LEN_MAX];
|
||||
|
@ -3,125 +3,95 @@
|
||||
Read LICENSE for more details
|
||||
*/
|
||||
|
||||
.section .text.xrqh
|
||||
.arm
|
||||
|
||||
#include <arm.h>
|
||||
#include <brf.h>
|
||||
#include "memmap.h"
|
||||
|
||||
.macro XRQ_FATAL id=0
|
||||
ldr sp, =__STACK_ABT_TOP
|
||||
sub sp, sp, #(18*4) @ Reserve space for registers
|
||||
stmia sp, {r0-r12}
|
||||
mov r11, #\id
|
||||
b XRQ_MainHandler
|
||||
.macro TRAP_ENTRY xrq_id
|
||||
msr cpsr_f, #(\xrq_id << 29) @ preserve xrq id (idea grabbed from fb3ds)
|
||||
.endm
|
||||
|
||||
.section .vectors, "ax"
|
||||
.global XRQ_Start
|
||||
XRQ_Start:
|
||||
XRQ_Vectors:
|
||||
b XRQ_Reset
|
||||
b XRQ_Undefined
|
||||
b XRQ_SWI
|
||||
b XRQ_PAbort
|
||||
b XRQ_DAbort
|
||||
b . @ Reserved exception vector
|
||||
subs pc, lr, #4 @ IRQs are unhandled
|
||||
b . @ FIQs are unused (except for debug?)
|
||||
ldr pc, IRQ_Vector
|
||||
IRQ_Vector: .word IRQ_Handler
|
||||
ldr pc, FIQ_Vector
|
||||
FIQ_Vector: .word FIQ_Handler
|
||||
ldr pc, SVC_Vector
|
||||
SVC_Vector: .word SVC_Handler
|
||||
ldr pc, UND_Vector
|
||||
UND_Vector: .word UND_Handler
|
||||
ldr pc, PABT_Vector
|
||||
PABT_Vector: .word PABT_Handler
|
||||
ldr pc, DABT_Vector
|
||||
DABT_Vector: .word DABT_Handler
|
||||
.global XRQ_End
|
||||
XRQ_End:
|
||||
|
||||
XRQ_Reset:
|
||||
msr cpsr_c, #(SR_ABT_MODE | SR_NOINT)
|
||||
XRQ_FATAL 0
|
||||
|
||||
XRQ_Undefined:
|
||||
XRQ_FATAL 1
|
||||
.section .text.xrqs
|
||||
IRQ_Handler:
|
||||
TRAP_ENTRY 6
|
||||
b XRQ_Fatal
|
||||
|
||||
XRQ_SWI:
|
||||
XRQ_FATAL 2
|
||||
FIQ_Handler:
|
||||
TRAP_ENTRY 7
|
||||
b XRQ_Fatal
|
||||
|
||||
XRQ_PAbort:
|
||||
XRQ_FATAL 3
|
||||
SVC_Handler:
|
||||
TRAP_ENTRY 2
|
||||
b XRQ_Fatal
|
||||
|
||||
XRQ_DAbort:
|
||||
XRQ_FATAL 4
|
||||
UND_Handler:
|
||||
TRAP_ENTRY 1
|
||||
b XRQ_Fatal
|
||||
|
||||
@ r11 = exception number
|
||||
XRQ_MainHandler:
|
||||
mrs r10, cpsr
|
||||
mrs r9, spsr
|
||||
mov r8, lr
|
||||
PABT_Handler:
|
||||
TRAP_ENTRY 3
|
||||
b XRQ_Fatal
|
||||
|
||||
@ Disable mpu / caches
|
||||
ldr r4, =BRF_WB_INV_DCACHE
|
||||
ldr r5, =BRF_INVALIDATE_ICACHE
|
||||
ldr r6, =BRF_RESETCP15
|
||||
blx r4
|
||||
blx r5
|
||||
blx r6
|
||||
DABT_Handler:
|
||||
sub lr, lr, #4 @ R14_abt = PC + 8, so it needs a small additional fixup
|
||||
TRAP_ENTRY 4
|
||||
@b XRQ_Fatal
|
||||
|
||||
@ Retrieve banked registers
|
||||
ands r0, r9, #(SR_PMODE_MASK & (0x0F))
|
||||
orreq r0, #(SR_SYS_MODE)
|
||||
orr r0, #(0x10 | SR_NOINT)
|
||||
XRQ_Fatal:
|
||||
sub lr, lr, #4 @ PC exception fixup
|
||||
|
||||
msr cpsr_c, r0 @ Switch to previous mode
|
||||
mov r0, sp
|
||||
mov r1, lr
|
||||
msr cpsr_c, r10 @ Return to abort
|
||||
ldr sp, =(__STACK_ABT_TOP - 18*4) @ Set up abort stack, 8 byte aligned
|
||||
stmia sp, {r0-r7} @ Preserve non-banked GPRs
|
||||
|
||||
add r2, sp, #(13*4)
|
||||
stmia r2, {r0, r1, r8, r9}
|
||||
mrs r1, cpsr
|
||||
orr r0, r1, #SR_NOINT
|
||||
msr cpsr_c, r0 @ Disable interrupts
|
||||
|
||||
@ Give read/write access to all the memory regions
|
||||
ldr r0, =0x33333333
|
||||
mcr p15, 0, r0, c5, c0, 2 @ write data access
|
||||
mcr p15, 0, r0, c5, c0, 3 @ write instruction access
|
||||
lsr r0, r1, #29 @ Retrieve exception source
|
||||
|
||||
@ Sets MPU regions and cache settings
|
||||
adr r0, __abt_mpu_regions
|
||||
ldmia r0, {r1-r8}
|
||||
mov r0, #0b00110010 @ bootrom, arm9 mem and fcram are cacheable/bufferable
|
||||
mcr p15, 0, r1, c6, c0, 0
|
||||
mcr p15, 0, r2, c6, c1, 0
|
||||
mcr p15, 0, r3, c6, c2, 0
|
||||
mcr p15, 0, r4, c6, c3, 0
|
||||
mcr p15, 0, r5, c6, c4, 0
|
||||
mcr p15, 0, r6, c6, c5, 0
|
||||
mcr p15, 0, r7, c6, c6, 0
|
||||
mcr p15, 0, r8, c6, c7, 0
|
||||
mcr p15, 0, r0, c3, c0, 0 @ Write bufferable 0, 2, 5
|
||||
mcr p15, 0, r0, c2, c0, 0 @ Data cacheable 0, 2, 5
|
||||
mcr p15, 0, r0, c2, c0, 1 @ Inst cacheable 0, 2, 5
|
||||
mrs r2, spsr
|
||||
str lr, [sp, #15*4]
|
||||
str r2, [sp, #16*4] @ Preserve exception PC and CPSR
|
||||
|
||||
@ Enable mpu/caches
|
||||
ldr r1, =(CR_MPU | CR_CACHES | CR_DTCM)
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
orr r0, r0, r1
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
ands r2, r2, #SR_PMODE_MASK
|
||||
orreq r2, r2, #SR_SYS_MODE @ Force a switch to system mode if
|
||||
@ the exception happened in user mode
|
||||
orr r2, r2, #(0x10 | SR_NOINT) @ With interrupts disabled
|
||||
|
||||
add r3, sp, #8*4
|
||||
msr cpsr_c, r2
|
||||
nop
|
||||
nop
|
||||
stmia r3, {r8-r14} @ Preserve banked GPRs (R8-R12, SP_xrq, LR_xrq)
|
||||
nop
|
||||
nop
|
||||
msr cpsr_c, r1
|
||||
|
||||
ldr r2, =XRQ_DumpRegisters @ void XRQ_DumpRegisters(u32 xrq_id, u32 *regs)
|
||||
mov r1, sp
|
||||
mov r0, r11
|
||||
blx r2
|
||||
bl XRQ_DumpRegisters @ XRQ_DumpRegisters(exception_number, saved_regs);
|
||||
|
||||
msr cpsr, #(SR_SVC_MODE | SR_NOINT)
|
||||
mov r0, #0
|
||||
1:
|
||||
mcr p15, 0, r0, c7, c0, 4
|
||||
b 1b
|
||||
|
||||
.pool
|
||||
|
||||
__abt_mpu_regions:
|
||||
.word 0x0000003F @ 00000000 4G | background region (includes IO regs)
|
||||
.word 0xFFFF001F @ FFFF0000 64k | bootrom (unprotected / protected)
|
||||
.word 0x3000801B @ 30008000 16k | dtcm
|
||||
.word 0x00000035 @ 00000000 128M | itcm
|
||||
.word 0x08000029 @ 08000000 2M | arm9 mem (O3DS / N3DS)
|
||||
.word 0x20000037 @ 20000000 256M | fcram (O3DS / N3DS)
|
||||
.word 0x1FF00027 @ 1FF00000 1M | dsp / axi wram
|
||||
.word 0x1800002D @ 18000000 8M | vram (+ 2MB)
|
||||
|
||||
.global XRQ_End
|
||||
XRQ_End:
|
||||
|
Loading…
x
Reference in New Issue
Block a user