320 Commits

Author SHA1 Message Date
e64a712de9 adds riscv_vp platform 2025-08-14 16:28:34 +02:00
Max Hsu
84044ee83c lib: utils: fdt: fix "ranges" translation
According to the Device Tree Spec, Chapter 2.3.8 "ranges" [1]:
The parent address size will be determined from the #address-cells
property of the node that defines the parent’s address space.

In fdt_translate_address(), which considered the parent address size
is the child address size, this commit fix the two address sizes
and parsing the address independently.

Signed-off-by: Max Hsu <max.hsu@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250711-dev-maxh-master_fdt_helper-v2-1-9579e1f02ee1@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-07-23 10:32:14 +05:30
Jessica Clarke
cc546e1a06 include: sbi: Remove unused (LOG_)REGBYTES
These are no longer used, so remove them.

Signed-off-by: Jessica Clarke <jrtc27@jrtc27.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250709232932.37622-3-jrtc27@jrtc27.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-07-22 15:54:27 +05:30
Jessica Clarke
079bf6f0f9 firmware: Replace sole uses of REGBYTES with __SIZEOF_LONG__
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>
2025-07-22 15:54:27 +05:30
Jessica Clarke
ffd3ed976d include: sbi: Use array for struct sbi_trap_regs and GET/SET macros
Rather than hand-rolling scaled pointer arithmetic with casts and
shifts, let the compiler do so by indexing an array of GPRs, taking
advantage of the language's type system to scale based on whatever type
the register happens to be. This makes it easier to support CHERI where
the registers are capabilities, not plain integers, and so this pointer
arithmetic would need to change (and currently REGBYTES is both the size
of a register and the size of an integer word upstream).

Signed-off-by: Jessica Clarke <jrtc27@jrtc27.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250709232932.37622-1-jrtc27@jrtc27.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-07-22 15:54:27 +05:30
Manuel Hernández Méndez
0b7c2e0d60 platform: openpiton: fix uninitialized plic_data struct
The plic_data struct was uninitialized. This led to misfunction behavior
since it was subsequently assigned to the global plic struct, and some
struct fields, such as flags and irqchip, contained random values.
The fix proposes to initialize the plic_data to the global plic struct,
so, after parsing the fdt, the fields of the struct will be set to the
default values set in global plic struct definition, or the parsed values
in the fdt, or zero.

Fixes: 4c37451 ("platform: openpiton: Read the device configurations from device tree")
Signed-off-by: Manuel Hernández Méndez <maherme.dev@gmail.com>
Reviewed-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250708180914.1131-1-maherme.dev@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-07-22 15:26:44 +05:30
Jessica Clarke
e10a45752f firmware: Rename __rel_dyn_start/end to __rela_dyn_start/end
We are using and expecting the RELA format, not the REL format, and this
is the conventional linker-generated name for the start/end symbols, so
use it rather than confusing things by making it look like we're
accessing .rel.dyn, which would be in the REL format with no explicit
addend.

Signed-off-by: Jessica Clarke <jrtc27@jrtc27.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Tested-by: Samuel Holland <samuel.holland@sifive.com>
Link: https://lore.kernel.org/r/20250710002937.44307-1-jrtc27@jrtc27.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-07-21 16:39:49 +05:30
Jessica Clarke
4825a3f87f include: sbi: Don't use #pragma when preprocessing device tree sources
Since this persists in the preprocessed output (so that it can affect
the subsequent compilation), it ends up in the input to dtc and is a
syntax error, breaking the k210 build. Ideally we wouldn't add the
-include flag to DTSCPPFLAGS in the first place as this header is wholly
pointless there, but that's a more invasive build system change compared
to just making this header safe to include there.

Fixes: 86c01a73ff ("lib: sbi: Avoid GOT indirection for global symbol references")
Signed-off-by: Jessica Clarke <jrtc27@jrtc27.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Tested-by: Xiang W <wxjstz@126.com>
Reviewed-by: Xiang W <wxjstz@126.com>
Link: https://lore.kernel.org/r/20250709232840.37551-1-jrtc27@jrtc27.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-07-21 16:37:22 +05:30
Xiang W
3876f8cd1e firmware: payload: test: Add SBI shutdown call after test message
Previously, 'make run' would hang in WFI after printing the test message.
This commit adds an SBI ecall to ensure QEMU exits cleanly after the test
payload runs.

Reviewed-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Xiang W <wxjstz@126.com>
Link: https://lore.kernel.org/r/20250721010807.460788-1-wxjstz@126.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-07-21 16:34:03 +05:30
Atish Patra
5b305e30a5 lib: sbi: Only enable TM bit in scounteren
The S-mode should disable Cycle and instruction counter for user space
to avoid side channel attacks. The Linux kernel already does this so that
any random user space code shouldn't be able to monitor cycle/instruction
without higher privilege mode involvement.

Remove the CY/IR bits in scountern in OpenSBI.

Reviewed-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Atish Patra <atishp@rivosinc.com>
Link: https://lore.kernel.org/r/20250513-fix_scounteren-v1-1-01018e0c0b0a@rivosinc.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-07-21 16:33:03 +05:30
Ben Dooks
663b05a5f7 include: sbi: fix swap errors with newer gcc -Werror=sequence-point
The BSWAPxx() macros are now throwing the following warnings with
newer gcc versions. This is due to throwing an argument in that may
be evaluated more than one (I think) and therefore things like the
example below should be avoided.

Fix by making a set of BSWAPxx() wrappers which specifically only
evaluate 'x' once.

In file included lib/sbi/sbi_mpxy.c:21:
lib/sbi/sbi_mpxy.c: In function ‘sbi_mpxy_write_attrs’:
ib/sbi/sbi_mpxy.c:632:63: error: operation on ‘mem_idx’ may be undefined [-Werror=sequence-point]
  632 |                         attr_val = le32_to_cpu(mem_ptr[mem_idx++]);
      |                                                        ~~~~~~~^~

Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
Reviewed-by: Rahul Pathak <rahul@summations.net>
Reviewed-by: Xiang W <wxjstz@126.com>
Link: https://lore.kernel.org/r/20250704122938.897832-1-ben.dooks@codethink.co.uk
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-07-20 21:15:10 +05:30
Alvin Chang
edfbc1285d firmware: Initial compiler built-in stack protector support
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>
2025-07-20 20:54:34 +05:30
Alvin Chang
ea5abd1f5e lib: sbi: Remove redundant call to sbi_hart_expected_trap_addr()
The variable "sbi_hart_expected_trap" has already been extern variable.
Therefore, the program can directly refer to it instead of calling
sbi_hart_expected_trap_addr().

Signed-off-by: Alvin Chang <alvinga@andestech.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250703151957.2545958-2-alvinga@andestech.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-07-20 20:54:34 +05:30
Yong-Xuan Wang
61083eb504 lib: sbi_list: add a helper for safe list iteration
Some use cases require iterating safe against removal of list entry.

Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250618025416.5331-1-yongxuan.wang@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-07-20 20:45:59 +05:30
Yi Pei
b8f370aa37 lib: utils/serial: Clear LSR status and check RBR status
On some platforms, read RBR when it is empty may result in an error.

Signed-off-by: Yi Pei <neopimail@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/CAFPVDjQZ1gpf8-u--RBbAL1Y0FfDN2vZ3g=wBw+Bp-8ppuz3HA@mail.gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-07-20 20:37:18 +05:30
Anup Patel
a32a910691 include: Bump-up version to 1.7
Update the OpenSBI version to 1.7 as part of release preparation.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-06-30 08:37:30 +05:30
Rahul Pathak
c2671bb69f lib: rpmi: Make RPMI drivers as non-experimental
As RPMI v1.0 specification is frozen, disable the
experimental tag for such RPMI drivers.

Signed-off-by: Rahul Pathak <rpathak@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250618053854.2577299-2-rpathak@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-06-24 08:42:27 +05:30
Rahul Pathak
a5fdef45db lib: utils: Add Implementation ID and Version as RPMI MPXY attributes
The latest frozen RPMI spec has added Implementation ID
and Implementation Version as message protocol specific
mpxy attributes. Add support for these.

Signed-off-by: Rahul Pathak <rpathak@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250618053854.2577299-1-rpathak@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-06-24 08:42:27 +05:30
Chao-ying Fu
13abda5169 lib: sbi_platform: Add platform specific pmp_set() and pmp_disable()
Allow platforms to implement platform specific PMP setup and
PMP disable functions which are called before actual PMP CSRs
are configured.

Also, implement pmp_set() and pmp_disable() for MIPS P8700.

Signed-off-by: Chao-ying Fu <cfu@mips.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Link: https://lore.kernel.org/r/20250614172756.153902-1-apatel@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-06-17 09:34:01 +05:30
Jesse Taube
324021423d lib: sbi: dbtr: Fix update_triggers to match SBI
OpenSBI implements sbi_dbtr_update_trig as
`sbi_dbtr_update_trig(unsigned long trig_idx_base,
                      unsigned long trig_idx_mask)`
yet SBI v3.0-rc7 Chapter 19. Debug Triggers Extension [0] declares it as
`sbi_debug_update_triggers(unsigned long trig_count)`

Change update_triggers to match SBI.

[0] https://github.com/riscv-non-isa/riscv-sbi-doc/tree/v3.0-rc7/src/ext-debug-triggers.adoc

Fixes: 97f234f15c ("lib: sbi: Introduce the SBI debug triggers extension support")
Signed-off-by: Jesse Taube <jesse@rivosinc.com>
Reviewed-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
Tested-by: Charlie Jenkins <charlie@rivosinc.com>
Reviewed-by: Charlie Jenkins <charlie@rivosinc.com>
Link: https://lore.kernel.org/r/20250528154604.571815-1-jesse@rivosinc.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-06-16 17:01:52 +05:30
Xiang W
03f44e6b82 lib: sbi: Optimize saddr mapping in sbi_dbtr.c
The original implementation mapped saddr individually for each entry.
The updated code now maps saddr for all entries in a single operation.
This change reduces the number of PMP (Physical Memory Protection)
operations, improving efficiency and performance.

Tested-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
Reviewed-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
Signed-off-by: Xiang W <wxjstz@126.com>
Link: https://lore.kernel.org/r/20250514052422.575551-1-wxjstz@126.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-06-16 16:53:50 +05:30
Jesse Taube
033e0e2353 lib: sbi: dbtr: Fix shared memory layout
The existing sbi_dbtr_shmem_entry has a size of 5 * XLEN with the final
entry being idx. This is in contrast to the SBI v3.0-rc7 Chapter 19.
Debug Triggers Extension [0] where idx and trig_state share the same
offset (0) in shared memory, with a total size of 4 * XLEN for all the
SBI calls.

Replace struct with union to match memory layout described in SBI.

[0] https://github.com/riscv-non-isa/riscv-sbi-doc/tree/v3.0-rc7/src/ext-debug-triggers.adoc

Fixes: 97f234f15c ("lib: sbi: Introduce the SBI debug triggers extension support")
Signed-off-by: Jesse Taube <jesse@rivosinc.com>
Reviewed-by: Charlie Jenkins <charlie@rivosinc.com>
Tested-by: Charlie Jenkins <charlie@rivosinc.com>
Reviewed-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
Tested-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
Link: https://lore.kernel.org/r/20250604135225.842241-1-jesse@rivosinc.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-06-16 10:14:20 +05:30
Anup Patel
9f64f06193 lib: utils: Fix fdt_parse_aclint_node() for non-contiguous hartid
Currently, the fdt_parse_aclint_node() does not handle non-contiguous
hartid correctly and returns incorrect first_hartid and hart_count.
This is because the for-loop in fdt_parse_aclint_node() skips a hartid
for which hartindex is not available (aka corresponding CPU DT node
is disabled).

For example, on a platform with 4 HARTs (hartid 0, 1, 2, and 3) where
CPU DT nodes with hartid 0 and 2 are disabled, the fdt_parse_aclint_node()
returns first_hartid = 1 and hart_count = 3 which is incorrect.

To address the above issue, drop the sbi_hartid_to_hartindex() check
from the for-loop of fdt_parse_aclint_node().

Fixes: 5e90e54a1a ("lib: utils:Check that hartid is valid")
Reported-by: Maria Mbaye <MameMaria.Mbaye@microchip.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Link: https://lore.kernel.org/r/20250606055810.237441-1-apatel@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-06-16 09:41:03 +05:30
Anup Patel
7dd09bfeca lib: sbi: Revert entry_count before doing hsm stop in hsm wait loop
Using hsm stop in hsm wait loop causes secondary harts to be stuck
forever in OpenSBI on RISC-V platforms where HSM hart hotplug is
available and all harts come-up at the same time during system
power-on.

For example, lets say we have two harts A and B on a RISC-V platform
with HSM hart hotplug which come-up at the same time during system
power-on. The hart A enters OpenSBI before hart B hence it becomes
the primary (or cold-boot) hart whereas hart B becomes the secondary
(or warm-boot) hart. The hart A follows the OpenSBI cold-boot path
and registers hsm device before hart B enters OpenSBI. The hart B
eventually enters OpenSBI and follows the OpenSBI warm-boot path
so it will increment it's own entry_count before entering hsm wait
loop where it sees hsm device and stops itself. Later as part of
the Linux boot-up sequence, hart A issues SBI HSM start call to
bring-up hart B but OpenSBI sees entry_count != init_count for
hart B in sbi_hsm_hart_start() hence hsm_device_hart_start() is
not called for hart B resulting in hart B stuck forever in OpenSBI.

To fix the above issue, revert entry_count before doing hsm stop
in hsm wait loop.

Fixes: d844deadec ("lib: sbi: Use hsm stop for hsm wait")
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Nick Hu <nick.hu@sifive.com>
Link: https://lore.kernel.org/r/20250527124821.2113467-1-apatel@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-06-16 09:40:28 +05:30
Inochi Amaoto
6f8bcae4cb lib: utils/irqchip: always parse msi information for each aplic device
OpenSBI only parses MSI information of the first next level subdomain
for now, which makes the root domain misconfigured in some case:
1. the msi is not enabled on the first subdomain of the root domain,
   but other subdomains enable MSI.
2. the root domain is set as direct mode, but its subdomains enable MSI.

So it is needed to parse all child of the root domain, Otherwise, the
some non-root domains are broken. As the specification says, it is
safe to parse the MSI information of all its subdomain and write the
msiaddrcfg register of the non root domain as they are read only.

Parse the aplic MSI information recursively for all aplic device.

Reviewed-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
Link: https://lore.kernel.org/r/20250523085348.1690368-1-inochiama@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-06-16 09:17:28 +05:30
Samuel Holland
771c656181 lib: sbi: fwft: Use only the provided PMLEN value
As of riscv-sbi-doc commit c7d3d1f7dcaa ("ext-fwft: use the provided
value in fwft_set(POINTER_MASKING_PMLEN)"), the SBI implementation must
use only the provided PMLEN value or else fail. It may not fall back to
a larger PMLEN value.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Radim Krčmář <rkrcmar@ventanamicro.com>
Link: https://lore.kernel.org/r/20250522013503.2556053-1-samuel.holland@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-06-15 18:56:33 +05:30
Clément Léger
f30a54f3b3 lib: sbi: pmu: Remove MIP clearing from pmu_sse_enable()
Clearing MIP at that point means that we can probably lose a pending
interrupt. This should not happen, remove MIP clearing from there.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Link: https://lore.kernel.org/r/20250519083950.739044-3-cleger@rivosinc.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-06-15 18:44:51 +05:30
Clément Léger
b31a0a2427 lib: sbi: pmu: Add SSE register/unregister() callbacks
As soon as the SSE event is registered, there is no reason not to
delegate the interrupt. Split the PMU SSE enable/disable()
callbacks by moving MIDELEG setting to register/unregister().

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Link: https://lore.kernel.org/r/20250519083950.739044-2-cleger@rivosinc.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-06-15 18:44:51 +05:30
Khem Raj
6d23a9c570 Makefile: Add flag for reprodubility compiler flags
Provides mechanism to remove absolute paths from binaries using
-ffile-prefix-map

It will help distros (e.g. yocto based ones ) which want to ship
the .elf files but need to scrub absolute paths in objects

Reviewed-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Khem Raj <raj.khem@gmail.com>
Link: https://lore.kernel.org/r/20250515025931.3383142-1-raj.khem@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-06-15 18:28:55 +05:30
Chao-ying Fu
66ab965e54 platform: generic: mips: add P8700
Extend generic platform to support MIPS P8700.

Signed-off-by: Chao-ying Fu <cfu@mips.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250522212141.3198-2-cfu@mips.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-06-14 21:44:11 +05:30
Ziang Wang
3f8159aa06 lib: utils: hsm: Do not fail on EALREADY in rpmi-hsm fixup.
In case harts are divided into groups that use different
rpmi-hsm channels in different mailboxes, the suspend
state fixup function will return EALREADY on secondary
entry, simply skip on this error.

Reviewed-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Ziang Wang <wangziang.ok@bytedance.com>
Link: https://lore.kernel.org/r/20250507074620.3162747-1-wangziang.ok@bytedance.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-06-14 10:31:32 +05:30
Charlie Jenkins
27347f0902 Makefile: Make $(LLVM) more flexible
Introduce a way for developers to easily switch between LLVM versions
with LLVM=/path/to/llvm/ and LLVM=-version. This is a useful
addition to the existing LLVM=1 variable which will select the first
clang and llvm binutils available on the path.

Reviewed-by: Anup Patel <anup@brainfault.org>
Tested-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
Link: https://lore.kernel.org/r/20250430-improve_llvm_building-v1-1-caae96cc6be6@rivosinc.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-06-14 10:11:11 +05:30
James Raphael Tiovalen
69a0f0245f lib: sbi: pmu: Return SBI_EINVAL if cidx_mask is 0
Currently, when configuring a matching programmable HPM counter with
Sscofpmf being present, cidx_base > 2, and cidx_mask == 0 to monitor
either the CPU_CYCLES or INSTRUCTIONS hardware event,
sbi_pmu_ctr_cfg_match will succeed but it will configure the
corresponding fixed counter instead of the counter specified by the
cidx_base parameter.

During counter configuration, the following issues may arise:
- If the SKIP_MATCH flag is set, an out-of-bounds memory read of the
phs->active_events array would occur, which could lead to undefined
behavior.

- If the CLEAR_VALUE flag is set, the corresponding fixed counter will
be reset, which could be considered unexpected behavior.

- If the AUTO_START flag is set, pmu_ctr_start_hw will silently start
the fixed counter, even though it has already started. From the
supervisor's perspective, nothing has changed, which could be confusing.
The supervisor will not see the SBI_ERR_ALREADY_STARTED error code since
sbi_pmu_ctr_cfg_match does not return the error code of
pmu_ctr_start_hw.

The only way to detect these issues is to check the ctr_idx return value
of sbi_pmu_ctr_cfg_match and compare it with cidx_base.

Fix these issues by returning the SBI_ERR_INVALID_PARAM error code if
the cidx_mask parameter value being passed in is 0 since an invalid
parameter should not lead to a successful sbi_pmu_ctr_cfg_match but with
unexpected side effects.

Following a similar rationale, add the validation check to
sbi_pmu_ctr_start and sbi_pmu_ctr_stop as well since sbi_fls is
undefined when the mask is 0.

This also aligns OpenSBI's behavior with KVM's.

Signed-off-by: James Raphael Tiovalen <jamestiotio@gmail.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Link: https://lore.kernel.org/r/20250520132533.30974-1-jamestiotio@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-05-20 21:01:14 +05:30
Anup Patel
d4f5a16598 include: sbi: Change SBI spec version to 3.0
Now that SBI v3.0 specification is frozen, change runtime SBI version
implemented by OpenSBI to v3.0. Also, mark extensions defined by the
SBI v3.0 specification as non-experimental.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
Link: https://lore.kernel.org/r/20250516122844.113423-1-apatel@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-05-20 13:47:34 +05:30
Yao Zi
60c3f97de8 lib: utils: fdt: Claim Zicntr if time CSR emulation is possible
OpenSBI is capable of emulating time CSR through an external timer
for HARTs that don't implement a full Zicntr extension. Let's add
Zicntr extension in the FDT if CSR emulation is active.

This avoids hardcoding the extension in the devicetree, which may
confuse pre-SBI bootloaders.

Signed-off-by: Yao Zi <ziyao@disroot.org>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250516133352.36617-4-ziyao@disroot.org
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-05-20 13:25:53 +05:30
Yao Zi
7e31dc8052 lib: sbi: hart: Detect existence of cycle and instret CSRs for Zicntr
Zicntr extension specifies three read-only CSRs, time, cycle and
instret. It isn't sufficient to report Zicntr is fully supported with
only time CSR detected.

This patch introduces a bitmap to sbi_hart_features to record
availability of these CSRs, which are detected using traps. Zicntr is
reported as present if and only if three CSRs are all available on the
HARTs.

Sites originally depending on SBI_HART_EXT_ZICNTR for detecting
existence of time CSR are switched to detect SBI_HART_CSR_TIME instead.

Suggested-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Yao Zi <ziyao@disroot.org>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250516133352.36617-3-ziyao@disroot.org
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-05-20 13:25:53 +05:30
Alvin Chang
2bb7632649 lib: utils: Fix fdt_mpxy_init() not returning error code
It seems that current implementation doesn't fail on fdt_mpxy_init(),
because platforms might not have any MPXY devices. In fact, if there are
no MPXY devices, fdt_driver_init_all() will return SBI_OK.

More importantly, if there is any MPXY device which fails the
initialization, OpenSBI must check the error code and stop the booting.
Thus, this commit adds the return value for fdt_mpxy_init().

Signed-off-by: Alvin Chang <alvinga@andestech.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250430091007.3768180-1-alvinga@andestech.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-05-20 11:20:57 +05:30
Anup Patel
f3cce5b97f lib: utils/mpxy: Remove p2a_db_index from RPMI system MSI attributes
The discovery of P2A doorbell system MSI index is now through RPMI
shared memory DT node so remove p2a_db_index from RPMI system MSI
attributes and access it as a mailbox channel attribute.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Link: https://lore.kernel.org/r/20250512083827.804151-5-apatel@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-05-20 11:10:35 +05:30
Anup Patel
8fadfebdd1 lib: utils/mailbox: Parse A2P doorbell value from DT
The A2P doorbell value written to the 32-bit A2P doorbell value
must be discoverd from device tree instead of always using the
default value 1.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Link: https://lore.kernel.org/r/20250512083827.804151-4-apatel@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-05-20 11:10:35 +05:30
Anup Patel
a79566175c lib: utils/mailbox: Parse P2A doorbell system MSI index from DT
The P2A doorbell system MSI index is expected to be discovered from
device tree instead of RPMI system MSI service group attribute. This
is based on ARC feedback before RPMI spec was frozen.

Let's parse P2A doorbell system MSI index from device tree and also
expose it as rpmi channel attribute to RPMI client drivers.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Link: https://lore.kernel.org/r/20250512083827.804151-3-apatel@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-05-20 11:10:35 +05:30
Anup Patel
8ca08044c2 lib: utils/mailbox: Update DT register name of A2P doorbell
The latest device tree bindings define A2P doorbell register name as
"a2p-doorbell" so update rpmi_shmem_transport_init() accordingly.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Link: https://lore.kernel.org/r/20250512083827.804151-2-apatel@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-05-20 11:10:35 +05:30
Chao-ying Fu
8a3071222a lib: Emulate AMO instructions when Zaamo is not available
The AMO instructions are very critical for Linux so allow low-end
RISC-V implementations without Zaamo to boot Linux by emulating AMO
instructions using Zalrsc when OpenSBI is compiled without Zaamo.

Signed-off-by: Chao-ying Fu <cfu@mips.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Link: https://lore.kernel.org/r/20250519121207.976949-1-apatel@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-05-20 09:18:03 +05:30
Parshintsev Anatoly
017a161788 Makefile: fix missing .debug_frame DWARF section for GCC
When OpenSBI is built with a relatively new compiler (gcc-13 and greater)
I observed that GDB is unable to produce proper backtraces and some
variable values appear corrupted (even if the associated DWARF
location descriptor is correct).

Turns out that to properly work with debug information, debuggers often
need to unwind the stack. They generally rely on Call Frame Information
(CFI) records provided by the compiler to facilitate this task.
Currently, the GCC compiler offers two mechanisms:

- `.debug_frame` section (as described in the DWARF specification).
- `.eh_frame` sections (as described in LSB documents).

The latter (`.eh_frame`) supports stack unwinding at runtime, providing
a framework for C++ exceptions or enabling backtrace generation using
libraries like libunwind. However, the downside of this approach is that
these sections should be part of loadable segments.

The former (`.debug_frame`) is simply an ordinary debug section.

Starting from GCC 13, Linux targets enable the `-fasynchronous-unwind-tables`
and `-funwind-tables` flags by default. Relevant commit:
https://github.com/gcc-mirror/gcc/commit/3cd08f7168

When these flags are active, the compiler generates `.eh_frame` sections
instead of `.debug_frame`. Since OpenSBI is built using the **Linux
toolchain**, this behavior applies to OpenSBI as well.

The problem arises because the SBI build system uses `-Wl,--gc-sections`,
which discards the `.eh_frame` section.

Possible Fixes:

1. Enforce `.debug_frame` generation – Modify compiler flags to generate
`.debug_frame` instead of `.eh_frame`.
2. Preserve `.eh_frame` in the linker script – Add `KEEP(*(.eh_frame))`
to ensure the section is not discarded.

I chose Option 1 because it avoids any runtime overhead.

Signed-off-by: Parshintsev Anatoly <anatoly.parshintsev@syntacore.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250421124729.36364-1-anatoly.parshintsev@syntacore.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-05-15 18:52:38 +05:30
Nick Hu
d844deadec lib: sbi: Use hsm stop for hsm wait
If we hotplug a core and then perform a suspend-to-RAM operation on a
multi-core platform, the hotplugged CPU may be woken up along with the rest
of the system, particularly on platforms that wake all cores from the
deepest sleep state. When this happens, the hotplugged CPU enters the
sbi_hsm_wait WFI wait loop instead of transitioning into a
platform-specific low-power state. To address this, we add a HSM stop call
within the wait loop. This allows platforms that support HSM stop to enter
a low-power state when the CPU is unexpectedly woken up.

Signed-off-by: Nick Hu <nick.hu@sifive.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250418064506.15771-1-nick.hu@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-05-15 17:31:11 +05:30
Radim Krčmář
316daaf1c2 lib: sbi_hart: properly reset Ssstateen
sstateen* and hstateen* CSRs must be zeroed by M-mode if the mstateen*
registers are missing, to avoid security issues.

Reviewed-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Radim Krčmář <rkrcmar@ventanamicro.com>
Link: https://lore.kernel.org/r/20250429142549.3673976-10-rkrcmar@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-30 10:14:26 +05:30
Radim Krčmář
937118ca65 lib: sbi_hart: add Ssstateen extension
We already detect Smstateen, but Ssstateen exists as well and it doesn't
have the M-state CSRs.

Reviewed-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Radim Krčmář <rkrcmar@ventanamicro.com>
Link: https://lore.kernel.org/r/20250429142549.3673976-9-rkrcmar@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-30 10:14:26 +05:30
Radim Krčmář
dac15cb910 lib: sbi_hart: reset mstateen0
The current logic clears some bits based on SBI known extensions.
Be safe and do not leave enabled anything that SBI doesn't control.

This is not a breaking change, because the register must be initialized
to 0 by the ISA on reset, but it is better to not depend on it when we
don't need to.

Reviewed-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Radim Krčmář <rkrcmar@ventanamicro.com>
Link: https://lore.kernel.org/r/20250429142549.3673976-8-rkrcmar@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-30 10:14:26 +05:30
Radim Krčmář
8c814b5c9b lib: sbi_hart: fix sstateen emulation
The Sstateen extension defines 4 sstateen registers, but SBI currently
configures the execution environment to throw illegal instruction
exception when accessing sstateen1-3.

SBI should implement all sstateen registers, so delegate the
implementation to hardware by setting the SE bit.

Reviewed-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Radim Krčmář <rkrcmar@ventanamicro.com>
Link: https://lore.kernel.org/r/20250429142549.3673976-7-rkrcmar@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-30 10:14:26 +05:30
Radim Krčmář
6b877fb53b lib: sbi_hart: reset sstateen and hstateen
Not resetting sstateen is a potential security hole, because U might be
able to access state that S does not properly context-switch.
Similar for hstateen with VS and HS.

Reviewed-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Radim Krčmář <rkrcmar@ventanamicro.com>
Link: https://lore.kernel.org/r/20250429142549.3673976-6-rkrcmar@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-30 10:14:26 +05:30
Radim Krčmář
009f77a9f0 lib: sbi_hart: reset hstatus
hstatus.HU must be cleared, because U-mode could otherwise use the
HLS/HSV instructions.  This would allow U-mode to read physical memory
directly if vgatp and vsatp was 0.

The remaining fields don't seem like a security vulnerability now, but
clearing the whole CSR is not an issue, so do that be safe.

Reviewed-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Radim Krčmář <rkrcmar@ventanamicro.com>
Link: https://lore.kernel.org/r/20250429142549.3673976-5-rkrcmar@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-30 10:14:26 +05:30
Radim Krčmář
65e8be4fe8 lib: sbi: use 64 bit csr macros
Switch the most obvious cases to new macros.

Reviewed-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Radim Krčmář <rkrcmar@ventanamicro.com>
Link: https://lore.kernel.org/r/20250429142549.3673976-4-rkrcmar@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-30 10:14:25 +05:30
Radim Krčmář
f82c4bdf8c lib: sbi: add 64 bit csr macros
Most CSRs are XLEN bits wide, but some are 64 bit, so rv32 needs two
accesses, plaguing the code with ifdefs.

Add new helpers that split 64 bit operation into two operations on rv32.

The helpers don't use "csr + 0x10", but append "H" at the end of the csr
name to get a compile-time error when accessing a non 64 bit register.
This has the downside that you have to use the name when accessing them.
e.g. csr_read64(0x1234) or csr_read64(CSR_SATP) won't compile and the
error messages you get for these bugs are not straightforward.

Reviewed-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Radim Krčmář <rkrcmar@ventanamicro.com>
Link: https://lore.kernel.org/r/20250429142549.3673976-3-rkrcmar@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-30 10:14:25 +05:30
Raj Vishwanathan
99aabc6b84 lib: sbi: Set the scratch allocation to alignment to cacheline size
Set the scratch allocation alignment to cacheline size specified by
riscv,cbom-block-size in the DTS file to avoid two atomic variables
from the same cache line causing livelock on some platforms. If the
cacheline is not specified, we set it a default value.

Signed-off-by: Raj Vishwanathan <Raj.Vishwanathan@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Link: https://lore.kernel.org/r/20250423225045.267983-1-Raj.Vishwanathan@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-24 09:23:47 +05:30
Alvin Chang
4d0128ec58 lib: sbi_domain: Reduce memory usage of per-domain hart context
In current implementation, the length of hartindex_to_context_table[]
array is fixed as SBI_HARTMASK_MAX_BITS. However, the number of harts
supported by the platform might not be SBI_HARTMASK_MAX_BITS and is
usually smaller than SBI_HARTMASK_MAX_BITS. This means it is unnecessary
to allocate such fixed-length array here.

Precisely, current implementation always allocates 1024 bytes for
hartindex_to_context_table[128] on RV64 platform. However, a platform
supports two harts only needs hartindex_to_context_table[2], which only
needs 16 bytes.

This commit calculates needed size of hartindex_to_context_table[]
according to supported number of harts on the platform when registering
per-domain data, so that memory usage of per-domain context data can be
reduced.

Signed-off-by: Alvin Chang <alvinga@andestech.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250326062051.3763530-1-alvinga@andestech.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-23 17:51:01 +05:30
Samuel Holland
2b09a98701 lib: sbi_platform: Remove the vendor_ext_check hook
Now that the generic platform only sets .vendor_ext_provider if the
function is really implemented, there is no need for a separate hook to
check if a vendor extension is implemented.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250325234342.711447-11-samuel.holland@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-23 12:32:51 +05:30
Samuel Holland
0dd8a26f1f lib: utils/fdt: Remove fdt_match_node()
This function has been obsoleted by the fdt_driver library and is no
longer used.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250325234342.711447-10-samuel.holland@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-23 12:32:51 +05:30
Samuel Holland
1c579675be platform: generic: Initialize overrides with fdt_driver
In addition to deduplicating the code, this also improves the match
selection logic to respect the priority order of the compatible strings,
as implemented in commit 0ffe265fd9 ("lib: utils/fdt: Respect
compatible string fallback priority").

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250325234342.711447-9-samuel.holland@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-23 12:32:51 +05:30
Samuel Holland
b80ded7756 platform: generic: Remove platform override hooks
Now that all of the overrides are modifying generic_platform_ops
directly, remove the unused hooks and forwarding functions. The
remaining members of struct platform_override match struct fdt_driver,
so use that type instead. This allows a future commit to reuse the
fdt_driver-based init function.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250325234342.711447-8-samuel.holland@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-23 12:32:51 +05:30
Samuel Holland
b353af63e2 platform: generic: Modify platform ops instead of using hooks
Switch all existing platform overrides to use the helper pattern instead
of the platform hooks. After this commit, only the .match_table and
.init members of struct platform_override are used.

There are two minor behavioral differences:
 - For Allwinner D1, fdt_add_cpu_idle_states() is now called before the
   body of generic_final_init(). This should have no functional impact.
 - For StarFive JH7110, if the /chosen/starfive,boot-hart-id property is
   missing, the code now falls back to using generic_coldboot_harts,
   instead of accepting any hart.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250325234342.711447-7-samuel.holland@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-23 12:32:51 +05:30
Samuel Holland
2489e1421d platform: generic: Allow replacing platform operations
Currently the generic platform follows the middleware pattern: it
implements the sbi_platform hooks, while providing its own set of hooks
for further customization. This has a few disadvantages: each location
where customization is needed requires a separate platform_override
hook, including places where the generic function does nothing except
forward to a platform_override hook, and the extra layer of function
pointers adds runtime overhead.

Let's restructure the generic platform to follow the helper pattern.
Allow platform overrides to treat the generic platform as a template,
adding or replacing the sbi_platform_operations as needed. Export the
generic implementations, so they can be called as helpers from inside
the override functions. With this pattern, the platform_override
function pointers are replaced by direct calls, and the forwarding
functions can be removed.

The forwarding functions are not exported, since there is no reason for
an override to call them. generic_vendor_ext_check() must be rewritten,
since now there is a new way to override vendor_ext_provider.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250325234342.711447-6-samuel.holland@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-23 12:32:50 +05:30
Samuel Holland
e78a0ebdc4 platform: generic: Add an init hook matching fdt_driver
In preparation for reusing the fdt_driver code to match platform
overrides, add a new .init hook matching the type signature from
fdt_driver. This hook replaces the existing .fw_init hook, since
it is called at roughly the same place in the init process.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250325234342.711447-5-samuel.holland@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-23 12:32:50 +05:30
Samuel Holland
de777cc633 platform: generic: thead: Avoid casting away const
struct fdt_match expects match data to be const. Follow this expectation
so that no type casting is needed.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250325234342.711447-4-samuel.holland@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-23 12:32:50 +05:30
Samuel Holland
ac2e428c4b platform: rzfive: Call andes_pma_setup_regions() only during cold boot
This function accesses the FDT blob, which means it is only valid to
call during cold boot, before a lower privilege level has an opportunity
to clobber that memory.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250325234342.711447-3-samuel.holland@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-23 12:32:50 +05:30
Samuel Holland
2a6f7ddf87 platform: generic: andes: Remove inline definitions
The addresses of these functions are used to set function pointers in
struct platform_override, so it is not valid for them to be inline.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250325234342.711447-2-samuel.holland@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-23 12:32:50 +05:30
Alvin Chang
fda0742e76 lib: sbi_mpxy: Change MPXY state as per-domain data
OpenSBI supports multiple supervisor domains run on same platform. When
these supervisor domains want to communicate with OpenSBI through MPXY
channels, they will allocate MPXY shared memory from their own memory
regions. Therefore, the MPXY state data structure must be per-domain and
per-hart data structure.

This commit registers per-domain MPXY state data in sbi_mpxy_init(). The
original MPXY state allocated in scratch region is also removed. We also
replace sbi_scratch_thishart_offset_ptr() macro as new
sbi_domain_mpxy_state_thishart_ptr() macro which gets MPXY state from
per-domain data.

Signed-off-by: Alvin Chang <alvinga@andestech.com>
Reviewed-by: Yu-Chien Peter Lin <peter.lin@sifive.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Link: https://lore.kernel.org/r/20250325071314.3113941-1-alvinga@andestech.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-21 11:35:44 +05:30
Jimmy Ho
d2166a9d40 lib: sbi: Handle length of extension name string exceed buffer size error
print error message and turncat the string when length
of extension name string exceed buffer size

Signed-off-by: Jimmy Ho <jimmy.ho@sifive.com>
Reviewed-by: Nick Hu <nick.hu@sifive.com>
Reviewed-by: Zong Li <zong.li@sifive.com>
Link: https://lore.kernel.org/r/20250321001450.11189-1-jimmy.ho@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-21 08:42:01 +05:30
Xiang W
190979b4fc lib: sbi: Remove unnecessary SBI_INIT_LIST_HEAD
No need to initialise the nodes to be added to the linked list

Signed-off-by: Xiang W <wxjstz@126.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250319123944.505756-1-wxjstz@126.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-15 11:38:20 +05:30
Xiang W
169b4b8ae2 lib: sbi: Simplify structure member offset checking
Add a macro assert_member_offset() to perform structure member offset
checking.

Signed-off-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250319123919.505443-1-wxjstz@126.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-15 11:26:36 +05:30
Xiang W
8b026abc5a lib: sbi: Fix SHMEM_PHYS_ADDR for RV32
Obtaining a 64-bit address under rv32 does not require combining two
32-bit registers because we ignore upper 32-bits on rv32.

Signed-off-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250319123832.505033-1-wxjstz@126.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-15 11:22:00 +05:30
Xiang W
ce57cb572e lib: sbi: Add parameter check in sbi_mpxy_set_shmem()
Shared memory needs to be accessed in M-Mode so for now the high
address of shared memory can't non-zero.

Signed-off-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250319123719.504622-1-wxjstz@126.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-15 10:19:13 +05:30
Leo Yu-Chi Liang
0442f1318e lib: sbi: Allow programmable counters to monitor cycle/instret events for Andes PMU
Referencing commit 0c304b6619
("lib: sbi: Allow programmable counters to monitor cycle/instret events")
to support this functionality for Andes PMU.

Signed-off-by: Leo Yu-Chi Liang <ycliang@andestech.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
Link: https://lore.kernel.org/r/20250328084142.540807-1-ycliang@andestech.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-14 17:28:59 +05:30
Leo Yu-Chi Liang
5ab908d622 docs: pmu_support: fix example typos
The (event ID & "second column mask") should equal
the "first column match value". Modify the example
to fit the description.

Signed-off-by: Leo Yu-Chi Liang <ycliang@andestech.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Link: https://lore.kernel.org/r/20250324043943.2513070-1-ycliang@andestech.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-14 17:25:54 +05:30
Andrew Jones
37eaca4ab3 lib: sbi_ipi: Return error for invalid hartids
sbi_send_ipi() should return SBI_ERR_INVALID_PARAM if even one hartid
constructed from hart_mask_base and hart_mask, is not valid.

Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250314163021.154530-6-ajones@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-14 15:29:36 +05:30
Andrew Jones
a6e5f8878c sbi: Introduce sbi_hartmask_weight
Provide a function to count the number of set bits in a hartmask,
which builds on a new function for the same that operates on a
bitmask. While at it, improve the performance of sbi_popcount()
which is used in the implementation.

Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250314163021.154530-5-ajones@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-14 15:29:19 +05:30
Samuel Holland
2142618f12 Makefile: Avoid repeated evaluation of shell commands
Recursively expanded variables (defined with '=') are expanded at
evaluation time. These version information variables are evaluated
inside a recipe as part of GENFLAGS. As a result, the shell commands
are executed separately for each compiler invocation. Convert the
version information variables to be simply expanded, so the shell
commands are executed only once, at Makefile evaluation time. This
speeds up the build by as much as 75%.

A separate check is needed to maintain the behavior of preferring the
value of OPENSBI_BUILD_TIME_STAMP from the environment.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250313035755.3796610-1-samuel.holland@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-13 21:49:14 +05:30
Rajnesh Kanwal
aa40c53ce4 lib: sbi: Enable Control Transfer Records (CTR) Ext using xstateen.
The Control Transfer Records (CTR) extension provides a method to
record a limited branch history in register-accessible internal chip
storage.

This extension is similar to Arch LBR in x86 and BRBE in ARM.
The Extension has been stable and the latest release can be found here
https://github.com/riscv/riscv-control-transfer-records/release

Signed-off-by: Rajnesh Kanwal <rkanwal@rivosinc.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250307124451.122828-1-rkanwal@rivosinc.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-13 06:11:43 +05:30
Samuel Holland
afa0e3091b lib: sbi_trap: Add support for vectored interrupts
When redirecting an exception to S-mode, transform the (v)stvec CSR
value as described in the privileged spec to derive the S-mode PC.
Since OpenSBI never redirects interrupts, only synchronous exceptions,
the only action needed is to mask out the (v)stvec.MODE field.

Reported-by: Jan Reinhard <jan.reinhard@sysgo.com>
Closes: https://github.com/riscv-software-src/opensbi/issues/391
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviwed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250305014729.3143535-1-samuel.holland@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-13 05:51:17 +05:30
Chao-ying Fu
995f226f3f lib: Emit lr and sc instructions based on -march flags
When -march=rv64im_zalrsc_zicsr is used, provide atomic operations
and locks using lr and sc instructions only.

Signed-off-by: Chao-ying Fu <cfu@mips.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250226014727.19710-1-cfu@mips.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-03-28 18:52:05 +05:30
Junhui Liu
8fe835303c lib: utils/serial: Add PXA UARTs support
The PXA variant of the uart8250 adds the UART Unit Enable bit (UUE) that
needs to be set to enable the XScale PXA UART. And it is required for
some RISC-V SoCs like the Spacemit K1 that implement the PXA UART.

This introduces the "intel,xscale-uart" compatible to handle setting the
UUE bit.

Signed-off-by: Junhui Liu <junhui.liu@pigmoral.tech>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250327-pxa-uart-support-v2-1-c4400c1fcd0b@pigmoral.tech
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-03-27 20:20:05 +05:30
Clément Léger
3ac49712e3 lib: sbi: sse: Add support for SSTATUS.SDT
Similarly to what is done for SPELP, handle SSTATUS.SDT upon event
injection. In order to mimick an interrupt, set SDT to 1 for injection and
save its previous value in interrupted_flags[5:5]. Restore it upon
completion.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
2025-03-27 18:16:44 +05:30
Clément Léger
b4464b22e4 lib: sbi: sse: Add support for SSTATUS.SPELP
As raised during the ARC review, SPELP was not handled during the event
injection process. Save it as part of the interrupted flags, clear it
before injecting the event and restore it after completion.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
2025-03-27 18:16:28 +05:30
Clément Léger
53d322f8ae lib: sbi: sse: Remove superfluous parenthesis around MSTATUS_* values
For some reason, there was a pair of useless parenthesis around MSTATUS_*
value usage. Remove them.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
2025-03-27 18:16:19 +05:30
Clément Léger
41fb89cb29 lib: sbi: sse: Rename STATUS* interrupted flags to SSTATUS*
As raised by Andrew on the kvm-unit-test review, this flags are meant to
hold SSTATUS bits in the specification. Rename them to match that.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
2025-03-27 18:15:44 +05:30
Clément Léger
1e7258d6a8 lib: sbi: sse: Return SBI_EDENIED for read only parameters.
The SSE specification did specified that read only parameters should
return SBI_EBADRANGE but was modified recently to return SBI_EDENIED.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
2025-03-27 18:15:25 +05:30
Clément Léger
5dc7a6db6f lib: sbi: sse: Remove printf from sbi_sse_exit()
This printf is mainly useful for debugging, remove it.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
2025-03-27 18:15:10 +05:30
Clément Léger
601bea45c5 lib: sbi: sse: Update SSE event ids
The latest specification added new high priority RAS events and renamed
the PMU to PMU_OVERFLOW.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
2025-03-27 18:03:41 +05:30
Raj Vishwanathan
321ca8063b lib: utils: Make sure that hartid and the scratch are aligned
Harts associated with an ACLINT_MSWI need not have sequential hartids.
It is insufficient to use first_hartid and hart_count. To account for
non-sequential hart ids, include the empty hart-ids' generate hart-count.

Signed-off-by: Raj Vishwanathan <Raj.Vishwanathan@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-03-26 19:11:10 +05:30
Samuel Holland
949c83a799 lib: sbi: Use sbi_hart_count() and sbi_for_each_hartindex()
Simplify the code and improve consistency by using the new macros where
possible. sbi_hart_count() obsoletes sbi_scratch_last_hartindex().

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-03-24 17:57:20 +05:30
Samuel Holland
757f7acafd lib: sbi_scratch: Add sbi_hart_count() and for_each_hartindex()
There is currently no helper for iterating through the harts in a
system, and code must choose between sbi_scratch_last_hartindex() and
sbi_platform_hart_count() for the loop condition.

sbi_scratch_last_hartindex() has unusual semantics, leading to the
likelihood of off-by-one errors, and sbi_platform_hart_count() is
provided by the platform and so may not be properly bounded.

Add a new helper which definitively reports the number of harts managed
by this OpenSBI instance, i.e. the number of valid hart indexes, and a
convenient iterator macro.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-03-24 17:56:08 +05:30
Samuel Holland
6b97950cf5 lib: sbi_scratch: Optimize hartid and scratch lookup
The compiler generates much better code for sbi_hartindex_to_hartid()
and sbi_hartindex_to_scratch() when using a constant for the bounds
check. This works out nicely because the underlying arrays are already
a constant size, so the only change needed is to fill the remainder of
each array with the appropriate default/out-of-bounds value. The
ellipsis in the designated initializer is a GCC extension (also
supported by Clang), but avoids runtime initialization of the array.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-03-24 17:56:05 +05:30
Samuel Holland
ef4ed2dda7 lib: sbi_scratch: Apply bounds check to platform hart_count
The internal limit on the number of harts is SBI_HARTMASK_MAX_BITS, as
this value determines the size of various bitmaps and arrays (including
hartindex_to_hartid_table and hartindex_to_scratch_table). Clamp the
value provided by the platform, and drop the extra array element.

Update the documentation to indicate that hart_index2id must be sized
based on hart_count, and that hart indexes must be contiguous. As of
commit 5e90e54a1a ("lib: utils:Check that hartid is valid"), there is
no restriction on the valid hart ID values.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-03-24 17:56:04 +05:30
Samuel Holland
86c01a73ff lib: sbi: Avoid GOT indirection for global symbol references
OpenSBI is compiled with -fPIE, which generally implies dynamic linking.
This causes the compiler to generate GOT references for global symbols
in order to support runtime symbol interposition. However, OpenSBI does
not actually perform dynamic linking, so the GOT indirection just adds
unnecessary overhead.

The GOT references can be avoided by declaring global symbols with
hidden visibility, thus making them local to this dynamic object and
non-interposable. GCC/Clang's -fvisibility parameter is insufficient for
this purpose when referencing objects from other translation units;
either __attribute__((visibility(...)) or the pragma is required. Use
the pragma since it is easier to apply to every symbol. Additionally
clean up the one GOT reference from inline assembly.

With this change, a firmware linked with LLD does not contain either a
GOT or a PLT, and a firmware linked with BFD ld contains only a GOT with
a single (unreferenced, legacy) _GLOBAL_OFFSET_TABLE_ entry.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-03-24 17:00:59 +05:30
Samuel Holland
98c0a3860a Revert "lib: utils/irqchip: Match against more specific compatible strings first"
This reverts commit 6019259dfb.

Now that fdt_driver_init_by_offset() respects the compatible string
fallback priority order, this workaround is no longer necessary.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-03-24 16:37:52 +05:30
Samuel Holland
0ffe265fd9 lib: utils/fdt: Respect compatible string fallback priority
When matching drivers to DT nodes, always match all drivers against the
first compatible string before considering fallback compatible strings.
This ensures the most specific match is always selected, regardless of
the order of the drivers or match structures, as long as no compatible
string appears in multiple match structures.

Fixes: 1ccc52c427 ("lib: utils/fdt: Add helpers for generic driver initialization")
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-03-24 16:37:06 +05:30
Himanshu Chauhan
b2e8e6986d lib: sbi: Return SBI_EALREADY error code if SSE event is present
Return SBI_EALREADY error code instead of SBI_EINVAL, in case an
event is already added to the supported list.

Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-03-23 21:17:36 +05:30
Anup Patel
8573a9b858 scripts: Fix firmware binaries compilation in create-binary-archive.sh
Currently, the generic libsbi.a is compiled in create-binary-archive.sh
before platform specific firmwares so a libsbi.a without any SBI extension
gets linked to the platform specific firmwares. To address this, remove
the temporary build directory in create-binary-archive.sh before using it.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2025-03-23 21:16:25 +05:30
Dongdong Zhang
3e6bd14246 lib: tests: add bitwise operations unit tests
Added unit tests for various bitwise operations using SBI unit
test framework.

Signed-off-by: Dongdong Zhang <zhangdongdong@eswincomputing.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-03-23 21:06:25 +05:30
Dongdong Zhang
56341e95ae lib: sbi: Fix potential garbage data in string copy functions
In the original implementation of `sbi_strcpy` and `sbi_strncpy`, if the
destination buffer (`dest`) was longer than the source string (`src`),
the functions did not ensure that the remaining bytes in `dest` were
properly null-terminated. This could result in garbage data being
present in the destination buffer after the copy operation, as the
functions only copied characters from `src` without explicitly
terminating `dest`.

Signed-off-by: Dongdong Zhang <zhangdongdong@eswincomputing.com>
Reviewed-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-03-23 18:38:57 +05:30
Akshay Behl
0b78665a6c lib: add tests for sbi_ecall functionality
This patch adds unit tests for verifying the sbi_ecall version,
impid handling, and extension registration functions. The tests
ensure that the extension registration and unregistration work
as expected.

Signed-off-by: Akshay Behl <akshaybehl231@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-03-23 16:56:54 +05:30
Clément Léger
1ad1991244 lib: sbi: fwft: Return SBI_ERR_DENIED_LOCKED when setting a locked feature
Latest modifications to the spec mandates that a set on a lock feature
returns SBI_ERR_DENIED_LOCKED.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-19 22:13:21 +05:30
Clément Léger
b91ab20cd2 include: sbi: Add SBI_ERR_DENIED_LOCKED
Add SBI_ERR_DENIED_LOCKED and set it as the SBI_LAST_ERR which was
wrongly set to SBI_ERR_BAD_RANGE.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-19 22:10:59 +05:30
Alex Studer
6019259dfb lib: utils/irqchip: Match against more specific compatible strings first
The T-HEAD C90x PLIC has some special quirks, such as the S-mode
delegation bit. OpenSBI currently handles this by checking the compatible
string in the device tree.

However, this matching is done in the order of the fdt_match array. So if
a device tree contains both strings, for example:

	compatible = "thead,c900-plic", "riscv,plic0";

Then OpenSBI will match against the generic "riscv,plic0" string, since
that appears first in the fdt_match array. This means it will fail to set
the S-mode delegation bit, and Linux will fail to boot. In some cases, it
is not possible to change the compatible string to just the T-HEAD PLIC,
as older versions of Linux only recognize the RISC-V compatible string.

This patch fixes that by moving the RISC-V string to the end, ensuring
that the more specific options get matched first.

Signed-off-by: Alex Studer <alex@studer.dev>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-19 21:49:08 +05:30
Samuel Holland
a2c172f526 lib: utils/fdt: Allocate fdt_pmu_evt_select on the heap
This reduces .bss size by 8 KiB, and should reduce overall memory usage
since most platforms will have significantly fewer than 512 entries in
this table. At the same time, it removes the fixed table size limit.
Since the table is only used within fdt_pmu.c, instead of updating the
extern declaration, make the table local to this file.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-19 18:25:17 +05:30
Samuel Holland
f95d1140f6 lib: utils/fdt: Remove redundant PMU property length checks
If a property value is too small, len will be zero after the division
on the next line, so the property will be ignored. This is the same
behavior as when the length check fails. Furthermore, the first two
length checks were already ineffectual, because each item in those
arrays is 12 bytes long, not 8.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-19 18:22:52 +05:30
Samuel Holland
38df94422b lib: utils: Constify FDT driver definitions
The carray referencing these definitions assumes they are const.

Fixes: 6a26726e08 ("lib/utils: reset: Add RPMI System Reset driver")
Fixes: 13f55f33a1 ("lib: utils/suspend: Add RPMI system suspend driver")
Fixes: 33ee9b8240 ("lib: utils/hsm: Add RPMI HSM driver")
Fixes: 591a98bdd5 ("lib: utils/cppc: Add RPMI CPPC driver")
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-19 17:47:24 +05:30
Clément Léger
f354400ebf lib: sbi: sse: fix invalid errors returned for sse_hart_mask/unmask()
When called twice, sse_hart_mask()/sse_hart_unmask() should return
SBI_EALREADY_STOPPED/SBI_EALREADY_STARTED. This was currently inverted.

Fixes: b919daf495 ("lib: sbi: Add support to mask/unmask SSE events")
Reported-by: Andrew Jones <ajones@ventanamicro.com>
Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-19 17:18:13 +05:30
Anup Patel
1f64fef919 lib: sbi: Fix non-root domain startup
Currently, the sbi_sse_init() in cold boot path is called after
sbi_domain_finalize() so boot HART of non-root domains will start
before SSE cold boot init which can cause warm boot of such HARTs
to crash in sbi_sse_init().

To address the above issue, factor-out the non-root domain startup
from sbi_domain_finalize() function as a separate sbi_domain_startup()
function  which can be called after sbi_sse_init() in cold boot path.

Fixes: 93f7d819fd ("lib: sbi: sse: allow adding new events")
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2025-02-19 17:11:39 +05:30
Joel Stanley
fe11dee7ea README: Remove comment about boolin toolchains being 64-bit only
As of January 2025 they have riscv32-ilp32d and riscv64-lp64d:

 https://toolchains.bootlin.com/releases_riscv32-ilp32d.html
 https://toolchains.bootlin.com/releases_riscv64-lp64d.html

Signed-off-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-18 14:10:54 +05:30
Joel Stanley
f3dfa6488f README: Update toolchain section to mention PIE requirement
Since commit 76d7e9b8ee ("firmware: remove copy-base relocation"), the
Makefile enforces PIE support.

Signed-off-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-18 14:10:11 +05:30
Joel Stanley
02c7a9bbef README: Any arch host can be used to cross compile
Verified by cross compiling from an arm64 host.

Signed-off-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-18 14:08:29 +05:30
Anup Patel
ec09918426 lib: sbi: Update MPXY framework and SBI extension as per latest spec
The latest SBI 3.0 spec defines a new sbi_mpxy_get_shmem_size()
function and simplifies sbi_mpxy_set_shmem() function so update
the MPXY framework and SBI extension accordingly.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2025-02-13 11:10:03 +05:30
Anup Patel
61abd975f2 lib: utils: Add MPXY RPMI mailbox driver for System MSI service group
The supervisor software can directly receive most of the system MSIs
except P2A doorbell and MSIs preferred to be handled in M-mode.

Add MPXY RPMI mailbox client driver for the System MSI service group.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2025-02-13 11:10:03 +05:30
Anup Patel
b05e2a1956 include: sbi_utils: Update RPMI service group IDs and BASE service group
The service group ID assignment and some of the BASE services have
changes in the latest RPMI specification so let's update the RPMI
implementation accordingly.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2025-02-13 11:10:03 +05:30
Anup Patel
e4bc55930b lib: utils: Populate MPXY channel attributes from RPMI channel attributes
Use the RPMI mailbox channel attributes to populate MPXY channel
attributes instead of hard coding them.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2025-02-13 11:10:03 +05:30
Anup Patel
91012b475d lib: utils: Implement get_attribute() for the RPMI shared memory mailbox
To allow clients query service group version of a RPMI mailbox channel,
implement get_attribute() callback for the RPMI shared memory mailbox
controller.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2025-02-13 11:10:03 +05:30
Anup Patel
f8272946da include: sbi_utils: Include mailbox.h in rpmi_mailbox.h header
The rpmi_mailbox.h uses structures defined in mailbox.h so let's
include mailbox.h in rpmi_mailbox.h header.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2025-02-13 11:10:03 +05:30
Anup Patel
218de6ff7d lib: utils: Improve variable declarations in MPXY RPMI mailbox client
The local variable declarations should be at the start of function
and preferrably organized like a inverted pyramid.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2025-02-13 11:10:03 +05:30
Anup Patel
879ee6859c lib: utils: Drop notifications from MPXY RPMI mailbox client
Currently, the common MPXY RPMI mailbox client does not support
notifications so no need for dummy notifications support.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2025-02-13 11:10:03 +05:30
Anup Patel
a4876e6c6c lib: sbi: Improve local variable declarations in MPXY framework
The local variable declarations should be at the start of function
and preferrably organized like a inverted pyramid.

Signed-off-by: Anup patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2025-02-13 11:10:03 +05:30
Anup Patel
30437eb204 lib: sbi: Fix capability bit assignment in MPXY framework
The capability bit assignment in MPXY framework does not match the
SBI MPXY extension in latest SBI specification so update it.

Fixes: 7939bf1329 ("lib: sbi: Add SBI Message Proxy (MPXY) framework")
Signed-off-by: Anup patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2025-02-13 11:10:03 +05:30
Anup Patel
75c2057a6f lib: utils: Introduce optional MPXY RPMI service group operations
Some of the RPMI service groups may need additional context and
special handling when transferring messages via underlying mailbox
channel so introduce optional MPXY RPMI service group operations
for this purpose.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2025-02-13 11:10:03 +05:30
Anup Patel
fc1232899d lib: utils: Constantify mpxy_rpmi_mbox_data in mpxy_rpmi_mbox
The mpxy_rpmi_mbox_data is provided by RPMI service group specific
MPXY driver to the common MPXY RPMI mailbox client implementation
so let's constantify mpxy_rpmi_mbox_data in mpxy_rpmi_mbox so that
it is not accidently modified.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2025-02-13 11:10:03 +05:30
Anup Patel
d14340cb31 lib: utils: Split the FDT MPXY RPMI mailbox client into two parts
Instead of having one common FDT MPXY RPMI mailbox client drivers
for various RPMI service groups, split this driver into two parts:
1) Common MPXY RPMI mailbox client library
2) MPXY driver for RPMI clock service group

The above split enables having a separate MPXY driver for each
RPMI clock service group and #1 (above) will allow code sharing
between various MPXY RPMI drivers.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2025-02-13 11:10:03 +05:30
Clément Léger
5ce121b7a1 lib: sbi: increase the size of the string used for extension display
With the "max" QEMU cpu, the displayed extension string is truncated due
to the buffer being too small. Increase it to 256 to display the full
set of extensions correctly.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-13 09:16:05 +05:30
Samuel Holland
434add551c lib: utils: Initialize miscellaneous drivers in one pass
For driver subsystems that are not tightly integrated into the OpenSBI
init sequence, it is not important that the drivers are initialized in
any particular order. By putting all of these drivers in one array, they
can all be initialized with a single pass through the devicetree. This
saves about 10 ms of boot time on HiFive Unmatched.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-12 21:39:25 +05:30
Samuel Holland
e84ba96634 lib: utils/fdt: Remove fdt_find_match()
Now that all drivers are using the fdt_driver functions for
initialization, this function is unused and can be removed.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-12 21:27:54 +05:30
Samuel Holland
9e1a1518d4 lib: utils/irqchip: Use fdt_driver for initialization
The irqchip driver subsystem does not need any extra data, so it can use
`struct fdt_driver` directly. The generic fdt_irqchip_init() performs a
best-effort initialization of all matching DT nodes.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-12 21:22:37 +05:30
Inochi Amaoto
a7f3c159a0 platform: generic: thead: add Sophgo SG2044
The Sophgo SG2044 is a new version of C920, although it supports
sscofpmf, it still needs this pmu quirks its cores.

Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-12 18:00:18 +05:30
Xiang W
82da072eb4 firmware: fw_base.S: Fix comments for _wait_for_boot_hart
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>
2025-02-12 09:34:06 +05:30
Raj Vishwanathan
5e90e54a1a lib: utils:Check that hartid is valid
It is possible that hartid may not be sequential and it should not be validated
against SBI_HARTMASK_MAX_BITS. Instead we should check the index of the hartid,
hart index, against SBI_HARTMASK_MAX_BITS.

Signed-off-by: Raj Vishwanathan <Raj.Vishwanathan@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-12 09:24:09 +05:30
Raj Vishwanathan
4f12f8b02f include: sbi: Align SBI trap registers to a nice boundary
Align SBI_TRAP_CONTEXT_SIZE to a multiple of 16 bytes. If it is not
aligned to 16 bytes for RV64, it can create performance problems.
Aligning it correctly can fix the performance issues.

Signed-off-by: Raj Vishwanathan <Raj.Vishwanathan@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-12 09:14:43 +05:30
Chao Du
3f25380d85 lib: utils: Make the enforce permission bit configurable from DT
The domain_support.md documentation states that the enforce permission
bit (BIT[6]) could be set in the "regions" property of a domain
instance DT node. However, this bit is masked in the current
implementation. This patch unmasks the bit to make it configurable
from DT.

Signed-off-by: Chao Du <duchao@eswincomputing.com>
Reviewed-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-11 17:56:48 +05:30
Huang Borong
a76aca030d lib: utils/fdt: update fdt_parse_aplic_node()
1. Initialize struct imsic_data imsic to 0 at definition to prevent the
   use of uninitialized memory, ensuring the variable starts with known
   values.

2. Remove the redundant memset call on the "aplic" parameter since the
   memory for aplic is allocated using sbi_zalloc() by the caller
   irqchip_aplic_cold_init(), which guarantees it is already set to 0.

Signed-off-by: Huang Borong <huangborong@bosc.ac.cn>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-02-11 16:58:24 +05:30
Leo Yu-Chi Liang
555055d145 include: utils/fdt_helper: fix typo har't'id
s/hard_id/hartid/

Signed-off-by: Leo Yu-Chi Liang <ycliang@andestech.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-01-30 11:15:09 +05:30
Clément Léger
5c7e2c8334 lib: sbi: pmu: add the PMU SSE event only if overflow IRQ is supported
Add the PMU SSE event only if an overflow irq bit is present.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
2025-01-30 10:43:16 +05:30
Clément Léger
ecab71e19a lib: sbi: sse: return SBI_ENOTSUPP for unsupported events
If a standard event was not found in the list of events that are handled
by harts but belongs to the standard event list defined by the
specification, return SBI_ENOTSUPP. Without that, we can not
distinguish a non implemented standard event from a non valid one.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
2025-01-30 10:42:27 +05:30
Clément Léger
93f7d819fd lib: sbi: sse: allow adding new events
In order to allow events to be dynamically added, remove the existing
static array of events and use a simply linked list of supported events.
This allows us to move the cb_ops into this list and associated it with
an event_id. Drivers can now register cb_ops before bringing up the sse
core to handle additional events (platform ones for instance).

sbi_sse_init() now allocates as many events as present in the linked
list. Events can now be added with sbi_sse_add_event() which allows to
add new supported events with some callback operations if any. If an
event is not to be supported, then sbi_sse_add_event() should not be
called. This approach currently consider that local events are to be
supported on all harts (ie, they all support the same ISA or
dependencies). If per-hart event availability needs to be supported,
then, an is_supported() callback could be added later and called for
each hart.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2025-01-30 10:40:49 +05:30
Clément Léger
147978f312 include: lib: add a simple singly linked list implementation
Add a simple singly linked list implementation when double linked list
are not needed. This allows to easily have statically defined linked
list that can be extended at runtime.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-01-30 10:35:46 +05:30
Clément Léger
e05782b8ff lib: sbi: sse: return an error value from sse_event_get()
Since event support will be checked in the next commits, return a value
from sse_event_get() to allow propagating it. This will be used to
report SBI_ERR_NOT_SUPPORTED when an event isn't supported.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
2025-01-30 10:34:14 +05:30
Clément Léger
9d2c9c6ca0 lib: sbi: move sbi_double_trap_handler() to a dedicated header
We will add new functions to sbi_double_trap.c in order to register an
SSE event, split this to a header as part of preparation work.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2025-01-30 10:32:18 +05:30
Clément Léger
3943ddbaab lib: sbi: pmu: fix usage of sbi_pmu_irq_bit()
While sbi_pmu_irq_bit() was used to delegate irq to S-mode, LCOFIP usage
was still hardcoded in various places. This led to change the returned
value of sbi_pmu_irq_bit() to be a bit number rather than a bit mask
since it returns an 'int' and we need to obtain the bit number itself to
handle it in the IRQs handlers. Add a similar function to return the
irq mask which can also be used where the mask is required rather than
the bit itself.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
2025-01-30 10:30:45 +05:30
Anup Patel
bd613dd921 include: Bump-up version to 1.6
Update the OpenSBI version to 1.6 as part of release preparation.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Signed-off-by: Anup Patel <anup@brainfault.org>
2024-12-24 15:28:18 +05:30
Anup Patel
7150db29d7 lib: utils: Fix irqchip registration for PLIC and APLIC
Currently, the same irqchip instance is registered for multiple PLIC
and APLIC instances which causes the sbi_list_for_each_entry() loop
in the sbi_irqchip_init() to hang at boot-time.

To address the above issue, register a separate irqchip instance for
each PLIC and APLIC instance.

Fixes: 2dd6eaf680 ("lib: sbi_irqchip: Call driver warm_init from SBI core")
Reported-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
2024-12-24 14:06:09 +05:30
Anup Patel
551ac0f2d4 lib: sbi: Improve the alignment of boot-time prints
Addition of "Experimental SBI Extensions" to the boot-time prints
disturbs the alignment of other prints so adjust all boot-time
prints accordingly.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-24 12:00:47 +05:30
Anup Patel
06754612f3 lib: sbi: Print list of available SBI extensions at boot-time
Add boot-time prints for list of available standard and experimental
SBI extensions.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-22 11:16:13 +05:30
Michael Neuling
d539d64a23 include: sbi: Fix compiling with C23 enabled compilers
C23 pre-defines bool so we need to gate our defines.

Signed-off-by: Michael Neuling <michaelneuling@tenstorrent.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-21 21:38:50 +05:30
Michael Neuling
91196d76b7 inclue: sbi_utils: Cleanup int vs bool in semihosting_init() definitions
This is needed for a future patches to enable the new C23 language dialect.

Signed-off-by: Michael Neuling <michaelneuling@tenstorrent.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-21 21:21:59 +05:30
Samuel Holland
8d8cc9507b lib: utils: Mark RPMI drivers as experimental
These drivers were merged on an experimental basis without the RPMI
specification being frozen. As a result, they may not be compatible with
the frozen version of the RPMI protocol. Additionally, their devicetree
bindings have not been reviewed and are subject to change. Warn the user
that these drivers make no compatibility guarantees, and that their
behavior and devicetree bindings may change incompatibly in future
versions of OpenSBI.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-21 18:22:47 +05:30
Samuel Holland
0c5dc12d73 platform: generic: Initialize console before other drivers
Initialize serial drivers first, so messages printed by other drivers do
not need to use the early console buffer.

Suggested-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-21 18:21:50 +05:30
Xiang W
f069301654 lib: utils: Improve rpmi_cppc_fc_db_trigger() for RV32
Improve 64-bit operation under rv32 and remove db_val_u32_hi
in rpmi_cppc_fc_db_trigger().

Signed-off-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-19 11:02:30 +05:30
Atish Patra
51dbc57fc7 lib: sbi_pmu: Verify the raw events first during event info
The raw events have same event_idx. Thus, the event info sanity check
only relies on the select mask. The raw event check should be done first
so that regular hardware events can be verified using event idx range
check.

Fixes: e434584216 ("lib: sbi_pmu: Implement SBI PMU event info function")
Signed-off-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-15 14:13:12 +05:30
Atish Patra
0928ca21bc lib: sbi_pmu: Fix the sanity check condition for hw event map
The hardware event map function invoked from platform code should
exclude any raw events as there is a separate function for the raw
events.

Fixes: d8a483fc7f ("lib: sbi_pmu: PMU raw event v2 support")
Signed-off-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-15 14:06:52 +05:30
Ben Dooks
39532d11e9 scripts/carray: change to using single awk invocation to generate .c
The shell script makes multiple call-outs to awk to get information
from the configuration file. It would be easier to just write the
whole thing in one .awk script and have the makefile altered to call
that instead.

There should be no functional difference other than the script type
and has been tested with PLATFORM=generic build. This should be both
quicker and easier to understand.

Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-15 12:39:59 +05:30
Ben Dooks
2c76548cba script/carry.sh: send error to stderr
Send the errors to stderr, otherwise they end up being
written to the file the script was redirecting to in the
Makefile

Also, use EOF block to make it easier to redirect

Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-15 12:30:50 +05:30
Ben Dooks
a36cd1b043 Makefile: remove carry output if scripts/carray.sh fails
If the script fails, we end up trying to build either
an empty or damaged .c file. Just remove it and let
gcc fail on non-existent file.

Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-15 12:30:47 +05:30
Ben Dooks
c7866d99fe top: add ~ files to .gitignore
Ignore temporary files, and avoid accidentally adding
them to a commit.

Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-15 12:30:45 +05:30
Clément Léger
b47fcd01b3 lib: sbi: sse: Fix a6 and a7 register content upon injection
The specification states that a6 contains the current hart id and
a7 contains the entry argument. This was inverted in the current
implementation.

Reported-by: Andrew Jones <andrew.jones@linux.dev>
Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-15 11:53:53 +05:30
Clément Léger
851e301098 lib: sbi: fix GLOBAL_PLAT_DEFINE
Fix GLOBAL_PLAT_0_START/END definitions. The specification states that
the beginning of the range is 0xc000 and the end is 0xffff.

Reported-by: Andrew Jones <andrew.jones@linux.dev>
Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-15 11:52:57 +05:30
Anup Patel
5545602f77 Makefile: Don't enable V-extension using -march option
Enabling V-extension using -march option causes OpenSBI boot-time
hang with LLVM compiler.

As a work-around, don't enable V-extension using -march option and
instead use a custom OpenSBI specific define inform availability of
V-extension to lib/sbi/sbi_trap_v_ldst.c.

Fixes: c2acc5e5b0 ("lib: sbi_misaligned_ldst: Add handling of vector load/store")
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2024-12-15 11:30:48 +05:30
Anup Patel
74c6ea014d lib: utils/fdt_cppc_rpmi: Fix compile error with LLVM
The following error is observed when compiling fdt_cppc_rpmi
driver using LLVM:

lib/utils/cppc/fdt_cppc_rpmi.c:87:3: error: label followed by a declaration is a C23 extension [-Werror,-Wc23-extensions]
   87 |                 u64 db_val_u64 = 0;

To fix the above issue, move the variable declaration at the
start of function.

Fixes: 591a98bdd5 ("lib: utils/cppc: Add RPMI CPPC driver")
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2024-12-15 11:28:13 +05:30
Nylon Chen
c2acc5e5b0 lib: sbi_misaligned_ldst: Add handling of vector load/store
Add misaligned load/store handling for the vector extension
to the sbi_misaligned_ldst library.

This implementation is inspired from the misaligned_vec_ldst
implementation in the riscv-pk project.

Co-developed-by: Zong Li <zong.li@sifive.com>
Signed-off-by: Zong Li <zong.li@sifive.com>
Signed-off-by: Nylon Chen <nylon.chen@sifive.com>
Reviewed-by: Andy Chiu <andy.chiu@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-06 17:43:06 +05:30
Rahul Pathak
c5a8b15e39 lib: utils/mpxy: Add RPMI client driver for MPXY
Add a generic RPMI mailbox client driver which provides a MPXY channel.
Initially, this driver only supports RPMI clock service group but can
be extended to support multiple RPMI service groups.

Signed-off-by: Rahul Pathak <rpathak@ventanamicro.com>
Co-developed-by: Anup Patel <apatel@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-06 09:26:57 +05:30
Anup Patel
32577ec3a1 lib: utils: Add simple FDT based MPXY driver framework
The generic platform can have multiple MPXY drivers so add a simple
FDT based MPXY driver framework.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-06 09:26:54 +05:30
Anup Patel
e67d91cdcc lib: sbi: Implement SBI MPXY extension
Implement the SBI MPXY extension which provides an SBI interface to
the supervisor software for send messages via MPXY framework.

Signed-off-by: Rahul Pathak <rpathak@ventanamicro.com>
Co-developed-by: Anup Patel <apatel@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-06 09:26:52 +05:30
Rahul Pathak
7939bf1329 lib: sbi: Add SBI Message Proxy (MPXY) framework
Introduce SBI Message Proxy (MPXY) framework which allows platform specific
code or drivers to register message protocol specific channels.

This framework enables the supervisor software to send messages belonging
to different message protocols via OpenSBI firmware.

Signed-off-by: Rahul Pathak <rpathak@ventanamicro.com>
Co-developed-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
Co-developed-by: Anup Patel <apatel@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-06 09:26:50 +05:30
Subrahmanya Lingappa
591a98bdd5 lib: utils/cppc: Add RPMI CPPC driver
Add RPMI based driver for CPPC register read, write and probe.

Signed-off-by: Subrahmanya Lingappa <slingappa@ventanamicro.com>
Co-developed-by: Rahul Pathak <rpathak@ventanamicro.com>
Signed-off-by: Rahul Pathak <rpathak@ventanamicro.com>
Co-developed-by: Sunil V L <sunilvl@ventanamicro.com>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-06 09:26:47 +05:30
Anup Patel
54e632b72e lib: utils: Add simple FDT based CPPC driver framework
The generic platform can have multiple CPPC drivers so add a simple
FDT based CPPC driver framework.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-06 09:26:45 +05:30
Subrahmanya Lingappa
33ee9b8240 lib: utils/hsm: Add RPMI HSM driver
The RPMI HSM service group provides set of routine to query and control
power states of a Hart. Add RPMI based Hart State Management (HSM) driver.

Signed-off-by: Subrahmanya Lingappa <slingappa@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-06 09:26:43 +05:30
Anup Patel
ff4769bf08 lib: utils: Add simple FDT based HSM driver framework
The generic platform can have multiple HSM drivers so add a simple
FDT based HSM driver framework.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-06 09:26:40 +05:30
Anup Patel
9d760b810e lib: utils/fdt: Allow dynamic registration of FDT fixup callbacks
It should possible to fixup FDT from any part of OpenSBI so add
fdt_register_general_fixup() which allows dynamic registration of
FDT fixup callbacks.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-06 09:26:38 +05:30
Subrahmanya Lingappa
fdd7263536 lib: sbi: Add optional resume address to hart suspend
Add an optional resume address to the platform specific hart suspend call.

Signed-off-by: Subrahmanya Lingappa <slingappa@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-06 09:26:35 +05:30
Subrahmanya Lingappa
13f55f33a1 lib: utils/suspend: Add RPMI system suspend driver
Add RPMI based system suspend driver.

To test this, execute the follwoing in Linux:
 $ echo mem > /sys/power/state

To wake up, execute the following command on qemu monitor terminal:
 (qemu) system_wakeup

Signed-off-by: Subrahmanya Lingappa <slingappa@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-06 09:26:32 +05:30
Anup Patel
3676324b0e lib: utils: Add simple FDT based system suspend driver framework
The generic platform can have multiple system suspend drivers so add a
simple FDT based system suspend driver framework.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-06 09:26:29 +05:30
Rahul Pathak
6a26726e08 lib/utils: reset: Add RPMI System Reset driver
Add RPMI based driver for system reset and enable it in the generic
platform defconfig

Signed-off-by: Rahul Pathak <rpathak@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-06 09:26:27 +05:30
Rahul Pathak
91f46fb47e lib/utils: Add RPMI messaging protocol and shared memory transport support
The RISC-V Platform Management Interface (RPMI) defines a messaging protocol
and shared memory based transport for bi-directional communication with an
on-chip or external microcontroller.

To support RPMI in OpenSBI, add:
1) The RPMI messaging protocol defines and helper macros
2) A FDT mailbox driver for the RPMI shared memory transport

Signed-off-by: Rahul Pathak <rpathak@ventanamicro.com>
Co-developed-by: Subrahmanya Lingappa <slingappa@ventanamicro.com>
Signed-off-by: Subrahmanya Lingappa <slingappa@ventanamicro.com>
Co-developed-by: Anup Patel <apatel@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-06 09:26:21 +05:30
Anup Patel
2244a34f0d lib: utils/mailbox: Add simple FDT based mailbox framework
Add a simple FDT based mailbox framework which is built on top of the generic
mailbox library. The phandle of FDT mailbox DT node is treated as the unique
mailbox controller ID which is required by the generic mailbox library. The
FDT based mailbox drivers will be probed on-demand from fdt_mailbox_request_chan()
called by the mailbox client drivers.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-06 09:26:19 +05:30
Anup Patel
ad846a7cb8 lib: utils/mailbox: Add generic mailbox library
Add generic mailbox library which is independent of hardware description
format. The OpenSBI platform support or mailbox drivers can register
mailbox controller instances which can be discovered and used by different
mailbox client drivers. Each mailbox controller instance has a unique ID
which can be used by mailbox client drivers for find the mailbox controller
instance. The mailbox client drivers will typically request a mailbox channel
from the mailbox controller and use it to do data transfer with the remote
end of mailbox channel.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-06 09:26:13 +05:30
Rahul Pathak
b49d67b70f lib: Increase ROOT_REGION_MAX to accomodate more memregions
As more drivers adding memregions into root domain, the current static limit
of ROOT_REGION_MAX is not sufficient. Increase the limit to accomodate more
memregions.

Signed-off-by: Rahul Pathak <rpathak@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-12-06 09:26:11 +05:30
Atish Patra
e434584216 lib: sbi_pmu: Implement SBI PMU event info function
Allow the supervisor software to query about the event using the
new function. This supports both firmware and hardware events.
The hardware event presence is verified hw_event_map which is populated
via PMU device tree node. The firmware event presence is checked through
event validation function which should take care of both standard and
platform firmware events.

Signed-off-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-02 09:52:55 +05:30
Atish Patra
05970d273c lib: sbi_pmu: Add SBI PMU event info function details.
The SBI v3.0 introduced a new function to query about the events
without invoking CFG_MATCH. This allows supervisor software to
identify which events are supported on the platform with single
SBI call instead of a CFG_MATCH for each event.

Signed-off-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-02 09:52:52 +05:30
Atish Patra
cf196d80aa lib: sbi_pmu: Remove redundant check for fw events
The pmu_validate_event already has the same check for fw events.
The validate function is called prior to the current function
to find a counter for firmware. That's why, the redudant
check can be removed from the find counter function.

Signed-off-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-02 09:52:50 +05:30
Atish Patra
d8a483fc7f lib: sbi_pmu: PMU raw event v2 support
As per the updated ISA specification and SBI PMU v3.0, lower 56
bits are available for the platform to implement mhpmeventX
encoding. Implement the PMU raw event V2 support defined in SBI
v3.0 which allows more bits for platforms to encode the raw events.

Signed-off-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-02 09:52:04 +05:30
Igor Melnikov
40e725da03 Makefile: Fix POSIX grep for multiple patterns
grep -e "-mstrict-align\|-mno-unaligned-access" makes use of GNU grep's
backslash-escaped alternation operator \| which is available in basic
regular expression syntax (BRE) mode.

However, in POSIX grep's BRE mode | is an ordinary character which, when
backslash-escaped, matches itself. Therefore, the search pattern becomes
a plain string '-mstrict-align|-mno-unaligned-access' which obviously
never matches the expected error and CC_SUPPORT_STRICT_ALIGN is always set
to y.

When cross-compiling with LLVM on amd64-unknown-openbsd7.6 host for
riscv64-unknown-elf target this results in a compilation error:

clang: error: unsupported option '-mno-unaligned-access' for target
'riscv64-unknown-elf'

Using multiple -e options for this case maintains consistent behaviour
across different grep implementations and fixes the issue.

Signed-off-by: Igor Melnikov <imel@purelymail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-12-01 12:32:18 +05:30
Samuel Holland
a387a8dff0 lib: utils/timer: Use fdt_driver for initialization
The timer driver subsystem does not need any extra data, so it can use
`struct fdt_driver` directly. The generic fdt_timer_init() performs a
best-effort initialization of all matching DT nodes.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 17:57:20 +05:30
Samuel Holland
a524f0a507 lib: utils/serial: Use fdt_driver for initialization
The serial driver subsystem does not need any extra data, so it can use
`struct fdt_driver` directly. The generic fdt_serial_init() first
attempts to match the chosen stdout device, and upon failure matches the
first available serial device in the DT. It is a fatal error if no such
device is found. This matches the behavior of fdt_driver_init_one().

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 17:52:58 +05:30
Samuel Holland
6d9ad492db lib: utils/reset: Use fdt_driver for initialization
The reset driver subsystem does not need any extra data, so it can use
`struct fdt_driver` directly. The generic fdt_reset_init() performs a
best-effort initialization of all matching DT nodes. Platform-specific
logic expects exactly one DT node to match a single driver. This is
accomplished by using fdt_driver_init_one() with a local list containing
that one driver.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 17:48:17 +05:30
Samuel Holland
1f8db2f18f lib: utils/regmap: Use fdt_driver for initialization
The regmap driver subsystem does not need any extra data, so it can use
`struct fdt_driver` directly. It always initializes the driver for a
specific DT node.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 17:45:29 +05:30
Samuel Holland
5fa510c5f6 lib: utils/ipi: Use fdt_driver for initialization
The ipi driver subsystem does not need any extra data, so it can use
`struct fdt_driver` directly. The generic fdt_ipi_init() performs a
best-effort initialization of all matching DT nodes.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 17:42:05 +05:30
Samuel Holland
333133edaa lib: utils/i2c: Use fdt_driver for initialization
The i2c driver subsystem does not need any extra data, so it can use
`struct fdt_driver` directly. It always initializes the driver for a
specific DT node.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 17:38:05 +05:30
Samuel Holland
bef8f9b806 lib: utils/gpio: Use fdt_driver for initialization
FDT gpio drivers have an extra .xlate operation, so they need to embed
the `struct fdt_driver` inside the subsystem-specific type. The gpio
subsystem always initializes the driver for a specific DT node.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 17:29:12 +05:30
Samuel Holland
10df2d6fb5 scripts/carray.sh: Allow referencing a struct member
It can be useful to embed the objects referenced by a carray inside
another struct. To avoid type punning, the generated carray code must
use the correct type for the enclosing struct and member access to
compute the desired object address.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 17:23:36 +05:30
Samuel Holland
bb008e5d27 scripts/carray.sh: Avoid useless use of cat
awk(1) takes input files as positional arguments, so there is no need
to read the file with cat(1).

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 17:17:54 +05:30
Samuel Holland
1ccc52c427 lib: utils/fdt: Add helpers for generic driver initialization
Currently, each driver subsystem contains its own code for matching
drivers against the platform's devicetree blob. This bloats firmware
size because the several FDT scanning loops are almost exact copies of
each other, and is confusing because the loops do have some subtle
differences. Furthermore, the existing match algorithm is inefficient:
it scans the FDT structure separately for each driver in the list. A
faster algorithm scans the FDT blob only once, matching all drivers in
the list for each `compatible` property seen.

Add new helpers implementing this faster algorithm. Since they must
iterate through the list of drivers, the driver structure cannot be
opaque. However, since the driver list is an array of pointers, the
`struct fdt_driver` can be embedded in a subsystem-specific driver
structure if needed. These three helpers cover all existing use cases
for driver initialization within OpenSBI.

An additional benefit of centralized driver initialization is the
consistent use of fdt_node_is_enabled().

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 17:13:05 +05:30
Samuel Holland
df1c100001 treewide: Make carray arrays const and NULL-terminated
This allows the compiler to generate significantly better code, because
it does not have to maintain either the loop counter or loop limit. Plus
there are half as many symbols to relocate. This also simplifies passing
carray arrays to helper functions.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 17:09:17 +05:30
Nick Hu
23ef9c5f00 sbi: fwft: clear the config lock when warm boot
The hotplug cpu should clear the fwft config's SBI_FWFT_SET_FLAG_LOCK
in the warm boot flow otherwise the cpu can't set the menvcfg.sse by
SBI_EXT_FWFT_SET sbi call and cause the illegal instruction when
accessing the CSR_SSP in kernel.

Signed-off-by: Nick Hu <nick.hu@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 12:13:38 +05:30
Samuel Holland
111772353f lib: sbi_irqchip: Set the IRQ handler when registering a chip
In addition to saving some code size, this moves the decision about
setting the top-level external interrupt handler to the irqchip core,
not the specific driver, which would be needed to support chained
interrupt handlers.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 11:51:56 +05:30
Samuel Holland
678f5909a3 platform: Drop irqchip warm init and exit hooks
Now that driver lifecycle is managed from within the SBI irqchip core,
platforms need only to initialize the driver once during cold init.
Remove the remaining platform hooks that are no longer used.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 11:46:36 +05:30
Samuel Holland
2dd6eaf680 lib: sbi_irqchip: Call driver warm_init from SBI core
Currently, each platform keeps track of which irqchip driver is in use
and calls its warm init function. Since the generic platform may use
multiple irqchip drivers, it has logic to track an array of drivers.

The code is simplified and made common across platforms by treating warm
init and exit as properties of the driver, not the platform. Then the
platform's only role is to select and prepare a driver during cold boot.

For now, only add a .warm_init hook, since none of the existing drivers
need an .exit hook. It could be added in the future if needed.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 11:40:17 +05:30
Samuel Holland
e3e5686ef9 lib: sbi_irqchip: Register devices during cold init
Have the SBI irqchip core keep track of registered irqchip devices. This
is useful for any callbacks the irqchip driver may have, such as for
warm initialization, the external interrupt handler function, and any
future support for handling external interrupts (beyond IPIs) in M-mode.

This improves on the tracking done in fdt_irqchip.c, as it tracks device
instances, not just drivers, so callbacks can target a specific device.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 11:37:25 +05:30
Samuel Holland
56fddce83f lib: utils/irqchip: Move per-hart data from fdt_plic to plic
The per-hart PLIC pointer is not really specific to FDT platforms. Move
it into the main driver and drop the extra wrapper functions.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 11:35:01 +05:30
Samuel Holland
c6c22f00f4 lib: utils/irqchip: plic: Common PM save/restore
Move the PLIC save/restore functions inside the driver, so they can be
reused on any platform that needs them. The memory needed to store the
PLIC context is also allocated by the driver. The PM data cannot be
completely encapsulated, as some platforms (including Allwinner D1) need
to program the IRQ enable status to a sideband interrupt controller for
wakeup capability.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 11:28:38 +05:30
Samuel Holland
69448a0790 lib: utils/irqchip: plic: Provide a hartindex to context map
This removes platform-specific arguments to plic_warm_irqchip_init(),
which makes the driver independent from the platform after cold init,
and allows for further refactoring.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 09:36:46 +05:30
Samuel Holland
c26e3fd2ed lib: utils/irqchip: plic: Move delegation to base PLIC driver
This needs to be in the base PLIC driver as part of the power management
save/restore flow.

This is also in preparation for moving the PLIC information in the
scratch area to the base PLIC driver. After that change, the FDT PLIC
layer will be unable to look up the `struct plic_data` after cold boot.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 09:35:11 +05:30
Samuel Holland
a786aed08d lib: utils/irqchip: plic: Allow enabling IRQs by default
Unlike other platforms, Ariane and OpenPiton enable all IRQs by default.
This was described in commit b44e844880 ("Add support for Ariane FPGA
SoC") as "due to some issue of the design." Add this workaround behind a
flag in plic_warm_irqchip_init(), so every platform can use the same
warm init function.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-28 09:35:10 +05:30
Samuel Holland
86d2c1797a platform: Drop IPI warm init and exit hooks
Now that the SBI IPI core clears IPIs at warm boot in a generic way,
none of the drivers or platforms use these hooks, and we can remove
them. Platforms need only to initialize the driver once during cold
init. If other hooks are needed in the future, they can be added to
struct sbi_ipi_device.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-11 18:21:04 +05:30
Samuel Holland
693afc818f lib: sbi_ipi: Move initial IPI clear to sbi_ipi_init()
sbi_ipi_init() expects the platform warm init function to clear IPIs
on the local hart, but there is already a generic function to do this.
After this change, none of the existing drivers need a warm init
callback.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-11 18:18:35 +05:30
Samuel Holland
be9752a071 lib: sbi_ipi: Make .ipi_clear always target the current hart
All existing users of this operation target the current hart, and it
seems unlikely that a future user will need to clear the pending IPI
status of a remote hart. Simplify the logic by changing .ipi_clear (and
its wrapper sbi_ipi_raw_clear()) to always operate on the current hart.

This incidentally fixes a bug introduced in commit 78c667b6fc ("lib:
sbi: Prefer hartindex over hartid in IPI framework"), which changed the
.ipi_clear parameter from a hartid to a hart index, but failed to update
the warm_init functions to match.

Fixes: 78c667b6fc ("lib: sbi: Prefer hartindex over hartid in IPI framework")
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-11 18:17:15 +05:30
Zhang RunMin
db8f03e512 include: sbi: Fix typo error
Fix typo in comments describing SBI_SCRATCH_FW_HEAP_SIZE_OFFSET.

Signed-off-by: Zhang RunMin <runmin.zhang@ingenic.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-11 17:53:32 +05:30
Inochi Amaoto
5d4e3fb2ee platform: introduce DT-based configurable heap size
The default heap size will work for most platforms, but for some
special platforms, the heap is too small to hold all the information
or is too big so that it take too much ram. Introduce configurable
heap should solve this problem and make all generic platforms happy.

Add DT-based heap-size for the generic platform.

Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
Reviewed-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-11 17:48:45 +05:30
Inochi Amaoto
dcb68dd17d platform: ensure enough heap size with debug triggers extension
DBTR introduce a big heap allocation to store hart state, this is
allocated percpu and needs big space when CPU number is high.

Increase the percpu part to fix this problem, and decrease the
fixed part to avoid too big heap size.

Fixes: 97f234f (lib: sbi: Introduce the SBI debug triggers extension support)
Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
Reviewed-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-11 17:40:22 +05:30
Tim Hutt
701948bdec docs: add example of building the Linux kernel
Slightly expand the QEMU docs to explain how to build the flat Linux kernel image.

Signed-off-by: Tim Hutt <tdhutt@gmail.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-09 14:30:41 +05:30
Kele Zhang
0171cfcc70 Makefile: enable --gc-sections
The --gc-sections option enables the linker to perform garbage
collection of unreferenced code and data, thereby reducing the binary
size.

The -ffunction-sections option will place each function into a separate
section, so it is necessary to add .text.* to the linker script.

Signed-off-by: Kele Zhang <zhangcola2003@gmail.com>
Signed-off-by: Yuan Tan <tanyuan@tinylab.org>
Signed-off-by: Zhangjin Wu <falcon@tinylab.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-06 16:29:39 +05:30
Hui Min Mina Chou
369c64517e top: Add .editorconfig to set basic coding styles
EditorConfig [1] ensures consistent coding styles for developers
collaborating on the same project across various editors and IDEs. By
adopting the Linux project's .editorconfig settings [2] and applying
them to OpenSBI, it helps users maintain uniform indentation across
different IDEs and version control systems, improving development
efficiency.

The main difference from Linux project is the addition of
'trim_trailing_whitespace = true', which removes trailing whitespace
before newlines. This change affects only three files in OpenSBI, but
it improves overall code consistency.

 $ grep -nr "\s$" --include={*.{c,dts,h,lds,ldS,mk,s,S.py},Kconfig,Makefile,Makefile.*} .
 ./include/sbi_utils/fdt/fdt_fixup.h:4: * Implement platform specific DT fixups on top of libfdt.
 ./platform/generic/platform.c:79: * The fw_platform_coldboot_harts_init() function is called by fw_platform_init()
 ./platform/generic/platform.c:81: * according to the DT property "cold-boot-harts" in "/chosen/opensbi-config"

Link: https://editorconfig.org/ [1]
Link: https://lore.kernel.org/lkml/ZbAbmchIO8Cd5hNd@surfacebook.localdomain/T/ [2]
Signed-off-by: Hui Min Mina Chou <minachou@andestech.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-06 16:25:37 +05:30
Samuel Holland
9782b8847d lib: utils/regmap: Use FDT node offset as regmap ID
Since the FDT is not modified during driver initialization, node offsets
are just as suitable as phandles for use as identifiers: they are stable
and unique. With this change, it is no longer necessary to pass the
phandle to the driver init functions, so these init functions now use
the same prototype as other kinds of drivers.

This matches what is already done for I2C adapters.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-05 17:54:41 +05:30
Samuel Holland
d71150ee70 lib: utils/gpio: Use FDT node offset as GPIO chip ID
Since the FDT is not modified during driver initialization, node offsets
are just as suitable as phandles for use as identifiers: they are stable
and unique. With this change, it is no longer necessary to pass the
phandle to the driver init functions, so these init functions now use
the same prototype as other kinds of drivers.

This matches what is already done for I2C adapters.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-05 17:54:39 +05:30
Samuel Holland
598cf961d8 lib: utils/gpio: Remove fdt_gpio_driver() function
This function looks up a chip's driver by matching known drivers against
chip->driver, but that is equivalent to using chip->driver directly.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-05 17:54:37 +05:30
Samuel Holland
99b01ab610 platform: Drop timer warm init and exit hooks
Now that driver lifecycle is managed from within the SBI timer core,
platforms need only to initialize the driver once during cold init.
Remove the remaining platform hooks that are no longer used.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-05 17:39:31 +05:30
Samuel Holland
4500828743 lib: sbi_timer: Call driver warm_init from SBI core
Currently, the platform's timer device is tracked in two places: the
core SBI implementation has `timer_dev`, and the FDT timer layer has
`current_driver`. The latter is used for warm initialization of the
timer device. However, this warm init is not specific to FDT-based
platforms; other platforms call exactly the same functions from the
same point in the boot sequence.

The code is simplified and made common across platforms by treating warm
init and exit as properties of the driver, not the platform. Then the
platform's only role is to select and prepare a driver during cold boot.

For now, only add a .warm_init hook, since none of the existing drivers
need an .exit hook. It could be added in the future if needed.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-11-05 17:29:13 +05:30
Vladimir Kondratiev
1a2e507d23 lib: sbi: fix number of PMP entries detection
CSR_PMPADDRn lower bits may read all-0 or all-1, depending on
the configuration. For TOR it is all-0, for NAPOT - all-1.

Thus if PMP entry was pre-configured as NAPOT, original code would
stop scanning because value read back not equal to the written one.

Mask lower bits before comparison to fix this

Signed-off-by: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-10-28 11:05:14 +05:30
Samuel Holland
62447cd7aa include: sbi: Optimize reads of mhartid and mscratch
csr_read() is marked as volatile and clobbering memory, which is
generally the safe thing to do. However, these two CSRs do not have any
side effects, and the values returned do not change between calls. The
compiler can generate better code if we allow it to reorder calls to
these functions and cache the return value. Introduce csr_read_relaxed()
for this use case.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-10-28 10:51:37 +05:30
Samuel Holland
3e0c170397 lib: utils/gpio: designware: Allocate chips on the heap
This reduces firmware size for SoCs which do not use this driver.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-10-28 10:40:25 +05:30
Clément Léger
c46a937fd9 lib: sbi: add Smdbltrp ISA extension support
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>
2024-10-26 00:00:12 +05:30
Clément Léger
3bc86854ab lib: sbi: implement firmware feature SBI_FWFT_DOUBLE_TRAP
Add support for double trap firmware feature.

Link: https://lists.riscv.org/g/tech-prs/message/985 [1]
Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2024-10-25 23:59:27 +05:30
Clément Léger
b2f77f5fa8 lib: sbi: fwft: factorize menvcfg read/write
MENVCFG access will be used as well for double trap, landing pad and
shadow stack fwft support. Factorize that in a common function.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2024-10-25 23:58:58 +05:30
Clément Léger
b0a7e4b853 lib: sbi: send a double trap SSE event to supervisor
In case the double trap handler is called and the double trap happened
in supervisor mode, send a double trap SSE event.

NOTE: this commit depends on the ratification of the new SSE event
id for double trap [1].

Link: https://lists.riscv.org/g/tech-prs/message/985 [1]
Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2024-10-25 23:58:39 +05:30
Clément Léger
9c78593269 lib: sbi: add Ssdbltrp ISA extension support
Add Ssdbltrp trap handler support for S-mode double trap handling. If
the trap is received while in VS-mode, then the trap is redirected to
S-mode. If caught while in HS-mode, then an error is returned to the top
trap handler which will panic.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2024-10-25 23:58:00 +05:30
Clément Léger
80656bdb1d lib: sbi: factorize previous mode computation
Previous privilege mode retrieval from mstatus is done at different
places, factorize it rather than copy/pasting it again.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2024-10-25 23:53:18 +05:30
Clément Léger
daa282573f lib: sbi: factorize previous virtualization mode read from regs
The same pattern is used at multiple places to verify in which mode
the exception was actually taken. Factorize it.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2024-10-25 23:52:51 +05:30
Himanshu Chauhan
b919daf495 lib: sbi: Add support to mask/unmask SSE events
Add functions to globally mask/unmask supervisor software events
on the calling hart.

Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-10-25 23:04:43 +05:30
Anup Patel
ebbd276146 docs: Remove hartindex_to_context_table from domain_support.md
The hartindex_to_context_table field is no longer part of sbi_domain
so remove related documentation from domain_support.md.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-10-25 23:00:15 +05:30
Anup Patel
f609fd8584 lib: sbi_domain: Use domain data support for per-domain hart context
The per-domain hartindex_to_context_table[] is yet another per-domain
data required for implementing hart entry into (or exit from) domain.

Use the recently added domain data support for per-domain hart context
so that a dedicated hartindex_to_context_table[] in struct sbi_domain
is not needed.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Yu Chien Peter Lin <peterlin@andestech.com>
2024-10-25 23:00:10 +05:30
Anup Patel
81d79913a0 lib: sbi: Introduce domain data
Different parts of OpenSBI require their own per-domain data so
introduce domain data (or sbi_domain_data) which can be registered
by any part of OpenSBI. Using the domain data, the domain framework
will create a data pointer for every domain which can be used to
maintain some per-domain state.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Yu Chien Peter Lin <peterlin@andestech.com>
2024-10-25 23:00:07 +05:30
Anup Patel
65d4e9be95 include: sbi: Remove cyclic include in sbi_domain_context.h
The sbi_domain_context.h includes sbi_domain.h and the sbi_domain.h
also includes sbi_domain_context.h. Remove this cyclic include in
sbi_domain_context.h.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2024-10-25 23:00:04 +05:30
Anup Patel
2d517fce9b lib: utils/fdt: Use sbi_domain_memregion_init() when parsing domains
Use sbi_domain_memregion_init() at the time of parsing domains from
FDT so that sbi_domain_memregion_init() is always used for setting
up all memregions.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2024-10-25 23:00:02 +05:30
Anup Patel
36c1e4064f lib: sbi_domain: Make sbi_domain_root_add_memregion() as local function
The sbi_domain_root_add_memregion() is only used within sbi_domain
implementation so rename and make it a local function.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2024-10-25 23:00:00 +05:30
Anup Patel
dc5d747af8 lib: utils/irqchip: Use sbi_domain_root_add_memrange() for APLIC
The sbi_domain_root_add_memrange() should be preferred for creating
multiple memregions over a range. Update APLIC driver to use
sbi_domain_root_add_memrange() instead of explicitly registering
memregions.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2024-10-25 22:59:58 +05:30
Anup Patel
abc68e881d lib: utils/irqchip: Use sbi_domain_root_add_memrange() for IMSIC
The sbi_domain_root_add_memrange() should be preferred for creating
multiple memregions over a range. Update IMSIC driver to use
sbi_domain_root_add_memrange() instead of explicitly registering
memregions.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2024-10-25 22:59:56 +05:30
Anup Patel
8576ca4234 lib: utils/ipi: Use sbi_domain_root_add_memrange() for ACLINT mswi
The sbi_domain_root_add_memrange() should be preferred for creating
multiple memregions over a range. Update ACLINT mswi driver to use
sbi_domain_root_add_memrange() instead of explicitly registering
memregions.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2024-10-25 22:59:54 +05:30
Xiang W
2ffa0a153d lib: sbi: fix missing high 32bits when sbi_cppc_write on rv32
sbi_cppc_write was writing to the a1 register only, which under rv32
would cause the high 32 bits to always be 0. This patch fixes that.

Closes: https://github.com/riscv-software-src/opensbi/issues/334

Signed-off-by: Xiang W <wxjstz@126.com>
Reported-by: Wesley Norris <repnop@outlook.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-27 13:09:51 +05:30
dong.yang
3e141a6950 firmware: fw_base.S: fix multi-core boot bug.
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>
2024-09-27 11:05:37 +05:30
Elyes Haouas
7b3de48cd5 include: sbi: Don't unconditionally define '__always_inline'
Update __always_inline macro define to fix opensbi upstream
build for coreboot.
Refer, https://qa.coreboot.org/job/coreboot-gerrit/257449/testReport/junit/(root)/clang/EMULATION_QEMU_RISCV_RV64_/

Closes: https://github.com/riscv-software-src/opensbi/issues/366
Signed-off-by: Elyes Haouas <ehaouas@noos.fr>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-09-27 10:52:32 +05:30
Samuel Holland
bfa9f9aee7 Makefile: Make .carray.c files depend on carray.sh
Force carray C source files to be regenerated when the script changes,
since their contents depend on the script's output.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-27 10:47:51 +05:30
Samuel Holland
cae230c935 lib: utils/ipi: Fix hartid wrongly used as hart index
Since commit 78c667b6fc ("lib: sbi: Prefer hartindex over hartid in
IPI framework"), The .ipi_clear callback functions take a hart index,
not a hartid. However, these warm_init functions were never updated.

Fixes: 78c667b6fc ("lib: sbi: Prefer hartindex over hartid in IPI framework")
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-27 10:42:24 +05:30
Samuel Holland
9155024972 lib: sbi: Remove unused hartid parameters
None of these functions use their hartid parameter.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-26 16:29:29 +05:30
Samuel Holland
3962be84d4 lib: sbi: Update sbi_{entry,init}_count() to take a hart index
All callers already have the hartindex available, so this removes a
hartid to hartindex conversion.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-26 16:29:27 +05:30
Samuel Holland
9f86524b58 lib: sbi: Update sbi_domain_is_assigned_hart() to take a hart index
This removes redundant hartid to hartindex conversions from four call
sites and provides a net reduction in code size.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-26 16:29:25 +05:30
Samuel Holland
fe153c5516 lib: sbi: Use sbi_hartmask in sbi_hsm_hart_interruptible_mask()
This removes several hartid/hartindex conversions, as well as two loops
through the mask for broadcast IPIs.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-26 16:28:18 +05:30
Samuel Holland
ebe0f31446 lib: sbi: Update __sbi_hsm_hart_get_state() to take a hart index
This removes some hartindex conversions in sbi_system_suspend(), but is
mostly intended to support refactoring sbi_hsm_hart_interruptible_mask()
to work exclusively with struct sbi_hartmask.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-26 11:30:04 +05:30
Samuel Holland
97b8038916 lib: sbi: Simplify halt broadcast logic
Use the IPI .update callback to exclude the local hart. This allows
reusing the normal logic for broadcasting an IPI to all active harts.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-26 11:16:53 +05:30
Samuel Holland
633e7cbd50 lib: sbi_ecall_legacy: Use SBI v0.2 encoding for "all harts"
This simplifies the logic so that sbi_hsm_hart_interruptible_mask() is
only called from one place (sbi_ipi_send_many()). A minor functional
change is that the legacy functions can now affect more than XLEN harts
when targeting all harts.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-26 10:44:34 +05:30
Samuel Holland
7f5fa9f9a4 lib: utils/irqchip: Look up IMSIC data by hart index
This avoids needing to map a hartid to a hart index.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-25 18:06:59 +05:30
Samuel Holland
d73a4c741c lib: sbi_sse: Cache the event's target hart index
This avoids needing to map the target hartid to a hart index when
enabling or disabling an event, and provides a net code size reduction.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-25 18:04:25 +05:30
Samuel Holland
15c4e285db lib: sbi: Use current_hartindex() where possible
This avoids calls to the expensive sbi_hartid_to_hartindex() function
and also makes the firmware smaller.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-25 12:03:30 +05:30
Samuel Holland
9d7a983060 include: sbi: Store the hart index in struct sbi_scratch
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>
2024-09-25 12:00:47 +05:30
Samuel Holland
4ac1818197 lib: sbi_init: Remove obsolete hartid check
This check has been obsolete since commit c51f02cf14 ("include:
sbi_platform: Introduce HART index to HART id table"). It originally
filtered out harts that were disabled in the FDT, but those harts are
omitted from the hart_index2id table, so they will hang in fw_base.S
after the "Find HART index" loop and never enter sbi_init().

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-25 10:55:30 +05:30
Samuel Holland
7c40909159 firmware: Simplify FDT header endianness conversion
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>
2024-09-25 09:46:35 +05:30
Deepak Gupta
7179e36ce7 lib: sbi: fwft: implement landing pad and shadow stack fwft interface
Supervisor software can enable control flow integrity features for itself
using fwft feature `SBI_FWFT_LANDING_PAD` and `SBI_FWFT_SHADOW_STACK`.
This patch implements the mechanism to enable both these fwft.

Signed-off-by: Deepak Gupta <debug@rivosinc.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Clément Léger <cleger@rivosinc.com>
2024-09-23 19:02:48 +05:30
Deepak Gupta
110524441a lib: sbi: sw check exception delegation
zicfiss and zicfilp introduces new exception (cause=18). Delegate this
exception to S mode because cfi violations in U / S will be reported
via this exception.

Signed-off-by: Deepak Gupta <debug@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
2024-09-23 18:59:24 +05:30
Deepak Gupta
c0804ed49a lib: sbi: add zicfilp/zicfiss and elp cfi state reflect back in status
This patch adds support to check for zicfilp / zicfiss extension.

zicfilp record status of hart's ELP state in *status csr. Missing landing
pad sets MPELP in mstatus. When SBI is redirecting back to S/VS/HS, SPELP
is set in sstatus/vsstatus.

Signed-off-by: Deepak Gupta <debug@rivosinc.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2024-09-23 18:58:04 +05:30
Deepak Gupta
6758a756c4 include: adding support for Zicfilp / Zicfiss encodings
Zicfilp / Zicfiss extension (see link) introduces b2 (LPE) in menvcfg CSR to
enable landing pads and b3 (SSE) in menvcfg CSR to enable shadow stack and
landing pad for privilege less than M. Additionally extension introduces new
bits in *status for recording landing pad state and a new exception type
`software check exception` with cause=0x12.

Link: https://github.com/riscv/riscv-cfi

Signed-off-by: Deepak Gupta <debug@rivosinc.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
2024-09-23 18:55:07 +05:30
Zong Li
570b9ae89a include: sbi_bitops: add ULL version for BIT and GENMASK
Add BIT_ULL and GENMASK_ULL for dealing with 64-bits data on
32-bits CPU, then we don't need to separate the operation to
low part and high part. For instance, the MMIO register is
64 bits wide.

Signed-off-by: Zong Li <zong.li@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-23 18:33:02 +05:30
Samuel Holland
040fcf49ab lib: sbi_domain_context: Fix file permissions
These C source files should not be marked as executable.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-23 18:26:47 +05:30
Samuel Holland
beef2f6937 lib: sbi: Respect scounteren when emulating the time CSR
This optimization creates a correctness issue, as it prevents supervisor
software from restricting VS-mode or U-mode access to the time CSR for
its own purposes.

Closes: https://github.com/riscv-software-src/opensbi/issues/370
Fixes: ebc8ebc0f8 ("lib: sbi: Improve HPM CSR read/write emulation")
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-23 18:12:39 +05:30
Atish Patra
00093a2000 docs: Remove github PR as an option
OpenSBI development workflow is mailing list based from the
beginning. Initially, github PRs were added as an option but it turned
out that it is not feasible to support both github PR and mailing list
based workflows. Hence, all the PRs has been redirected to use the
mailing list from a long time. In fact, it is source of confusion to
have both options.

Update the documentation to reflect the reality.

Signed-off-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-23 17:55:30 +05:30
Samuel Holland
1cb234b1c9 lib: sbi: fwft: add support for SBI_FWFT_POINTER_MASKING_PMLEN
Add support for controlling the pointer masking mode on harts which
support the Smnpm extension. This extension can only exist on harts
where XLEN >= 64 bits. This implementation selects the mode with the
smallest PMLEN that satisfies the caller's requested lower bound.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-23 17:50:40 +05:30
Samuel Holland
ebfaf1974e lib: sbi: Fix writes to emulated 32-bit htimedelta CSR
Writes to the low half CSR should not affect the high half of the value.
Make this separation explicit by writing to the delta in memory as two
adjacent XLEN-sized values.

Fixes: 1e9f88889f ("lib: Emulate HTIMEDELTA CSR for platforms not having TIME CSR")
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-20 21:52:06 +05:30
Samuel Holland
65f04badf7 lib: sbi: Use a linked list to track domains
This removes the compile-time limit on the number of domains. It also
reduces firmware size by about 200 bytes by removing the lookup table.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-20 21:40:32 +05:30
Samuel Holland
792715e4f3 include: sbi_domain: Fix incorrect comments
These comments are inaccurate as of commit db56341dfa ("lib: sbi:
Allow platforms to provide root domain memory regions"), which modified
root domain registration to go through sbi_domain_register() like other
domains.

Fixes: db56341dfa ("lib: sbi: Allow platforms to provide root domain memory regions")
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-09-20 21:16:41 +05:30
Anup Patel
c4940a9517 platform: generic: Fix fw_platform_coldboot_harts_init() function
It is possible that the OpenSBI config DT node is present but
the "cold-boot-harts" DT property is not present. In this case,
the fw_platform_coldboot_harts_init() will do nothing which
in-turn causes OpenSBI firmware hang at boot time.

To address the above issue, fallback to the default approach
when the "cold-boot-harts" DT property is not present.

Fixes: 67ce5a763c ("platform: generic: Add support for specify coldboot harts in DT")
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
2024-08-27 10:52:03 +05:30
Zhang RunMin
ef4520b1c6 lib: Delete redundant ulong
In `csr_read_allowed` and `csr_write_allowed` macros, has already
converted second param to `ulong`. So delete redundant `ulong`
where uses csr_read/write_allowed macros.

Signed-off-by: Zhang RunMin <runmin.zhang@ingenic.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 14:42:14 +05:30
Gregor Haas
b0ad9e0bdd lib: utils: fdt_domain: Make opensbi-domain optional in CPU node
The domain_support.md documentation states that "the HART to domain instance
assignment can be parsed from the device tree using *optional* DT property
opensbi-domain in each CPU DT node". However, the current implementation does
not treat this parameter as optional when determining which HARTs to assign to
a freshly discovered domain from the device tree, causing an effect where every
HART in the system must be explicitly assigned to a domain only if a domain is
specified in the device tree. Instead, this patch simply ignores CPUs that do
not specify a domain, and does not attempt to assign them into the recently
discovered domain.

Signed-off-by: Gregor Haas <gregorhaas1997@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 14:08:00 +05:30
Daniel Henrique Barboza
c5b6ebd141 Makefile: fix OPENSBI_VERSION_GIT build with submodules
When building OpenSBI via a submodule, OPENSBI_VERSION_GIT can be left
unset in case '.git' isn't a dir. This is the case when building OpenSBI
as a QEMU submodule:

$ cat .git
gitdir: ../../.git/modules/roms/opensbi

As a result, building OpenSBI tag v1.5.1 in QEMU will result in a binary
that will have "OpenSBI v1.5" as a banner.

Use "git rev-parse --git-dir" instead of checking if '.git' is a dir to
detect if the current dir is a git repo.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:59:05 +05:30
Clément Léger
70f3441452 lib: sse: remove unused sse_inject_out() parameter
This parameters was a remnant of a previous version, remove it now that
it is unused.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:15:58 +05:30
Yu Chien Peter Lin
a44df8024b util: atcsmu.c: modify sbi_printf() formatting
Beautify multi-line printing.

Signed-off-by: Leo Yu-Chi Liang <ycliang@andestech.com>
Reviewed-by: Yu Chien Peter Lin <peterlin@andestech.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:10:36 +05:30
Leo Yu-Chi Liang
f7a625884c util: atcsmu.c: fix typo "%s/hard/hart/"
%s/hard/hart

Signed-off-by: Leo Yu-Chi Liang <ycliang@andestech.com>
Reviewed-by: Yu Chien Peter Lin <peterlin@andestech.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:10:35 +05:30
Samuel Holland
8cb7f89d7c lib: utils/fdt: Add fdt_get_address_rw() helper
Help tracking the lifecycle of the FDT blob by indicating which parts of
the firmware modify it, and thus invalidate any previously-obtained
offsets or pointers to data inside the blob.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:03:04 +05:30
Samuel Holland
c36801841e lib: utils/serial: Pass the FDT to fdt_serial_init()
Indicate that this function does not modify the FDT blob, and
deduplicate the call to fdt_get_address().

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:03:01 +05:30
Samuel Holland
fa6dfce017 lib: utils/reset: Pass the FDT to fdt_reset_init()
Indicate that this function does not modify the FDT blob, and
deduplicate the call to fdt_get_address().

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:02:58 +05:30
Samuel Holland
6e5db7b09c platform: generic: Pass FDT to early/final_init overrides
Several of these override functions access the FDT blob. Explicitly
indicate which callbacks are allowed to modify the FDT blob by passing
the parameter as a possibly-const pointer. This also reduces code size
by deduplicating the call to fdt_get_address().

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:02:54 +05:30
Samuel Holland
3f964652d9 platform: generic: Constify FDT pointers in fw_platform_init()
Indicate that none of these functions modify the devicetree by
constifying the parameter type.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:02:51 +05:30
Samuel Holland
b15cc7715a lib: utils/timer: Constify FDT pointers in parsing functions
Indicate that none of these functions modify the devicetree by
constifying the parameter type.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:02:48 +05:30
Samuel Holland
bd76eb4950 lib: utils/serial: Constify FDT pointers in parsing functions
Indicate that none of these functions modify the devicetree by
constifying the parameter type.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:02:46 +05:30
Samuel Holland
57a0479302 lib: utils/reset: Constify FDT pointers in parsing functions
Indicate that none of these functions modify the devicetree by
constifying the parameter type.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:02:42 +05:30
Samuel Holland
1bbda9b26f lib: utils/regmap: Constify FDT pointers in parsing functions
Indicate that none of these functions modify the devicetree by
constifying the parameter type.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:02:39 +05:30
Samuel Holland
7df1c8126f lib: utils/irqchip: Constify FDT pointers in parsing functions
Indicate that none of these functions modify the devicetree by
constifying the parameter type.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:02:36 +05:30
Samuel Holland
d561418f22 lib: utils/ipi: Constify FDT pointers in parsing functions
Indicate that none of these functions modify the devicetree by
constifying the parameter type.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:02:33 +05:30
Samuel Holland
039e810437 lib: utils/i2c: Constify FDT pointers in parsing functions
Indicate that none of these functions modify the devicetree by
constifying the parameter type.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:02:28 +05:30
Samuel Holland
c585354380 lib: utils/gpio: Constify FDT pointers in parsing functions
Indicate that none of these functions modify the devicetree by
constifying the parameter type.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:02:27 +05:30
Samuel Holland
33ba4e0567 lib: utils/fdt: Constify FDT parsing functions
Distinguish between functions which modify the devicetree and those
which only extract information from it. Other than the iterators in
fdt_domain.c, this is a mechanical conversion.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:02:25 +05:30
Samuel Holland
f229a32828 lib: utils/regmap: Fix typo in comment
Balance the quotation marks; double quotes are idiomatic here.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:02:23 +05:30
Samuel Holland
bcb81f0cbe lib: utils/fdt: Fix fdt_add_cpu_idle_states() prototype
The function prototype should use the same parameter name as the
documentation and the function definition.

Fixes: 33bf917460 ("lib: utils: Add fdt_add_cpu_idle_states() helper function")
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-24 13:02:21 +05:30
Yu Chien Peter Lin
56183ca609 lib: utils: fdt_domain: Use consistent device-tree address when next-arg1 is missing
The diagram shown below illustrates the boot-flow involving OP-TEE OS
initialization.

    (1)-----------+
     | U-Boot SPL |
     +------------+
         |
         v
    (2)-------------------------------------------------------------+
     | OpenSBI (fw_dynamic)                                         |
     |                (4)------------------------+                  |
     |                 | optee dispatcher driver |                  |
     +-----------------+-------^---------|-------+------------------+
M-mode   |                     |         |
---------+--[trusted domain]---+----.----+--[untrusted domain]-------
S-mode   |  (coldboot domain)  |    |    |
         v                     |    |    v
    (3)---------------------------+ |(5)----------------------------+
     | OP-TEE OS                  | | | U-Boot                      |
     +----------------------------+ | +-----------------------------+
                                    |    |
                                    |    v
                                    |(6)----------------------------+
                                    | | Linux                       |
                                    | +-----------------------------+

As OP-TEE OS has device-tree node fixups that need to be passed
through to the next boot stages, e.g. the reserved memory node:

  reserved-memory {
    #address-cells = <2>;
    #size-cells = <2>;
    ranges;
    optee_core@f1000000 {
      no-map;
      reg = <0x0 0xf1000000   // OP-TEE OS base address
             0x0 0x01000000>;
    };
    <...>
  };

Instead of using 0x0 as the default value, allow identical next-arg1
to be used by non-coldboot domain (i.e., untrusted domain) when the
property is not provided.

Also, update the description of next-arg1 property in the document.

Signed-off-by: Yu Chien Peter Lin <peterlin@andestech.com>
Reviewed-by: Alvin Chang <alvinga@andestech.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-23 14:17:29 +05:30
Ben Zong-You Xie
3d1f53b173 platform: generic: andes: add a new Andes SBI call to free a PMA entry
Add a new Andes SBI call to free a PMA entry, and reset the memory
attributes for the corresponding NAPOT region.

Signed-off-by: Ben Zong-You Xie <ben717@andestech.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-23 14:10:30 +05:30
Ben Zong-You Xie
aa56084c4d platform: generic: andes: add a new Andes SBI call to set up a PMA entry
Implement a new Andes SBI call, which is to set up a NAPOT region
with given memory attributes.

Signed-off-by: Ben Zong-You Xie <ben717@andestech.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-23 14:08:19 +05:30
Ben Zong-You Xie
4a72abb5f4 platform: generic: andes: add Andes SBI call to probe Andes PMA feature
Add a new Andes SBI call to check whether PPMA is supported by hardware
or not.

Signed-off-by: Ben Zong-You Xie <ben717@andestech.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-23 14:05:39 +05:30
Ben Zong-You Xie
17100394f9 platform: generic: Kconfig: add the description for Andes PMA feature
Describe Andes PPMA in the config option, and select it for AE350
platform.

Signed-off-by: Ben Zong-You Xie <ben717@andestech.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-23 14:03:45 +05:30
Dongdong Zhang
d4322eebd0 lib: sbi: Enhance CSR Handling in system_opcode_insn
- Completed TODO in `system_opcode_insn` to ensure CSR read/write
  instruction handling.
- Refactored to use new macros `GET_RS1_NUM` and `GET_CSR_NUM`.
- Updated `GET_RM` macro and replaced hardcoded funct3 values with
  constants (`CSRRW`, `CSRRS`, `CSRRC`, etc.).
- Removed redundant `GET_RM` from `riscv_fp.h`.
- Improved validation and error handling for CSR instructions.

This patch enhances the clarity and correctness of CSR handling
in `system_opcode_insn`.

Signed-off-by: Dongdong Zhang <zhangdongdong@eswincomputing.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-23 13:36:49 +05:30
Gregor Haas
b9c091ed89 lib: sbi: Implement aligned memory allocators
This change adds a simple implementation of sbi_aligned_alloc(), for future use
in allocating aligned memory for SMMTT tables.

Signed-off-by: Gregor Haas <gregorhaas1997@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-09 08:51:27 +05:30
Gregor Haas
cda0014795 lib: sbi: Allocate from beginning of heap blocks
In the next commit, we'll add a new sbi_memalign() function. In order to
allocate aligned memory, we'll sometimes need to allocate from the middle of a
heap block, effectively splitting it in two. Allocating from the beginning of a
heap block in the nonaligned case more closely matches this behavior, reducing
the complexity of understanding the heap implementation.

Signed-off-by: Gregor Haas <gregorhaas1997@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-09 08:51:26 +05:30
Gregor Haas
8b898c4e50 lib: sbi: Support multiple heaps
The upcoming SMMTT implementation will require some larger contiguous memory
regions for the memory tracking tables. We plan to specify the memory region
for these tables as a reserved-memory node in the device tree, and then
dynamically allocate individual tables out of this region. These changes to the
SBI heap allocator will allow us to explicitly create and allocate from a
dedicated heap tied to the table memory region.

Signed-off-by: Gregor Haas <gregorhaas1997@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-09 08:51:24 +05:30
Carlos López
6a090ee9dc lib: sbi: check result of pmp_get() in is_pmp_entry_mapped()
pmp_get() may return an error if the given entry, given by the caller
of is_pmp_entry_mapped(), is invalid. This results in the output
parameters for pmp_get() being uninitialized. To avoid using garbage
values, check the result and return early if necessary.

This issue is not being hit because at the moment
is_pmp_entry_mapped() is only being called from a single site with a
valid hardcoded value.

Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-02 08:45:10 +05:30
Carlos López
41bb668315 lib: sbi: fwft: fix incorrect size passed to sbi_zalloc()
The fwt_hart_state struct inciludes a flexible array member, so its
allocation size will be that of the struct itself, plus that of each
of the members in the array. When calculating this size, instead of
taking the size of the struct, the size of a pointer to it was taken,
which is incorrect. Luckily, this happenned to not produce memory
corruption because the size of the non-flexible members of the struct
is the same as the size of a pointer.

Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-02 08:45:07 +05:30
Carlos López
d2353c9e22 lib: sbi: dbtr: fix potential NULL pointer dereferences
In several dbtr functions, we first check that the dbtr trigger is not
NULL and that its state is what we expect. However, it only makes
sense to perform the second check if the dbtr trigger is not NULL.
Othwerwise we will dereference a NULL pointer. Thus, change the
condition so that it shortcuts to the first check if necessary.

Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
Reviewed-By: Anup Patel <anup@brainfault.org>
2024-08-02 08:45:05 +05:30
Eric Lin
df997c6e55 include: Adjust Sscofpmf mhpmevent mask for upper 8 bits
Currently, OpenSBI reserves the upper 16 bits in mhpmevent for
the Sscofpmf extension.

However, according to the Sscofpmf extension specification[1],
it only defines the upper 8 bits in mhpmevent for privilege mode
inhibit and counter overflow disable. Other bits are defined by
the platform for event selection.

Since vendors might define raw event encoding exceeding 48 bits in
mhpmevent, we should adjust the MHPMEVENT_SSCOF_MASK to support it.

Link: https://github.com/riscvarchive/riscv-count-overflow [1]
Signed-off-by: Eric Lin <eric.lin@sifive.com>
Reviewed-by: Xiang W <wxjstz@126.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-08-02 08:43:27 +05:30
Anup Patel
bb7267a07f lib: sbi: Introduce an early console buffer for caching early prints
The console device is registered by platform only in early_init()
callback so any prints before this point will be lost. Introduce an
early console buffer for caching prints before platform early_init().

For crashes before platform early_init(), users can simply dump the
contents of the console_early_buffer[] string using a debugger. The
relative address of the console_early_buffer[] string can be found
using following two commands:

CONSOLE_EARLY_FIFO_ADDR=`${CROSS_COMPILE}objdump -D \
build/platform/generic/firmware/fw_dynamic.elf | \
grep "<console_early_fifo>:" | awk '{print $1}'`

${CROSS_COMPILE}objdump -R build/platform/generic/firmware/fw_dynamic.elf | \
grep $CONSOLE_EARLY_FIFO_ADDR | awk '{print $3}'

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-By: Himanshu Chauhan <hchauhan@ventanamicro.com>
2024-07-24 12:18:41 +05:30
Anup Patel
d35c76a766 include: sbi: Add macros to create FIFO as local or global variable
The FIFO data structure is quite handy of variety of use-case so add
SBI_FIFO_INITIALIZER() and SBI_FIFO_DEFINE() helper macros to create
FIFO as local or global variable.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-By: Himanshu Chauhan <hchauhan@ventanamicro.com>
2024-07-24 12:18:39 +05:30
Anup Patel
94c3c53a56 lib: sbi: Allow forceful queueing of data in sbi_fifo_enqueue()
Extend sbi_fifo_enqueue() to allow forceful queueing by droping
data from the tail.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-By: Himanshu Chauhan <hchauhan@ventanamicro.com>
2024-07-24 12:18:36 +05:30
Anup Patel
9a275fc153 lib: sbi: Optimize fifo enqueue/dequeue for basic data types
Don't use sbi_memcpy() for basic data types in fifo enqueue/dequeue
instead use direct type-cast and assignment.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-By: Himanshu Chauhan <hchauhan@ventanamicro.com>
2024-07-24 12:18:35 +05:30
Anup Patel
119b15a553 lib: sbi: Remove sbi_console_init() and console_init() platform callback
Now that all platforms have been updated to initialize serial console
device in early_init(), the sbi_console_init() and console_init()
platform callback are redundant hence remove them.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-By: Himanshu Chauhan <hchauhan@ventanamicro.com>
2024-07-24 12:18:33 +05:30
Anup Patel
9e8a18fd0d platform: Setup serial console device in early_init()
The sbi_console_init() does not do any special initialization so
setup serial console device in early_init() so that console prints
work as early as possible.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-By: Himanshu Chauhan <hchauhan@ventanamicro.com>
2024-07-24 12:18:31 +05:30
Samuel Holland
4afb57c9eb lib: sbi_hsm: Save/restore menvcfg only when it exists
Attempting to access the menvcfg CSR raises an illegal instruction
exception on hardware which implements Sm1p11 or older.

Fixes: e9ee9678ba ("lib: sbi: fwft: add support for SBI_FWFT_PTE_AD_HW_UPDATING")
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-07-24 10:42:46 +05:30
Conor Dooley
f7a92f6b67 lib: utils/fdt: Add support for parsing riscv,isa-extensions
A new property has been added, with an extensive rationale at [1], that
can be used in place of "riscv,isa" to indicate what extensions are
supported by a given platform that is a list of strings rather than a
single string. There are some differences between the new property,
"riscv,isa-extensions" and the incumbent "riscv,isa" - chief among them
for the sake of parsing being the list of strings, as opposed to a
string. Another advantage is strictly defined meanings for each string
in a dt-binding, rather than deriving meaning from RVI standards. This
may likely to some divergence over time, but, at least for now, there's
no relevant differences between the two for an M-Mode program.

Add support for the new property in OpenSBI, prioritising it, before
falling back to the, now deprecated, "riscv,isa" property if it is not
present.

Link: https://lore.kernel.org/all/20230702-eats-scorebook-c951f170d29f@spud/ [1]
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-07-23 11:12:56 +05:30
Dongdong Zhang
b7e7e66026 lib: tests: add math test suite
This patch introduces a new math test suite to the SBI unit
tests. The changes include:

* Updating lib/sbi/tests/objects.mk to include
  math_test_suite and sbi_math_test.o.
* Adding a new file lib/sbi/tests/sbi_math_test.c which
  contains tests for log2roundup function using various cases.

The addition of this test suite ensures that mathematical
functions are verified and work as expected.

Signed-off-by: Dongdong Zhang <zhangdongdong@eswincomputing.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-07-23 10:17:51 +05:30
Dongdong Zhang
c5c1d04346 lib: tests: enhance test output with colored pass/fail messages
This patch improves the readability of the SBI unit test
output by adding color-coded status messages.

Adding ANSI color codes for green (pass) and red (fail)
in sbi_unit_test.c.

Now, the test results will be displayed in green for passed
tests and red for failed tests, making it easier to quickly
distinguish between them.

Signed-off-by: Dongdong Zhang <zhangdongdong@eswincomputing.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-07-23 10:13:50 +05:30
Ivan Orlov
0a66754295 docs: writing tests: update cleaning instructions
After the changes introduced by the previous patches are applied, there
is no need of the manual removal of the `build/` directory every time
new test is added. Running `make clean` should be enough to regenerate
the carray-related files.

Update the documentation correspondingly.

Signed-off-by: Ivan Orlov <ivan.orlov0322@gmail.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-07-04 12:11:52 +05:30
Ben Dooks
1ede0cab0e Makefile: remove any .carray.c during clean
Now we've renamed the carray output files to .carray.c
we can now use find to remove them.

Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-07-04 12:11:50 +05:30
Ben Dooks
fd9e8b17ed Makefile: change to using .carray.c for carray files
We would like to clean any files generated by the carray
scripts by just searching for the filename as the current
make system turns f.carray into f.o. Change to make the
make system turn f.carray into f.carray.o

note, command to go through .mk files changing the .o
in the .mk files is:
find . -type f -name "*.carray" | xargs -t -I fname /bin/bash -x -c ' fn=`basename -s .carray fname`; echo "$fn"; sed -i `dirname fname `/objects.mk -e s/"$fn".o/"$fn".carray.o/g'

Link: https://patchwork.ozlabs.org/project/opensbi/patch/20240401213438.590209-2-ivan.orlov0322@gmail.com/
Reported-by: Ivan Orlov <ivan.orlov0322@gmail.com>
Suggested-by: Andrew Jones <ajones@ventanamicro.com>
Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-07-04 12:11:45 +05:30
Ivan Orlov
75ad25ab59 scripts/carray.sh: Add comment to generated files
Add a comment about where auto-generated file came from to the carray.sh
output. This should help avoiding confusion for the developers looking
at the build artifacts and finding .c files there.

Signed-off-by: Ivan Orlov <ivan.orlov0322@gmail.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-07-04 10:52:37 +05:30
Samuel Holland
d8608e615f lib: sbi_emulate_csr: Do not log illegal CSR accesses
Illegal CSR accesses from lower privilege modes are delegated to S-mode
and do not necessarily indicate a bug. Supervisor software may want to
emulate some CSRs, or may intentionally disable access to certain
existing CSRs, and thus will expect traps when those CSRs are accessed.

For example, Linux disables sstatus.VS by default in order to detect
when userspace first accesses vector register state; this includes the
CSRs defined by the V extesion. As a result, if the first vector
instruction in a process is a CSR access, OpenSBI will log the illegal
instruction exception, even though there is no unexpected or erroneous
behavior occurring.

Since the illegal instruction exception is delegated to S-mode, S-mode
software should be responsible for reporting the exception, not OpenSBI.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-07-04 10:42:16 +05:30
Dongdong Zhang
c531adbf08 .github: Add repo lockdown GitHub workflow and update .gitignore
This commit adds a new GitHub Actions workflow for repository
lockdown. The workflow triggers when a pull request is opened, and it
notifies the contributor to use the OpenSBI mailing list for patch
reviews.

Additionally, the .gitignore file is updated to include the .github
directory.

Signed-off-by: Dongdong Zhang <zhangdongdong@eswincomputing.com>
Reviewed-by: Anup Patel <anup@branifault.org>
2024-07-04 10:31:39 +05:30
278 changed files with 12517 additions and 3276 deletions

21
.editorconfig Normal file
View File

@@ -0,0 +1,21 @@
# SPDX-License-Identifier: GPL-2.0-only
# See here for more information about the format and editor support:
# https://editorconfig.org/
root = true
[{*.{c,dts,h,lds,ldS,mk,s,S},Kconfig,Makefile,Makefile.*}]
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = tab
indent_size = 8
[*.py]
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 4

26
.github/workflows/repo-lockdown.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: 'Repo Lockdown'
on:
pull_request_target:
types: opened
permissions:
pull-requests: write
jobs:
action:
runs-on: ubuntu-latest
steps:
- uses: dessant/repo-lockdown@v4
with:
pr-comment: |
We have mailing list based patch review so it would be great if you can send these patchs to OpenSBI mailing list.
You need to join OpenSBI mailing list using following link
http://lists.infradead.org/mailman/listinfo/opensbi
Make sure you use "git send-email" to send the patches.
Thanks for your contribution to OpenSBI project.
lock-pr: true
close-pr: true

3
.gitignore vendored
View File

@@ -4,6 +4,8 @@
# exceptions we need even begin with dot
!.clang-format
!.gitignore
!.github
!.editorconfig
# Object files
*.o
@@ -17,3 +19,4 @@ install/
# Development friendly files
tags
cscope*
*~

View File

@@ -91,14 +91,29 @@ endif
# Find library version
OPENSBI_VERSION_MAJOR=`grep "define OPENSBI_VERSION_MAJOR" $(include_dir)/sbi/sbi_version.h | sed 's/.*MAJOR.*\([0-9][0-9]*\)/\1/'`
OPENSBI_VERSION_MINOR=`grep "define OPENSBI_VERSION_MINOR" $(include_dir)/sbi/sbi_version.h | sed 's/.*MINOR.*\([0-9][0-9]*\)/\1/'`
OPENSBI_VERSION_GIT=$(shell if [ -d $(src_dir)/.git ]; then git describe 2> /dev/null; fi)
OPENSBI_VERSION_GIT=
# Detect 'git' presence before issuing 'git' commands
GIT_AVAIL := $(shell command -v git 2> /dev/null)
ifneq ($(GIT_AVAIL),)
GIT_DIR := $(shell git rev-parse --git-dir 2> /dev/null)
ifneq ($(GIT_DIR),)
OPENSBI_VERSION_GIT := $(shell if [ -d $(GIT_DIR) ]; then git describe 2> /dev/null; fi)
endif
endif
# Setup compilation commands
ifneq ($(LLVM),)
CC = clang
AR = llvm-ar
LD = ld.lld
OBJCOPY = llvm-objcopy
ifneq ($(filter %/,$(LLVM)),)
LLVM_PREFIX := $(LLVM)
else ifneq ($(filter -%,$(LLVM)),)
LLVM_SUFFIX := $(LLVM)
endif
CC = $(LLVM_PREFIX)clang$(LLVM_SUFFIX)
AR = $(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX)
LD = $(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX)
OBJCOPY = $(LLVM_PREFIX)llvm-objcopy$(LLVM_SUFFIX)
else
ifdef CROSS_COMPILE
CC = $(CROSS_COMPILE)gcc
@@ -165,6 +180,11 @@ else
USE_LD_FLAG = -fuse-ld=bfd
endif
REPRODUCIBLE ?= n
ifeq ($(REPRODUCIBLE),y)
REPRODUCIBLE_FLAGS += -ffile-prefix-map=$(src_dir)=
endif
# Check whether the linker supports creating PIEs
OPENSBI_LD_PIE := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) $(USE_LD_FLAG) -fPIE -nostdlib -Wl,-pie -x c /dev/null -o /dev/null >/dev/null 2>&1 && echo y || echo n)
@@ -175,10 +195,13 @@ OPENSBI_LD_EXCLUDE_LIBS := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) $(USE_LD_
CC_SUPPORT_SAVE_RESTORE := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib -mno-save-restore -x c /dev/null -o /dev/null 2>&1 | grep -e "-save-restore" >/dev/null && echo n || echo y)
# Check whether the compiler supports -m(no-)strict-align
CC_SUPPORT_STRICT_ALIGN := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib -mstrict-align -x c /dev/null -o /dev/null 2>&1 | grep -e "-mstrict-align\|-mno-unaligned-access" >/dev/null && echo n || echo y)
CC_SUPPORT_STRICT_ALIGN := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib -mstrict-align -x c /dev/null -o /dev/null 2>&1 | grep -e "-mstrict-align" -e "-mno-unaligned-access" >/dev/null && echo n || echo y)
# Check whether the assembler and the compiler support the Zicsr and Zifencei extensions
CC_SUPPORT_ZICSR_ZIFENCEI := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib -march=rv$(OPENSBI_CC_XLEN)imafd_zicsr_zifencei -x c /dev/null -o /dev/null 2>&1 | grep "zicsr\|zifencei" > /dev/null && echo n || echo y)
CC_SUPPORT_ZICSR_ZIFENCEI := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib -march=rv$(OPENSBI_CC_XLEN)imafd_zicsr_zifencei -x c /dev/null -o /dev/null 2>&1 | grep -e "zicsr" -e "zifencei" > /dev/null && echo n || echo y)
# Check whether the assembler and the compiler support the Vector extension
CC_SUPPORT_VECTOR := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib -march=rv$(OPENSBI_CC_XLEN)gv -dM -E -x c /dev/null 2>&1 | grep -q riscv.*vector && echo y || echo n)
ifneq ($(OPENSBI_LD_PIE),y)
$(error Your linker does not support creating PIEs, opensbi requires this.)
@@ -190,16 +213,18 @@ endif
BUILD_INFO ?= n
ifeq ($(BUILD_INFO),y)
OPENSBI_BUILD_DATE_FMT = +%Y-%m-%d %H:%M:%S %z
ifndef OPENSBI_BUILD_TIME_STAMP
ifdef SOURCE_DATE_EPOCH
OPENSBI_BUILD_TIME_STAMP ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" \
OPENSBI_BUILD_TIME_STAMP := $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" \
"$(OPENSBI_BUILD_DATE_FMT)" 2>/dev/null || \
date -u -r "$(SOURCE_DATE_EPOCH)" \
"$(OPENSBI_BUILD_DATE_FMT)" 2>/dev/null || \
date -u "$(OPENSBI_BUILD_DATE_FMT)")
else
OPENSBI_BUILD_TIME_STAMP ?= $(shell date "$(OPENSBI_BUILD_DATE_FMT)")
OPENSBI_BUILD_TIME_STAMP := $(shell date "$(OPENSBI_BUILD_DATE_FMT)")
endif
OPENSBI_BUILD_COMPILER_VERSION=$(shell $(CC) -v 2>&1 | grep ' version ' | \
endif
OPENSBI_BUILD_COMPILER_VERSION := $(shell $(CC) -v 2>&1 | grep ' version ' | \
sed 's/[[:space:]]*$$//')
endif
@@ -285,10 +310,9 @@ ifndef PLATFORM_RISCV_ABI
endif
ifndef PLATFORM_RISCV_ISA
ifneq ($(PLATFORM_RISCV_TOOLCHAIN_DEFAULT), 1)
PLATFORM_RISCV_ISA := rv$(PLATFORM_RISCV_XLEN)imafdc
ifeq ($(CC_SUPPORT_ZICSR_ZIFENCEI), y)
PLATFORM_RISCV_ISA = rv$(PLATFORM_RISCV_XLEN)imafdc_zicsr_zifencei
else
PLATFORM_RISCV_ISA = rv$(PLATFORM_RISCV_XLEN)imafdc
PLATFORM_RISCV_ISA := $(PLATFORM_RISCV_ISA)_zicsr_zifencei
endif
else
PLATFORM_RISCV_ISA = $(OPENSBI_CC_ISA)
@@ -339,6 +363,7 @@ ifeq ($(BUILD_INFO),y)
GENFLAGS += -DOPENSBI_BUILD_TIME_STAMP="\"$(OPENSBI_BUILD_TIME_STAMP)\""
GENFLAGS += -DOPENSBI_BUILD_COMPILER_VERSION="\"$(OPENSBI_BUILD_COMPILER_VERSION)\""
endif
GENFLAGS += -include $(include_dir)/sbi/sbi_visibility.h
ifdef PLATFORM
GENFLAGS += -include $(KCONFIG_AUTOHEADER)
endif
@@ -346,14 +371,14 @@ GENFLAGS += $(libsbiutils-genflags-y)
GENFLAGS += $(platform-genflags-y)
GENFLAGS += $(firmware-genflags-y)
CFLAGS = -g -Wall -Werror -ffreestanding -nostdlib -fno-stack-protector -fno-strict-aliasing
ifneq ($(DEBUG),)
CFLAGS += -O0
else
CFLAGS += -O2
endif
CFLAGS = -g -Wall -Werror -ffreestanding -nostdlib -fno-stack-protector -fno-strict-aliasing -ffunction-sections -fdata-sections
CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
CFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables
CFLAGS += $(REPRODUCIBLE_FLAGS)
# Optionally supported flags
ifeq ($(CC_SUPPORT_VECTOR),y)
CFLAGS += -DOPENSBI_CC_SUPPORT_VECTOR
endif
ifeq ($(CC_SUPPORT_SAVE_RESTORE),y)
CFLAGS += -mno-save-restore
endif
@@ -375,6 +400,7 @@ CPPFLAGS += $(firmware-cppflags-y)
ASFLAGS = -g -Wall -nostdlib
ASFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
ASFLAGS += -fPIE
ASFLAGS += $(REPRODUCIBLE_FLAGS)
# Optionally supported flags
ifeq ($(CC_SUPPORT_SAVE_RESTORE),y)
ASFLAGS += -mno-save-restore
@@ -397,6 +423,7 @@ ASFLAGS += $(firmware-asflags-y)
ARFLAGS = rcs
ELFFLAGS += $(USE_LD_FLAG)
ELFFLAGS += -Wl,--gc-sections
ifeq ($(OPENSBI_LD_EXCLUDE_LIBS),y)
ELFFLAGS += -Wl,--exclude-libs,ALL
endif
@@ -415,6 +442,13 @@ MERGEFLAGS += -m elf$(PLATFORM_RISCV_XLEN)lriscv
DTSCPPFLAGS = $(CPPFLAGS) -nostdinc -nostdlib -fno-builtin -D__DTS__ -x assembler-with-cpp
ifneq ($(DEBUG),)
CFLAGS += -O0
ELFFLAGS += -Wl,--print-gc-sections
else
CFLAGS += -O2
endif
# Setup functions for compilation
define dynamic_flags
-I$(shell dirname $(2)) -D__OBJNAME__=$(subst -,_,$(shell basename $(1) .o))
@@ -489,8 +523,8 @@ compile_d2c = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
$(src_dir)/scripts/d2c.sh -i $(6) -a $(D2C_ALIGN_BYTES) -p $(D2C_NAME_PREFIX) -t $(D2C_PADDING_BYTES) > $(1)
compile_carray = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
echo " CARRAY $(subst $(build_dir)/,,$(1))"; \
$(eval CARRAY_VAR_LIST := $(carray-$(subst .c,,$(shell basename $(1)))-y)) \
$(src_dir)/scripts/carray.sh -i $(2) -l "$(CARRAY_VAR_LIST)" > $(1)
$(eval CARRAY_VAR_LIST := $(carray-$(subst .carray.c,,$(shell basename $(1)))-y)) \
$(src_dir)/scripts/carray.sh -i $(2) -l "$(CARRAY_VAR_LIST)" > $(1) || rm $(1)
compile_gen_dep = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
echo " GEN-DEP $(subst $(build_dir)/,,$(1))"; \
echo "$(1:.dep=$(2)): $(3)" >> $(1)
@@ -519,7 +553,7 @@ $(build_dir)/%.dep: $(src_dir)/%.carray $(KCONFIG_AUTOHEADER)
$(call compile_gen_dep,$@,.c,$< $(KCONFIG_AUTOHEADER))
$(call compile_gen_dep,$@,.o,$(@:.dep=.c))
$(build_dir)/%.c: $(src_dir)/%.carray
$(build_dir)/%.carray.c: $(src_dir)/%.carray $(src_dir)/scripts/carray.sh
$(call compile_carray,$@,$<)
$(build_dir)/%.dep: $(src_dir)/%.c $(KCONFIG_AUTOHEADER)
@@ -547,7 +581,7 @@ $(platform_build_dir)/%.dep: $(platform_src_dir)/%.carray $(KCONFIG_AUTOHEADER)
$(call compile_gen_dep,$@,.c,$< $(KCONFIG_AUTOHEADER))
$(call compile_gen_dep,$@,.o,$(@:.dep=.c))
$(platform_build_dir)/%.c: $(platform_src_dir)/%.carray
$(platform_build_dir)/%.carray.c: $(platform_src_dir)/%.carray $(src_dir)/scripts/carray.sh
$(call compile_carray,$@,$<)
$(platform_build_dir)/%.dep: $(platform_src_dir)/%.c $(KCONFIG_AUTOHEADER)
@@ -590,7 +624,7 @@ $(platform_build_dir)/%.dep: $(src_dir)/%.carray $(KCONFIG_AUTOHEADER)
$(call compile_gen_dep,$@,.c,$< $(KCONFIG_AUTOHEADER))
$(call compile_gen_dep,$@,.o,$(@:.dep=.c))
$(platform_build_dir)/%.c: $(src_dir)/%.carray
$(platform_build_dir)/%.carray.c: $(src_dir)/%.carray $(src_dir)/scripts/carray.sh
$(call compile_carray,$@,$<)
$(platform_build_dir)/%.dep: $(src_dir)/%.c $(KCONFIG_AUTOHEADER)
@@ -687,6 +721,8 @@ clean:
$(CMD_PREFIX)mkdir -p $(build_dir)
$(if $(V), @echo " RM $(build_dir)/*.o")
$(CMD_PREFIX)find $(build_dir) -type f -name "*.o" -exec rm -rf {} +
$(if $(V), @echo " RM $(build_dir)/*.carray.c")
$(CMD_PREFIX)find $(build_dir) -type f -name "*.carray.c" -exec rm -rf {} +
$(if $(V), @echo " RM $(build_dir)/*.a")
$(CMD_PREFIX)find $(build_dir) -type f -name "*.a" -exec rm -rf {} +
$(if $(V), @echo " RM $(build_dir)/*.elf")

View File

@@ -99,7 +99,7 @@ capable enough to bring up all other non-booting harts using HSM extension.
Required Toolchain and Packages
-------------------------------
OpenSBI can be compiled natively or cross-compiled on a x86 host. For
OpenSBI can be compiled natively or cross-compiled on a host machine. For
cross-compilation, you can build your own toolchain, download a prebuilt one
from the [Bootlin toolchain repository] or install a distribution-provided
toolchain; if you opt to use LLVM/Clang, most distribution toolchains will
@@ -108,16 +108,12 @@ LLVM/Clang toolchain due to LLVM's ability to support multiple backends in the
same binary, so is often an easy way to obtain a working cross-compilation
toolchain.
Basically, we prefer toolchains with Position Independent Executable (PIE)
support like *riscv64-linux-gnu-gcc*, *riscv64-unknown-freebsd-gcc*, or
*Clang/LLVM* as they generate PIE firmware images that can run at arbitrary
address with appropriate alignment. If a bare-metal GNU toolchain (e.g.
*riscv64-unknown-elf-gcc*) is used, static linked firmware images are
generated instead. *Clang/LLVM* can still generate PIE images if a bare-metal
triple is used (e.g. *-target riscv64-unknown-elf*).
Please note that only a 64-bit version of the toolchain is available in
the Bootlin toolchain repository for now.
Toolchains with Position Independent Executable (PIE) support like
*riscv64-linux-gnu-gcc*, *riscv64-unknown-freebsd-gcc*, or *Clang/LLVM* are
required in order to generate PIE firmware images that can run at arbitrary
address with appropriate alignment. Bare-metal GNU toolchains (e.g.
*riscv64-unknown-elf-gcc*) cannot be used. *Clang/LLVM* can still generate PIE
images if a bare-metal triple is used (e.g. *-target riscv64-unknown-elf*).
In addition to a toolchain, OpenSBI also requires the following packages on
the host:
@@ -256,6 +252,18 @@ option with:
make LLVM=1
```
To build with a specific version of LLVM, a path to a directory containing the
LLVM tools can be provided:
```
make LLVM=/path/to/llvm/
```
If you have versioned llvm tools you would like to use, such as `clang-17`, the LLVM variable can
be set as:
```
make LLVM=-17
```
When using Clang, *CROSS_COMPILE* often does not need to be defined unless
using GNU binutils with prefixed binary names. *PLATFORM_RISCV_XLEN* will be
used to infer a default triple to pass to Clang, so if *PLATFORM_RISCV_XLEN*

View File

@@ -1,17 +1,15 @@
OpenSBI Contribution Guideline
==============================
All contributions to OpenSBI can be sent in the following ways:
1. Email patches to the OpenSBI mailing list at `opensbi@lists.infradead.org`
2. GitHub Pull Requests (PRs) to the [OpenSBI main repository]
All contributions to OpenSBI must be sent via email patches to the OpenSBI
mailing list at `opensbi@lists.infradead.org`
To join the OpenSBI mailing list, please visit the [OpenSBI infradead page].
The OpenSBI maintainers prefer patches via the OpenSBI mailing list
(option 1 above) so that they are visible to a wider audience. All
accepted patches on the OpenSBI mailing list will be taken by any of
the OpenSBI maintainers and merged into the [OpenSBI main repository]
using GitHub PRs.
The mailing list based patch approach is preferred over github PRs so that they
are visible to a wider audience. All accepted patches on the OpenSBI mailing
list will be taken by one of the OpenSBI maintainers and merged into the
[OpenSBI main repository].
All contributed work must follow the following rules:
1. OpenSBI code should be written in accordance to the [Linux coding style].
@@ -33,9 +31,6 @@ riscv/opensbi repository. Instead, prefer using a fork of the riscv/opensbi main
repository and branches within that fork to create pull requests.
7. A maintainer cannot merge his own pull requests in the riscv/opensbi main
repository.
8. A pull request must get at least one review from a maintainer.
9. A pull request must spend at least 24 hours in review to allow for other
developers to review.
-----------------------------------------------------------------------

View File

@@ -41,7 +41,6 @@ has following details:
* **name** - Name of this domain
* **assigned_harts** - HARTs assigned to this domain
* **possible_harts** - HARTs possible in this domain
* **hartindex_to_context_table** - Contexts corresponding to possible HARTs
* **regions** - Array of memory regions terminated by a memory region
with order zero
* **boot_hartid** - HART id of the HART booting this domain. The domain
@@ -81,7 +80,6 @@ following manner:
platform support
* **possible_harts** - All valid HARTs of a RISC-V platform are possible
HARTs of the ROOT domain
* **hartindex_to_context_table** - Contexts corresponding to ROOT domain's possible HARTs
* **regions** - Two memory regions available to the ROOT domain:
**A)** A memory region to protect OpenSBI firmware from S-mode and U-mode
**B)** A memory region of **order=__riscv_xlen** allowing S-mode and
@@ -180,9 +178,7 @@ The DT properties of a domain instance DT node are as follows:
boot HART of the domain instance.
* **next-arg1** (Optional) - The 64 bit next booting stage arg1 for the
domain instance. If this DT property is not available and coldboot HART
is not assigned to the domain instance then **0x0** is used as default
value. If this DT property is not available and coldboot HART is assigned
to the domain instance then **next booting stage arg1 of coldboot HART**
is not assigned to the domain instance then **next booting stage arg1 of coldboot HART**
is used as default value.
* **next-addr** (Optional) - The 64 bit next booting stage address for the
domain instance. If this DT property is not available and coldboot HART

View File

@@ -23,6 +23,9 @@ The DT properties of a domain configuration DT node are as follows:
set of harts is permitted to perform a cold boot. Otherwise, all
harts are allowed to cold boot.
* **heap-size** (Optional) - When present, the specified value is used
as the size of the heap in bytes.
* **system-suspend-test** (Optional) - When present, enable a system
suspend test implementation which simply waits five seconds and issues a WFI.
@@ -36,6 +39,7 @@ The OpenSBI Configuration Node will be deleted at the end of cold boot
opensbi-config {
compatible = "opensbi,config";
cold-boot-harts = <&cpu1 &cpu2 &cpu3 &cpu4>;
heap-size = <0x400000>;
system-suspend-test;
};
};

View File

@@ -56,7 +56,14 @@ qemu-system-riscv64 -M virt -m 256M -nographic \
**Linux Kernel Payload**
Note: We assume that the Linux kernel is compiled using
*arch/riscv/configs/defconfig*.
*arch/riscv/configs/defconfig*. The kernel must be a flattened image (a file
called `Image`) rather than an ELF (`vmlinux`).
Example of building a Linux kernel:
```
make ARCH=riscv CROSS_COMPILE=riscv64-linux- defconfig
make ARCH=riscv CROSS_COMPILE=riscv64-linux- Image
```
Build:
```

View File

@@ -19,6 +19,10 @@ Base Platform Requirements
The base RISC-V platform requirements for OpenSBI are as follows:
1. At least rv32ima_zicsr or rv64ima_zicsr required on all HARTs
* Users may restrict the usage of atomic instructions to lr/sc
via rv32im_zalrsc_zicsr or rv64im_zalrsc_zicsr if preferred
2. At least one HART should have S-mode support because:
* SBI calls are meant for RISC-V S-mode (Supervisor mode)

View File

@@ -74,10 +74,10 @@ pmu {
<0x10000 0x10033 0x000ff000>;
/* For event ID 0x0002 */
riscv,raw-event-to-mhpmcounters = <0x0000 0x0002 0xffffffff 0xffffffff 0x00000f8>,
/* For event ID 0-4 */
/* For event ID 0-15 */
<0x0 0x0 0xffffffff 0xfffffff0 0x00000ff0>,
/* For event ID 0xffffffff0000000f - 0xffffffff000000ff */
<0xffffffff 0x0 0xffffffff 0xffffff0f 0x00000ff0>;
<0xffffffff 0xf 0xffffffff 0xffffff0f 0x00000ff0>;
};
```

View File

@@ -57,9 +57,7 @@ carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += string_test_suite
libsbi-objs-$(CONFIG_SBIUNIT) += tests/sbi_string_test.o
```
If you compiled OpenSBI with CONFIG_SBIUNIT enabled before, you may need to
manually remove the build folder in order to regenerate the carray files:
`rm -rf build/`.
Now, run `make clean` in order to regenerate the carray-related files.
Recompile OpenSBI with the CONFIG_SBIUNIT option enabled and run it in QEMU.
You will see something like this:

View File

@@ -1 +1,28 @@
# SPDX-License-Identifier: BSD-2-Clause
menu "Stack Protector Support"
config STACK_PROTECTOR
bool "Stack Protector buffer overflow detection"
default n
help
This option turns on the "stack-protector" compiler feature.
config STACK_PROTECTOR_STRONG
bool "Strong Stack Protector"
depends on STACK_PROTECTOR
default n
help
Turn on the "stack-protector" with "-fstack-protector-strong" option.
Like -fstack-protector but includes additional functions to be
protected.
config STACK_PROTECTOR_ALL
bool "Almighty Stack Protector"
depends on STACK_PROTECTOR
default n
help
Turn on the "stack-protector" with "-fstack-protector-all" option.
Like -fstack-protector except that all functions are protected.
endmenu

View File

@@ -14,8 +14,8 @@
#include <sbi/sbi_scratch.h>
#include <sbi/sbi_trap.h>
#define BOOT_STATUS_LOTTERY_DONE 1
#define BOOT_STATUS_BOOT_HART_DONE 2
#define BOOT_LOTTERY_ACQUIRED 1
#define BOOT_STATUS_BOOT_HART_DONE 1
.macro MOV_3R __d0, __s0, __d1, __s1, __d2, __s2
add \__d0, \__s0, zero
@@ -31,6 +31,16 @@
add \__d4, \__s4, zero
.endm
.macro CLEAR_MDT tmp
#if __riscv_xlen == 32
li \tmp, MSTATUSH_MDT
csrc CSR_MSTATUSH, \tmp
#else
li \tmp, MSTATUS_MDT
csrc CSR_MSTATUS, \tmp
#endif
.endm
.section .entry, "ax", %progbits
.align 3
.globl _start
@@ -47,30 +57,40 @@ _start:
bne a0, a6, _wait_for_boot_hart
_try_lottery:
/* Jump to relocation wait loop if we don't get relocation lottery */
lla a6, _boot_status
li a7, BOOT_STATUS_LOTTERY_DONE
lla a6, _boot_lottery
li a7, BOOT_LOTTERY_ACQUIRED
#ifdef __riscv_atomic
amoswap.w a6, a7, (a6)
bnez a6, _wait_for_boot_hart
#elif __riscv_zalrsc
_sc_fail:
lr.w t0, (a6)
sc.w t1, a7, (a6)
bnez t1, _sc_fail
bnez t0, _wait_for_boot_hart
#else
#error "need a or zalrsc"
#endif
/* relocate the global table content */
li t0, FW_TEXT_START /* link start */
lla t1, _fw_start /* load start */
sub t2, t1, t0 /* load offset */
lla t0, __rel_dyn_start
lla t1, __rel_dyn_end
lla t0, __rela_dyn_start
lla t1, __rela_dyn_end
beq t0, t1, _relocate_done
2:
REG_L t5, REGBYTES(t0) /* t5 <-- relocation info:type */
REG_L t5, __SIZEOF_LONG__(t0) /* t5 <-- relocation info:type */
li t3, R_RISCV_RELATIVE /* reloc type R_RISCV_RELATIVE */
bne t5, t3, 3f
REG_L t3, 0(t0)
REG_L t5, (REGBYTES * 2)(t0) /* t5 <-- addend */
REG_L t5, (__SIZEOF_LONG__ * 2)(t0) /* t5 <-- addend */
add t5, t5, t2
add t3, t3, t2
REG_S t5, 0(t3) /* store runtime address to the GOT entry */
3:
addi t0, t0, (REGBYTES * 3)
addi t0, t0, (__SIZEOF_LONG__ * 3)
blt t0, t1, 2b
_relocate_done:
/* At this point we are running from link address */
@@ -91,6 +111,14 @@ _bss_zero:
lla s4, _start_hang
csrw CSR_MTVEC, s4
/*
* While at this point, trap handling is rudimentary, if a trap happens,
* it will end up in _start_hang which is enough to hook up a GDB. Clear
* MDT to avoid generating a double trap and thus entering a
* critical-error state.
*/
CLEAR_MDT t0
/* Setup temporary stack */
lla s4, _fw_end
li s5, (SBI_SCRATCH_SIZE * 2)
@@ -218,6 +246,8 @@ _scratch_init:
#endif
REG_S a0, SBI_SCRATCH_OPTIONS_OFFSET(tp)
MOV_3R a0, s0, a1, s1, a2, s2
/* Store hart index in scratch space */
REG_S t1, SBI_SCRATCH_HARTINDEX_OFFSET(tp)
/* Move to next scratch space */
add t1, t1, t2
blt t1, s7, _scratch_init
@@ -242,30 +272,14 @@ _scratch_init:
beq t1, a1, _fdt_reloc_done
/* t0 = source FDT start address */
add t0, a1, zero
/* t2 = source FDT size in big-endian */
#if __riscv_xlen > 32
lwu t2, 4(t0)
#else
lw t2, 4(t0)
#endif
/* t3 = bit[15:8] of FDT size */
add t3, t2, zero
srli t3, t3, 16
and t3, t3, a4
/* t2 = source FDT size (convert from big-endian) */
lbu t2, 7(t0)
lbu t3, 6(t0)
lbu t4, 5(t0)
lbu t5, 4(t0)
slli t3, t3, 8
/* t4 = bit[23:16] of FDT size */
add t4, t2, zero
srli t4, t4, 8
and t4, t4, a4
slli t4, t4, 16
/* t5 = bit[31:24] of FDT size */
add t5, t2, zero
and t5, t5, a4
slli t5, t5, 24
/* t2 = bit[7:0] of FDT size */
srli t2, t2, 24
and t2, t2, a4
/* t2 = FDT size in little-endian */
or t2, t2, t3
or t2, t2, t4
or t2, t2, t5
@@ -288,7 +302,7 @@ _fdt_reloc_done:
REG_S t0, 0(t1)
j _start_warm
/* waiting for boot hart to be done (_boot_status == 2) */
/* waiting for boot hart to be done (_boot_status == BOOT_STATUS_BOOT_HART_DONE) */
_wait_for_boot_hart:
li t0, BOOT_STATUS_BOOT_HART_DONE
lla t1, _boot_status
@@ -362,6 +376,9 @@ _start_warm:
_skip_trap_handler_hyp:
csrw CSR_MTVEC, a4
/* Clear MDT here again for all harts */
CLEAR_MDT t0
/* Initialize SBI runtime */
csrr a0, CSR_MSCRATCH
call sbi_init
@@ -371,6 +388,8 @@ _skip_trap_handler_hyp:
.data
.align 3
_boot_lottery:
RISCV_PTR 0
_boot_status:
RISCV_PTR 0
@@ -557,6 +576,9 @@ memcmp:
li t0, 0
.endif
REG_S t0, (SBI_TRAP_REGS_SIZE + SBI_TRAP_INFO_OFFSET(gva))(sp)
/* We are ready to take another trap, clear MDT */
CLEAR_MDT t0
.endm
.macro TRAP_CALL_C_ROUTINE
@@ -599,15 +621,18 @@ memcmp:
.endm
.macro TRAP_RESTORE_MEPC_MSTATUS have_mstatush
/* Restore MEPC and MSTATUS CSRs */
REG_L t0, SBI_TRAP_REGS_OFFSET(mepc)(a0)
csrw CSR_MEPC, t0
REG_L t0, SBI_TRAP_REGS_OFFSET(mstatus)(a0)
csrw CSR_MSTATUS, t0
/*
* Restore MSTATUS and MEPC CSRs starting with MSTATUS/H to set MDT
* flags since we can not take a trap now or MEPC would be cloberred
*/
.if \have_mstatush
REG_L t0, SBI_TRAP_REGS_OFFSET(mstatusH)(a0)
csrw CSR_MSTATUSH, t0
.endif
REG_L t0, SBI_TRAP_REGS_OFFSET(mstatus)(a0)
csrw CSR_MSTATUS, t0
REG_L t0, SBI_TRAP_REGS_OFFSET(mepc)(a0)
csrw CSR_MEPC, t0
.endm
.macro TRAP_RESTORE_A0_T0
@@ -711,6 +736,27 @@ _reset_regs:
ret
.section .rodata
.Lstack_corrupt_msg:
.string "stack smashing detected\n"
/* This will be called when the stack corruption is detected */
.section .text
.align 3
.globl __stack_chk_fail
.type __stack_chk_fail, %function
__stack_chk_fail:
la a0, .Lstack_corrupt_msg
call sbi_panic
/* Initial value of the stack guard variable */
.section .data
.align 3
.globl __stack_chk_guard
.type __stack_chk_guard, %object
__stack_chk_guard:
RISCV_PTR 0x95B5FF5A
#ifdef FW_FDT_PATH
.section .rodata
.align 4

View File

@@ -20,6 +20,7 @@
PROVIDE(_text_start = .);
*(.entry)
*(.text)
*(.text.*)
. = ALIGN(8);
PROVIDE(_text_end = .);
}
@@ -46,9 +47,9 @@
. = ALIGN(0x1000); /* Ensure next section is page aligned */
.rela.dyn : {
PROVIDE(__rel_dyn_start = .);
PROVIDE(__rela_dyn_start = .);
*(.rela*)
PROVIDE(__rel_dyn_end = .);
PROVIDE(__rela_dyn_end = .);
}
PROVIDE(_rodata_end = .);

View File

@@ -66,3 +66,12 @@ endif
ifdef FW_OPTIONS
firmware-genflags-y += -DFW_OPTIONS=$(FW_OPTIONS)
endif
ifeq ($(CONFIG_STACK_PROTECTOR),y)
stack-protector-cflags-$(CONFIG_STACK_PROTECTOR) := -fstack-protector
stack-protector-cflags-$(CONFIG_STACK_PROTECTOR_STRONG) := -fstack-protector-strong
stack-protector-cflags-$(CONFIG_STACK_PROTECTOR_ALL) := -fstack-protector-all
else
stack-protector-cflags-y := -fno-stack-protector
endif
firmware-cflags-y += $(stack-protector-cflags-y)

View File

@@ -30,7 +30,18 @@ _start:
/* Pick one hart to run the main boot sequence */
lla a3, _hart_lottery
li a2, 1
#ifdef __riscv_atomic
amoadd.w a3, a2, (a3)
#elif __riscv_zalrsc
_sc_fail:
lr.w t0, (a3)
addw t1, t0, a2
sc.w t1, t1, (a3)
bnez t1, _sc_fail
move a3, t0
#else
#error "need a or zalrsc"
#endif
bnez a3, _start_hang
/* Save a0 and a1 */
@@ -86,3 +97,18 @@ _boot_a0:
RISCV_PTR 0
_boot_a1:
RISCV_PTR 0
/* This will be called when the stack corruption is detected */
.section .text
.align 3
.globl __stack_chk_fail
.type __stack_chk_fail, %function
.equ __stack_chk_fail, _start_hang
/* Initial value of the stack guard variable */
.section .data
.align 3
.globl __stack_chk_guard
.type __stack_chk_guard, %object
__stack_chk_guard:
RISCV_PTR 0x95B5FF5A

View File

@@ -46,6 +46,13 @@ static inline void sbi_ecall_console_puts(const char *str)
sbi_strlen(str), (unsigned long)str, 0, 0, 0, 0);
}
static inline void sbi_ecall_shutdown(void)
{
sbi_ecall(SBI_EXT_SRST, SBI_EXT_SRST_RESET,
SBI_SRST_RESET_TYPE_SHUTDOWN, SBI_SRST_RESET_REASON_NONE,
0, 0, 0, 0);
}
#define wfi() \
do { \
__asm__ __volatile__("wfi" ::: "memory"); \
@@ -54,7 +61,6 @@ static inline void sbi_ecall_console_puts(const char *str)
void test_main(unsigned long a0, unsigned long a1)
{
sbi_ecall_console_puts("\nTest payload running\n");
while (1)
wfi();
sbi_ecall_shutdown();
sbi_ecall_console_puts("sbi_ecall_shutdown failed to execute.\n");
}

View File

@@ -79,36 +79,12 @@ struct fw_dynamic_info {
* Prevent modification of struct fw_dynamic_info from affecting
* FW_DYNAMIC_INFO_xxx_OFFSET
*/
_Static_assert(
offsetof(struct fw_dynamic_info, magic)
== FW_DYNAMIC_INFO_MAGIC_OFFSET,
"struct fw_dynamic_info definition has changed, please redefine "
"FW_DYNAMIC_INFO_MAGIC_OFFSET");
_Static_assert(
offsetof(struct fw_dynamic_info, version)
== FW_DYNAMIC_INFO_VERSION_OFFSET,
"struct fw_dynamic_info definition has changed, please redefine "
"FW_DYNAMIC_INFO_VERSION_OFFSET");
_Static_assert(
offsetof(struct fw_dynamic_info, next_addr)
== FW_DYNAMIC_INFO_NEXT_ADDR_OFFSET,
"struct fw_dynamic_info definition has changed, please redefine "
"FW_DYNAMIC_INFO_NEXT_ADDR_OFFSET");
_Static_assert(
offsetof(struct fw_dynamic_info, next_mode)
== FW_DYNAMIC_INFO_NEXT_MODE_OFFSET,
"struct fw_dynamic_info definition has changed, please redefine "
"FW_DYNAMIC_INFO_NEXT_MODE_OFFSET");
_Static_assert(
offsetof(struct fw_dynamic_info, options)
== FW_DYNAMIC_INFO_OPTIONS_OFFSET,
"struct fw_dynamic_info definition has changed, please redefine "
"FW_DYNAMIC_INFO_OPTIONS_OFFSET");
_Static_assert(
offsetof(struct fw_dynamic_info, boot_hart)
== FW_DYNAMIC_INFO_BOOT_HART_OFFSET,
"struct fw_dynamic_info definition has changed, please redefine "
"FW_DYNAMIC_INFO_BOOT_HART_OFFSET");
assert_member_offset(struct fw_dynamic_info, magic, FW_DYNAMIC_INFO_MAGIC_OFFSET);
assert_member_offset(struct fw_dynamic_info, version, FW_DYNAMIC_INFO_VERSION_OFFSET);
assert_member_offset(struct fw_dynamic_info, next_addr, FW_DYNAMIC_INFO_NEXT_ADDR_OFFSET);
assert_member_offset(struct fw_dynamic_info, next_mode, FW_DYNAMIC_INFO_NEXT_MODE_OFFSET);
assert_member_offset(struct fw_dynamic_info, options, FW_DYNAMIC_INFO_OPTIONS_OFFSET);
assert_member_offset(struct fw_dynamic_info, boot_hart, FW_DYNAMIC_INFO_BOOT_HART_OFFSET);
#endif

View File

@@ -101,6 +101,14 @@
__v; \
})
/* Variant of csr_read() that allows the compiler to cache the value. */
#define csr_read_relaxed(csr) \
({ \
register unsigned long __v; \
__asm__ ("csrr %0, " __ASM_STR(csr) : "=r"(__v)); \
__v; \
})
#define csr_write(csr, val) \
({ \
unsigned long __v = (unsigned long)(val); \
@@ -148,6 +156,26 @@
: "memory"); \
})
#if __riscv_xlen == 64
#define __csrrw64(op, csr, csrh, val) (true ? op(csr, val) : (uint64_t)csrh)
#define __csrr64( op, csr, csrh) (true ? op(csr) : (uint64_t)csrh)
#define __csrw64( op, csr, csrh, val) (true ? op(csr, val) : (uint64_t)csrh)
#elif __riscv_xlen == 32
#define __csrrw64(op, csr, csrh, val) ( op(csr, val) | (uint64_t)op(csrh, val >> 32) << 32)
#define __csrr64( op, csr, csrh) ( op(csr) | (uint64_t)op(csrh) << 32)
#define __csrw64( op, csr, csrh, val) ({ op(csr, val); op(csrh, val >> 32); })
#endif
#define csr_swap64( csr, val) __csrrw64(csr_swap, csr, csr ## H, val)
#define csr_read64( csr) __csrr64 (csr_read, csr, csr ## H)
#define csr_read_relaxed64(csr) __csrr64 (csr_read_relaxed, csr, csr ## H)
#define csr_write64( csr, val) __csrw64 (csr_write, csr, csr ## H, val)
#define csr_read_set64( csr, val) __csrrw64(csr_read_set, csr, csr ## H, val)
#define csr_set64( csr, val) __csrw64 (csr_set, csr, csr ## H, val)
#define csr_clear64( csr, val) __csrw64 (csr_clear, csr, csr ## H, val)
#define csr_read_clear64( csr, val) __csrrw64(csr_read_clear, csr, csr ## H, val)
#define csr_clear64( csr, val) __csrw64 (csr_clear, csr, csr ## H, val)
unsigned long csr_read_num(int csr_num);
void csr_write_num(int csr_num, unsigned long val);
@@ -163,7 +191,7 @@ void csr_write_num(int csr_num, unsigned long val);
} while (0)
/* Get current HART id */
#define current_hartid() ((unsigned int)csr_read(CSR_MHARTID))
#define current_hartid() ((unsigned int)csr_read_relaxed(CSR_MHARTID))
/* determine CPU extension, return non-zero support */
int misa_extension_imp(char ext);

View File

@@ -32,6 +32,8 @@
#define MSTATUS_TVM _UL(0x00100000)
#define MSTATUS_TW _UL(0x00200000)
#define MSTATUS_TSR _UL(0x00400000)
#define MSTATUS_SPELP _UL(0x00800000)
#define MSTATUS_SDT _UL(0x01000000)
#define MSTATUS32_SD _UL(0x80000000)
#if __riscv_xlen == 64
#define MSTATUS_UXL _ULL(0x0000000300000000)
@@ -41,12 +43,16 @@
#define MSTATUS_GVA _ULL(0x0000004000000000)
#define MSTATUS_GVA_SHIFT 38
#define MSTATUS_MPV _ULL(0x0000008000000000)
#define MSTATUS_MPELP _ULL(0x0000020000000000)
#define MSTATUS_MDT _ULL(0x0000040000000000)
#else
#define MSTATUSH_SBE _UL(0x00000010)
#define MSTATUSH_MBE _UL(0x00000020)
#define MSTATUSH_GVA _UL(0x00000040)
#define MSTATUSH_GVA_SHIFT 6
#define MSTATUSH_MPV _UL(0x00000080)
#define MSTATUSH_MPELP _UL(0x00000200)
#define MSTATUSH_MDT _UL(0x00000400)
#endif
#define MSTATUS32_SD _UL(0x80000000)
#define MSTATUS64_SD _ULL(0x8000000000000000)
@@ -80,6 +86,8 @@
#define HSTATUS_GVA _UL(0x00000040)
#define HSTATUS_VSBE _UL(0x00000020)
#define MTVEC_MODE _UL(0x00000003)
#define MCAUSE_IRQ_MASK (_UL(1) << (__riscv_xlen - 1))
#define IRQ_S_SOFT 1
@@ -207,12 +215,19 @@
#endif
#define MHPMEVENT_SSCOF_MASK _ULL(0xFFFF000000000000)
#define MHPMEVENT_SSCOF_MASK _ULL(0xFF00000000000000)
#define ENVCFG_STCE (_ULL(1) << 63)
#define ENVCFG_PBMTE (_ULL(1) << 62)
#define ENVCFG_ADUE (_ULL(1) << 61)
#define ENVCFG_ADUE_SHIFT 61
#define ENVCFG_ADUE (_ULL(1) << ENVCFG_ADUE_SHIFT)
#define ENVCFG_CDE (_ULL(1) << 60)
#define ENVCFG_DTE_SHIFT 59
#define ENVCFG_DTE (_ULL(1) << ENVCFG_DTE_SHIFT)
#define ENVCFG_PMM (_ULL(0x3) << 32)
#define ENVCFG_PMM_PMLEN_0 (_ULL(0x0) << 32)
#define ENVCFG_PMM_PMLEN_7 (_ULL(0x2) << 32)
#define ENVCFG_PMM_PMLEN_16 (_ULL(0x3) << 32)
#define ENVCFG_CBZE (_UL(1) << 7)
#define ENVCFG_CBCFE (_UL(1) << 6)
#define ENVCFG_CBIE_SHIFT 4
@@ -220,6 +235,10 @@
#define ENVCFG_CBIE_ILL _UL(0x0)
#define ENVCFG_CBIE_FLUSH _UL(0x1)
#define ENVCFG_CBIE_INV _UL(0x3)
#define ENVCFG_SSE_SHIFT 3
#define ENVCFG_SSE (_UL(1) << ENVCFG_SSE_SHIFT)
#define ENVCFG_LPE_SHIFT 2
#define ENVCFG_LPE (_UL(1) << ENVCFG_LPE_SHIFT)
#define ENVCFG_FIOM _UL(0x1)
/* ===== User-level CSRs ===== */
@@ -228,6 +247,7 @@
#define CSR_USTATUS 0x000
#define CSR_UIE 0x004
#define CSR_UTVEC 0x005
#define CSR_SSP 0x011
/* User Trap Handling (N-extension) */
#define CSR_USCRATCH 0x040
@@ -358,6 +378,17 @@
#define CSR_SSTATEEN2 0x10E
#define CSR_SSTATEEN3 0x10F
/* Machine-Level Control transfer records CSRs */
#define CSR_MCTRCTL 0x34e
/* Supervisor-Level Control transfer records CSRs */
#define CSR_SCTRCTL 0x14e
#define CSR_SCTRSTATUS 0x14f
#define CSR_SCTRDEPTH 0x15f
/* VS-Level Control transfer records CSRs */
#define CSR_VSCTRCTL 0x24e
/* ===== Hypervisor-level CSRs ===== */
/* Hypervisor Trap Setup (H-extension) */
@@ -746,6 +777,12 @@
#define CSR_MVIPH 0x319
#define CSR_MIPH 0x354
/* Vector extension registers */
#define CSR_VSTART 0x8
#define CSR_VL 0xc20
#define CSR_VTYPE 0xc21
#define CSR_VLENB 0xc22
/* ===== Trap/Exception Causes ===== */
#define CAUSE_MISALIGNED_FETCH 0x0
@@ -763,6 +800,8 @@
#define CAUSE_FETCH_PAGE_FAULT 0xc
#define CAUSE_LOAD_PAGE_FAULT 0xd
#define CAUSE_STORE_PAGE_FAULT 0xf
#define CAUSE_DOUBLE_TRAP 0x10
#define CAUSE_SW_CHECK_EXCP 0x12
#define CAUSE_FETCH_GUEST_PAGE_FAULT 0x14
#define CAUSE_LOAD_GUEST_PAGE_FAULT 0x15
#define CAUSE_VIRTUAL_INST_FAULT 0x16
@@ -774,6 +813,8 @@
#define SMSTATEEN0_CS (_ULL(1) << SMSTATEEN0_CS_SHIFT)
#define SMSTATEEN0_FCSR_SHIFT 1
#define SMSTATEEN0_FCSR (_ULL(1) << SMSTATEEN0_FCSR_SHIFT)
#define SMSTATEEN0_CTR_SHIFT 54
#define SMSTATEEN0_CTR (_ULL(1) << SMSTATEEN0_CTR_SHIFT)
#define SMSTATEEN0_CONTEXT_SHIFT 57
#define SMSTATEEN0_CONTEXT (_ULL(1) << SMSTATEEN0_CONTEXT_SHIFT)
#define SMSTATEEN0_IMSIC_SHIFT 58
@@ -872,11 +913,365 @@
#define INSN_MASK_FENCE_TSO 0xffffffff
#define INSN_MATCH_FENCE_TSO 0x8330000f
#define INSN_MASK_VECTOR_UNIT_STRIDE 0xfdf0707f
#define INSN_MASK_VECTOR_FAULT_ONLY_FIRST 0xfdf0707f
#define INSN_MASK_VECTOR_STRIDE 0xfc00707f
#define INSN_MASK_VECTOR_WHOLE_REG 0xfff0707f
#define INSN_MASK_VECTOR_INDEXED 0xfc00707f
#define INSN_MATCH_VLUXSEG(n, bits) ((((n) - 1) << 29) | 0x04000007 | \
((bits) == 16 ? 5 : (bits) == 32 ? 6 : 7) << 12)
#define INSN_MATCH_VSUXSEG(n, bits) ((((n) - 1) << 29) | 0x04000027 | \
((bits) == 16 ? 5 : (bits) == 32 ? 6 : 7) << 12)
#define INSN_MATCH_VLOXSEG(n, bits) ((((n) - 1) << 29) | 0x0c000007 | \
((bits) == 16 ? 5 : (bits) == 32 ? 6 : 7) << 12)
#define INSN_MATCH_VSOXSEG(n, bits) ((((n) - 1) << 29) | 0x0c000027 | \
((bits) == 16 ? 5 : (bits) == 32 ? 6 : 7) << 12)
#define INSN_MATCH_VLSSEG(n, bits) ((((n) - 1) << 29) | 0x08000007 | \
((bits) == 16 ? 5 : (bits) == 32 ? 6 : 7) << 12)
#define INSN_MATCH_VSSSEG(n, bits) ((((n) - 1) << 29) | 0x08000027 | \
((bits) == 16 ? 5 : (bits) == 32 ? 6 : 7) << 12)
#define INSN_MATCH_VSSEG(n, bits) ((((n) - 1) << 29) | 0x00004027 | \
((bits) == 16 ? 5 : (bits) == 32 ? 6 : 7) << 12)
#define INSN_MATCH_VLSEG(n, bits) ((((n) - 1) << 29) | 0x00004007 | \
((bits) == 16 ? 5 : (bits) == 32 ? 6 : 7) << 12)
#define INSN_MATCH_VLSEGFF(n, bits) ((((n) - 1) << 29) | 0x1000007 | \
((bits) == 16 ? 5 : (bits) == 32 ? 6 : 7) << 12)
#define INSN_MATCH_VLE16V 0x00005007
#define INSN_MATCH_VLE32V 0x00006007
#define INSN_MATCH_VLE64V 0x00007007
#define INSN_MATCH_VSE16V 0x00005027
#define INSN_MATCH_VSE32V 0x00006027
#define INSN_MATCH_VSE64V 0x00007027
#define INSN_MATCH_VLSE16V 0x08005007
#define INSN_MATCH_VLSE32V 0x08006007
#define INSN_MATCH_VLSE64V 0x08007007
#define INSN_MATCH_VSSE16V 0x08005027
#define INSN_MATCH_VSSE32V 0x08006027
#define INSN_MATCH_VSSE64V 0x08007027
#define INSN_MATCH_VLOXEI16V 0x0c005007
#define INSN_MATCH_VLOXEI32V 0x0c006007
#define INSN_MATCH_VLOXEI64V 0x0c007007
#define INSN_MATCH_VSOXEI16V 0x0c005027
#define INSN_MATCH_VSOXEI32V 0x0c006027
#define INSN_MATCH_VSOXEI64V 0x0c007027
#define INSN_MATCH_VLUXEI16V 0x04005007
#define INSN_MATCH_VLUXEI32V 0x04006007
#define INSN_MATCH_VLUXEI64V 0x04007007
#define INSN_MATCH_VSUXEI16V 0x04005027
#define INSN_MATCH_VSUXEI32V 0x04006027
#define INSN_MATCH_VSUXEI64V 0x04007027
#define INSN_MATCH_VLE16FFV 0x01005007
#define INSN_MATCH_VLE32FFV 0x01006007
#define INSN_MATCH_VLE64FFV 0x01007007
#define INSN_MATCH_VL1RE8V 0x02800007
#define INSN_MATCH_VL1RE16V 0x02805007
#define INSN_MATCH_VL1RE32V 0x02806007
#define INSN_MATCH_VL1RE64V 0x02807007
#define INSN_MATCH_VL2RE8V 0x22800007
#define INSN_MATCH_VL2RE16V 0x22805007
#define INSN_MATCH_VL2RE32V 0x22806007
#define INSN_MATCH_VL2RE64V 0x22807007
#define INSN_MATCH_VL4RE8V 0x62800007
#define INSN_MATCH_VL4RE16V 0x62805007
#define INSN_MATCH_VL4RE32V 0x62806007
#define INSN_MATCH_VL4RE64V 0x62807007
#define INSN_MATCH_VL8RE8V 0xe2800007
#define INSN_MATCH_VL8RE16V 0xe2805007
#define INSN_MATCH_VL8RE32V 0xe2806007
#define INSN_MATCH_VL8RE64V 0xe2807007
#define INSN_MATCH_VS1RV 0x02800027
#define INSN_MATCH_VS2RV 0x22800027
#define INSN_MATCH_VS4RV 0x62800027
#define INSN_MATCH_VS8RV 0xe2800027
#define INSN_OPCODE_MASK 0x7f
#define INSN_OPCODE_VECTOR_LOAD 0x07
#define INSN_OPCODE_VECTOR_STORE 0x27
#define INSN_OPCODE_AMO 0x2f
#define IS_VECTOR_LOAD_STORE(insn) \
((((insn) & INSN_OPCODE_MASK) == INSN_OPCODE_VECTOR_LOAD) || \
(((insn) & INSN_OPCODE_MASK) == INSN_OPCODE_VECTOR_STORE))
#define IS_VECTOR_INSN_MATCH(insn, match, mask) \
(((insn) & (mask)) == ((match) & (mask)))
#define IS_UNIT_STRIDE_MATCH(insn, match) \
IS_VECTOR_INSN_MATCH(insn, match, INSN_MASK_VECTOR_UNIT_STRIDE)
#define IS_STRIDE_MATCH(insn, match) \
IS_VECTOR_INSN_MATCH(insn, match, INSN_MASK_VECTOR_STRIDE)
#define IS_INDEXED_MATCH(insn, match) \
IS_VECTOR_INSN_MATCH(insn, match, INSN_MASK_VECTOR_INDEXED)
#define IS_FAULT_ONLY_FIRST_MATCH(insn, match) \
IS_VECTOR_INSN_MATCH(insn, match, INSN_MASK_VECTOR_FAULT_ONLY_FIRST)
#define IS_WHOLE_REG_MATCH(insn, match) \
IS_VECTOR_INSN_MATCH(insn, match, INSN_MASK_VECTOR_WHOLE_REG)
#define IS_UNIT_STRIDE_LOAD(insn) ( \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLE16V) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLE32V) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLE64V) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(2, 16)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(3, 16)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(4, 16)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(5, 16)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(6, 16)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(7, 16)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(8, 16)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(2, 32)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(3, 32)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(4, 32)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(5, 32)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(6, 32)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(7, 32)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(8, 32)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(2, 64)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(3, 64)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(4, 64)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(5, 64)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(6, 64)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(7, 64)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VLSEG(8, 64)))
#define IS_UNIT_STRIDE_STORE(insn) ( \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSE16V) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSE32V) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSE64V) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(2, 16)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(3, 16)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(4, 16)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(5, 16)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(6, 16)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(7, 16)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(8, 16)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(2, 32)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(3, 32)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(4, 32)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(5, 32)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(6, 32)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(7, 32)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(8, 32)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(2, 64)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(3, 64)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(4, 64)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(5, 64)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(6, 64)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(7, 64)) || \
IS_UNIT_STRIDE_MATCH(insn, INSN_MATCH_VSSEG(8, 64)))
#define IS_STRIDE_LOAD(insn) ( \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSE16V) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSE32V) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSE64V) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(2, 16)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(3, 16)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(4, 16)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(5, 16)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(6, 16)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(7, 16)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(8, 16)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(2, 32)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(3, 32)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(4, 32)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(5, 32)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(6, 32)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(7, 32)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(8, 32)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(2, 64)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(3, 64)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(4, 64)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(5, 64)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(6, 64)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(7, 64)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VLSSEG(8, 64)))
#define IS_STRIDE_STORE(insn) ( \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSE16V) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSE32V) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSE64V) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(2, 16)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(3, 16)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(4, 16)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(5, 16)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(6, 16)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(7, 16)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(8, 16)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(2, 32)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(3, 32)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(4, 32)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(5, 32)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(6, 32)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(7, 32)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(8, 32)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(2, 64)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(3, 64)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(4, 64)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(5, 64)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(6, 64)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(7, 64)) || \
IS_STRIDE_MATCH(insn, INSN_MATCH_VSSSEG(8, 64)))
#define IS_INDEXED_LOAD(insn) ( \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXEI16V) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXEI32V) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXEI64V) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXEI16V) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXEI32V) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXEI64V) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(2, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(3, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(4, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(5, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(6, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(7, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(8, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(2, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(3, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(4, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(5, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(6, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(7, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(8, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(2, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(3, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(4, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(5, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(6, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(7, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLUXSEG(8, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(2, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(3, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(4, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(5, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(6, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(7, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(8, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(2, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(3, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(4, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(5, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(6, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(7, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(8, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(2, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(3, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(4, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(5, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(6, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(7, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VLOXSEG(8, 64)))
#define IS_INDEXED_STORE(insn) ( \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXEI16V) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXEI32V) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXEI64V) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXEI16V) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXEI32V) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXEI64V) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(2, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(3, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(4, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(5, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(6, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(7, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(8, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(2, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(3, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(4, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(5, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(6, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(7, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(8, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(2, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(3, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(4, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(5, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(6, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(7, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSUXSEG(8, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(2, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(3, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(4, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(5, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(6, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(7, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(8, 16)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(2, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(3, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(4, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(5, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(6, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(7, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(8, 32)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(2, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(3, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(4, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(5, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(6, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(7, 64)) || \
IS_INDEXED_MATCH(insn, INSN_MATCH_VSOXSEG(8, 64)))
#define IS_FAULT_ONLY_FIRST_LOAD(insn) ( \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLE16FFV) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLE32FFV) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLE64FFV) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(2, 16)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(3, 16)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(4, 16)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(5, 16)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(6, 16)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(7, 16)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(8, 16)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(2, 32)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(3, 32)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(4, 32)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(5, 32)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(6, 32)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(7, 32)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(8, 32)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(2, 64)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(3, 64)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(4, 64)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(5, 64)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(6, 64)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(7, 64)) || \
IS_FAULT_ONLY_FIRST_MATCH(insn, INSN_MATCH_VLSEGFF(8, 64)))
#define IS_WHOLE_REG_LOAD(insn) ( \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VL1RE8V) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VL1RE16V) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VL1RE32V) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VL1RE64V) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VL2RE8V) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VL2RE16V) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VL2RE32V) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VL2RE64V) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VL4RE8V) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VL4RE16V) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VL4RE32V) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VL4RE64V) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VL8RE8V) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VL8RE16V) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VL8RE32V) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VL8RE64V))
#define IS_WHOLE_REG_STORE(insn) ( \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VS1RV) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VS2RV) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VS4RV) || \
IS_WHOLE_REG_MATCH(insn, INSN_MATCH_VS8RV))
#if __riscv_xlen == 64
/* 64-bit read for VS-stage address translation (RV64) */
#define INSN_PSEUDO_VS_LOAD 0x00003000
/* 64-bit write for VS-stage address translation (RV64) */
#define INSN_PSEUDO_VS_STORE 0x00003020
@@ -892,6 +1287,25 @@
#error "Unexpected __riscv_xlen"
#endif
#define MASK_FUNCT3 0x7000
#define SHIFT_FUNCT3 12
#define MASK_RS1 0xf8000
#define MASK_RS2 0x1f00000
#define MASK_RD 0xf80
#define MASK_CSR 0xfff00000
#define SHIFT_CSR 20
#define MASK_AQRL 0x06000000
#define SHIFT_AQRL 25
#define VM_MASK 0x1
#define VIEW_MASK 0x3
#define VSEW_MASK 0x3
#define VLMUL_MASK 0x7
#define VD_MASK 0x1f
#define VS2_MASK 0x1f
#define INSN_16BIT_MASK 0x3
#define INSN_32BIT_MASK 0x1c
@@ -903,13 +1317,12 @@
#define INSN_LEN(insn) (INSN_IS_16BIT(insn) ? 2 : 4)
#if __riscv_xlen == 64
#define LOG_REGBYTES 3
#else
#define LOG_REGBYTES 2
#endif
#define REGBYTES (1 << LOG_REGBYTES)
#define SH_VSEW 3
#define SH_VIEW 12
#define SH_VD 7
#define SH_VS2 20
#define SH_VM 25
#define SH_MEW 28
#define SH_RD 7
#define SH_RS1 15
#define SH_RS2 20
@@ -938,28 +1351,39 @@
#define SHIFT_RIGHT(x, y) \
((y) < 0 ? ((x) << -(y)) : ((x) >> (y)))
#define REG_MASK \
((1 << (5 + LOG_REGBYTES)) - (1 << LOG_REGBYTES))
#define GET_FUNC3(insn) ((insn & MASK_FUNCT3) >> SHIFT_FUNCT3)
#define GET_RM(insn) GET_FUNC3(insn)
#define GET_RS1_NUM(insn) ((insn & MASK_RS1) >> SH_RS1)
#define GET_RS2_NUM(insn) ((insn & MASK_RS2) >> SH_RS2)
#define GET_RS1S_NUM(insn) RVC_RS1S(insn)
#define GET_RS2S_NUM(insn) RVC_RS2S(insn)
#define GET_RS2C_NUM(insn) RVC_RS2(insn)
#define GET_RD_NUM(insn) ((insn & MASK_RD) >> SH_RD)
#define GET_CSR_NUM(insn) ((insn & MASK_CSR) >> SHIFT_CSR)
#define GET_AQRL(insn) ((insn & MASK_AQRL) >> SHIFT_AQRL)
#define REG_OFFSET(insn, pos) \
(SHIFT_RIGHT((insn), (pos) - LOG_REGBYTES) & REG_MASK)
#define REG_PTR(insn, pos, regs) \
(ulong *)((ulong)(regs) + REG_OFFSET(insn, pos))
#define GET_RM(insn) (((insn) >> 12) & 7)
#define GET_RS1(insn, regs) (*REG_PTR(insn, SH_RS1, regs))
#define GET_RS2(insn, regs) (*REG_PTR(insn, SH_RS2, regs))
#define GET_RS1S(insn, regs) (*REG_PTR(RVC_RS1S(insn), 0, regs))
#define GET_RS2S(insn, regs) (*REG_PTR(RVC_RS2S(insn), 0, regs))
#define GET_RS2C(insn, regs) (*REG_PTR(insn, SH_RS2C, regs))
#define GET_SP(regs) (*REG_PTR(2, 0, regs))
#define SET_RD(insn, regs, val) (*REG_PTR(insn, SH_RD, regs) = (val))
#define IMM_I(insn) ((s32)(insn) >> 20)
#define IMM_S(insn) (((s32)(insn) >> 25 << 5) | \
(s32)(((insn) >> 7) & 0x1f))
#define MASK_FUNCT3 0x7000
#define IS_MASKED(insn) (((insn >> SH_VM) & VM_MASK) == 0)
#define GET_VD(insn) ((insn >> SH_VD) & VD_MASK)
#define GET_VS2(insn) ((insn >> SH_VS2) & VS2_MASK)
#define GET_VIEW(insn) (((insn) >> SH_VIEW) & VIEW_MASK)
#define GET_MEW(insn) (((insn) >> SH_MEW) & 1)
#define GET_VSEW(vtype) (((vtype) >> SH_VSEW) & VSEW_MASK)
#define GET_VLMUL(vtype) ((vtype) & VLMUL_MASK)
#define GET_LEN(view) (1UL << (view))
#define GET_NF(insn) (1 + ((insn >> 29) & 7))
#define GET_VEMUL(vlmul, view, vsew) ((vlmul + view - vsew) & 7)
#define GET_EMUL(vemul) (1UL << ((vemul) >= 4 ? 0 : (vemul)))
#define CSRRW 1
#define CSRRS 2
#define CSRRC 3
#define CSRRWI 5
#define CSRRSI 6
#define CSRRCI 7
/* clang-format on */

View File

@@ -15,7 +15,6 @@
#include <sbi/sbi_types.h>
#define GET_PRECISION(insn) (((insn) >> 25) & 3)
#define GET_RM(insn) (((insn) >> 12) & 7)
#define PRECISION_S 0
#define PRECISION_D 1

View File

@@ -130,4 +130,17 @@ static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1,
__bitmap_xor(dst, src1, src2, nbits);
}
static inline int bitmap_weight(const unsigned long *src, int nbits)
{
int i, res = 0;
for (i = 0; i < nbits / BITS_PER_LONG; i++)
res += sbi_popcount(src[i]);
if (nbits % BITS_PER_LONG)
res += sbi_popcount(src[i] & BITMAP_LAST_WORD_MASK(nbits));
return res;
}
#endif

View File

@@ -14,6 +14,8 @@
#define BITS_PER_LONG (8 * __SIZEOF_LONG__)
#define BITS_PER_LONG_LONG 64
#define EXTRACT_FIELD(val, which) \
(((val) & (which)) / ((which) & ~((which)-1)))
#define INSERT_FIELD(val, which, fieldval) \
@@ -28,9 +30,13 @@
#define BIT_WORD_OFFSET(bit) ((bit) & (BITS_PER_LONG - 1))
#define BIT_ALIGN(bit, align) (((bit) + ((align) - 1)) & ~((align) - 1))
#define BIT_ULL(nr) (1ULL << (nr))
#define GENMASK(h, l) \
(((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
#define GENMASK_ULL(h, l) \
(((~0ULL) - (1ULL << (l)) + 1) & (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h))))
/**
* sbi_ffs - find first (less-significant) set bit in a long word.
* @word: The word to search
@@ -119,14 +125,22 @@ static inline unsigned long sbi_fls(unsigned long word)
*/
static inline unsigned long sbi_popcount(unsigned long word)
{
unsigned long count = 0;
unsigned long count;
while (word) {
word &= word - 1;
count++;
}
return count;
#if BITS_PER_LONG == 64
count = word - ((word >> 1) & 0x5555555555555555ul);
count = (count & 0x3333333333333333ul) + ((count >> 2) & 0x3333333333333333ul);
count = (count + (count >> 4)) & 0x0F0F0F0F0F0F0F0Ful;
count = count + (count >> 8);
count = count + (count >> 16);
return (count + (count >> 32)) & 0x00000000000000FFul;
#else
count = word - ((word >> 1) & 0x55555555);
count = (count & 0x33333333) + ((count >> 2) & 0x33333333);
count = (count + (count >> 4)) & 0x0F0F0F0F;
count = count + (count >> 8);
return (count + (count >> 16)) & 0x000000FF;
#endif
}
#define for_each_set_bit(bit, addr, size) \

View File

@@ -14,13 +14,13 @@
# define _conv_cast(type, val) ((type)(val))
#endif
#define BSWAP16(x) ((((x) & 0x00ff) << 8) | \
#define __BSWAP16(x) ((((x) & 0x00ff) << 8) | \
(((x) & 0xff00) >> 8))
#define BSWAP32(x) ((((x) & 0x000000ff) << 24) | \
#define __BSWAP32(x) ((((x) & 0x000000ff) << 24) | \
(((x) & 0x0000ff00) << 8) | \
(((x) & 0x00ff0000) >> 8) | \
(((x) & 0xff000000) >> 24))
#define BSWAP64(x) ((((x) & 0x00000000000000ffULL) << 56) | \
#define __BSWAP64(x) ((((x) & 0x00000000000000ffULL) << 56) | \
(((x) & 0x000000000000ff00ULL) << 40) | \
(((x) & 0x0000000000ff0000ULL) << 24) | \
(((x) & 0x00000000ff000000ULL) << 8) | \
@@ -29,6 +29,10 @@
(((x) & 0x00ff000000000000ULL) >> 40) | \
(((x) & 0xff00000000000000ULL) >> 56))
#define BSWAP64(x) ({ uint64_t _sv = (x); __BSWAP64(_sv); })
#define BSWAP32(x) ({ uint32_t _sv = (x); __BSWAP32(_sv); })
#define BSWAP16(x) ({ uint16_t _sv = (x); __BSWAP16(_sv); })
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* CPU(little-endian) */
#define cpu_to_be16(x) _conv_cast(uint16_t, BSWAP16(x))
#define cpu_to_be32(x) _conv_cast(uint32_t, BSWAP32(x))

View File

@@ -58,8 +58,6 @@ void sbi_console_set_device(const struct sbi_console_device *dev);
struct sbi_scratch;
int sbi_console_init(struct sbi_scratch *scratch);
#define SBI_ASSERT(cond, args) do { \
if (unlikely(!(cond))) \
sbi_panic args; \

View File

@@ -18,7 +18,7 @@
({ \
register ulong tinfo asm("a3") = (ulong)trap; \
register ulong ttmp asm("a4"); \
register ulong mtvec = sbi_hart_expected_trap_addr(); \
register ulong mtvec = (ulong)sbi_hart_expected_trap; \
register ulong ret = 0; \
((struct sbi_trap_info *)(trap))->cause = 0; \
asm volatile( \
@@ -37,7 +37,7 @@
({ \
register ulong tinfo asm("a3") = (ulong)trap; \
register ulong ttmp asm("a4"); \
register ulong mtvec = sbi_hart_expected_trap_addr(); \
register ulong mtvec = (ulong)sbi_hart_expected_trap; \
((struct sbi_trap_info *)(trap))->cause = 0; \
asm volatile( \
"add %[ttmp], %[tinfo], zero\n" \

View File

@@ -90,7 +90,7 @@ struct sbi_dbtr_hart_triggers_state {
}while (0);
/** SBI shared mem messages layout */
struct sbi_dbtr_shmem_entry {
union sbi_dbtr_shmem_entry {
struct sbi_dbtr_data_msg data;
struct sbi_dbtr_id_msg id;
};
@@ -115,8 +115,7 @@ int sbi_dbtr_uninstall_trig(unsigned long trig_idx_base,
int sbi_dbtr_enable_trig(unsigned long trig_idx_base,
unsigned long trig_idx_mask);
int sbi_dbtr_update_trig(unsigned long smode,
unsigned long trig_idx_base,
unsigned long trig_idx_mask);
unsigned long trig_count);
int sbi_dbtr_disable_trig(unsigned long trig_idx_base,
unsigned long trig_idx_mask);

View File

@@ -11,9 +11,11 @@
#define __SBI_DOMAIN_H__
#include <sbi/riscv_locks.h>
#include <sbi/sbi_list.h>
#include <sbi/sbi_types.h>
#include <sbi/sbi_hartmask.h>
#include <sbi/sbi_domain_context.h>
#include <sbi/sbi_domain_data.h>
struct sbi_scratch;
@@ -158,21 +160,15 @@ struct sbi_domain_memregion {
unsigned long flags;
};
/** Maximum number of domains */
#define SBI_DOMAIN_MAX_INDEX 32
/** Representation of OpenSBI domain */
struct sbi_domain {
/**
* Logical index of this domain
* Note: This set by sbi_domain_finalize() in the coldboot path
*/
/** Node in linked list of domains */
struct sbi_dlist node;
/** Internal state of per-domain data */
struct sbi_domain_data_priv data_priv;
/** Logical index of this domain */
u32 index;
/**
* HARTs assigned to this domain
* Note: This set by sbi_domain_init() and sbi_domain_finalize()
* in the coldboot path
*/
/** HARTs assigned to this domain */
struct sbi_hartmask assigned_harts;
/** Spinlock for accessing assigned_harts */
spinlock_t assigned_harts_lock;
@@ -180,8 +176,6 @@ struct sbi_domain {
char name[64];
/** Possible HARTs in this domain */
const struct sbi_hartmask *possible_harts;
/** Contexts for possible HARTs indexed by hartindex */
struct sbi_context *hartindex_to_context_table[SBI_HARTMASK_MAX_BITS];
/** Array of memory regions terminated by a region with order zero */
struct sbi_domain_memregion *regions;
/** HART id of the HART booting this domain */
@@ -211,18 +205,14 @@ void sbi_update_hartindex_to_domain(u32 hartindex, struct sbi_domain *dom);
/** Get pointer to sbi_domain for current HART */
#define sbi_domain_thishart_ptr() \
sbi_hartindex_to_domain(sbi_hartid_to_hartindex(current_hartid()))
sbi_hartindex_to_domain(current_hartindex())
/** Index to domain table */
extern struct sbi_domain *domidx_to_domain_table[];
/** Get pointer to sbi_domain from index */
#define sbi_index_to_domain(__index) \
domidx_to_domain_table[__index]
/** Head of linked list of domains */
extern struct sbi_dlist domain_list;
/** Iterate over each domain */
#define sbi_domain_for_each(__i, __d) \
for ((__i) = 0; ((__d) = sbi_index_to_domain(__i)); (__i)++)
#define sbi_domain_for_each(__d) \
sbi_list_for_each_entry(__d, &domain_list, node)
/** Iterate over each memory region of a domain */
#define sbi_domain_for_each_memregion(__d, __r) \
@@ -231,20 +221,19 @@ extern struct sbi_domain *domidx_to_domain_table[];
/**
* Check whether given HART is assigned to specified domain
* @param dom pointer to domain
* @param hartid the HART ID
* @param hartindex the HART index
* @return true if HART is assigned to domain otherwise false
*/
bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartid);
bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartindex);
/**
* Get ulong assigned HART mask for given domain and HART base ID
* Get the assigned HART mask for given domain
* @param dom pointer to domain
* @param hbase the HART base ID
* @return ulong possible HART mask
* Note: the return ulong mask will be set to zero on failure.
* @param mask the output hartmask to fill
* @return 0 on success and SBI_Exxx (< 0) on failure
*/
ulong sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom,
ulong hbase);
int sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom,
struct sbi_hartmask *mask);
/**
* Initialize a domain memory region based on it's physical
@@ -304,16 +293,6 @@ void sbi_domain_dump_all(const char *suffix);
int sbi_domain_register(struct sbi_domain *dom,
const struct sbi_hartmask *assign_mask);
/**
* Add a memory region to the root domain
* @param reg pointer to the memory region to be added
*
* @return 0 on success
* @return SBI_EALREADY if memory region conflicts with the existing one
* @return SBI_EINVAL otherwise
*/
int sbi_domain_root_add_memregion(const struct sbi_domain_memregion *reg);
/**
* Add a memory range with its flags to the root domain
* @param addr start physical address of memory range
@@ -328,8 +307,11 @@ int sbi_domain_root_add_memregion(const struct sbi_domain_memregion *reg);
int sbi_domain_root_add_memrange(unsigned long addr, unsigned long size,
unsigned long align, unsigned long region_flags);
/** Finalize domain tables and startup non-root domains */
int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid);
/** Startup non-root domains */
int sbi_domain_startup(struct sbi_scratch *scratch, u32 cold_hartid);
/** Finalize domain tables */
int sbi_domain_finalize(struct sbi_scratch *scratch);
/** Initialize domains */
int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid);

58
include/sbi/sbi_domain_context.h Executable file → Normal file
View File

@@ -8,54 +8,8 @@
#define __SBI_DOMAIN_CONTEXT_H__
#include <sbi/sbi_types.h>
#include <sbi/sbi_trap.h>
#include <sbi/sbi_domain.h>
/** Context representation for a hart within a domain */
struct sbi_context {
/** Trap-related states such as GPRs, mepc, and mstatus */
struct sbi_trap_context trap_ctx;
/** Supervisor status register */
unsigned long sstatus;
/** Supervisor interrupt enable register */
unsigned long sie;
/** Supervisor trap vector base address register */
unsigned long stvec;
/** Supervisor scratch register for temporary storage */
unsigned long sscratch;
/** Supervisor exception program counter register */
unsigned long sepc;
/** Supervisor cause register */
unsigned long scause;
/** Supervisor trap value register */
unsigned long stval;
/** Supervisor interrupt pending register */
unsigned long sip;
/** Supervisor address translation and protection register */
unsigned long satp;
/** Counter-enable register */
unsigned long scounteren;
/** Supervisor environment configuration register */
unsigned long senvcfg;
/** Reference to the owning domain */
struct sbi_domain *dom;
/** Previous context (caller) to jump to during context exits */
struct sbi_context *prev_ctx;
/** Is context initialized and runnable */
bool initialized;
};
/** Get the context pointer for a given hart index and domain */
#define sbi_hartindex_to_domain_context(__hartindex, __d) \
(__d)->hartindex_to_context_table[__hartindex]
/** Macro to obtain the current hart's context pointer */
#define sbi_domain_context_thishart_ptr() \
sbi_hartindex_to_domain_context( \
sbi_hartid_to_hartindex(current_hartid()), \
sbi_domain_thishart_ptr())
struct sbi_domain;
/**
* Enter a specific domain context synchronously
@@ -74,4 +28,14 @@ int sbi_domain_context_enter(struct sbi_domain *dom);
*/
int sbi_domain_context_exit(void);
/**
* Initialize domain context support
*
* @return 0 on success and negative error code on failure
*/
int sbi_domain_context_init(void);
/* Deinitialize domain context support */
void sbi_domain_context_deinit(void);
#endif // __SBI_DOMAIN_CONTEXT_H__

View File

@@ -0,0 +1,93 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2024 Ventana Micro Systems Inc.
*/
#ifndef __SBI_DOMAIN_DATA_H__
#define __SBI_DOMAIN_DATA_H__
#include <sbi/sbi_types.h>
#include <sbi/sbi_list.h>
struct sbi_domain;
/** Maximum domain data per-domain */
#define SBI_DOMAIN_MAX_DATA_PTRS 32
/** Representation of per-domain data */
struct sbi_domain_data_priv {
/** Array of domain data pointers indexed by domain data identifier */
void *idx_to_data_ptr[SBI_DOMAIN_MAX_DATA_PTRS];
};
/** Representation of a domain data */
struct sbi_domain_data {
/**
* Head is used for maintaining data list
*
* Note: initialized by domain framework
*/
struct sbi_dlist head;
/**
* Identifier which used to locate per-domain data
*
* Note: initialized by domain framework
*/
unsigned long data_idx;
/** Size of per-domain data */
unsigned long data_size;
/** Optional callback to setup domain data */
int (*data_setup)(struct sbi_domain *dom,
struct sbi_domain_data *data, void *data_ptr);
/** Optional callback to cleanup domain data */
void (*data_cleanup)(struct sbi_domain *dom,
struct sbi_domain_data *data, void *data_ptr);
};
/**
* Get per-domain data pointer for a given domain
* @param dom pointer to domain
* @param data pointer to domain data
*
* @return per-domain data pointer
*/
void *sbi_domain_data_ptr(struct sbi_domain *dom, struct sbi_domain_data *data);
/**
* Setup all domain data for a domain
* @param dom pointer to domain
*
* @return 0 on success and negative error code on failure
*
* Note: This function is used internally within domain framework.
*/
int sbi_domain_setup_data(struct sbi_domain *dom);
/**
* Cleanup all domain data for a domain
* @param dom pointer to domain
*
* Note: This function is used internally within domain framework.
*/
void sbi_domain_cleanup_data(struct sbi_domain *dom);
/**
* Register a domain data
* @param hndl pointer to domain data
*
* @return 0 on success and negative error code on failure
*
* Note: This function must be used only in cold boot path.
*/
int sbi_domain_register_data(struct sbi_domain_data *data);
/**
* Unregister a domain data
* @param hndl pointer to domain data
*
* Note: This function must be used only in cold boot path.
*/
void sbi_domain_unregister_data(struct sbi_domain_data *data);
#endif

View File

@@ -0,0 +1,20 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 Rivos Inc.
*
* Authors:
* Clément Léger <cleger@rivosinc.com>
*/
#ifndef __SBI_DOUBLE_TRAP_H__
#define __SBI_DOUBLE_TRAP_H__
#include <sbi/sbi_types.h>
#include <sbi/sbi_trap.h>
int sbi_double_trap_handler(struct sbi_trap_context *tcntx);
void sbi_double_trap_init(struct sbi_scratch *scratch);
#endif

View File

@@ -13,7 +13,7 @@
#include <sbi/sbi_types.h>
#include <sbi/sbi_list.h>
#define SBI_ECALL_VERSION_MAJOR 2
#define SBI_ECALL_VERSION_MAJOR 3
#define SBI_ECALL_VERSION_MINOR 0
#define SBI_OPENSBI_IMPID 1
@@ -30,6 +30,8 @@ struct sbi_ecall_return {
struct sbi_ecall_extension {
/* head is used by the extension list */
struct sbi_dlist head;
/* short name of the extension */
char name[8];
/*
* extid_start and extid_end specify the range for this extension. As
* the initial range may be wider than the valid runtime range, the
@@ -38,6 +40,8 @@ struct sbi_ecall_extension {
*/
unsigned long extid_start;
unsigned long extid_end;
/* flag showing whether given extension is experimental or not */
bool experimental;
/*
* register_extensions
*
@@ -83,6 +87,8 @@ void sbi_ecall_set_impid(unsigned long impid);
struct sbi_ecall_extension *sbi_ecall_find_extension(unsigned long extid);
void sbi_ecall_get_extensions_str(char *exts_str, int exts_str_size, bool experimental);
int sbi_ecall_register_extension(struct sbi_ecall_extension *ext);
void sbi_ecall_unregister_extension(struct sbi_ecall_extension *ext);

View File

@@ -12,6 +12,8 @@
/* clang-format off */
#include <sbi/sbi_types.h>
/* SBI Extension IDs */
#define SBI_EXT_0_1_SET_TIMER 0x0
#define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1
@@ -35,6 +37,7 @@
#define SBI_EXT_DBTR 0x44425452
#define SBI_EXT_SSE 0x535345
#define SBI_EXT_FWFT 0x46574654
#define SBI_EXT_MPXY 0x4D505859
/* SBI function IDs for BASE extension*/
#define SBI_EXT_BASE_GET_SPEC_VERSION 0x0
@@ -107,6 +110,7 @@
#define SBI_EXT_PMU_COUNTER_FW_READ 0x5
#define SBI_EXT_PMU_COUNTER_FW_READ_HI 0x6
#define SBI_EXT_PMU_SNAPSHOT_SET_SHMEM 0x7
#define SBI_EXT_PMU_EVENT_GET_INFO 0x8
/* SBI function IDs for DBTR extension */
#define SBI_EXT_DBTR_NUM_TRIGGERS 0x0
@@ -128,7 +132,8 @@ enum sbi_fwft_feature_t {
SBI_FWFT_SHADOW_STACK = 0x2,
SBI_FWFT_DOUBLE_TRAP = 0x3,
SBI_FWFT_PTE_AD_HW_UPDATING = 0x4,
SBI_FWFT_LOCAL_RESERVED_START = 0x5,
SBI_FWFT_POINTER_MASKING_PMLEN = 0x5,
SBI_FWFT_LOCAL_RESERVED_START = 0x6,
SBI_FWFT_LOCAL_RESERVED_END = 0x3fffffff,
SBI_FWFT_LOCAL_PLATFORM_START = 0x40000000,
SBI_FWFT_LOCAL_PLATFORM_END = 0x7fffffff,
@@ -244,6 +249,7 @@ enum sbi_pmu_event_type_id {
SBI_PMU_EVENT_TYPE_HW = 0x0,
SBI_PMU_EVENT_TYPE_HW_CACHE = 0x1,
SBI_PMU_EVENT_TYPE_HW_RAW = 0x2,
SBI_PMU_EVENT_TYPE_HW_RAW_V2 = 0x3,
SBI_PMU_EVENT_TYPE_FW = 0xf,
SBI_PMU_EVENT_TYPE_MAX,
};
@@ -254,12 +260,19 @@ enum sbi_pmu_ctr_type {
SBI_PMU_CTR_TYPE_FW,
};
struct sbi_pmu_event_info {
uint32_t event_idx;
uint32_t output;
uint64_t event_data;
};
/* Helper macros to decode event idx */
#define SBI_PMU_EVENT_IDX_MASK 0xFFFFF
#define SBI_PMU_EVENT_IDX_TYPE_OFFSET 16
#define SBI_PMU_EVENT_IDX_TYPE_MASK (0xF << SBI_PMU_EVENT_IDX_TYPE_OFFSET)
#define SBI_PMU_EVENT_IDX_CODE_MASK 0xFFFF
#define SBI_PMU_EVENT_RAW_IDX 0x20000
#define SBI_PMU_EVENT_RAW_V2_IDX 0x30000
#define SBI_PMU_EVENT_IDX_INVALID 0xFFFFFFFF
@@ -341,6 +354,8 @@ enum sbi_cppc_reg_id {
#define SBI_EXT_SSE_DISABLE 0x00000005
#define SBI_EXT_SSE_COMPLETE 0x00000006
#define SBI_EXT_SSE_INJECT 0x00000007
#define SBI_EXT_SSE_HART_UNMASK 0x00000008
#define SBI_EXT_SSE_HART_MASK 0x00000009
/* SBI SSE Event Attributes. */
enum sbi_sse_attr_id {
@@ -365,10 +380,12 @@ enum sbi_sse_attr_id {
#define SBI_SSE_ATTR_CONFIG_ONESHOT (1 << 0)
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_STATUS_SPP BIT(0)
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_STATUS_SPIE BIT(1)
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPP BIT(0)
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPIE BIT(1)
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_HSTATUS_SPV BIT(2)
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_HSTATUS_SPVP BIT(3)
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPELP BIT(4)
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SDT BIT(5)
enum sbi_sse_state {
SBI_SSE_STATE_UNUSED = 0,
@@ -378,38 +395,77 @@ enum sbi_sse_state {
};
/* SBI SSE Event IDs. */
#define SBI_SSE_EVENT_LOCAL_RAS 0x00000000
/* Range 0x00000000 - 0x0000ffff */
#define SBI_SSE_EVENT_LOCAL_HIGH_PRIO_RAS 0x00000000
#define SBI_SSE_EVENT_LOCAL_DOUBLE_TRAP 0x00000001
#define SBI_SSE_EVENT_LOCAL_RESERVED_0_START 0x00000002
#define SBI_SSE_EVENT_LOCAL_RESERVED_0_END 0x00003fff
#define SBI_SSE_EVENT_LOCAL_PLAT_0_START 0x00004000
#define SBI_SSE_EVENT_LOCAL_PLAT_0_END 0x00007fff
#define SBI_SSE_EVENT_GLOBAL_RAS 0x00008000
#define SBI_SSE_EVENT_GLOBAL_PLAT_0_START 0x00004000
#define SBI_SSE_EVENT_GLOBAL_PLAT_0_END 0x00007fff
#define SBI_SSE_EVENT_LOCAL_PMU 0x00010000
#define SBI_SSE_EVENT_GLOBAL_HIGH_PRIO_RAS 0x00008000
#define SBI_SSE_EVENT_GLOBAL_RESERVED_0_START 0x00008001
#define SBI_SSE_EVENT_GLOBAL_RESERVED_0_END 0x0000bfff
#define SBI_SSE_EVENT_GLOBAL_PLAT_0_START 0x0000c000
#define SBI_SSE_EVENT_GLOBAL_PLAT_0_END 0x0000ffff
/* Range 0x00010000 - 0x0001ffff */
#define SBI_SSE_EVENT_LOCAL_PMU_OVERFLOW 0x00010000
#define SBI_SSE_EVENT_LOCAL_RESERVED_1_START 0x00010001
#define SBI_SSE_EVENT_LOCAL_RESERVED_1_END 0x00013fff
#define SBI_SSE_EVENT_LOCAL_PLAT_1_START 0x00014000
#define SBI_SSE_EVENT_LOCAL_PLAT_1_END 0x00017fff
#define SBI_SSE_EVENT_GLOBAL_RESERVED_1_START 0x00018000
#define SBI_SSE_EVENT_GLOBAL_RESERVED_1_END 0x0001bfff
#define SBI_SSE_EVENT_GLOBAL_PLAT_1_START 0x0001c000
#define SBI_SSE_EVENT_GLOBAL_PLAT_1_END 0x0001ffff
#define SBI_SSE_EVENT_LOCAL_PLAT_2_START 0x00024000
#define SBI_SSE_EVENT_LOCAL_PLAT_2_END 0x00027fff
#define SBI_SSE_EVENT_GLOBAL_PLAT_2_START 0x0002c000
#define SBI_SSE_EVENT_GLOBAL_PLAT_2_END 0x0002ffff
/* Range 0x00100000 - 0x0010ffff */
#define SBI_SSE_EVENT_LOCAL_LOW_PRIO_RAS 0x00100000
#define SBI_SSE_EVENT_LOCAL_RESERVED_2_START 0x00100001
#define SBI_SSE_EVENT_LOCAL_RESERVED_2_END 0x00103fff
#define SBI_SSE_EVENT_LOCAL_PLAT_2_START 0x00104000
#define SBI_SSE_EVENT_LOCAL_PLAT_2_END 0x00107fff
#define SBI_SSE_EVENT_GLOBAL_LOW_PRIO_RAS 0x00108000
#define SBI_SSE_EVENT_GLOBAL_RESERVED_2_START 0x00108001
#define SBI_SSE_EVENT_GLOBAL_RESERVED_2_END 0x0010bfff
#define SBI_SSE_EVENT_GLOBAL_PLAT_2_START 0x0010c000
#define SBI_SSE_EVENT_GLOBAL_PLAT_2_END 0x0010ffff
/* Range 0xffff0000 - 0xffffffff */
#define SBI_SSE_EVENT_LOCAL_SOFTWARE 0xffff0000
#define SBI_SSE_EVENT_LOCAL_RESERVED_3_START 0xffff0001
#define SBI_SSE_EVENT_LOCAL_RESERVED_3_END 0xffff3fff
#define SBI_SSE_EVENT_LOCAL_PLAT_3_START 0xffff4000
#define SBI_SSE_EVENT_LOCAL_PLAT_3_END 0xffff7fff
#define SBI_SSE_EVENT_GLOBAL_SOFTWARE 0xffff8000
#define SBI_SSE_EVENT_GLOBAL_RESERVED_3_START 0xffff8001
#define SBI_SSE_EVENT_GLOBAL_RESERVED_3_END 0xffffbfff
#define SBI_SSE_EVENT_GLOBAL_PLAT_3_START 0xffffc000
#define SBI_SSE_EVENT_GLOBAL_PLAT_3_END 0xffffffff
#define SBI_SSE_EVENT_GLOBAL_BIT (1 << 15)
#define SBI_SSE_EVENT_PLATFORM_BIT (1 << 14)
#define SBI_SSE_EVENT_GLOBAL_BIT BIT(15)
#define SBI_SSE_EVENT_PLATFORM_BIT BIT(14)
/* SBI function IDs for MPXY extension */
#define SBI_EXT_MPXY_GET_SHMEM_SIZE 0x0
#define SBI_EXT_MPXY_SET_SHMEM 0x1
#define SBI_EXT_MPXY_GET_CHANNEL_IDS 0x2
#define SBI_EXT_MPXY_READ_ATTRS 0x3
#define SBI_EXT_MPXY_WRITE_ATTRS 0x4
#define SBI_EXT_MPXY_SEND_MSG_WITH_RESP 0x5
#define SBI_EXT_MPXY_SEND_MSG_WITHOUT_RESP 0x6
#define SBI_EXT_MPXY_GET_NOTIFICATION_EVENTS 0x7
/* SBI base specification related macros */
#define SBI_SPEC_VERSION_MAJOR_OFFSET 24
#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f
#define SBI_SPEC_VERSION_MINOR_MASK 0xffffff
#define SBI_EXT_EXPERIMENTAL_START 0x08000000
#define SBI_EXT_EXPERIMENTAL_END 0x08FFFFFF
#define SBI_EXT_VENDOR_START 0x09000000
#define SBI_EXT_VENDOR_END 0x09FFFFFF
#define SBI_EXT_FIRMWARE_START 0x0A000000
@@ -428,8 +484,11 @@ enum sbi_sse_state {
#define SBI_ERR_NO_SHMEM -9
#define SBI_ERR_INVALID_STATE -10
#define SBI_ERR_BAD_RANGE -11
#define SBI_ERR_TIMEOUT -12
#define SBI_ERR_IO -13
#define SBI_ERR_DENIED_LOCKED -14
#define SBI_LAST_ERR SBI_ERR_BAD_RANGE
#define SBI_LAST_ERR SBI_ERR_DENIED_LOCKED
/* clang-format on */

View File

@@ -26,16 +26,18 @@
#define SBI_ENO_SHMEM SBI_ERR_NO_SHMEM
#define SBI_EINVALID_STATE SBI_ERR_INVALID_STATE
#define SBI_EBAD_RANGE SBI_ERR_BAD_RANGE
#define SBI_ETIMEOUT SBI_ERR_TIMEOUT
#define SBI_ETIMEDOUT SBI_ERR_TIMEOUT
#define SBI_EIO SBI_ERR_IO
#define SBI_EDENIED_LOCKED SBI_ERR_DENIED_LOCKED
#define SBI_ENODEV -1000
#define SBI_ENOSYS -1001
#define SBI_ETIMEDOUT -1002
#define SBI_EIO -1003
#define SBI_EILL -1004
#define SBI_ENOSPC -1005
#define SBI_ENOMEM -1006
#define SBI_EUNKNOWN -1007
#define SBI_ENOENT -1008
#define SBI_EILL -1002
#define SBI_ENOSPC -1003
#define SBI_ENOMEM -1004
#define SBI_EUNKNOWN -1005
#define SBI_ENOENT -1006
/* clang-format on */

View File

@@ -23,6 +23,18 @@ struct sbi_fifo {
u16 tail;
};
#define SBI_FIFO_INITIALIZER(__queue_mem, __entries, __entry_size) \
{ .queue = __queue_mem, \
.qlock = SPIN_LOCK_INITIALIZER, \
.num_entries = __entries, \
.entry_size = __entry_size, \
.avail = 0, \
.tail = 0, \
}
#define SBI_FIFO_DEFINE(__name, __queue_mem, __entries, __entry_size) \
struct sbi_fifo __name = SBI_FIFO_INITIALIZER(__queue_mem, __entries, __entry_size)
enum sbi_fifo_inplace_update_types {
SBI_FIFO_SKIP,
SBI_FIFO_UPDATED,
@@ -30,7 +42,7 @@ enum sbi_fifo_inplace_update_types {
};
int sbi_fifo_dequeue(struct sbi_fifo *fifo, void *data);
int sbi_fifo_enqueue(struct sbi_fifo *fifo, void *data);
int sbi_fifo_enqueue(struct sbi_fifo *fifo, void *data, bool force);
void sbi_fifo_init(struct sbi_fifo *fifo, void *queue_mem, u16 entries,
u16 entry_size);
int sbi_fifo_is_empty(struct sbi_fifo *fifo);

View File

@@ -31,7 +31,7 @@ enum sbi_hart_extensions {
SBI_HART_EXT_SMAIA = 0,
/** HART has Smepmp */
SBI_HART_EXT_SMEPMP,
/** HART has Smstateen CSR **/
/** HART has Smstateen extension **/
SBI_HART_EXT_SMSTATEEN,
/** Hart has Sscofpmt extension */
SBI_HART_EXT_SSCOFPMF,
@@ -67,6 +67,20 @@ enum sbi_hart_extensions {
SBI_HART_EXT_SVADE,
/** Hart has Svadu extension */
SBI_HART_EXT_SVADU,
/** Hart has Smnpm extension */
SBI_HART_EXT_SMNPM,
/** HART has zicfilp extension */
SBI_HART_EXT_ZICFILP,
/** HART has zicfiss extension */
SBI_HART_EXT_ZICFISS,
/** Hart has Ssdbltrp extension */
SBI_HART_EXT_SSDBLTRP,
/** HART has CTR M-mode CSRs */
SBI_HART_EXT_SMCTR,
/** HART has CTR S-mode CSRs */
SBI_HART_EXT_SSCTR,
/** HART has Ssstateen extension **/
SBI_HART_EXT_SSSTATEEN,
/** Maximum index of Hart extension */
SBI_HART_EXT_MAX,
@@ -79,6 +93,14 @@ struct sbi_hart_ext_data {
extern const struct sbi_hart_ext_data sbi_hart_ext[];
/** CSRs should be detected by access and trapping */
enum sbi_hart_csrs {
SBI_HART_CSR_CYCLE = 0,
SBI_HART_CSR_TIME,
SBI_HART_CSR_INSTRET,
SBI_HART_CSR_MAX,
};
/*
* Smepmp enforces access boundaries between M-mode and
* S/U-mode. When it is enabled, the PMPs are programmed
@@ -98,6 +120,7 @@ struct sbi_hart_features {
bool detected;
int priv_version;
unsigned long extensions[BITS_TO_LONGS(SBI_HART_EXT_MAX)];
unsigned long csrs[BITS_TO_LONGS(SBI_HART_CSR_MAX)];
unsigned int pmp_count;
unsigned int pmp_addr_bits;
unsigned int pmp_log2gran;
@@ -111,10 +134,6 @@ int sbi_hart_reinit(struct sbi_scratch *scratch);
int sbi_hart_init(struct sbi_scratch *scratch, bool cold_boot);
extern void (*sbi_hart_expected_trap)(void);
static inline ulong sbi_hart_expected_trap_addr(void)
{
return (ulong)sbi_hart_expected_trap;
}
unsigned int sbi_hart_mhpm_mask(struct sbi_scratch *scratch);
void sbi_hart_delegation_dump(struct sbi_scratch *scratch,
@@ -136,6 +155,7 @@ bool sbi_hart_has_extension(struct sbi_scratch *scratch,
enum sbi_hart_extensions ext);
void sbi_hart_get_extensions_str(struct sbi_scratch *scratch,
char *extension_str, int nestr);
bool sbi_hart_has_csr(struct sbi_scratch *scratch, enum sbi_hart_csrs csr);
void __attribute__((noreturn)) sbi_hart_hang(void);

View File

@@ -127,6 +127,18 @@ static inline void sbi_hartmask_clear_all(struct sbi_hartmask *dstp)
bitmap_zero(sbi_hartmask_bits(dstp), SBI_HARTMASK_MAX_BITS);
}
/**
* *dstp = *srcp
* @param dstp the hartmask destination
* @param srcp the hartmask source
*/
static inline void sbi_hartmask_copy(struct sbi_hartmask *dstp,
const struct sbi_hartmask *srcp)
{
bitmap_copy(sbi_hartmask_bits(dstp), sbi_hartmask_bits(srcp),
SBI_HARTMASK_MAX_BITS);
}
/**
* *dstp = *src1p & *src2p
* @param dstp the hartmask result
@@ -169,6 +181,17 @@ static inline void sbi_hartmask_xor(struct sbi_hartmask *dstp,
sbi_hartmask_bits(src2p), SBI_HARTMASK_MAX_BITS);
}
/**
* Count of bits in *srcp
* @param srcp the hartmask to count bits in
*
* Return: count of bits set in *srcp
*/
static inline int sbi_hartmask_weight(const struct sbi_hartmask *srcp)
{
return bitmap_weight(sbi_hartmask_bits(srcp), SBI_HARTMASK_MAX_BITS);
}
/**
* Iterate over each HART index in hartmask
* __i hart index

View File

@@ -12,16 +12,41 @@
#include <sbi/sbi_types.h>
/* Opaque declaration of heap control struct */
struct sbi_heap_control;
/* Global heap control structure */
extern struct sbi_heap_control global_hpctrl;
/* Alignment of heap base address and size */
#define HEAP_BASE_ALIGN 1024
struct sbi_scratch;
/** Allocate from heap area */
void *sbi_malloc(size_t size);
void *sbi_malloc_from(struct sbi_heap_control *hpctrl, size_t size);
static inline void *sbi_malloc(size_t size)
{
return sbi_malloc_from(&global_hpctrl, size);
}
/** Allocate aligned from heap area */
void *sbi_aligned_alloc_from(struct sbi_heap_control *hpctrl,
size_t alignment,size_t size);
static inline void *sbi_aligned_alloc(size_t alignment, size_t size)
{
return sbi_aligned_alloc_from(&global_hpctrl, alignment, size);
}
/** Zero allocate from heap area */
void *sbi_zalloc(size_t size);
void *sbi_zalloc_from(struct sbi_heap_control *hpctrl, size_t size);
static inline void *sbi_zalloc(size_t size)
{
return sbi_zalloc_from(&global_hpctrl, size);
}
/** Allocate array from heap area */
static inline void *sbi_calloc(size_t nitems, size_t size)
@@ -29,19 +54,48 @@ static inline void *sbi_calloc(size_t nitems, size_t size)
return sbi_zalloc(nitems * size);
}
static inline void *sbi_calloc_from(struct sbi_heap_control *hpctrl,
size_t nitems, size_t size)
{
return sbi_zalloc_from(hpctrl, nitems * size);
}
/** Free-up to heap area */
void sbi_free(void *ptr);
void sbi_free_from(struct sbi_heap_control *hpctrl, void *ptr);
static inline void sbi_free(void *ptr)
{
return sbi_free_from(&global_hpctrl, ptr);
}
/** Amount (in bytes) of free space in the heap area */
unsigned long sbi_heap_free_space(void);
unsigned long sbi_heap_free_space_from(struct sbi_heap_control *hpctrl);
static inline unsigned long sbi_heap_free_space(void)
{
return sbi_heap_free_space_from(&global_hpctrl);
}
/** Amount (in bytes) of used space in the heap area */
unsigned long sbi_heap_used_space(void);
unsigned long sbi_heap_used_space_from(struct sbi_heap_control *hpctrl);
static inline unsigned long sbi_heap_used_space(void)
{
return sbi_heap_used_space_from(&global_hpctrl);
}
/** Amount (in bytes) of reserved space in the heap area */
unsigned long sbi_heap_reserved_space(void);
unsigned long sbi_heap_reserved_space_from(struct sbi_heap_control *hpctrl);
static inline unsigned long sbi_heap_reserved_space(void)
{
return sbi_heap_reserved_space_from(&global_hpctrl);
}
/** Initialize heap area */
int sbi_heap_init(struct sbi_scratch *scratch);
int sbi_heap_init_new(struct sbi_heap_control *hpctrl, unsigned long base,
unsigned long size);
int sbi_heap_alloc_new(struct sbi_heap_control **hpctrl);
#endif

View File

@@ -10,6 +10,7 @@
#ifndef __SBI_HSM_H__
#define __SBI_HSM_H__
#include <sbi/sbi_hartmask.h>
#include <sbi/sbi_types.h>
/** Hart state managment device */
@@ -39,8 +40,12 @@ struct sbi_hsm_device {
*
* For successful non-retentive suspend, the hart will resume from
* the warm boot entry point.
*
* NOTE: mmode_resume_addr(resume address) is optional hence it
* may or may not be honored by the platform. If its not honored
* then platform must ensure to resume from the warmboot address.
*/
int (*hart_suspend)(u32 suspend_type);
int (*hart_suspend)(u32 suspend_type, ulong mmode_resume_addr);
/**
* Perform platform-specific actions to resume from a suspended state.
@@ -58,7 +63,7 @@ const struct sbi_hsm_device *sbi_hsm_get_device(void);
void sbi_hsm_set_device(const struct sbi_hsm_device *dev);
int sbi_hsm_init(struct sbi_scratch *scratch, u32 hartid, bool cold_boot);
int sbi_hsm_init(struct sbi_scratch *scratch, bool cold_boot);
void __noreturn sbi_hsm_exit(struct sbi_scratch *scratch);
int sbi_hsm_hart_start(struct sbi_scratch *scratch,
@@ -72,10 +77,10 @@ int sbi_hsm_hart_suspend(struct sbi_scratch *scratch, u32 suspend_type,
ulong raddr, ulong rmode, ulong arg1);
bool sbi_hsm_hart_change_state(struct sbi_scratch *scratch, long oldstate,
long newstate);
int __sbi_hsm_hart_get_state(u32 hartid);
int __sbi_hsm_hart_get_state(u32 hartindex);
int sbi_hsm_hart_get_state(const struct sbi_domain *dom, u32 hartid);
int sbi_hsm_hart_interruptible_mask(const struct sbi_domain *dom,
ulong hbase, ulong *out_hmask);
struct sbi_hartmask *mask);
void __sbi_hsm_suspend_non_ret_save(struct sbi_scratch *scratch);
void __noreturn sbi_hsm_hart_start_finish(struct sbi_scratch *scratch,
u32 hartid);

View File

@@ -0,0 +1,17 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 MIPS
*
*/
#ifndef __SBI_ILLEGAL_ATOMIC_H__
#define __SBI_ILLEGAL_ATOMIC_H__
#include <sbi/sbi_types.h>
struct sbi_trap_regs;
int sbi_illegal_atomic(ulong insn, struct sbi_trap_regs *regs);
#endif

View File

@@ -14,6 +14,10 @@
struct sbi_trap_context;
typedef int (*illegal_insn_func)(ulong insn, struct sbi_trap_regs *regs);
int truly_illegal_insn(ulong insn, struct sbi_trap_regs *regs);
int sbi_illegal_insn_handler(struct sbi_trap_context *tcntx);
#endif

View File

@@ -16,9 +16,11 @@ struct sbi_scratch;
void __noreturn sbi_init(struct sbi_scratch *scratch);
unsigned long sbi_entry_count(u32 hartid);
void sbi_revert_entry_count(struct sbi_scratch *scratch);
unsigned long sbi_init_count(u32 hartid);
unsigned long sbi_entry_count(u32 hartindex);
unsigned long sbi_init_count(u32 hartindex);
void __noreturn sbi_exit(struct sbi_scratch *scratch);

View File

@@ -26,8 +26,8 @@ struct sbi_ipi_device {
/** Send IPI to a target HART index */
void (*ipi_send)(u32 hart_index);
/** Clear IPI for a target HART index */
void (*ipi_clear)(u32 hart_index);
/** Clear IPI for the current hart */
void (*ipi_clear)(void);
};
enum sbi_ipi_update_type {
@@ -87,7 +87,7 @@ void sbi_ipi_process(void);
int sbi_ipi_raw_send(u32 hartindex);
void sbi_ipi_raw_clear(u32 hartindex);
void sbi_ipi_raw_clear(void);
const struct sbi_ipi_device *sbi_ipi_get_device(void);

View File

@@ -10,19 +10,22 @@
#ifndef __SBI_IRQCHIP_H__
#define __SBI_IRQCHIP_H__
#include <sbi/sbi_list.h>
#include <sbi/sbi_types.h>
struct sbi_scratch;
/**
* Set external interrupt handling function
*
* This function is called by OpenSBI platform code to set a handler for
* external interrupts
*
* @param fn function pointer for handling external irqs
*/
void sbi_irqchip_set_irqfn(int (*fn)(void));
/** irqchip hardware device */
struct sbi_irqchip_device {
/** Node in the list of irqchip devices */
struct sbi_dlist node;
/** Initialize per-hart state for the current hart */
int (*warm_init)(struct sbi_irqchip_device *dev);
/** Handle an IRQ from this irqchip */
int (*irq_handle)(void);
};
/**
* Process external interrupts
@@ -34,6 +37,9 @@ void sbi_irqchip_set_irqfn(int (*fn)(void));
*/
int sbi_irqchip_process(void);
/** Register an irqchip device to receive callbacks */
void sbi_irqchip_add_device(struct sbi_irqchip_device *dev);
/** Initialize interrupt controllers */
int sbi_irqchip_init(struct sbi_scratch *scratch, bool cold_boot);

View File

@@ -160,4 +160,17 @@ static inline void sbi_list_del_init(struct sbi_dlist *entry)
&pos->member != (head); \
pos = sbi_list_entry(pos->member.next, typeof(*pos), member))
/**
* Iterate over list of given type safe against removal of list entry
* @param pos the type * to use as a loop cursor.
* @param n another type * to use as temporary storage.
* @param head the head for your list.
* @param member the name of the list_struct within the struct.
*/
#define sbi_list_for_each_entry_safe(pos, n, head, member) \
for (pos = sbi_list_entry((head)->next, typeof(*pos), member), \
n = sbi_list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = sbi_list_entry(pos->member.next, typeof(*pos), member))
#endif

185
include/sbi/sbi_mpxy.h Normal file
View File

@@ -0,0 +1,185 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2024 Ventana Micro Systems Inc.
*
* Authors:
* Rahul Pathak <rpathak@ventanamicro.com>
*/
#ifndef __SBI_MPXY_H__
#define __SBI_MPXY_H__
#include <sbi/sbi_list.h>
struct sbi_scratch;
#define SBI_MPXY_MSGPROTO_VERSION(Major, Minor) ((Major << 16) | Minor)
enum sbi_mpxy_attr_id {
/* Standard channel attributes managed by MPXY framework */
SBI_MPXY_ATTR_MSG_PROT_ID = 0x00000000,
SBI_MPXY_ATTR_MSG_PROT_VER = 0x00000001,
SBI_MPXY_ATTR_MSG_MAX_LEN = 0x00000002,
SBI_MPXY_ATTR_MSG_SEND_TIMEOUT = 0x00000003,
SBI_MPXY_ATTR_MSG_COMPLETION_TIMEOUT = 0x00000004,
SBI_MPXY_ATTR_CHANNEL_CAPABILITY = 0x00000005,
SBI_MPXY_ATTR_SSE_EVENT_ID = 0x00000006,
SBI_MPXY_ATTR_MSI_CONTROL = 0x00000007,
SBI_MPXY_ATTR_MSI_ADDR_LO = 0x00000008,
SBI_MPXY_ATTR_MSI_ADDR_HI = 0x00000009,
SBI_MPXY_ATTR_MSI_DATA = 0x0000000A,
SBI_MPXY_ATTR_EVENTS_STATE_CONTROL = 0x0000000B,
SBI_MPXY_ATTR_STD_ATTR_MAX_IDX,
/* Message protocol specific attributes, managed by
* message protocol driver */
SBI_MPXY_ATTR_MSGPROTO_ATTR_START = 0x80000000,
SBI_MPXY_ATTR_MSGPROTO_ATTR_END = 0xffffffff
};
/**
* SBI MPXY Message Protocol IDs
*/
enum sbi_mpxy_msgproto_id {
SBI_MPXY_MSGPROTO_RPMI_ID = 0x00000000,
SBI_MPXY_MSGPROTO_MAX_IDX,
/** Vendor specific message protocol IDs */
SBI_MPXY_MSGPROTO_VENDOR_START = 0x80000000,
SBI_MPXY_MSGPROTO_VENDOR_END = 0xffffffff
};
enum SBI_EXT_MPXY_SHMEM_FLAGS {
SBI_EXT_MPXY_SHMEM_FLAG_OVERWRITE = 0b00,
SBI_EXT_MPXY_SHMEM_FLAG_OVERWRITE_RETURN = 0b01,
SBI_EXT_MPXY_SHMEM_FLAG_MAX_IDX
};
struct sbi_mpxy_msi_info {
/* MSI target address low 32-bit */
u32 msi_addr_lo;
/* MSI target address high 32-bit */
u32 msi_addr_hi;
/* MSI data */
u32 msi_data;
};
/**
* Channel attributes.
* NOTE: The sequence of attribute fields are as per the
* defined sequence in the attribute table in spec(or as
* per the enum sbi_mpxy_attr_id).
*/
struct sbi_mpxy_channel_attrs {
/* Message protocol ID */
u32 msg_proto_id;
/* Message protocol Version */
u32 msg_proto_version;
/* Message protocol maximum message data length(bytes) */
u32 msg_data_maxlen;
/* Message protocol message send timeout
* in microseconds */
u32 msg_send_timeout;
/* Message protocol message response timeout in
* microseconds. Its the aggregate of msg_send_timeout
* and the timeout in receiving the response */
u32 msg_completion_timeout;
/* Bit array for channel capabilities */
u32 capability;
u32 sse_event_id;
u32 msi_control;
struct sbi_mpxy_msi_info msi_info;
/* Events State Control */
u32 eventsstate_ctrl;
};
/** A Message proxy channel accessible through SBI interface */
struct sbi_mpxy_channel {
/** List head to a set of channels */
struct sbi_dlist head;
u32 channel_id;
struct sbi_mpxy_channel_attrs attrs;
/**
* Read message protocol attributes
* NOTE: inmem requires little-endian byte-ordering
*/
int (*read_attributes)(struct sbi_mpxy_channel *channel,
u32 *outmem,
u32 base_attr_id,
u32 attr_count);
/**
* Write message protocol attributes
* NOTE: outmem requires little-endian byte-ordering
*/
int (*write_attributes)(struct sbi_mpxy_channel *channel,
u32 *inmem,
u32 base_attr_id,
u32 attr_count);
/**
* Send a message and wait for response
* NOTE: msgbuf requires little-endian byte-ordering
*/
int (*send_message_with_response)(struct sbi_mpxy_channel *channel,
u32 msg_id, void *msgbuf, u32 msg_len,
void *respbuf, u32 resp_max_len,
unsigned long *resp_len);
/** Send message without response */
int (*send_message_without_response)(struct sbi_mpxy_channel *channel,
u32 msg_id, void *msgbuf, u32 msg_len);
/**
* Get notifications events if supported on a channel
* NOTE: eventsbuf requires little-endian byte-ordering
*/
int (*get_notification_events)(struct sbi_mpxy_channel *channel,
void *eventsbuf, u32 bufsize,
unsigned long *events_len);
/**
* Callback to enable the events state reporting
* in the message protocol implementation
*/
void (*switch_eventsstate)(u32 enable);
};
/** Register a Message proxy channel */
int sbi_mpxy_register_channel(struct sbi_mpxy_channel *channel);
/** Initialize Message proxy subsystem */
int sbi_mpxy_init(struct sbi_scratch *scratch);
/** Check if some Message proxy channel is available */
bool sbi_mpxy_channel_available(void);
/** Get message proxy shared memory size */
unsigned long sbi_mpxy_get_shmem_size(void);
/** Set message proxy shared memory on the calling HART */
int sbi_mpxy_set_shmem(unsigned long shmem_phys_lo,
unsigned long shmem_phys_hi,
unsigned long flags);
/** Get channel IDs list */
int sbi_mpxy_get_channel_ids(u32 start_index);
/** Read MPXY channel attributes */
int sbi_mpxy_read_attrs(u32 channel_id, u32 base_attr_id, u32 attr_count);
/** Write MPXY channel attributes */
int sbi_mpxy_write_attrs(u32 channel_id, u32 base_attr_id, u32 attr_count);
/**
* Send a message over a MPXY channel.
* In case if response is not expected, resp_data_len will be NULL.
*/
int sbi_mpxy_send_message(u32 channel_id, u8 msg_id,
unsigned long msg_data_len,
unsigned long *resp_data_len);
/** Get Message proxy notification events */
int sbi_mpxy_get_notification_events(u32 channel_id,
unsigned long *events_len);
#endif

View File

@@ -39,6 +39,8 @@
#define SBI_PLATFORM_FIRMWARE_CONTEXT_OFFSET (0x60 + __SIZEOF_POINTER__)
/** Offset of hart_index2id in struct sbi_platform */
#define SBI_PLATFORM_HART_INDEX2ID_OFFSET (0x60 + (__SIZEOF_POINTER__ * 2))
/** Offset of cbom_block_size in struct sbi_platform */
#define SBI_PLATFORM_CBOM_BLOCK_SIZE_OFFSET (0x60 + (__SIZEOF_POINTER__ * 3))
#define SBI_PLATFORM_TLB_RANGE_FLUSH_LIMIT_DEFAULT (1UL << 12)
@@ -111,18 +113,11 @@ struct sbi_platform_operations {
/** Get platform specific mhpmevent value */
uint64_t (*pmu_xlate_to_mhpmevent)(uint32_t event_idx, uint64_t data);
/** Initialize the platform console */
int (*console_init)(void);
/** Initialize the platform interrupt controller during cold boot */
int (*irqchip_init)(void);
/** Initialize the platform interrupt controller for current HART */
int (*irqchip_init)(bool cold_boot);
/** Exit the platform interrupt controller for current HART */
void (*irqchip_exit)(void);
/** Initialize IPI for current HART */
int (*ipi_init)(bool cold_boot);
/** Exit IPI for current HART */
void (*ipi_exit)(void);
/** Initialize IPI during cold boot */
int (*ipi_init)(void);
/** Get tlb flush limit value **/
u64 (*get_tlbr_flush_limit)(void);
@@ -130,13 +125,12 @@ struct sbi_platform_operations {
/** Get tlb fifo num entries*/
u32 (*get_tlb_num_entries)(void);
/** Initialize platform timer for current HART */
int (*timer_init)(bool cold_boot);
/** Exit platform timer for current HART */
void (*timer_exit)(void);
/** Initialize platform timer during cold boot */
int (*timer_init)(void);
/** Initialize the platform Message Proxy(MPXY) driver */
int (*mpxy_init)(void);
/** Check if SBI vendor extension is implemented or not */
bool (*vendor_ext_check)(void);
/** platform specific SBI extension implementation provider */
int (*vendor_ext_provider)(long funcid,
struct sbi_trap_regs *regs,
@@ -148,6 +142,13 @@ struct sbi_platform_operations {
/** platform specific handler to fixup store fault */
int (*emulate_store)(int wlen, unsigned long addr,
union sbi_ldst_data in_val);
/** platform specific pmp setup on current HART */
void (*pmp_set)(unsigned int n, unsigned long flags,
unsigned long prot, unsigned long addr,
unsigned long log2len);
/** platform specific pmp disable on current HART */
void (*pmp_disable)(unsigned int n);
};
/** Platform default per-HART stack size for exception/interrupt handling */
@@ -155,7 +156,7 @@ struct sbi_platform_operations {
/** Platform default heap size */
#define SBI_PLATFORM_DEFAULT_HEAP_SIZE(__num_hart) \
(0x8000 + 0x800 * (__num_hart))
(0x8000 + 0x1000 * (__num_hart))
/** Representation of a platform */
struct sbi_platform {
@@ -175,7 +176,7 @@ struct sbi_platform {
char name[64];
/** Supported features */
u64 features;
/** Total number of HARTs */
/** Total number of HARTs (at most SBI_HARTMASK_MAX_BITS) */
u32 hart_count;
/** Per-HART stack size for exception/interrupt handling */
u32 hart_stack_size;
@@ -190,70 +191,34 @@ struct sbi_platform {
/**
* HART index to HART id table
*
* For used HART index <abc>:
* If hart_index2id != NULL then the table must contain a mapping
* for each HART index 0 <= <abc> < hart_count:
* hart_index2id[<abc>] = some HART id
* For unused HART index <abc>:
* hart_index2id[<abc>] = -1U
*
* If hart_index2id == NULL then we assume identity mapping
* hart_index2id[<abc>] = <abc>
*
* We have only two restrictions:
* 1. HART index < sbi_platform hart_count
* 2. HART id < SBI_HARTMASK_MAX_BITS
*/
const u32 *hart_index2id;
/** Allocation alignment for Scratch */
unsigned long cbom_block_size;
};
/**
* Prevent modification of struct sbi_platform from affecting
* SBI_PLATFORM_xxx_OFFSET
*/
_Static_assert(
offsetof(struct sbi_platform, opensbi_version)
== SBI_PLATFORM_OPENSBI_VERSION_OFFSET,
"struct sbi_platform definition has changed, please redefine "
"SBI_PLATFORM_OPENSBI_VERSION_OFFSET");
_Static_assert(
offsetof(struct sbi_platform, platform_version)
== SBI_PLATFORM_VERSION_OFFSET,
"struct sbi_platform definition has changed, please redefine "
"SBI_PLATFORM_VERSION_OFFSET");
_Static_assert(
offsetof(struct sbi_platform, name)
== SBI_PLATFORM_NAME_OFFSET,
"struct sbi_platform definition has changed, please redefine "
"SBI_PLATFORM_NAME_OFFSET");
_Static_assert(
offsetof(struct sbi_platform, features)
== SBI_PLATFORM_FEATURES_OFFSET,
"struct sbi_platform definition has changed, please redefine "
"SBI_PLATFORM_FEATURES_OFFSET");
_Static_assert(
offsetof(struct sbi_platform, hart_count)
== SBI_PLATFORM_HART_COUNT_OFFSET,
"struct sbi_platform definition has changed, please redefine "
"SBI_PLATFORM_HART_COUNT_OFFSET");
_Static_assert(
offsetof(struct sbi_platform, hart_stack_size)
== SBI_PLATFORM_HART_STACK_SIZE_OFFSET,
"struct sbi_platform definition has changed, please redefine "
"SBI_PLATFORM_HART_STACK_SIZE_OFFSET");
_Static_assert(
offsetof(struct sbi_platform, platform_ops_addr)
== SBI_PLATFORM_OPS_OFFSET,
"struct sbi_platform definition has changed, please redefine "
"SBI_PLATFORM_OPS_OFFSET");
_Static_assert(
offsetof(struct sbi_platform, firmware_context)
== SBI_PLATFORM_FIRMWARE_CONTEXT_OFFSET,
"struct sbi_platform definition has changed, please redefine "
"SBI_PLATFORM_FIRMWARE_CONTEXT_OFFSET");
_Static_assert(
offsetof(struct sbi_platform, hart_index2id)
== SBI_PLATFORM_HART_INDEX2ID_OFFSET,
"struct sbi_platform definition has changed, please redefine "
"SBI_PLATFORM_HART_INDEX2ID_OFFSET");
assert_member_offset(struct sbi_platform, opensbi_version, SBI_PLATFORM_OPENSBI_VERSION_OFFSET);
assert_member_offset(struct sbi_platform, platform_version, SBI_PLATFORM_VERSION_OFFSET);
assert_member_offset(struct sbi_platform, name, SBI_PLATFORM_NAME_OFFSET);
assert_member_offset(struct sbi_platform, features, SBI_PLATFORM_FEATURES_OFFSET);
assert_member_offset(struct sbi_platform, hart_count, SBI_PLATFORM_HART_COUNT_OFFSET);
assert_member_offset(struct sbi_platform, hart_stack_size, SBI_PLATFORM_HART_STACK_SIZE_OFFSET);
assert_member_offset(struct sbi_platform, heap_size, SBI_PLATFORM_HEAP_SIZE_OFFSET);
assert_member_offset(struct sbi_platform, reserved, SBI_PLATFORM_RESERVED_OFFSET);
assert_member_offset(struct sbi_platform, platform_ops_addr, SBI_PLATFORM_OPS_OFFSET);
assert_member_offset(struct sbi_platform, firmware_context, SBI_PLATFORM_FIRMWARE_CONTEXT_OFFSET);
assert_member_offset(struct sbi_platform, hart_index2id, SBI_PLATFORM_HART_INDEX2ID_OFFSET);
assert_member_offset(struct sbi_platform, cbom_block_size, SBI_PLATFORM_CBOM_BLOCK_SIZE_OFFSET);
/** Get pointer to sbi_platform for sbi_scratch pointer */
#define sbi_platform_ptr(__s) \
@@ -337,7 +302,7 @@ static inline u32 sbi_platform_tlb_fifo_num_entries(const struct sbi_platform *p
{
if (plat && sbi_platform_ops(plat)->get_tlb_num_entries)
return sbi_platform_ops(plat)->get_tlb_num_entries();
return sbi_scratch_last_hartindex() + 1;
return sbi_hart_count();
}
/**
@@ -550,98 +515,59 @@ static inline uint64_t sbi_platform_pmu_xlate_to_mhpmevent(const struct sbi_plat
}
/**
* Initialize the platform console
* Initialize the platform interrupt controller during cold boot
*
* @param plat pointer to struct sbi_platform
*
* @return 0 on success and negative error code on failure
*/
static inline int sbi_platform_console_init(const struct sbi_platform *plat)
{
if (plat && sbi_platform_ops(plat)->console_init)
return sbi_platform_ops(plat)->console_init();
return 0;
}
/**
* Initialize the platform interrupt controller for current HART
*
* @param plat pointer to struct sbi_platform
* @param cold_boot whether cold boot (true) or warm_boot (false)
*
* @return 0 on success and negative error code on failure
*/
static inline int sbi_platform_irqchip_init(const struct sbi_platform *plat,
bool cold_boot)
static inline int sbi_platform_irqchip_init(const struct sbi_platform *plat)
{
if (plat && sbi_platform_ops(plat)->irqchip_init)
return sbi_platform_ops(plat)->irqchip_init(cold_boot);
return sbi_platform_ops(plat)->irqchip_init();
return 0;
}
/**
* Exit the platform interrupt controller for current HART
* Initialize the platform IPI support during cold boot
*
* @param plat pointer to struct sbi_platform
*/
static inline void sbi_platform_irqchip_exit(const struct sbi_platform *plat)
{
if (plat && sbi_platform_ops(plat)->irqchip_exit)
sbi_platform_ops(plat)->irqchip_exit();
}
/**
* Initialize the platform IPI support for current HART
*
* @param plat pointer to struct sbi_platform
* @param cold_boot whether cold boot (true) or warm_boot (false)
*
* @return 0 on success and negative error code on failure
*/
static inline int sbi_platform_ipi_init(const struct sbi_platform *plat,
bool cold_boot)
static inline int sbi_platform_ipi_init(const struct sbi_platform *plat)
{
if (plat && sbi_platform_ops(plat)->ipi_init)
return sbi_platform_ops(plat)->ipi_init(cold_boot);
return sbi_platform_ops(plat)->ipi_init();
return 0;
}
/**
* Exit the platform IPI support for current HART
* Initialize the platform timer during cold boot
*
* @param plat pointer to struct sbi_platform
*/
static inline void sbi_platform_ipi_exit(const struct sbi_platform *plat)
{
if (plat && sbi_platform_ops(plat)->ipi_exit)
sbi_platform_ops(plat)->ipi_exit();
}
/**
* Initialize the platform timer for current HART
*
* @param plat pointer to struct sbi_platform
* @param cold_boot whether cold boot (true) or warm_boot (false)
*
* @return 0 on success and negative error code on failure
*/
static inline int sbi_platform_timer_init(const struct sbi_platform *plat,
bool cold_boot)
static inline int sbi_platform_timer_init(const struct sbi_platform *plat)
{
if (plat && sbi_platform_ops(plat)->timer_init)
return sbi_platform_ops(plat)->timer_init(cold_boot);
return sbi_platform_ops(plat)->timer_init();
return 0;
}
/**
* Exit the platform timer for current HART
* Initialize the platform Message Proxy drivers
*
* @param plat pointer to struct sbi_platform
*
* @return 0 on success and negative error code on failure
*/
static inline void sbi_platform_timer_exit(const struct sbi_platform *plat)
static inline int sbi_platform_mpxy_init(const struct sbi_platform *plat)
{
if (plat && sbi_platform_ops(plat)->timer_exit)
sbi_platform_ops(plat)->timer_exit();
if (plat && sbi_platform_ops(plat)->mpxy_init)
return sbi_platform_ops(plat)->mpxy_init();
return 0;
}
/**
@@ -654,10 +580,7 @@ static inline void sbi_platform_timer_exit(const struct sbi_platform *plat)
static inline bool sbi_platform_vendor_ext_check(
const struct sbi_platform *plat)
{
if (plat && sbi_platform_ops(plat)->vendor_ext_check)
return sbi_platform_ops(plat)->vendor_ext_check();
return false;
return plat && sbi_platform_ops(plat)->vendor_ext_provider;
}
/**
@@ -728,6 +651,38 @@ static inline int sbi_platform_emulate_store(const struct sbi_platform *plat,
return SBI_ENOTSUPP;
}
/**
* Platform specific PMP setup on current HART
*
* @param plat pointer to struct sbi_platform
* @param n index of the pmp entry
* @param flags domain memregion flags
* @param prot attribute of the pmp entry
* @param addr address of the pmp entry
* @param log2len size of the pmp entry as power-of-2
*/
static inline void sbi_platform_pmp_set(const struct sbi_platform *plat,
unsigned int n, unsigned long flags,
unsigned long prot, unsigned long addr,
unsigned long log2len)
{
if (plat && sbi_platform_ops(plat)->pmp_set)
sbi_platform_ops(plat)->pmp_set(n, flags, prot, addr, log2len);
}
/**
* Platform specific PMP disable on current HART
*
* @param plat pointer to struct sbi_platform
* @param n index of the pmp entry
*/
static inline void sbi_platform_pmp_disable(const struct sbi_platform *plat,
unsigned int n)
{
if (plat && sbi_platform_ops(plat)->pmp_disable)
sbi_platform_ops(plat)->pmp_disable(n);
}
#endif
#endif

View File

@@ -114,6 +114,9 @@ void sbi_pmu_exit(struct sbi_scratch *scratch);
/** Return the pmu irq bit depending on extension existence */
int sbi_pmu_irq_bit(void);
/** Return the pmu irq mask or 0 if the pmu overflow irq is not supported */
unsigned long sbi_pmu_irq_mask(void);
/**
* Add the hardware event to counter mapping information. This should be called
* from the platform code to update the mapping table.
@@ -142,6 +145,8 @@ int sbi_pmu_ctr_start(unsigned long cidx_base, unsigned long cidx_mask,
unsigned long flags, uint64_t ival);
int sbi_pmu_ctr_get_info(uint32_t cidx, unsigned long *ctr_info);
int sbi_pmu_event_get_info(unsigned long shmem_lo, unsigned long shmem_high,
unsigned long num_events, unsigned long flags);
unsigned long sbi_pmu_num_ctr(void);

View File

@@ -22,7 +22,7 @@
#define SBI_SCRATCH_FW_RW_OFFSET (2 * __SIZEOF_POINTER__)
/** Offset of fw_heap_offset member in sbi_scratch */
#define SBI_SCRATCH_FW_HEAP_OFFSET (3 * __SIZEOF_POINTER__)
/** Offset of fw_heap_size_offset member in sbi_scratch */
/** Offset of fw_heap_size member in sbi_scratch */
#define SBI_SCRATCH_FW_HEAP_SIZE_OFFSET (4 * __SIZEOF_POINTER__)
/** Offset of next_arg1 member in sbi_scratch */
#define SBI_SCRATCH_NEXT_ARG1_OFFSET (5 * __SIZEOF_POINTER__)
@@ -42,8 +42,10 @@
#define SBI_SCRATCH_TMP0_OFFSET (12 * __SIZEOF_POINTER__)
/** Offset of options member in sbi_scratch */
#define SBI_SCRATCH_OPTIONS_OFFSET (13 * __SIZEOF_POINTER__)
/** Offset of hartindex member in sbi_scratch */
#define SBI_SCRATCH_HARTINDEX_OFFSET (14 * __SIZEOF_POINTER__)
/** Offset of extra space in sbi_scratch */
#define SBI_SCRATCH_EXTRA_SPACE_OFFSET (14 * __SIZEOF_POINTER__)
#define SBI_SCRATCH_EXTRA_SPACE_OFFSET (15 * __SIZEOF_POINTER__)
/** Maximum size of sbi_scratch (4KB) */
#define SBI_SCRATCH_SIZE (0x1000)
@@ -83,67 +85,29 @@ struct sbi_scratch {
unsigned long tmp0;
/** Options for OpenSBI library */
unsigned long options;
/** Index of the hart */
unsigned long hartindex;
};
/**
* Prevent modification of struct sbi_scratch from affecting
* SBI_SCRATCH_xxx_OFFSET
*/
_Static_assert(
offsetof(struct sbi_scratch, fw_start)
== SBI_SCRATCH_FW_START_OFFSET,
"struct sbi_scratch definition has changed, please redefine "
"SBI_SCRATCH_FW_START_OFFSET");
_Static_assert(
offsetof(struct sbi_scratch, fw_size)
== SBI_SCRATCH_FW_SIZE_OFFSET,
"struct sbi_scratch definition has changed, please redefine "
"SBI_SCRATCH_FW_SIZE_OFFSET");
_Static_assert(
offsetof(struct sbi_scratch, next_arg1)
== SBI_SCRATCH_NEXT_ARG1_OFFSET,
"struct sbi_scratch definition has changed, please redefine "
"SBI_SCRATCH_NEXT_ARG1_OFFSET");
_Static_assert(
offsetof(struct sbi_scratch, next_addr)
== SBI_SCRATCH_NEXT_ADDR_OFFSET,
"struct sbi_scratch definition has changed, please redefine "
"SBI_SCRATCH_NEXT_ADDR_OFFSET");
_Static_assert(
offsetof(struct sbi_scratch, next_mode)
== SBI_SCRATCH_NEXT_MODE_OFFSET,
"struct sbi_scratch definition has changed, please redefine "
"SBI_SCRATCH_NEXT_MODE_OFFSET");
_Static_assert(
offsetof(struct sbi_scratch, warmboot_addr)
== SBI_SCRATCH_WARMBOOT_ADDR_OFFSET,
"struct sbi_scratch definition has changed, please redefine "
"SBI_SCRATCH_WARMBOOT_ADDR_OFFSET");
_Static_assert(
offsetof(struct sbi_scratch, platform_addr)
== SBI_SCRATCH_PLATFORM_ADDR_OFFSET,
"struct sbi_scratch definition has changed, please redefine "
"SBI_SCRATCH_PLATFORM_ADDR_OFFSET");
_Static_assert(
offsetof(struct sbi_scratch, hartid_to_scratch)
== SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET,
"struct sbi_scratch definition has changed, please redefine "
"SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET");
_Static_assert(
offsetof(struct sbi_scratch, trap_context)
== SBI_SCRATCH_TRAP_CONTEXT_OFFSET,
"struct sbi_scratch definition has changed, please redefine "
"SBI_SCRATCH_TRAP_CONTEXT_OFFSET");
_Static_assert(
offsetof(struct sbi_scratch, tmp0)
== SBI_SCRATCH_TMP0_OFFSET,
"struct sbi_scratch definition has changed, please redefine "
"SBI_SCRATCH_TMP0_OFFSET");
_Static_assert(
offsetof(struct sbi_scratch, options)
== SBI_SCRATCH_OPTIONS_OFFSET,
"struct sbi_scratch definition has changed, please redefine "
"SBI_SCRATCH_OPTIONS_OFFSET");
assert_member_offset(struct sbi_scratch, fw_start, SBI_SCRATCH_FW_START_OFFSET);
assert_member_offset(struct sbi_scratch, fw_size, SBI_SCRATCH_FW_SIZE_OFFSET);
assert_member_offset(struct sbi_scratch, fw_rw_offset, SBI_SCRATCH_FW_RW_OFFSET);
assert_member_offset(struct sbi_scratch, fw_heap_offset, SBI_SCRATCH_FW_HEAP_OFFSET);
assert_member_offset(struct sbi_scratch, fw_heap_size, SBI_SCRATCH_FW_HEAP_SIZE_OFFSET);
assert_member_offset(struct sbi_scratch, next_arg1, SBI_SCRATCH_NEXT_ARG1_OFFSET);
assert_member_offset(struct sbi_scratch, next_addr, SBI_SCRATCH_NEXT_ADDR_OFFSET);
assert_member_offset(struct sbi_scratch, next_mode, SBI_SCRATCH_NEXT_MODE_OFFSET);
assert_member_offset(struct sbi_scratch, warmboot_addr, SBI_SCRATCH_WARMBOOT_ADDR_OFFSET);
assert_member_offset(struct sbi_scratch, platform_addr, SBI_SCRATCH_PLATFORM_ADDR_OFFSET);
assert_member_offset(struct sbi_scratch, hartid_to_scratch, SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET);
assert_member_offset(struct sbi_scratch, trap_context, SBI_SCRATCH_TRAP_CONTEXT_OFFSET);
assert_member_offset(struct sbi_scratch, tmp0, SBI_SCRATCH_TMP0_OFFSET);
assert_member_offset(struct sbi_scratch, options, SBI_SCRATCH_OPTIONS_OFFSET);
assert_member_offset(struct sbi_scratch, hartindex, SBI_SCRATCH_HARTINDEX_OFFSET);
/** Possible options for OpenSBI library */
enum sbi_scratch_options {
@@ -155,7 +119,7 @@ enum sbi_scratch_options {
/** Get pointer to sbi_scratch for current HART */
#define sbi_scratch_thishart_ptr() \
((struct sbi_scratch *)csr_read(CSR_MSCRATCH))
((struct sbi_scratch *)csr_read_relaxed(CSR_MSCRATCH))
/** Get Arg1 of next booting stage for current HART */
#define sbi_scratch_thishart_arg1_ptr() \
@@ -202,15 +166,22 @@ do { \
= (__type)(__ptr); \
} while (0)
/** Last HART index having a sbi_scratch pointer */
extern u32 last_hartindex_having_scratch;
/** Get the hart index of the current hart */
#define current_hartindex() \
(sbi_scratch_thishart_ptr()->hartindex)
/** Get last HART index having a sbi_scratch pointer */
#define sbi_scratch_last_hartindex() last_hartindex_having_scratch
/** Number of harts managed by this OpenSBI instance */
extern u32 sbi_scratch_hart_count;
/** Get the number of harts managed by this OpenSBI instance */
#define sbi_hart_count() sbi_scratch_hart_count
/** Iterate over the harts managed by this OpenSBI instance */
#define sbi_for_each_hartindex(__var) \
for (u32 __var = 0; __var < sbi_hart_count(); ++__var)
/** Check whether a particular HART index is valid or not */
#define sbi_hartindex_valid(__hartindex) \
(((__hartindex) <= sbi_scratch_last_hartindex()) ? true : false)
#define sbi_hartindex_valid(__hartindex) ((__hartindex) < sbi_hart_count())
/** HART index to HART id table */
extern u32 hartindex_to_hartid_table[];
@@ -218,7 +189,7 @@ extern u32 hartindex_to_hartid_table[];
/** Get sbi_scratch from HART index */
#define sbi_hartindex_to_hartid(__hartindex) \
({ \
((__hartindex) <= sbi_scratch_last_hartindex()) ?\
((__hartindex) < SBI_HARTMASK_MAX_BITS) ? \
hartindex_to_hartid_table[__hartindex] : -1U; \
})
@@ -228,7 +199,7 @@ extern struct sbi_scratch *hartindex_to_scratch_table[];
/** Get sbi_scratch from HART index */
#define sbi_hartindex_to_scratch(__hartindex) \
({ \
((__hartindex) <= sbi_scratch_last_hartindex()) ?\
((__hartindex) < SBI_HARTMASK_MAX_BITS) ? \
hartindex_to_scratch_table[__hartindex] : NULL; \
})

33
include/sbi/sbi_slist.h Normal file
View File

@@ -0,0 +1,33 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Simple simply-linked list library.
*
* Copyright (c) 2025 Rivos Inc.
*
* Authors:
* Clément Léger <cleger@rivosinc.com>
*/
#ifndef __SBI_SLIST_H__
#define __SBI_SLIST_H__
#include <sbi/sbi_types.h>
#define SBI_SLIST_HEAD_INIT(_ptr) (_ptr)
#define SBI_SLIST_HEAD(_lname, _stype) struct _stype *_lname
#define SBI_SLIST_NODE(_stype) SBI_SLIST_HEAD(next, _stype)
#define SBI_SLIST_NODE_INIT(_ptr) .next = _ptr
#define SBI_INIT_SLIST_HEAD(_head) (_head) = NULL
#define SBI_SLIST_ADD(_ptr, _head) \
do { \
(_ptr)->next = _head; \
(_head) = _ptr; \
} while (0)
#define SBI_SLIST_FOR_EACH_ENTRY(_ptr, _head) \
for (_ptr = _head; _ptr; _ptr = _ptr->next)
#endif

View File

@@ -54,12 +54,12 @@ struct sbi_sse_cb_ops {
void (*disable_cb)(uint32_t event_id);
};
/* Set the callback operations for an event
* @param event_id Event identifier (SBI_SSE_EVENT_*)
* @param cb_ops Callback operations
/* Add a supported event with associated callback operations
* @param event_id Event identifier (SBI_SSE_EVENT_* or a custom platform one)
* @param cb_ops Callback operations (Can be NULL if any)
* @return 0 on success, error otherwise
*/
int sbi_sse_set_cb_ops(uint32_t event_id, const struct sbi_sse_cb_ops *cb_ops);
int sbi_sse_add_event(uint32_t event_id, const struct sbi_sse_cb_ops *cb_ops);
/* Inject an event to the current hard
* @param event_id Event identifier (SBI_SSE_EVENT_*)
@@ -78,6 +78,8 @@ void sbi_sse_exit(struct sbi_scratch *scratch);
int sbi_sse_register(uint32_t event_id, unsigned long handler_entry_pc,
unsigned long handler_entry_arg);
int sbi_sse_unregister(uint32_t event_id);
int sbi_sse_hart_mask(void);
int sbi_sse_hart_unmask(void);
int sbi_sse_enable(uint32_t event_id);
int sbi_sse_disable(uint32_t event_id);
int sbi_sse_complete(struct sbi_trap_regs *regs, struct sbi_ecall_return *out);

View File

@@ -28,6 +28,9 @@ struct sbi_timer_device {
/** Stop timer event for current HART */
void (*timer_event_stop)(void);
/** Initialize timer device for current HART */
int (*warm_init)(void);
};
struct sbi_scratch;
@@ -78,8 +81,10 @@ u64 sbi_timer_get_delta(void);
/** Set timer delta value for current HART */
void sbi_timer_set_delta(ulong delta);
#if __riscv_xlen == 32
/** Set upper 32-bits of timer delta value for current HART */
void sbi_timer_set_delta_upper(ulong delta_upper);
#endif
/** Start timer event for current HART */
void sbi_timer_event_start(u64 next_event);

View File

@@ -112,10 +112,13 @@
/** Size (in bytes) of sbi_trap_info */
#define SBI_TRAP_INFO_SIZE SBI_TRAP_INFO_OFFSET(last)
#define STACK_BOUNDARY 16
#define ALIGN_TO_BOUNDARY(x, a) (((x) + (a) - 1) & ~((a) - 1))
/** Size (in bytes) of sbi_trap_context */
#define SBI_TRAP_CONTEXT_SIZE (SBI_TRAP_REGS_SIZE + \
#define SBI_TRAP_CONTEXT_SIZE ALIGN_TO_BOUNDARY((SBI_TRAP_REGS_SIZE + \
SBI_TRAP_INFO_SIZE + \
__SIZEOF_POINTER__)
__SIZEOF_POINTER__), STACK_BOUNDARY)
#ifndef __ASSEMBLER__
@@ -124,6 +127,9 @@
/** Representation of register state at time of trap/interrupt */
struct sbi_trap_regs {
union {
unsigned long gprs[32];
struct {
/** zero register state */
unsigned long zero;
/** ra register state */
@@ -188,6 +194,8 @@ struct sbi_trap_regs {
unsigned long t5;
/** t6 register state */
unsigned long t6;
};
};
/** mepc register state */
unsigned long mepc;
/** mstatus register state */
@@ -196,6 +204,21 @@ struct sbi_trap_regs {
unsigned long mstatusH;
};
_Static_assert(
sizeof(((struct sbi_trap_regs *)0)->gprs) ==
offsetof(struct sbi_trap_regs, t6) +
sizeof(((struct sbi_trap_regs *)0)->t6),
"struct sbi_trap_regs's layout differs between gprs and named members");
#define REG_VAL(idx, regs) ((regs)->gprs[(idx)])
#define GET_RS1(insn, regs) REG_VAL(GET_RS1_NUM(insn), regs)
#define GET_RS2(insn, regs) REG_VAL(GET_RS2_NUM(insn), regs)
#define GET_RS1S(insn, regs) REG_VAL(GET_RS1S_NUM(insn), regs)
#define GET_RS2S(insn, regs) REG_VAL(GET_RS2S_NUM(insn), regs)
#define GET_RS2C(insn, regs) REG_VAL(GET_RS2C_NUM(insn), regs)
#define SET_RD(insn, regs, val) (REG_VAL(GET_RD_NUM(insn), regs) = (val))
/** Representation of trap details */
struct sbi_trap_info {
/** cause Trap exception cause */
@@ -236,6 +259,20 @@ static inline unsigned long sbi_regs_gva(const struct sbi_trap_regs *regs)
#endif
}
static inline bool sbi_regs_from_virt(const struct sbi_trap_regs *regs)
{
#if __riscv_xlen == 32
return (regs->mstatusH & MSTATUSH_MPV) ? true : false;
#else
return (regs->mstatus & MSTATUS_MPV) ? true : false;
#endif
}
static inline int sbi_mstatus_prev_mode(unsigned long mstatus)
{
return (mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT;
}
int sbi_trap_redirect(struct sbi_trap_regs *regs,
const struct sbi_trap_info *trap);

View File

@@ -28,4 +28,13 @@ int sbi_load_access_handler(struct sbi_trap_context *tcntx);
int sbi_store_access_handler(struct sbi_trap_context *tcntx);
ulong sbi_misaligned_tinst_fixup(ulong orig_tinst, ulong new_tinst,
ulong addr_offset);
int sbi_misaligned_v_ld_emulator(int rlen, union sbi_ldst_data *out_val,
struct sbi_trap_context *tcntx);
int sbi_misaligned_v_st_emulator(int wlen, union sbi_ldst_data in_val,
struct sbi_trap_context *tcntx);
#endif

View File

@@ -44,7 +44,12 @@ typedef unsigned long long uint64_t;
#error "Unexpected __riscv_xlen"
#endif
typedef int bool;
#if __STDC_VERSION__ < 202000L
typedef _Bool bool;
#define true 1
#define false 0
#endif
typedef unsigned long ulong;
typedef unsigned long uintptr_t;
typedef unsigned long size_t;
@@ -61,15 +66,15 @@ typedef uint32_t be32_t;
typedef uint64_t le64_t;
typedef uint64_t be64_t;
#define true 1
#define false 0
#define NULL ((void *)0)
#define __packed __attribute__((packed))
#define __noreturn __attribute__((noreturn))
#define __aligned(x) __attribute__((aligned(x)))
#ifndef __always_inline
#define __always_inline inline __attribute__((always_inline))
#endif
#define likely(x) __builtin_expect((x), 1)
#define unlikely(x) __builtin_expect((x), 0)
@@ -91,6 +96,13 @@ typedef uint64_t be64_t;
const typeof(((type *)0)->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })
#define assert_member_offset(type, member, offset) \
_Static_assert( \
(offsetof(type, member)) == (offset ), \
"The offset " #offset " of " #member " in " #type \
"is not correct, please redefine it.")
#define array_size(x) (sizeof(x) / sizeof((x)[0]))
#define MAX(a, b) ((a) > (b) ? (a) : (b))

View File

@@ -11,7 +11,7 @@
#define __SBI_VERSION_H__
#define OPENSBI_VERSION_MAJOR 1
#define OPENSBI_VERSION_MINOR 5
#define OPENSBI_VERSION_MINOR 7
/**
* OpenSBI 32-bit version with:

View File

@@ -0,0 +1,18 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 SiFive
*/
#ifndef __SBI_VISIBILITY_H__
#define __SBI_VISIBILITY_H__
#ifndef __DTS__
/*
* Declare all global objects with hidden visibility so access is PC-relative
* instead of going through the GOT.
*/
#pragma GCC visibility push(hidden)
#endif
#endif

View File

@@ -70,12 +70,12 @@ void fdt_domain_fixup(void *fdt);
*
* @return 0 on success and negative error code on failure
*/
int fdt_domains_populate(void *fdt);
int fdt_domains_populate(const void *fdt);
#else
static inline void fdt_domain_fixup(void *fdt) { }
static inline int fdt_domains_populate(void *fdt) { return 0; }
static inline int fdt_domains_populate(const void *fdt) { return 0; }
#endif

View File

@@ -0,0 +1,63 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* fdt_driver.h - Generic support for initializing drivers from DT nodes.
*
* Copyright (c) 2024 SiFive
*/
#ifndef __FDT_DRIVER_H__
#define __FDT_DRIVER_H__
#include <sbi_utils/fdt/fdt_helper.h>
struct fdt_driver {
const struct fdt_match *match_table;
int (*init)(const void *fdt, int nodeoff,
const struct fdt_match *match);
bool experimental;
};
/* List of early FDT drivers generated at compile time */
extern const struct fdt_driver *const fdt_early_drivers[];
/**
* Initialize a driver instance for a specific DT node
*
* @param fdt devicetree blob
* @param nodeoff offset of a node in the devicetree blob
* @param drivers NULL-terminated array of drivers to match against this node
*
* @return 0 if a driver was matched and successfully initialized or a negative
* error code on failure
*/
int fdt_driver_init_by_offset(const void *fdt, int nodeoff,
const struct fdt_driver *const *drivers);
/**
* Initialize a driver instance for each DT node that matches any of the
* provided drivers
*
* @param fdt devicetree blob
* @param drivers NULL-terminated array of drivers to match against each node
*
* @return 0 if drivers for all matches (if any) were successfully initialized
* or a negative error code on failure
*/
int fdt_driver_init_all(const void *fdt,
const struct fdt_driver *const *drivers);
/**
* Initialize a driver instance for the first DT node that matches any of the
* provided drivers
*
* @param fdt devicetree blob
* @param drivers NULL-terminated array of drivers to match against each node
*
* @return 0 if a driver was matched and successfully initialized or a negative
* error code on failure
*/
int fdt_driver_init_one(const void *fdt,
const struct fdt_driver *const *drivers);
#endif /* __FDT_DRIVER_H__ */

View File

@@ -9,6 +9,8 @@
#ifndef __FDT_FIXUP_H__
#define __FDT_FIXUP_H__
#include <sbi/sbi_list.h>
struct sbi_cpu_idle_state {
const char *name;
uint32_t suspend_param;
@@ -30,7 +32,7 @@ struct sbi_cpu_idle_state {
* @param states: array of idle state descriptions, ending with empty element
* @return zero on success and -ve on failure
*/
int fdt_add_cpu_idle_states(void *dtb, const struct sbi_cpu_idle_state *state);
int fdt_add_cpu_idle_states(void *fdt, const struct sbi_cpu_idle_state *state);
/**
* Fix up the CPU node in the device tree
@@ -93,6 +95,19 @@ void fdt_plic_fixup(void *fdt);
*/
int fdt_reserved_memory_fixup(void *fdt);
/** Representation of a general fixup */
struct fdt_general_fixup {
struct sbi_dlist head;
const char *name;
void (*do_fixup)(struct fdt_general_fixup *f, void *fdt);
};
/** Register a general fixup */
int fdt_register_general_fixup(struct fdt_general_fixup *fixup);
/** UnRegister a general fixup */
void fdt_unregister_general_fixup(struct fdt_general_fixup *fixup);
/**
* General device tree fix-up
*

View File

@@ -34,87 +34,87 @@ struct platform_uart_data {
unsigned long reg_offset;
};
const struct fdt_match *fdt_match_node(void *fdt, int nodeoff,
const struct fdt_match *match_table);
int fdt_find_match(void *fdt, int startoff,
const struct fdt_match *match_table,
const struct fdt_match **out_match);
int fdt_parse_phandle_with_args(void *fdt, int nodeoff,
int fdt_parse_phandle_with_args(const void *fdt, int nodeoff,
const char *prop, const char *cells_prop,
int index, struct fdt_phandle_args *out_args);
int fdt_get_node_addr_size(void *fdt, int node, int index,
int fdt_get_node_addr_size(const void *fdt, int node, int index,
uint64_t *addr, uint64_t *size);
int fdt_get_node_addr_size_by_name(void *fdt, int node, const char *name,
int fdt_get_node_addr_size_by_name(const void *fdt, int node, const char *name,
uint64_t *addr, uint64_t *size);
bool fdt_node_is_enabled(void *fdt, int nodeoff);
bool fdt_node_is_enabled(const void *fdt, int nodeoff);
int fdt_parse_hart_id(void *fdt, int cpu_offset, u32 *hartid);
int fdt_parse_hart_id(const void *fdt, int cpu_offset, u32 *hartid);
int fdt_parse_max_enabled_hart_id(void *fdt, u32 *max_hartid);
int fdt_parse_max_enabled_hart_id(const void *fdt, u32 *max_hartid);
int fdt_parse_timebase_frequency(void *fdt, unsigned long *freq);
int fdt_parse_cbom_block_size(const void *fdt, int cpu_offset, unsigned long *cbom_block_size);
int fdt_parse_isa_extensions(void *fdt, unsigned int hard_id,
int fdt_parse_timebase_frequency(const void *fdt, unsigned long *freq);
int fdt_parse_isa_extensions(const void *fdt, unsigned int hartid,
unsigned long *extensions);
int fdt_parse_gaisler_uart_node(void *fdt, int nodeoffset,
int fdt_parse_gaisler_uart_node(const void *fdt, int nodeoffset,
struct platform_uart_data *uart);
int fdt_parse_renesas_scif_node(void *fdt, int nodeoffset,
int fdt_parse_renesas_scif_node(const void *fdt, int nodeoffset,
struct platform_uart_data *uart);
int fdt_parse_shakti_uart_node(void *fdt, int nodeoffset,
int fdt_parse_shakti_uart_node(const void *fdt, int nodeoffset,
struct platform_uart_data *uart);
int fdt_parse_sifive_uart_node(void *fdt, int nodeoffset,
int fdt_parse_sifive_uart_node(const void *fdt, int nodeoffset,
struct platform_uart_data *uart);
int fdt_parse_uart_node(void *fdt, int nodeoffset,
int fdt_parse_uart_node(const void *fdt, int nodeoffset,
struct platform_uart_data *uart);
int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
int fdt_parse_uart8250(const void *fdt, struct platform_uart_data *uart,
const char *compatible);
int fdt_parse_xlnx_uartlite_node(void *fdt, int nodeoffset,
int fdt_parse_xlnx_uartlite_node(const void *fdt, int nodeoffset,
struct platform_uart_data *uart);
struct aplic_data;
int fdt_parse_aplic_node(void *fdt, int nodeoff, struct aplic_data *aplic);
int fdt_parse_aplic_node(const void *fdt, int nodeoff, struct aplic_data *aplic);
struct imsic_data;
bool fdt_check_imsic_mlevel(void *fdt);
bool fdt_check_imsic_mlevel(const void *fdt);
int fdt_parse_imsic_node(void *fdt, int nodeoff, struct imsic_data *imsic);
int fdt_parse_imsic_node(const void *fdt, int nodeoff, struct imsic_data *imsic);
struct plic_data;
int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic);
int fdt_parse_plic_node(const void *fdt, int nodeoffset, struct plic_data *plic);
int fdt_parse_plic(void *fdt, struct plic_data *plic, const char *compat);
int fdt_parse_plic(const void *fdt, struct plic_data *plic, const char *compat);
int fdt_parse_aclint_node(void *fdt, int nodeoffset,
int fdt_parse_aclint_node(const void *fdt, int nodeoffset,
bool for_timer, bool allow_regname,
unsigned long *out_addr1, unsigned long *out_size1,
unsigned long *out_addr2, unsigned long *out_size2,
u32 *out_first_hartid, u32 *out_hart_count);
int fdt_parse_plmt_node(void *fdt, int nodeoffset, unsigned long *plmt_base,
int fdt_parse_plmt_node(const void *fdt, int nodeoffset, unsigned long *plmt_base,
unsigned long *plmt_size, u32 *hart_count);
int fdt_parse_plicsw_node(void *fdt, int nodeoffset, unsigned long *plicsw_base,
int fdt_parse_plicsw_node(const void *fdt, int nodeoffset, unsigned long *plicsw_base,
unsigned long *size, u32 *hart_count);
int fdt_parse_compat_addr(void *fdt, uint64_t *addr,
int fdt_parse_compat_addr(const void *fdt, uint64_t *addr,
const char *compatible);
static inline void *fdt_get_address(void)
static inline const void *fdt_get_address(void)
{
return (const void *)root.next_arg1;
}
static inline void *fdt_get_address_rw(void)
{
return (void *)root.next_arg1;
}

View File

@@ -52,7 +52,7 @@ int fdt_pmu_fixup(void *fdt);
*
* @return 0 on success and negative error code on failure
*/
int fdt_pmu_setup(void *fdt);
int fdt_pmu_setup(const void *fdt);
/**
* Get the mhpmevent select value read from DT for a given event
@@ -62,15 +62,10 @@ int fdt_pmu_setup(void *fdt);
*/
uint64_t fdt_pmu_get_select_value(uint32_t event_idx);
/** The event index to selector value table instance */
extern struct fdt_pmu_hw_event_select_map fdt_pmu_evt_select[];
/** The number of valid entries in fdt_pmu_evt_select[] */
extern uint32_t hw_event_count;
#else
static inline void fdt_pmu_fixup(void *fdt) { }
static inline int fdt_pmu_setup(void *fdt) { return 0; }
static inline int fdt_pmu_setup(const void *fdt) { return 0; }
static inline uint64_t fdt_pmu_get_select_value(uint32_t event_idx) { return 0; }
#endif

View File

@@ -10,22 +10,21 @@
#ifndef __FDT_GPIO_H__
#define __FDT_GPIO_H__
#include <sbi_utils/fdt/fdt_driver.h>
#include <sbi_utils/gpio/gpio.h>
struct fdt_phandle_args;
/** FDT based GPIO driver */
struct fdt_gpio {
const struct fdt_match *match_table;
struct fdt_driver driver;
int (*xlate)(struct gpio_chip *chip,
const struct fdt_phandle_args *pargs,
struct gpio_pin *out_pin);
int (*init)(void *fdt, int nodeoff, u32 phandle,
const struct fdt_match *match);
};
/** Get a GPIO pin using "gpios" DT property of client DT node */
int fdt_gpio_pin_get(void *fdt, int nodeoff, int index,
int fdt_gpio_pin_get(const void *fdt, int nodeoff, int index,
struct gpio_pin *out_pin);
/** Simple xlate function to convert two GPIO FDT cells into GPIO pin */

View File

@@ -40,7 +40,7 @@ struct gpio_pin {
/** Representation of a GPIO chip */
struct gpio_chip {
/** Pointer to GPIO driver owning this GPIO chip */
void *driver;
const void *driver;
/** Uniquie ID of the GPIO chip assigned by the driver */
unsigned int id;
/** Number of GPIOs supported by the GPIO chip */

View File

@@ -10,17 +10,11 @@
#ifndef __FDT_I2C_H__
#define __FDT_I2C_H__
#include <sbi_utils/fdt/fdt_driver.h>
#include <sbi_utils/i2c/i2c.h>
/** FDT based I2C adapter driver */
struct fdt_i2c_adapter {
const struct fdt_match *match_table;
int (*init)(void *fdt, int nodeoff,
const struct fdt_match *match);
};
/** Get I2C adapter identified by nodeoff */
int fdt_i2c_adapter_get(void *fdt, int nodeoff,
int fdt_i2c_adapter_get(const void *fdt, int nodeoff,
struct i2c_adapter **out_adapter);
#endif

View File

@@ -26,8 +26,6 @@ struct aclint_mswi_data {
u32 hart_count;
};
int aclint_mswi_warm_init(void);
int aclint_mswi_cold_init(struct aclint_mswi_data *mswi);
#endif

View File

@@ -32,8 +32,6 @@ struct plicsw_data {
uint32_t hart_count;
};
int plicsw_warm_ipi_init(void);
int plicsw_cold_ipi_init(struct plicsw_data *plicsw);
#endif /* _IPI_ANDES_PLICSW_H_ */

View File

@@ -11,24 +11,15 @@
#define __FDT_IPI_H__
#include <sbi/sbi_types.h>
#include <sbi_utils/fdt/fdt_driver.h>
#ifdef CONFIG_FDT_IPI
struct fdt_ipi {
const struct fdt_match *match_table;
int (*cold_init)(void *fdt, int nodeoff, const struct fdt_match *match);
int (*warm_init)(void);
void (*exit)(void);
};
void fdt_ipi_exit(void);
int fdt_ipi_init(bool cold_boot);
int fdt_ipi_init(void);
#else
static inline void fdt_ipi_exit(void) { }
static inline int fdt_ipi_init(bool cold_boot) { return 0; }
static inline int fdt_ipi_init(void) { return 0; }
#endif

View File

@@ -12,6 +12,7 @@
#define __IRQCHIP_APLIC_H__
#include <sbi/sbi_types.h>
#include <sbi/sbi_irqchip.h>
#define APLIC_MAX_DELEGATE 16
@@ -30,6 +31,9 @@ struct aplic_delegate_data {
};
struct aplic_data {
/* Private members */
struct sbi_irqchip_device irqchip;
/* Public members */
unsigned long addr;
unsigned long size;
unsigned long num_idc;

View File

@@ -11,25 +11,15 @@
#define __FDT_IRQCHIP_H__
#include <sbi/sbi_types.h>
#include <sbi_utils/fdt/fdt_driver.h>
#ifdef CONFIG_FDT_IRQCHIP
struct fdt_irqchip {
const struct fdt_match *match_table;
int (*cold_init)(void *fdt, int nodeoff, const struct fdt_match *match);
int (*warm_init)(void);
void (*exit)(void);
};
void fdt_irqchip_exit(void);
int fdt_irqchip_init(bool cold_boot);
int fdt_irqchip_init(void);
#else
static inline void fdt_irqchip_exit(void) { }
static inline int fdt_irqchip_init(bool cold_boot) { return 0; }
static inline int fdt_irqchip_init(void) { return 0; }
#endif

View File

@@ -1,33 +0,0 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 Samuel Holland <samuel@sholland.org>
*/
#ifndef __IRQCHIP_FDT_IRQCHIP_PLIC_H__
#define __IRQCHIP_FDT_IRQCHIP_PLIC_H__
#include <sbi/sbi_types.h>
/**
* Save the PLIC priority state
* @param priority pointer to the memory region for the saved priority
* @param num size of the memory region including interrupt source 0
*/
void fdt_plic_priority_save(u8 *priority, u32 num);
/**
* Restore the PLIC priority state
* @param priority pointer to the memory region for the saved priority
* @param num size of the memory region including interrupt source 0
*/
void fdt_plic_priority_restore(const u8 *priority, u32 num);
void fdt_plic_context_save(bool smode, u32 *enable, u32 *threshold, u32 num);
void fdt_plic_context_restore(bool smode, const u32 *enable, u32 threshold,
u32 num);
void thead_plic_restore(void);
#endif

View File

@@ -37,14 +37,12 @@ struct imsic_data {
int imsic_map_hartid_to_data(u32 hartid, struct imsic_data *imsic, int file);
struct imsic_data *imsic_get_data(u32 hartid);
struct imsic_data *imsic_get_data(u32 hartindex);
int imsic_get_target_file(u32 hartid);
int imsic_get_target_file(u32 hartindex);
void imsic_local_irqchip_init(void);
int imsic_warm_irqchip_init(void);
int imsic_data_check(struct imsic_data *imsic);
int imsic_cold_irqchip_init(struct imsic_data *imsic);

View File

@@ -11,31 +11,41 @@
#define __IRQCHIP_PLIC_H__
#include <sbi/sbi_types.h>
#include <sbi/sbi_irqchip.h>
struct plic_data {
/* Private members */
struct sbi_irqchip_device irqchip;
/* Public members */
unsigned long addr;
unsigned long size;
unsigned long num_src;
unsigned long flags;
void *pm_data;
s16 context_map[][2];
};
/* So far, priorities on all consumers of these functions fit in 8 bits. */
void plic_priority_save(const struct plic_data *plic, u8 *priority, u32 num);
/** Work around a bug on Ariane that requires enabling interrupts at boot */
#define PLIC_FLAG_ARIANE_BUG BIT(0)
/** PLIC must be delegated to S-mode like T-HEAD C906 and C910 */
#define PLIC_FLAG_THEAD_DELEGATION BIT(1)
/** Allocate space for power management save/restore operations */
#define PLIC_FLAG_ENABLE_PM BIT(2)
void plic_priority_restore(const struct plic_data *plic, const u8 *priority,
u32 num);
#define PLIC_M_CONTEXT 0
#define PLIC_S_CONTEXT 1
void plic_context_save(const struct plic_data *plic, int context_id,
u32 *enable, u32 *threshold, u32 num);
#define PLIC_DATA_SIZE(__hart_count) (sizeof(struct plic_data) + \
(__hart_count) * 2 * sizeof(s16))
void plic_context_restore(const struct plic_data *plic, int context_id,
const u32 *enable, u32 threshold, u32 num);
#define PLIC_IE_WORDS(__p) ((__p)->num_src / 32 + 1)
int plic_context_init(const struct plic_data *plic, int context_id,
bool enable, u32 threshold);
struct plic_data *plic_get(void);
int plic_warm_irqchip_init(const struct plic_data *plic,
int m_cntx_id, int s_cntx_id);
void plic_suspend(void);
int plic_cold_irqchip_init(const struct plic_data *plic);
void plic_resume(void);
int plic_cold_irqchip_init(struct plic_data *plic);
#endif

View File

@@ -0,0 +1,35 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2024 Ventana Micro Systems Inc.
*
* Authors:
* Anup Patel <apatel@ventanamicro.com>
*/
#ifndef __FDT_MAILBOX_H__
#define __FDT_MAILBOX_H__
#include <sbi_utils/fdt/fdt_driver.h>
#include <sbi_utils/mailbox/mailbox.h>
struct fdt_phandle_args;
/** FDT based mailbox driver */
struct fdt_mailbox {
struct fdt_driver driver;
int (*xlate)(struct mbox_controller *mbox,
const struct fdt_phandle_args *pargs,
u32 *out_chan_args);
};
/** Request a mailbox channel using "mboxes" DT property of client DT node */
int fdt_mailbox_request_chan(const void *fdt, int nodeoff, int index,
struct mbox_chan **out_chan);
/** Simple xlate function to convert one mailbox FDT cell into channel args */
int fdt_mailbox_simple_xlate(struct mbox_controller *mbox,
const struct fdt_phandle_args *pargs,
u32 *out_chan_args);
#endif

View File

@@ -0,0 +1,180 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2024 Ventana Micro Systems Inc.
*
* Authors:
* Anup Patel <apatel@ventanamicro.com>
*/
#ifndef __MAILBOX_H__
#define __MAILBOX_H__
#include <sbi/sbi_types.h>
#include <sbi/sbi_list.h>
#include <sbi/riscv_atomic.h>
/** Representation of a mailbox channel */
struct mbox_chan {
/** List head */
struct sbi_dlist node;
/** Pointer to the mailbox controller */
struct mbox_controller *mbox;
/**
* Arguments (or parameters) to identify a mailbox channel
* within a mailbox controller.
*/
#define MBOX_CHAN_MAX_ARGS 2
u32 chan_args[MBOX_CHAN_MAX_ARGS];
};
#define to_mbox_chan(__node) \
container_of((__node), struct mbox_chan, node)
/**
* Representation of a mailbox data transfer
*
* NOTE: If both "tx" and "rx" are non-NULL then Tx is done before Rx.
*/
struct mbox_xfer {
#define MBOX_XFER_SEQ (1UL << 0)
/** Transfer flags */
unsigned long flags;
/** Transfer arguments (or parameters) */
void *args;
/**
* Sequence number
*
* If MBOX_XFER_SEQ is not set in flags then mbox_chan_xfer()
* will generate a unique sequence number and update this field
* else mbox_chan_xfer() will blindly use the sequence number
* specified by this field.
*/
long seq;
/** Send data pointer */
void *tx;
/** Send data length (valid only if tx != NULL) */
unsigned long tx_len;
/**
* Send timeout milliseconds (valid only if tx != NULL)
*
* If this field is non-zero along with tx != NULL then the
* mailbox controller driver will wait specified milliseconds
* for send data transfer to complete else the mailbox controller
* driver will not wait.
*/
unsigned long tx_timeout;
/** Receive data pointer */
void *rx;
/** Receive data length (valid only if rx != NULL) */
unsigned long rx_len;
/**
* Receive timeout milliseconds (valid only if rx != NULL)
*
* If this field is non-zero along with rx != NULL then the
* mailbox controller driver will wait specified milliseconds
* for receive data transfer to complete else the mailbox
* controller driver will not wait.
*/
unsigned long rx_timeout;
};
#define mbox_xfer_init_tx(__p, __a, __t, __t_len, __t_tim) \
do { \
(__p)->flags = 0; \
(__p)->args = (__a); \
(__p)->tx = (__t); \
(__p)->tx_len = (__t_len); \
(__p)->tx_timeout = (__t_tim); \
(__p)->rx = NULL; \
(__p)->rx_len = 0; \
(__p)->rx_timeout = 0; \
} while (0)
#define mbox_xfer_init_rx(__p, __a, __r, __r_len, __r_tim) \
do { \
(__p)->flags = 0; \
(__p)->args = (__a); \
(__p)->tx = NULL; \
(__p)->tx_len = 0; \
(__p)->tx_timeout = 0; \
(__p)->rx = (__r); \
(__p)->rx_len = (__r_len); \
(__p)->rx_timeout = (__r_tim); \
} while (0)
#define mbox_xfer_init_txrx(__p, __a, __t, __t_len, __t_tim, __r, __r_len, __r_tim)\
do { \
(__p)->flags = 0; \
(__p)->args = (__a); \
(__p)->tx = (__t); \
(__p)->tx_len = (__t_len); \
(__p)->tx_timeout = (__t_tim); \
(__p)->rx = (__r); \
(__p)->rx_len = (__r_len); \
(__p)->rx_timeout = (__r_tim); \
} while (0)
#define mbox_xfer_set_sequence(__p, __seq) \
do { \
(__p)->flags |= MBOX_XFER_SEQ; \
(__p)->seq = (__seq); \
} while (0)
/** Representation of a mailbox controller */
struct mbox_controller {
/** List head */
struct sbi_dlist node;
/** Next sequence atomic counter */
atomic_t xfer_next_seq;
/* List of mailbox channels */
struct sbi_dlist chan_list;
/** Unique ID of the mailbox controller assigned by the driver */
unsigned int id;
/** Maximum length of transfer supported by the mailbox controller */
unsigned int max_xfer_len;
/** Pointer to mailbox driver owning this mailbox controller */
void *driver;
/** Request a mailbox channel from the mailbox controller */
struct mbox_chan *(*request_chan)(struct mbox_controller *mbox,
u32 *chan_args);
/** Free a mailbox channel from the mailbox controller */
void (*free_chan)(struct mbox_controller *mbox,
struct mbox_chan *chan);
/** Transfer data over mailbox channel */
int (*xfer)(struct mbox_chan *chan, struct mbox_xfer *xfer);
/** Get an attribute of mailbox channel */
int (*get_attribute)(struct mbox_chan *chan, int attr_id, void *out_value);
/** Set an attribute of mailbox channel */
int (*set_attribute)(struct mbox_chan *chan, int attr_id, void *new_value);
};
#define to_mbox_controller(__node) \
container_of((__node), struct mbox_controller, node)
/** Find a registered mailbox controller */
struct mbox_controller *mbox_controller_find(unsigned int id);
/** Register mailbox controller */
int mbox_controller_add(struct mbox_controller *mbox);
/** Un-register mailbox controller */
void mbox_controller_remove(struct mbox_controller *mbox);
/** Request a mailbox channel */
struct mbox_chan *mbox_controller_request_chan(struct mbox_controller *mbox,
u32 *chan_args);
/** Free a mailbox channel */
void mbox_controller_free_chan(struct mbox_chan *chan);
/** Data transfer over mailbox channel */
int mbox_chan_xfer(struct mbox_chan *chan, struct mbox_xfer *xfer);
/** Get an attribute of mailbox channel */
int mbox_chan_get_attribute(struct mbox_chan *chan, int attr_id, void *out_value);
/** Set an attribute of mailbox channel */
int mbox_chan_set_attribute(struct mbox_chan *chan, int attr_id, void *new_value);
#endif

View File

@@ -0,0 +1,33 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2023 Ventana Micro Systems Inc.
*
* Authors:
* Anup Patel <apatel@ventanamicro.com>
*/
#ifndef __RPMI_MAILBOX_H__
#define __RPMI_MAILBOX_H__
#include <sbi/sbi_error.h>
#include <sbi_utils/mailbox/mailbox.h>
#include <sbi_utils/mailbox/rpmi_msgprot.h>
#define rpmi_u32_count(__var) (sizeof(__var) / sizeof(u32))
/** Convert RPMI error to SBI error */
int rpmi_xlate_error(enum rpmi_error error);
/** Typical RPMI normal request with at least status code in response */
int rpmi_normal_request_with_status(
struct mbox_chan *chan, u32 service_id,
void *req, u32 req_words, u32 req_endian_words,
void *resp, u32 resp_words, u32 resp_endian_words);
/* RPMI posted request which is without any response*/
int rpmi_posted_request(
struct mbox_chan *chan, u32 service_id,
void *req, u32 req_words, u32 req_endian_words);
#endif /* !__RPMI_MAILBOX_H__ */

View File

@@ -0,0 +1,706 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2023 Ventana Micro Systems Inc.
*
* Authors:
* Rahul Pathak <rpathak@ventanamicro.com>
* Subrahmanya Lingappa <slingappa@ventanamicro.com>
*/
#ifndef __RPMI_MSGPROT_H__
#define __RPMI_MSGPROT_H__
#include <sbi/sbi_byteorder.h>
#include <sbi/sbi_error.h>
/*
* 31 0
* +---------------------+-----------------------+
* | FLAGS | SERVICE_ID | SERVICEGROUP_ID |
* +---------------------+-----------------------+
* | TOKEN | DATA LENGTH |
* +---------------------+-----------------------+
* | DATA/PAYLOAD |
* +---------------------------------------------+
*/
/** Message Header byte offset */
#define RPMI_MSG_HDR_OFFSET (0x0)
/** Message Header Size in bytes */
#define RPMI_MSG_HDR_SIZE (8)
/** ServiceGroup ID field byte offset */
#define RPMI_MSG_SERVICEGROUP_ID_OFFSET (0x0)
/** ServiceGroup ID field size in bytes */
#define RPMI_MSG_SERVICEGROUP_ID_SIZE (2)
/** Service ID field byte offset */
#define RPMI_MSG_SERVICE_ID_OFFSET (0x2)
/** Service ID field size in bytes */
#define RPMI_MSG_SERVICE_ID_SIZE (1)
/** Flags field byte offset */
#define RPMI_MSG_FLAGS_OFFSET (0x3)
/** Flags field size in bytes */
#define RPMI_MSG_FLAGS_SIZE (1)
#define RPMI_MSG_FLAGS_TYPE_POS (0U)
#define RPMI_MSG_FLAGS_TYPE_MASK 0x7
#define RPMI_MSG_FLAGS_TYPE \
((0x7) << RPMI_MSG_FLAGS_TYPE_POS)
#define RPMI_MSG_FLAGS_DOORBELL_POS (3U)
#define RPMI_MSG_FLAGS_DOORBELL_MASK 0x1
#define RPMI_MSG_FLAGS_DOORBELL \
((0x1) << RPMI_MSG_FLAGS_DOORBELL_POS)
/** Data length field byte offset */
#define RPMI_MSG_DATALEN_OFFSET (0x4)
/** Data length field size in bytes */
#define RPMI_MSG_DATALEN_SIZE (2)
/** Token field byte offset */
#define RPMI_MSG_TOKEN_OFFSET (0x6)
/** Token field size in bytes */
#define RPMI_MSG_TOKEN_SIZE (2)
/** Token field mask */
#define RPMI_MSG_TOKEN_MASK (0xffffU)
/** Data field byte offset */
#define RPMI_MSG_DATA_OFFSET (RPMI_MSG_HDR_SIZE)
/** Data field size in bytes */
#define RPMI_MSG_DATA_SIZE(__slot_size) ((__slot_size) - RPMI_MSG_HDR_SIZE)
/** Minimum slot size in bytes */
#define RPMI_SLOT_SIZE_MIN (64)
/** Name length of 16 characters */
#define RPMI_NAME_CHARS_MAX (16)
/** Queue layout */
#define RPMI_QUEUE_HEAD_SLOT 0
#define RPMI_QUEUE_TAIL_SLOT 1
#define RPMI_QUEUE_HEADER_SLOTS 2
/** Default timeout values */
#define RPMI_DEF_TX_TIMEOUT 20
#define RPMI_DEF_RX_TIMEOUT 20
/**
* Common macro to generate composite version from major
* and minor version numbers.
*
* RPMI has Specification version, Implementation version
* Service group versions which follow the same versioning
* encoding as below.
*/
#define RPMI_VERSION(__major, __minor) (((__major) << 16) | (__minor))
/** RPMI Message Header */
struct rpmi_message_header {
le16_t servicegroup_id;
uint8_t service_id;
uint8_t flags;
le16_t datalen;
le16_t token;
} __packed;
/** RPMI Message */
struct rpmi_message {
struct rpmi_message_header header;
u8 data[0];
} __packed;
/** RPMI Messages Types */
enum rpmi_message_type {
/* Normal request backed with ack */
RPMI_MSG_NORMAL_REQUEST = 0x0,
/* Request without any ack */
RPMI_MSG_POSTED_REQUEST = 0x1,
/* Acknowledgment for normal request message */
RPMI_MSG_ACKNOWLDGEMENT = 0x2,
/* Notification message */
RPMI_MSG_NOTIFICATION = 0x3,
};
/** RPMI Error Types */
enum rpmi_error {
/* Success */
RPMI_SUCCESS = 0,
/* General failure */
RPMI_ERR_FAILED = -1,
/* Service or feature not supported */
RPMI_ERR_NOTSUPP = -2,
/* Invalid Parameter */
RPMI_ERR_INVALID_PARAM = -3,
/*
* Denied to insufficient permissions
* or due to unmet prerequisite
*/
RPMI_ERR_DENIED = -4,
/* Invalid address or offset */
RPMI_ERR_INVALID_ADDR = -5,
/*
* Operation failed as it was already in
* progress or the state has changed already
* for which the operation was carried out.
*/
RPMI_ERR_ALREADY = -6,
/*
* Error in implementation which violates
* the specification version
*/
RPMI_ERR_EXTENSION = -7,
/* Operation failed due to hardware issues */
RPMI_ERR_HW_FAULT = -8,
/* System, device or resource is busy */
RPMI_ERR_BUSY = -9,
/* System or device or resource in invalid state */
RPMI_ERR_INVALID_STATE = -10,
/* Index, offset or address is out of range */
RPMI_ERR_BAD_RANGE = -11,
/* Operation timed out */
RPMI_ERR_TIMEOUT = -12,
/*
* Error in input or output or
* error in sending or receiving data
* through communication medium
*/
RPMI_ERR_IO = -13,
/* No data available */
RPMI_ERR_NO_DATA = -14,
RPMI_ERR_RESERVED_START = -15,
RPMI_ERR_RESERVED_END = -127,
RPMI_ERR_VENDOR_START = -128,
};
/** RPMI Mailbox Message Arguments */
struct rpmi_message_args {
u32 flags;
#define RPMI_MSG_FLAGS_NO_TX (1U << 0)
#define RPMI_MSG_FLAGS_NO_RX (1U << 1)
#define RPMI_MSG_FLAGS_NO_RX_TOKEN (1U << 2)
enum rpmi_message_type type;
u8 service_id;
u32 tx_endian_words;
u32 rx_endian_words;
u16 rx_token;
u32 rx_data_len;
};
/** RPMI Mailbox Channel Attribute IDs */
enum rpmi_channel_attribute_id {
RPMI_CHANNEL_ATTR_PROTOCOL_VERSION = 0,
RPMI_CHANNEL_ATTR_MAX_DATA_LEN,
RPMI_CHANNEL_ATTR_P2A_DOORBELL_SYSMSI_INDEX,
RPMI_CHANNEL_ATTR_TX_TIMEOUT,
RPMI_CHANNEL_ATTR_RX_TIMEOUT,
RPMI_CHANNEL_ATTR_SERVICEGROUP_ID,
RPMI_CHANNEL_ATTR_SERVICEGROUP_VERSION,
RPMI_CHANNEL_ATTR_IMPL_ID,
RPMI_CHANNEL_ATTR_IMPL_VERSION,
RPMI_CHANNEL_ATTR_MAX,
};
/*
* RPMI SERVICEGROUPS AND SERVICES
*/
/** RPMI ServiceGroups IDs */
enum rpmi_servicegroup_id {
RPMI_SRVGRP_ID_MIN = 0,
RPMI_SRVGRP_BASE = 0x0001,
RPMI_SRVGRP_SYSTEM_MSI = 0x0002,
RPMI_SRVGRP_SYSTEM_RESET = 0x0003,
RPMI_SRVGRP_SYSTEM_SUSPEND = 0x0004,
RPMI_SRVGRP_HSM = 0x0005,
RPMI_SRVGRP_CPPC = 0x0006,
RPMI_SRVGRP_CLOCK = 0x0008,
RPMI_SRVGRP_ID_MAX_COUNT,
/* Reserved range for service groups */
RPMI_SRVGRP_RESERVE_START = RPMI_SRVGRP_ID_MAX_COUNT,
RPMI_SRVGRP_RESERVE_END = 0x7FFF,
/* Vendor/Implementation-specific service groups range */
RPMI_SRVGRP_VENDOR_START = 0x8000,
RPMI_SRVGRP_VENDOR_END = 0xFFFF,
};
/** RPMI enable notification request */
struct rpmi_enable_notification_req {
u32 eventid;
};
/** RPMI enable notification response */
struct rpmi_enable_notification_resp {
s32 status;
};
/** RPMI Base ServiceGroup Service IDs */
enum rpmi_base_service_id {
RPMI_BASE_SRV_ENABLE_NOTIFICATION = 0x01,
RPMI_BASE_SRV_GET_IMPLEMENTATION_VERSION = 0x02,
RPMI_BASE_SRV_GET_IMPLEMENTATION_IDN = 0x03,
RPMI_BASE_SRV_GET_SPEC_VERSION = 0x04,
RPMI_BASE_SRV_GET_PLATFORM_INFO = 0x05,
RPMI_BASE_SRV_PROBE_SERVICE_GROUP = 0x06,
RPMI_BASE_SRV_GET_ATTRIBUTES = 0x07,
};
#define RPMI_BASE_FLAGS_F0_PRIVILEGE (1U << 1)
#define RPMI_BASE_FLAGS_F0_EV_NOTIFY (1U << 0)
enum rpmi_base_context_priv_level {
RPMI_BASE_CONTEXT_PRIV_S_MODE,
RPMI_BASE_CONTEXT_PRIV_M_MODE,
};
struct rpmi_base_get_attributes_resp {
s32 status_code;
u32 f0;
u32 f1;
u32 f2;
u32 f3;
};
struct rpmi_base_get_platform_info_resp {
s32 status;
u32 plat_info_len;
char plat_info[];
};
/** RPMI System MSI ServiceGroup Service IDs */
enum rpmi_sysmsi_service_id {
RPMI_SYSMSI_SRV_ENABLE_NOTIFICATION = 0x01,
RPMI_SYSMSI_SRV_GET_ATTRIBUTES = 0x2,
RPMI_SYSMSI_SRV_GET_MSI_ATTRIBUTES = 0x3,
RPMI_SYSMSI_SRV_SET_MSI_STATE = 0x4,
RPMI_SYSMSI_SRV_GET_MSI_STATE = 0x5,
RPMI_SYSMSI_SRV_SET_MSI_TARGET = 0x6,
RPMI_SYSMSI_SRV_GET_MSI_TARGET = 0x7,
RPMI_SYSMSI_SRV_ID_MAX_COUNT,
};
/** Response for system MSI service group attributes */
struct rpmi_sysmsi_get_attributes_resp {
s32 status;
u32 sys_num_msi;
u32 flag0;
u32 flag1;
};
/** Request for system MSI attributes */
struct rpmi_sysmsi_get_msi_attributes_req {
u32 sys_msi_index;
};
/** Response for system MSI attributes */
struct rpmi_sysmsi_get_msi_attributes_resp {
s32 status;
u32 flag0;
u32 flag1;
u8 name[16];
};
#define RPMI_SYSMSI_MSI_ATTRIBUTES_FLAG0_PREF_PRIV (1U << 0)
/** Request for system MSI set state */
struct rpmi_sysmsi_set_msi_state_req {
u32 sys_msi_index;
u32 sys_msi_state;
};
#define RPMI_SYSMSI_MSI_STATE_ENABLE (1U << 0)
#define RPMI_SYSMSI_MSI_STATE_PENDING (1U << 1)
/** Response for system MSI set state */
struct rpmi_sysmsi_set_msi_state_resp {
s32 status;
};
/** Request for system MSI get state */
struct rpmi_sysmsi_get_msi_state_req {
u32 sys_msi_index;
};
/** Response for system MSI get state */
struct rpmi_sysmsi_get_msi_state_resp {
s32 status;
u32 sys_msi_state;
};
/** Request for system MSI set target */
struct rpmi_sysmsi_set_msi_target_req {
u32 sys_msi_index;
u32 sys_msi_address_low;
u32 sys_msi_address_high;
u32 sys_msi_data;
};
/** Response for system MSI set target */
struct rpmi_sysmsi_set_msi_target_resp {
s32 status;
};
/** Request for system MSI get target */
struct rpmi_sysmsi_get_msi_target_req {
u32 sys_msi_index;
};
/** Response for system MSI get target */
struct rpmi_sysmsi_get_msi_target_resp {
s32 status;
u32 sys_msi_address_low;
u32 sys_msi_address_high;
u32 sys_msi_data;
};
/** RPMI System Reset ServiceGroup Service IDs */
enum rpmi_system_reset_service_id {
RPMI_SYSRST_SRV_ENABLE_NOTIFICATION = 0x01,
RPMI_SYSRST_SRV_GET_ATTRIBUTES = 0x02,
RPMI_SYSRST_SRV_SYSTEM_RESET = 0x03,
RPMI_SYSRST_SRV_ID_MAX_COUNT,
};
/** RPMI System Reset types */
enum rpmi_sysrst_reset_type {
RPMI_SYSRST_TYPE_SHUTDOWN = 0x0,
RPMI_SYSRST_TYPE_COLD_REBOOT = 0x1,
RPMI_SYSRST_TYPE_WARM_REBOOT = 0x2,
RPMI_SYSRST_TYPE_MAX,
};
#define RPMI_SYSRST_ATTRS_FLAGS_RESETTYPE_POS (1)
#define RPMI_SYSRST_ATTRS_FLAGS_RESETTYPE_MASK \
(1U << RPMI_SYSRST_ATTRS_FLAGS_RESETTYPE_POS)
/** Response for system reset attributes */
struct rpmi_sysrst_get_reset_attributes_resp {
s32 status;
u32 flags;
};
/** RPMI System Suspend ServiceGroup Service IDs */
enum rpmi_system_suspend_service_id {
RPMI_SYSSUSP_SRV_ENABLE_NOTIFICATION = 0x01,
RPMI_SYSSUSP_SRV_GET_ATTRIBUTES = 0x02,
RPMI_SYSSUSP_SRV_SYSTEM_SUSPEND = 0x03,
RPMI_SYSSUSP_SRV_ID_MAX_COUNT,
};
/** Request for system suspend attributes */
struct rpmi_syssusp_get_attr_req {
u32 susp_type;
};
#define RPMI_SYSSUSP_ATTRS_FLAGS_RESUMEADDR (1U << 1)
#define RPMI_SYSSUSP_ATTRS_FLAGS_SUSPENDTYPE 1U
/** Response for system suspend attributes */
struct rpmi_syssusp_get_attr_resp {
s32 status;
u32 flags;
};
struct rpmi_syssusp_suspend_req {
u32 hartid;
u32 suspend_type;
u32 resume_addr_lo;
u32 resume_addr_hi;
};
struct rpmi_syssusp_suspend_resp {
s32 status;
};
/** RPMI HSM State Management ServiceGroup Service IDs */
enum rpmi_hsm_service_id {
RPMI_HSM_SRV_ENABLE_NOTIFICATION = 0x01,
RPMI_HSM_SRV_GET_HART_STATUS = 0x02,
RPMI_HSM_SRV_GET_HART_LIST = 0x03,
RPMI_HSM_SRV_GET_SUSPEND_TYPES = 0x04,
RPMI_HSM_SRV_GET_SUSPEND_INFO = 0x05,
RPMI_HSM_SRV_HART_START = 0x06,
RPMI_HSM_SRV_HART_STOP = 0x07,
RPMI_HSM_SRV_HART_SUSPEND = 0x08,
RPMI_HSM_SRV_ID_MAX = 0x09,
};
/* HSM service group request and response structs */
struct rpmi_hsm_hart_start_req {
u32 hartid;
u32 start_addr_lo;
u32 start_addr_hi;
};
struct rpmi_hsm_hart_start_resp {
s32 status;
};
struct rpmi_hsm_hart_stop_req {
u32 hartid;
};
struct rpmi_hsm_hart_stop_resp {
s32 status;
};
struct rpmi_hsm_hart_susp_req {
u32 hartid;
u32 suspend_type;
u32 resume_addr_lo;
u32 resume_addr_hi;
};
struct rpmi_hsm_hart_susp_resp {
s32 status;
};
struct rpmi_hsm_get_hart_status_req {
u32 hartid;
};
struct rpmi_hsm_get_hart_status_resp {
s32 status;
u32 hart_status;
};
struct rpmi_hsm_get_hart_list_req {
u32 start_index;
};
struct rpmi_hsm_get_hart_list_resp {
s32 status;
u32 remaining;
u32 returned;
/* remaining space need to be adjusted for the above 3 u32's */
u32 hartid[(RPMI_MSG_DATA_SIZE(RPMI_SLOT_SIZE_MIN) - (sizeof(u32) * 3)) / sizeof(u32)];
};
struct rpmi_hsm_get_susp_types_req {
u32 start_index;
};
struct rpmi_hsm_get_susp_types_resp {
s32 status;
u32 remaining;
u32 returned;
/* remaining space need to be adjusted for the above 3 u32's */
u32 types[(RPMI_MSG_DATA_SIZE(RPMI_SLOT_SIZE_MIN) - (sizeof(u32) * 3)) / sizeof(u32)];
};
struct rpmi_hsm_get_susp_info_req {
u32 suspend_type;
};
#define RPMI_HSM_SUSPEND_INFO_FLAGS_TIMER_STOP 1U
struct rpmi_hsm_get_susp_info_resp {
s32 status;
u32 flags;
u32 entry_latency_us;
u32 exit_latency_us;
u32 wakeup_latency_us;
u32 min_residency_us;
};
/** RPMI CPPC ServiceGroup Service IDs */
enum rpmi_cppc_service_id {
RPMI_CPPC_SRV_ENABLE_NOTIFICATION = 0x01,
RPMI_CPPC_SRV_PROBE_REG = 0x02,
RPMI_CPPC_SRV_READ_REG = 0x03,
RPMI_CPPC_SRV_WRITE_REG = 0x04,
RPMI_CPPC_SRV_GET_FAST_CHANNEL_REGION = 0x05,
RPMI_CPPC_SRV_GET_FAST_CHANNEL_OFFSET = 0x06,
RPMI_CPPC_SRV_GET_HART_LIST = 0x07,
RPMI_CPPC_SRV_MAX_COUNT,
};
struct rpmi_cppc_probe_req {
u32 hart_id;
u32 reg_id;
};
struct rpmi_cppc_probe_resp {
s32 status;
u32 reg_len;
};
struct rpmi_cppc_read_reg_req {
u32 hart_id;
u32 reg_id;
};
struct rpmi_cppc_read_reg_resp {
s32 status;
u32 data_lo;
u32 data_hi;
};
struct rpmi_cppc_write_reg_req {
u32 hart_id;
u32 reg_id;
u32 data_lo;
u32 data_hi;
};
struct rpmi_cppc_write_reg_resp {
s32 status;
};
struct rpmi_cppc_get_fastchan_offset_req {
u32 hart_id;
};
struct rpmi_cppc_get_fastchan_offset_resp {
s32 status;
u32 fc_perf_request_offset_lo;
u32 fc_perf_request_offset_hi;
u32 fc_perf_feedback_offset_lo;
u32 fc_perf_feedback_offset_hi;
};
#define RPMI_CPPC_FAST_CHANNEL_CPPC_MODE_POS 3
#define RPMI_CPPC_FAST_CHANNEL_CPPC_MODE_MASK \
(3U << RPMI_CPPC_FAST_CHANNEL_CPPC_MODE_POS)
#define RPMI_CPPC_FAST_CHANNEL_FLAGS_DB_WIDTH_POS 1
#define RPMI_CPPC_FAST_CHANNEL_FLAGS_DB_WIDTH_MASK \
(3U << RPMI_CPPC_FAST_CHANNEL_FLAGS_DB_WIDTH_POS)
#define RPMI_CPPC_FAST_CHANNEL_FLAGS_DB_SUPPORTED (1U << 0)
struct rpmi_cppc_get_fastchan_region_resp {
s32 status;
u32 flags;
u32 region_addr_lo;
u32 region_addr_hi;
u32 region_size_lo;
u32 region_size_hi;
u32 db_addr_lo;
u32 db_addr_hi;
u32 db_setmask_lo;
u32 db_setmask_hi;
u32 db_preservemask_lo;
u32 db_preservemask_hi;
};
enum rpmi_cppc_fast_channel_db_width {
RPMI_CPPC_FAST_CHANNEL_DB_WIDTH_8 = 0x0,
RPMI_CPPC_FAST_CHANNEL_DB_WIDTH_16 = 0x1,
RPMI_CPPC_FAST_CHANNEL_DB_WIDTH_32 = 0x2,
RPMI_CPPC_FAST_CHANNEL_DB_WIDTH_64 = 0x3,
};
enum rpmi_cppc_fast_channel_cppc_mode {
RPMI_CPPC_FAST_CHANNEL_CPPC_MODE_PASSIVE = 0x0,
RPMI_CPPC_FAST_CHANNEL_CPPC_MODE_ACTIVE = 0x1,
RPMI_CPPC_FAST_CHANNEL_CPPC_MODE_MAX_IDX,
};
struct rpmi_cppc_hart_list_req {
u32 start_index;
};
struct rpmi_cppc_hart_list_resp {
s32 status;
u32 remaining;
u32 returned;
/* remaining space need to be adjusted for the above 3 u32's */
u32 hartid[(RPMI_MSG_DATA_SIZE(RPMI_SLOT_SIZE_MIN) - (sizeof(u32) * 3)) / sizeof(u32)];
};
/** RPMI Clock ServiceGroup Service IDs */
enum rpmi_clock_service_id {
RPMI_CLOCK_SRV_ENABLE_NOTIFICATION = 0x01,
RPMI_CLOCK_SRV_GET_NUM_CLOCKS = 0x02,
RPMI_CLOCK_SRV_GET_ATTRIBUTES = 0x03,
RPMI_CLOCK_SRV_GET_SUPPORTED_RATES = 0x04,
RPMI_CLOCK_SRV_SET_CONFIG = 0x05,
RPMI_CLOCK_SRV_GET_CONFIG = 0x06,
RPMI_CLOCK_SRV_SET_RATE = 0x07,
RPMI_CLOCK_SRV_GET_RATE = 0x08,
RPMI_CLOCK_SRV_MAX_COUNT,
};
struct rpmi_clock_get_num_clocks_resp {
s32 status;
u32 num_clocks;
};
struct rpmi_clock_get_attributes_req {
u32 clock_id;
};
struct rpmi_clock_get_attributes_resp {
s32 status;
#define RPMI_CLOCK_FLAGS_FORMAT_POS 30
#define RPMI_CLOCK_FLAGS_FORMAT_MASK \
(3U << RPMI_CLOCK_FLAGS_CLOCK_FORMAT_POS)
#define RPMI_CLOCK_FLAGS_FORMAT_DISCRETE 0
#define RPMI_CLOCK_FLAGS_FORMAT_LINEAR 1
u32 flags;
u32 num_rates;
u32 transition_latency;
u8 name[16];
};
struct rpmi_clock_get_supported_rates_req {
u32 clock_id;
u32 clock_rate_index;
};
struct rpmi_clock_get_supported_rates_resp {
s32 status;
u32 flags;
u32 remaining;
u32 returned;
u32 clock_rate[0];
};
struct rpmi_clock_set_config_req {
u32 clock_id;
#define RPMI_CLOCK_CONFIG_ENABLE (1U << 0)
u32 config;
};
struct rpmi_clock_set_config_resp {
s32 status;
};
struct rpmi_clock_get_config_req {
u32 clock_id;
};
struct rpmi_clock_get_config_resp {
s32 status;
u32 config;
};
struct rpmi_clock_set_rate_req {
u32 clock_id;
#define RPMI_CLOCK_SET_RATE_FLAGS_MASK (3U << 0)
#define RPMI_CLOCK_SET_RATE_FLAGS_ROUND_DOWN 0
#define RPMI_CLOCK_SET_RATE_FLAGS_ROUND_UP 1
#define RPMI_CLOCK_SET_RATE_FLAGS_ROUND_PLAT 2
u32 flags;
u32 clock_rate_low;
u32 clock_rate_high;
};
struct rpmi_clock_set_rate_resp {
s32 status;
};
struct rpmi_clock_get_rate_req {
u32 clock_id;
};
struct rpmi_clock_get_rate_resp {
s32 status;
u32 clock_rate_low;
u32 clock_rate_high;
};
#endif /* !__RPMI_MSGPROT_H__ */

View File

@@ -0,0 +1,26 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2024 Ventana Micro Systems Inc.
*
* Authors:
* Anup Patel <apatel@ventanamicro.com>
*/
#ifndef __FDT_MPXY_H__
#define __FDT_MPXY_H__
#include <sbi/sbi_types.h>
#include <sbi_utils/fdt/fdt_driver.h>
#ifdef CONFIG_FDT_MPXY
int fdt_mpxy_init(const void *fdt);
#else
static inline int fdt_mpxy_init(const void *fdt) { return 0; }
#endif
#endif

View File

@@ -0,0 +1,85 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2024 Ventana Micro Systems Inc.
*
* Authors:
* Anup Patel <apatel@ventanamicro.com>
*/
#ifndef __FDT_MPXY_RPMI_MBOX_H__
#define __FDT_MPXY_RPMI_MBOX_H__
#include <sbi/sbi_types.h>
#include <sbi/sbi_mpxy.h>
#include <sbi_utils/mailbox/fdt_mailbox.h>
#include <sbi_utils/mailbox/rpmi_msgprot.h>
#include <sbi_utils/mpxy/fdt_mpxy.h>
/** Convert the mpxy attribute ID to attribute array index */
#define attr_id2index(attr_id) (attr_id - SBI_MPXY_ATTR_MSGPROTO_ATTR_START)
enum mpxy_msgprot_rpmi_attr_id {
MPXY_MSGPROT_RPMI_ATTR_SERVICEGROUP_ID = SBI_MPXY_ATTR_MSGPROTO_ATTR_START,
MPXY_MSGPROT_RPMI_ATTR_SERVICEGROUP_VERSION,
MPXY_MSGPROT_RPMI_ATTR_IMPL_ID,
MPXY_MSGPROT_RPMI_ATTR_IMPL_VERSION,
MPXY_MSGPROT_RPMI_ATTR_MAX_ID
};
/**
* MPXY message protocol attributes for RPMI
* Order of attribute fields must follow the
* attribute IDs in `enum mpxy_msgprot_rpmi_attr_id`
*/
struct mpxy_rpmi_channel_attrs {
u32 servicegrp_id;
u32 servicegrp_ver;
u32 impl_id;
u32 impl_ver;
};
/** Make sure all attributes are packed for direct memcpy */
#define assert_field_offset(field, attr_offset) \
_Static_assert( \
((offsetof(struct mpxy_rpmi_channel_attrs, field)) / \
sizeof(u32)) == (attr_offset - SBI_MPXY_ATTR_MSGPROTO_ATTR_START),\
"field " #field \
" from struct mpxy_rpmi_channel_attrs invalid offset, expected " #attr_offset)
assert_field_offset(servicegrp_id, MPXY_MSGPROT_RPMI_ATTR_SERVICEGROUP_ID);
assert_field_offset(servicegrp_ver, MPXY_MSGPROT_RPMI_ATTR_SERVICEGROUP_VERSION);
assert_field_offset(impl_id, MPXY_MSGPROT_RPMI_ATTR_IMPL_ID);
assert_field_offset(impl_ver, MPXY_MSGPROT_RPMI_ATTR_IMPL_VERSION);
/** MPXY RPMI service data for each service group */
struct mpxy_rpmi_service_data {
u8 id;
u32 min_tx_len;
u32 max_tx_len;
u32 min_rx_len;
u32 max_rx_len;
};
/** MPXY RPMI mbox data for each service group */
struct mpxy_rpmi_mbox_data {
u32 servicegrp_id;
u32 num_services;
struct mpxy_rpmi_service_data *service_data;
/** Transfer RPMI service group message */
int (*xfer_group)(void *context, struct mbox_chan *chan,
struct mbox_xfer *xfer);
/** Setup RPMI service group context for MPXY */
int (*setup_group)(void **context, struct mbox_chan *chan,
const struct mpxy_rpmi_mbox_data *data);
/** Cleanup RPMI service group context for MPXY */
void (*cleanup_group)(void *context);
};
/** Common probe function for MPXY RPMI drivers */
int mpxy_rpmi_mbox_init(const void *fdt, int nodeoff, const struct fdt_match *match);
#endif

View File

@@ -10,22 +10,16 @@
#ifndef __FDT_REGMAP_H__
#define __FDT_REGMAP_H__
#include <sbi_utils/fdt/fdt_driver.h>
#include <sbi_utils/regmap/regmap.h>
struct fdt_phandle_args;
/** FDT based regmap driver */
struct fdt_regmap {
const struct fdt_match *match_table;
int (*init)(void *fdt, int nodeoff, u32 phandle,
const struct fdt_match *match);
};
/** Get regmap instance based on phandle */
int fdt_regmap_get_by_phandle(void *fdt, u32 phandle,
int fdt_regmap_get_by_phandle(const void *fdt, u32 phandle,
struct regmap **out_rmap);
/** Get regmap instance based on "regmap' property of the specified DT node */
int fdt_regmap_get(void *fdt, int nodeoff, struct regmap **out_rmap);
/** Get regmap instance based on "regmap" property of the specified DT node */
int fdt_regmap_get(const void *fdt, int nodeoff, struct regmap **out_rmap);
#endif

View File

@@ -1,44 +0,0 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
*
* Authors:
* Anup Patel <anup.patel@wdc.com>
*/
#ifndef __FDT_RESET_H__
#define __FDT_RESET_H__
#include <sbi/sbi_types.h>
struct fdt_reset {
const struct fdt_match *match_table;
int (*init)(void *fdt, int nodeoff, const struct fdt_match *match);
};
#ifdef CONFIG_FDT_RESET
/**
* fdt_reset_driver_init() - initialize reset driver based on the device-tree
*/
int fdt_reset_driver_init(void *fdt, struct fdt_reset *drv);
/**
* fdt_reset_init() - initialize reset drivers based on the device-tree
*
* This function shall be invoked in final init.
*/
void fdt_reset_init(void);
#else
static inline int fdt_reset_driver_init(void *fdt, struct fdt_reset *drv)
{
return 0;
}
static inline void fdt_reset_init(void) { }
#endif
#endif

View File

@@ -11,19 +11,15 @@
#define __FDT_SERIAL_H__
#include <sbi/sbi_types.h>
#include <sbi_utils/fdt/fdt_driver.h>
#ifdef CONFIG_FDT_SERIAL
struct fdt_serial {
const struct fdt_match *match_table;
int (*init)(void *fdt, int nodeoff, const struct fdt_match *match);
};
int fdt_serial_init(void);
int fdt_serial_init(const void *fdt);
#else
static inline int fdt_serial_init(void) { return 0; }
static inline int fdt_serial_init(const void *fdt) { return 0; }
#endif

View File

@@ -38,10 +38,10 @@ enum semihosting_open_mode {
#ifdef CONFIG_SERIAL_SEMIHOSTING
int semihosting_init(void);
int semihosting_enabled(void);
bool semihosting_enabled(void);
#else
static inline int semihosting_init(void) { return SBI_ENODEV; }
static inline int semihosting_enabled(void) { return 0; }
static inline bool semihosting_enabled(void) { return false; }
#endif
#endif

View File

@@ -12,7 +12,9 @@
#include <sbi/sbi_types.h>
#define UART_CAP_UUE BIT(0) /* Check UUE capability for XScale PXA UARTs */
int uart8250_init(unsigned long base, u32 in_freq, u32 baudrate, u32 reg_shift,
u32 reg_width, u32 reg_offset);
u32 reg_width, u32 reg_offset, u32 caps);
#endif

View File

@@ -47,8 +47,6 @@ void aclint_mtimer_sync(struct aclint_mtimer_data *mt);
void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
struct aclint_mtimer_data *ref);
int aclint_mtimer_warm_init(void);
int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,
struct aclint_mtimer_data *reference);

View File

@@ -24,6 +24,5 @@ struct plmt_data {
};
int plmt_cold_timer_init(struct plmt_data *plmt);
int plmt_warm_timer_init(void);
#endif /* __TIMER_ANDES_PLMT_H__ */

View File

@@ -11,24 +11,15 @@
#define __FDT_TIMER_H__
#include <sbi/sbi_types.h>
#include <sbi_utils/fdt/fdt_driver.h>
#ifdef CONFIG_FDT_TIMER
struct fdt_timer {
const struct fdt_match *match_table;
int (*cold_init)(void *fdt, int nodeoff, const struct fdt_match *match);
int (*warm_init)(void);
void (*exit)(void);
};
void fdt_timer_exit(void);
int fdt_timer_init(bool cold_boot);
int fdt_timer_init(void);
#else
static inline void fdt_timer_exit(void) { }
static inline int fdt_timer_init(bool cold_boot) { return 0; }
static inline int fdt_timer_init(void) { return 0; }
#endif

View File

@@ -1,6 +1,10 @@
# SPDX-License-Identifier: BSD-2-Clause
menu "SBI Extension Support"
menu "Generic SBI Support"
config CONSOLE_EARLY_BUFFER_SIZE
int "Early console buffer size (bytes)"
default 256
config SBI_ECALL_TIME
bool "Timer extension"
@@ -62,4 +66,7 @@ config SBI_ECALL_SSE
bool "SSE extension"
default y
config SBI_ECALL_MPXY
bool "MPXY extension"
default y
endmenu

View File

@@ -13,7 +13,7 @@ libsbi-objs-y += riscv_hardfp.o
libsbi-objs-y += riscv_locks.o
libsbi-objs-y += sbi_ecall.o
libsbi-objs-y += sbi_ecall_exts.o
libsbi-objs-y += sbi_ecall_exts.carray.o
# The order of below extensions is performance optimized
carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_TIME) += ecall_time
@@ -61,11 +61,16 @@ libsbi-objs-$(CONFIG_SBI_ECALL_DBTR) += sbi_ecall_dbtr.o
carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_SSE) += ecall_sse
libsbi-objs-$(CONFIG_SBI_ECALL_SSE) += sbi_ecall_sse.o
carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_MPXY) += ecall_mpxy
libsbi-objs-$(CONFIG_SBI_ECALL_MPXY) += sbi_ecall_mpxy.o
libsbi-objs-y += sbi_bitmap.o
libsbi-objs-y += sbi_bitops.o
libsbi-objs-y += sbi_console.o
libsbi-objs-y += sbi_domain_context.o
libsbi-objs-y += sbi_domain_data.o
libsbi-objs-y += sbi_domain.o
libsbi-objs-y += sbi_double_trap.o
libsbi-objs-y += sbi_emulate_csr.o
libsbi-objs-y += sbi_fifo.o
libsbi-objs-y += sbi_fwft.o
@@ -74,6 +79,7 @@ libsbi-objs-y += sbi_heap.o
libsbi-objs-y += sbi_math.o
libsbi-objs-y += sbi_hfence.o
libsbi-objs-y += sbi_hsm.o
libsbi-objs-y += sbi_illegal_atomic.o
libsbi-objs-y += sbi_illegal_insn.o
libsbi-objs-y += sbi_init.o
libsbi-objs-y += sbi_ipi.o
@@ -81,6 +87,7 @@ libsbi-objs-y += sbi_irqchip.o
libsbi-objs-y += sbi_platform.o
libsbi-objs-y += sbi_pmu.o
libsbi-objs-y += sbi_dbtr.o
libsbi-objs-y += sbi_mpxy.o
libsbi-objs-y += sbi_scratch.o
libsbi-objs-y += sbi_sse.o
libsbi-objs-y += sbi_string.o
@@ -89,6 +96,7 @@ libsbi-objs-y += sbi_timer.o
libsbi-objs-y += sbi_tlb.o
libsbi-objs-y += sbi_trap.o
libsbi-objs-y += sbi_trap_ldst.o
libsbi-objs-y += sbi_trap_v_ldst.o
libsbi-objs-y += sbi_unpriv.o
libsbi-objs-y += sbi_expected_trap.o
libsbi-objs-y += sbi_cppc.o

View File

@@ -291,7 +291,8 @@ int is_pmp_entry_mapped(unsigned long entry)
unsigned long addr;
unsigned long log2len;
pmp_get(entry, &prot, &addr, &log2len);
if (pmp_get(entry, &prot, &addr, &log2len) != 0)
return false;
/* If address matching bits are non-zero, the entry is enable */
if (prot & PMP_A)

View File

@@ -12,7 +12,7 @@
#include <sbi/riscv_atomic.h>
#include <sbi/riscv_barrier.h>
#ifndef __riscv_atomic
#if !defined(__riscv_atomic) && !defined(__riscv_zalrsc)
#error "opensbi strongly relies on the A extension of RISC-V"
#endif
@@ -31,6 +31,7 @@ void atomic_write(atomic_t *atom, long value)
long atomic_add_return(atomic_t *atom, long value)
{
#ifdef __riscv_atomic
long ret;
#if __SIZEOF_LONG__ == 4
__asm__ __volatile__(" amoadd.w.aqrl %1, %2, %0"
@@ -43,6 +44,29 @@ long atomic_add_return(atomic_t *atom, long value)
: "r"(value)
: "memory");
#endif
#elif __riscv_zalrsc
long ret, temp;
#if __SIZEOF_LONG__ == 4
__asm__ __volatile__("1:lr.w.aqrl %1,%0\n"
" addw %2,%1,%3\n"
" sc.w.aqrl %2,%2,%0\n"
" bnez %2,1b"
: "+A"(atom->counter), "=&r"(ret), "=&r"(temp)
: "r"(value)
: "memory");
#elif __SIZEOF_LONG__ == 8
__asm__ __volatile__("1:lr.d.aqrl %1,%0\n"
" add %2,%1,%3\n"
" sc.d.aqrl %2,%2,%0\n"
" bnez %2,1b"
: "+A"(atom->counter), "=&r"(ret), "=&r"(temp)
: "r"(value)
: "memory");
#endif
#else
#error "need a or zalrsc"
#endif
return ret + value;
}
@@ -51,6 +75,7 @@ long atomic_sub_return(atomic_t *atom, long value)
return atomic_add_return(atom, -value);
}
#ifdef __riscv_atomic
#define __axchg(ptr, new, size) \
({ \
__typeof__(ptr) __ptr = (ptr); \
@@ -76,6 +101,39 @@ long atomic_sub_return(atomic_t *atom, long value)
} \
__ret; \
})
#elif __riscv_zalrsc
#define __axchg(ptr, new, size) \
({ \
__typeof__(ptr) __ptr = (ptr); \
__typeof__(new) __new = (new); \
__typeof__(*(ptr)) __ret, __temp; \
switch (size) { \
case 4: \
__asm__ __volatile__ ( \
"1: lr.w.aqrl %0, %1\n" \
" sc.w.aqrl %2, %3, %1\n" \
" bnez %2, 1b\n" \
: "=&r" (__ret), "+A" (*__ptr), "=&r" (__temp) \
: "r" (__new) \
: "memory"); \
break; \
case 8: \
__asm__ __volatile__ ( \
"1: lr.d.aqrl %0, %1\n" \
" sc.d.aqrl %2, %3, %1\n" \
" bnez %2, 1b\n" \
: "=&r" (__ret), "+A" (*__ptr), "=&r" (__temp) \
: "r" (__new) \
: "memory"); \
break; \
default: \
break; \
} \
__ret; \
})
#else
#error "need a or zalrsc"
#endif
#define axchg(ptr, x) \
({ \

View File

@@ -53,7 +53,16 @@ void spin_lock(spinlock_t *lock)
__asm__ __volatile__(
/* Atomically increment the next ticket. */
#ifdef __riscv_atomic
" amoadd.w.aqrl %0, %4, %3\n"
#elif __riscv_zalrsc
"3: lr.w.aqrl %0, %3\n"
" addw %1, %0, %4\n"
" sc.w.aqrl %1, %1, %3\n"
" bnez %1, 3b\n"
#else
#error "need a or zalrsc"
#endif
/* Did we get the lock? */
" srli %1, %0, %6\n"

View File

@@ -9,6 +9,7 @@
#include <sbi/riscv_locks.h>
#include <sbi/sbi_console.h>
#include <sbi/sbi_fifo.h>
#include <sbi/sbi_hart.h>
#include <sbi/sbi_platform.h>
#include <sbi/sbi_scratch.h>
@@ -21,6 +22,15 @@ static char console_tbuf[CONSOLE_TBUF_MAX];
static u32 console_tbuf_len;
static spinlock_t console_out_lock = SPIN_LOCK_INITIALIZER;
#ifdef CONFIG_CONSOLE_EARLY_BUFFER_SIZE
#define CONSOLE_EARLY_BUFFER_SIZE CONFIG_CONSOLE_EARLY_BUFFER_SIZE
#else
#define CONSOLE_EARLY_BUFFER_SIZE 256
#endif
static char console_early_buffer[CONSOLE_EARLY_BUFFER_SIZE] = { 0 };
static SBI_FIFO_DEFINE(console_early_fifo, console_early_buffer, \
CONSOLE_EARLY_BUFFER_SIZE, sizeof(char));
bool sbi_isprintable(char c)
{
if (((31 < c) && (c < 127)) || (c == '\f') || (c == '\r') ||
@@ -39,6 +49,7 @@ int sbi_getc(void)
static unsigned long nputs(const char *str, unsigned long len)
{
char ch;
unsigned long i;
if (console_dev) {
@@ -51,6 +62,11 @@ static unsigned long nputs(const char *str, unsigned long len)
console_dev->console_putc(str[i]);
}
}
} else {
for (i = 0; i < len; i++) {
ch = str[i];
sbi_fifo_enqueue(&console_early_fifo, &ch, true);
}
}
return len;
}
@@ -472,19 +488,19 @@ const struct sbi_console_device *sbi_console_get_device(void)
void sbi_console_set_device(const struct sbi_console_device *dev)
{
char ch;
bool flush_early_fifo = false;
if (!dev)
return;
if (!console_dev)
flush_early_fifo = true;
console_dev = dev;
if (flush_early_fifo) {
while (!sbi_fifo_dequeue(&console_early_fifo, &ch))
sbi_putc(ch);
}
int sbi_console_init(struct sbi_scratch *scratch)
{
int rc = sbi_platform_console_init(sbi_platform_ptr(scratch));
/* console is not a necessary device */
if (rc == SBI_ENODEV)
return 0;
return rc;
}

View File

@@ -167,11 +167,11 @@ int sbi_dbtr_init(struct sbi_scratch *scratch, bool coldboot)
goto _probed;
for (i = 0; i < RV_MAX_TRIGGERS; i++) {
csr_write_allowed(CSR_TSELECT, (ulong)&trap, i);
csr_write_allowed(CSR_TSELECT, &trap, i);
if (trap.cause)
break;
val = csr_read_allowed(CSR_TSELECT, (ulong)&trap);
val = csr_read_allowed(CSR_TSELECT, &trap);
if (trap.cause)
break;
@@ -182,7 +182,7 @@ int sbi_dbtr_init(struct sbi_scratch *scratch, bool coldboot)
if (val != i)
break;
val = csr_read_allowed(CSR_TINFO, (ulong)&trap);
val = csr_read_allowed(CSR_TINFO, &trap);
if (trap.cause) {
/*
* If reading tinfo caused an exception, the
@@ -190,7 +190,7 @@ int sbi_dbtr_init(struct sbi_scratch *scratch, bool coldboot)
* type.
*/
tdata1 = csr_read_allowed(CSR_TDATA1,
(ulong)&trap);
&trap);
if (trap.cause)
break;
@@ -243,10 +243,9 @@ int sbi_dbtr_setup_shmem(const struct sbi_domain *dom, unsigned long smode,
unsigned long shmem_phys_lo,
unsigned long shmem_phys_hi)
{
u32 hartid = current_hartid();
struct sbi_dbtr_hart_triggers_state *hart_state;
if (dom && !sbi_domain_is_assigned_hart(dom, hartid)) {
if (dom && !sbi_domain_is_assigned_hart(dom, current_hartindex())) {
sbi_dprintf("%s: calling hart not assigned to this domain\n",
__func__);
return SBI_ERR_DENIED;
@@ -357,7 +356,7 @@ static void dbtr_trigger_enable(struct sbi_dbtr_trigger *trig)
unsigned long state;
unsigned long tdata1;
if (!trig && !(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
if (!trig || !(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
return;
state = trig->state;
@@ -403,7 +402,7 @@ static void dbtr_trigger_disable(struct sbi_dbtr_trigger *trig)
{
unsigned long tdata1;
if (!trig && !(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
if (!trig || !(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
return;
tdata1 = trig->tdata1;
@@ -429,7 +428,7 @@ static void dbtr_trigger_disable(struct sbi_dbtr_trigger *trig)
static void dbtr_trigger_clear(struct sbi_dbtr_trigger *trig)
{
if (!trig && !(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
if (!trig || !(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
return;
csr_write(CSR_TSELECT, trig->index);
@@ -507,7 +506,7 @@ int sbi_dbtr_read_trig(unsigned long smode,
{
struct sbi_dbtr_data_msg *xmit;
struct sbi_dbtr_trigger *trig;
struct sbi_dbtr_shmem_entry *entry;
union sbi_dbtr_shmem_entry *entry;
void *shmem_base = NULL;
struct sbi_dbtr_hart_triggers_state *hs = NULL;
@@ -524,16 +523,17 @@ int sbi_dbtr_read_trig(unsigned long smode,
shmem_base = hart_shmem_base(hs);
sbi_hart_map_saddr((unsigned long)shmem_base,
trig_count * sizeof(*entry));
for_each_trig_entry(shmem_base, trig_count, typeof(*entry), entry) {
sbi_hart_map_saddr((unsigned long)entry, sizeof(*entry));
xmit = &entry->data;
trig = INDEX_TO_TRIGGER((_idx + trig_idx_base));
xmit->tstate = cpu_to_lle(trig->state);
xmit->tdata1 = cpu_to_lle(trig->tdata1);
xmit->tdata2 = cpu_to_lle(trig->tdata2);
xmit->tdata3 = cpu_to_lle(trig->tdata3);
sbi_hart_unmap_saddr();
}
sbi_hart_unmap_saddr();
return SBI_SUCCESS;
}
@@ -542,7 +542,7 @@ int sbi_dbtr_install_trig(unsigned long smode,
unsigned long trig_count, unsigned long *out)
{
void *shmem_base = NULL;
struct sbi_dbtr_shmem_entry *entry;
union sbi_dbtr_shmem_entry *entry;
struct sbi_dbtr_data_msg *recv;
struct sbi_dbtr_id_msg *xmit;
unsigned long ctrl;
@@ -557,10 +557,11 @@ int sbi_dbtr_install_trig(unsigned long smode,
return SBI_ERR_NO_SHMEM;
shmem_base = hart_shmem_base(hs);
sbi_hart_map_saddr((unsigned long)shmem_base,
trig_count * sizeof(*entry));
/* Check requested triggers configuration */
for_each_trig_entry(shmem_base, trig_count, typeof(*entry), entry) {
sbi_hart_map_saddr((unsigned long)entry, sizeof(*entry));
recv = (struct sbi_dbtr_data_msg *)(&entry->data);
ctrl = recv->tdata1;
@@ -575,11 +576,11 @@ int sbi_dbtr_install_trig(unsigned long smode,
sbi_hart_unmap_saddr();
return SBI_ERR_FAILED;
}
sbi_hart_unmap_saddr();
}
if (hs->available_trigs < trig_count) {
*out = hs->available_trigs;
sbi_hart_unmap_saddr();
return SBI_ERR_FAILED;
}
@@ -591,16 +592,15 @@ int sbi_dbtr_install_trig(unsigned long smode,
*/
trig = sbi_alloc_trigger();
sbi_hart_map_saddr((unsigned long)entry, sizeof(*entry));
recv = (struct sbi_dbtr_data_msg *)(&entry->data);
xmit = (struct sbi_dbtr_id_msg *)(&entry->id);
dbtr_trigger_setup(trig, recv);
dbtr_trigger_enable(trig);
xmit->idx = cpu_to_lle(trig->index);
sbi_hart_unmap_saddr();
}
sbi_hart_unmap_saddr();
return SBI_SUCCESS;
}
@@ -652,15 +652,11 @@ int sbi_dbtr_enable_trig(unsigned long trig_idx_base,
}
int sbi_dbtr_update_trig(unsigned long smode,
unsigned long trig_idx_base,
unsigned long trig_idx_mask)
unsigned long trig_count)
{
unsigned long trig_mask = trig_idx_mask << trig_idx_base;
unsigned long idx = trig_idx_base;
struct sbi_dbtr_data_msg *recv;
unsigned long uidx = 0;
unsigned long trig_idx;
struct sbi_dbtr_trigger *trig;
struct sbi_dbtr_shmem_entry *entry;
union sbi_dbtr_shmem_entry *entry;
void *shmem_base = NULL;
struct sbi_dbtr_hart_triggers_state *hs = NULL;
@@ -673,18 +669,28 @@ int sbi_dbtr_update_trig(unsigned long smode,
shmem_base = hart_shmem_base(hs);
for_each_set_bit_from(idx, &trig_mask, hs->total_trigs) {
trig = INDEX_TO_TRIGGER(idx);
if (trig_count >= hs->total_trigs)
return SBI_ERR_BAD_RANGE;
if (!(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED)))
for_each_trig_entry(shmem_base, trig_count, typeof(*entry), entry) {
sbi_hart_map_saddr((unsigned long)entry, sizeof(*entry));
trig_idx = entry->id.idx;
if (trig_idx >= hs->total_trigs) {
sbi_hart_unmap_saddr();
return SBI_ERR_INVALID_PARAM;
}
entry = (shmem_base + uidx * sizeof(*entry));
recv = &entry->data;
trig = INDEX_TO_TRIGGER(trig_idx);
trig->tdata2 = lle_to_cpu(recv->tdata2);
if (!(trig->state & RV_DBTR_BIT_MASK(TS, MAPPED))) {
sbi_hart_unmap_saddr();
return SBI_ERR_FAILED;
}
dbtr_trigger_setup(trig, &entry->data);
sbi_hart_unmap_saddr();
dbtr_trigger_enable(trig);
uidx++;
}
return SBI_SUCCESS;

View File

@@ -13,20 +13,18 @@
#include <sbi/sbi_hartmask.h>
#include <sbi/sbi_heap.h>
#include <sbi/sbi_hsm.h>
#include <sbi/sbi_list.h>
#include <sbi/sbi_math.h>
#include <sbi/sbi_platform.h>
#include <sbi/sbi_scratch.h>
#include <sbi/sbi_string.h>
/*
* We allocate an extra element because sbi_domain_for_each() expects
* the array to be null-terminated.
*/
struct sbi_domain *domidx_to_domain_table[SBI_DOMAIN_MAX_INDEX + 1] = { 0 };
SBI_LIST_HEAD(domain_list);
static u32 domain_count = 0;
static bool domain_finalized = false;
#define ROOT_REGION_MAX 16
#define ROOT_REGION_MAX 32
static u32 root_memregs_count = 0;
struct sbi_domain root = {
@@ -62,7 +60,7 @@ void sbi_update_hartindex_to_domain(u32 hartindex, struct sbi_domain *dom)
sbi_scratch_write_type(scratch, void *, domain_hart_ptr_offset, dom);
}
bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartid)
bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartindex)
{
bool ret;
struct sbi_domain *tdom = (struct sbi_domain *)dom;
@@ -71,26 +69,25 @@ bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartid)
return false;
spin_lock(&tdom->assigned_harts_lock);
ret = sbi_hartmask_test_hartid(hartid, &tdom->assigned_harts);
ret = sbi_hartmask_test_hartindex(hartindex, &tdom->assigned_harts);
spin_unlock(&tdom->assigned_harts_lock);
return ret;
}
ulong sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom,
ulong hbase)
int sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom,
struct sbi_hartmask *mask)
{
ulong ret = 0;
struct sbi_domain *tdom = (struct sbi_domain *)dom;
if (!dom)
if (!dom) {
sbi_hartmask_clear_all(mask);
return 0;
}
spin_lock(&tdom->assigned_harts_lock);
for (int i = 0; i < 8 * sizeof(ret); i++) {
if (sbi_hartmask_test_hartid(hbase + i, &tdom->assigned_harts))
ret |= 1UL << i;
}
sbi_hartmask_copy(mask, &tdom->assigned_harts);
spin_unlock(&tdom->assigned_harts_lock);
return ret;
@@ -449,7 +446,7 @@ void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix)
sbi_hartmask_for_each_hartindex(i, dom->possible_harts) {
j = sbi_hartindex_to_hartid(i);
sbi_printf("%s%d%s", (k++) ? "," : "",
j, sbi_domain_is_assigned_hart(dom, j) ? "*" : "");
j, sbi_domain_is_assigned_hart(dom, i) ? "*" : "");
}
sbi_printf("\n");
@@ -519,10 +516,9 @@ void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix)
void sbi_domain_dump_all(const char *suffix)
{
u32 i;
const struct sbi_domain *dom;
sbi_domain_for_each(i, dom) {
sbi_domain_for_each(dom) {
sbi_domain_dump(dom, suffix);
sbi_printf("\n");
}
@@ -541,21 +537,11 @@ int sbi_domain_register(struct sbi_domain *dom,
return SBI_EINVAL;
/* Check if domain already discovered */
sbi_domain_for_each(i, tdom) {
sbi_domain_for_each(tdom) {
if (tdom == dom)
return SBI_EALREADY;
}
/*
* Ensure that we have room for Domain Index to
* HART ID mapping
*/
if (SBI_DOMAIN_MAX_INDEX <= domain_count) {
sbi_printf("%s: No room for %s\n",
__func__, dom->name);
return SBI_ENOSPC;
}
/* Sanitize discovered domain */
rc = sanitize_domain(dom);
if (rc) {
@@ -565,9 +551,10 @@ int sbi_domain_register(struct sbi_domain *dom,
return rc;
}
sbi_list_add_tail(&dom->node, &domain_list);
/* Assign index to domain */
dom->index = domain_count++;
domidx_to_domain_table[dom->index] = dom;
/* Initialize spinlock for dom->assigned_harts */
SPIN_LOCK_INIT(dom->assigned_harts_lock);
@@ -599,10 +586,19 @@ int sbi_domain_register(struct sbi_domain *dom,
}
}
/* Setup data for the discovered domain */
rc = sbi_domain_setup_data(dom);
if (rc) {
sbi_printf("%s: domain data setup failed for %s (error %d)\n",
__func__, dom->name, rc);
sbi_list_del(&dom->node);
return rc;
}
return 0;
}
int sbi_domain_root_add_memregion(const struct sbi_domain_memregion *reg)
static int root_add_memregion(const struct sbi_domain_memregion *reg)
{
int rc;
bool reg_merged;
@@ -680,7 +676,7 @@ int sbi_domain_root_add_memrange(unsigned long addr, unsigned long size,
(end - pos) : align;
sbi_domain_memregion_init(pos, rsize, region_flags, &reg);
rc = sbi_domain_root_add_memregion(&reg);
rc = root_add_memregion(&reg);
if (rc)
return rc;
pos += rsize;
@@ -689,23 +685,18 @@ int sbi_domain_root_add_memrange(unsigned long addr, unsigned long size,
return 0;
}
int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid)
int sbi_domain_startup(struct sbi_scratch *scratch, u32 cold_hartid)
{
int rc;
u32 i, dhart;
u32 dhart;
struct sbi_domain *dom;
const struct sbi_platform *plat = sbi_platform_ptr(scratch);
/* Initialize and populate domains for the platform */
rc = sbi_platform_domains_init(plat);
if (rc) {
sbi_printf("%s: platform domains_init() failed (error %d)\n",
__func__, rc);
return rc;
}
/* Sanity checks */
if (!domain_finalized)
return SBI_EINVAL;
/* Startup boot HART of domains */
sbi_domain_for_each(i, dom) {
sbi_domain_for_each(dom) {
/* Domain boot HART index */
dhart = sbi_hartid_to_hartindex(dom->boot_hartid);
@@ -748,6 +739,26 @@ int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid)
}
}
return 0;
}
int sbi_domain_finalize(struct sbi_scratch *scratch)
{
int rc;
const struct sbi_platform *plat = sbi_platform_ptr(scratch);
/* Sanity checks */
if (domain_finalized)
return SBI_EINVAL;
/* Initialize and populate domains for the platform */
rc = sbi_platform_domains_init(plat);
if (rc) {
sbi_printf("%s: platform domains_init() failed (error %d)\n",
__func__, rc);
return rc;
}
/*
* Set the finalized flag so that the root domain
* regions can't be changed.
@@ -759,11 +770,11 @@ int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid)
int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid)
{
u32 i;
int rc;
struct sbi_hartmask *root_hmask;
struct sbi_domain_memregion *root_memregs;
const struct sbi_platform *plat = sbi_platform_ptr(scratch);
SBI_INIT_LIST_HEAD(&domain_list);
if (scratch->fw_rw_offset == 0 ||
(scratch->fw_rw_offset & (scratch->fw_rw_offset - 1)) != 0) {
@@ -782,11 +793,16 @@ int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid)
if (!domain_hart_ptr_offset)
return SBI_ENOMEM;
/* Initialize domain context support */
rc = sbi_domain_context_init();
if (rc)
goto fail_free_domain_hart_ptr_offset;
root_memregs = sbi_calloc(sizeof(*root_memregs), ROOT_REGION_MAX + 1);
if (!root_memregs) {
sbi_printf("%s: no memory for root regions\n", __func__);
rc = SBI_ENOMEM;
goto fail_free_domain_hart_ptr_offset;
goto fail_deinit_context;
}
root.regions = root_memregs;
@@ -837,7 +853,7 @@ int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid)
root.next_mode = scratch->next_mode;
/* Root domain possible and assigned HARTs */
for (i = 0; i < plat->hart_count; i++)
sbi_for_each_hartindex(i)
sbi_hartmask_set_hartindex(i, root_hmask);
/* Finally register the root domain */
@@ -851,6 +867,8 @@ fail_free_root_hmask:
sbi_free(root_hmask);
fail_free_root_memregs:
sbi_free(root_memregs);
fail_deinit_context:
sbi_domain_context_deinit();
fail_free_domain_hart_ptr_offset:
sbi_scratch_free_offset(domain_hart_ptr_offset);
return rc;

120
lib/sbi/sbi_domain_context.c Executable file → Normal file
View File

@@ -13,7 +13,77 @@
#include <sbi/sbi_heap.h>
#include <sbi/sbi_scratch.h>
#include <sbi/sbi_string.h>
#include <sbi/sbi_domain.h>
#include <sbi/sbi_domain_context.h>
#include <sbi/sbi_platform.h>
#include <sbi/sbi_trap.h>
/** Context representation for a hart within a domain */
struct hart_context {
/** Trap-related states such as GPRs, mepc, and mstatus */
struct sbi_trap_context trap_ctx;
/** Supervisor status register */
unsigned long sstatus;
/** Supervisor interrupt enable register */
unsigned long sie;
/** Supervisor trap vector base address register */
unsigned long stvec;
/** Supervisor scratch register for temporary storage */
unsigned long sscratch;
/** Supervisor exception program counter register */
unsigned long sepc;
/** Supervisor cause register */
unsigned long scause;
/** Supervisor trap value register */
unsigned long stval;
/** Supervisor interrupt pending register */
unsigned long sip;
/** Supervisor address translation and protection register */
unsigned long satp;
/** Counter-enable register */
unsigned long scounteren;
/** Supervisor environment configuration register */
unsigned long senvcfg;
/** Reference to the owning domain */
struct sbi_domain *dom;
/** Previous context (caller) to jump to during context exits */
struct hart_context *prev_ctx;
/** Is context initialized and runnable */
bool initialized;
};
static struct sbi_domain_data dcpriv;
static inline struct hart_context *hart_context_get(struct sbi_domain *dom,
u32 hartindex)
{
struct hart_context **dom_hartindex_to_context_table;
dom_hartindex_to_context_table = sbi_domain_data_ptr(dom, &dcpriv);
if (!dom_hartindex_to_context_table || !sbi_hartindex_valid(hartindex))
return NULL;
return dom_hartindex_to_context_table[hartindex];
}
static void hart_context_set(struct sbi_domain *dom, u32 hartindex,
struct hart_context *hc)
{
struct hart_context **dom_hartindex_to_context_table;
dom_hartindex_to_context_table = sbi_domain_data_ptr(dom, &dcpriv);
if (!dom_hartindex_to_context_table || !sbi_hartindex_valid(hartindex))
return;
dom_hartindex_to_context_table[hartindex] = hc;
}
/** Macro to obtain the current hart's context pointer */
#define hart_context_thishart_get() \
hart_context_get(sbi_domain_thishart_ptr(), \
current_hartindex())
/**
* Switches the HART context from the current domain to the target domain.
@@ -23,10 +93,10 @@
* @param ctx pointer to the current HART context
* @param dom_ctx pointer to the target domain context
*/
static void switch_to_next_domain_context(struct sbi_context *ctx,
struct sbi_context *dom_ctx)
static void switch_to_next_domain_context(struct hart_context *ctx,
struct hart_context *dom_ctx)
{
u32 hartindex = sbi_hartid_to_hartindex(current_hartid());
u32 hartindex = current_hartindex();
struct sbi_trap_context *trap_ctx;
struct sbi_domain *current_dom = ctx->dom;
struct sbi_domain *target_dom = dom_ctx->dom;
@@ -46,6 +116,7 @@ static void switch_to_next_domain_context(struct sbi_context *ctx,
/* Reconfigure PMP settings for the new domain */
for (int i = 0; i < pmp_count; i++) {
sbi_platform_pmp_disable(sbi_platform_thishart_ptr(), i);
pmp_disable(i);
}
sbi_hart_pmp_configure(scratch);
@@ -89,9 +160,8 @@ static void switch_to_next_domain_context(struct sbi_context *ctx,
int sbi_domain_context_enter(struct sbi_domain *dom)
{
struct sbi_context *ctx = sbi_domain_context_thishart_ptr();
struct sbi_context *dom_ctx = sbi_hartindex_to_domain_context(
sbi_hartid_to_hartindex(current_hartid()), dom);
struct hart_context *ctx = hart_context_thishart_get();
struct hart_context *dom_ctx = hart_context_get(dom, current_hartindex());
/* Validate the domain context existence */
if (!dom_ctx)
@@ -107,10 +177,10 @@ int sbi_domain_context_enter(struct sbi_domain *dom)
int sbi_domain_context_exit(void)
{
u32 i, hartindex = sbi_hartid_to_hartindex(current_hartid());
u32 hartindex = current_hartindex();
struct sbi_domain *dom;
struct sbi_context *ctx = sbi_domain_context_thishart_ptr();
struct sbi_context *dom_ctx, *tmp;
struct hart_context *ctx = hart_context_thishart_get();
struct hart_context *dom_ctx, *tmp;
/*
* If it's first time to call `exit` on the current hart, no
@@ -118,21 +188,21 @@ int sbi_domain_context_exit(void)
* its context on the current hart if valid.
*/
if (!ctx) {
sbi_domain_for_each(i, dom) {
sbi_domain_for_each(dom) {
if (!sbi_hartmask_test_hartindex(hartindex,
dom->possible_harts))
continue;
dom_ctx = sbi_zalloc(sizeof(struct sbi_context));
dom_ctx = sbi_zalloc(sizeof(struct hart_context));
if (!dom_ctx)
return SBI_ENOMEM;
/* Bind context and domain */
dom_ctx->dom = dom;
dom->hartindex_to_context_table[hartindex] = dom_ctx;
hart_context_set(dom, hartindex, dom_ctx);
}
ctx = sbi_domain_context_thishart_ptr();
ctx = hart_context_thishart_get();
}
dom_ctx = ctx->prev_ctx;
@@ -140,11 +210,11 @@ int sbi_domain_context_exit(void)
/* If no previous caller context */
if (!dom_ctx) {
/* Try to find next uninitialized user-defined domain's context */
sbi_domain_for_each(i, dom) {
sbi_domain_for_each(dom) {
if (dom == &root || dom == sbi_domain_thishart_ptr())
continue;
tmp = sbi_hartindex_to_domain_context(hartindex, dom);
tmp = hart_context_get(dom, hartindex);
if (tmp && !tmp->initialized) {
dom_ctx = tmp;
break;
@@ -154,9 +224,27 @@ int sbi_domain_context_exit(void)
/* Take the root domain context if fail to find */
if (!dom_ctx)
dom_ctx = sbi_hartindex_to_domain_context(hartindex, &root);
dom_ctx = hart_context_get(&root, hartindex);
switch_to_next_domain_context(ctx, dom_ctx);
return 0;
}
int sbi_domain_context_init(void)
{
/**
* Allocate per-domain and per-hart context data.
* The data type is "struct hart_context **" whose memory space will be
* dynamically allocated by domain_setup_data_one(). Calculate needed
* size of memory space here.
*/
dcpriv.data_size = sizeof(struct hart_context *) * sbi_hart_count();
return sbi_domain_register_data(&dcpriv);
}
void sbi_domain_context_deinit(void)
{
sbi_domain_unregister_data(&dcpriv);
}

138
lib/sbi/sbi_domain_data.c Normal file
View File

@@ -0,0 +1,138 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2024 Ventana Micro Systems Inc.
*/
#include <sbi/sbi_bitmap.h>
#include <sbi/sbi_domain.h>
#include <sbi/sbi_error.h>
#include <sbi/sbi_heap.h>
static SBI_LIST_HEAD(data_list);
static DECLARE_BITMAP(data_idx_bmap, SBI_DOMAIN_MAX_DATA_PTRS);
void *sbi_domain_data_ptr(struct sbi_domain *dom, struct sbi_domain_data *data)
{
if (dom && data && data->data_idx < SBI_DOMAIN_MAX_DATA_PTRS)
return dom->data_priv.idx_to_data_ptr[data->data_idx];
return NULL;
}
static int domain_setup_data_one(struct sbi_domain *dom,
struct sbi_domain_data *data)
{
struct sbi_domain_data_priv *priv = &dom->data_priv;
void *data_ptr;
int rc;
if (priv->idx_to_data_ptr[data->data_idx])
return SBI_EALREADY;
data_ptr = sbi_zalloc(data->data_size);
if (!data_ptr) {
sbi_domain_cleanup_data(dom);
return SBI_ENOMEM;
}
if (data->data_setup) {
rc = data->data_setup(dom, data, data_ptr);
if (rc) {
sbi_free(data_ptr);
return rc;
}
}
priv->idx_to_data_ptr[data->data_idx] = data_ptr;
return 0;
}
static void domain_cleanup_data_one(struct sbi_domain *dom,
struct sbi_domain_data *data)
{
struct sbi_domain_data_priv *priv = &dom->data_priv;
void *data_ptr;
data_ptr = priv->idx_to_data_ptr[data->data_idx];
if (!data_ptr)
return;
if (data->data_cleanup)
data->data_cleanup(dom, data, data_ptr);
sbi_free(data_ptr);
priv->idx_to_data_ptr[data->data_idx] = NULL;
}
int sbi_domain_setup_data(struct sbi_domain *dom)
{
struct sbi_domain_data *data;
int rc;
if (!dom)
return SBI_EINVAL;
sbi_list_for_each_entry(data, &data_list, head) {
rc = domain_setup_data_one(dom, data);
if (rc) {
sbi_domain_cleanup_data(dom);
return rc;
}
}
return 0;
}
void sbi_domain_cleanup_data(struct sbi_domain *dom)
{
struct sbi_domain_data *data;
if (!dom)
return;
sbi_list_for_each_entry(data, &data_list, head)
domain_cleanup_data_one(dom, data);
}
int sbi_domain_register_data(struct sbi_domain_data *data)
{
struct sbi_domain *dom;
u32 data_idx;
int rc;
if (!data || !data->data_size)
return SBI_EINVAL;
for (data_idx = 0; data_idx < SBI_DOMAIN_MAX_DATA_PTRS; data_idx++) {
if (!bitmap_test(data_idx_bmap, data_idx))
break;
}
if (SBI_DOMAIN_MAX_DATA_PTRS <= data_idx)
return SBI_ENOSPC;
bitmap_set(data_idx_bmap, data_idx, 1);
data->data_idx = data_idx;
sbi_list_add_tail(&data->head, &data_list);
sbi_domain_for_each(dom) {
rc = domain_setup_data_one(dom, data);
if (rc) {
sbi_domain_unregister_data(data);
return rc;
}
}
return 0;
}
void sbi_domain_unregister_data(struct sbi_domain_data *data)
{
struct sbi_domain *dom;
sbi_domain_for_each(dom)
domain_cleanup_data_one(dom, data);
sbi_list_del(&data->head);
bitmap_clear(data_idx_bmap, data->data_idx, 1);
}

37
lib/sbi/sbi_double_trap.c Normal file
View File

@@ -0,0 +1,37 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2024 Rivos Inc.
*
* Authors:
* Clément Léger <clement.leger@rivosinc.com>
*/
#include <sbi/sbi_console.h>
#include <sbi/sbi_ecall_interface.h>
#include <sbi/sbi_error.h>
#include <sbi/sbi_hart.h>
#include <sbi/sbi_sse.h>
#include <sbi/sbi_trap.h>
int sbi_double_trap_handler(struct sbi_trap_context *tcntx)
{
struct sbi_trap_regs *regs = &tcntx->regs;
const struct sbi_trap_info *trap = &tcntx->trap;
bool prev_virt = sbi_regs_from_virt(regs);
if (sbi_mstatus_prev_mode(regs->mstatus) != PRV_S)
return SBI_ERR_INVALID_PARAM;
/* Exception was taken in VS-mode, redirect it to S-mode */
if (prev_virt)
return sbi_trap_redirect(regs, trap);
return sbi_sse_inject_event(SBI_SSE_EVENT_LOCAL_DOUBLE_TRAP);
}
void sbi_double_trap_init(struct sbi_scratch *scratch)
{
if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SSDBLTRP))
sbi_sse_add_event(SBI_SSE_EVENT_LOCAL_DOUBLE_TRAP, NULL);
}

View File

@@ -11,10 +11,10 @@
#include <sbi/sbi_ecall.h>
#include <sbi/sbi_ecall_interface.h>
#include <sbi/sbi_error.h>
#include <sbi/sbi_string.h>
#include <sbi/sbi_trap.h>
extern struct sbi_ecall_extension *sbi_ecall_exts[];
extern unsigned long sbi_ecall_exts_size;
extern struct sbi_ecall_extension *const sbi_ecall_exts[];
u16 sbi_ecall_version_major(void)
{
@@ -54,6 +54,29 @@ struct sbi_ecall_extension *sbi_ecall_find_extension(unsigned long extid)
return ret;
}
void sbi_ecall_get_extensions_str(char *exts_str, int exts_str_size, bool experimental)
{
struct sbi_ecall_extension *t;
int offset = 0;
if (!exts_str || exts_str_size <= 0)
return;
sbi_memset(exts_str, 0, exts_str_size);
sbi_list_for_each_entry(t, &ecall_exts_list, head) {
if (experimental != t->experimental)
continue;
sbi_snprintf(exts_str + offset, exts_str_size - offset,
"%s,", t->name);
offset = offset + sbi_strlen(t->name) + 1;
}
if (offset)
exts_str[offset - 1] = '\0';
else
sbi_strncpy(exts_str, "none", exts_str_size);
}
int sbi_ecall_register_extension(struct sbi_ecall_extension *ext)
{
struct sbi_ecall_extension *t;
@@ -70,7 +93,6 @@ int sbi_ecall_register_extension(struct sbi_ecall_extension *ext)
return SBI_EINVAL;
}
SBI_INIT_LIST_HEAD(&ext->head);
sbi_list_add_tail(&ext->head, &ecall_exts_list);
return 0;
@@ -148,7 +170,7 @@ int sbi_ecall_init(void)
struct sbi_ecall_extension *ext;
unsigned long i;
for (i = 0; i < sbi_ecall_exts_size; i++) {
for (i = 0; sbi_ecall_exts[i]; i++) {
ext = sbi_ecall_exts[i];
ret = SBI_ENODEV;

Some files were not shown because too many files have changed in this diff Show More