1 /*
2  * Copyright (c) 2019 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #ifndef ZEPHYR_INCLUDE_APP_MEMORY_APP_MEMDOMAIN_H_
7 #define ZEPHYR_INCLUDE_APP_MEMORY_APP_MEMDOMAIN_H_
8 
9 #include <zephyr/linker/linker-defs.h>
10 #include <zephyr/sys/dlist.h>
11 #include <zephyr/kernel.h>
12 
13 /**
14  * @brief Application memory domain APIs
15  * @defgroup mem_domain_apis_app Application memory domain APIs
16  * @ingroup mem_domain_apis
17  * @{
18  */
19 
20 #ifdef CONFIG_USERSPACE
21 
22 /**
23  * @brief Name of the data section for a particular partition
24  *
25  * Useful for defining memory pools, or any other macro that takes a
26  * section name as a parameter.
27  *
28  * @param id Partition name
29  */
30 #define K_APP_DMEM_SECTION(id) data_smem_##id##_data
31 
32 /**
33  * @brief Name of the bss section for a particular partition
34  *
35  * Useful for defining memory pools, or any other macro that takes a
36  * section name as a parameter.
37  *
38  * @param id Partition name
39  */
40 #define K_APP_BMEM_SECTION(id) data_smem_##id##_bss
41 
42 /**
43  * @brief Place data in a partition's data section
44  *
45  * Globals tagged with this will end up in the data section for the
46  * specified memory partition. This data should be initialized to some
47  * desired value.
48  *
49  * @param id Name of the memory partition to associate this data
50  */
51 #define K_APP_DMEM(id) Z_GENERIC_SECTION(K_APP_DMEM_SECTION(id))
52 
53 /**
54  * @brief Place data in a partition's bss section
55  *
56  * Globals tagged with this will end up in the bss section for the
57  * specified memory partition. This data will be zeroed at boot.
58  *
59  * @param id Name of the memory partition to associate this data
60  */
61 #define K_APP_BMEM(id) Z_GENERIC_SECTION(K_APP_BMEM_SECTION(id))
62 
63 struct z_app_region {
64 	void *bss_start;
65 	size_t bss_size;
66 };
67 
68 #define Z_APP_START(id) z_data_smem_##id##_part_start
69 #define Z_APP_SIZE(id) z_data_smem_##id##_part_size
70 #define Z_APP_BSS_START(id) z_data_smem_##id##_bss_start
71 #define Z_APP_BSS_SIZE(id) z_data_smem_##id##_bss_size
72 
73 /* If a partition is declared with K_APPMEM_PARTITION, but never has any
74  * data assigned to its contents, then no symbols with its prefix will end
75  * up in the symbol table. This prevents gen_app_partitions.py from detecting
76  * that the partition exists, and the linker symbols which specify partition
77  * bounds will not be generated, resulting in build errors.
78  *
79  * What this inline assembly code does is define a symbol with no data.
80  * This should work for all arches that produce ELF binaries, see
81  * https://sourceware.org/binutils/docs/as/Section.html
82  *
83  * We don't know what active flags/type of the pushed section were, so we are
84  * specific: "aw" indicates section is allocatable and writable,
85  * and "@progbits" indicates the section has data.
86  */
87 #if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
88 /* ARM has a quirk in that '@' denotes a comment, so we have to send
89  * %progbits to the assembler instead.
90  */
91 #define Z_PROGBITS_SYM	"%"
92 #else
93 #define Z_PROGBITS_SYM "@"
94 #endif
95 
96 #if defined(CONFIG_ARC) && defined(__CCAC__)
97 /* ARC MWDT assembler has slightly different pushsection/popsection directives
98  * names.
99  */
100 #define Z_PUSHSECTION_DIRECTIV		".pushsect"
101 #define Z_POPSECTION_DIRECTIVE		".popsect"
102 #else
103 #define Z_PUSHSECTION_DIRECTIV		".pushsection"
104 #define Z_POPSECTION_DIRECTIVE		".popsection"
105 #endif
106 
107 #define Z_APPMEM_PLACEHOLDER(name) \
108 	__asm__ ( \
109 		Z_PUSHSECTION_DIRECTIV " " STRINGIFY(K_APP_DMEM_SECTION(name)) \
110 			",\"aw\"," Z_PROGBITS_SYM "progbits\n\t" \
111 		".global " STRINGIFY(name) "_placeholder\n\t" \
112 		STRINGIFY(name) "_placeholder:\n\t" \
113 		Z_POPSECTION_DIRECTIVE "\n\t")
114 
115 /**
116  * @brief Define an application memory partition with linker support
117  *
118  * Defines a k_mem_paritition with the provided name.
119  * This name may be used with the K_APP_DMEM and K_APP_BMEM macros to
120  * place globals automatically in this partition.
121  *
122  * NOTE: placeholder char variable is defined here to prevent build errors
123  * if a partition is defined but nothing ever placed in it.
124  *
125  * @param name Name of the k_mem_partition to declare
126  */
127 #define K_APPMEM_PARTITION_DEFINE(name) \
128 	extern char Z_APP_START(name)[]; \
129 	extern char Z_APP_SIZE(name)[]; \
130 	struct k_mem_partition name = { \
131 		.start = (uintptr_t) &Z_APP_START(name), \
132 		.size = (size_t) &Z_APP_SIZE(name), \
133 		.attr = K_MEM_PARTITION_P_RW_U_RW \
134 	}; \
135 	extern char Z_APP_BSS_START(name)[]; \
136 	extern char Z_APP_BSS_SIZE(name)[]; \
137 	Z_GENERIC_SECTION(.app_regions.name) \
138 	const struct z_app_region name##_region = { \
139 		.bss_start = &Z_APP_BSS_START(name), \
140 		.bss_size = (size_t) &Z_APP_BSS_SIZE(name) \
141 	}; \
142 	Z_APPMEM_PLACEHOLDER(name)
143 #else
144 
145 #define K_APP_BMEM(ptn)
146 #define K_APP_DMEM(ptn)
147 #define K_APP_DMEM_SECTION(ptn) .data
148 #define K_APP_BMEM_SECTION(ptn) .bss
149 #define K_APPMEM_PARTITION_DEFINE(name)
150 
151 #endif /* CONFIG_USERSPACE */
152 
153 /**
154  * @}
155  */
156 
157 #endif /* ZEPHYR_INCLUDE_APP_MEMORY_APP_MEMDOMAIN_H_ */
158