Compare commits

...

24 Commits
v1.7 ... master

Author SHA1 Message Date
Samuel Holland
153cdeea53 lib: sbi_heap: Simplify allocation algorithm
Now that the allocator cannot run out of nodes in the middle of an
allocation, the code can be simplified greatly. First it moves bytes
from the beginning and/or end of the node to new nodes in the free
list as necessary. These new nodes are inserted into the free list
in address order. Then it moves the original node to the used list.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Tested-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250617032306.1494528-4-samuel.holland@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-09-01 10:39:11 +05:30
Samuel Holland
8dcd1448e7 lib: sbi_heap: Allocate list nodes dynamically
Currently the heap has a fixed housekeeping factor of 16, which means
1/16 of the heap is reserved for list nodes. But this is not enough when
there are many small allocations; in the worst case, 1/3 of the heap is
needed for list nodes (32 byte heap_node for each 64 byte allocation).
This has caused allocation failures on some platforms.

Let's avoid trying to guess the best ratio. Instead, allocate more nodes
as needed. To avoid recursion, the nodes are permanent allocations. So
to minimize fragmentation, allocate them in small batches from the end
of the last free space node. Bootstrap the free space list by embedding
one node in the heap control struct.

Some error paths are avoided because the nodes are allocated up front.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Tested-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250617032306.1494528-3-samuel.holland@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-09-01 10:39:11 +05:30
Samuel Holland
64a38525e6 lib: sbi_list: Add a helper for reverse list iteration
Some use cases require iterating through a list in both directions.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Tested-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250617032306.1494528-2-samuel.holland@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-09-01 10:39:11 +05:30
Chao-ying Fu
1ffbd063c4 generic: mips: support harts to boot from mips_warm_boot
We program reset base for harts (other than hart 0) to boot at
mips_warm_boot that jumps to _start_warm. This helps to skip some code
sequence to speed up.

Signed-off-by: Chao-ying Fu <cfu@mips.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250723204010.9927-1-cfu@mips.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-08-28 11:00:16 +05:30
Jesse Taube
6a1f53bc2d dbtr: Fix sbi_dbtr_read_trig to read from CSRs
sbi_dbtr_read_trig returned the saved state of tdata{1-3}, when it
should have returned the updated state read from CSRs.

Update sbi_dbtr_read_trig to return updated state read from CSRs.

Signed-off-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Jesse Taube <jesse@rivosinc.com>
Link: https://lore.kernel.org/r/20250811152947.851208-1-jesse@rivosinc.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-08-28 10:50:14 +05:30
Jesse Taube
4b687e3669 dbtr: Add support for icount trigger type
The linux kernel needs icount to implement hardware breakpoints.

Signed-off-by: Jesse Taube <jesse@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250724183120.1822667-1-jesse@rivosinc.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-08-28 10:36:52 +05:30
Xiang W
6068efc7f5 Fix license to compatible BSD-2-Clause
OpenSBI is a BSD project. We need to modify some codes to compatible
with BSD-2-Clause license.

Signed-off-by: Xiang W <wxjstz@126.com>
Reviewed-by: Ben Zong-You Xie <ben717@andestech.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250728074334.372355-1-wxjstz@126.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-08-28 10:32:46 +05:30
Samuel Holland
bbe9a23060 platform: generic: Pack the FDT after applying fixups
This minimizes the size that will be reserved by the OS for the FDT, and
it prevents the FDT buffer from containing uninitialized memory, which
can be important for some simulation platforms and for attestation.

Closes: https://github.com/riscv-software-src/opensbi/issues/388
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250722233923.1356605-1-samuel.holland@sifive.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-08-28 10:26:25 +05:30
Manuel Hernández Méndez
525ac970b3 platform: openpiton: Move openpiton platform from fpga to generic
The OpenPiton framework has a generic PMU that is not used by OpenSBI.
Due to OpenSBI’s build system we cannot directly reuse the generic
platform functions, so move the OpenPiton platform to generic. Also due
to the generic platform is where new features are added.

Signed-off-by: Manuel Hernández Méndez <maherme.dev@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250813104759.33276-1-maherme.dev@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-08-26 17:08:00 +05:30
Manuel Hernández Méndez
3204d74486 lib: sbi: pmu: Improve loop in pmu_ctr_find_hw
We do not need to iterate over all values in the loop,
we can break the loop when we found a valid counter
that is not started yet.

