nios2: support more global pointer scenarios
We now allow use of -mgpopt=global and -mgpopt=data. The 'global' option is now the default instead of compiler-default local, expanding global pointer usage to all small data in the system. For systems where all RAM is less than 64K, the 'data' option may be appropriate. Some fixes had to be made to the system in order to get around some issues: * prep_c.c no longer uses fake linker variables to figure out the size of data or BSS, as these gave the linker fits as it tried to compute relative addresses to them. * _k_task_ptr_idle is create by sysgen and placed in a special section. Any small data in a special section needs to be declared extern with __attribute__((section)) else the compiler will assume it's in .sdata. * same situation with extern references to k_pipe_t (fixed pipe_priv test) For legacy applications being ported to Nios II which do things that freak out global pointer calculation, it can be disabled entirely. Change-Id: I5eb86ee8aefb8e2fac49c5cdd104ee19cea23f6f Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
5846bb6d65
commit
ef29812d51
8 changed files with 68 additions and 23 deletions
|
@ -77,6 +77,38 @@ config INCLUDE_RESET_VECTOR
|
||||||
nios2-download tool since it refuses to load data anywhere other than
|
nios2-download tool since it refuses to load data anywhere other than
|
||||||
RAM.
|
RAM.
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Global Pointer options"
|
||||||
|
default GP_GLOBAL
|
||||||
|
|
||||||
|
config GP_NONE
|
||||||
|
bool "No global pointer"
|
||||||
|
help
|
||||||
|
Do not use global pointer relative offsets at all
|
||||||
|
|
||||||
|
config GP_LOCAL
|
||||||
|
bool "Local data global pointer references"
|
||||||
|
help
|
||||||
|
Use global pointer relative offsets for small globals declared in the
|
||||||
|
same C file as the code that uses it.
|
||||||
|
|
||||||
|
config GP_GLOBAL
|
||||||
|
bool "Global data global pointer references"
|
||||||
|
help
|
||||||
|
Use global pointer relative offsets for small globals declared
|
||||||
|
anywhere in the executable. Note that if any small globals that are put
|
||||||
|
in alternate sections (such as _k_task_list_ptr in the microkernel)
|
||||||
|
they must be declared in headers with proper __attribute__((section)) or
|
||||||
|
the linker will error out.
|
||||||
|
|
||||||
|
config GP_ALL_DATA
|
||||||
|
bool "All data global pointer references"
|
||||||
|
help
|
||||||
|
Use GP relative access for all data in the program, not just
|
||||||
|
small data. Use this if your platform has 64K or less of RAM.
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
source "arch/nios2/soc/*/Kconfig"
|
source "arch/nios2/soc/*/Kconfig"
|
||||||
|
|
|
@ -1,5 +1,18 @@
|
||||||
-include $(srctree)/arch/$(ARCH)/soc/$(SOC_PATH)/Makefile
|
-include $(srctree)/arch/$(ARCH)/soc/$(SOC_PATH)/Makefile
|
||||||
|
|
||||||
|
ifdef CONFIG_GP_NONE
|
||||||
|
gpopt = none
|
||||||
|
else ifdef CONFIG_GP_LOCAL
|
||||||
|
gpopt = local
|
||||||
|
else ifdef CONFIG_GP_GLOBAL
|
||||||
|
gpopt = global
|
||||||
|
else ifdef CONFIG_GP_ALL_DATA
|
||||||
|
gpopt = data
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Set Global Pointer option based on Kconfig.
|
||||||
|
arch_cflags += -mgpopt=$(gpopt)
|
||||||
|
|
||||||
# Put functions and data in their own binary sections so that ld can
|
# Put functions and data in their own binary sections so that ld can
|
||||||
# garbage collect them
|
# garbage collect them
|
||||||
arch_cflags += $(call cc-option,-ffunction-sections) \
|
arch_cflags += $(call cc-option,-ffunction-sections) \
|
||||||
|
|
|
@ -145,9 +145,12 @@ SECTION_FUNC(TEXT, __start)
|
||||||
/* Align the stack pointer */
|
/* Align the stack pointer */
|
||||||
and sp, sp, r1
|
and sp, sp, r1
|
||||||
|
|
||||||
|
#if defined(CONFIG_GP_LOCAL) || defined(CONFIG_GP_GLOBAL) || \
|
||||||
|
defined(CONFIG_GP_ALL_DATA)
|
||||||
/* Initialize global pointer with the linker variable we set */
|
/* Initialize global pointer with the linker variable we set */
|
||||||
movhi gp, %hi(_gp)
|
movhi gp, %hi(_gp)
|
||||||
ori gp, gp, %lo(_gp)
|
ori gp, gp, %lo(_gp)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* TODO if shadow register sets enabled, interate through them to set
|
/* TODO if shadow register sets enabled, interate through them to set
|
||||||
* up. Need to clear r0, write gp, set the execption stack pointer
|
* up. Need to clear r0, write gp, set the execption stack pointer
|
||||||
|
|
|
@ -42,11 +42,10 @@
|
||||||
|
|
||||||
static void bssZero(void)
|
static void bssZero(void)
|
||||||
{
|
{
|
||||||
volatile uint32_t *pBSS = (uint32_t *)&__bss_start;
|
uint32_t *pos = (uint32_t *)&__bss_start;
|
||||||
unsigned int n;
|
|
||||||
|
|
||||||
for (n = 0; n < (unsigned int)&__bss_num_words; n++) {
|
for ( ; pos < (uint32_t *)&__bss_end; pos++) {
|
||||||
pBSS[n] = 0;
|
*pos = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,12 +61,13 @@ static void bssZero(void)
|
||||||
#ifdef CONFIG_XIP
|
#ifdef CONFIG_XIP
|
||||||
static void dataCopy(void)
|
static void dataCopy(void)
|
||||||
{
|
{
|
||||||
volatile uint32_t *pROM = (uint32_t *)&__data_rom_start;
|
uint32_t *pROM, *pRAM;
|
||||||
volatile uint32_t *pRAM = (uint32_t *)&__data_ram_start;
|
|
||||||
unsigned int n;
|
|
||||||
|
|
||||||
for (n = 0; n < (unsigned int)&__data_num_words; n++) {
|
pROM = (uint32_t *)&__data_rom_start;
|
||||||
pRAM[n] = pROM[n];
|
pRAM = (uint32_t *)&__data_ram_start;
|
||||||
|
|
||||||
|
for ( ; pRAM < (uint32_t *)&__data_ram_end; pROM++, pRAM++) {
|
||||||
|
*pRAM = *pROM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In most XIP scenarios we copy the exception code into RAM, so need
|
/* In most XIP scenarios we copy the exception code into RAM, so need
|
||||||
|
|
|
@ -115,6 +115,11 @@ SECTIONS
|
||||||
|
|
||||||
_image_text_end = .;
|
_image_text_end = .;
|
||||||
|
|
||||||
|
#if defined(CONFIG_GP_ALL_DATA)
|
||||||
|
_gp = ABSOLUTE(. + 0x8000);
|
||||||
|
PROVIDE(gp = _gp);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_CPLUSPLUS
|
#ifdef CONFIG_CPLUSPLUS
|
||||||
SECTION_PROLOGUE(_CTOR_SECTION_NAME, ,)
|
SECTION_PROLOGUE(_CTOR_SECTION_NAME, ,)
|
||||||
{
|
{
|
||||||
|
@ -266,8 +271,10 @@ SECTIONS
|
||||||
* beginning of .sdata so that we can use both positive and negative
|
* beginning of .sdata so that we can use both positive and negative
|
||||||
* offsets.
|
* offsets.
|
||||||
*/
|
*/
|
||||||
|
#if defined(CONFIG_GP_LOCAL) || defined(CONFIG_GP_GLOBAL)
|
||||||
_gp = ABSOLUTE(. + 0x8000);
|
_gp = ABSOLUTE(. + 0x8000);
|
||||||
PROVIDE(gp = _gp);
|
PROVIDE(gp = _gp);
|
||||||
|
#endif
|
||||||
|
|
||||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||||
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
|
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
|
||||||
|
@ -309,20 +316,8 @@ SECTIONS
|
||||||
/* Define linker symbols */
|
/* Define linker symbols */
|
||||||
_image_ram_end = .;
|
_image_ram_end = .;
|
||||||
_end = .; /* end of image */
|
_end = .; /* end of image */
|
||||||
__bss_num_words = (__bss_end - __bss_start) >> 2;
|
|
||||||
|
|
||||||
GROUP_END(RAMABLE_REGION)
|
GROUP_END(RAMABLE_REGION)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_XIP
|
|
||||||
/*
|
|
||||||
* Round up number of words for DATA section to ensure that XIP copies the
|
|
||||||
* entire data section. XIP copy is done in words only, so there may be up
|
|
||||||
* to 3 extra bytes copied in next section (BSS). At run time, the XIP copy
|
|
||||||
* is done first followed by clearing the BSS section.
|
|
||||||
*/
|
|
||||||
__data_size = (__data_ram_end - __data_ram_start);
|
|
||||||
__data_num_words = (__data_size + 3) >> 2;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
|
@ -132,10 +132,12 @@ GDATA(__data_num_words)
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
extern char __bss_start[];
|
extern char __bss_start[];
|
||||||
|
extern char __bss_end[];
|
||||||
extern int __bss_num_words[];
|
extern int __bss_num_words[];
|
||||||
#ifdef CONFIG_XIP
|
#ifdef CONFIG_XIP
|
||||||
extern char __data_rom_start[];
|
extern char __data_rom_start[];
|
||||||
extern char __data_ram_start[];
|
extern char __data_ram_start[];
|
||||||
|
extern char __data_ram_end[];
|
||||||
extern int __data_num_words[];
|
extern int __data_num_words[];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -126,7 +126,7 @@ static void _main(void)
|
||||||
|
|
||||||
typedef int32_t ktask_t; /* Must match definition in base_api.h */
|
typedef int32_t ktask_t; /* Must match definition in base_api.h */
|
||||||
|
|
||||||
extern ktask_t _k_task_ptr_idle;
|
extern ktask_t _k_task_ptr_idle _GENERIC_SECTION(_k_task_list);
|
||||||
|
|
||||||
#define MICROKERNEL_IDLE_TASK_PTR ((void *) _k_task_ptr_idle)
|
#define MICROKERNEL_IDLE_TASK_PTR ((void *) _k_task_ptr_idle)
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ extern ksem_t regSem;
|
||||||
extern ksem_t altSem;
|
extern ksem_t altSem;
|
||||||
extern ksem_t counterSem;
|
extern ksem_t counterSem;
|
||||||
|
|
||||||
extern kpipe_t pipeId;
|
extern kpipe_t pipeId _GENERIC_SECTION(_k_pipe_ptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue