blob: ed83c138c63a3342105ee1d13c851cf27674722b [file] [log] [blame]
/* 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
}