diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2013-08-01 10:05:33 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2013-08-01 10:05:33 -0600 |
commit | 81e62ae8dc23aa3bf1590ed598b331f79794e345 (patch) | |
tree | eea0f87837089318accc334101cfb809a2f5250a | |
parent | 90a203229ff892024bf1026eb14607f0073d8234 (diff) | |
download | px4-nuttx-81e62ae8dc23aa3bf1590ed598b331f79794e345.tar.gz px4-nuttx-81e62ae8dc23aa3bf1590ed598b331f79794e345.tar.bz2 px4-nuttx-81e62ae8dc23aa3bf1590ed598b331f79794e345.zip |
ARMv7-A: Map all of .text, .bss, .data., stacks before enabling the MMU and caching. This is simpler and avoids fears I have about caching
-rw-r--r-- | nuttx/ChangeLog | 6 | ||||
-rw-r--r-- | nuttx/arch/arm/src/armv7-a/arm_head.S | 307 | ||||
-rw-r--r-- | nuttx/arch/arm/src/sama5/chip/sama5d3x_memorymap.h | 9 |
3 files changed, 145 insertions, 177 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 6ec0b1819..fad83a3ea 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -5248,4 +5248,8 @@ enabled by CONFIG_PAGING out of arm_head.S. That was just too much conditional compilation to be supportable (2013-8-1). - + * arch/arm/src/sama5/arm_head.S: Setup page table mappings for + all of .text, .bss, .data, stacks and heap before enabling + the MMU and caching. This is safer because it avoids the + caching issues (and much less redundant) (2013-8-1) + diff --git a/nuttx/arch/arm/src/armv7-a/arm_head.S b/nuttx/arch/arm/src/armv7-a/arm_head.S index ec3a33d56..88cad42f4 100644 --- a/nuttx/arch/arm/src/armv7-a/arm_head.S +++ b/nuttx/arch/arm/src/armv7-a/arm_head.S @@ -144,7 +144,6 @@ * Read/eXecute address region. This is based on NUTTX_TEXT_SIZE. */ -#define RX_NSECTIONS ((NUTTX_TEXT_SIZE+0x000fffff) >> 20) #define WR_NSECTIONS ((NUTTX_RAM_SIZE+0x000fffff) >> 20) /**************************************************************************** @@ -207,9 +206,9 @@ __start: /* Clear the 16K level 1 page table */ - ldr r4, .LCppgtable /* r4=phys. page table */ + ldr r5, .LCppgtable /* r5=phys. page table */ #ifndef CONFIG_ARCH_ROMPGTABLE - mov r0, r4 + mov r0, r5 mov r1, #0 add r2, r0, #PGTABLE_SIZE .Lpgtableclear: @@ -220,6 +219,19 @@ __start: teq r0, r2 bne .Lpgtableclear + /* Load information needed to map the .text region. After the ldmia, we + * will have: + * + * R1 = Aligned, physical address of the start of the .text region + * R2 = Aligned, virtual address of the start of the .text region + * R3 = MMU flags associated with the .txt region + * R4 = The number of 1MB sections in the mapping + * R5 = The physical address of the L1 page table (from above) + */ + + adr r0, .LCtextinfo /* Address of text info */ + ldmia r0, {r1, r2, r3, r4} /* Load the text description */ + /* Create identity mapping for first MB of the .text section to support * this startup logic executing out of the physical address space. This * identity mapping will be removed by .Lvstart (see below). Of course, @@ -228,54 +240,73 @@ __start: */ #ifndef CONFIG_IDENTITY_TEXTMAP - ldr r0, .LCptextbase /* r0=phys. base address of .text section */ - ldr r1, .LCtextflags /* R1=.text section MMU flags */ - orr r3, r1, r0 /* r3=flags + base */ - str r3, [r4, r0, lsr #18] /* identity mapping */ + orr r0, r1, r3 /* OR MMU flags into physical address */ + str r0, [r5, r1, lsr #18] /* Identity mapping */ #endif - /* Create a virtual single section mapping for the first MB of the .text - * address space. Now, we have the first 1MB mapping to both physical and - * virtual addresses. The rest of the .text mapping will be completed in - * .Lvstart once we have moved the physical mapping out of the way. + /* Map the entire .text regtion. We do this before enabling caches so + * we know that the data will be in place in the data cache. We map the + * entire text region because we don't know which parts are needed for + * start-up. * - * Here we expect to have: - * r4 = Address of the base of the L1 table + * The page table base address is in R5. Each 32-bit page table entry + * maps 1 MB of address space and is indexed by the lower 20 bits of + * the virtual address in R2 */ -#ifdef CONFIG_IDENTITY_TEXTMAP - ldr r0, .LCptextbase /* r0=phys. base address of .text section */ - ldr r1, .LCtextflags /* R1=.text section MMU flags */ - orr r3, r1, r0 /* r3=flags + base */ -#endif - - ldr r0, .LCvtextbase /* r0=virtual base address of .text section */ - str r3, [r4, r0, lsr #18] /* Save the L1 entry using vaddress as an index */ + add r2, r5, r2, lsr #18 /* R2=Offset page table address */ - /* NOTE: No .data/.bss access should be attempted. This temporary mapping - * can only be assumed to cover the initial .text region. + /* No loop until each page table entry has been written for the .text + * regtion. */ +.Lpgtextloop: + orr r0, r1, r3 /* R0: OR MMU flags into physical address */ + subs r4, r4, #1 /* R4: Decrement the section count */ + str r0, [r2], #4 /* Save page table entry, increment page table address */ + add r1, r1, #(1024*1024) /* R1: Increment the physical address */ + bne .Lpgtextloop /* Loop while R4 is non-zero */ + #ifdef CONFIG_BOOT_RUNFROMFLASH - /* If we are executing from FLASH, then we will need an additional mapping - * for the page table itself (otherwise, we will crash when we try to modify - * the page table after turning the MMU on. + /* If we are executing from FLASH, then we will need additional mappings for + * the primay RAM region that holds the .data, .bss, stack, and heap memory. * - * Here we expect to have: - * r4 = Address of the base of the L1 table + * Here we expect to have: + * r5 = Address of the base of the L1 table + * + * REVISIT: We might need this second mapping under certain conditions + * when executing from RAM too. When the RAM region is larger than 1MB + * and the page table is in the high end of RAM, then the single mapping + * above will not be sufficient. * - * REVISIT: We might need this second mapping under certain conditions - * when executing from RAM too. When the RAM region is larger than 1MB - * and the page table is in the high end of RAM, then the single mapping - * above will not be sufficient. + * REVISIT: If the page table is not located in the primary RAM regions, + * then we will also need an additional map the page table if the page + * table resides in internal SRAM. + * + * Load information needed to map the .text region. After the ldmia, we + * will have: + * + * R1 = Aligned, physical address of the start of the .text region + * R2 = Aligned, virtual address of the start of the .text region + * R3 = MMU flags associated with the .txt region + * R4 = The number of 1MB sections in the mapping + * R5 = The physical address of the L1 page table (from above) */ - ldr r0, .LCprambase /* r0=phys. base address of the primary RAM region */ - ldr r1, .LCramflags /* R1=MMU flags use with the primary RAM region */ - orr r3, r1, r0 /* r3=flags + base */ + adr r0, .LCraminfo /* Address of primary RAM info */ + ldmia r0, {r1, r2, r3, r4} /* Load the primary RAM description */ + add r2, r5, r2, lsr #18 /* R2=Offset page table addres */ - ldr r0, .LCvrambase /* r0=virtual base address of .text section */ - str r3, [r4, r0, lsr #18] /* Save the L1 entry using vaddress as an index */ + /* Loop until each page table entry has been written for the primary RAM + * region. + */ + +.Lpgramloop: + orr r0, r1, r3 /* R0: OR MMU flags into physical address */ + subs r4, r4, #1 /* R4: Decrement the section count */ + str r0, [r2], #4 /* Save page table entry, increment page table address */ + add r1, r1, #(1024*1024) /* R1: Increment the physical address */ + bne .Lpgramloop /* Loop while R4 is non-zero */ #endif /* CONFIG_BOOT_RUNFROMFLASH */ #endif /* CONFIG_ARCH_ROMPGTABLE */ @@ -283,7 +314,7 @@ __start: /* The following logic will set up the ARMv7-A for normal operation. * * Here we expect to have: - * r4 = Address of the base of the L1 table + * r5 = Address of the base of the L1 table */ /* Invalidate caches and TLBs. @@ -314,11 +345,11 @@ __start: * * Here we expect to have: * r0 = Zero - * r4 = Address of the base of the L1 table + * r5 = Address of the base of the L1 table */ - mcr CP15_TTBR0(r4) - mcr CP15_TTBR1(r4) + mcr CP15_TTBR0(r5) + mcr CP15_TTBR1(r5) /* Set the TTB control register (TTBCR) to indicate that we are using * TTBR0. r0 still holds the value of zero. @@ -457,80 +488,70 @@ __start: * PC_Relative Data ****************************************************************************/ - /* The virtual start address of the second phase boot logic */ + /* The physical base address of the page table */ - .type .LCvstart, %object -.LCvstart: - .long .Lvstart - .size .LCvstart, . -.LCvstart + .type .LCppgtable, %object +.LCppgtable: + .long PGTABLE_BASE_PADDR /* Physical start of page table */ + .size .LCppgtable, . -.LCppgtable #ifndef CONFIG_ARCH_ROMPGTABLE - /* The aligned, physical base address of the .text section */ + /* Text region description. The order of these fields must not change + * because the values are loaded using ldmia: + * + * 1) The aligned, physical base address of the .text section + * 2) The aligned, virtual base address of the .text section + * 3) The MMU flags to use with the .text space mapping + * 4) The number of 1MB sections in the .text region + * + * Values provided for NUTTX_TEXT_* must all be properly aligned to 1MB + * address boundaries + */ - .type .LCptextbase, %object + .type .LCtextinfo, %object +.LCtextinfo: .LCptextbase: - .long NUTTX_TEXT_PADDR & 0xfff00000 - .size .LCptextbase, . -.LCptextbase - - /* The aligned, virtual base address of the .text section */ - - .type .LCvtextbase, %object -.LCvtextbase: - .long NUTTX_TEXT_VADDR & 0xfff00000 - .size .LCvtextbase, . -.LCvtextbase - - /* The MMU flags used with the .text mapping */ - - .type .LCtextflags, %object + .long NUTTX_TEXT_PADDR /* Physical base address */ + .long NUTTX_TEXT_VADDR /* Virtual base address */ .LCtextflags: #ifdef CONFIG_BOOT_RUNFROMFLASH - .long MMU_ROMFLAGS /* MMU flags text section in FLASH/ROM */ + .long MMU_ROMFLAGS /* MMU flags text section in FLASH/ROM */ #else - .long MMU_MEMFLAGS /* MMU flags for text section in RAM */ + .long MMU_MEMFLAGS /* MMU flags for text section in RAM */ #endif - .size .LCtextflags, . -.LCtextflags + .long (NUTTX_TEXT_SIZE >> 20) /* Number of 1MB read-execute sections */ + .size .LCtextinfo, . -.LCtextinfo #ifdef CONFIG_BOOT_RUNFROMFLASH - /* The physical base address of the primary RAM region */ - - .type .LCprambase, %object -.LCprambase: - .long NUTTX_RAM_PADDR & 0xfff00000 - .size .LCprambase, . -.LCprambase - - /* The virtual base address of the primary RAM region */ - - .type .LCvrambase, %object -.LCvrambase: - .long NUTTX_RAM_VADDR & 0xfff00000 - .size .LCvrambase, . -.LCvrambase - - /* The MMU flags used with the primary RAM region */ + /* Primary RAM region description. The order of these fields must not change + * because the values are loaded using ldmia: + * + * 1) The aligned, physical base address of the primary RAM section + * 2) The aligned, virtual base address of the primary RAM section + * 3) The MMU flags to use with the primary RAM space mapping + * 4) The number of 1MB sections in the primary RAM region + * + * Values provided for NUTTX_RAM_* must all be properly aligned to 1MB + * address boundaries + */ - .type .LCramflags, %object -.LCramflags: - .long MMU_MEMFLAGS /* MMU flags for RAM section */ - .size .LCramflags, . -.LCramflags + .type .LCraminfo, %object +.LCraminfo: + .long NUTTX_RAM_PADDR /* Physical base address */ + .long NUTTX_RAM_VADDR /* Virtual base address */ + .long MMU_MEMFLAGS /* MMU flags for primary RAM section */ + .long (NUTTX_RAM_SIZE >> 20) /* Number of 1MB read-execute sections */ + .size .LCraminfo, . -.LCraminfo #endif /* CONFIG_BOOT_RUNFROMFLASH */ #endif /* CONFIG_ARCH_ROMPGTABLE */ - /* The physical base address of the page table */ - - .type .LCppgtable, %object -.LCppgtable: - .long PGTABLE_BASE_PADDR /* Physical start of page table */ - .size .LCppgtable, . -.LCppgtable - -#ifndef CONFIG_ARCH_ROMPGTABLE - /* The virtual base address of the page table */ - - .type .LCvpgtable, %object -.LCvpgtable: - .long PGTABLE_BASE_VADDR /* Virtual start of page table */ - .size .LCvpgtable, . -.LCvpgtable + /* The virtual start address of the second phase boot logic */ -#endif /* CONFIG_ARCH_ROMPGTABLE */ + .type .LCvstart, %object +.LCvstart: + .long .Lvstart + .size .LCvstart, . -.LCvstart .size __start, .-__start @@ -552,82 +573,12 @@ __start: * cover additional RAM sections. */ -#ifndef CONFIG_ARCH_ROMPGTABLE -#ifndef CONFIG_IDENTITY_TEXTMAP - ldr r4, .LCvpgtable /* r4=virtual page table base address */ - ldr r3, .LCvtextbase /* r0=virtual base address of .text section */ +#if !defined(CONFIG_ARCH_ROMPGTABLE) && !defined(CONFIG_IDENTITY_TEXTMAP) + ldr r5, .LCvpgtable /* r5=Virtual page table base address */ + ldr r3, .LCptextbase /* r0=Physical base address of .text section */ mov r0, #0 /* flags + base = 0 */ - str r3, [r4, r3, lsr #18] /* identity mapping */ -#endif - - /* Get the following value (if we did not already do so above): - * - * R4 = Virtual address of the page table - * R3 = Physical address of the NuttX execution space (aligned to a - * one megabyte addres boundary - */ - -#ifdef CONFIG_IDENTITY_TEXTMAP - ldr r4, .LCvpgtable /* r4=virtual page table */ -#endif - ldr r3, .LCptextbase /* r3=Aligned Nuttx start address (physical) */ - - /* Now setup the page tables for our normal mapped execution region. - * We round NUTTX_TEXT_VADDR down to the nearest megabyte boundary. - */ - - ldr r1, .LCtextflags /* R1=.text section MMU flags */ - add r3, r3, r1 /* r3=flags + base */ - - add r0, r4, #(NUTTX_TEXT_VADDR & 0xfff00000) >> 18 - str r3, [r0], #4 - - /* Now map the remaining RX_NSECTIONS-1 sections of the executable - * memory region. - */ - - .rept RX_NSECTIONS-1 - add r3, r3, #SECTION_SIZE - str r3, [r0], #4 - .endr - - /* If we are executing from RAM with a fixed page configuration, then - * we can assume that the above contiguous mapping included all of the - * .text, .data, .bss, heap, etc. But if we are executing from FLASH, - * then the RAM area is probably in a separate physical address region - * and will require a separate mapping. Or, if we are supporting on-demand - * paging of the .text region, then the RAM-based .data/.bss/heap section - * will still probably be located in a separate (virtual) address region. - * - * Here we still have R4 = The virtual address of the page table. - */ - -#ifdef CONFIG_BOOT_RUNFROMFLASH - - /* Get R3 = Value of RAM L1 page table entry */ - - ldr r3, .LCprambase /* r3=Aligned Nuttx RAM address (physical) */ - ldr r1, .LCramflags /* R1=.bss/.data section MMU flags */ - add r3, r3, r1 /* r3=flags + base */ - - /* Now setup the page tables for our normal mapped RAM region. - * We round NUTTX_RAM_VADDR down to the nearest megabyte boundary. - */ - - add r0, r4, #(NUTTX_RAM_VADDR & 0xfff00000) >> 18 - str r3, [r0], #4 - - /* Now map the remaining WR_NSECTIONS-1 sections of the RAM memory - * region. - */ - - .rept WR_NSECTIONS-1 - add r3, r3, #SECTION_SIZE - str r3, [r0], #4 - .endr - -#endif /* CONFIG_BOOT_RUNFROMFLASH */ -#endif /* CONFIG_ARCH_ROMPGTABLE */ + str r3, [r5, r3, lsr #18] /* identity mapping */ +#endif /* !CONFIG_ARCH_ROMPGTABLE && !CONFIG_IDENTITY_TEXTMAP */ /* Zero BSS and set up the stack pointer */ @@ -681,6 +632,16 @@ __start: * end of memory. See g_idle_topstack below. */ +#ifndef CONFIG_ARCH_ROMPGTABLE + /* The virtual base address of the page table */ + + .type .LCvpgtable, %object +.LCvpgtable: + .long PGTABLE_BASE_VADDR /* Virtual start of page table */ + .size .LCvpgtable, . -.LCvpgtable + +#endif /* CONFIG_ARCH_ROMPGTABLE */ + .type .Linitparms, %object .Linitparms: .long _sbss diff --git a/nuttx/arch/arm/src/sama5/chip/sama5d3x_memorymap.h b/nuttx/arch/arm/src/sama5/chip/sama5d3x_memorymap.h index baf811050..abb40b63a 100644 --- a/nuttx/arch/arm/src/sama5/chip/sama5d3x_memorymap.h +++ b/nuttx/arch/arm/src/sama5/chip/sama5d3x_memorymap.h @@ -443,7 +443,8 @@ # define NUTTX_TEXT_VADDR (CONFIG_FLASH_VSTART & 0xfff00000) # define NUTTX_TEXT_PADDR (CONFIG_FLASH_START & 0xfff00000) -# define NUTTX_TEXT_SIZE (CONFIG_FLASH_END - NUTTX_TEXT_VADDR) +# define NUTTX_TEXT_PEND ((CONFIG_FLASH_END + 0x000fffff) & 0xfff00000) +# define NUTTX_TEXT_SIZE (NUTTX_TEXT_PEND - NUTTX_TEXT_PADDR) /* In the default configuration, the primary RAM use for .bss and .data * is the internal SRAM. @@ -451,7 +452,8 @@ # define NUTTX_RAM_VADDR (CONFIG_RAM_VSTART & 0xfff00000) # define NUTTX_RAM_PADDR (CONFIG_RAM_START & 0xfff00000) -# define NUTTX_RAM_SIZE (CONFIG_RAM_END - NUTTX_RAM_PADDR) +# define NUTTX_RAM_PEND ((CONFIG_RAM_END + 0x000fffff) & 0xfff00000) +# define NUTTX_RAM_SIZE (NUTTX_RAM_PEND - NUTTX_RAM_PADDR) #else /* Otherwise we are running from some kind of RAM (ISRAM or SDRAM). @@ -460,7 +462,8 @@ # define NUTTX_TEXT_VADDR (CONFIG_RAM_VSTART & 0xfff00000) # define NUTTX_TEXT_PADDR (CONFIG_RAM_START & 0xfff00000) -# define NUTTX_TEXT_SIZE (CONFIG_RAM_END - NUTTX_TEXT_VADDR) +# define NUTTX_TEXT_PEND ((CONFIG_RAM_END + 0x000fffff) & 0xfff00000) +# define NUTTX_TEXT_SIZE (NUTTX_TEXT_PEND - NUTTX_TEXT_PADDR) #endif /* MMU Page Table Location |