1/*
2 * Copyright (c) 2020 Synopsys.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7/**
8 * @brief Common parts of the linker scripts for the ARCv2 targets for
9 * GNU and MWDT toolchains.
10 */
11
12#include <zephyr/linker/sections.h>
13#include <zephyr/linker/linker-defs.h>
14#include <zephyr/linker/linker-tool.h>
15
16/* physical address of RAM */
17#ifdef CONFIG_HARVARD
18	#define ROMABLE_REGION ICCM
19	#define RAMABLE_REGION DCCM
20	#define ROM_RAM_IN_SAME_REGION 0
21#else
22	#if defined(CONFIG_XIP) && (FLASH_SIZE != 0)
23		#define ROMABLE_REGION FLASH
24		#define RAMABLE_REGION SRAM
25		#define ROM_RAM_IN_SAME_REGION 0
26	#else
27		#define ROMABLE_REGION SRAM
28		#define RAMABLE_REGION SRAM
29		#define ROM_RAM_IN_SAME_REGION 1
30	#endif
31#endif
32
33#ifdef CONFIG_ARC_MPU_ENABLE
34	#if CONFIG_ARC_MPU_VER == 2
35		#define MPU_MIN_SIZE 2048
36	#elif (CONFIG_ARC_MPU_VER == 3) ||  (CONFIG_ARC_MPU_VER == 4) || \
37			(CONFIG_ARC_MPU_VER == 6) || (CONFIG_ARC_MPU_VER == 8)
38		#define MPU_MIN_SIZE 32
39	#endif
40	#define MPU_MIN_SIZE_ALIGN . = ALIGN(MPU_MIN_SIZE);
41	#if defined(CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT)
42		#define MPU_ALIGN(region_size) \
43			. = ALIGN(MPU_MIN_SIZE); \
44			. = ALIGN( 1 << LOG2CEIL(region_size))
45	#else
46		#define MPU_ALIGN(region_size) \
47			. = ALIGN(MPU_MIN_SIZE)
48	#endif
49#else
50	#define MPU_MIN_SIZE_ALIGN
51	#define MPU_ALIGN(region_size) . = ALIGN(4)
52#endif
53
54OUTPUT_ARCH(arc)
55ENTRY(CONFIG_KERNEL_ENTRY)
56
57MEMORY {
58#ifdef FLASH_START
59	FLASH (rx)  : ORIGIN = FLASH_START, LENGTH = FLASH_SIZE
60#endif
61#ifdef ICCM_START
62	ICCM  (rwx)  : ORIGIN = ICCM_START,  LENGTH = ICCM_SIZE
63#endif
64#ifdef SRAM_START
65	SRAM  (rwx) : ORIGIN = SRAM_START,  LENGTH = SRAM_SIZE
66#endif
67#ifdef DCCM_START
68	DCCM  (rw)  : ORIGIN = DCCM_START,  LENGTH = DCCM_SIZE
69#endif
70#ifdef XCCM_START
71	XCCM  (rw)  : ORIGIN = XCCM_START,  LENGTH = XCCM_SIZE
72#endif
73#ifdef YCCM_START
74	YCCM  (rw)  : ORIGIN = YCCM_START,  LENGTH = YCCM_SIZE
75#endif
76	/* Used by and documented in include/linker/intlist.ld */
77	IDT_LIST  (wx)      : ORIGIN = 0xFFFFF7FF, LENGTH = 2K
78}
79
80SECTIONS {
81
82#include <zephyr/linker/rel-sections.ld>
83
84#ifdef CONFIG_LLEXT
85#include <zephyr/linker/llext-sections.ld>
86#endif
87
88	GROUP_START(ROMABLE_REGION)
89
90	SECTION_PROLOGUE(_TEXT_SECTION_NAME,,ALIGN(1024)) {
91		__rom_region_start = .;
92		__text_region_start = .;
93
94/* Located in generated directory. This file is populated by the
95 * zephyr_linker_sources() Cmake function.
96 */
97#include <snippets-rom-start.ld>
98		*(.text .text.*)
99		*(.gnu.linkonce.t.*)
100
101	. = ALIGN(4);
102#include <zephyr/linker/kobject-text.ld>
103	} GROUP_LINK_IN(ROMABLE_REGION)
104
105	__text_region_end = .;
106	__rodata_region_start = .;
107
108#include <zephyr/linker/common-rom.ld>
109/* Located in generated directory. This file is populated by calling
110 * zephyr_linker_sources(ROM_SECTIONS ...). Useful for grouping iterable RO structs.
111 */
112#include <snippets-rom-sections.ld>
113#ifdef __MWDT_LINKER_CMD__
114	SECTION_DATA_PROLOGUE(tdata,,)
115	{
116		*(.tls .tls.*);
117	} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
118
119	#ifdef CONFIG_XIP
120		/* The "primary copy" of tls should be only in flash on XIP systems */
121		PROVIDE(_arcmwdt_tls_start = LOADADDR(tdata));
122	#else
123		PROVIDE(_arcmwdt_tls_start = ADDR(tdata));
124	#endif
125
126	PROVIDE(_arcmwdt_tls_size = SIZEOF(tdata));
127
128/* TODO: add mwdt specific ROM C++ sections */
129#else
130#include <zephyr/linker/thread-local-storage.ld>
131#include <zephyr/linker/cplusplus-rom.ld>
132#endif /* __MWDT_LINKER_CMD__ */
133
134	SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) {
135		*(".rodata")
136		*(".rodata.*")
137		*(.gnu.linkonce.r.*)
138
139/* Located in generated directory. This file is populated by the
140 * zephyr_linker_sources() Cmake function.
141 */
142#include <snippets-rodata.ld>
143#include <zephyr/linker/kobject-rom.ld>
144
145#if defined(CONFIG_CPP) && !defined(CONFIG_STATIC_INIT_GNU) && defined(__MWDT_LINKER_CMD__)
146		. = ALIGN(4);
147		_fctors = .;
148		KEEP(*(.ctors*))
149		_ectors = .;
150#endif /* CONFIG_CPP && !CONFIG_STATIC_INIT_GNU && __MWDT_LINKER_CMD__ */
151
152/* This extra MPU alignment of RAMABLE_REGION is only required if we put ROMABLE_REGION and
153 * RAMABLE_REGION into the same (continuous) memory - otherwise we can get beginning of the
154 * RAMABLE_REGION in the end of ROMABLE_REGION MPU aperture.
155 */
156#if ROM_RAM_IN_SAME_REGION
157		MPU_ALIGN(ABSOLUTE(.) - __rom_region_start);
158#endif
159	} GROUP_LINK_IN(ROMABLE_REGION)
160
161	__rodata_region_end = .;
162
163	MPU_ALIGN(__rodata_region_end - __rom_region_start);
164	__rom_region_end = .;
165	__rom_region_size = __rom_region_end - __rom_region_start;
166
167	GROUP_END(ROMABLE_REGION)
168
169	GROUP_START(RAMABLE_REGION)
170
171	MPU_MIN_SIZE_ALIGN
172
173	_image_ram_start = .;
174
175#include <app_data_alignment.ld>
176
177/* Located in generated directory. This file is populated by the
178 * zephyr_linker_sources() Cmake function.
179 */
180#include <snippets-ram-sections.ld>
181
182#if defined(CONFIG_USERSPACE)
183#define APP_SHARED_ALIGN MPU_MIN_SIZE_ALIGN
184#define SMEM_PARTITION_ALIGN MPU_ALIGN
185
186#include <app_smem.ld>
187	_app_smem_size = _app_smem_end - _app_smem_start;
188	_app_smem_rom_start = LOADADDR(_APP_SMEM_SECTION_NAME);
189#endif /* CONFIG_USERSPACE */
190
191	SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) {
192		MPU_MIN_SIZE_ALIGN
193		/*
194		 * For performance, BSS section is assumed to be 4 byte aligned and
195		 * a multiple of 4 bytes
196		 */
197		. = ALIGN(4);
198		__bss_start = .;
199		__kernel_ram_start = .;
200		*(".bss")
201		*(".bss.*")
202		*(COMMON)
203		*(".kernel_bss.*")
204
205		/*
206		 * BSP clears this memory in words only and doesn't clear any
207		 * potential left over bytes.
208		 */
209		__bss_end = ALIGN(4);
210	} GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
211
212#include <zephyr/linker/common-noinit.ld>
213
214	GROUP_START(DATA_REGION)
215
216	SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,) {
217
218/* when XIP, .text is in ROM, but vector table must be at start of .data */
219		__data_region_start = .;
220		__data_start = .;
221		*(".data")
222		*(".data.*")
223		*(".kernel.*")
224
225/* Located in generated directory. This file is populated by the
226 * zephyr_linker_sources() Cmake function.
227 */
228#include <snippets-rwdata.ld>
229
230		__data_end = .;
231
232	} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
233
234	__data_size = __data_end - __data_start;
235	__data_load_start = LOADADDR(_DATA_SECTION_NAME);
236
237	__data_region_load_start = LOADADDR(_DATA_SECTION_NAME);
238
239#include <zephyr/linker/common-ram.ld>
240#include <zephyr/linker/kobject-data.ld>
241
242#ifdef __MWDT_LINKER_CMD__
243/* TODO: add mwdt specific RAM C++ sections */
244#else
245#include <zephyr/linker/cplusplus-ram.ld>
246#endif /* __MWDT_LINKER_CMD__ */
247
248/* Located in generated directory. This file is populated by the
249 * zephyr_linker_sources() Cmake function.
250 */
251#include <snippets-data-sections.ld>
252
253	__data_region_end = .;
254
255	MPU_MIN_SIZE_ALIGN
256	/* Define linker symbols */
257
258	__kernel_ram_end = .;
259	__kernel_ram_size = __kernel_ram_end - __kernel_ram_start;
260
261#ifdef __MWDT_LINKER_CMD__
262/* mwdt requires _fstack, _estack which will be used in _stkchk.
263 * _stkchk is inserted by mwdt automatically, if _fstack, _estack is not
264 * set correctly, the  brk_s instruction will be called
265 * here, we use a trick to deceive the compiler.
266 */
267	_fstack = _image_ram_start;
268	_estack = .;
269#endif /* __MWDT_LINKER_CMD__ */
270
271#ifdef CONFIG_ARC_XY_ENABLE
272	SECTION_PROLOGUE(xdata,,)
273	{
274		__xdata_start = .;
275		*(.Xdata*)
276		__xdata_end = .;
277	} GROUP_DATA_LINK_IN(XCCM, RAMABLE_REGION)
278
279	SECTION_PROLOGUE(ydata,,)
280	{
281		__ydata_start = .;
282		*(.Ydata*)
283		__ydata_end = .;
284	} GROUP_DATA_LINK_IN(YCCM, RAMABLE_REGION)
285#endif
286
287/* Located in generated directory. This file is populated by the
288 * zephyr_linker_sources() Cmake function.
289 */
290#include <snippets-sections.ld>
291
292#include <zephyr/linker/ram-end.ld>
293
294	GROUP_END(RAMABLE_REGION)
295
296#include <zephyr/linker/debug-sections.ld>
297
298	SECTION_PROLOGUE(.arcextmap, 0,) {
299		*(.arcextmap)
300		*(.arcextmap.*)
301		*(.gnu.linkonce.arcextmap.*)
302	}
303
304	SECTION_PROLOGUE(.ARC.attributes, 0,) {
305		KEEP(*(.ARC.attributes))
306		KEEP(*(.gnu.attributes))
307	}
308
309#if !defined(CONFIG_XIP)
310	/*
311	 * Zephyr uses _estack as a start of heap allocation area.
312	 * Region [_estack .. sram_end] should be defined in MPU.
313	 * Including _image_ram region which is [_image_ram_start .. _image_ram_end]
314	 * we get [_image_ram_start .. sram_end] region to be defined in MPU.
315	 */
316	__arc_rw_sram_size = SRAM_START + SRAM_SIZE - _image_ram_start;
317#endif
318
319	/DISCARD/ : {
320#if defined(CONFIG_CPP) && !defined(CONFIG_STATIC_INIT_GNU) && defined(__MWDT_LINKER_CMD__)
321		*(.dtors*)
322		*(.fini*)
323		*(.eh_frame*)
324#endif /* CONFIG_CPP && !CONFIG_STATIC_INIT_GNU && __MWDT_LINKER_CMD__ */
325		*(.note.GNU-stack)
326		*(.got.plt)
327		*(.igot.plt)
328		*(.got)
329		*(.igot)
330	}
331}
332