Memory layout: Difference between revisions
mNo edit summary |
|||
(45 intermediate revisions by 13 users not shown) | |||
Line 1: | Line 1: | ||
=ARM11 | = Physical Memory = | ||
== ARM11 == | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
Line 31: | Line 33: | ||
| 0x17E10000 | | 0x17E10000 | ||
| 0x00001000 | | 0x00001000 | ||
| | | L2C-310 Level 2 Cache Controller (2MB) | ||
|- | |- | ||
| style="background: green" | Yes | | style="background: green" | Yes | ||
Line 69: | Line 71: | ||
|} | |} | ||
=ARM9 | ===0x17E10000=== | ||
The 32-bit register at <code>0x17E10000</code>+<code>0x100</code> only has bit 0 set when, on New 3DS, [[PTMSYSM:ConfigureNew3DSCPU]] was used with bit 1 set for the input value (the L2 cache flag). All other bits in this register are normally all-zero. Therefore, bit 0 set = new cache hardware enabled, bit 0 clear = new cache hardware disabled. This bit is how the ARM11 kernel checks whether the additional cache hardware is enabled). | |||
To enable the additional cache hardware, the following is used by the ARM11 kernel: | |||
* Sets bit 0 in 32-bit register <code>0x17E10000</code>+<code>0x100</code>. | |||
To disable the additional cache hardware, the following is used by the ARM11 kernel: | |||
* Writes value <code>0xFFFF</code> to 32-bit register <code>0x17E10000</code>+<code>0x77C</code>. | |||
* Waits for bit 0 in 32-bit register <code>0x17E10000</code>+<code>0x730</code> to become clear. | |||
* Writes value <code>0x0</code> to 32-bit register <code>0x17E10000</code>+<code>0x0</code>. | |||
* Clears bit 0 in 32-bit register <code>0x17E10000</code>+<code>0x100</code>. | |||
=== <code>0x1F000000</code> ([[New 3DS]] only) === | |||
This area is used by [[QTM Services]],starting at offset <code>0x200000</code>, size <code>0x180000</code>. This area is not accessible to the GPU on the old 3DS. The old 3DS and New 3DS GSP module has <code>vaddr->physaddr</code> conversion code for this entire region. On the New 3DS, only the first <code>0x200000</code> bytes (half of this memory) are accessible to the GPU. | |||
== ARM9 == | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
Line 135: | Line 152: | ||
| 0xFFF00000 | | 0xFFF00000 | ||
| 0x00004000 | | 0x00004000 | ||
| Data TCM (Mapped during bootrom) | | Data TCM (Mapped during bootrom). Enabled at the time Boot9 jumps to FIRM, however Kernel9+arm9loader disables it. | ||
|- | |- | ||
| style="background: green" | Yes | | style="background: green" | Yes | ||
Line 143: | Line 160: | ||
|} | |} | ||
==ARM9 MPU | ==ARM9 MPU Regions== | ||
For the below instruction permissions: RO = memory is executable, while None = not-executable. | For the below instruction permissions: RO = memory is executable, while None = not-executable. | ||
Line 349: | Line 366: | ||
| RO | | RO | ||
|} | |} | ||
===[[Bootloader|Boot9]]=== | |||
{| class="wikitable" border="1" | |||
|- | |||
! Region | |||
! Address | |||
! Size | |||
! Privileged-mode data permissions | |||
! User-mode data permissions | |||
! Privileged-mode instruction permissions | |||
! User-mode instruction permissions | |||
|- | |||
| 0 | |||
| 0x20000000 | |||
| 0x08000000 | |||
| None | |||
| None | |||
| None | |||
| None | |||
|- | |||
| 1 | |||
| 0x10000000 | |||
| 0x10000000 | |||
| RW | |||
| RW | |||
| None | |||
| None | |||
|- | |||
| 2 | |||
| 0x08000000 | |||
| 0x00100000 | |||
| RW | |||
| RW | |||
| None | |||
| None | |||
|- | |||
| 3 | |||
| 0x08000000 | |||
| 0x00000400 | |||
| RW | |||
| RW | |||
| RO | |||
| RO | |||
|- | |||
| 4 | |||
| 0xFFF00000 | |||
| 0x00004000 | |||
| RW | |||
| RW | |||
| None | |||
| None | |||
|- | |||
| 5 | |||
| 0x07FF8000 | |||
| 0x00008000 | |||
| RW | |||
| RW | |||
| RO | |||
| RO | |||
|- | |||
| 6 | |||
| 0xFFFF0000 | |||
| 0x00010000 | |||
| RO | |||
| RO | |||
| RO | |||
| RO | |||
|- | |||
| 7 | |||
| 0x1FFFE000 | |||
| 0x00000800 | |||
| RW | |||
| RW | |||
| None | |||
| None | |||
|} | |||
* Instruction cachable bits = 0x40(only enabled for region6). | |||
* Data cachable bits = 0x44(only enabled for region2 and region6). | |||
* Data bufferable bits = 0x44(only enabled for region2 and region6). | |||
These are the same for both Old3DS/New3DS. | |||
==ARM9 ITCM== | ==ARM9 ITCM== | ||
Line 374: | Line 473: | ||
| | | | ||
| 0x3800 | | 0x3800 | ||
| | | 0x100 | ||
| This is the first 0x90 bytes of [[OTP_Registers#Plaintext_OTP|plaintext OTP]] when OTP hash verification is successful. The remaining 0x70 bytes are cleared. | |||
| This is the [[ | |||
|- | |- | ||
| 0x01FFB880 | | 0x01FFB880 | ||
| | | | ||
| | | 0x3890 | ||
| | | 0x70 | ||
| This is all- | | This is all zeros; boot ROM does not reveal the console-specific keys or the OTP hash in ITCM. | ||
|- | |- | ||
| 0x01FFB900 | | 0x01FFB900 | ||
Line 447: | Line 492: | ||
| 0x3B00 | | 0x3B00 | ||
| 0x200 | | 0x200 | ||
| This is the 0x200-bytes from the plaintext | | This is the 0x200-bytes from the plaintext FIRM header for the FIRM which was loaded by [[Bootloader|Boot9]]. This is the only location Boot9 uses for storing the loaded FIRM headers internally, it's not stored anywhere else. | ||
|- | |- | ||
| 0x01FFBD00 | | 0x01FFBD00 | ||
| | | | ||
| 0x3D00 | | 0x3D00 | ||
| | | 0x100 | ||
| | | This is the RSA-2048 modulus for [[RSA_Registers|RSA]]-engine slot0 set by bootrom. | ||
|- | |||
| 0x01FFBE00 | |||
| | |||
| 0x3E00 | |||
| 0x100 | |||
| This is the RSA-2048 modulus for RSA-engine slot1 set by bootrom. | |||
|- | |- | ||
| 0x01FFBF00 | | 0x01FFBF00 | ||
Line 459: | Line 510: | ||
| 0x3F00 | | 0x3F00 | ||
| 0x100 | | 0x100 | ||
| This is the RSA-2048 | | This is the RSA-2048 modulus for RSA-engine slot2. | ||
|- | |- | ||
| 0x01FFC000 | | 0x01FFC000 | ||
Line 465: | Line 516: | ||
| 0x4000 | | 0x4000 | ||
| 0x100 | | 0x100 | ||
| This is the RSA-2048 | | This is the RSA-2048 modulus for RSA-engine slot3. | ||
|- | |- | ||
| 0x01FFC100 | | 0x01FFC100 | ||
Line 471: | Line 522: | ||
| 0x4100 | | 0x4100 | ||
| 0x800 | | 0x800 | ||
| | | These are RSA-2048 keys: 4 slots, each slot is 0x200-bytes. Slot+0 is the modulus, slot+0x100 is the private exponent. This can be confirmed by RSA-decrypting a message into a signature, then RSA-encrypting the signature back into a message, and comparing the original message with the output from the last operation. | ||
[[FIRM]] doesn't seem to ever use these. None of these are related to RSA-keyslot0 used for v6.0/v7.0 key generation. These moduli are separate from all other moduli used elsewhere. | |||
|- | |- | ||
| 0x01FFC900 | | 0x01FFC900 | ||
Line 477: | Line 530: | ||
| 0x4900 | | 0x4900 | ||
| 0x400 | | 0x400 | ||
| The unprotected ARM9-bootrom copies data to 0x07FFC900(mirror of 0x01FFC900) size 0x400. This data is copied from AXI WRAM, initialized by ARM11-bootrom(the addr used for the src is determined by [[CONFIG_Registers|REG_UNITINFO]]). These are RSA | | The unprotected ARM9-bootrom copies data to 0x07FFC900(mirror of 0x01FFC900) size 0x400. This data is copied from AXI WRAM, initialized by ARM11-bootrom(the addr used for the src is determined by [[CONFIG_Registers|REG_UNITINFO]]). These are RSA moduli: retailsrcptr = 0x1FFFD000, devsrvptr = 0x1FFFD400. | ||
* The first 0x100-bytes here is the RSA-2048 | * The first 0x100-bytes here is the RSA-2048 modulus for the CFA NCCH header, and for the gamecard NCSD header. | ||
* 0x01FFCA00 is the RSA-2048 | * 0x01FFCA00 is the RSA-2048 modulus for the CXI accessdesc signature, written to rsaengine keyslot1 by NATIVE_FIRM. | ||
* 0x01FFCB00 size 0x200 is unknown, probably RSA related, these aren't used by [[FIRM]](these are not console-unique). | * 0x01FFCB00 size 0x200 is unknown, probably RSA related, these aren't used by [[FIRM]](these are not console-unique). | ||
|- | |- | ||
Line 487: | Line 540: | ||
| 0x80 | | 0x80 | ||
| Unknown, not used by [[FIRM]]. This isn't console-unique. | | Unknown, not used by [[FIRM]]. This isn't console-unique. | ||
The first 0x10-bytes are checked by the v6.0/v7.0 NATIVE_FIRM keyinit function, when non-zero it clears this block and continues to do the key generation. Otherwise when this block was already all-zero, it immediately returns. | The first 0x10-bytes are checked by the v6.0/v7.0 NATIVE_FIRM keyinit function, when non-zero it clears this block and continues to do the key generation. Otherwise when this block was already all-zero, it immediately returns. This memclear was probably an attempt at destroying the RSA slot0 modulus, that missed (exactly 0x1000-bytes away). Even though they "failed" here, one would still need to derive the private exponent, which would require obtaining a ciphertext and plaintext. | ||
|- | |- | ||
| 0x01FFCD80 | | 0x01FFCD80 | ||
Line 513: | Line 566: | ||
* 0x01FFD220 is the keyY for fixed-keyX ES blocks | * 0x01FFD220 is the keyY for fixed-keyX ES blocks | ||
* 0x01FFD300 is the DSi common (normal)key | * 0x01FFD300 is the DSi common (normal)key | ||
* 0x01FFD380 is the first half of the retail | * 0x01FFD350 is a normalkey set on keyslot 0x02, and is likely only used during boot | ||
* 0x01FFD380 is the keyslot 0x00 keyX and the first half of the retail keyX for modcrypt crypto "Nintendo" | |||
* 0x01FFD398 is the keyX used for 'Tad' crypto, usually in keyslot 0x02 "Nintendo DS", .. | * 0x01FFD398 is the keyX used for 'Tad' crypto, usually in keyslot 0x02 "Nintendo DS", .. | ||
* 0x01FFD3C8 is the fixed keyY used for eMMC partition crypto (keyslot 0x03) | * 0x01FFD3A8 is set as the middle two words of keyslot 0x03's keyX, before being overwritten "NINTENDO" | ||
* 0x01FFD3BC is the keyY for keyslot 0x01, see below | |||
* 0x01FFD3C8 is the fixed keyY used for eMMC partition crypto on retail DSi, see below (keyslot 0x03) | |||
* 0x01FFD3E0 is the 0x1048-byte Blowfish data for DSi cart crypto | * 0x01FFD3E0 is the 0x1048-byte Blowfish data for DSi cart crypto | ||
* 0x01FFE428 is the 0x1048-byte Blowfish data for DS cart crypto | * 0x01FFE428 is the 0x1048-byte Blowfish data for DS cart crypto | ||
On the 3DS, keyslots 0x01 and 0x03 have the last word set as 0xE1A00005 instead of the next word in ITCM. This is consistent with retail DSis. | |||
|- | |- | ||
| 0x01FFF470 | | 0x01FFF470 | ||
Line 524: | Line 581: | ||
| 0xB90 | | 0xB90 | ||
| Uninitialized memory. | | Uninitialized memory. | ||
0x01FFFC00 | |- | ||
| 0x01FFFC00 | |||
| | |||
| 0x7C00 | |||
| 0x100 | |||
| Starting with [[9.5.0-22|9.5.0-X]] is the FIRM header used during FIRM-launching. | |||
|} | |} | ||
=Memory map by firmware= | =Memory map by firmware= | ||
Line 538: | Line 597: | ||
* [[Virtual address mapping FW38]] | * [[Virtual address mapping FW38]] | ||
* [[Virtual address mapping FW3F]] | * [[Virtual address mapping FW3F]] | ||
* FW49([[9.6.0-24|9.6.0-X]]) ARM11-kernel vmem mapping is identical to FW40([[9.5.0-22|9.5.0-X]]). | * FW49([[9.6.0-24|9.6.0-X]]) and [[10.0.0-27|10.0.0-X]] ARM11-kernel vmem mapping is identical to FW40([[9.5.0-22|9.5.0-X]]). | ||
Line 547: | Line 606: | ||
* [[Virtual address mapping New3DS v9.0]] | * [[Virtual address mapping New3DS v9.0]] | ||
* [[Virtual address mapping New3DS v9.2]] | * [[Virtual address mapping New3DS v9.2]] | ||
* [[Virtual address mapping New3DS v11.1]] | |||
=ARM11 Detailed physical memory map= | =ARM11 Detailed physical memory map= | ||
Line 573: | Line 633: | ||
20000000 - 28000000: Main memory | 20000000 - 28000000: Main memory | ||
The entire FCRAM is cleared during NATIVE_FIRM boot. This is | The entire FCRAM is cleared during NATIVE_FIRM boot. This is done by the ARM11 kernel in order by region as it initializes after loading [[FIRM]] launch parameters from FCRAM. | ||
== FCRAM memory-regions layout == | == FCRAM memory-regions layout == | ||
FCRAM is partitioned into three regions of memory (APPLICATION, SYSTEM, and BASE). Most applications can only allocate memory from one of these regions (which is encoded in the [[NCCH/Extended_Header#ARM11_Kernel_Flags|process kernel flags]]). There is a fixed set of possible size of each memory region, determined by the APPMEMTYPE value in [[Configuration_Memory#APPMEMTYPE|configuration memory]] (which in turn is set up according to the [[FIRM#FIRM_Launch_Parameters|firmware launch parameters]]). | |||
Support for APPMEMTYPEs 6 and 7 was implemented in [[NS]] with [[8.0.0-18]]. These configurations are only supported in the [[New_3DS]] ARM11-kernel, and are in fact the only ones supported there at all. Applications only get access to the larger memory regions when this is specified in their [[NCCH/Extended Header#New3DS System Mode|extended header]]. | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
! | ! APPMEMTYPE | ||
! | ! APPLICATION starting address (relative to FCRAM) | ||
! | ! APPLICATION region size | ||
! | ! SYSTEM starting address (relative to FCRAM) | ||
! | ! SYSTEM region size | ||
! | ! BASE starting address (relative to FCRAM) | ||
! | ! BASE region size | ||
|- | |- | ||
| 0 (default with regular 3DS kernel, used when the type is not 2-5) | | 0 (default with regular 3DS kernel, used when the type is not 2-5) | ||
Line 643: | Line 707: | ||
The SYSTEM mem-region size is calculated with: size = FCRAMTOTALSIZE - (APPLICATION_MEMREGIONSIZE + BASE_MEMREGIONSIZE). | The SYSTEM mem-region size is calculated with: size = FCRAMTOTALSIZE - (APPLICATION_MEMREGIONSIZE + BASE_MEMREGIONSIZE). | ||
All memory allocated by the kernel itself for kernel use is located under BASE. Most system-modules run under the BASE memregion too. | All memory allocated by the kernel itself for kernel use is located under BASE. Most system-modules run under the BASE memregion too. | ||
Line 746: | Line 808: | ||
==0xFF4XX000== | ==0xFF4XX000== | ||
Each [[KThread|thread]] is allocated a 0x1000-byte page in this region: the first page at 0xFF401000 is for the first created thread, 0xFF403000 for the second thread. This region is used to store the SVC-mode stack for the thread, and thread context data used for context switching. When the IRQ handler, prefetch/data abort handlers, and undefined instruction handler are entered where the SPSR-mode=user, these handlers then store LR+SPSR for the current mode on the SVC-mode stack, then these handlers switch to SVC-mode. | Each [[KThread|thread]] is allocated a 0x1000-byte page in this region for the [[KThreadContext|thread context]]: the first page at 0xFF401000 is for the first created thread, 0xFF403000 for the second thread. This region is used to store the SVC-mode stack for the thread, and thread context data used for context switching. When the IRQ handler, prefetch/data abort handlers, and undefined instruction handler are entered where the SPSR-mode=user, these handlers then store LR+SPSR for the current mode on the SVC-mode stack, then these handlers switch to SVC-mode. | ||
This page does not contain a dedicated block for storing R0-PC(etc). For user-mode, the user-mode regs are instead saved on the SVC-mode stack when IRQs such as timers for context switching are triggered. | This page does not contain a dedicated block for storing R0-PC(etc). For user-mode, the user-mode regs are instead saved on the SVC-mode stack when IRQs such as timers for context switching are triggered. | ||
For NATIVE_FIRM the memory pages for this region are located in FCRAM, however for TWL_FIRM these are located in AXI WRAM. For TWL_FIRM v6704 the first thread's page for this region is located at physical address 0x1FF93000, the next one at 0x1FF92000, etc. | For NATIVE_FIRM the memory pages for this region are located in FCRAM, however for TWL_FIRM these are located in AXI WRAM. For TWL_FIRM v6704 the first thread's page for this region is located at physical address 0x1FF93000, the next one at 0x1FF92000, etc. | ||
== IO Process virtual addressing equivalence == | |||
It seems an IO register's process virtual address can be calculated by adding 0xEB00000 to its physical address. However for kernel mappings there is no fixed address equivalence. | |||
=ARM11 User-land memory regions= | =ARM11 User-land memory regions= | ||
Line 826: | Line 872: | ||
| 0x1EC00000 | | 0x1EC00000 | ||
| 0x10100000 | | 0x10100000 | ||
| | | 0x00400000 | ||
| No | | No | ||
| [[IO]] registers, the mapped IO pages which each process can access is specified in the [[NCCH | | [[IO]] registers, the mapped IO pages which each process can access is specified in the [[NCCH/Extended_Header|exheader]]. (Applications normally don't have access to registers in this range) | ||
|- | |- | ||
| 0x1F000000 | | 0x1F000000 | ||
Line 855: | Line 901: | ||
|- | |- | ||
| 0x1FF82000 | | 0x1FF82000 | ||
| | | Dynamically taken from the BASE region of FCRAM | ||
| | | Number of threads * 0x1000 / 8 | ||
| No | | No | ||
| [[Thread Local Storage]] | | [[Thread Local Storage]] | ||
Line 953: | Line 999: | ||
| 0x27D00000 | | 0x27D00000 | ||
| | | | ||
| The data located here is copied to here by the ARM11 process. The data located here is a TWL NAND [http://dsibrew.org/wiki/Bootloader bootloader] image, using the same format+encryption/verification methods as the DSi NAND bootloader(stage2). The keyX for this bootloader keyslot is initially set to the retail DSi key-data, however when TWL_FIRM is launched this keyX key-data is replaced with a separate keyX. TWL_FIRM can use either the retail DSi bootloader RSA-1024 | | The data located here is copied to here by the ARM11 process. The data located here is a TWL NAND [http://dsibrew.org/wiki/Bootloader bootloader] image, using the same format+encryption/verification methods as the DSi NAND bootloader(stage2). The keyX for this bootloader keyslot is initially set to the retail DSi key-data, however when TWL_FIRM is launched this keyX key-data is replaced with a separate keyX. TWL_FIRM can use either the retail DSi bootloader RSA-1024 modulus, or a seperate modulus: normally only the latter is used(the former is only used when loading the image from FS instead of FCRAM). When using the image from FCRAM(default code-path), TWL_FIRM will not calculate+check the hashes for the bootloader code binaries(this is done when loading from FS however). | ||
|- | |- | ||
| 0x0FDF7000 | | 0x0FDF7000 | ||
Line 965: | Line 1,011: | ||
0xFFFF9004 Pointer to the current KProcess instance | 0xFFFF9004 Pointer to the current KProcess instance | ||
0xFFFF9008 Pointer to the current KScheduler instance | 0xFFFF9008 Pointer to the current KScheduler instance | ||
0xFFFF900C Pointer to the current KSchedulableInterruptEventLinkedList instance | |||
0xFFFF9010 Pointer to the last KThread to encounter an exception | 0xFFFF9010 Pointer to the last KThread to encounter an exception | ||
Line 970: | Line 1,017: | ||
0x8000044 Pointer to the current KProcess instance on the ARM9 | 0x8000044 Pointer to the current KProcess instance on the ARM9 | ||
0x8000048 Pointer to the current KScheduler instance on the ARM9 | 0x8000048 Pointer to the current KScheduler instance on the ARM9 | ||
= VRAM Map While Running System Applets = | = VRAM Map While Running System Applets = | ||
*0x1E6000-0x22C500 -- top screen 3D left framebuffer 0(240x400x3) (The "3D right first-framebuf" addr stored in the LCD register is set to this, when the 3D is set to "off") | *0x1E6000-0x22C500 -- top screen 3D left framebuffer 0(240x400x3) (The "3D right first-framebuf" addr stored in the LCD register is set to this, when the 3D is set to "off") | ||
*0x22C800-0x272D00 -- top screen 3D | *0x22C800-0x272D00 -- top screen 3D right framebuffer 0(240x400x3) | ||
*0x273000-0x2B9500 -- top screen 3D | *0x273000-0x2B9500 -- top screen 3D left framebuffer 1(240x400x3) | ||
*0x2B9800-0x2FFD00 -- top screen 3D right framebuffer 1(240x400x3) | *0x2B9800-0x2FFD00 -- top screen 3D right framebuffer 1(240x400x3) | ||
*0x48F000-0x4C7400 -- bottom screen framebuffer 0(240x320x3) | *0x48F000-0x4C7400 -- bottom screen framebuffer 0(240x320x3) |