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);
((void (*)(void))0xFFFF0830)(); //Clean and flush the entire DCache, then drain the write buffer
((void (*)(void))0xFFFF0AB4)(); //Flush the entire ICache
((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 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);
void flushEntireDCache(void); //actually: "clean and flush"
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 ,
@ 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
.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
flushEntireICache();
//Set ARM11 kernel entrypoint
*arm11 = (u32)firm->arm11Entry;

View File

@ -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)();
}
}

View File

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