- 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:
Wolfvak 2019-05-26 12:47:58 -03:00 committed by d0k3
parent 8b098fa91a
commit ca7944ce04
7 changed files with 176 additions and 146 deletions

View File

@ -5,7 +5,7 @@ TARGET := $(shell basename $(CURDIR))
SOURCE := source SOURCE := source
BUILD := build 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 INCDIRS := source
INCLUDE := $(foreach dir,$(INCDIRS),-I"$(shell pwd)/$(dir)") INCLUDE := $(foreach dir,$(INCDIRS),-I"$(shell pwd)/$(dir)")

View File

@ -25,7 +25,8 @@
.global __boot .global __boot
__boot: __boot:
cpsid aif, #SR_SVC_MODE cpsid aif, #SR_SVC_MODE
clrex
@ Writeback and invalidate all DCache @ Writeback and invalidate all DCache
@ Invalidate all caches @ Invalidate all caches
@ -44,6 +45,18 @@ __boot:
mcr p15, 0, r1, c1, c0, 1 mcr p15, 0, r1, c1, c0, 1
mcr p15, 0, r2, c1, c0, 2 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 @ Get CPU ID
mrc p15, 0, r12, c0, c0, 5 mrc p15, 0, r12, c0, c0, 5
ands r12, r12, #3 ands r12, r12, #3

View File

@ -5,7 +5,7 @@ TARGET := $(shell basename $(CURDIR))
SOURCE := source SOURCE := source
BUILD := build 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 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)") INCLUDE := $(foreach dir,$(INCDIRS),-I"$(shell pwd)/$(dir)")

View File

@ -2,19 +2,46 @@ OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm) OUTPUT_ARCH(arm)
ENTRY(_start) ENTRY(_start)
MEMORY
{
AHBWRAM (RWX) : ORIGIN = 0x08006000, LENGTH = 512K
VECTORS (RX) : ORIGIN = 0x08000000, LENGTH = 64
}
SECTIONS SECTIONS
{ {
. = 0x08006000; .vectors : ALIGN(4) {
__start__ = ABSOLUTE(.); __vectors_lma = LOADADDR(.vectors);
__vectors_vma = ABSOLUTE(.);
KEEP(*(.vectors));
. = ALIGN(4);
__vectors_len = ABSOLUTE(.) - __vectors_vma;
} >VECTORS AT>AHBWRAM
.text.start : ALIGN(4) { *(.text.start) } .text : ALIGN(4) {
.text : ALIGN(4) { *(.text*) } __text_s = ABSOLUTE(.);
.rodata : ALIGN(4) { *(.rodata*) } *(.text.start);
.data : ALIGN(4) { *(.data*) } *(.text*);
.bss : ALIGN(4) { __bss_start = .; *(.bss* COMMON); __bss_end = .;} . = ALIGN(4);
__text_e = ABSOLUTE(.);
} >AHBWRAM
. = ALIGN(4); .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(.); __end__ = ABSOLUTE(.);
__code_size__ = __end__ - __start__;
} }

View File

