linker-tool-gcc: revise for MMU support

We need to do a few things differently if we are to support
a virtual memory map, i.e. CONFIG_MMU where CONFIG_KERNEL_VM_BASE
is not the same as CONFIG_SRAM_BASE_ADDRESS.

 - All sections must be specified with a VMA and LMA, where
   VMA is the virtual address and LMA is the physical memory
   location.
 - All sections must be specified with ALIGN_WITH_INPUT to
   keep VMAs and LMAs synchronized

To do this, the existing linker macros need some adjustment:

 - GROUP_LINK_IN undefined when CONFIG_KERNEL_VM_BASE is not
   the same as CONFIG_SRAM_BASE_ADDRESS.
 - New macro GROUP_ROM_LINK_IN for text/rodata sections
 - New macro GROUP_NOLOAD_LINK_IN for bss/noinit sections
 - Implicit ALIGN_WITH_INPUT for all sections

GROUP_FOLLOWS_AT is unused anywhere in the kernel for years
now and has been removed.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
Andrew Boie 2021-03-06 17:44:44 -08:00 committed by Anas Nashif
parent a120799b85
commit acda9bf9ce
12 changed files with 151 additions and 71 deletions

View file

@ -43,7 +43,7 @@
#include <linker/linker-tool.h>
#ifdef CONFIG_XIP
#if defined(CONFIG_XIP) || defined(Z_VM_KERNEL)
#define ROMABLE_REGION ROM
#define RAMABLE_REGION RAM
#else
@ -122,7 +122,7 @@ SECTIONS
#include <linker/kobject-text.ld>
MMU_PAGE_ALIGN_PERM
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
_image_text_end = .;
_image_text_size = _image_text_end - _image_text_start;
@ -161,7 +161,7 @@ SECTIONS
#include <snippets-rodata.ld>
#include <linker/kobject-rom.ld>
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
#include <linker/cplusplus-rom.ld>
@ -234,7 +234,7 @@ SECTIONS
*/
. = ALIGN(4);
__bss_end = .;
} GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
} GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
__bss_num_words = (__bss_end - __bss_start) >> 2;

View file

@ -31,7 +31,7 @@ SECTIONS
* ... there is no 16-bit code yet, but there will be when we add SMP.
*/
.locore : ALIGN(16)
SECTION_PROLOGUE(.locore,,)
{
_locore_start = .;
*(.locore)
@ -85,8 +85,9 @@ SECTIONS
* placed above 1MB to avoid the by memory hole at 0x90000-0xFFFFF).
*/
SECTION_PROLOGUE(_TEXT_SECTION_NAME,,ALIGN(16))
SECTION_PROLOGUE(_TEXT_SECTION_NAME,,)
{
. = ALIGN(16);
_image_rom_start = .;
_image_text_start = .;
z_mapped_start = .;
@ -96,7 +97,7 @@ SECTIONS
#include <linker/kobject-text.ld>
MMU_PAGE_ALIGN_PERM
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
_image_text_end = .;
_image_text_size = _image_text_end - _image_text_start;
@ -105,8 +106,9 @@ SECTIONS
#include <linker/common-rom.ld>
#include <linker/thread-local-storage.ld>
SECTION_PROLOGUE(_RODATA_SECTION_NAME,,ALIGN(16))
SECTION_PROLOGUE(_RODATA_SECTION_NAME,,)
{
. = ALIGN(16);
*(.rodata)
*(.rodata.*)
@ -121,7 +123,7 @@ SECTIONS
#endif /* CONFIG_X86_MMU */
#include <linker/kobject-rom.ld>
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
#include <linker/cplusplus-rom.ld>
@ -148,8 +150,9 @@ SECTIONS
* be put in BSS section. That causes gcov not work properly */
#include <snippets-ram-sections.ld>
SECTION_PROLOGUE(_BSS_SECTION_NAME, (NOLOAD), ALIGN(16))
SECTION_PROLOGUE(_BSS_SECTION_NAME, (NOLOAD),)
{
. = ALIGN(16);
MMU_PAGE_ALIGN_PERM
#ifndef CONFIG_USERSPACE
_image_ram_start = .;
@ -161,7 +164,7 @@ SECTIONS
*(COMMON)
. = ALIGN(4); /* so __bss_num_dwords is exact */
__bss_end = .;
} GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
} GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
__bss_num_dwords = (__bss_end - __bss_start) >> 2;
@ -169,8 +172,9 @@ SECTIONS
#include <snippets-sections.ld>
SECTION_PROLOGUE(_DATA_SECTION_NAME,,ALIGN(16))
SECTION_PROLOGUE(_DATA_SECTION_NAME,,)
{
. = ALIGN(16);
*(.data)
*(.data.*)
#include <snippets-rwdata.ld>

View file

@ -23,4 +23,4 @@ SECTION_PROLOGUE(_NOINIT_SECTION_NAME,(NOLOAD),)
*/
#include <snippets-noinit.ld>
} GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
} GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

