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	GROUP_START(ROMABLE_REGION)
85
86	SECTION_PROLOGUE(_TEXT_SECTION_NAME,,ALIGN(1024)) {
87		__rom_region_start = .;
88		__text_region_start = .;
89
90/* Located in generated directory. This file is populated by the
91 * zephyr_linker_sources() Cmake function.
92 */
93#include <snippets-rom-start.ld>
94		*(.text .text.*)
95		*(.gnu.linkonce.t.*)
96
97	. = ALIGN(4);
98#include <zephyr/linker/kobject-text.ld>
99	} GROUP_LINK_IN(ROMABLE_REGION)
100
101	__text_region_end = .;
102	__rodata_region_start = .;
103
104#include <zephyr/linker/common-rom.ld>
105#ifdef __MWDT_LINKER_CMD__
106	SECTION_DATA_PROLOGUE(tdata,,)
107	{
108		*(.tls .tls.*);
109	} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
110
111	#ifdef CONFIG_XIP
112		/* The "primary copy" of tls should be only in flash on XIP systems */
113		PROVIDE(_arcmwdt_tls_start = LOADADDR(tdata));
114	#else
115		PROVIDE(_arcmwdt_tls_start = ADDR(tdata));
116	#endif
117
118	PROVIDE(_arcmwdt_tls_size = SIZEOF(tdata));
119
120/* TODO: add mwdt specific ROM C++ sections */
121#else
122#include <zephyr/linker/thread-local-storage.ld>
123#include <zephyr/linker/cplusplus-rom.ld>
124#endif /* __MWDT_LINKER_CMD__ */
125
126	SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) {
127		*(".rodata")
128		*(".rodata.*")
129		*(.gnu.linkonce.r.*)
130
131/* Located in generated directory. This file is populated by the
132 * zephyr_linker_sources() Cmake function.
133 */
134#include <snippets-rodata.ld>
135#include <zephyr/linker/kobject-rom.ld>
136
137#if defined(CONFIG_CPP) && !defined(CONFIG_CPP_STATIC_INIT_GNU) && defined(__MWDT_LINKER_CMD__)
138		. = ALIGN(4);
139		_fctors = .;
140		KEEP(*(.ctors*))
141		_ectors = .;
142#endif /* CONFIG_CPP && !CONFIG_CPP_STATIC_INIT_GNU && __MWDT_LINKER_CMD__ */
143
144/* This extra MPU alignment of RAMABLE_REGION is only required if we put ROMABLE_REGION and
145 * RAMABLE_REGION into the same (continuous) memory - otherwise we can get beginning of the
146 * RAMABLE_REGION in the end of ROMABLE_REGION MPU aperture.
147 */
148#if ROM_RAM_IN_SAME_REGION
149		MPU_ALIGN(ABSOLUTE(.) - __rom_region_start);
150#endif
151	} GROUP_LINK_IN(ROMABLE_REGION)
152
153	__rodata_region_end = .;
154
155	MPU_ALIGN(__rodata_region_end - __rom_region_start);
156	__rom_region_end = .;
157	__rom_region_size = __rom_region_end - __rom_region_start;
158
159	GROUP_END(ROMABLE_REGION)
160
161	GROUP_START(RAMABLE_REGION)
162
163	MPU_MIN_SIZE_ALIGN
164
165	_image_ram_start = .;
166
167#include <app_data_alignment.ld>
168
169/* Located in generated directory. This file is populated by the
170 * zephyr_linker_sources() Cmake function.
171 */
172#include <snippets-ram-sections.ld>
173
174#if defined(CONFIG_USERSPACE)
175#define APP_SHARED_ALIGN MPU_MIN_SIZE_ALIGN
176#define SMEM_PARTITION_ALIGN MPU_ALIGN
177
178#include <app_smem.ld>
179	_app_smem_size = _app_smem_end - _app_smem_start;
180	_app_smem_rom_start = LOADADDR(_APP_SMEM_SECTION_NAME);
181#endif /* CONFIG_USERSPACE */
182
183	SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) {
184		MPU_MIN_SIZE_ALIGN
185		/*
186		 * For performance, BSS section is assumed to be 4 byte aligned and
187		 * a multiple of 4 bytes
188		 */
189		. = ALIGN(4);
190		__bss_start = .;
191		__kernel_ram_start = .;
192		*(".bss")
193		*(".bss.*")
194		*(COMMON)
195		*(".kernel_bss.*")
196
197		/*
198		 * BSP clears this memory in words only and doesn't clear any
199		 * potential left over bytes.
200		 */
201		__bss_end = ALIGN(4);
202	} GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
203
204#include <zephyr/linker/common-noinit.ld>
205
206	GROUP_START(DATA_REGION)
207
208	SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,) {
209
210/* when XIP, .text is in ROM, but vector table must be at start of .data */
211		__data_region_start = .;
212		__data_start = .;
213		*(".data")
214		*(".data.*")
215		*(".kernel.*")
216
217/* Located in generated directory. This file is populated by the
218 * zephyr_linker_sources() Cmake function.
219 */
220#include <snippets-rwdata.ld>
221
222		__data_end = .;
223
224	} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
225
226	__data_size = __data_end - __data_start;
227	__data_load_start = LOADADDR(_DATA_SECTION_NAME);
228
229	__data_region_load_start = LOADADDR(_DATA_SECTION_NAME);
230
231#include <zephyr/linker/common-ram.ld>
232#include <zephyr/linker/kobject-data.ld>
233
234#ifdef __MWDT_LINKER_CMD__
235/* TODO: add mwdt specific RAM C++ sections */
236#else
237#include <zephyr/linker/cplusplus-ram.ld>
238#endif /* __MWDT_LINKER_CMD__ */
239
240/* Located in generated directory. This file is populated by the
241 * zephyr_linker_sources() Cmake function.
242 */
243#include <snippets-data-sections.ld>
244
245	__data_region_end = .;
246
247	MPU_MIN_SIZE_ALIGN
248	/* Define linker symbols */
249
250	__kernel_ram_end = .;
251	__kernel_ram_size = __kernel_ram_end - __kernel_ram_start;
252
253#ifdef __MWDT_LINKER_CMD__
254/* mwdt requires _fstack, _estack which will be used in _stkchk.
255 * _stkchk is inserted by mwdt automatically, if _fstack, _estack is not
256 * set correctly, the  brk_s instruction will be called
257 * here, we use a trick to deceive the compiler.
258 */
259	_fstack = _image_ram_start;
260	_estack = .;
261#endif /* __MWDT_LINKER_CMD__ */
262
263#ifdef CONFIG_ARC_XY_ENABLE
264	SECTION_PROLOGUE(xdata,,)
265	{
266		__xdata_start = .;
267		*(.Xdata*)
268		__xdata_end = .;
269	} GROUP_DATA_LINK_IN(XCCM, RAMABLE_REGION)
270
271	SECTION_PROLOGUE(ydata,,)
272	{
273		__ydata_start = .;
274		*(.Ydata*)
275		__ydata_end = .;
276	} GROUP_DATA_LINK_IN(YCCM, RAMABLE_REGION)
277#endif
278
279/* Located in generated directory. This file is populated by the
280 * zephyr_linker_sources() Cmake function.
281 */
282#include <snippets-sections.ld>
283
284#include <zephyr/linker/ram-end.ld>
285
286    GROUP_END(RAMABLE_REGION)
287
288#include <zephyr/linker/debug-sections.ld>
289
290	SECTION_PROLOGUE(.ARC.attributes, 0,) {
291		KEEP(*(.ARC.attributes))
292		KEEP(*(.gnu.attributes))
293	}
294
295#if !defined(CONFIG_XIP)
296	/*
297	 * Zephyr uses _estack as a start of heap allocation area.
298	 * Region [_estack .. sram_end] should be defined in MPU.
299	 * Including _image_ram region which is [_image_ram_start .. _image_ram_end]
300	 * we get [_image_ram_start .. sram_end] region to be defined in MPU.
301	 */
302	__arc_rw_sram_size = SRAM_START + SRAM_SIZE - _image_ram_start;
303#endif
304
305	/DISCARD/ : {
306#if defined(CONFIG_CPP) && !defined(CONFIG_CPP_STATIC_INIT_GNU) && defined(__MWDT_LINKER_CMD__)
307		*(.dtors*)
308		*(.fini*)
309		*(.eh_frame*)
310#endif /* CONFIG_CPP && !CONFIG_CPP_STATIC_INIT_GNU && __MWDT_LINKER_CMD__ */
311		*(.note.GNU-stack)
312		*(.got.plt)
313		*(.igot.plt)
314		*(.got)
315		*(.igot)
316	}
317}
318