1/* 2 * Copyright (c) 2016-2017 Jean-Paul Etienne <fractalclone@gmail.com> 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7/** 8 * @file 9 * @brief Linker command/script file 10 * 11 * Generic Linker script for the riscv platform 12 */ 13 14#include <soc.h> 15#include <zephyr/devicetree.h> 16 17#include <zephyr/linker/sections.h> 18#include <zephyr/linker/devicetree_regions.h> 19 20#include <zephyr/linker/linker-defs.h> 21#include <zephyr/linker/linker-tool.h> 22 23#ifdef CONFIG_XIP 24#define ROMABLE_REGION ROM 25#else 26#define ROMABLE_REGION RAM 27#endif 28#define RAMABLE_REGION RAM 29 30#define _EXCEPTION_SECTION_NAME exceptions 31#define _RESET_SECTION_NAME reset 32 33#ifdef CONFIG_XIP 34#if DT_NODE_HAS_COMPAT_STATUS(DT_CHOSEN(zephyr_flash), soc_nv_flash, okay) 35#ifdef CONFIG_FLASH_LOAD_OFFSET 36#define ROM_BASE (DT_REG_ADDR(DT_CHOSEN(zephyr_flash)) + \ 37 CONFIG_FLASH_LOAD_OFFSET) 38#else /* !CONFIG_FLASH_LOAD_OFFSET */ 39#define ROM_BASE DT_REG_ADDR(DT_CHOSEN(zephyr_flash)) 40#endif /* CONFIG_FLASH_LOAD_OFFSET */ 41#define ROM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_flash)) 42#elif DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_flash), jedec_spi_nor) 43/* For jedec,spi-nor we expect the spi controller to memory map the flash 44 * and for that mapping to be the second register property of the spi 45 * controller. 46 */ 47#define SPI_CTRL DT_PARENT(DT_CHOSEN(zephyr_flash)) 48#define ROM_BASE DT_REG_ADDR_BY_IDX(SPI_CTRL, 1) 49#define ROM_SIZE DT_REG_SIZE_BY_IDX(SPI_CTRL, 1) 50#endif 51#else /* CONFIG_XIP */ 52#define ROM_BASE CONFIG_SRAM_BASE_ADDRESS 53#define ROM_SIZE KB(CONFIG_SRAM_SIZE) 54#endif /* CONFIG_XIP */ 55 56#define RAM_BASE CONFIG_SRAM_BASE_ADDRESS 57#define RAM_SIZE KB(CONFIG_SRAM_SIZE) 58 59#ifdef CONFIG_RISCV_PMP 60 #define MPU_MIN_SIZE CONFIG_PMP_GRANULARITY 61 #define MPU_MIN_SIZE_ALIGN . = ALIGN(MPU_MIN_SIZE); 62 #if defined(CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT) 63 #define MPU_ALIGN(region_size) \ 64 . = ALIGN(MPU_MIN_SIZE); \ 65 . = ALIGN( 1 << LOG2CEIL(region_size)) 66 #else 67 #define MPU_ALIGN(region_size) \ 68 . = ALIGN(MPU_MIN_SIZE) 69 #endif 70#else 71 #define MPU_MIN_SIZE_ALIGN 72 #define MPU_ALIGN(region_size) . = ALIGN(4) 73#endif 74 75MEMORY 76{ 77#ifdef CONFIG_XIP 78 ROM (rx) : ORIGIN = ROM_BASE, LENGTH = ROM_SIZE 79#endif 80 RAM (rwx) : ORIGIN = RAM_BASE, LENGTH = RAM_SIZE 81 82 LINKER_DT_REGIONS() 83 84 /* Used by and documented in include/linker/intlist.ld */ 85 IDT_LIST (wx) : ORIGIN = 0xFFFFF7FF, LENGTH = 2K 86} 87 88ENTRY(CONFIG_KERNEL_ENTRY) 89 90SECTIONS 91 { 92 93#include <zephyr/linker/rel-sections.ld> 94 95 /* 96 * The .plt and .iplt are here according to 97 * 'riscv32-zephyr-elf-ld --verbose', before text section. 98 */ 99 SECTION_PROLOGUE(.plt,,) 100 { 101 *(.plt) 102 } 103 104 SECTION_PROLOGUE(.iplt,,) 105 { 106 *(.iplt) 107 } 108 109 GROUP_START(ROMABLE_REGION) 110 __rom_region_start = ROM_BASE; 111 112 SECTION_PROLOGUE(rom_start,,) 113 { 114 . = ALIGN(16); 115/* Located in generated directory. This file is populated by calling 116 * zephyr_linker_sources(ROM_START ...). 117 */ 118#include <snippets-rom-start.ld> 119 } GROUP_LINK_IN(ROMABLE_REGION) 120 121#ifdef CONFIG_CODE_DATA_RELOCATION 122#include <linker_relocate.ld> 123#endif 124 125 SECTION_PROLOGUE(_RESET_SECTION_NAME,,) 126 { 127 KEEP(*(.reset.*)) 128 } GROUP_LINK_IN(ROMABLE_REGION) 129 130 SECTION_PROLOGUE(_EXCEPTION_SECTION_NAME,,) 131 { 132 KEEP(*(".exception.entry.*")) 133 *(".exception.other.*") 134 } GROUP_LINK_IN(ROMABLE_REGION) 135 136 SECTION_PROLOGUE(_TEXT_SECTION_NAME,,) 137 { 138 . = ALIGN(4); 139 KEEP(*(.openocd_debug)) 140 KEEP(*(".openocd_debug.*")) 141 142 __text_region_start = .; 143 144 *(.text) 145 *(".text.*") 146 *(.gnu.linkonce.t.*) 147#include <zephyr/linker/kobject-text.ld> 148 } GROUP_LINK_IN(ROMABLE_REGION) 149 150 __text_region_end = .; 151 152 __rodata_region_start = .; 153#include <zephyr/linker/common-rom.ld> 154#include <zephyr/linker/thread-local-storage.ld> 155 156 SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) 157 { 158 . = ALIGN(4); 159 *(.srodata) 160 *(".srodata.*") 161 *(.rodata) 162 *(".rodata.*") 163 *(.gnu.linkonce.r.*) 164 *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) 165 166/* Located in generated directory. This file is populated by the 167 * zephyr_linker_sources() Cmake function. 168 */ 169#include <snippets-rodata.ld> 170#include <zephyr/linker/kobject-rom.ld> 171 . = ALIGN(4); 172 } GROUP_LINK_IN(ROMABLE_REGION) 173 174#include <zephyr/linker/cplusplus-rom.ld> 175 __rodata_region_end = .; 176 177 /* For non-XIP system, __rom_region_end symbol should be set to 178 * the end of common ROMABLE_REGIONs (text and rodata) instead of 179 * the linker script end, so it wouldn't mistakenly contain 180 * RAMABLE_REGION in it. 181 */ 182#ifndef CONFIG_XIP 183#ifdef CONFIG_RISCV_PMP 184 SECTION_PROLOGUE(rom_mpu_padding,,) 185 { 186 MPU_ALIGN(__rodata_region_end - __rom_region_start); 187#ifdef CONFIG_QEMU_TARGET 188 /* 189 * QEMU doesn't vet each instruction fetch individually. 190 * Instead, it grabs a whole page and perform dynamic 191 * transation on it in a batch. It therefore validates 192 * PMP permissions using page-sized and -aligned chunks. 193 */ 194 . = ALIGN(0x1000); 195#endif 196 } GROUP_LINK_IN(ROMABLE_REGION) 197#endif /* CONFIG_RISCV_PMP */ 198 199 __rom_region_end = .; 200 __rom_region_size = __rom_region_end - __rom_region_start; 201#endif /* CONFIG_XIP */ 202 GROUP_END(ROMABLE_REGION) 203 204 GROUP_START(RAMABLE_REGION) 205 206 . = RAM_BASE; 207 _image_ram_start = .; 208/* Located in generated directory. This file is populated by the 209 * zephyr_linker_sources() Cmake function. 210 */ 211#include <snippets-ram-sections.ld> 212 213#if defined(CONFIG_USERSPACE) 214#define APP_SHARED_ALIGN MPU_MIN_SIZE_ALIGN 215#define SMEM_PARTITION_ALIGN MPU_ALIGN 216 217#include <app_smem.ld> 218 219 _app_smem_size = _app_smem_end - _app_smem_start; 220 _app_smem_rom_start = LOADADDR(_APP_SMEM_SECTION_NAME); 221#endif /* CONFIG_USERSPACE */ 222 223 SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) 224 { 225 MPU_MIN_SIZE_ALIGN 226 /* 227 * For performance, BSS section is assumed to be 4 byte aligned and 228 * a multiple of 4 bytes 229 */ 230 . = ALIGN(4); 231 __bss_start = .; 232 __kernel_ram_start = .; 233 *(.sbss) 234 *(".sbss.*") 235 *(.bss) 236 *(".bss.*") 237 COMMON_SYMBOLS 238 239#ifdef CONFIG_CODE_DATA_RELOCATION 240#include <linker_sram_bss_relocate.ld> 241#endif 242 243 /* 244 * As memory is cleared in words only, it is simpler to ensure the BSS 245 * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes. 246 */ 247 __bss_end = ALIGN(4); 248 } GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) 249 250#include <zephyr/linker/common-noinit.ld> 251 252 SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,) 253 { 254 . = ALIGN(4); 255 /* _image_ram_start = .; */ 256 __data_region_start = .; 257 __data_start = .; 258 259 *(.data) 260 *(".data.*") 261 262#ifdef CONFIG_RISCV_GP 263 /* 264 * RISC-V architecture has 12-bit signed immediate offsets in the 265 * instructions. If we can put the most commonly accessed globals 266 * in a special 4K span of memory addressed by the GP register, then 267 * we can access those values in a single instruction, saving both 268 * codespace and runtime. 269 * 270 * Since these immediate offsets are signed, place gp 0x800 past the 271 * beginning of .sdata so that we can use both positive and negative 272 * offsets. 273 */ 274 . = ALIGN(8); 275 PROVIDE (__global_pointer$ = . + 0x800); 276#endif 277 278 *(.sdata .sdata.* .gnu.linkonce.s.*) 279 280/* Located in generated directory. This file is populated by the 281 * zephyr_linker_sources() Cmake function. 282 */ 283#include <snippets-rwdata.ld> 284 285#ifdef CONFIG_CODE_DATA_RELOCATION 286#include <linker_sram_data_relocate.ld> 287#endif 288 289 __data_end = .; 290 291 } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) 292 __data_size = __data_end - __data_start; 293 __data_load_start = LOADADDR(_DATA_SECTION_NAME); 294 295 __data_region_load_start = LOADADDR(_DATA_SECTION_NAME); 296 297#include <zephyr/linker/common-ram.ld> 298#include <zephyr/linker/kobject-data.ld> 299#include <zephyr/linker/cplusplus-ram.ld> 300 301/* Located in generated directory. This file is populated by the 302 * zephyr_linker_sources() Cmake function. 303 */ 304#include <snippets-data-sections.ld> 305 306 __data_region_end = .; 307 308 MPU_MIN_SIZE_ALIGN 309 310 _image_ram_end = .; 311 _end = .; /* end of image */ 312 313 __kernel_ram_end = .; 314 __kernel_ram_size = __kernel_ram_end - __kernel_ram_start; 315 316#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay) 317GROUP_START(ITCM) 318 319 SECTION_PROLOGUE(_ITCM_SECTION_NAME,,SUBALIGN(8)) 320 { 321 __itcm_start = .; 322 *(.itcm) 323 *(".itcm.*") 324 __itcm_end = .; 325 } GROUP_LINK_IN(ITCM AT> ROMABLE_REGION) 326 327 __itcm_size = __itcm_end - __itcm_start; 328 __itcm_load_start = LOADADDR(_ITCM_SECTION_NAME); 329 330GROUP_END(ITCM) 331#endif 332 333#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay) 334GROUP_START(DTCM) 335 336 SECTION_PROLOGUE(_DTCM_BSS_SECTION_NAME, (NOLOAD),SUBALIGN(8)) 337 { 338 __dtcm_start = .; 339 __dtcm_bss_start = .; 340 *(.dtcm_bss) 341 *(".dtcm_bss.*") 342 __dtcm_bss_end = .; 343 } GROUP_LINK_IN(DTCM) 344 345 SECTION_PROLOGUE(_DTCM_NOINIT_SECTION_NAME, (NOLOAD),SUBALIGN(8)) 346 { 347 __dtcm_noinit_start = .; 348 *(.dtcm_noinit) 349 *(".dtcm_noinit.*") 350 __dtcm_noinit_end = .; 351 } GROUP_LINK_IN(DTCM) 352 353 SECTION_PROLOGUE(_DTCM_DATA_SECTION_NAME,,SUBALIGN(8)) 354 { 355 __dtcm_data_start = .; 356 *(.dtcm_data) 357 *(".dtcm_data.*") 358 __dtcm_data_end = .; 359 } GROUP_LINK_IN(DTCM AT> ROMABLE_REGION) 360 361 __dtcm_end = .; 362 363 __dtcm_data_load_start = LOADADDR(_DTCM_DATA_SECTION_NAME); 364 365GROUP_END(DTCM) 366#endif 367 368/* Located in generated directory. This file is populated by the 369 * zephyr_linker_sources() Cmake function. 370 */ 371#include <snippets-sections.ld> 372 373 GROUP_END(RAMABLE_REGION) 374 375#include <zephyr/linker/debug-sections.ld> 376 377 /DISCARD/ : { *(.note.GNU-stack) } 378 379 SECTION_PROLOGUE(.riscv.attributes, 0,) 380 { 381 KEEP(*(.riscv.attributes)) 382 KEEP(*(.gnu.attributes)) 383 } 384 385 /* Sections generated from 'zephyr,memory-region' nodes */ 386 LINKER_DT_SECTIONS() 387 388/* Because ROMABLE_REGION != RAMABLE_REGION in XIP-system, it is valid 389 * to set __rom_region_end symbol at the end of linker script and 390 * doesn't mistakenly contain the RAMABLE_REGION in it. 391 */ 392#ifdef CONFIG_XIP 393/* Must be last in romable region */ 394SECTION_PROLOGUE(.last_section,,) 395{ 396#ifdef CONFIG_LINKER_LAST_SECTION_ID 397 /* Fill last section with a word to ensure location counter and actual rom 398 * region data usage match. */ 399 LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN) 400#endif 401} GROUP_LINK_IN(ROMABLE_REGION) 402 403/* To provide the image size as a const expression, 404 * calculate this value here. */ 405__rom_region_end = LOADADDR(.last_section) + SIZEOF(.last_section); 406__rom_region_size = __rom_region_end - __rom_region_start; 407#endif 408 409} 410