View file

@ -15,7 +15,7 @@
CREATE_OBJ_LEVEL(init, APPLICATION)
CREATE_OBJ_LEVEL(init, SMP)
__init_end = .;
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
#if defined(CONFIG_GEN_SW_ISR_TABLE) && !defined(CONFIG_DYNAMIC_INTERRUPTS)
SECTION_PROLOGUE(sw_isr_table,,)
@ -27,7 +27,7 @@
*/
. = ALIGN(CONFIG_ARCH_SW_ISR_TABLE_ALIGN);
*(_SW_ISR_TABLE_SECTION_SYMS)
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
#endif
/* verify we don't have rogue .init_<something> initlevel sections */
@ -62,7 +62,7 @@
LONG(0)
__CTOR_END__ = .;
#endif
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
SECTION_PROLOGUE(init_array,,)
{
@ -70,7 +70,7 @@
__init_array_start = .;
KEEP(*(SORT_BY_NAME(".init_array*")))
__init_array_end = .;
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
#endif
#ifdef CONFIG_USERSPACE
/* Build-time assignment of permissions to kernel objects to
@ -84,7 +84,7 @@
__app_shmem_regions_start = .;
KEEP(*(SORT(.app_regions.*)));
__app_shmem_regions_end = .;
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
#if defined(CONFIG_NET_SOCKETS)
Z_ITERABLE_SECTION_ROM(net_socket_register, 4)
@ -154,14 +154,14 @@
__log_const_start = .;
KEEP(*(SORT(.log_const_*)));
__log_const_end = .;
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
SECTION_DATA_PROLOGUE(log_backends_sections,,)
{
__log_backends_start = .;
KEEP(*("._log_backend.*"));
__log_backends_end = .;
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
Z_ITERABLE_SECTION_ROM(shell, 4)
@ -170,14 +170,14 @@
__shell_root_cmds_start = .;
KEEP(*(SORT(.shell_root_cmd_*)));
__shell_root_cmds_end = .;
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
SECTION_DATA_PROLOGUE(font_entry_sections,,)
{
__font_entry_start = .;
KEEP(*(SORT_BY_NAME("._cfb_font.*")))
__font_entry_end = .;
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
Z_ITERABLE_SECTION_ROM(tracing_backend, 4)
@ -190,4 +190,4 @@
KEEP(*(SORT(.__device_handles_pass1*)));
#endif /* LINKER_PASS2 */
__device_handles_end = .;
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

View file

@ -5,8 +5,8 @@
*/
#if defined (CONFIG_CPLUSPLUS)
SECTION_PROLOGUE(.gcc_except_table,,ONLY_IF_RW)
SECTION_DATA_PROLOGUE(.gcc_except_table,,ONLY_IF_RW)
{
*(.gcc_except_table .gcc_except_table.*)
} GROUP_LINK_IN(RAMABLE_REGION)
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
#endif

View file

@ -8,5 +8,5 @@
SECTION_PROLOGUE(.gcc_except_table,,ONLY_IF_RO)
{
*(.gcc_except_table .gcc_except_table.*)
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
#endif

View file

@ -34,9 +34,9 @@
#ifndef LINKER_PASS2
SECTION_PROLOGUE(.intList,,)
{
KEEP(*(.irq_info*))
KEEP(*(.intList*))
} GROUP_LINK_IN(IDT_LIST)
KEEP(*(.irq_info))
KEEP(*(.intList))
} GROUP_ROM_LINK_IN(IDT_LIST, IDT_LIST)
#else
/DISCARD/ :
{

View file

@ -61,7 +61,7 @@
SECTION_PROLOGUE(struct_type##_area,,SUBALIGN(subalign)) \
{ \
Z_LINK_ITERABLE(struct_type); \
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
/* Define an output section which will set up an iterable area
* of equally-sized data structures. For use with Z_STRUCT_SECTION_ITERABLE.

View file

@ -15,6 +15,8 @@
#ifndef ZEPHYR_INCLUDE_LINKER_LINKER_TOOL_GCC_H_
#define ZEPHYR_INCLUDE_LINKER_LINKER_TOOL_GCC_H_
#include <sys/mem_manage.h>
#if defined(CONFIG_ARM)
#if defined(CONFIG_ARM64)
#define OUTPUT_FORMAT_ "elf64-littleaarch64"
@ -63,72 +65,139 @@
#define GROUP_START(where)
#define GROUP_END(where)
/*
/**
* @def GROUP_LINK_IN
*
* Route memory to a specified memory area
*
* The GROUP_LINK_IN() macro is located at the end of the section
* description and tells the linker that this section is located in
* the memory area specified by <where> argument.
* the memory area specified by 'where' argument.
*
* This macro is intentionally undefined for CONFIG_MMU systems when
* CONFIG_KERNEL_VM_BASE is not the same as CONFIG_SRAM_BASE_ADDRESS,
* as both the LMA and VMA destinations must be known for all sections
* as this corresponds to physical vs. virtual location.
*
* @param where Destination memory area
*/
#if defined(CONFIG_ARCH_POSIX)
#define GROUP_LINK_IN(where)
#else
#elif !defined(Z_VM_KERNEL)
#define GROUP_LINK_IN(where) > where
#endif
/*
* As GROUP_LINK_IN(), but takes a second argument indicating the
* memory region (e.g. "ROM") for the load address. Used for
* initialized data sections that on XIP platforms must be copied at
/**
* @def GROUP_ROM_LINK_IN
*
* Route memory for a read-only section
*
* The GROUP_ROM_LINK_IN() macro is located at the end of the section
* description and tells the linker that this a read-only section
* that is physically placed at the 'lregion` argument.
*
* If CONFIG_XIP is active, the 'lregion' area is flash memory.
*
* If CONFIG_MMU is active, the vregion argument will be used to
* determine where this is located in the virtual memory map, otherwise
* it is ignored.
*
* @param vregion Output VMA (only used if CONFIG_MMU where LMA != VMA)
* @param lregion Output LMA
*/
#if defined(CONFIG_ARCH_POSIX)
#define GROUP_ROM_LINK_IN(vregion, lregion)
#elif defined(Z_VM_KERNEL)
#define GROUP_ROM_LINK_IN(vregion, lregion) > vregion AT > lregion
#else
#define GROUP_ROM_LINK_IN(vregion, lregion) > lregion
#endif
/**
* @def GROUP_DATA_LINK_IN
*
* Route memory for read-write sections that are loaded.
*
* Used for initialized data sections that on XIP platforms must be copied at
* startup.
*
* And, because output directives in GNU ld are "sticky", this must
* also be used on the first section *after* such an initialized data
* section, specifying the same memory region (e.g. "RAM") for both
* vregion and lregion.
* @param vregion Output VMA
* @param lregion Output LMA (only used if CONFIG_MMU if VMA != LMA,
* or CONFIG_XIP)
*/
#if defined(CONFIG_ARCH_POSIX)
#define GROUP_DATA_LINK_IN(vregion, lregion)
#else
#ifdef CONFIG_XIP
#define GROUP_DATA_LINK_IN(vregion, lregion) > vregion AT> lregion
#elif defined(CONFIG_XIP) || defined(Z_VM_KERNEL)
#define GROUP_DATA_LINK_IN(vregion, lregion) > vregion AT > lregion
#else
#define GROUP_DATA_LINK_IN(vregion, lregion) > vregion
#endif
#endif /*CONFIG_ARCH_POSIX*/
/*
* The GROUP_FOLLOWS_AT() macro is located at the end of the section
* and indicates that the section does not specify an address at which
* it is to be loaded, but that it follows a section which did specify
* such an address
/**
* @def GROUP_NOLOAD_LINK_IN
*
* Route memory for read-write sections that are NOT loaded; typically this
* is only used for 'BSS' and 'noinit'.
*
* @param vregion Output VMA
* @param lregion Output LMA (only used if CONFIG_MMU if VMA != LMA,
* corresponds to physical location)
*/
#ifdef CONFIG_ARCH_POSIX
#define GROUP_FOLLOWS_AT(where)
#if defined(CONFIG_ARCH_POSIX)
#define GROUP_NOLOAD_LINK_IN(vregion, lregion)
#elif defined(Z_VM_KERNEL)
#define GROUP_NOLOAD_LINK_IN(vregion, lregion) > vregion AT > lregion
#elif defined(CONFIG_XIP)
#define GROUP_NOLOAD_LINK_IN(vregion, lregion) > vregion AT > vregion
#else
#define GROUP_FOLLOWS_AT(where) AT > where
#define GROUP_NOLOAD_LINK_IN(vregion, lregion) > vregion
#endif
/*
/**
* @def SECTION_PROLOGUE
*
* The SECTION_PROLOGUE() macro is used to define the beginning of a section.
* The <name> parameter is the name of the section, and the <option> parameter
* is to include any special options such as (NOLOAD). Page alignment has its
* own parameter since it needs abstraction across the different toolchains.
* If not required, the <options> and <align> parameters should be left blank.
*
* On MMU systems where VMA != LMA there is an implicit ALIGN_WITH_INPUT
* specified.
*
* @param name Name of the output sectio
* @param options Section options, such as (NOLOAD), or left blank
* @param align Alignment directives, such as SUBALIGN(). ALIGN() itself is
* not allowed. May be blank.
*/
#ifdef Z_VM_KERNEL
/* If we have a virtual memory map we need ALIGN_WITH_INPUT in all sections */
#define SECTION_PROLOGUE(name, options, align) \
name options : ALIGN_WITH_INPUT align
#else
#define SECTION_PROLOGUE(name, options, align) \
name options : align
#endif
#define SECTION_PROLOGUE(name, options, align) name options : align
/*
* As for SECTION_PROLOGUE(), except that this one must (!) be used
/**
* @def SECTION_DATA_PROLOGUE
*
* Same as for SECTION_PROLOGUE(), except that this one must be used
* for data sections which on XIP platforms will have differing
* virtual and load addresses (i.e. they'll be copied into RAM at
* program startup). Such a section must (!) also use
* GROUP_LINK_IN_LMA to specify the correct output load address.
* program startup). Such a section must also use
* GROUP_DATA_LINK_IN to specify the correct output load address.
*
* This is equivalent to SECTION_PROLOGUE() on non-XIP systems.
* On XIP systems there is an implicit ALIGN_WITH_INPUT specified.
*
* @param name Name of the output sectio
* @param options Section options, or left blank
* @param align Alignment directives, such as SUBALIGN(). ALIGN() itself is
* not allowed. May be blank.
*/
#ifdef CONFIG_XIP
#if defined(CONFIG_XIP)
#define SECTION_DATA_PROLOGUE(name, options, align) \
name options : ALIGN_WITH_INPUT align
#else
#define SECTION_DATA_PROLOGUE(name, options, align) name options : align
#define SECTION_DATA_PROLOGUE(name, options, align) \
SECTION_PROLOGUE(name, options, align)
#endif
#define COMMON_SYMBOLS *(COMMON)

View file

@ -5,12 +5,12 @@
SECTION_DATA_PROLOGUE(tdata,,)
{
*(.tdata .tdata.* .gnu.linkonce.td.*);
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
SECTION_DATA_PROLOGUE(tbss,,)
{
*(.tbss .tbss.* .gnu.linkonce.tb.* .tcommon);
} GROUP_LINK_IN(ROMABLE_REGION)
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
/*
* These needs to be outside of the tdata/tbss

View file

@ -66,6 +66,13 @@
#define Z_MEM_PHYS_ADDR(virt) ((virt) - Z_MEM_VM_OFFSET)
#define Z_MEM_VIRT_ADDR(phys) ((phys) + Z_MEM_VM_OFFSET)
#if Z_MEM_VM_OFFSET != 0
#define Z_VM_KERNEL 1
#ifdef CONFIG_XIP
#error "XIP and a virtual memory kernel are not allowed"
#endif
#endif
#ifndef _ASMLANGUAGE
#include <stdint.h>
#include <stddef.h>

View file

@ -25,7 +25,7 @@ SECTION_DATA_PROLOGUE(_GCOV_BSS_SECTION_NAME,(NOLOAD),)
#endif /* CONFIG_USERSPACE */
__gcov_bss_end = .;
} GROUP_LINK_IN(RAMABLE_REGION)
} GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
__gcov_bss_num_words = ((__gcov_bss_end - __gcov_bss_start) >> 2);
__gcov_bss_size = __gcov_bss_end - __gcov_bss_start;
@ -54,7 +54,7 @@ SECTION_PROLOGUE(_GCOV_BSS_SECTION_NAME, (NOLOAD),)
. = ALIGN(4);
MMU_PAGE_ALIGN
__gcov_bss_end = .;
}GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
} GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
__gcov_bss_num_words = ((__gcov_bss_end - __gcov_bss_start) >> 2);
__gcov_bss_size = __gcov_bss_end - __gcov_bss_start;
@ -72,7 +72,7 @@ SECTION_PROLOGUE(_GCOV_BSS_SECTION_NAME, (NOLOAD),)
MPU_MIN_SIZE_ALIGN
#endif
__gcov_bss_end = .;
}GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
} GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
__gcov_bss_num_words = ((__gcov_bss_end - __gcov_bss_start) >> 2);
__gcov_bss_size = __gcov_bss_end - __gcov_bss_start;