- 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
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)")

View File

@ -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

View File

@ -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)")

View File

@ -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__;
}

View File

@ -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)

View File

@ -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];

View File

@ -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: