mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-31 04:59:55 +00:00 
			
		
		
		
	Merge branch 'bugfix/tls_threadptr_calculation' into 'master'
freertos: fix TLS run-time address calculation See merge request espressif/esp-idf!13271
This commit is contained in:
		| @@ -232,7 +232,6 @@ SECTIONS | |||||||
|   ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), |   ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), | ||||||
|           "DRAM segment data does not fit.") |           "DRAM segment data does not fit.") | ||||||
|  |  | ||||||
|   /* When modifying the alignment, update tls_section_alignment in pxPortInitialiseStack */ |  | ||||||
|   .flash.appdesc : ALIGN(0x10) |   .flash.appdesc : ALIGN(0x10) | ||||||
|   { |   { | ||||||
|     _rodata_start = ABSOLUTE(.); |     _rodata_start = ABSOLUTE(.); | ||||||
| @@ -248,6 +247,8 @@ SECTIONS | |||||||
|  |  | ||||||
|   .flash.rodata : ALIGN(0x10) |   .flash.rodata : ALIGN(0x10) | ||||||
|   { |   { | ||||||
|  |     _flash_rodata_start = ABSOLUTE(.); | ||||||
|  |  | ||||||
|     mapping[flash_rodata] |     mapping[flash_rodata] | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -305,6 +306,8 @@ SECTIONS | |||||||
|     . = ALIGN(4); |     . = ALIGN(4); | ||||||
|   } >default_rodata_seg |   } >default_rodata_seg | ||||||
|  |  | ||||||
|  |   _flash_rodata_align = ALIGNOF(.flash.rodata); | ||||||
|  |  | ||||||
|   .flash.text : |   .flash.text : | ||||||
|   { |   { | ||||||
|     _stext = .; |     _stext = .; | ||||||
|   | |||||||
| @@ -262,7 +262,6 @@ SECTIONS | |||||||
|     _rodata_reserved_start = .; |     _rodata_reserved_start = .; | ||||||
|   } > default_rodata_seg |   } > default_rodata_seg | ||||||
|  |  | ||||||
|   /* When modifying the alignment, don't forget to update tls_section_alignment in pxPortInitialiseStack */ |  | ||||||
|   .flash.appdesc : ALIGN(0x10) |   .flash.appdesc : ALIGN(0x10) | ||||||
|   { |   { | ||||||
|     _rodata_start = ABSOLUTE(.); |     _rodata_start = ABSOLUTE(.); | ||||||
| @@ -278,6 +277,8 @@ SECTIONS | |||||||
|  |  | ||||||
|   .flash.rodata : ALIGN(0x10) |   .flash.rodata : ALIGN(0x10) | ||||||
|   { |   { | ||||||
|  |     _flash_rodata_start = ABSOLUTE(.); | ||||||
|  |  | ||||||
|     mapping[flash_rodata] |     mapping[flash_rodata] | ||||||
|  |  | ||||||
|     *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ |     *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ | ||||||
|   | |||||||
| @@ -251,7 +251,6 @@ SECTIONS | |||||||
|     _bss_end = ABSOLUTE(.); |     _bss_end = ABSOLUTE(.); | ||||||
|   } > dram0_0_seg |   } > dram0_0_seg | ||||||
|  |  | ||||||
|   /* When modifying the alignment, update tls_section_alignment in pxPortInitialiseStack */ |  | ||||||
|   .flash.appdesc : ALIGN(0x10) |   .flash.appdesc : ALIGN(0x10) | ||||||
|   { |   { | ||||||
|     _rodata_reserved_start = ABSOLUTE(.); |     _rodata_reserved_start = ABSOLUTE(.); | ||||||
| @@ -268,6 +267,8 @@ SECTIONS | |||||||
|  |  | ||||||
|   .flash.rodata : ALIGN(0x10) |   .flash.rodata : ALIGN(0x10) | ||||||
|   { |   { | ||||||
|  |     _flash_rodata_start = ABSOLUTE(.); | ||||||
|  |  | ||||||
|     mapping[flash_rodata] |     mapping[flash_rodata] | ||||||
|  |  | ||||||
|     *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ |     *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ | ||||||
| @@ -324,6 +325,8 @@ SECTIONS | |||||||
|     . = ALIGN(4); |     . = ALIGN(4); | ||||||
|   } >default_rodata_seg |   } >default_rodata_seg | ||||||
|  |  | ||||||
|  |   _flash_rodata_align = ALIGNOF(.flash.rodata); | ||||||
|  |  | ||||||
|   .flash.text : |   .flash.text : | ||||||
|   { |   { | ||||||
|     _stext = .; |     _stext = .; | ||||||
|   | |||||||
| @@ -293,7 +293,6 @@ SECTIONS | |||||||
|     _rodata_reserved_start = .; |     _rodata_reserved_start = .; | ||||||
|   } > default_rodata_seg |   } > default_rodata_seg | ||||||
|  |  | ||||||
|   /* When modifying the alignment, don't forget to update tls_section_alignment in pxPortInitialiseStack */ |  | ||||||
|   .flash.appdesc : ALIGN(0x10) |   .flash.appdesc : ALIGN(0x10) | ||||||
|   { |   { | ||||||
|     _rodata_start = ABSOLUTE(.); |     _rodata_start = ABSOLUTE(.); | ||||||
| @@ -309,6 +308,8 @@ SECTIONS | |||||||
|  |  | ||||||
|   .flash.rodata : ALIGN(0x10) |   .flash.rodata : ALIGN(0x10) | ||||||
|   { |   { | ||||||
|  |     _flash_rodata_start = ABSOLUTE(.); | ||||||
|  |  | ||||||
|     mapping[flash_rodata] |     mapping[flash_rodata] | ||||||
|  |  | ||||||
|     *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ |     *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ | ||||||
| @@ -362,6 +363,8 @@ SECTIONS | |||||||
|     . = ALIGN(4); |     . = ALIGN(4); | ||||||
|   } > default_rodata_seg |   } > default_rodata_seg | ||||||
|  |  | ||||||
|  |   _flash_rodata_align = ALIGNOF(.flash.rodata); | ||||||
|  |  | ||||||
|   /* Marks the end of IRAM code segment */ |   /* Marks the end of IRAM code segment */ | ||||||
|   .iram0.text_end (NOLOAD) : |   .iram0.text_end (NOLOAD) : | ||||||
|   { |   { | ||||||
|   | |||||||
| @@ -224,18 +224,58 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC | |||||||
|     extern uint32_t __global_pointer$; |     extern uint32_t __global_pointer$; | ||||||
|     uint8_t* task_thread_local_start; |     uint8_t* task_thread_local_start; | ||||||
|     uint8_t* threadptr; |     uint8_t* threadptr; | ||||||
|     extern char _thread_local_start, _thread_local_end, _rodata_start; |     extern char _thread_local_start, _thread_local_end, _flash_rodata_start; | ||||||
|  |  | ||||||
|     /* Byte pointer, so that subsequent calculations don't depend on sizeof(StackType_t). */ |     /* Byte pointer, so that subsequent calculations don't depend on sizeof(StackType_t). */ | ||||||
|     uint8_t* sp = (uint8_t*) pxTopOfStack; |     uint8_t* sp = (uint8_t*) pxTopOfStack; | ||||||
|  |  | ||||||
|     /* Set up TLS area */ |     /* Set up TLS area. | ||||||
|  |      * The following diagram illustrates the layout of link-time and run-time | ||||||
|  |      * TLS sections. | ||||||
|  |      * | ||||||
|  |      *          +-------------+ | ||||||
|  |      *          |Section:     |      Linker symbols: | ||||||
|  |      *          |.flash.rodata|      --------------- | ||||||
|  |      *       0x0+-------------+ <-- _flash_rodata_start | ||||||
|  |      *        ^ |             | | ||||||
|  |      *        | | Other data  | | ||||||
|  |      *        | |     ...     | | ||||||
|  |      *        | +-------------+ <-- _thread_local_start | ||||||
|  |      *        | |.tbss        | ^ | ||||||
|  |      *        v |             | | | ||||||
|  |      *    0xNNNN|int example; | | (thread_local_size) | ||||||
|  |      *          |.tdata       | v | ||||||
|  |      *          +-------------+ <-- _thread_local_end | ||||||
|  |      *          | Other data  | | ||||||
|  |      *          |     ...     | | ||||||
|  |      *          |             | | ||||||
|  |      *          +-------------+ | ||||||
|  |      * | ||||||
|  |      *                                Local variables of | ||||||
|  |      *                              pxPortInitialiseStack | ||||||
|  |      *                             ----------------------- | ||||||
|  |      *          +-------------+ <-- pxTopOfStack | ||||||
|  |      *          |.tdata (*)   |  ^ | ||||||
|  |      *        ^ |int example; |  |(thread_local_size | ||||||
|  |      *        | |             |  | | ||||||
|  |      *        | |.tbss (*)    |  v | ||||||
|  |      *        | +-------------+ <-- task_thread_local_start | ||||||
|  |      * 0xNNNN | |             |  ^ | ||||||
|  |      *        | |             |  | | ||||||
|  |      *        | |             |  |_thread_local_start - _rodata_start | ||||||
|  |      *        | |             |  | | ||||||
|  |      *        | |             |  v | ||||||
|  |      *        v +-------------+ <-- threadptr | ||||||
|  |      * | ||||||
|  |      *   (*) The stack grows downward! | ||||||
|  |      */ | ||||||
|  |  | ||||||
|     uint32_t thread_local_sz = (uint32_t) (&_thread_local_end - &_thread_local_start); |     uint32_t thread_local_sz = (uint32_t) (&_thread_local_end - &_thread_local_start); | ||||||
|     thread_local_sz = ALIGNUP(0x10, thread_local_sz); |     thread_local_sz = ALIGNUP(0x10, thread_local_sz); | ||||||
|     sp -= thread_local_sz; |     sp -= thread_local_sz; | ||||||
|     task_thread_local_start = sp; |     task_thread_local_start = sp; | ||||||
|     memcpy(task_thread_local_start, &_thread_local_start, thread_local_sz); |     memcpy(task_thread_local_start, &_thread_local_start, thread_local_sz); | ||||||
|     threadptr = task_thread_local_start - (&_thread_local_start - &_rodata_start); |     threadptr = task_thread_local_start - (&_thread_local_start - &_flash_rodata_start); | ||||||
|  |  | ||||||
|     /* Simulate the stack frame as it would be created by a context switch interrupt. */ |     /* Simulate the stack frame as it would be created by a context switch interrupt. */ | ||||||
|     sp -= RV_STK_FRMSZ; |     sp -= RV_STK_FRMSZ; | ||||||
|   | |||||||
| @@ -189,7 +189,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px | |||||||
| 	#endif | 	#endif | ||||||
| 	uint32_t *threadptr; | 	uint32_t *threadptr; | ||||||
| 	void *task_thread_local_start; | 	void *task_thread_local_start; | ||||||
| 	extern int _thread_local_start, _thread_local_end, _rodata_start; | 	extern int _thread_local_start, _thread_local_end, _flash_rodata_start, _flash_rodata_align; | ||||||
| 	// TODO: check that TLS area fits the stack | 	// TODO: check that TLS area fits the stack | ||||||
| 	uint32_t thread_local_sz = (uint8_t *)&_thread_local_end - (uint8_t *)&_thread_local_start; | 	uint32_t thread_local_sz = (uint8_t *)&_thread_local_end - (uint8_t *)&_thread_local_start; | ||||||
|  |  | ||||||
| @@ -248,24 +248,25 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px | |||||||
| 	frame->vpri = 0xFFFFFFFF; | 	frame->vpri = 0xFFFFFFFF; | ||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
| 	/* Init threadptr reg and TLS vars */ | 	/* Init threadptr register and set up TLS run-time area. | ||||||
|  | 	 * The diagram in port/riscv/port.c illustrates the calculations below. | ||||||
|  | 	 */ | ||||||
| 	task_thread_local_start = (void *)(((uint32_t)pxTopOfStack - XT_CP_SIZE - thread_local_sz) & ~0xf); | 	task_thread_local_start = (void *)(((uint32_t)pxTopOfStack - XT_CP_SIZE - thread_local_sz) & ~0xf); | ||||||
| 	memcpy(task_thread_local_start, &_thread_local_start, thread_local_sz); | 	memcpy(task_thread_local_start, &_thread_local_start, thread_local_sz); | ||||||
| 	threadptr = (uint32_t *)(sp + XT_STK_EXTRA); | 	threadptr = (uint32_t *)(sp + XT_STK_EXTRA); | ||||||
| 	/* Calculate THREADPTR value: | 	/* Calculate THREADPTR value. | ||||||
| 	 * The generated code will add THREADPTR value to a constant value determined at link time, | 	 * The generated code will add THREADPTR value to a constant value determined at link time, | ||||||
| 	 * to get the address of the TLS variable. | 	 * to get the address of the TLS variable. | ||||||
| 	 * The constant value is calculated by the linker as follows | 	 * The constant value is calculated by the linker as follows | ||||||
| 	 * (search for 'tpoff' in elf32-xtensa.c in BFD): | 	 * (search for 'tpoff' in elf32-xtensa.c in BFD): | ||||||
| 	 *    offset = address - tls_section_vma + align_up(TCB_SIZE, tls_section_alignment) | 	 *    offset = address - tls_section_vma + align_up(TCB_SIZE, tls_section_alignment) | ||||||
| 	 * where TCB_SIZE is hardcoded to 8. There doesn't seem to be a way to propagate | 	 * where TCB_SIZE is hardcoded to 8. | ||||||
| 	 * the section alignment value from the ld script into the code, so it is hardcoded | 	 * Note this is slightly different compared to the RISC-V port, where offset = address - tls_section_vma. | ||||||
| 	 * in both places. |  | ||||||
| 	 */ | 	 */ | ||||||
| 	const uint32_t tls_section_alignment = 0x10;  /* has to be in sync with ALIGN value of .flash.rodata section */ | 	const uint32_t tls_section_alignment = (uint32_t) &_flash_rodata_align;  /* ALIGN value of .flash.rodata section */ | ||||||
| 	const uint32_t tcb_size = 8; /* Unrelated to FreeRTOS, this is the constant from BFD */ | 	const uint32_t tcb_size = 8; /* Unrelated to FreeRTOS, this is the constant from BFD */ | ||||||
| 	const uint32_t base = (tcb_size + tls_section_alignment - 1) & (~(tls_section_alignment - 1)); | 	const uint32_t base = (tcb_size + tls_section_alignment - 1) & (~(tls_section_alignment - 1)); | ||||||
| 	*threadptr = (uint32_t)task_thread_local_start - ((uint32_t)&_thread_local_start - (uint32_t)&_rodata_start) - base; | 	*threadptr = (uint32_t)task_thread_local_start - ((uint32_t)&_thread_local_start - (uint32_t)&_flash_rodata_start) - base; | ||||||
|  |  | ||||||
| 	#if XCHAL_CP_NUM > 0 | 	#if XCHAL_CP_NUM > 0 | ||||||
| 	/* Init the coprocessor save area (see xtensa_context.h) */ | 	/* Init the coprocessor save area (see xtensa_context.h) */ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Angus Gratton
					Angus Gratton