1/*
2 * Copyright (c) 2016 Cadence Design Systems, Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7/**
8 * @file
9 * @brief Linker command/script file
10 *
11 * Linker script for the Xtensa platform.
12 */
13
14#include <xtensa/config/core-isa.h>
15
16#include <zephyr/linker/sections.h>
17
18#include <zephyr/devicetree.h>
19#include <zephyr/linker/linker-defs.h>
20#include <zephyr/linker/linker-tool.h>
21
22#define RAMABLE_REGION RAM :sram0_phdr
23#define ROMABLE_REGION RAM :sram0_phdr
24
25#ifdef CONFIG_MMU
26#define MMU_PAGE_ALIGN . = ALIGN(CONFIG_MMU_PAGE_SIZE);
27#define HDR_MMU_PAGE_ALIGN ALIGN(CONFIG_MMU_PAGE_SIZE)
28#define HDR_4K_OR_MMU_PAGE_ALIGN ALIGN(CONFIG_MMU_PAGE_SIZE)
29#define LAST_RAM_ALIGN MMU_PAGE_ALIGN
30#else
31#define MMU_PAGE_ALIGN . = ALIGN(4);
32#define HDR_MMU_PAGE_ALIGN ALIGN(4)
33#define HDR_4K_OR_MMU_PAGE_ALIGN ALIGN(4096)
34#endif
35
36#define PHYS_SRAM0_ADDR	(DT_REG_ADDR(DT_NODELABEL(sram0)))
37#define PHYS_SRAM0_SIZE	(DT_REG_SIZE(DT_NODELABEL(sram0)))
38
39#define PHYS_ROM0_ADDR	(DT_REG_ADDR(DT_NODELABEL(rom0)))
40#define PHYS_ROM0_SIZE	(DT_REG_SIZE(DT_NODELABEL(rom0)))
41
42/* Usable RAM is after the exception vectors and page-aligned. */
43#define PHYS_RAM_ADDR	(PHYS_SRAM0_ADDR + CONFIG_SRAM_OFFSET)
44#define PHYS_RAM_SIZE	(PHYS_SRAM0_SIZE - CONFIG_SRAM_OFFSET)
45
46MEMORY
47{
48  vectors : org = 0x00002000, len = 0x2400
49#ifdef CONFIG_XTENSA_MMU
50  vec_helpers  : org = 0x00002400, len = (PHYS_RAM_ADDR - 0x00002400)
51#endif
52  RAM          : org = PHYS_RAM_ADDR, len = PHYS_RAM_SIZE
53
54  /* Although ROM is of size 0x02000000, we limit it to 8KB so
55   * fewer L2 page table entries are needed.
56   */
57  rom0_seg    : org = PHYS_ROM0_ADDR, len = PHYS_ROM0_SIZE
58
59#ifdef CONFIG_GEN_ISR_TABLES
60  /* The space before exception vectors is not being used.
61   * So we stuff the temporary IDT_LIST there to avoid
62   * some linker issues which would balloon the size of
63   * the intermediate files (like zephyr_pre0.elf, to
64   * couple hundred MBs or even GBs).
65   */
66  IDT_LIST     : org = 0x00000000, len = 0x2000
67#endif
68}
69
70PHDRS
71{
72  vectors_phdr PT_LOAD;
73#ifdef CONFIG_XTENSA_MMU
74  vec_helpers_phdr PT_LOAD;
75#endif
76
77  rom0_phdr PT_LOAD;
78  sram0_phdr PT_LOAD;
79  sram0_bss_phdr PT_LOAD;
80}
81
82
83/*  Default entry point:  */
84ENTRY(CONFIG_KERNEL_ENTRY)
85
86_rom_store_table = 0;
87PROVIDE(_memmap_vecbase_reset = 0x00002000);
88PROVIDE(_memmap_reset_vector = 0xFE000000);
89/* Various memory-map dependent cache attribute settings:
90 *
91 * Note that there is no cacheattr register which means thah
92 * cacheattr is emulated through TLB way 6 (8x 512MB regions).
93 * So the attributes here are the MMU memory attributes:
94 *   0x3 - rwx, bypass cache
95 *   0x7 - rwx, cache write back
96 *   0xB - wrx, cache write through
97 * Refer to the ISA manual for other attributes.
98 */
99_memmap_cacheattr_wb_base = 0x70000007;
100_memmap_cacheattr_wt_base = 0xB000000B;
101_memmap_cacheattr_bp_base = 0x30000003;
102_memmap_cacheattr_unused_mask = 0x0FFFFFF0;
103_memmap_cacheattr_wb_strict = 0x7FFFFFF7;
104_memmap_cacheattr_wt_strict = 0xBFFFFFFB;
105_memmap_cacheattr_bp_strict = 0x3FFFFFF3;
106_memmap_cacheattr_wb_allvalid = 0x73333337;
107_memmap_cacheattr_wt_allvalid = 0xB333333B;
108_memmap_cacheattr_bp_allvalid = 0x33333333;
109PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_allvalid);
110
111SECTIONS
112{
113
114#include <zephyr/linker/rel-sections.ld>
115
116#ifdef CONFIG_LLEXT
117#include <zephyr/linker/llext-sections.ld>
118#endif
119
120#ifdef CONFIG_GEN_ISR_TABLES
121#include <zephyr/linker/intlist.ld>
122#endif
123
124/* Auto-generated vector linkage, to "vectors" memory region */
125#include <xtensa_vectors.ld>
126 >vectors :vectors_phdr
127
128#define LIB_OBJ_FUNC_IN_SECT(library, obj_file, func)		\
129	*##library##:##obj_file##(.literal.##func .text.##func)	\
130
131#ifdef CONFIG_XTENSA_MMU
132  .vec_helpers :
133  {
134    /* There is quite some space between .DoubleExceptionVector
135     * and the beginning of .text. We can put exception handling
136     * code here to avoid TLB misses, thus speed up exception
137     * handling a little bit.
138     *
139     * Note: DO NOT PUT MMU init code here as this will be
140     *       mapped in TLB manually. This manual entry will
141     *       conflict with auto-refill TLB resulting in
142     *       TLB multi-hit exception.
143     */
144
145    *libarch__xtensa__core.a:xtensa_asm2_util.S.obj(.literal .text)
146    *libarch__xtensa__core.a:xtensa_asm2_util.S.obj(.iram.text .iram0.text)
147
148    *libarch__xtensa__core.a:window_vectors.S.obj(.iram.text)
149
150    *libarch__xtensa__core.a:crt1.S.obj(.literal .text)
151
152    LIB_OBJ_FUNC_IN_SECT(libarch__xtensa__core.a,xtensa_asm2.c.obj,*)
153    LIB_OBJ_FUNC_IN_SECT(libarch__xtensa__core.a,fatal.c.obj,*)
154    LIB_OBJ_FUNC_IN_SECT(libarch__xtensa__core.a,cpu_idle.c.obj,*)
155
156    *(.text.arch_is_in_isr)
157
158    /* To support backtracing */
159    LIB_OBJ_FUNC_IN_SECT(libarch__xtensa__core.a,xtensa_backtrace.c.obj,*)
160
161    *libarch__xtensa__core.a:debug_helpers_asm.S.obj(.iram1.literal .iram1)
162
163    /* Userspace related stuff */
164    LIB_OBJ_FUNC_IN_SECT(libarch__xtensa__core.a,userspace.S.obj,xtensa_do_syscall)
165    LIB_OBJ_FUNC_IN_SECT(libarch__xtensa__core.a,ptables.c.obj,xtensa_swap_update_page_tables)
166
167    /* Below are to speed up execution by avoiding TLB misses
168     * on frequently used functions.
169     *
170     * There is almost 1MB space (due to TLB pinning) so we can
171     * be generous.
172     */
173    LIB_OBJ_FUNC_IN_SECT(libkernel.a,,*)
174
175    LIB_OBJ_FUNC_IN_SECT(libdrivers__console.a,,*)
176    LIB_OBJ_FUNC_IN_SECT(libdrivers__timer.a,,*)
177
178    *(.literal.z_vrfy_* .text.z_vrfy_*)
179    *(.literal.z_mrsh_* .text.z_mrsh_*)
180    *(.literal.z_impl_* .text.z_impl_*)
181    *(.literal.z_obj_*  .text.z_obj_*)
182
183    *(.literal.k_sys_fatal_error_handler .text.k_sys_fatal_error_handler)
184  } >vec_helpers :vec_helpers_phdr
185#endif /* CONFIG_XTENSA_MMU */
186
187#ifdef CONFIG_CODE_DATA_RELOCATION
188#include <linker_relocate.ld>
189#endif
190
191  .ResetVector.text : ALIGN(4)
192  {
193    __rom_region_start = ABSOLUTE(.);
194    _ResetVector_text_start = ABSOLUTE(.);
195    KEEP (*(.ResetVector.text))
196    _ResetVector_text_end = ABSOLUTE(.);
197  } >rom0_seg :rom0_phdr
198
199  .text : HDR_MMU_PAGE_ALIGN
200  {
201    _stext = .;
202    __text_region_start = .;
203    z_mapped_start = .;
204    _text_start = ABSOLUTE(.);
205    *(.entry.text)
206    *(.init.literal)
207    *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text)
208    *(.iram1.literal .iram1)
209    KEEP(*(.init))
210    *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
211    *(.fini.literal)
212    KEEP(*(.fini))
213    *(.gnu.version)
214
215    #include <zephyr/linker/kobject-text.ld>
216
217    MMU_PAGE_ALIGN
218
219    _text_end = ABSOLUTE(.);
220    _etext = .;
221  } >RAMABLE_REGION
222  __text_region_end = .;
223
224  .rodata : HDR_MMU_PAGE_ALIGN
225  {
226    __rodata_region_start = ABSOLUTE(.);
227    *(.rodata)
228    *(.rodata.*)
229    *(.gnu.linkonce.r.*)
230    *(.rodata1)
231
232    . = ALIGN(4);
233    #include <snippets-rodata.ld>
234    #include <zephyr/linker/kobject-rom.ld>
235  } >RAMABLE_REGION
236
237#include <zephyr/linker/common-rom.ld>
238/* Located in generated directory. This file is populated by calling
239 * zephyr_linker_sources(ROM_SECTIONS ...). Useful for grouping iterable RO structs.
240 */
241#include <snippets-rom-sections.ld>
242
243#include <zephyr/linker/thread-local-storage.ld>
244
245#include <zephyr/linker/cplusplus-rom.ld>
246
247  .rodata_end : ALIGN(4)
248  {
249    . = ALIGN(4);		/* this table MUST be 4-byte aligned */
250    _bss_table_start = ABSOLUTE(.);
251    LONG(_bss_start)
252    LONG(_bss_end)
253    _bss_table_end = ABSOLUTE(.);
254
255    MMU_PAGE_ALIGN
256
257    __rodata_region_end = ABSOLUTE(.);
258  } >RAMABLE_REGION
259
260#ifdef CONFIG_USERSPACE
261#define SMEM_PARTITION_ALIGN(size) MMU_PAGE_ALIGN
262#define APP_SHARED_ALIGN  MMU_PAGE_ALIGN
263
264#include <app_smem.ld>
265
266  _image_ram_start = _app_smem_start;
267  _app_smem_size = _app_smem_end - _app_smem_start;
268  _app_smem_num_words = _app_smem_size >> 2;
269  _app_smem_rom_start = LOADADDR(_APP_SMEM_SECTION_NAME);
270  _app_smem_num_words = _app_smem_size >> 2;
271#endif /* CONFIG_USERSPACE */
272
273  .data : HDR_MMU_PAGE_ALIGN
274  {
275#ifndef CONFIG_USERSPACE
276    _image_ram_start = ABSOLUTE(.);
277#endif
278    __data_start = ABSOLUTE(.);
279    *(.data)
280    *(.data.*)
281    *(.gnu.linkonce.d.*)
282    KEEP(*(.gnu.linkonce.d.*personality*))
283    *(.data1)
284    *(.sdata)
285    *(.sdata.*)
286    *(.gnu.linkonce.s.*)
287    *(.sdata2)
288    *(.sdata2.*)
289    *(.gnu.linkonce.s2.*)
290    KEEP(*(.jcr))
291
292    . = ALIGN(4);
293    #include <snippets-rwdata.ld>
294    . = ALIGN(4);
295
296    MMU_PAGE_ALIGN
297
298    __data_end = ABSOLUTE(.);
299  } >RAMABLE_REGION
300
301#include <snippets-sections.ld>
302
303#include <snippets-data-sections.ld>
304
305#include <zephyr/linker/common-ram.ld>
306
307#include <zephyr/linker/cplusplus-ram.ld>
308
309#include <snippets-ram-sections.ld>
310
311  .bss (NOLOAD) : HDR_MMU_PAGE_ALIGN
312  {
313    . = ALIGN (8);
314    _bss_start = ABSOLUTE(.);
315    *(.dynsbss)
316    *(.sbss)
317    *(.sbss.*)
318    *(.gnu.linkonce.sb.*)
319    *(.scommon)
320    *(.sbss2)
321    *(.sbss2.*)
322    *(.gnu.linkonce.sb2.*)
323    *(.dynbss)
324    *(.bss)
325    *(.bss.*)
326    *(.gnu.linkonce.b.*)
327    *(COMMON)
328    *(.sram.bss)
329    . = ALIGN (8);
330    _bss_end = ABSOLUTE(.);
331
332    MMU_PAGE_ALIGN
333
334  } >RAM :sram0_bss_phdr
335
336#include <zephyr/linker/common-noinit.ld>
337
338/* Must be last in RAM */
339#include <zephyr/linker/kobject-data.ld>
340
341#include <zephyr/linker/ram-end.ld>
342
343  _heap_start = .;
344
345  PROVIDE(_heap_sentry = ORIGIN(RAM) + LENGTH(RAM));
346  PROVIDE(_heap_end = ORIGIN(RAM) + LENGTH(RAM));
347
348  PROVIDE(__stack = z_interrupt_stacks + CONFIG_ISR_STACK_SIZE);
349
350#include <zephyr/linker/debug-sections.ld>
351
352  .xtensa.info  0 :  { *(.xtensa.info) }
353  .xt.insn 0 :
354  {
355    KEEP (*(.xt.insn))
356    KEEP (*(.gnu.linkonce.x.*))
357  }
358  .xt.prop 0 :
359  {
360    KEEP (*(.xt.prop))
361    KEEP (*(.xt.prop.*))
362    KEEP (*(.gnu.linkonce.prop.*))
363  }
364  .xt.lit 0 :
365  {
366    KEEP (*(.xt.lit))
367    KEEP (*(.xt.lit.*))
368    KEEP (*(.gnu.linkonce.p.*))
369  }
370  .debug.xt.callgraph 0 :
371  {
372    KEEP (*(.debug.xt.callgraph .debug.xt.callgraph.* .gnu.linkonce.xt.callgraph.*))
373  }
374}
375