@ -32,18 +32,18 @@ _start:
ldr r0, =BRF_INVALIDATE_ICACHE ldr r0, =BRF_INVALIDATE_ICACHE
blx r0 @ Invalidate Instruction Cache blx r0 @ Invalidate Instruction Cache
@ Disable caches / DTCM / MPU @ Disable caches / TCMs / MPU
ldr r1, =(CR_MPU | CR_CACHES | CR_DTCM | CR_TCM_LOAD) ldr r1, =(CR_MPU | CR_CACHES | CR_DTCM | CR_ITCM | CR_TCM_LOAD)
ldr r2, =(CR_ITCM)
mrc p15, 0, r0, c1, c0, 0 mrc p15, 0, r0, c1, c0, 0
bic r0, r1 bic r0, r1
orr r0, r2
mcr p15, 0, r0, c1, c0, 0 mcr p15, 0, r0, c1, c0, 0
@ Give full access to defined memory regions @ Set access permissions
ldr r0, =0x33333333 ldr r0, =0x11111115 @ RO data access for BootROM, RW otherwise
mcr p15, 0, r0, c5, c0, 2 @ write data access ldr r1, =0x00505005 @ Can only execute code from ARM9 RAM, FCRAM and BootROM
mcr p15, 0, r0, c5, c0, 3 @ write instruction access
mcr p15, 0, r0, c5, c0, 2
mcr p15, 0, r1, c5, c0, 3
@ Set MPU regions and cache settings @ Set MPU regions and cache settings
ldr r0, =__mpu_regions ldr r0, =__mpu_regions
@ -64,15 +64,12 @@ _start:
mcr p15, 0, r0, c2, c0, 0 @ Data cacheable mcr p15, 0, r0, c2, c0, 0 @ Data cacheable
mcr p15, 0, r0, c2, c0, 1 @ Inst cacheable mcr p15, 0, r0, c2, c0, 1 @ Inst cacheable
@ Enable DTCM @ Configure TCMs
ldr r0, =0x3000800A 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 @ Setup heap
ldr r0, =fake_heap_start ldr r0, =fake_heap_start
@ -84,18 +81,18 @@ _start:
str r1, [r0] str r1, [r0]
@ Install exception handlers @ Install exception handlers
ldr r0, =XRQ_Start ldr r0, =__vectors_lma
ldr r1, =XRQ_End ldr r1, =__vectors_len
ldr r2, =0x00000000 ldr r2, =XRQ_Start
add r1, r0, r1
.LXRQ_Install: .LXRQ_Install:
cmp r0, r1 cmp r0, r1
ldrlo r3, [r0], #4 ldrlo r3, [r0], #4
strlo r3, [r2], #4 strlo r3, [r2], #4
blo .LXRQ_Install blo .LXRQ_Install
@ Enable caches / DTCM / select low exception vectors @ Enable caches / TCMs / select high exception vectors
ldr r1, =(CR_ALT_VECTORS | CR_V4TLD) ldr r2, =(CR_MPU | CR_CACHES | CR_ITCM | CR_DTCM | CR_ALT_VECTORS)
ldr r2, =(CR_MPU | CR_CACHES | CR_DTCM)
mrc p15, 0, r0, c1, c0, 0 mrc p15, 0, r0, c1, c0, 0
bic r0, r1 bic r0, r1
orr r0, r2 orr r0, r2
@ -162,7 +159,7 @@ _start:
__mpu_regions: __mpu_regions:
.word 0xFFFF001F @ FFFF0000 64k | bootrom (unprotected / protected) .word 0xFFFF001F @ FFFF0000 64k | bootrom (unprotected / protected)
.word 0x3000801B @ 30008000 16k | dtcm .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 0x08000029 @ 08000000 2M | arm9 mem (O3DS / N3DS)
.word 0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB) .word 0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB)
.word 0x20000037 @ 20000000 256M | fcram (O3DS / N3DS) .word 0x20000037 @ 20000000 256M | fcram (O3DS / N3DS)

View File

