zephyr/include/linker/linker-defs.h

277 lines
7.7 KiB
C
Raw Normal View History

/*
* Copyright (c) 2013-2014, Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* DESCRIPTION
* Platform independent, commonly used macros and defines related to linker
* script.
*
* This file may be included by:
* - Linker script files: for linker section declarations
* - C files: for external declaration of address or size of linker section
* - Assembly files: for external declaration of address or size of linker
* section
*/
#ifndef ZEPHYR_INCLUDE_LINKER_LINKER_DEFS_H_
#define ZEPHYR_INCLUDE_LINKER_LINKER_DEFS_H_
#include <toolchain.h>
#include <linker/sections.h>
#include <misc/util.h>
#include <offsets.h>
/* include platform dependent linker-defs */
#ifdef CONFIG_X86
/* Nothing yet to include */
#elif defined(CONFIG_ARM)
/* Nothing yet to include */
#elif defined(CONFIG_ARC)
/* Nothing yet to include */
#elif defined(CONFIG_NIOS2)
/* Nothing yet to include */
arch: added support for the riscv32 architecture RISC-V is an open-source instruction set architecture. Added support for the 32bit version of RISC-V to Zephyr. 1) exceptions/interrupts/faults are handled at the architecture level via the __irq_wrapper handler. Context saving/restoring of registers can be handled at both architecture and SOC levels. If SOC-specific registers need to be saved, SOC level needs to provide __soc_save_context and __soc_restore_context functions that shall be accounted by the architecture level, when corresponding config variable RISCV_SOC_CONTEXT_SAVE is set. 2) As RISC-V architecture does not provide a clear ISA specification about interrupt handling, each RISC-V SOC handles it in its own way. Hence, at the architecture level, the __irq_wrapper handler expects the following functions to be provided by the SOC level: __soc_is_irq: to check if the exception is the result of an interrupt or not. __soc_handle_irq: handle pending IRQ at SOC level (ex: clear pending IRQ in SOC-specific IRQ register) 3) Thread/task scheduling, as well as IRQ offloading are handled via the RISC-V system call ("ecall"), which is also handled via the __irq_wrapper handler. The _Swap asm function just calls "ecall" to generate an exception. 4) As there is no conventional way of handling CPU power save in RISC-V, the default nano_cpu_idle and nano_cpu_atomic_idle functions just unlock interrupts and return to the caller, without issuing any CPU power saving instruction. Nonetheless, to allow SOC-level to implement proper CPU power save, nano_cpu_idle and nano_cpu_atomic_idle functions are defined as __weak at the architecture level. Change-Id: I980a161d0009f3f404ad22b226a6229fbb492389 Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
2017-01-11 07:24:30 +08:00
#elif defined(CONFIG_RISCV32)
/* Nothing yet to include */
#elif defined(CONFIG_XTENSA)
/* Nothing yet to include */
#elif defined(CONFIG_ARCH_POSIX)
/* Nothing yet to include */
#else
#error Arch not supported.
#endif
#ifdef _LINKER
/*
* Space for storing per device busy bitmap. Since we do not know beforehand
* the number of devices, we go through the below mechanism to allocate the
* required space.
*/
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
kernel/arch: consolidate tTCS and TNANO definitions There was a lot of duplication between architectures for the definition of threads and the "nanokernel" guts. These have been consolidated. Now, a common file kernel/unified/include/kernel_structs.h holds the common definitions. Architectures provide two files to complement it: kernel_arch_data.h and kernel_arch_func.h. The first one contains at least the struct _thread_arch and struct _kernel_arch data structures, as well as the struct _callee_saved and struct _caller_saved register layouts. The second file contains anything that needs what is provided by the common stuff in kernel_structs.h. Those two files are only meant to be included in kernel_structs.h in very specific locations. The thread data structure has been separated into three major parts: common struct _thread_base and struct k_thread, and arch-specific struct _thread_arch. The first and third ones are included in the second. The struct s_NANO data structure has been split into two: common struct _kernel and arch-specific struct _kernel_arch. The latter is included in the former. Offsets files have also changed: nano_offsets.h has been renamed kernel_offsets.h and is still included by the arch-specific offsets.c. Also, since the thread and kernel data structures are now made of sub-structures, offsets have to be added to make up the full offset. Some of these additions have been consolidated in shorter symbols, available from kernel/unified/include/offsets_short.h, which includes an arch-specific offsets_arch_short.h. Most of the code include offsets_short.h now instead of offsets.h. Change-Id: I084645cb7e6db8db69aeaaf162963fe157045d5a Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-11-08 23:36:50 +08:00
#define DEVICE_COUNT \
((__device_init_end - __device_init_start) / _DEVICE_STRUCT_SIZEOF)
#define DEV_BUSY_SZ (((DEVICE_COUNT + 31) / 32) * 4)
#define DEVICE_BUSY_BITFIELD() \
FILL(0x00) ; \
__device_busy_start = .; \
. = . + DEV_BUSY_SZ; \
__device_busy_end = .;
#else
#define DEVICE_BUSY_BITFIELD()
#endif
/*
* generate a symbol to mark the start of the device initialization objects for
* the specified level, then link all of those objects (sorted by priority);
* ensure the objects aren't discarded if there is no direct reference to them
*/
#define DEVICE_INIT_LEVEL(level) \
__device_##level##_start = .; \
KEEP(*(SORT(.init_##level[0-9]))); \
KEEP(*(SORT(.init_##level[1-9][0-9]))); \
/*
* link in device initialization objects for all devices that are automatically
* initialized by the kernel; the objects are sorted in the order they will be
* initialized (i.e. ordered by level, sorted by priority within a level)
*/
#define DEVICE_INIT_SECTIONS() \
__device_init_start = .; \
DEVICE_INIT_LEVEL(PRE_KERNEL_1) \
DEVICE_INIT_LEVEL(PRE_KERNEL_2) \
DEVICE_INIT_LEVEL(POST_KERNEL) \
DEVICE_INIT_LEVEL(APPLICATION) \
__device_init_end = .; \
DEVICE_BUSY_BITFIELD() \
/* define a section for undefined device initialization levels */
#define DEVICE_INIT_UNDEFINED_SECTION() \
KEEP(*(SORT(.init_[_A-Z0-9]*))) \
/*
* link in shell initialization objects for all modules that use shell and
* their shell commands are automatically initialized by the kernel.
*/
#define SHELL_INIT_SECTIONS() \
__shell_module_start = .; \
KEEP(*(".shell_module_*")); \
__shell_module_end = .; \
__shell_cmd_start = .; \
KEEP(*(".shell_cmd_*")); \
__shell_cmd_end = .; \
/*
* link in shell initialization objects for all modules that use shell and
* their shell commands are automatically initialized by the kernel.
*/
#ifdef CONFIG_APPLICATION_MEMORY
/*
* KERNELSPACE_OBJECT_FILES is a space-separated list of object files
* and libraries that belong in kernelspace.
*/
#define MAYBE_EXCLUDE_SOME_FILES EXCLUDE_FILE (KERNELSPACE_OBJECT_FILES)
#else
#define MAYBE_EXCLUDE_SOME_FILES
#endif /* CONFIG_APPLICATION_MEMORY */
/*
* APP_INPUT_SECTION should be invoked on sections that should be in
* 'app' space. KERNEL_INPUT_SECTION should be invoked on sections
* that should be in 'kernel' space.
*
* NB: APP_INPUT_SECTION must be invoked before
* KERNEL_INPUT_SECTION. If it is not all sections will end up in
* kernelspace.
*/
#define APP_INPUT_SECTION(sect) *(MAYBE_EXCLUDE_SOME_FILES sect)
#define KERNEL_INPUT_SECTION(sect) *(sect)
#define APP_SMEM_SECTION() KEEP(*(SORT(data_smem_[_a-zA-Z0-9]*)))
#ifdef CONFIG_X86 /* LINKER FILES: defines used by linker script */
/* Should be moved to linker-common-defs.h */
#if defined(CONFIG_XIP)
#define ROMABLE_REGION ROM
#else
#define ROMABLE_REGION RAM
#endif
#endif
/*
* If image is loaded via kexec Linux system call, then program
* headers need to be page aligned.
* This can be done by section page aligning.
*/
#ifdef CONFIG_BOOTLOADER_KEXEC
#define KEXEC_PGALIGN_PAD(x) . = ALIGN(x);
#else
#define KEXEC_PGALIGN_PAD(x)
#endif
#elif defined(_ASMLANGUAGE)
/* Assembly FILES: declaration defined by the linker script */
GDATA(__bss_start)
GDATA(__bss_num_words)
#ifdef CONFIG_XIP
GDATA(__data_rom_start)
GDATA(__data_ram_start)
GDATA(__data_num_words)
#endif
#else /* ! _ASMLANGUAGE */
#include <zephyr/types.h>
userspace: compartmentalized app memory organization Summary: revised attempt at addressing issue 6290. The following provides an alternative to using CONFIG_APPLICATION_MEMORY by compartmentalizing data into Memory Domains. Dependent on MPU limitations, supports compartmentalized Memory Domains for 1...N logical applications. This is considered an initial attempt at designing flexible compartmentalized Memory Domains for multiple logical applications and, with the provided python script and edited CMakeLists.txt, provides support for power of 2 aligned MPU architectures. Overview: The current patch uses qualifiers to group data into subsections. The qualifier usage allows for dynamic subsection creation and affords the developer a large amount of flexibility in the grouping, naming, and size of the resulting partitions and domains that are built on these subsections. By additional macro calls, functions are created that help calculate the size, address, and permissions for the subsections and enable the developer to control application data in specified partitions and memory domains. Background: Initial attempts focused on creating a single section in the linker script that then contained internally grouped variables/data to allow MPU/MMU alignment and protection. This did not provide additional functionality beyond CONFIG_APPLICATION_MEMORY as we were unable to reliably group data or determine their grouping via exported linker symbols. Thus, the resulting decision was made to dynamically create subsections using the current qualifier method. An attempt to group the data by object file was tested, but found that this broke applications such as ztest where two object files are created: ztest and main. This also creates an issue of grouping the two object files together in the same memory domain while also allowing for compartmenting other data among threads. Because it is not possible to know a) the name of the partition and thus the symbol in the linker, b) the size of all the data in the subsection, nor c) the overall number of partitions created by the developer, it was not feasible to align the subsections at compile time without using dynamically generated linker script for MPU architectures requiring power of 2 alignment. In order to provide support for MPU architectures that require a power of 2 alignment, a python script is run at build prior to when linker_priv_stacks.cmd is generated. This script scans the built object files for all possible partitions and the names given to them. It then generates a linker file (app_smem.ld) that is included in the main linker.ld file. This app_smem.ld allows the compiler and linker to then create each subsection and align to the next power of 2. Usage: - Requires: app_memory/app_memdomain.h . - _app_dmem(id) marks a variable to be placed into a data section for memory partition id. - _app_bmem(id) marks a variable to be placed into a bss section for memory partition id. - These are seen in the linker.map as "data_smem_id" and "data_smem_idb". - To create a k_mem_partition, call the macro app_mem_partition(part0) where "part0" is the name then used to refer to that partition. This macro only creates a function and necessary data structures for the later "initialization". - To create a memory domain for the partition, the macro app_mem_domain(dom0) is called where "dom0" is the name then used for the memory domain. - To initialize the partition (effectively adding the partition to a linked list), init_part_part0() is called. This is followed by init_app_memory(), which walks all partitions in the linked list and calculates the sizes for each partition. - Once the partition is initialized, the domain can be initialized with init_domain_dom0(part0) which initializes the domain with partition part0. - After the domain has been initialized, the current thread can be added using add_thread_dom0(k_current_get()). - The code used in ztests ans kernel/init has been added under a conditional #ifdef to isolate the code from other tests. The userspace test CMakeLists.txt file has commands to insert the CONFIG_APP_SHARED_MEM definition into the required build targets. Example: /* create partition at top of file outside functions */ app_mem_partition(part0); /* create domain */ app_mem_domain(dom0); _app_dmem(dom0) int var1; _app_bmem(dom0) static volatile int var2; int main() { init_part_part0(); init_app_memory(); init_domain_dom0(part0); add_thread_dom0(k_current_get()); ... } - If multiple partitions are being created, a variadic preprocessor macro can be used as provided in app_macro_support.h: FOR_EACH(app_mem_partition, part0, part1, part2); or, for multiple domains, similarly: FOR_EACH(app_mem_domain, dom0, dom1); Similarly, the init_part_* can also be used in the macro: FOR_EACH(init_part, part0, part1, part2); Testing: - This has been successfully tested on qemu_x86 and the ARM frdm_k64f board. It compiles and builds power of 2 aligned subsections for the linker script on the 96b_carbon boards. These power of 2 alignments have been checked by hand and are viewable in the zephyr.map file that is produced during build. However, due to a shortage of available MPU regions on the 96b_carbon board, we are unable to test this. - When run on the 96b_carbon board, the test suite will enter execution, but each individaul test will fail due to an MPU FAULT. This is expected as the required number of MPU regions exceeds the number allowed due to the static allocation. As the MPU driver does not detect this issue, the fault occurs because the data being accessed has been placed outside the active MPU region. - This now compiles successfully for the ARC boards em_starterkit_em7d and em_starterkit_em7d_v22. However, as we lack ARC hardware to run this build on, we are unable to test this build. Current known issues: 1) While the script and edited CMakeLists.txt creates the ability to align to the next power of 2, this does not address the shortage of available MPU regions on certain devices (e.g. 96b_carbon). In testing the APB and PPB regions were commented out. 2) checkpatch.pl lists several issues regarding the following: a) Complex macros. The FOR_EACH macros as defined in app_macro_support.h are listed as complex macros needing parentheses. Adding parentheses breaks their functionality, and we have otherwise been unable to resolve the reported error. b) __aligned() preferred. The _app_dmem_pad() and _app_bmem_pad() macros give warnings that __aligned() is preferred. Prior iterations had this implementation, which resulted in errors due to "complex macros". c) Trailing semicolon. The macro init_part(name) has a trailing semicolon as the semicolon is needed for the inlined macro call that is generated when this macro expands. Update: updated to alternative CONFIG_APPLCATION_MEMORY. Added config option CONFIG_APP_SHARED_MEM to enable a new section app_smem to contain the shared memory component. This commit seperates the Kconfig definition from the definition used for the conditional code. The change is in response to changes in the way the build system treats definitions. The python script used to generate a linker script for app_smem was also midified to simplify the alignment directives. A default linker script app_smem.ld was added to remove the conditional includes dependency on CONFIG_APP_SHARED_MEM. By addining the default linker script the prebuild stages link properly prior to the python script running Signed-off-by: Joshua Domagalski <jedomag@tycho.nsa.gov> Signed-off-by: Shawn Mosley <smmosle@tycho.nsa.gov>
2018-04-26 22:14:02 +08:00
/*
* The following are externs symbols from the linker. This enables
* the dynamic k_mem_domain and k_mem_partition creation and alignment
* to the section produced in the linker.
*/
extern char _app_smem_start[];
extern char _app_smem_end[];
extern char _app_smem_size[];
extern char _app_smem_rom_start[];
#ifdef CONFIG_APPLICATION_MEMORY
/* Memory owned by the application. Start and end will be aligned for memory
* management/protection hardware for the target architecture.
* The policy for this memory will be to configure all of it as user thread
* accessible. It consists of all non-kernel globals.
*/
extern char __app_ram_start[];
extern char __app_ram_end[];
extern char __app_ram_size[];
#endif
/* Memory owned by the kernel. Start and end will be aligned for memory
* management/protection hardware for the target architecture..
*
* Consists of all kernel-side globals, all kernel objects, all thread stacks,
* and all currently unused RAM. If CONFIG_APPLICATION_MEMORY is not enabled,
* has all globals, not just kernel side.
*
* Except for the stack of the currently executing thread, none of this memory
* is normally accessible to user threads unless specifically granted at
* runtime.
*/
extern char __kernel_ram_start[];
extern char __kernel_ram_end[];
extern char __kernel_ram_size[];
/* Used by _bss_zero or arch-specific implementation */
extern char __bss_start[];
extern char __bss_end[];
#ifdef CONFIG_APPLICATION_MEMORY
extern char __app_bss_start[];
extern char __app_bss_end[];
#endif
/* Used by _data_copy() or arch-specific implementation */
#ifdef CONFIG_XIP
extern char __data_rom_start[];
extern char __data_ram_start[];
extern char __data_ram_end[];
#ifdef CONFIG_APPLICATION_MEMORY
extern char __app_data_rom_start[];
extern char __app_data_ram_start[];
extern char __app_data_ram_end[];
#endif /* CONFIG_APPLICATION_MEMORY */
#endif /* CONFIG_XIP */
/* Includes text and rodata */
extern char _image_rom_start[];
extern char _image_rom_end[];
extern char _image_rom_size[];
/* datas, bss, noinit */
extern char _image_ram_start[];
extern char _image_ram_end[];
extern char _image_text_start[];
extern char _image_text_end[];
extern char _image_rodata_start[];
extern char _image_rodata_end[];
extern char _vector_start[];
extern char _vector_end[];
/* end address of image, used by newlib for the heap */
extern char _end[];
#ifdef CONFIG_CCM_BASE_ADDRESS
extern char __ccm_data_rom_start[];
extern char __ccm_start[];
extern char __ccm_data_start[];
extern char __ccm_data_end[];
extern char __ccm_bss_start[];
extern char __ccm_bss_end[];
extern char __ccm_noinit_start[];
extern char __ccm_noinit_end[];
extern char __ccm_end[];
#endif /* CONFIG_CCM_BASE_ADDRESS */
/* Used by the Security Attribution Unit to configure the
* Non-Secure Callable region.
*/
#ifdef CONFIG_ARM_FIRMWARE_HAS_SECURE_ENTRY_FUNCS
extern char __sg_start[];
extern char __sg_end[];
extern char __sg_size[];
#endif /* CONFIG_ARM_FIRMWARE_HAS_SECURE_ENTRY_FUNCS */
#endif /* ! _ASMLANGUAGE */
#endif /* ZEPHYR_INCLUDE_LINKER_LINKER_DEFS_H_ */