Views: 6,846,614 Homepage | Main | Rules/FAQ | Memberlist | Active users | Last posts | Calendar | Stats | Online users | Search 04-18-24 08:38 AM
Guest:

0 users reading the DSi RAM size shitshow | 1 bot

Main - Development - the DSi RAM size shitshow Hide post layouts | New reply


Arisotura
Posted on 09-03-21 05:11 PM Link | #4397
basically: melonDS doesn't currently emulate the DSi RAM size setting. the use is restricting the RAM to 4MB when running DS games.

thing is: in melonDS, the ARM9 changes the RAM size while the ARM7 is still busy clearing RAM, causing the ARM9 code to be erased -- you guess how this goes.

I replicated the code doing all that, and played around with it. observations:

* when changed, the new RAM size reflects instantly on the ARM7 side.

* seems to be some weird timing issue -- on hardware, the ARM7 actually has the time to do all its RAM clearing work and wait for VCount to be 0 before the RAM size will be changed. but, that's the thing -- the ARM7 has a bunch of memory regions to clear/relocate, mostly in main RAM. in comparison, the ARM9 has nothing to do beyond clearing its DTCM, which should be quick. I don't see how the ARM9 can take so long (or the ARM7 be so quick).

____________________
Kuribo64

Generic aka RSDuck
Posted on 09-03-21 05:30 PM Link | #4398
Posted by Arisotura
thing is: in melonDS, the ARM9 changes the RAM size while the ARM7 is still busy clearing RAM, causing the ARM9 code to be erased -- you guess how this goes.


what about icache? Shouldn't that allow the ARM9 to continue running?

____________________
Take me to your heart / never let me go!

"clearly you need to mow more lawns and buy a better pc" - Hydr8gon

Arisotura
Posted on 09-03-21 06:39 PM Link | #4399
the caches are disabled when the code in question is running

____________________
Kuribo64

Generic aka RSDuck
Posted on 09-03-21 06:48 PM Link | #4400
Posted by Arisotura
the caches are disabled when the code in question is running

well then shouldn't the execution from uncached main ram be incredibly slow for the ARM9?

____________________
Take me to your heart / never let me go!

"clearly you need to mow more lawns and buy a better pc" - Hydr8gon

Arisotura
Posted on 09-03-21 06:49 PM Link | #4401
it would be, but the ARM9 hardly does any task besides clearing its ITCM. by comparison, the ARM7 clears a whole bunch of the main RAM, so it should take much more time to complete its task.

____________________
Kuribo64

Arisotura
Posted on 09-04-21 03:55 PM (rev. 2 of 09-05-21 11:31 AM) Link | #4410
according to my observations: the ARM9 is running abysmally slow due to concurrent mainRAM access from the ARM7 (removing the ARM7-side memory clearing makes it have timing much closer to that of melonDS).

that's super shitty.


actual data:

ARM9 takes 5230691 cycles, from the beginning of its part to the moment the RAM size register is changed.
ARM7 takes 6764360 cycles to complete its RAM relocating/clearing.

ARM9 completes the same workload in 66266 cycles if the ARM7 isn't clearing RAM.

timings are as such because EXMEMCNT is configured as to give mainRAM priority to the ARM7. giving priority to the ARM9 causes it to crash, and, if the RAM size change is removed, ARM9 takes 47825 cycles and ARM7 takes a whopping 37908444 cycles.

____________________
Kuribo64

Mighy Max
Posted on 09-21-21 03:18 PM Link | #4499
This seems really like a bug in the boot code.

The following is my try of reversing that part I did a while ago.
Between IPC Sync Value 5 and 0 is the part that gives you the problem. There is no sync/barrier between the mem access and the SCFG write. The memory regions used are passed from the actual app/stage2 while the boot relict code seems to be SDK code, as it is also present in (some?) other apps.

Imho there are two options here: have the timings correct, or patch the loader.
Both have some serious issues: the timings will vary often until melonDS is mature. It will repeat to break within the development process. Patching the laoder does not reflect the actual console and its code, so the console and melon would move a step apart and detecting the boot relict code is tricky, as it might be used in multiple apps and might appear in different versions.

oid bootClearMemory(uint32_t *target, uint32_t length) ;
void bootClearMemoryListEntries(uint32_t *memoryList) ;
void bootSimpleCopy(uint32_t *source, uint32_t *target, uint32_t count) ;
void bootReverseCopy(uint32_t *source, uint32_t *target, uint32_t count) ;

typedef void (*ARM9BOOTFUNC)(void) ;

void bootBootRelictCode(SBOOTCONFIG *cfg, uint32_t *memoryList, uint32_t memoryListLength, uint32_t stackPtr)
{
bootReverseCopy((uint32_t *)cfg, (uint32_t *)(stackPtr - 0x110), 0xe0) ;
SBOOTCONFIG *cfgCopy = (SBOOTCONFIG *)(stackPtr - 0x110) ;
/* sync with arm7 */
WaitForIPCSyncValue(4) ;
SetIPCSyncValue(4) ;
/* copy list of memory to be cleared to the new stack */
bootReverseCopy(memoryList, (uint32_t *)(stackPtr + 0x110), memoryListLength) ;
bootClearMemoryListEntries(memoryList) ;
/* wait for arm7 to complete memory clear up */
WaitForIPCSyncValue(5) ;
/* Set up new WRAM Settings */
if (cfgCopy->wramFlag != 0)
{
bootSimpleCopy(cfgCopy->wramSettings, (uint32_t *)0x04004040, sizeof(cfgCopy->wramSettings)) ;
*(volatile uint8_t *)0x4000247 = *(uint8_t *)(cfgCopy->wramCnt >> 24) & 3 ;
}
/* tell arm7 we set up the wram */
SetIPCSyncValue(5) ;

ARM9BOOTFUNC arm9boot = *(ARM9BOOTFUNC *)(cfgCopy->entry) ;

uint32_t targetScfgExt = cfgCopy->sfcg_ext ;
bool setSCFG = !((cfgCopy->unknown_04 | cfgCopy->unknown_08) & 0x80000000) ;

// TODO (or not) the memory list are actually 4 consequtive lists terminated with 0
// the first is only used.
// the second list is used for copying data blocks from start to end
// the third list is used for copying data blocks from end to start
// and the lsit is to clear again
// Since the memory list is hardcoded in the calling method, we know that
// the last 3 lists are never used so we skip it

// clear the bootloader stack
bootClearMemory((uint32_t *)0x02fe0000, 0x3fc0) ;
// Clear the memory of that list too and the cfgCopy
bootClearMemory((uint32_t *)(stackPtr - (0x110 + memoryListLength)), 0x110 + memoryListLength) ;

if (setSCFG)
{
*(volatile uint32_t *)0x04004008 = targetScfgExt ;
}

/* sync with arm7 */
WaitForIPCSyncValue(0) ;
SetIPCSyncValue(0) ;

/* start new code or die! */
if (arm9boot != 0)
arm9boot() ;
while (true)
;
}

void bootSimpleCopy(uint32_t *source, uint32_t *target, uint32_t count)
{
uint32_t *end = target + count / 4;
while (target < end)
{
*(target++) = *(source++) ;
}
}

void bootReverseCopy(uint32_t *source, uint32_t *target, uint32_t count)
{
uint32_t *curTarget = target + count / 4 ;
uint32_t *curSource = source + count / 4;
while (target < curTarget)
{
*(--curTarget) = *(--curSource) ;
}
}

void bootClearMemory(uint32_t *target, uint32_t length)
{
while (length >= 4)
{
*(target++) = 0 ;
length -= 4 ;
}
}

void bootClearMemoryListEntries(uint32_t *memoryList)
{
while (true)
{
if (!*memoryList)
break;
bootClearMemory((uint32_t *)(memoryList[0]), memoryList[1]) ;
memoryList += 2 ;
}
}

Below is the code for the arm7 at the same time between ipc 5 and 0 (out of ghidra):
037b84b8 05 00 a0 e3 mov r0,#0x5
037b84bc 54 00 00 eb bl SetIPCSyncValue_1 undefined SetIPCSyncValue_1()
037b84c0 58 00 00 eb bl WaitForIPCSyncValue_1 undefined WaitForIPCSyncValue_1()
037b84c4 00 00 58 e3 cmp r8,#0x0
037b84c8 40 00 8b 12 addne r0,r11,#0x40
037b84cc 54 10 87 12 addne r1,r7,#0x54
037b84d0 10 20 a0 13 movne r2,#0x10
037b84d4 1d 00 00 1b blne bootSimpleCopy undefined bootSimpleCopy()
037b84d8 40 0f 9b e8 ldmia r11,{r6 r8 r9 r10 r11}
037b84dc 0a a0 89 e1 orr r10,r9,r10
LAB_037b84e0 XREF[1]: 037b84ec(j)
037b84e0 45 00 00 eb bl bootGetMemoryListEntry undefined bootGetMemoryListEntry()
037b84e4 01 00 00 0a beq LAB_037b84f0
037b84e8 18 00 00 eb bl bootSimpleCopy undefined bootSimpleCopy()
037b84ec fb ff ff ea b LAB_037b84e0
LAB_037b84f0 XREF[2]: 037b84e4(j), 037b84fc(j)
037b84f0 41 00 00 eb bl bootGetMemoryListEntry undefined bootGetMemoryListEntry()
037b84f4 01 00 00 0a beq LAB_037b8500
037b84f8 1a 00 00 eb bl bootReverseCopy undefined bootReverseCopy()
037b84fc fb ff ff ea b LAB_037b84f0
LAB_037b8500 XREF[1]: 037b84f4(j)
037b8500 35 00 00 eb bl FUN_037b85dc undefined FUN_037b85dc()
037b8504 05 10 4d e0 sub r1,sp,r5
037b8508 05 20 a0 e1 cpy r2,r5
037b850c 1d 00 00 eb bl bootClearMemory undefined bootClearMemory()
037b8510 00 00 a0 e3 mov r0,#0x0
037b8514 3e 00 00 eb bl SetIPCSyncValue_1 undefined SetIPCSyncValue_1()


Main - Development - the DSi RAM size shitshow Hide post layouts | New reply

Page rendered in 0.069 seconds. (2048KB of memory used)
MySQL - queries: 27, rows: 89/89, time: 0.030 seconds.
[powered by Acmlm] Acmlmboard 2.064 (2018-07-20)
© 2005-2008 Acmlm, Xkeeper, blackhole89 et al.