@ -15,23 +15,45 @@
#include <arm.h> #include <arm.h>
#define PC_DUMPRAD (0x30) #define PC_DUMPRAD (0x40)
#define SP_DUMPLEN (0x60) #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) \ #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; \ char *c = b; \
while(s<e) { \ while(s<e) { \
b+=sprintf(b, "%08lX: ",s); \ b+=sprintf(b, "%08lX: ",s); \
type *dl = (type*)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, "%0" #size "lX ", (u32)dl[i]); \
} \ } \
b+=sprintf(b, "\n"); \ b+=sprintf(b, "\n"); \
s+=16; \ s+=16; \
} \ } \
return (int)(b-c); \ return (unsigned)(b-c); \
} }
XRQ_DUMPDATAFUNC(u8, 2) XRQ_DUMPDATAFUNC(u8, 2)
XRQ_DUMPDATAFUNC(u16, 4) XRQ_DUMPDATAFUNC(u16, 4)
@ -46,7 +68,7 @@ const char *XRQ_Name[] = {
void XRQ_DumpRegisters(u32 xrq, u32 *regs) 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; char dumpstr[2048], *wstr = dumpstr;
DsTime dstime; DsTime dstime;
@ -75,24 +97,25 @@ void XRQ_DumpRegisters(u32 xrq, u32 *regs)
ClearScreen(MAIN_SCREEN, COLOR_STD_BG); ClearScreen(MAIN_SCREEN, COLOR_STD_BG);
DrawStringF(MAIN_SCREEN, draw_x, draw_y, COLOR_STD_FONT, COLOR_STD_BG, dumpstr); DrawStringF(MAIN_SCREEN, draw_x, draw_y, COLOR_STD_FONT, COLOR_STD_BG, dumpstr);
/* Dump STACK */ /* Dump STACK */
sp = regs[13] & ~0xF; sp = regs[13] & ~0xF;
st = __STACK_TOP; if (sp_dumpable(sp, &sp_lower, &sp_upper)) {
wstr += sprintf(wstr, "Stack dump:\n"); wstr += sprintf(wstr, "Stack:\n");
wstr += XRQ_DumpData_u8(wstr, sp, min(sp+SP_DUMPLEN, st)); wstr += XRQ_DumpData_u8(wstr, sp_lower, sp_upper);
wstr += sprintf(wstr, "\n"); wstr += sprintf(wstr, "\n");
/* Dump TEXT */
pc = regs[15] & ~0xF;
wstr += sprintf(wstr, "Code dump:\n");
if (regs[16] & SR_THUMB) {
wstr += XRQ_DumpData_u16(wstr, pc-PC_DUMPRAD, pc+PC_DUMPRAD);
} else {
wstr += XRQ_DumpData_u32(wstr, pc-PC_DUMPRAD, pc+PC_DUMPRAD);
} }
/* Dump CODE */
pc = regs[15] & ~0xF;
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 */ /* Draw QR Code */
u8 qrcode[qrcodegen_BUFFER_LEN_MAX]; u8 qrcode[qrcodegen_BUFFER_LEN_MAX];

View File

@ -3,125 +3,95 @@
Read LICENSE for more details Read LICENSE for more details
*/ */
.section .text.xrqh
.arm .arm
#include <arm.h> #include <arm.h>
#include <brf.h> #include <brf.h>
#include "memmap.h" #include "memmap.h"
.macro XRQ_FATAL id=0 .macro TRAP_ENTRY xrq_id
ldr sp, =__STACK_ABT_TOP msr cpsr_f, #(\xrq_id << 29) @ preserve xrq id (idea grabbed from fb3ds)
sub sp, sp, #(18*4) @ Reserve space for registers
stmia sp, {r0-r12}
mov r11, #\id
b XRQ_MainHandler
.endm .endm
.section .vectors, "ax"
.global XRQ_Start .global XRQ_Start
XRQ_Start: XRQ_Start:
XRQ_Vectors: ldr pc, IRQ_Vector
b XRQ_Reset IRQ_Vector: .word IRQ_Handler
b XRQ_Undefined ldr pc, FIQ_Vector
b XRQ_SWI FIQ_Vector: .word FIQ_Handler
b XRQ_PAbort ldr pc, SVC_Vector
b XRQ_DAbort SVC_Vector: .word SVC_Handler
b . @ Reserved exception vector ldr pc, UND_Vector
subs pc, lr, #4 @ IRQs are unhandled UND_Vector: .word UND_Handler
b . @ FIQs are unused (except for debug?) 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: .section .text.xrqs
XRQ_FATAL 1 IRQ_Handler:
TRAP_ENTRY 6
b XRQ_Fatal
XRQ_SWI: FIQ_Handler:
XRQ_FATAL 2 TRAP_ENTRY 7
b XRQ_Fatal
XRQ_PAbort: SVC_Handler:
XRQ_FATAL 3 TRAP_ENTRY 2
b XRQ_Fatal
XRQ_DAbort: UND_Handler:
XRQ_FATAL 4 TRAP_ENTRY 1
b XRQ_Fatal
@ r11 = exception number PABT_Handler:
XRQ_MainHandler: TRAP_ENTRY 3
mrs r10, cpsr b XRQ_Fatal
mrs r9, spsr
mov r8, lr
@ Disable mpu / caches DABT_Handler:
ldr r4, =BRF_WB_INV_DCACHE sub lr, lr, #4 @ R14_abt = PC + 8, so it needs a small additional fixup
ldr r5, =BRF_INVALIDATE_ICACHE TRAP_ENTRY 4
ldr r6, =BRF_RESETCP15 @b XRQ_Fatal
blx r4
blx r5
blx r6
@ Retrieve banked registers XRQ_Fatal:
ands r0, r9, #(SR_PMODE_MASK & (0x0F)) sub lr, lr, #4 @ PC exception fixup
orreq r0, #(SR_SYS_MODE)
orr r0, #(0x10 | SR_NOINT)
msr cpsr_c, r0 @ Switch to previous mode ldr sp, =(__STACK_ABT_TOP - 18*4) @ Set up abort stack, 8 byte aligned
mov r0, sp stmia sp, {r0-r7} @ Preserve non-banked GPRs
mov r1, lr
msr cpsr_c, r10 @ Return to abort
add r2, sp, #(13*4) mrs r1, cpsr
stmia r2, {r0, r1, r8, r9} orr r0, r1, #SR_NOINT
msr cpsr_c, r0 @ Disable interrupts
@ Give read/write access to all the memory regions lsr r0, r1, #29 @ Retrieve exception source
ldr r0, =0x33333333
mcr p15, 0, r0, c5, c0, 2 @ write data access
mcr p15, 0, r0, c5, c0, 3 @ write instruction access
@ Sets MPU regions and cache settings mrs r2, spsr
adr r0, __abt_mpu_regions str lr, [sp, #15*4]
ldmia r0, {r1-r8} str r2, [sp, #16*4] @ Preserve exception PC and CPSR
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
@ Enable mpu/caches ands r2, r2, #SR_PMODE_MASK
ldr r1, =(CR_MPU | CR_CACHES | CR_DTCM) orreq r2, r2, #SR_SYS_MODE @ Force a switch to system mode if
mrc p15, 0, r0, c1, c0, 0 @ the exception happened in user mode
orr r0, r0, r1 orr r2, r2, #(0x10 | SR_NOINT) @ With interrupts disabled
mcr p15, 0, r0, c1, c0, 0
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 r1, sp
mov r0, r11 bl XRQ_DumpRegisters @ XRQ_DumpRegisters(exception_number, saved_regs);
blx r2
msr cpsr, #(SR_SVC_MODE | SR_NOINT)
mov r0, #0 mov r0, #0
1: 1:
mcr p15, 0, r0, c7, c0, 4 mcr p15, 0, r0, c7, c0, 4
b 1b 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: