From fd5320b86f7aec5459f08a684b95ffc2e16dc2b7 Mon Sep 17 00:00:00 2001 From: Wolfvak Date: Wed, 25 Sep 2019 19:35:01 -0300 Subject: [PATCH] - properly align ARM11 stacks and buffers - add very simple exception dumping for the ARM11 --- Makefile | 2 +- arm11/Makefile | 4 +- arm11/source/arm/exception.c | 217 ++++++++++++++++++++++++++++++++++ arm11/source/arm/vectors.s | 96 ++++++++++++--- arm11/source/boot.s | 8 +- arm11/source/hw/spi.c | 3 +- arm11/source/system/xalloc.c | 2 +- arm9/source/system/i2c.c | 4 +- arm9/source/system/spiflash.c | 22 ++-- common/arm.h | 2 +- common/common.h | 6 +- 11 files changed, 327 insertions(+), 39 deletions(-) create mode 100644 arm11/source/arm/exception.c diff --git a/Makefile b/Makefile index 99e2dee..0ff2da0 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ export INCLUDE := -I"$(shell pwd)/common" export ASFLAGS := -g -x assembler-with-cpp $(INCLUDE) export CFLAGS := -DDBUILTS="\"$(DBUILTS)\"" -DDBUILTL="\"$(DBUILTL)\"" -DVERSION="\"$(VERSION)\"" -DFLAVOR="\"$(FLAVOR)\"" \ - -g -Os -Wall -Wextra -Wpedantic -Wcast-align -Wformat=2 -Wno-main \ + -g -Os -Wall -Wextra -Wcast-align -Wformat=2 -Wno-main \ -fomit-frame-pointer -ffast-math -std=gnu11 -MMD -MP \ -Wno-unused-function -Wno-format-truncation $(INCLUDE) -ffunction-sections -fdata-sections export LDFLAGS := -Tlink.ld -nostartfiles -Wl,--gc-sections,-z,max-page-size=512 diff --git a/arm11/Makefile b/arm11/Makefile index 09dde18..2f321a1 100644 --- a/arm11/Makefile +++ b/arm11/Makefile @@ -10,8 +10,8 @@ INCDIRS := source INCLUDE := $(foreach dir,$(INCDIRS),-I"$(shell pwd)/$(dir)") ASFLAGS += $(SUBARCH) $(INCLUDE) -CFLAGS += $(SUBARCH) $(INCLUDE) -LDFLAGS += $(SUBARCH) -Wl,-Map,$(TARGET).map +CFLAGS += $(SUBARCH) $(INCLUDE) -flto +LDFLAGS += $(SUBARCH) -Wl,-Map,$(TARGET).map -flto include ../Makefile.common include ../Makefile.build diff --git a/arm11/source/arm/exception.c b/arm11/source/arm/exception.c new file mode 100644 index 0000000..86df02e --- /dev/null +++ b/arm11/source/arm/exception.c @@ -0,0 +1,217 @@ +/* + * This file is part of GodMode9 + * Copyright (C) 2019 Wolfvak + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include + +static const u8 num_font[16*8]; + +#define SCREEN ((u16*)(VRAM_TOP_LA)) + +void draw_char(u16 *fb, int c, int x, int y) +{ + for (int _y = 0; _y < 8; _y++) { + for (int _x = 0; _x < 8; _x++) { + u16 *fbpos = fb + (240 - (y + _y)) + (240 * (x + _x)); + + u8 mask = (num_font[(c * 8) + _y] >> (8 - _x)) & 1; + + if (mask) + *fbpos = ~0; + else + *fbpos = 0; + } + } +} + +void draw_hex(u16 *fb, u32 num, int x, int y) +{ + x += 7*8; + for (int i = 0; i < 8; i++) { + draw_char(fb, num & 0xf, x, y); + num >>= 4; + x -= 8; + } +} + +void do_exception(u32 type, u32 *regs) +{ + for (int i = 0; i < 400*240; i++) + SCREEN[i] = 0; + + draw_hex(SCREEN, type, 8, 16); + + for (int i = 0; i < 20; i += 2) { + draw_hex(SCREEN, i, 8, 32 + (i * 4)); + draw_hex(SCREEN, regs[i], 80, 32 + (i * 4)); + + draw_hex(SCREEN, i + 1, 208, 32 + (i * 4)); + draw_hex(SCREEN, regs[i + 1], 280, 32 + (i * 4)); + } + + while(1) + ARM_WFI(); +} + +static const u8 num_font[] = { + 0b00000000, + 0b00011000, + 0b00100100, + 0b00101100, + 0b00110100, + 0b00100100, + 0b00011000, + 0b00000000, // 0 + + 0b00000000, + 0b00011000, + 0b00101000, + 0b00001000, + 0b00001000, + 0b00001000, + 0b00111100, + 0b00000000, // 1 + + 0b00000000, + 0b00011000, + 0b00100100, + 0b00000100, + 0b00001000, + 0b00010000, + 0b00111100, + 0b00000000, // 2 + + 0b00000000, + 0b00111000, + 0b00000100, + 0b00011000, + 0b00000100, + 0b00000100, + 0b00111000, + 0b00000000, // 3 + + 0b00000000, + 0b00100100, + 0b00100100, + 0b00111100, + 0b00000100, + 0b00000100, + 0b00000100, + 0b00000000, // 4 + + 0b00000000, + 0b00111100, + 0b00100000, + 0b00111000, + 0b00000100, + 0b00000100, + 0b00111000, + 0b00000000, // 5 + + 0b00000000, + 0b00011100, + 0b00100000, + 0b00111000, + 0b00100100, + 0b00100100, + 0b00011000, + 0b00000000, // 6 + + 0b00000000, + 0b00111100, + 0b00000100, + 0b00000100, + 0b00001000, + 0b00010000, + 0b00010000, + 0b00000000, // 7 + + 0b00000000, + 0b00011000, + 0b00100100, + 0b00011000, + 0b00100100, + 0b00100100, + 0b00011000, + 0b00000000, // 8 + + 0b00000000, + 0b00011000, + 0b00100100, + 0b00011100, + 0b00000100, + 0b00000100, + 0b00111000, + 0b00000000, // 9 + + 0b00000000, + 0b00011000, + 0b00100100, + 0b00111100, + 0b00100100, + 0b00100100, + 0b00100100, + 0b00000000, // A + + 0b00000000, + 0b00111000, + 0b00100100, + 0b00111000, + 0b00100100, + 0b00100100, + 0b00111000, + 0b00000000, // B + + 0b00000000, + 0b00011100, + 0b00100000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b00011100, + 0b00000000, // C + + 0b00000000, + 0b00110000, + 0b00101000, + 0b00100100, + 0b00100100, + 0b00101000, + 0b00110000, + 0b00000000, // C + + 0b00000000, + 0b00111100, + 0b00100000, + 0b00111100, + 0b00100000, + 0b00100000, + 0b00111100, + 0b00000000, // E + + 0b00000000, + 0b00111100, + 0b00100000, + 0b00111100, + 0b00100000, + 0b00100000, + 0b00100000, + 0b00000000, // F +}; diff --git a/arm11/source/arm/vectors.s b/arm11/source/arm/vectors.s index 6536ea0..3043516 100644 --- a/arm11/source/arm/vectors.s +++ b/arm11/source/arm/vectors.s @@ -16,31 +16,88 @@ * along with this program. If not, see . */ +/* + * This is almost the same as the ARM9 exception handler, + * but with a few extra register dumps (DFSR, IFSR and FAR) + */ + #include .arm .align 3 +.macro TRAP_ENTRY xrq + msr cpsr_f, #(\xrq << 29) + b XRQ_Main +.endm + .section .vector, "ax" vectors: - b XRQ_Reset @ RESET - b XRQ_Reset @ UNDEFINED - b XRQ_Reset @ SVC - b XRQ_Reset @ PREFETCH ABORT - b XRQ_Reset @ DATA ABORT - b XRQ_Reset @ RESERVED - b XRQ_IRQ @ IRQ - b XRQ_Reset @ FIQ + b XRQ_Reset + b XRQ_Undefined + b XRQ_SVC + b XRQ_PrefetchAbt + b XRQ_DataAbt + b XRQ_Reserved + b XRQ_IRQ + b XRQ_FIQ XRQ_Reset: - mov r0, #0x18000000 - add r1, r0, #(6 << 20) - mov r2, #0xFFFFFFFF - 1: - cmp r0, r1 - strne r2, [r0], #4 - moveq r0, #0x18000000 - b 1b + TRAP_ENTRY 0 + +XRQ_Undefined: + TRAP_ENTRY 1 + +XRQ_SVC: + TRAP_ENTRY 2 + +XRQ_PrefetchAbt: + TRAP_ENTRY 3 + +XRQ_DataAbt: + TRAP_ENTRY 4 + +XRQ_Reserved: + TRAP_ENTRY 5 + +XRQ_FIQ: + TRAP_ENTRY 7 + +XRQ_Main: + ldr sp, =(exception_stack_top - 32*4) + stmia sp, {r0-r7} + + cpsid aif + + mrs r1, cpsr + lsr r0, r1, #29 + + mrs r2, spsr + str lr, [sp, #15*4] + str r2, [sp, #16*4] + + ands r2, r2, #SR_PMODE_MASK + orreq r2, r2, #SR_SYS_MODE + orr r2, r2, #(0x10 | SR_NOINT) + + add r3, sp, #8*4 + msr cpsr_c, r2 + nop + nop + stmia r3!, {r8-r14} + nop + nop + msr cpsr_c, r1 + + mrc p15, 0, r4, c5, c0, 0 @ data fault status register + mrc p15, 0, r5, c5, c0, 1 @ instruction fault status register + mrc p15, 0, r6, c6, c0, 0 @ data fault address + add r3, r3, #2*4 @ skip saved PC and CPSR + stmia r3!, {r4, r5, r6} + + mov r1, sp + bl do_exception + XRQ_IRQ: sub lr, lr, #4 @ Fix return address @@ -58,3 +115,10 @@ XRQ_IRQ: pop {r0-r4, r12, lr} rfeia sp! @ Return from exception + +.section .bss.xrq_stk +.align 12 +exception_stack: @ reserve a single aligned page for the exception stack + .space 4096 +exception_stack_top: +.global exception_stack_top diff --git a/arm11/source/boot.s b/arm11/source/boot.s index 4cb35d2..9e7deef 100644 --- a/arm11/source/boot.s +++ b/arm11/source/boot.s @@ -21,7 +21,7 @@ #include -#define STACK_SZ (16384) +#define STACK_SZ (8192) .global __boot __boot: @@ -95,9 +95,11 @@ corezero_start: coresmp_start: bl SYS_CoreInit - b MainLoop + ldr lr, =MainLoop + bx lr .section .bss.stack -.align 3 +.align 12 @ make sure stack is aligned to a page boundary +.global _stack_base _stack_base: .space (MAX_CPU * STACK_SZ) diff --git a/arm11/source/hw/spi.c b/arm11/source/hw/spi.c index 358f546..32560f7 100755 --- a/arm11/source/hw/spi.c +++ b/arm11/source/hw/spi.c @@ -122,8 +122,7 @@ int SPI_DoXfer(u32 dev, const SPI_XferInfo *xfers, u32 xfer_cnt) void SPI_Init(void) { - // This cuts off access from the old SPI - // interface used during the NDS days + // This cuts off access to the old NDS SPI interface *REG_CFG_SPI_CNT = 7; } diff --git a/arm11/source/system/xalloc.c b/arm11/source/system/xalloc.c index 3850ea8..02a7921 100755 --- a/arm11/source/system/xalloc.c +++ b/arm11/source/system/xalloc.c @@ -21,7 +21,7 @@ #include "system/xalloc.h" -static char xalloc_buf[XALLOC_BUF_SIZE]; +static char ALIGN(4096) xalloc_buf[XALLOC_BUF_SIZE]; static size_t mark = 0; void *XAlloc(size_t size) diff --git a/arm9/source/system/i2c.c b/arm9/source/system/i2c.c index d9a3586..6ee1fd4 100755 --- a/arm9/source/system/i2c.c +++ b/arm9/source/system/i2c.c @@ -15,6 +15,7 @@ static bool I2C_AllocBuffer(void) return false; i2c_xfer_buf = (char*)xbuf; } + return true; } @@ -41,11 +42,12 @@ bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size) bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size) { int ret; + u32 *args; if (!I2C_AllocBuffer()) return false; - u32 args[] = {devId, regAddr, (u32)i2c_xfer_buf, size}; + args = (u32[]){devId, regAddr, (u32)i2c_xfer_buf, size}; memcpy(i2c_xfer_buf, in, size); ARM_WbDC_Range(i2c_xfer_buf, size); diff --git a/arm9/source/system/spiflash.c b/arm9/source/system/spiflash.c index 4dbb830..00bc1a8 100755 --- a/arm9/source/system/spiflash.c +++ b/arm9/source/system/spiflash.c @@ -4,7 +4,7 @@ #define SPIFLASH_CHUNK_SIZE (0x1000) -static char *spiflash_xalloc_buf = NULL; +static char *spiflash_xfer_buf = NULL; bool spiflash_get_status(void) { @@ -15,29 +15,29 @@ bool spiflash_read(u32 offset, u32 size, u8 *buf) { u32 args[3]; - if (!spiflash_xalloc_buf) { + if (!spiflash_xfer_buf) { u32 xbuf = PXI_DoCMD(PXI_XALLOC, (u32[]){SPIFLASH_CHUNK_SIZE}, 1); if (xbuf == 0 || xbuf == 0xFFFFFFFF) return false; - spiflash_xalloc_buf = (char*)xbuf; + spiflash_xfer_buf = (char*)xbuf; } - args[1] = (u32)spiflash_xalloc_buf; + args[1] = (u32)spiflash_xfer_buf; while(size > 0) { - u32 rem = min(size, SPIFLASH_CHUNK_SIZE); + u32 blksz = min(size, SPIFLASH_CHUNK_SIZE); args[0] = offset; - args[2] = rem; + args[2] = blksz; ARM_DSB(); PXI_DoCMD(PXI_NVRAM_READ, args, 3); - ARM_InvDC_Range(spiflash_xalloc_buf, rem); - memcpy(buf, spiflash_xalloc_buf, rem); + ARM_InvDC_Range(spiflash_xfer_buf, blksz); + memcpy(buf, spiflash_xfer_buf, blksz); - buf += rem; - size -= rem; - offset += rem; + buf += blksz; + size -= blksz; + offset += blksz; } return true; diff --git a/common/arm.h b/common/arm.h index 28fc084..53843ed 100644 --- a/common/arm.h +++ b/common/arm.h @@ -10,7 +10,7 @@ #define SR_ABT_MODE (0x17) #define SR_UND_MODE (0x1B) #define SR_SYS_MODE (0x1F) -#define SR_PMODE_MASK (0x1F) +#define SR_PMODE_MASK (0x0F) #define SR_THUMB BIT(5) #define SR_NOFIQ BIT(6) diff --git a/common/common.h b/common/common.h index 5e81eeb..2fadb31 100755 --- a/common/common.h +++ b/common/common.h @@ -56,7 +56,11 @@ (sizeof(x) / sizeof(*(x))) #define bkpt \ - asm volatile("bkpt\n\t") + __builtin_trap() + +#define assert(x) \ + (!!(x) ? (void)0 : __builtin_trap()) + #define STATIC_ASSERT(...) \ _Static_assert((__VA_ARGS__), #__VA_ARGS__)