Signed-off-by: Manuel Hernández Méndez <maherme.dev@gmail.com>
Link: https://lore.kernel.org/r/20250721160712.8766-1-maherme.dev@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-08-26 16:37:47 +05:30
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: 86c01a73ff9d ("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
42 changed files with 461 additions and 293 deletions

View File

@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-License-Identifier: BSD-2-Clause
# See here for more information about the format and editor support:
# https://editorconfig.org/

View File

@ -7,8 +7,8 @@ processor from ETH Zurich. To this end, Ariane has been equipped with a
different L1 cache subsystem that follows a write-through protocol and that has
support for cache invalidations and atomics.
To build platform specific library and firmwares, provide the
*PLATFORM=fpga/openpiton* parameter to the top level `make` command.
To build platform specific library and firmwares, provide the *PLATFORM=generic*
parameter to the top level `make` command.
Platform Options
----------------
@ -21,7 +21,7 @@ Building Ariane FPGA Platform
**Linux Kernel Payload**
```
make PLATFORM=fpga/openpiton FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
make PLATFORM=generic FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
```
Booting Ariane FPGA Platform

View File

@ -47,6 +47,7 @@ RISC-V Platforms Using Generic Platform
* **SiFive HiFive Unleashed** (*[sifive_fu540.md]*)
* **Spike** (*[spike.md]*)
* **T-HEAD C9xx series Processors** (*[thead-c9xx.md]*)
* **OpenPiton FPGA SoC** (*[fpga-openpiton.md]*)
[andes-ae350.md]: andes-ae350.md
[qemu_virt.md]: qemu_virt.md
@ -55,3 +56,4 @@ RISC-V Platforms Using Generic Platform
[sifive_fu540.md]: sifive_fu540.md
[spike.md]: spike.md
[thead-c9xx.md]: thead-c9xx.md
[fpga-openpiton.md]: fpga-openpiton.md

View File

@ -31,10 +31,6 @@ OpenSBI currently supports the following virtual and hardware platforms:
* **Spike**: Platform support for the Spike emulator. More
details on this platform can be found in the file *[spike.md]*.
* **OpenPiton FPGA SoC**: Platform support OpenPiton research platform based
on ariane core. More details on this platform can be found in the file
*[fpga-openpiton.md]*.
* **Shakti C-class SoC Platform**: Platform support for Shakti C-class
processor based SOCs. More details on this platform can be found in the
file *[shakti_cclass.md]*.
@ -56,6 +52,5 @@ comments to facilitate the implementation.
[andes-ae350.md]: andes-ae350.md
[thead-c910.md]: thead-c910.md
[spike.md]: spike.md
[fpga-openpiton.md]: fpga-openpiton.md
[shakti_cclass.md]: shakti_cclass.md
[renesas-rzfive.md]: renesas-rzfive.md

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

@ -76,21 +76,21 @@ _sc_fail:
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 */
@ -736,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

@ -47,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

@ -97,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

@ -122,6 +122,50 @@ enum {
RV_DBTR_DECLARE_BIT_MASK(MC, TYPE, 4),
};
/* ICOUNT - Match Control Type Register */
enum {
RV_DBTR_DECLARE_BIT(ICOUNT, ACTION, 0),
RV_DBTR_DECLARE_BIT(ICOUNT, U, 6),
RV_DBTR_DECLARE_BIT(ICOUNT, S, 7),
RV_DBTR_DECLARE_BIT(ICOUNT, PENDING, 8),
RV_DBTR_DECLARE_BIT(ICOUNT, M, 9),
RV_DBTR_DECLARE_BIT(ICOUNT, COUNT, 10),
RV_DBTR_DECLARE_BIT(ICOUNT, HIT, 24),
RV_DBTR_DECLARE_BIT(ICOUNT, VU, 25),
RV_DBTR_DECLARE_BIT(ICOUNT, VS, 26),
#if __riscv_xlen == 64
RV_DBTR_DECLARE_BIT(ICOUNT, DMODE, 59),
RV_DBTR_DECLARE_BIT(ICOUNT, TYPE, 60),
#elif __riscv_xlen == 32
RV_DBTR_DECLARE_BIT(ICOUNT, DMODE, 27),
RV_DBTR_DECLARE_BIT(ICOUNT, TYPE, 28),
#else
#error "Unknown __riscv_xlen"
#endif
};
enum {
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, ACTION, 6),
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, U, 1),
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, S, 1),
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, PENDING, 1),
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, M, 1),
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, COUNT, 14),
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, HIT, 1),
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, VU, 1),
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, VS, 1),
#if __riscv_xlen == 64
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, DMODE, 1),
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, TYPE, 4),
#elif __riscv_xlen == 32
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, DMODE, 1),
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, TYPE, 4),
#else
#error "Unknown __riscv_xlen"
#endif
};
/* MC6 - Match Control 6 Type Register */
enum {
RV_DBTR_DECLARE_BIT(MC6, LOAD, 0),

View File

@ -1291,6 +1291,8 @@
#define SHIFT_FUNCT3 12
#define MASK_RS1 0xf8000
#define MASK_RS2 0x1f00000
#define MASK_RD 0xf80
#define MASK_CSR 0xfff00000
#define SHIFT_CSR 20
@ -1315,13 +1317,6 @@
#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
@ -1356,28 +1351,17 @@
#define SHIFT_RIGHT(x, y) \
((y) < 0 ? ((x) << -(y)) : ((x) >> (y)))
#define REG_MASK \
((1 << (5 + LOG_REGBYTES)) - (1 << LOG_REGBYTES))
#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_FUNC3(insn) ((insn & MASK_FUNCT3) >> SHIFT_FUNCT3)
#define GET_RM(insn) GET_FUNC3(insn)
#define GET_RS1_NUM(insn) ((insn & MASK_RS1) >> 15)
#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 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))

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

@ -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

@ -134,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,

View File

@ -160,4 +160,28 @@ 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))
/**
* Iterate over list of given type in reverse order
* @param pos the type * to use as a loop cursor.
* @param head the head for your list.
* @param member the name of the list_struct within the struct.
*/
#define sbi_list_for_each_entry_reverse(pos, head, member) \
for (pos = sbi_list_entry((head)->prev, typeof(*pos), member); \
&pos->member != (head); \
pos = sbi_list_entry(pos->member.prev, typeof(*pos), member))
#endif

