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