We need to clean and flush caches before jumping to payloads, actually.

This commit is contained in:
TuxSH 2016-06-14 19:50:38 +02:00
parent 159c9cb475
commit 61684ecb68
6 changed files with 49 additions and 9 deletions

View File

@ -6,5 +6,8 @@ void main(void)
memcpy(payloadAddress, (void*)0x24F00000, *(u32 *)0x24FFFF04); 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)(); ((void (*)())payloadAddress)();
} }

View File

@ -8,11 +8,15 @@
/*** /***
The following functions flush the data cache, then waits for all memory transfers to be finished. 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 - rebooting
- powering down - powering down
- setting the ARM11 entrypoint to execute a function - setting the ARM11 entrypoint to execute a function
- jumping to a payload
***/ ***/
void flushEntireDCache(void); void flushEntireDCache(void); //actually: "clean and flush"
void flushDCacheRange(void *startAddress, u32 size); void flushDCacheRange(void *startAddress, u32 size);
void flushEntireICache(void);
void flushICacheRange(void *startAddress, u32 size);

View File

@ -15,6 +15,7 @@ flushEntireDCache:
@ Adpated from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html , @ 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 @ 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) @ 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 mov r1, #0 @ segment counter
outer_loop: outer_loop:
@ -31,21 +32,49 @@ flushEntireDCache:
cmp r1, #0 cmp r1, #0
bne outer_loop 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 bx lr
.global flushDCacheRange .global flushDCacheRange
.type flushDCacheRange, %function .type flushDCacheRange, %function
flushDCacheRange: flushDCacheRange:
@ Implemented in bootROM at address 0xffff08a0
add r1, r0, r1 @ end address add r1, r0, r1 @ end address
bic r0, #0x1f @ align source address to cache line size (32 bytes) 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 mcr p15, 0, r0, c7, c14, 1 @ clean and flush the line corresponding to the address r0 is holding
add r0, #0x20 add r0, #0x20
cmp r0, r1 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 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
bx lr bx lr
.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

View File

@ -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 flushEntireDCache(); //Ensure that all memory transfers have completed and that the data cache has been flushed
flushEntireICache();
//Set ARM11 kernel entrypoint //Set ARM11 kernel entrypoint
*arm11 = (u32)firm->arm11Entry; *arm11 = (u32)firm->arm11Entry;

View File

@ -4,6 +4,7 @@
#include "fs.h" #include "fs.h"
#include "memory.h" #include "memory.h"
#include "cache.h"
#include "screen.h" #include "screen.h"
#include "fatfs/ff.h" #include "fatfs/ff.h"
#include "buttons.h" #include "buttons.h"
@ -85,6 +86,8 @@ void loadPayload(u32 pressed)
loaderAddress[1] = fileRead((void *)0x24F00000, path); loaderAddress[1] = fileRead((void *)0x24F00000, path);
flushDCacheRange(loaderAddress, loader_size);
flushICacheRange(loaderAddress, loader_size);
((void (*)())loaderAddress)(); ((void (*)())loaderAddress)();
} }
} }

View File

@ -120,7 +120,7 @@ void clearScreens(void)
WAIT_FOR_ARM9(); WAIT_FOR_ARM9();
} }
flushDCacheRange(fb, sizeof(struct fb)); flushDCacheRange((void *)fb, sizeof(struct fb));
invokeArm11Function(ARM11); invokeArm11Function(ARM11);
} }
@ -229,7 +229,7 @@ u32 initScreens(void)
if(needToInit) if(needToInit)
{ {
flushDCacheRange(&config, 4); flushDCacheRange(&config, 4);
flushDCacheRange(fb, sizeof(struct fb)); flushDCacheRange((void *)fb, sizeof(struct fb));
invokeArm11Function(ARM11); invokeArm11Function(ARM11);
//Turn on backlight //Turn on backlight