View File

@ -127,70 +127,75 @@
/** Representation of register state at time of trap/interrupt */
struct sbi_trap_regs {
/** zero register state */
unsigned long zero;
/** ra register state */
unsigned long ra;
/** sp register state */
unsigned long sp;
/** gp register state */
unsigned long gp;
/** tp register state */
unsigned long tp;
/** t0 register state */
unsigned long t0;
/** t1 register state */
unsigned long t1;
/** t2 register state */
unsigned long t2;
/** s0 register state */
unsigned long s0;
/** s1 register state */
unsigned long s1;
/** a0 register state */
unsigned long a0;
/** a1 register state */
unsigned long a1;
/** a2 register state */
unsigned long a2;
/** a3 register state */
unsigned long a3;
/** a4 register state */
unsigned long a4;
/** a5 register state */
unsigned long a5;
/** a6 register state */
unsigned long a6;
/** a7 register state */
unsigned long a7;
/** s2 register state */
unsigned long s2;
/** s3 register state */
unsigned long s3;
/** s4 register state */
unsigned long s4;
/** s5 register state */
unsigned long s5;
/** s6 register state */
unsigned long s6;
/** s7 register state */
unsigned long s7;
/** s8 register state */
unsigned long s8;
/** s9 register state */
unsigned long s9;
/** s10 register state */
unsigned long s10;
/** s11 register state */
unsigned long s11;
/** t3 register state */
unsigned long t3;
/** t4 register state */
unsigned long t4;
/** t5 register state */
unsigned long t5;
/** t6 register state */
unsigned long t6;
union {
unsigned long gprs[32];
struct {
/** zero register state */
unsigned long zero;
/** ra register state */
unsigned long ra;
/** sp register state */
unsigned long sp;
/** gp register state */
unsigned long gp;
/** tp register state */
unsigned long tp;
/** t0 register state */
unsigned long t0;
/** t1 register state */
unsigned long t1;
/** t2 register state */
unsigned long t2;
/** s0 register state */
unsigned long s0;
/** s1 register state */
unsigned long s1;
/** a0 register state */
unsigned long a0;
/** a1 register state */
unsigned long a1;
/** a2 register state */
unsigned long a2;
/** a3 register state */
unsigned long a3;
/** a4 register state */
unsigned long a4;
/** a5 register state */
unsigned long a5;
/** a6 register state */
unsigned long a6;
/** a7 register state */
unsigned long a7;
/** s2 register state */
unsigned long s2;
/** s3 register state */
unsigned long s3;
/** s4 register state */
unsigned long s4;
/** s5 register state */
unsigned long s5;
/** s6 register state */
unsigned long s6;
/** s7 register state */
unsigned long s7;
/** s8 register state */
unsigned long s8;
/** s9 register state */
unsigned long s9;
/** s10 register state */
unsigned long s10;
/** s11 register state */
unsigned long s11;
/** t3 register state */
unsigned long t3;
/** t4 register state */
unsigned long t4;
/** t5 register state */
unsigned long t5;
/** t6 register state */
unsigned long t6;
};
};
/** mepc register state */
unsigned long mepc;
/** mstatus register state */
@ -199,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 */

View File

@ -7,10 +7,12 @@
#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

@ -336,6 +336,19 @@ static void dbtr_trigger_setup(struct sbi_dbtr_trigger *trig,
if (__test_bit(RV_DBTR_BIT(MC6, VS), &tdata1))
__set_bit(RV_DBTR_BIT(TS, VS), &trig->state);
break;
case RISCV_DBTR_TRIG_ICOUNT:
if (__test_bit(RV_DBTR_BIT(ICOUNT, U), &tdata1))
__set_bit(RV_DBTR_BIT(TS, U), &trig->state);
if (__test_bit(RV_DBTR_BIT(ICOUNT, S), &tdata1))
__set_bit(RV_DBTR_BIT(TS, S), &trig->state);
if (__test_bit(RV_DBTR_BIT(ICOUNT, VU), &tdata1))
__set_bit(RV_DBTR_BIT(TS, VU), &trig->state);
if (__test_bit(RV_DBTR_BIT(ICOUNT, VS), &tdata1))
__set_bit(RV_DBTR_BIT(TS, VS), &trig->state);
break;
default:
sbi_dprintf("%s: Unknown type (tdata1: 0x%lx Type: %ld)\n",
__func__, tdata1, TDATA1_GET_TYPE(tdata1));
@ -379,6 +392,16 @@ static void dbtr_trigger_enable(struct sbi_dbtr_trigger *trig)
update_bit(state & RV_DBTR_BIT_MASK(TS, S),
RV_DBTR_BIT(MC6, S), &trig->tdata1);
break;
case RISCV_DBTR_TRIG_ICOUNT:
update_bit(state & RV_DBTR_BIT_MASK(TS, VU),
RV_DBTR_BIT(ICOUNT, VU), &trig->tdata1);
update_bit(state & RV_DBTR_BIT_MASK(TS, VS),
RV_DBTR_BIT(ICOUNT, VS), &trig->tdata1);
update_bit(state & RV_DBTR_BIT_MASK(TS, U),
RV_DBTR_BIT(ICOUNT, U), &trig->tdata1);
update_bit(state & RV_DBTR_BIT_MASK(TS, S),
RV_DBTR_BIT(ICOUNT, S), &trig->tdata1);
break;
default:
break;
}
@ -418,6 +441,12 @@ static void dbtr_trigger_disable(struct sbi_dbtr_trigger *trig)
__clear_bit(RV_DBTR_BIT(MC6, U), &trig->tdata1);
__clear_bit(RV_DBTR_BIT(MC6, S), &trig->tdata1);
break;
case RISCV_DBTR_TRIG_ICOUNT:
__clear_bit(RV_DBTR_BIT(ICOUNT, VU), &trig->tdata1);
__clear_bit(RV_DBTR_BIT(ICOUNT, VS), &trig->tdata1);
__clear_bit(RV_DBTR_BIT(ICOUNT, U), &trig->tdata1);
__clear_bit(RV_DBTR_BIT(ICOUNT, S), &trig->tdata1);
break;
default:
break;
}
@ -441,6 +470,7 @@ static int dbtr_trigger_supported(unsigned long type)
switch (type) {
case RISCV_DBTR_TRIG_MCONTROL:
case RISCV_DBTR_TRIG_MCONTROL6:
case RISCV_DBTR_TRIG_ICOUNT:
return 1;
default:
break;
@ -462,6 +492,11 @@ static int dbtr_trigger_valid(unsigned long type, unsigned long tdata)
!(tdata & RV_DBTR_BIT_MASK(MC6, M)))
return 1;
break;
case RISCV_DBTR_TRIG_ICOUNT:
if (!(tdata & RV_DBTR_BIT_MASK(ICOUNT, DMODE)) &&
!(tdata & RV_DBTR_BIT_MASK(ICOUNT, M)))
return 1;
break;
default:
break;
}
@ -528,6 +563,10 @@ int sbi_dbtr_read_trig(unsigned long smode,
for_each_trig_entry(shmem_base, trig_count, typeof(*entry), entry) {
xmit = &entry->data;
trig = INDEX_TO_TRIGGER((_idx + trig_idx_base));
csr_write(CSR_TSELECT, trig->index);
trig->tdata1 = csr_read(CSR_TDATA1);
trig->tdata2 = csr_read(CSR_TDATA2);
trig->tdata3 = csr_read(CSR_TDATA3);
xmit->tstate = cpu_to_lle(trig->state);
xmit->tdata1 = cpu_to_lle(trig->tdata1);
xmit->tdata2 = cpu_to_lle(trig->tdata2);

View File

@ -49,10 +49,10 @@ static void mstatus_init(struct sbi_scratch *scratch)
csr_write(CSR_MSTATUS, mstatus_val);
/* Disable user mode usage of all perf counters except default ones (CY, TM, IR) */
/* Disable user mode usage of all perf counters except TM */
if (misa_extension('S') &&
sbi_hart_priv_version(scratch) >= SBI_HART_PRIV_VER_1_10)
csr_write(CSR_SCOUNTEREN, 7);
csr_write(CSR_SCOUNTEREN, 0x02);
/**
* OpenSBI doesn't use any PMU counters in M-mode.

View File

@ -16,7 +16,9 @@
/* Minimum size and alignment of heap allocations */
#define HEAP_ALLOC_ALIGN 64
#define HEAP_HOUSEKEEPING_FACTOR 16
/* Number of heap nodes to allocate at once */
#define HEAP_NODE_BATCH_SIZE 8
struct heap_node {
struct sbi_dlist head;
@ -28,20 +30,50 @@ struct sbi_heap_control {
spinlock_t lock;
unsigned long base;
unsigned long size;
unsigned long hkbase;
unsigned long hksize;
unsigned long resv;
struct sbi_dlist free_node_list;
struct sbi_dlist free_space_list;
struct sbi_dlist used_space_list;
struct heap_node init_free_space_node;
};
struct sbi_heap_control global_hpctrl;
static bool alloc_nodes(struct sbi_heap_control *hpctrl)
{
size_t size = HEAP_NODE_BATCH_SIZE * sizeof(struct heap_node);
struct heap_node *n, *new = NULL;
/* alloc_with_align() requires at most two free nodes */
if (hpctrl->free_node_list.next != hpctrl->free_node_list.prev)
return true;
sbi_list_for_each_entry_reverse(n, &hpctrl->free_space_list, head) {
if (n->size >= size) {
n->size -= size;
if (!n->size) {
sbi_list_del(&n->head);
sbi_list_add_tail(&n->head, &hpctrl->free_node_list);
}
new = (void *)(n->addr + n->size);
break;
}
}
if (!new)
return false;
for (size_t i = 0; i < HEAP_NODE_BATCH_SIZE; i++)
sbi_list_add_tail(&new[i].head, &hpctrl->free_node_list);
hpctrl->resv += size;
return true;
}
static void *alloc_with_align(struct sbi_heap_control *hpctrl,
size_t align, size_t size)
{
void *ret = NULL;
struct heap_node *n, *np, *rem;
struct heap_node *n, *np;
unsigned long lowest_aligned;
size_t pad;
@ -53,6 +85,10 @@ static void *alloc_with_align(struct sbi_heap_control *hpctrl,
spin_lock(&hpctrl->lock);
/* Ensure at least two free nodes are available for use below */
if (!alloc_nodes(hpctrl))
goto out;
np = NULL;
sbi_list_for_each_entry(n, &hpctrl->free_space_list, head) {
lowest_aligned = ROUNDUP(n->addr, align);
@ -67,55 +103,34 @@ static void *alloc_with_align(struct sbi_heap_control *hpctrl,
goto out;
if (pad) {
if (sbi_list_empty(&hpctrl->free_node_list)) {
goto out;
}
n = sbi_list_first_entry(&hpctrl->free_node_list,
struct heap_node, head);
sbi_list_del(&n->head);
if ((size + pad < np->size) &&
!sbi_list_empty(&hpctrl->free_node_list)) {
rem = sbi_list_first_entry(&hpctrl->free_node_list,
struct heap_node, head);
sbi_list_del(&rem->head);
rem->addr = np->addr + (size + pad);
rem->size = np->size - (size + pad);
sbi_list_add_tail(&rem->head,
&hpctrl->free_space_list);
} else if (size + pad != np->size) {
/* Can't allocate, return n */
sbi_list_add(&n->head, &hpctrl->free_node_list);
ret = NULL;
goto out;
}
n->addr = np->addr;
n->size = pad;
sbi_list_add_tail(&n->head, &np->head);
n->addr = lowest_aligned;
n->size = size;
sbi_list_add_tail(&n->head, &hpctrl->used_space_list);
np->size = pad;
ret = (void *)n->addr;
} else {
if ((size < np->size) &&
!sbi_list_empty(&hpctrl->free_node_list)) {
n = sbi_list_first_entry(&hpctrl->free_node_list,
struct heap_node, head);
sbi_list_del(&n->head);
n->addr = np->addr;
n->size = size;
np->addr += size;
np->size -= size;
sbi_list_add_tail(&n->head, &hpctrl->used_space_list);
ret = (void *)n->addr;
} else if (size == np->size) {
sbi_list_del(&np->head);
sbi_list_add_tail(&np->head, &hpctrl->used_space_list);
ret = (void *)np->addr;
}
np->addr += pad;
np->size -= pad;
}
if (size < np->size) {
n = sbi_list_first_entry(&hpctrl->free_node_list,
struct heap_node, head);
sbi_list_del(&n->head);
n->addr = np->addr + size;
n->size = np->size - size;
sbi_list_add(&n->head, &np->head);
np->size = size;
}
sbi_list_del(&np->head);
sbi_list_add_tail(&np->head, &hpctrl->used_space_list);
ret = (void *)np->addr;
out:
spin_unlock(&hpctrl->lock);
@ -216,44 +231,32 @@ unsigned long sbi_heap_free_space_from(struct sbi_heap_control *hpctrl)
unsigned long sbi_heap_used_space_from(struct sbi_heap_control *hpctrl)
{
return hpctrl->size - hpctrl->hksize - sbi_heap_free_space();
return hpctrl->size - hpctrl->resv - sbi_heap_free_space();
}
unsigned long sbi_heap_reserved_space_from(struct sbi_heap_control *hpctrl)
{
return hpctrl->hksize;
return hpctrl->resv;
}
int sbi_heap_init_new(struct sbi_heap_control *hpctrl, unsigned long base,
unsigned long size)
{
unsigned long i;
struct heap_node *n;
/* Initialize heap control */
SPIN_LOCK_INIT(hpctrl->lock);
hpctrl->base = base;
hpctrl->size = size;
hpctrl->hkbase = hpctrl->base;
hpctrl->hksize = hpctrl->size / HEAP_HOUSEKEEPING_FACTOR;
hpctrl->hksize &= ~((unsigned long)HEAP_BASE_ALIGN - 1);
hpctrl->resv = 0;
SBI_INIT_LIST_HEAD(&hpctrl->free_node_list);
SBI_INIT_LIST_HEAD(&hpctrl->free_space_list);
SBI_INIT_LIST_HEAD(&hpctrl->used_space_list);
/* Prepare free node list */
for (i = 0; i < (hpctrl->hksize / sizeof(*n)); i++) {
n = (struct heap_node *)(hpctrl->hkbase + (sizeof(*n) * i));
n->addr = n->size = 0;
sbi_list_add_tail(&n->head, &hpctrl->free_node_list);
}
/* Prepare free space list */
n = sbi_list_first_entry(&hpctrl->free_node_list,
struct heap_node, head);
sbi_list_del(&n->head);
n->addr = hpctrl->hkbase + hpctrl->hksize;
n->size = hpctrl->size - hpctrl->hksize;
n = &hpctrl->init_free_space_node;
n->addr = base;
n->size = size;
sbi_list_add_tail(&n->head, &hpctrl->free_space_list);
return 0;

View File

@ -30,7 +30,7 @@ int sbi_illegal_atomic(ulong insn, struct sbi_trap_regs *regs)
{ \
register ulong tinfo asm("a3"); \
register ulong mstatus = 0; \
register ulong mtvec = sbi_hart_expected_trap_addr(); \
register ulong mtvec = (ulong)sbi_hart_expected_trap; \
type ret = 0; \
trap->cause = 0; \
asm volatile( \
@ -57,7 +57,7 @@ int sbi_illegal_atomic(ulong insn, struct sbi_trap_regs *regs)
{ \
register ulong tinfo asm("a3"); \
register ulong mstatus = 0; \
register ulong mtvec = sbi_hart_expected_trap_addr(); \
register ulong mtvec = (ulong)sbi_hart_expected_trap; \
type ret = 0; \
trap->cause = 0; \
asm volatile( \

View File

@ -780,6 +780,7 @@ static int pmu_ctr_find_hw(struct sbi_pmu_hart_state *phs,
continue;
/* We found a valid counter that is not started yet */
ctr_idx = cbase;
break;
}
}

View File

@ -24,7 +24,7 @@
{ \
register ulong tinfo asm("a3"); \
register ulong mstatus = 0; \
register ulong mtvec = sbi_hart_expected_trap_addr(); \
register ulong mtvec = (ulong)sbi_hart_expected_trap; \
type ret = 0; \
trap->cause = 0; \
asm volatile( \
@ -51,7 +51,7 @@
{ \
register ulong tinfo asm("a3") = (ulong)trap; \
register ulong mstatus = 0; \
register ulong mtvec = sbi_hart_expected_trap_addr(); \
register ulong mtvec = (ulong)sbi_hart_expected_trap; \
trap->cause = 0; \
asm volatile( \
"add %[tinfo], %[taddr], zero\n" \
@ -121,7 +121,7 @@ ulong sbi_get_insn(ulong mepc, struct sbi_trap_info *trap)
register ulong tinfo asm("a3");
register ulong ttmp asm("a4");
register ulong mstatus = 0;
register ulong mtvec = sbi_hart_expected_trap_addr();
register ulong mtvec = (ulong)sbi_hart_expected_trap;
ulong insn = 0;
trap->cause = 0;

View File

@ -84,23 +84,27 @@ static int fdt_translate_address(const void *fdt, uint64_t reg, int parent,
uint64_t *addr)
{
int i, rlen;
int cell_addr, cell_size;
int cell_parent_addr, cell_child_addr, cell_size;
const fdt32_t *ranges;
uint64_t offset, caddr = 0, paddr = 0, rsize = 0;
cell_addr = fdt_address_cells(fdt, parent);
if (cell_addr < 1)
return SBI_ENODEV;
cell_size = fdt_size_cells(fdt, parent);
if (cell_size < 0)
return SBI_ENODEV;
ranges = fdt_getprop(fdt, parent, "ranges", &rlen);
if (ranges && rlen > 0) {
for (i = 0; i < cell_addr; i++)
cell_child_addr = fdt_address_cells(fdt, parent);
if (cell_child_addr < 1)
return SBI_ENODEV;
cell_parent_addr = fdt_address_cells(fdt, fdt_parent_offset(fdt, parent));
if (cell_parent_addr < 1)
return SBI_ENODEV;
cell_size = fdt_size_cells(fdt, parent);
if (cell_size < 0)
return SBI_ENODEV;
for (i = 0; i < cell_child_addr; i++)
caddr = (caddr << 32) | fdt32_to_cpu(*ranges++);
for (i = 0; i < cell_addr; i++)
for (i = 0; i < cell_parent_addr; i++)
paddr = (paddr << 32) | fdt32_to_cpu(*ranges++);
for (i = 0; i < cell_size; i++)
rsize = (rsize << 32) | fdt32_to_cpu(*ranges++);

View File

@ -133,10 +133,9 @@ int uart8250_init(unsigned long base, u32 in_freq, u32 baudrate, u32 reg_shift,
set_reg(UART_FCR_OFFSET, 0x01);
/* No modem control DTR RTS */
set_reg(UART_MCR_OFFSET, 0x00);
/* Clear line status */
get_reg(UART_LSR_OFFSET);
/* Read receive buffer */
get_reg(UART_RBR_OFFSET);
/* Clear line status and read receive buffer */
if (get_reg(UART_LSR_OFFSET) & UART_LSR_DR)
get_reg(UART_RBR_OFFSET);
/* Set scratchpad */
set_reg(UART_SCR_OFFSET, 0x00);

View File

@ -1,10 +0,0 @@
# SPDX-License-Identifier: BSD-2-Clause
config PLATFORM_OPENPITON_FPGA
bool
select FDT
select IPI_MSWI
select IRQCHIP_PLIC
select SERIAL_UART8250
select TIMER_MTIMER
default y

View File

@ -1,41 +0,0 @@
#
# SPDX-License-Identifier: BSD-2-Clause
#
# Copyright (c) 2020 Western Digital Corporation or its affiliates.
#
# Compiler flags
platform-cppflags-y =
platform-cflags-y =
platform-asflags-y =
platform-ldflags-y =
# Objects to build
platform-objs-y += platform.o
PLATFORM_RISCV_XLEN = 64
# Blobs to build
FW_JUMP=n
ifeq ($(PLATFORM_RISCV_XLEN), 32)
# This needs to be 4MB aligned for 32-bit support
FW_JUMP_ADDR=0x80400000
else
# This needs to be 2MB aligned for 64-bit support
FW_JUMP_ADDR=0x80200000
endif
FW_JUMP_FDT_ADDR=0x82200000
# Firmware with payload configuration.
FW_PAYLOAD=y
ifeq ($(PLATFORM_RISCV_XLEN), 32)
# This needs to be 4MB aligned for 32-bit support
FW_PAYLOAD_OFFSET=0x400000
else
# This needs to be 2MB aligned for 64-bit support
FW_PAYLOAD_OFFSET=0x200000
endif
FW_PAYLOAD_FDT_ADDR=0x82200000
FW_PAYLOAD_ALIGN=0x1000

View File

@ -36,6 +36,10 @@ config PLATFORM_ANDES_AE350
select ANDES_PMA
default n
config PLATFORM_OPENHWGROUP_OPENPITON
bool "OpenHWGroup Openpiton support"
default n
config PLATFORM_RENESAS_RZFIVE
bool "Renesas RZ/Five support"
select ANDES_PMA

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (C) 2023 Renesas Electronics Corp.
* Copyright (c) 2024 Andes Technology Corporation

View File

@ -7,6 +7,7 @@ CONFIG_PLATFORM_SOPHGO_SG2042=y
CONFIG_PLATFORM_STARFIVE_JH7110=y
CONFIG_PLATFORM_THEAD=y
CONFIG_PLATFORM_MIPS_P8700=y
CONFIG_PLATFORM_OPENHWGROUP_OPENPITON=y
CONFIG_FDT_CPPC=y
CONFIG_FDT_CPPC_RPMI=y
CONFIG_FDT_GPIO=y

View File

@ -1,4 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (C) 2024 Andes Technology Corporation
*/

View File

@ -1,4 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (C) 2023 Renesas Electronics Corp.
*/

View File

@ -0,0 +1,12 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 MIPS
*
*/
.text
.align 12
.globl mips_warm_boot
mips_warm_boot:
j _start_warm
.align 2

View File

@ -4,5 +4,5 @@
ifeq ($(PLATFORM_RISCV_XLEN), 64)
carray-platform_override_modules-$(CONFIG_PLATFORM_MIPS_P8700) += mips_p8700
platform-objs-$(CONFIG_PLATFORM_MIPS_P8700) += mips/p8700.o
platform-objs-$(CONFIG_PLATFORM_MIPS_P8700) += mips/p8700.o mips/mips_warm_boot.o
endif

View File

@ -16,6 +16,8 @@
#include <mips/p8700.h>
#include <mips/mips-cm.h>
extern void mips_warm_boot(void);
static unsigned long mips_csr_read_num(int csr_num)
{
#define switchcase_csr_read(__csr_num, __val) \
@ -150,6 +152,9 @@ static int mips_hart_start(u32 hartid, ulong saddr)
if (hartid == 0)
return SBI_ENOTSUPP;
/* Change reset base to mips_warm_boot */
write_gcr_co_reset_base(hartid, (unsigned long)mips_warm_boot, local_p);
if (cpu_hart(hartid) == 0) {
/* Ensure its coherency is disabled */
write_gcr_co_coherence(hartid, 0, local_p);

View File

@ -0,0 +1,8 @@
#
# SPDX-License-Identifier: BSD-2-Clause
#
# Copyright (c) 2020 Western Digital Corporation or its affiliates.
#
carray-platform_override_modules-$(CONFIG_PLATFORM_OPENHWGROUP_OPENPITON) += openhwgroup_openpiton
platform-objs-$(CONFIG_PLATFORM_OPENHWGROUP_OPENPITON) += openhwgroup/openpiton.o

View File

@ -3,12 +3,7 @@
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
*/
#include <sbi/riscv_asm.h>
#include <sbi/riscv_encoding.h>
#include <sbi/riscv_io.h>
#include <sbi/sbi_const.h>
#include <sbi/sbi_hart.h>
#include <sbi/sbi_platform.h>
#include <platform_override.h>
#include <sbi_utils/fdt/fdt_helper.h>
#include <sbi_utils/fdt/fdt_fixup.h>
#include <sbi_utils/ipi/aclint_mswi.h>
@ -16,19 +11,19 @@
#include <sbi_utils/serial/uart8250.h>
#include <sbi_utils/timer/aclint_mtimer.h>
#define OPENPITON_DEFAULT_UART_ADDR 0xfff0c2c000
#define OPENPITON_DEFAULT_UART_ADDR 0xfff0c2c000ULL
#define OPENPITON_DEFAULT_UART_FREQ 60000000
#define OPENPITON_DEFAULT_UART_BAUDRATE 115200
#define OPENPITON_DEFAULT_UART_REG_SHIFT 0
#define OPENPITON_DEFAULT_UART_REG_WIDTH 1
#define OPENPITON_DEFAULT_UART_REG_OFFSET 0
#define OPENPITON_DEFAULT_UART_CAPS 0
#define OPENPITON_DEFAULT_PLIC_ADDR 0xfff1100000
#define OPENPITON_DEFAULT_PLIC_ADDR 0xfff1100000ULL
#define OPENPITON_DEFAULT_PLIC_SIZE (0x200000 + \
(OPENPITON_DEFAULT_HART_COUNT * 0x1000))
#define OPENPITON_DEFAULT_PLIC_NUM_SOURCES 2
#define OPENPITON_DEFAULT_HART_COUNT 3
#define OPENPITON_DEFAULT_CLINT_ADDR 0xfff1020000
#define OPENPITON_DEFAULT_CLINT_ADDR 0xfff1020000ULL
#define OPENPITON_DEFAULT_ACLINT_MTIMER_FREQ 1000000
#define OPENPITON_DEFAULT_ACLINT_MSWI_ADDR \
(OPENPITON_DEFAULT_CLINT_ADDR + CLINT_MSWI_OFFSET)
@ -36,12 +31,12 @@
(OPENPITON_DEFAULT_CLINT_ADDR + CLINT_MTIMER_OFFSET)
static struct platform_uart_data uart = {
OPENPITON_DEFAULT_UART_ADDR,
(unsigned long)OPENPITON_DEFAULT_UART_ADDR,
OPENPITON_DEFAULT_UART_FREQ,
OPENPITON_DEFAULT_UART_BAUDRATE,
};
static struct plic_data plic = {
.addr = OPENPITON_DEFAULT_PLIC_ADDR,
.addr = (unsigned long)OPENPITON_DEFAULT_PLIC_ADDR,
.size = OPENPITON_DEFAULT_PLIC_SIZE,
.num_src = OPENPITON_DEFAULT_PLIC_NUM_SOURCES,
.flags = PLIC_FLAG_ARIANE_BUG,
@ -53,7 +48,7 @@ static struct plic_data plic = {
};
static struct aclint_mswi_data mswi = {
.addr = OPENPITON_DEFAULT_ACLINT_MSWI_ADDR,
.addr = (unsigned long)OPENPITON_DEFAULT_ACLINT_MSWI_ADDR,
.size = ACLINT_MSWI_SIZE,
.first_hartid = 0,
.hart_count = OPENPITON_DEFAULT_HART_COUNT,
@ -61,10 +56,10 @@ static struct aclint_mswi_data mswi = {
static struct aclint_mtimer_data mtimer = {
.mtime_freq = OPENPITON_DEFAULT_ACLINT_MTIMER_FREQ,
.mtime_addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
.mtime_addr = (unsigned long)OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
ACLINT_DEFAULT_MTIME_OFFSET,
.mtime_size = ACLINT_DEFAULT_MTIME_SIZE,
.mtimecmp_addr = OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
.mtimecmp_addr = (unsigned long)OPENPITON_DEFAULT_ACLINT_MTIMER_ADDR +
ACLINT_DEFAULT_MTIMECMP_OFFSET,
.mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE,
.first_hartid = 0,
@ -79,7 +74,7 @@ static int openpiton_early_init(bool cold_boot)
{
const void *fdt;
struct platform_uart_data uart_data = { 0 };
struct plic_data plic_data;
struct plic_data plic_data = plic;
unsigned long aclint_freq;
uint64_t clint_addr;
int rc;
@ -156,25 +151,23 @@ static int openpiton_timer_init(void)
return aclint_mtimer_cold_init(&mtimer, NULL);
}
/*
* Platform descriptor.
*/
const struct sbi_platform_operations platform_ops = {
.early_init = openpiton_early_init,
.final_init = openpiton_final_init,
.irqchip_init = openpiton_irqchip_init,
.ipi_init = openpiton_ipi_init,
.timer_init = openpiton_timer_init,
static int openhwgroup_openpiton_platform_init(const void *fdt, int nodeoff, const struct fdt_match *match)
{
generic_platform_ops.early_init = openpiton_early_init;
generic_platform_ops.timer_init = openpiton_timer_init;
generic_platform_ops.ipi_init = openpiton_ipi_init;
generic_platform_ops.irqchip_init = openpiton_irqchip_init;
generic_platform_ops.final_init = openpiton_final_init;
return 0;
}
static const struct fdt_match openhwgroup_openpiton_match[] = {
{ .compatible = "openpiton,cva6platform" },
{ },
};
const struct sbi_platform platform = {
.opensbi_version = OPENSBI_VERSION,
.platform_version = SBI_PLATFORM_VERSION(0x0, 0x01),
.name = "OPENPITON RISC-V",
.features = SBI_PLATFORM_DEFAULT_FEATURES,
.hart_count = OPENPITON_DEFAULT_HART_COUNT,
.hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE,
.heap_size =
SBI_PLATFORM_DEFAULT_HEAP_SIZE(OPENPITON_DEFAULT_HART_COUNT),
.platform_ops_addr = (unsigned long)&platform_ops
const struct fdt_driver openhwgroup_openpiton = {
.match_table = openhwgroup_openpiton_match,
.init = openhwgroup_openpiton_platform_init,
};

View File

@ -245,6 +245,8 @@ int generic_final_init(bool cold_boot)
fdt_fixups(fdt);
fdt_domain_fixup(fdt);
fdt_pack(fdt);
return 0;
}

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (C) 2022 Renesas Electronics Corp.
*

View File

@ -102,7 +102,6 @@ build_opensbi() {
BUILD_PLATFORM_SUBDIR+=("nuclei/ux600")
BUILD_PLATFORM_SUBDIR+=("kendryte/k210")
BUILD_PLATFORM_SUBDIR+=("fpga/ariane")
BUILD_PLATFORM_SUBDIR+=("fpga/openpiton")
BUILD_PLATFORM_SUBDIR+=("generic")
;;
*)