| /* Copyright lowRISC contributors. */ |
| /* Licensed under the Apache License, Version 2.0, see LICENSE for details. */ |
| /* SPDX-License-Identifier: Apache-2.0 */ |
| |
| /** |
| * Linker script for OpenTitan OTTF-launched test binaries. |
| * |
| * Portions of this file are Ibex-specific. |
| * |
| * This linker script generates a binary to run rom. |
| */ |
| |
| INCLUDE hw/top_matcha/sw/autogen/top_matcha_memory.ld |
| MEMORY { |
| virtual(rx): ORIGIN = 0x10000, LENGTH = 0x400000 |
| super_virtual(rx): ORIGIN = 0xff800000, LENGTH = 0x400000 |
| } |
| |
| /** |
| * Reserving space at the top of the RAM for DV verification. |
| */ |
| _dv_sim_window_size = 0x10; |
| _dv_sim_window_end = ORIGIN(ram_smc) + LENGTH(ram_smc); |
| _dv_sim_window_start = _dv_sim_window_end - _dv_sim_window_size; |
| |
| /** |
| * Reserving space at the top of the RAM for the stack. |
| */ |
| _stack_size = 0x2000; |
| _stack_end = _dv_sim_window_start; |
| _stack_start = _stack_end - _stack_size; |
| |
| /** |
| * DV Log offset. |
| * TODO: this will need to be different depending on the boot stage the OTTF is |
| * launched at. See lowrisc/opentitan:#10712. |
| */ |
| _dv_log_offset = 0x10000; |
| |
| OUTPUT_ARCH(riscv) |
| |
| /** |
| * Indicate that there are no dynamic libraries, whatsoever. |
| */ |
| __DYNAMIC = 0; |
| |
| /** |
| * Marking the entry point correctly for the ELF file. The signer tool will |
| * transfer this value to the `entry_point` field of the manifest, which will |
| * then be used by `rom_boot` or `rom_ext_boot` to handover execution to |
| * the OTTF. |
| */ |
| ENTRY(_ottf_start); |
| |
| /** |
| * NOTE: We have to align each section to word boundaries as our current |
| * s19->slm conversion scripts are not able to handle non-word aligned sections. |
| */ |
| SECTIONS { |
| /** |
| * Ibex interrupt vector. See 'ottf_start.S' for more information. |
| * |
| * This has to be set up at a 256-byte offset, so that we can use it with |
| * Ibex. |
| */ |
| .vectors : ALIGN (256){ |
| _text_start = .; |
| *(.vectors) |
| } > ram_smc |
| |
| /** |
| * C runtime (CRT) section, containing program initialization code. |
| */ |
| .crt : ALIGN(4) { |
| KEEP(*(.crt)) |
| } > ram_smc |
| |
| /** |
| * For LLVM profiling. This contains a pointer to the runtime initialization |
| * function that is generated by the compiler. See |
| * 'InstrProfiling::emitInitialization()' in 'InstrProfiling.cpp' and |
| * 'getInstrProfInitFuncName()' in 'InstrProf.h'. |
| */ |
| .init_array : ALIGN(4) { |
| _init_array_start = .; |
| KEEP(*(.init_array)) |
| KEEP(*(.init_array.*)) |
| . = ALIGN(4); |
| _init_array_end = .; |
| } > ram_smc |
| |
| /** |
| * Standard text section, containing program code. |
| */ |
| .text : ALIGN(4) { |
| *(.text) |
| *(.text.*) |
| |
| /* Ensure section end is word-aligned. */ |
| . = ALIGN(4); |
| } > ram_smc |
| |
| /** |
| * Shutdown text section, containing shutdown function(s). |
| * |
| * This must be the last executable section in the OTTF flash image. |
| */ |
| .shutdown : ALIGN(4) { |
| *(.shutdown) |
| *(.shutdown.*) |
| |
| /* Ensure section end is word-aligned. */ |
| . = ALIGN(4); |
| _text_end = .; |
| } > ram_smc |
| |
| /** |
| * Read-only data section, containing all large compile-time constants, like |
| * strings. |
| */ |
| .rodata : ALIGN(4) { |
| /** |
| * Small read-only data comes before regular read-only data for the same |
| * reasons as in the data section. |
| */ |
| *(.srodata) |
| *(.srodata.*) |
| *(.rodata) |
| *(.rodata.*) |
| |
| /* Read-only sections for LLVM profiling. */ |
| KEEP(*(__llvm_covfun)) |
| KEEP(*(__llvm_covmap)) |
| KEEP(*(__llvm_prf_names)) |
| } > ram_smc |
| |
| /** |
| * Standard mutable data section, at the bottom of RAM. This will be |
| * initialized from the .idata section at runtime by the CRT. |
| */ |
| .data : ALIGN(4) { |
| _data_start = .; |
| _data_init_start = LOADADDR(.data); |
| |
| /** |
| * This will get loaded into `gp`, and the linker will use that register for |
| * accessing data within [-2048,2047] of `__global_pointer$`. |
| * |
| * This is much cheaper (for small data) than materializing the |
| * address and loading from that (which will take one extra instruction). |
| */ |
| __global_pointer$ = . + 2048; |
| |
| /* SRAM programs embedded in functional tests must come first. */ |
| *(.data.sram_program) |
| |
| /** |
| * Small data should come before larger data. This helps to ensure small |
| * globals are within 2048 bytes of the value of `gp`, making their accesses |
| * hopefully only take one instruction. |
| */ |
| *(.sdata) |
| *(.sdata.*) |
| |
| /** |
| * Other data will likely need multiple instructions to load, so we're less |
| * concerned about address materialisation taking more than one instruction. |
| */ |
| *(.data) |
| *(.data.*) |
| |
| /* Sections for LLVM profiling. */ |
| KEEP(*(__llvm_prf_cnts)) |
| KEEP(*(__llvm_prf_data)) |
| |
| /* Ensure section end is word-aligned. */ |
| . = ALIGN(4); |
| _data_end = .; |
| _data_init_end = LOADADDR(.data) + SIZEOF(.data); |
| |
| /** |
| * This puts it in ram_smc at runtime (for the VMA), but puts the section |
| * into flash for load time (for the LMA). This is why `_data_init_*` uses |
| * `LOADADDR`. |
| * |
| * Using `AT>` means we don't have to keep track of the next free part of |
| * flash, as we do in our other linker scripts. |
| */ |
| } > ram_smc |
| |
| /** |
| * Standard BSS section. This will be zeroed at runtime by the CRT. |
| */ |
| .bss : ALIGN(4) { |
| _bss_start = .; |
| |
| /** |
| * Small BSS comes before regular BSS for the same reasons as in the data |
| * section. |
| */ |
| *(.sbss) |
| *(.sbss.*) |
| *(.bss) |
| *(.bss.*) |
| |
| /* Ensure section end is word-aligned. */ |
| . = ALIGN(4); |
| _bss_end = .; |
| } > ram_smc |
| |
| /** |
| * FreeRTOS heap (for OTTF). |
| * |
| * This is a separate NOLOAD section so that it does not end up in the `.bss` |
| * section which gets zeroed during the second boot stage initialization, |
| * causing wasted simulation cycles. |
| */ |
| .freertos.heap (NOLOAD): ALIGN(4) { |
| _freertos_heap_start = .; |
| *(.freertos.heap) |
| } > ram_smc |
| |
| . = ALIGN(4096); |
| __VIRTUAL_ROM = .; |
| .virtual : AT(__VIRTUAL_ROM) |
| { |
| __virtual_start = .; |
| *(.virtual*) |
| . = ALIGN(4096); |
| __virtual_end = .; |
| } > virtual |
| |
| __SUPER_VIRTUAL_ROM = __VIRTUAL_ROM + (__virtual_end - __virtual_start); |
| .super_virtual : AT(__SUPER_VIRTUAL_ROM) |
| { |
| __super_virtual_start = .; |
| *(.super_virtual*) |
| __super_virtual_end = .; |
| } > super_virtual |
| |
| .stack ORIGIN(ram_smc) + LENGTH(ram_smc) - _stack_size - _dv_sim_window_size (NOLOAD) : ALIGN(4) { |
| __stack_start__ = .; |
| . += _stack_size; |
| . = ALIGN(4); |
| __stack_end__ = .; |
| } > ram_smc |
| |
| |
| INCLUDE external/lowrisc_opentitan/sw/device/info_sections.ld |
| } |