This code has nothing to do with the ISA's registers, it's about the
format of ELF relocations. As such, __SIZEOF_LONG__, being a language /
ABI-level property, is a more appropriate constant to use. This also
makes it easier to support CHERI, where general-purpose registers are
extended to be capabilities, not just integers, and so the register size
is not the same as the machine word size. This also happens to make it
more correct for RV64ILP32, where the registers are 64-bit integers but
the ABI is 32-bit (both for long and for the ELF format), though
properly supporting that ABI is not part of the motivation here, just a
consequence of improving the code for CHERI.
Signed-off-by: Jessica Clarke <jrtc27@jrtc27.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250709232932.37622-2-jrtc27@jrtc27.com
Signed-off-by: Anup Patel <anup@brainfault.org>
Add __stack_chk_fail() and __stack_chk_guard variable which are used by
compiler built-in stack protector.
This patch just try to support stack-protector so the value of the stack
guard variable is simply fixed for now. It could be improved by
deriving from a random number generator, such as Zkr extension or any
platform-specific random number sources.
Introduce three configurations for the stack protector:
1. CONFIG_STACK_PROTECTOR to enable the stack protector feature by
providing "-fstack-protector" compiler flag
2. CONFIG_STACK_PROTECTOR_STRONG to provide "-fstack-protector-strong"
3. CONFIG_STACK_PROTECTOR_ALL to provide "-fstack-protector-all"
Instead of fixing the compiler flag of stack-protector feature as
"-fstack-protector", we derive it from the introduced Kconfig
configurations. The compiler flag "stack-protector-cflags-y" is defined
as Makefile "immediately expanded variables" with ":=". Thus, the
stronger configuration of the stack protector can overwrite the
preceding one.
Signed-off-by: Alvin Chang <alvinga@andestech.com>
Reviewed-by: Yu-Chien Peter Lin <peter.lin@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250703151957.2545958-3-alvinga@andestech.com
Signed-off-by: Anup Patel <anup@brainfault.org>
Due to some historical issues, the value of BOOT_STATUS_BOOT_HART_DONE
has changed and the comment message needs to be corrected.
Signed-off-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Add support for the Smdbltrp[1] ISA extension. First thing to do is
clearing MDT on entry after setting the first MTVEC (since MDT is
reset to 1). Additionally, during trap handling, clear MDT once all
critical CSRs have been saved and in return path, restore MSTATUS/H
before restoring MEPC to avoid taking another trap which would clobber
it.
Link: https://github.com/riscv/riscv-double-trap/releases/download/v0.56/riscv-double-trap.pdf [1]
Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
In a multi-core startup scenario, if both _try_lottery and
_wait_for_boot_hart use the data in the _boot_status address, when
a CPU enters OpenSBI later than boot hart set the _boot_status to
BOOT_STATUS_BOOT_HART_DONE, the CPU will modify _boot_status to 1
by amoswap.w and will never be awakened in _wait_for_boot_hart.
So let _try_lottery and _boot_status use data from two addresses.
Fixes: 8151105af5 ("firmware: fw_base.S: Remove _relocate_lottery")
Signed-off-by: dong.yang <dong.yang@sophgo.com>
Reviewed-by: Xing Xiaoguang <xiaoguang.xing@sophgo.com>
Reviewed-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
This is a more efficient way to get the index of the current hart than
calling a function to loop through the hartindex -> hartid lookup table.
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Reduce the code size by using single-byte loads instead of bit
manipulation. This method also does the right thing on (hypothetical)
big-endian systems.
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Bring back FW_TEXT_START as an optional parameter to allow users
explicitly specify compile time address for loading debug symbols.
When not specified, the FW_TEXT_START is assumed to be 0.
Fixes: d4d2582eef ("firmware: remove FW_TEXT_START")
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Tested-by: Clément Léger <cleger@rivosinc.com>
Now opensbi can run at any address via dynamic relocation. We can
remove FW_TEXT_START.
Signed-off-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Tested-by: Anup Patel <anup@brainfault.org>
Club the struct sbi_trap_regs and struct sbi_trap_info a new
struct sbi_trap_context (aka trap context) which must be saved
by low-level trap handler before calling sbi_trap_handler().
To track nested traps, the struct sbi_scratch points to the current
trap context and the trap context has pointer to pervious context
of previous trap.
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Tested-by: Samuel Holland <samuel.holland@sifive.com>
To track nested traps, the struct sbi_scratch needs a pointer the
current trap context so add trap_context pointer in struct sbi_context.
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Tested-by: Samuel Holland <samuel.holland@sifive.com>
Over the years, no uses of sbi_trap_exit() have been found so remove
it and also remove related code from fw_base.S and sbi_scratch.h.
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Tested-by: Samuel Holland <samuel.holland@sifive.com>
The same detection was done twice when setting mtvec and trap_exit.
Merging can reduce code size.
Signed-off-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
lwu exists under the current rv64 and should also exist under the rv128
in the future, so I modified the conditions of conditional compilation
so that it can adapt to the future situation
Signed-off-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
When calling '_reset_regs', it'll reset all registers except some
specific registers (ra, a0, a1, and a2).
Both boot HART and non-boot HARTs will execute the '_start_warm'
function. Therefore, when '_reset_regs' is called in '_start_warm', it
will reset all registers except some specific registers (ra, a0, a1 and
a2) for both boot HART and non-boot HARTs.
Signed-off-by: Zhang Runmin <fmrt19zrmin@163.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
It's wrong to put the fence after setting the boot status flag because
all relocation operations must be finished before setting the status
flag. So, this fence must be put before the setting status flag, and
there is no use in putting a fence between _start_warm and setting
status flag.
Also, nop can't delay other harts too much, so use div instead, just
like Linux cpu_relax. Current opensbi force enables “M” Standard
Extension, and mul instructions have been used in the fw_base.S.
After the above two fixes, the boot hart index param of the
fw_dynamic_info could be guaranteed properly for all platforms.
Signed-off-by: Guo Ren <guoren@linux.alibaba.com>
Signed-off-by: Guo Ren <guoren@kernel.org>
Reviewed-by: Anup Patel <anup@brainfault.org>
Since everything is statically linked, we won't actually have
R_RISCV_{32,64} relocations. No need to handle these.
Fixes: 0f20e8adcf ("firmware: Support position independent execution")
Signed-off-by: Vivian Wang <dramforever@live.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Attempting to build OpenSBI with clang 16 and the following command:
$ make LLVM=1 PLATFORM=generic
Results in the following error:
AS platform/generic/firmware/fw_dynamic.o
/tmp/fw_dynamic-d000a6.s:429:9: error: symbol '_fw_start' can not be undefined in a subtraction expression
.dword _fw_rw_start - _fw_start
Work around this issue by eliminating the __fw_rw_offset variable and
performing the offset calculation at run-time instead. This takes
advantage of the fact that the a4 register contains the value of
_fw_start.
Signed-off-by: Mitchell Horne <mhorne@FreeBSD.org>
Reviewed-by: Anup Patel <anup@brainfault.org>
After the loop to find the hartid is launched, assigning -1 to
index will fail in the subsequent compare instruction bge. Fix
This.
Signed-off-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
We extend struct sbi_platform and struct sbi_scratch to allow platforms
specify the heap size to the OpenSBI firmwares. The OpenSBI firmwares
will use this information to determine the location of heap and provide
heap base address in per-HART scratch space.
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
The codes currently skip the very first relocation entry, but later
reference the elements in the relocation entry using minus offsets.
Change to use positive offsets so that there is no need to skip the
first relocation entry.
Signed-off-by: Bin Meng <bmeng@tinylab.org>
Reviewed-by: Anup Patel <anup@brainfault.org>
Reviewed-by: Xiang W <wxjstz@126.com>
If mip.SEIP bit is not cleared then on HiFive Unmatched board it causes
spurious external interrupts. This breaks the boot up of HiFive Unmatched
board. Hence it is required to bring the mip CSR to a known state during
hart init and avoid spurious interrupts.
Fixes: d9e7368 ("firmware: Not to clear all the MIP")
Signed-off-by: Mayuresh Chitale <mchitale@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
In generic behavior of QEMU, if the pending bits of PLIC are still set and
we clear the SEIP, the QEMU may not set the SEIP back immediately and the
interrupt may not be handled anymore until the new interrupts arrived and
QEMU set the SEIP back which is a generic behavior in QEMU.
Signed-off-by: Nick Hu <nick.hu@sifive.com>
Signed-off-by: Jim Shu <jim.shu@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
It seems BFD just does totally nonsensical things for SHN_ABS symbols
when producing position-independent outputs (both -pie and -shared)
for various historical reasons, and so SHN_ABS symbols are still
subject to relocation as far as BFD is concerned (except AArch64,
which fixes it in limited cases that don’t apply here...).
The above affects the _fw_rw_offset provided through fw_base.ldS
linker script which results in OpenSBI firmware failing to boot
when loaded at an address different from FW_TEXT_START.
Fixes: c10e3fe5f9 ("firmware: Add RW section offset in scratch")
Signed-off-by: Jessica Clarke <jrtc27@jrtc27.com>
Reported-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Tested-by: Anup Patel <apatel@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Add the RW section offset, provided by _fw_rw_offset symbol,
to the scratch structure. This will be used to program
separate pmp entry for RW section.
Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
The t3 register stores the address of _load_end. If relocation is not
required, it is unnecessary to calculate the address of _load_end.
This can reduce the operation time of two instructions.
Signed-off-by: Dongdong Zhang <zhangdongdong@eswincomputing.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Reviewed-by: Anup Patel <anup@brainfault.org>
lwu exists under the current rv64 and should also exist under the rv128
in the future, so I modified the conditions of conditional compilation
so that it can adapt to the future situation
Signed-off-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Some of the external firmwares using OpenSBI as library are facing
issues with the weak memcpy() and memset() aliases in libsbi.a so
we move these to fw_base.S. This way mapping of implicit memcpy()
or memset() calls to sbi_memcpy() or sbi_memset() will only be done
for OpenSBI firmwares.
(Refer, https://github.com/riscv-software-src/opensbi/issues/234)
In addition, we also add memmove() and memcmp() mappings in fw_base.S
because as-per the GCC documentation the freestanding environment must
provide memcpy(), memmove(), memset(), and memcmp().
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
The previous code uses _start as the load address, this default .entry is
the first segment, using _fw_start does not need to make this assumption.
Signed-off-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup.patel@wdc.com>
If the device tree is at an address that is not __SIZEOF_POINTER__
aligned, the fdt relocation code tries to align both source and
destination address to __SIZEOF_POINTER__ before the memory copy.
But such alignment can lead to unexpected results if either source
or destination address is not aligned.
In fact libfdt requires that the device tree must be at an 8-byte
aligned address. Hence remove the unhelpful alignment codes.
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Anup Patel <anup.patel@wdc.com>
The -N linker option is supposed to make .text writable, but GNU ld and
LLD differ in interpreting what that means. GNU ld will happily let you
have relocations in it, but LLD will see that the input section is
read-only (even though the output section is writable) and give an
error. It's unclear if either of them intend to have that behaviour in
this edge case, but regardless there's no reason not to just put the
data in a writable .data section.
Signed-off-by: Jessica Clarke <jrtc27@jrtc27.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Tested-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Anup Patel <anup.patel@wdc.com>
These are mutually exclusive. GNU as and LLVM both let later binding
directives override earlier ones so this works as intended, but LLVM 12
turned this into a warning as there's no good reason to do such a thing
and could be a potential bug. Thus, remove the redundant and incorrect
.globl directive for fw_platform_init.
Signed-off-by: Jessica Clarke <jrtc27@jrtc27.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Tested-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Anup Patel <anup.patel@wdc.com>
Before entering _scratch_init(), register t3 already holds a copy
of the firmware end address, hence there is no need to calculate
it again. This reduces 3 instructions in each _scratch_init() loop.
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Xiang W <wxjstz@126.com>
Reviewed-by: Atish Patra <atish.patra@wdc.com>
The "add sp, a0, zero" instruction in the trap restore path is redundant
and can be avoided if TRAP_RESTORE_xyz() assembly macros use a0 as the
base register instead of sp.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Reviewed-by: Xiang W <wxjstz@126.com>
There are two copies of the same abnormal exit code, this patch deletes one
Signed-off-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup.patel@wdc.com>
Enable OpenSBI to support position independent execution. Because the
position independent code will cause an additional GOT reference when
accessing the global variables, it will reduce performance a bit. Therefore,
the position independent execution is disabled by default. Users can
through specifying "FW_PIC=y" on the make command to enable this feature.
In theory, after enabling position-independent execution, the OpenSBI
can run at arbitrary address with appropriate alignment. Therefore, the
original relocation mechanism will be skipped. In other words, OpenSBI will
directly run at the load address without any code movement.
Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
Reviewed-by: Anup Patel <anup.patel@wdc.com>
When OpenSBI is compiled as fPIE mode, the assembler will translate "la"
to GOT reference pattern. It will cause to cost an additional load
instruction when obtaining the symbol address. However, if the symbol
locates within the positive or negative 2GB region, we can use "lla"
instead of "la" to avoid unneeded GOT references. This patch assumes that
the OpenSBI image excluding the payload does not exceed 2GB. Based on
this assumption, all "la" instructions are replaced by "lla" to avoid
performance degradation when compiling as fPIE mode.
Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
Reviewed-by: Anup Patel <anup.patel@wdc.com>
We introduce sbi_trap_exit() API which can help non-firmware
(i.e. generic or platform) code to force exit trap/interrupt
handling and resume execution at context pointed by parameter
"const struct sbi_trap_regs *regs".
This new sbi_trap_exit() API will help Keystone Enclave project
to resume execution of enclave from custom SBI call handler.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Reviewed-by: Atish Patra <atish.patra@wdc.com>
On RV32 systems, we have two CSRs for M-mode status (MSTATUS and
MSTATUSH) when H-extension is implemented. This means we have to
save/restore MSTATUSH for RV32 systems only when H-extension is
implemented. The current _trap_handler() has extra instructions
(roughly 10) for conditional save/restore of MSTATUSH CSR.
These extra instructions in RV32 _trap_handler() can be avoided
if we create separate low-level trap handler for RV32 systems
having H-extension. This patch optimizes low-level trap handler
for RV32 systems accordingly.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
The FW_PAYLOAD_FDT_PATH compile-time option is replaced by
FW_FDT_PATH compile-time option which is more flexible and
common across all OpenSBI firmwares.
This patch removes FW_PAYLOAD_FDT_PATH and updates related
documentation to use FW_FDT_PATH.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Reviewed-by: Atish Patra <atish.patra@wdc.com>
Currently, only FW_PAYLOAD has mechanism to embed external
FDT using FW_PAYLOAD_FDT_PATH compile-time option.
This patch adds a common FW_FDT_PATH compile-time option to
embed external FDT for all OpenSBI firmwares (i.e FW_JUMP,
FW_PAYLOAD, and FW_DYNAMIC).
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Reviewed-by: Atish Patra <atish.patra@wdc.com>
Currently, the low-level trap handler (i.e. _trap_handler()) uses
branch instructions to conditionally setup exception stack based
on which mode trap occured.
This patch implements exception stack setup using xor instructions
which is faster with same number of instructions due to lack of
branch instructions.
The new exception stack setup approach can be best described by the
following pseudocode:
Came_From_M_Mode = ((MSTATUS.MPP < PRV_M) ? 1 : 0) - 1;
Exception_Stack = TP ^ (Came_From_M_Mode & (SP ^ TP))
Came_From_M_Mode = 0 ==> Exception_Stack = TP
Came_From_M_Mode = -1 ==> Exception_Stack = SP
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Reviewed-by: Atish Patra <atish.patra@wdc.com>