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:
Andrew Boie 2016-06-30 16:45:08 -07:00 committed by Inaky Perez-Gonzalez
commit ef29812d51
8 changed files with 68 additions and 23 deletions

View file

@ -77,6 +77,38 @@ config INCLUDE_RESET_VECTOR
nios2-download tool since it refuses to load data anywhere other than
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
source "arch/nios2/soc/*/Kconfig"

View file

@ -1,5 +1,18 @@
-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
# garbage collect them
arch_cflags += $(call cc-option,-ffunction-sections) \

View file

@ -145,9 +145,12 @@ SECTION_FUNC(TEXT, __start)
/* Align the stack pointer */
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 */
movhi gp, %hi(_gp)
ori gp, gp, %lo(_gp)
#endif
/* TODO if shadow register sets enabled, interate through them to set
* up. Need to clear r0, write gp, set the execption stack pointer

View file

@ -42,11 +42,10 @@
static void bssZero(void)
{
volatile uint32_t *pBSS = (uint32_t *)&__bss_start;
unsigned int n;
uint32_t *pos = (uint32_t *)&__bss_start;
for (n = 0; n < (unsigned int)&__bss_num_words; n++) {
pBSS[n] = 0;
for ( ; pos < (uint32_t *)&__bss_end; pos++) {
*pos = 0;
}
}
@ -62,12 +61,13 @@ static void bssZero(void)
#ifdef CONFIG_XIP
static void dataCopy(void)
{
volatile uint32_t *pROM = (uint32_t *)&__data_rom_start;
volatile uint32_t *pRAM = (uint32_t *)&__data_ram_start;
unsigned int n;
uint32_t *pROM, *pRAM;
for (n = 0; n < (unsigned int)&__data_num_words; n++) {
pRAM[n] = pROM[n];
pROM = (uint32_t *)&__data_rom_start;
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

View file

@ -115,6 +115,11 @@ SECTIONS
_image_text_end = .;
#if defined(CONFIG_GP_ALL_DATA)
_gp = ABSOLUTE(. + 0x8000);
PROVIDE(gp = _gp);
#endif
#ifdef CONFIG_CPLUSPLUS
SECTION_PROLOGUE(_CTOR_SECTION_NAME, ,)
{
@ -266,8 +271,10 @@ SECTIONS
* beginning of .sdata so that we can use both positive and negative
* offsets.
*/
#if defined(CONFIG_GP_LOCAL) || defined(CONFIG_GP_GLOBAL)
_gp = ABSOLUTE(. + 0x8000);
PROVIDE(gp = _gp);
#endif
*(.sdata .sdata.* .gnu.linkonce.s.*)
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
@ -309,20 +316,8 @@ SECTIONS
/* Define linker symbols */
_image_ram_end = .;
_end = .; /* end of image */
__bss_num_words = (__bss_end - __bss_start) >> 2;
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

View file

@ -132,10 +132,12 @@ GDATA(__data_num_words)
#include <stdint.h>
extern char __bss_start[];
extern char __bss_end[];
extern int __bss_num_words[];
#ifdef CONFIG_XIP
extern char __data_rom_start[];
extern char __data_ram_start[];
extern char __data_ram_end[];
extern int __data_num_words[];
#endif

View file

@ -126,7 +126,7 @@ static void _main(void)
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)

View file

@ -138,7 +138,7 @@ extern ksem_t regSem;
extern ksem_t altSem;
extern ksem_t counterSem;
extern kpipe_t pipeId;
extern kpipe_t pipeId _GENERIC_SECTION(_k_pipe_ptr);
/**
*