From 61684ecb68adae7e6f7c02e5d9e42f85e02c34a2 Mon Sep 17 00:00:00 2001 From: TuxSH Date: Tue, 14 Jun 2016 19:50:38 +0200 Subject: [PATCH] We need to clean and flush caches before jumping to payloads, actually. --- loader/source/main.c | 3 +++ source/cache.h | 10 +++++++--- source/cache.s | 37 +++++++++++++++++++++++++++++++++---- source/firm.c | 1 + source/fs.c | 3 +++ source/screen.c | 4 ++-- 6 files changed, 49 insertions(+), 9 deletions(-) diff --git a/loader/source/main.c b/loader/source/main.c index b611bfe..633eee2 100644 --- a/loader/source/main.c +++ b/loader/source/main.c @@ -6,5 +6,8 @@ void main(void) memcpy(payloadAddress, (void*)0x24F00000, *(u32 *)0x24FFFF04); + ((void (*)(void))0xFFFF0830)(); //Clean and flush the entire DCache, then drain the write buffer + ((void (*)(void))0xFFFF0AB4)(); //Flush the entire ICache + ((void (*)())payloadAddress)(); } \ No newline at end of file diff --git a/source/cache.h b/source/cache.h index 5cd225d..0176c94 100644 --- a/source/cache.h +++ b/source/cache.h @@ -8,11 +8,15 @@ /*** The following functions flush the data cache, then waits for all memory transfers to be finished. - The data cache MUST be flushed before doing one of the following: + The data cache and/or the instruction cache MUST be flushed before doing one of the following: - rebooting - powering down - setting the ARM11 entrypoint to execute a function + - jumping to a payload ***/ -void flushEntireDCache(void); -void flushDCacheRange(void *startAddress, u32 size); \ No newline at end of file +void flushEntireDCache(void); //actually: "clean and flush" +void flushDCacheRange(void *startAddress, u32 size); + +void flushEntireICache(void); +void flushICacheRange(void *startAddress, u32 size); \ No newline at end of file diff --git a/source/cache.s b/source/cache.s index f7af2bc..d9fdad1 100644 --- a/source/cache.s +++ b/source/cache.s @@ -15,6 +15,7 @@ flushEntireDCache: @ Adpated from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html , @ and https://github.com/gemarcano/libctr9_io/blob/master/src/ctr_system_ARM.c#L39 as well @ Note: ARM's example is actually for a 8KB DCache (which is what the 3DS has) + @ Implemented in bootROM at address 0xffff0830 mov r1, #0 @ segment counter outer_loop: @@ -31,21 +32,49 @@ flushEntireDCache: cmp r1, #0 bne outer_loop - mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + mcr p15, 0, r1, c7, c10, 4 @ drain write buffer bx lr .global flushDCacheRange .type flushDCacheRange, %function flushDCacheRange: + @ Implemented in bootROM at address 0xffff08a0 + add r1, r0, r1 @ end address bic r0, #0x1f @ align source address to cache line size (32 bytes) - flush_range_loop: + flush_dcache_range_loop: mcr p15, 0, r0, c7, c14, 1 @ clean and flush the line corresponding to the address r0 is holding add r0, #0x20 cmp r0, r1 - bls flush_range_loop + blt flush_dcache_range_loop + mov r0, #0 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer bx lr - \ No newline at end of file + +.global flushEntireICache +.type flushEntireICache, %function +flushEntireICache: + @ Implemented in bootROM at address 0xffff0ab4 + + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 + bx lr + +.global flushICacheRange +.type flushICacheRange, %function +flushICacheRange: + @ Implemented in bootROM at address 0xffff0ac0 + + add r1, r0, r1 @ end address + bic r0, #0x1f @ align source address to cache line size (32 bytes) + + flush_icache_range_loop: + mcr p15, 0, r0, c7, c5, 1 @ flush the line corresponding to the address r0 is holding + add r0, #0x20 + cmp r0, r1 + blt flush_icache_range_loop + + bx lr + \ No newline at end of file diff --git a/source/firm.c b/source/firm.c index 95ad043..dba2364 100755 --- a/source/firm.c +++ b/source/firm.c @@ -380,6 +380,7 @@ static inline void launchFirm(FirmwareType firmType, u32 isFirmlaunch) } flushEntireDCache(); //Ensure that all memory transfers have completed and that the data cache has been flushed + flushEntireICache(); //Set ARM11 kernel entrypoint *arm11 = (u32)firm->arm11Entry; diff --git a/source/fs.c b/source/fs.c index 61b2c04..83a35f4 100644 --- a/source/fs.c +++ b/source/fs.c @@ -4,6 +4,7 @@ #include "fs.h" #include "memory.h" +#include "cache.h" #include "screen.h" #include "fatfs/ff.h" #include "buttons.h" @@ -85,6 +86,8 @@ void loadPayload(u32 pressed) loaderAddress[1] = fileRead((void *)0x24F00000, path); + flushDCacheRange(loaderAddress, loader_size); + flushICacheRange(loaderAddress, loader_size); ((void (*)())loaderAddress)(); } } diff --git a/source/screen.c b/source/screen.c index d0d5cc6..8c21ee2 100644 --- a/source/screen.c +++ b/source/screen.c @@ -120,7 +120,7 @@ void clearScreens(void) WAIT_FOR_ARM9(); } - flushDCacheRange(fb, sizeof(struct fb)); + flushDCacheRange((void *)fb, sizeof(struct fb)); invokeArm11Function(ARM11); } @@ -229,7 +229,7 @@ u32 initScreens(void) if(needToInit) { flushDCacheRange(&config, 4); - flushDCacheRange(fb, sizeof(struct fb)); + flushDCacheRange((void *)fb, sizeof(struct fb)); invokeArm11Function(ARM11); //Turn on backlight