10 Commits

Author SHA1 Message Date
dong.yang
f9766a91e7 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.

Signed-off-by: dong.yang <dong.yang@sophgo.com>
2024-09-08 18:56:17 +08:00
pbw
748244a84b fix bug for booting tp without serial 2024-09-07 16:16:53 +08:00
Xiaoguang Xing
b34f366831 lib: Invalid all tlb entries to workaroud c920 bug
Signed-off-by: Xiaoguang Xing <xiaoguang.xing@sophgo.com>
2024-08-30 09:30:46 +08:00
Xiaoguang Xing
14a44c33ba Fix: add heap size to fix cpu 59-63 offline when linux smp bringup
Signed-off-by: Xiaoguang Xing <xiaoguang.xing@sophgo.com>
2024-08-28 17:20:50 +08:00
dong.yang
91259a7058 riscv: sophgo: change Soc names for SG2044.
1. modify the cpu compatible attribyte to "sophgo,sg2044"
2. set the Soc name as SG2044.
2024-08-28 11:13:06 +08:00
Xiaoguang Xing
e48b09dc40 github: workflows: stop repo-lockdown workflow for new pr
Signed-off-by: Xiaoguang Xing <xiaoguang.xing@sophgo.com>
2024-08-28 10:52:13 +08:00
Xiaoguang Xing
7c4563b652 lib: Invalid all tlb entries that belong to an asid to workaroud c920 bug
Signed-off-by: Xiaoguang Xing <xiaoguang.xing@sophgo.com>
2024-08-24 13:01:22 +08:00
Xiaoguang Xing
725bce31fb platform: sophgo: allow any hart as cold boot hart
Signed-off-by: Xiaoguang Xing <xiaoguang.xing@sophgo.com>
2024-08-24 13:01:22 +08:00
Xiaoguang Xing
408283dd89 lib: add mtimer and mswi support for sg2260
Signed-off-by: Xiaoguang Xing <xiaoguang.xing@sophgo.com>
2024-08-24 13:01:22 +08:00
tingzhu.wang
08c8572c8d platform: generic: add sophgo sg2260 soc support
Signed-off-by: tingzhu.wang <tingzhu.wang@sophgo.com>
Signed-off-by: Xiaoguang Xing <xiaoguang.xing@sophgo.com>
2024-08-24 13:01:22 +08:00
219 changed files with 2068 additions and 8024 deletions

View File

@@ -1,21 +0,0 @@
# 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

View File

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

2
.gitignore vendored
View File

@@ -5,7 +5,6 @@
!.clang-format !.clang-format
!.gitignore !.gitignore
!.github !.github
!.editorconfig
# Object files # Object files
*.o *.o
@@ -19,4 +18,3 @@ install/
# Development friendly files # Development friendly files
tags tags
cscope* cscope*
*~

View File

@@ -91,16 +91,7 @@ endif
# Find library version # 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_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_MINOR=`grep "define OPENSBI_VERSION_MINOR" $(include_dir)/sbi/sbi_version.h | sed 's/.*MINOR.*\([0-9][0-9]*\)/\1/'`
OPENSBI_VERSION_GIT= OPENSBI_VERSION_GIT=$(shell if [ -d $(src_dir)/.git ]; then git describe 2> /dev/null; fi)
# 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 # Setup compilation commands
ifneq ($(LLVM),) ifneq ($(LLVM),)
@@ -184,13 +175,10 @@ 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) 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 # 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" -e "-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\|-mno-unaligned-access" >/dev/null && echo n || echo y)
# Check whether the assembler and the compiler support the Zicsr and Zifencei extensions # 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 -e "zicsr" -e "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 "zicsr\|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) ifneq ($(OPENSBI_LD_PIE),y)
$(error Your linker does not support creating PIEs, opensbi requires this.) $(error Your linker does not support creating PIEs, opensbi requires this.)
@@ -297,9 +285,10 @@ ifndef PLATFORM_RISCV_ABI
endif endif
ifndef PLATFORM_RISCV_ISA ifndef PLATFORM_RISCV_ISA
ifneq ($(PLATFORM_RISCV_TOOLCHAIN_DEFAULT), 1) ifneq ($(PLATFORM_RISCV_TOOLCHAIN_DEFAULT), 1)
PLATFORM_RISCV_ISA := rv$(PLATFORM_RISCV_XLEN)imafdc
ifeq ($(CC_SUPPORT_ZICSR_ZIFENCEI), y) ifeq ($(CC_SUPPORT_ZICSR_ZIFENCEI), y)
PLATFORM_RISCV_ISA := $(PLATFORM_RISCV_ISA)_zicsr_zifencei PLATFORM_RISCV_ISA = rv$(PLATFORM_RISCV_XLEN)imafdc_zicsr_zifencei
else
PLATFORM_RISCV_ISA = rv$(PLATFORM_RISCV_XLEN)imafdc
endif endif
else else
PLATFORM_RISCV_ISA = $(OPENSBI_CC_ISA) PLATFORM_RISCV_ISA = $(OPENSBI_CC_ISA)
@@ -357,12 +346,14 @@ GENFLAGS += $(libsbiutils-genflags-y)
GENFLAGS += $(platform-genflags-y) GENFLAGS += $(platform-genflags-y)
GENFLAGS += $(firmware-genflags-y) GENFLAGS += $(firmware-genflags-y)
CFLAGS = -g -Wall -Werror -ffreestanding -nostdlib -fno-stack-protector -fno-strict-aliasing -ffunction-sections -fdata-sections CFLAGS = -g -Wall -Werror -ffreestanding -nostdlib -fno-stack-protector -fno-strict-aliasing
ifneq ($(DEBUG),)
CFLAGS += -O0
else
CFLAGS += -O2
endif
CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
# Optionally supported flags # Optionally supported flags
ifeq ($(CC_SUPPORT_VECTOR),y)
CFLAGS += -DOPENSBI_CC_SUPPORT_VECTOR
endif
ifeq ($(CC_SUPPORT_SAVE_RESTORE),y) ifeq ($(CC_SUPPORT_SAVE_RESTORE),y)
CFLAGS += -mno-save-restore CFLAGS += -mno-save-restore
endif endif
@@ -406,7 +397,6 @@ ASFLAGS += $(firmware-asflags-y)
ARFLAGS = rcs ARFLAGS = rcs
ELFFLAGS += $(USE_LD_FLAG) ELFFLAGS += $(USE_LD_FLAG)
ELFFLAGS += -Wl,--gc-sections
ifeq ($(OPENSBI_LD_EXCLUDE_LIBS),y) ifeq ($(OPENSBI_LD_EXCLUDE_LIBS),y)
ELFFLAGS += -Wl,--exclude-libs,ALL ELFFLAGS += -Wl,--exclude-libs,ALL
endif endif
@@ -425,12 +415,6 @@ MERGEFLAGS += -m elf$(PLATFORM_RISCV_XLEN)lriscv
DTSCPPFLAGS = $(CPPFLAGS) -nostdinc -nostdlib -fno-builtin -D__DTS__ -x assembler-with-cpp DTSCPPFLAGS = $(CPPFLAGS) -nostdinc -nostdlib -fno-builtin -D__DTS__ -x assembler-with-cpp
ifneq ($(DEBUG),)
CFLAGS += -O0
else
CFLAGS += -O2
endif
# Setup functions for compilation # Setup functions for compilation
define dynamic_flags define dynamic_flags
-I$(shell dirname $(2)) -D__OBJNAME__=$(subst -,_,$(shell basename $(1) .o)) -I$(shell dirname $(2)) -D__OBJNAME__=$(subst -,_,$(shell basename $(1) .o))
@@ -506,7 +490,7 @@ compile_d2c = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
compile_carray = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \ compile_carray = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
echo " CARRAY $(subst $(build_dir)/,,$(1))"; \ echo " CARRAY $(subst $(build_dir)/,,$(1))"; \
$(eval CARRAY_VAR_LIST := $(carray-$(subst .carray.c,,$(shell basename $(1)))-y)) \ $(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) $(src_dir)/scripts/carray.sh -i $(2) -l "$(CARRAY_VAR_LIST)" > $(1)
compile_gen_dep = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \ compile_gen_dep = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
echo " GEN-DEP $(subst $(build_dir)/,,$(1))"; \ echo " GEN-DEP $(subst $(build_dir)/,,$(1))"; \
echo "$(1:.dep=$(2)): $(3)" >> $(1) echo "$(1:.dep=$(2)): $(3)" >> $(1)
@@ -535,7 +519,7 @@ $(build_dir)/%.dep: $(src_dir)/%.carray $(KCONFIG_AUTOHEADER)
$(call compile_gen_dep,$@,.c,$< $(KCONFIG_AUTOHEADER)) $(call compile_gen_dep,$@,.c,$< $(KCONFIG_AUTOHEADER))
$(call compile_gen_dep,$@,.o,$(@:.dep=.c)) $(call compile_gen_dep,$@,.o,$(@:.dep=.c))
$(build_dir)/%.carray.c: $(src_dir)/%.carray $(src_dir)/scripts/carray.sh $(build_dir)/%.carray.c: $(src_dir)/%.carray
$(call compile_carray,$@,$<) $(call compile_carray,$@,$<)
$(build_dir)/%.dep: $(src_dir)/%.c $(KCONFIG_AUTOHEADER) $(build_dir)/%.dep: $(src_dir)/%.c $(KCONFIG_AUTOHEADER)
@@ -563,7 +547,7 @@ $(platform_build_dir)/%.dep: $(platform_src_dir)/%.carray $(KCONFIG_AUTOHEADER)
$(call compile_gen_dep,$@,.c,$< $(KCONFIG_AUTOHEADER)) $(call compile_gen_dep,$@,.c,$< $(KCONFIG_AUTOHEADER))
$(call compile_gen_dep,$@,.o,$(@:.dep=.c)) $(call compile_gen_dep,$@,.o,$(@:.dep=.c))
$(platform_build_dir)/%.carray.c: $(platform_src_dir)/%.carray $(src_dir)/scripts/carray.sh $(platform_build_dir)/%.carray.c: $(platform_src_dir)/%.carray
$(call compile_carray,$@,$<) $(call compile_carray,$@,$<)
$(platform_build_dir)/%.dep: $(platform_src_dir)/%.c $(KCONFIG_AUTOHEADER) $(platform_build_dir)/%.dep: $(platform_src_dir)/%.c $(KCONFIG_AUTOHEADER)
@@ -606,7 +590,7 @@ $(platform_build_dir)/%.dep: $(src_dir)/%.carray $(KCONFIG_AUTOHEADER)
$(call compile_gen_dep,$@,.c,$< $(KCONFIG_AUTOHEADER)) $(call compile_gen_dep,$@,.c,$< $(KCONFIG_AUTOHEADER))
$(call compile_gen_dep,$@,.o,$(@:.dep=.c)) $(call compile_gen_dep,$@,.o,$(@:.dep=.c))
$(platform_build_dir)/%.carray.c: $(src_dir)/%.carray $(src_dir)/scripts/carray.sh $(platform_build_dir)/%.carray.c: $(src_dir)/%.carray
$(call compile_carray,$@,$<) $(call compile_carray,$@,$<)
$(platform_build_dir)/%.dep: $(src_dir)/%.c $(KCONFIG_AUTOHEADER) $(platform_build_dir)/%.dep: $(src_dir)/%.c $(KCONFIG_AUTOHEADER)

View File

@@ -1,15 +1,17 @@
OpenSBI Contribution Guideline OpenSBI Contribution Guideline
============================== ==============================
All contributions to OpenSBI must be sent via email patches to the OpenSBI All contributions to OpenSBI can be sent in the following ways:
mailing list at `opensbi@lists.infradead.org` 1. Email patches to the OpenSBI mailing list at `opensbi@lists.infradead.org`
2. GitHub Pull Requests (PRs) to the [OpenSBI main repository]
To join the OpenSBI mailing list, please visit the [OpenSBI infradead page]. To join the OpenSBI mailing list, please visit the [OpenSBI infradead page].
The mailing list based patch approach is preferred over github PRs so that they The OpenSBI maintainers prefer patches via the OpenSBI mailing list
are visible to a wider audience. All accepted patches on the OpenSBI mailing (option 1 above) so that they are visible to a wider audience. All
list will be taken by one of the OpenSBI maintainers and merged into the accepted patches on the OpenSBI mailing list will be taken by any of
[OpenSBI main repository]. the OpenSBI maintainers and merged into the [OpenSBI main repository]
using GitHub PRs.
All contributed work must follow the following rules: All contributed work must follow the following rules:
1. OpenSBI code should be written in accordance to the [Linux coding style]. 1. OpenSBI code should be written in accordance to the [Linux coding style].
@@ -31,6 +33,9 @@ riscv/opensbi repository. Instead, prefer using a fork of the riscv/opensbi main
repository and branches within that fork to create pull requests. repository and branches within that fork to create pull requests.
7. A maintainer cannot merge his own pull requests in the riscv/opensbi main 7. A maintainer cannot merge his own pull requests in the riscv/opensbi main
repository. 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,6 +41,7 @@ has following details:
* **name** - Name of this domain * **name** - Name of this domain
* **assigned_harts** - HARTs assigned to this domain * **assigned_harts** - HARTs assigned to this domain
* **possible_harts** - HARTs possible in 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 * **regions** - Array of memory regions terminated by a memory region
with order zero with order zero
* **boot_hartid** - HART id of the HART booting this domain. The domain * **boot_hartid** - HART id of the HART booting this domain. The domain
@@ -80,6 +81,7 @@ following manner:
platform support platform support
* **possible_harts** - All valid HARTs of a RISC-V platform are possible * **possible_harts** - All valid HARTs of a RISC-V platform are possible
HARTs of the ROOT domain 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: * **regions** - Two memory regions available to the ROOT domain:
**A)** A memory region to protect OpenSBI firmware from S-mode and U-mode **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 **B)** A memory region of **order=__riscv_xlen** allowing S-mode and

View File

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

View File

@@ -56,14 +56,7 @@ qemu-system-riscv64 -M virt -m 256M -nographic \
**Linux Kernel Payload** **Linux Kernel Payload**
Note: We assume that the Linux kernel is compiled using Note: We assume that the Linux kernel is compiled using
*arch/riscv/configs/defconfig*. The kernel must be a flattened image (a file *arch/riscv/configs/defconfig*.
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: Build:
``` ```

View File

@@ -14,8 +14,8 @@
#include <sbi/sbi_scratch.h> #include <sbi/sbi_scratch.h>
#include <sbi/sbi_trap.h> #include <sbi/sbi_trap.h>
#define BOOT_LOTTERY_ACQUIRED 1 #define BOOT_STATUS_LOTTERY_DONE 1
#define BOOT_STATUS_BOOT_HART_DONE 1 #define BOOT_STATUS_BOOT_HART_DONE 2
.macro MOV_3R __d0, __s0, __d1, __s1, __d2, __s2 .macro MOV_3R __d0, __s0, __d1, __s1, __d2, __s2
add \__d0, \__s0, zero add \__d0, \__s0, zero
@@ -31,16 +31,6 @@
add \__d4, \__s4, zero add \__d4, \__s4, zero
.endm .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 .section .entry, "ax", %progbits
.align 3 .align 3
.globl _start .globl _start
@@ -57,8 +47,8 @@ _start:
bne a0, a6, _wait_for_boot_hart bne a0, a6, _wait_for_boot_hart
_try_lottery: _try_lottery:
/* Jump to relocation wait loop if we don't get relocation lottery */ /* Jump to relocation wait loop if we don't get relocation lottery */
lla a6, _boot_lottery lla a6, _relocate_lottery
li a7, BOOT_LOTTERY_ACQUIRED li a7, BOOT_STATUS_LOTTERY_DONE
amoswap.w a6, a7, (a6) amoswap.w a6, a7, (a6)
bnez a6, _wait_for_boot_hart bnez a6, _wait_for_boot_hart
@@ -101,14 +91,6 @@ _bss_zero:
lla s4, _start_hang lla s4, _start_hang
csrw CSR_MTVEC, s4 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 */ /* Setup temporary stack */
lla s4, _fw_end lla s4, _fw_end
li s5, (SBI_SCRATCH_SIZE * 2) li s5, (SBI_SCRATCH_SIZE * 2)
@@ -236,8 +218,6 @@ _scratch_init:
#endif #endif
REG_S a0, SBI_SCRATCH_OPTIONS_OFFSET(tp) REG_S a0, SBI_SCRATCH_OPTIONS_OFFSET(tp)
MOV_3R a0, s0, a1, s1, a2, s2 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 */ /* Move to next scratch space */
add t1, t1, t2 add t1, t1, t2
blt t1, s7, _scratch_init blt t1, s7, _scratch_init
@@ -262,14 +242,30 @@ _scratch_init:
beq t1, a1, _fdt_reloc_done beq t1, a1, _fdt_reloc_done
/* t0 = source FDT start address */ /* t0 = source FDT start address */
add t0, a1, zero add t0, a1, zero
/* t2 = source FDT size (convert from big-endian) */ /* t2 = source FDT size in big-endian */
lbu t2, 7(t0) #if __riscv_xlen > 32
lbu t3, 6(t0) lwu t2, 4(t0)
lbu t4, 5(t0) #else
lbu t5, 4(t0) lw t2, 4(t0)
#endif
/* t3 = bit[15:8] of FDT size */
add t3, t2, zero
srli t3, t3, 16
and t3, t3, a4
slli t3, t3, 8 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 slli t4, t4, 16
/* t5 = bit[31:24] of FDT size */
add t5, t2, zero
and t5, t5, a4
slli t5, t5, 24 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, t3
or t2, t2, t4 or t2, t2, t4
or t2, t2, t5 or t2, t2, t5
@@ -366,9 +362,6 @@ _start_warm:
_skip_trap_handler_hyp: _skip_trap_handler_hyp:
csrw CSR_MTVEC, a4 csrw CSR_MTVEC, a4
/* Clear MDT here again for all harts */
CLEAR_MDT t0
/* Initialize SBI runtime */ /* Initialize SBI runtime */
csrr a0, CSR_MSCRATCH csrr a0, CSR_MSCRATCH
call sbi_init call sbi_init
@@ -378,8 +371,8 @@ _skip_trap_handler_hyp:
.data .data
.align 3 .align 3
_boot_lottery: _relocate_lottery:
RISCV_PTR 0 RISCV_PTR 0
_boot_status: _boot_status:
RISCV_PTR 0 RISCV_PTR 0
@@ -566,9 +559,6 @@ memcmp:
li t0, 0 li t0, 0
.endif .endif
REG_S t0, (SBI_TRAP_REGS_SIZE + SBI_TRAP_INFO_OFFSET(gva))(sp) 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 .endm
.macro TRAP_CALL_C_ROUTINE .macro TRAP_CALL_C_ROUTINE
@@ -611,18 +601,15 @@ memcmp:
.endm .endm
.macro TRAP_RESTORE_MEPC_MSTATUS have_mstatush .macro TRAP_RESTORE_MEPC_MSTATUS have_mstatush
/* /* Restore MEPC and MSTATUS CSRs */
* Restore MSTATUS and MEPC CSRs starting with MSTATUS/H to set MDT REG_L t0, SBI_TRAP_REGS_OFFSET(mepc)(a0)
* flags since we can not take a trap now or MEPC would be cloberred csrw CSR_MEPC, t0
*/ REG_L t0, SBI_TRAP_REGS_OFFSET(mstatus)(a0)
csrw CSR_MSTATUS, t0
.if \have_mstatush .if \have_mstatush
REG_L t0, SBI_TRAP_REGS_OFFSET(mstatusH)(a0) REG_L t0, SBI_TRAP_REGS_OFFSET(mstatusH)(a0)
csrw CSR_MSTATUSH, t0 csrw CSR_MSTATUSH, t0
.endif .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 .endm
.macro TRAP_RESTORE_A0_T0 .macro TRAP_RESTORE_A0_T0

View File

@@ -20,7 +20,6 @@
PROVIDE(_text_start = .); PROVIDE(_text_start = .);
*(.entry) *(.entry)
*(.text) *(.text)
*(.text.*)
. = ALIGN(8); . = ALIGN(8);
PROVIDE(_text_end = .); PROVIDE(_text_end = .);
} }

View File

@@ -101,14 +101,6 @@
__v; \ __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) \ #define csr_write(csr, val) \
({ \ ({ \
unsigned long __v = (unsigned long)(val); \ unsigned long __v = (unsigned long)(val); \
@@ -171,7 +163,7 @@ void csr_write_num(int csr_num, unsigned long val);
} while (0) } while (0)
/* Get current HART id */ /* Get current HART id */
#define current_hartid() ((unsigned int)csr_read_relaxed(CSR_MHARTID)) #define current_hartid() ((unsigned int)csr_read(CSR_MHARTID))
/* determine CPU extension, return non-zero support */ /* determine CPU extension, return non-zero support */
int misa_extension_imp(char ext); int misa_extension_imp(char ext);

View File

@@ -32,7 +32,6 @@
#define MSTATUS_TVM _UL(0x00100000) #define MSTATUS_TVM _UL(0x00100000)
#define MSTATUS_TW _UL(0x00200000) #define MSTATUS_TW _UL(0x00200000)
#define MSTATUS_TSR _UL(0x00400000) #define MSTATUS_TSR _UL(0x00400000)
#define MSTATUS_SPELP _UL(0x00800000)
#define MSTATUS32_SD _UL(0x80000000) #define MSTATUS32_SD _UL(0x80000000)
#if __riscv_xlen == 64 #if __riscv_xlen == 64
#define MSTATUS_UXL _ULL(0x0000000300000000) #define MSTATUS_UXL _ULL(0x0000000300000000)
@@ -42,16 +41,12 @@
#define MSTATUS_GVA _ULL(0x0000004000000000) #define MSTATUS_GVA _ULL(0x0000004000000000)
#define MSTATUS_GVA_SHIFT 38 #define MSTATUS_GVA_SHIFT 38
#define MSTATUS_MPV _ULL(0x0000008000000000) #define MSTATUS_MPV _ULL(0x0000008000000000)
#define MSTATUS_MPELP _ULL(0x0000020000000000)
#define MSTATUS_MDT _ULL(0x0000040000000000)
#else #else
#define MSTATUSH_SBE _UL(0x00000010) #define MSTATUSH_SBE _UL(0x00000010)
#define MSTATUSH_MBE _UL(0x00000020) #define MSTATUSH_MBE _UL(0x00000020)
#define MSTATUSH_GVA _UL(0x00000040) #define MSTATUSH_GVA _UL(0x00000040)
#define MSTATUSH_GVA_SHIFT 6 #define MSTATUSH_GVA_SHIFT 6
#define MSTATUSH_MPV _UL(0x00000080) #define MSTATUSH_MPV _UL(0x00000080)
#define MSTATUSH_MPELP _UL(0x00000200)
#define MSTATUSH_MDT _UL(0x00000400)
#endif #endif
#define MSTATUS32_SD _UL(0x80000000) #define MSTATUS32_SD _UL(0x80000000)
#define MSTATUS64_SD _ULL(0x8000000000000000) #define MSTATUS64_SD _ULL(0x8000000000000000)
@@ -216,15 +211,8 @@
#define ENVCFG_STCE (_ULL(1) << 63) #define ENVCFG_STCE (_ULL(1) << 63)
#define ENVCFG_PBMTE (_ULL(1) << 62) #define ENVCFG_PBMTE (_ULL(1) << 62)
#define ENVCFG_ADUE_SHIFT 61 #define ENVCFG_ADUE (_ULL(1) << 61)
#define ENVCFG_ADUE (_ULL(1) << ENVCFG_ADUE_SHIFT)
#define ENVCFG_CDE (_ULL(1) << 60) #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_CBZE (_UL(1) << 7)
#define ENVCFG_CBCFE (_UL(1) << 6) #define ENVCFG_CBCFE (_UL(1) << 6)
#define ENVCFG_CBIE_SHIFT 4 #define ENVCFG_CBIE_SHIFT 4
@@ -232,10 +220,6 @@
#define ENVCFG_CBIE_ILL _UL(0x0) #define ENVCFG_CBIE_ILL _UL(0x0)
#define ENVCFG_CBIE_FLUSH _UL(0x1) #define ENVCFG_CBIE_FLUSH _UL(0x1)
#define ENVCFG_CBIE_INV _UL(0x3) #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) #define ENVCFG_FIOM _UL(0x1)
/* ===== User-level CSRs ===== */ /* ===== User-level CSRs ===== */
@@ -244,7 +228,6 @@
#define CSR_USTATUS 0x000 #define CSR_USTATUS 0x000
#define CSR_UIE 0x004 #define CSR_UIE 0x004
#define CSR_UTVEC 0x005 #define CSR_UTVEC 0x005
#define CSR_SSP 0x011
/* User Trap Handling (N-extension) */ /* User Trap Handling (N-extension) */
#define CSR_USCRATCH 0x040 #define CSR_USCRATCH 0x040
@@ -763,12 +746,6 @@
#define CSR_MVIPH 0x319 #define CSR_MVIPH 0x319
#define CSR_MIPH 0x354 #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 ===== */ /* ===== Trap/Exception Causes ===== */
#define CAUSE_MISALIGNED_FETCH 0x0 #define CAUSE_MISALIGNED_FETCH 0x0
@@ -786,8 +763,6 @@
#define CAUSE_FETCH_PAGE_FAULT 0xc #define CAUSE_FETCH_PAGE_FAULT 0xc
#define CAUSE_LOAD_PAGE_FAULT 0xd #define CAUSE_LOAD_PAGE_FAULT 0xd
#define CAUSE_STORE_PAGE_FAULT 0xf #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_FETCH_GUEST_PAGE_FAULT 0x14
#define CAUSE_LOAD_GUEST_PAGE_FAULT 0x15 #define CAUSE_LOAD_GUEST_PAGE_FAULT 0x15
#define CAUSE_VIRTUAL_INST_FAULT 0x16 #define CAUSE_VIRTUAL_INST_FAULT 0x16
@@ -897,364 +872,11 @@
#define INSN_MASK_FENCE_TSO 0xffffffff #define INSN_MASK_FENCE_TSO 0xffffffff
#define INSN_MATCH_FENCE_TSO 0x8330000f #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_MASK_VECTOR_LOAD_STORE 0x7f
#define INSN_MATCH_VECTOR_LOAD 0x07
#define INSN_MATCH_VECTOR_STORE 0x27
#define IS_VECTOR_LOAD_STORE(insn) \
((((insn) & INSN_MASK_VECTOR_LOAD_STORE) == INSN_MATCH_VECTOR_LOAD) || \
(((insn) & INSN_MASK_VECTOR_LOAD_STORE) == INSN_MATCH_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 #if __riscv_xlen == 64
/* 64-bit read for VS-stage address translation (RV64) */ /* 64-bit read for VS-stage address translation (RV64) */
#define INSN_PSEUDO_VS_LOAD 0x00003000 #define INSN_PSEUDO_VS_LOAD 0x00003000
/* 64-bit write for VS-stage address translation (RV64) */ /* 64-bit write for VS-stage address translation (RV64) */
#define INSN_PSEUDO_VS_STORE 0x00003020 #define INSN_PSEUDO_VS_STORE 0x00003020
@@ -1270,12 +892,6 @@
#error "Unexpected __riscv_xlen" #error "Unexpected __riscv_xlen"
#endif #endif
#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_16BIT_MASK 0x3
#define INSN_32BIT_MASK 0x1c #define INSN_32BIT_MASK 0x1c
@@ -1294,12 +910,6 @@
#endif #endif
#define REGBYTES (1 << LOG_REGBYTES) #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_RD 7
#define SH_RS1 15 #define SH_RS1 15
#define SH_RS2 20 #define SH_RS2 20
@@ -1353,18 +963,6 @@
#define IMM_S(insn) (((s32)(insn) >> 25 << 5) | \ #define IMM_S(insn) (((s32)(insn) >> 25 << 5) | \
(s32)(((insn) >> 7) & 0x1f)) (s32)(((insn) >> 7) & 0x1f))
#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 MASK_FUNCT3 0x7000 #define MASK_FUNCT3 0x7000
#define MASK_RS1 0xf8000 #define MASK_RS1 0xf8000
#define MASK_CSR 0xfff00000 #define MASK_CSR 0xfff00000

View File

@@ -14,8 +14,6 @@
#define BITS_PER_LONG (8 * __SIZEOF_LONG__) #define BITS_PER_LONG (8 * __SIZEOF_LONG__)
#define BITS_PER_LONG_LONG 64
#define EXTRACT_FIELD(val, which) \ #define EXTRACT_FIELD(val, which) \
(((val) & (which)) / ((which) & ~((which)-1))) (((val) & (which)) / ((which) & ~((which)-1)))
#define INSERT_FIELD(val, which, fieldval) \ #define INSERT_FIELD(val, which, fieldval) \
@@ -30,13 +28,9 @@
#define BIT_WORD_OFFSET(bit) ((bit) & (BITS_PER_LONG - 1)) #define BIT_WORD_OFFSET(bit) ((bit) & (BITS_PER_LONG - 1))
#define BIT_ALIGN(bit, align) (((bit) + ((align) - 1)) & ~((align) - 1)) #define BIT_ALIGN(bit, align) (((bit) + ((align) - 1)) & ~((align) - 1))
#define BIT_ULL(nr) (1ULL << (nr))
#define GENMASK(h, l) \ #define GENMASK(h, l) \
(((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) (((~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. * sbi_ffs - find first (less-significant) set bit in a long word.
* @word: The word to search * @word: The word to search

View File

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

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

@@ -8,8 +8,54 @@
#define __SBI_DOMAIN_CONTEXT_H__ #define __SBI_DOMAIN_CONTEXT_H__
#include <sbi/sbi_types.h> #include <sbi/sbi_types.h>
#include <sbi/sbi_trap.h>
#include <sbi/sbi_domain.h>
struct sbi_domain; /** 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())
/** /**
* Enter a specific domain context synchronously * Enter a specific domain context synchronously
@@ -28,14 +74,4 @@ int sbi_domain_context_enter(struct sbi_domain *dom);
*/ */
int sbi_domain_context_exit(void); 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__ #endif // __SBI_DOMAIN_CONTEXT_H__

View File

@@ -1,93 +0,0 @@
/*
* 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

@@ -30,8 +30,6 @@ struct sbi_ecall_return {
struct sbi_ecall_extension { struct sbi_ecall_extension {
/* head is used by the extension list */ /* head is used by the extension list */
struct sbi_dlist head; struct sbi_dlist head;
/* short name of the extension */
char name[8];
/* /*
* extid_start and extid_end specify the range for this extension. As * extid_start and extid_end specify the range for this extension. As
* the initial range may be wider than the valid runtime range, the * the initial range may be wider than the valid runtime range, the
@@ -40,8 +38,6 @@ struct sbi_ecall_extension {
*/ */
unsigned long extid_start; unsigned long extid_start;
unsigned long extid_end; unsigned long extid_end;
/* flag showing whether given extension is experimental or not */
bool experimental;
/* /*
* register_extensions * register_extensions
* *
@@ -87,8 +83,6 @@ void sbi_ecall_set_impid(unsigned long impid);
struct sbi_ecall_extension *sbi_ecall_find_extension(unsigned long extid); 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); int sbi_ecall_register_extension(struct sbi_ecall_extension *ext);
void sbi_ecall_unregister_extension(struct sbi_ecall_extension *ext); void sbi_ecall_unregister_extension(struct sbi_ecall_extension *ext);

View File

@@ -12,8 +12,6 @@
/* clang-format off */ /* clang-format off */
#include <sbi/sbi_types.h>
/* SBI Extension IDs */ /* SBI Extension IDs */
#define SBI_EXT_0_1_SET_TIMER 0x0 #define SBI_EXT_0_1_SET_TIMER 0x0
#define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1 #define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1
@@ -37,7 +35,6 @@
#define SBI_EXT_DBTR 0x44425452 #define SBI_EXT_DBTR 0x44425452
#define SBI_EXT_SSE 0x535345 #define SBI_EXT_SSE 0x535345
#define SBI_EXT_FWFT 0x46574654 #define SBI_EXT_FWFT 0x46574654
#define SBI_EXT_MPXY 0x4D505859
/* SBI function IDs for BASE extension*/ /* SBI function IDs for BASE extension*/
#define SBI_EXT_BASE_GET_SPEC_VERSION 0x0 #define SBI_EXT_BASE_GET_SPEC_VERSION 0x0
@@ -110,7 +107,6 @@
#define SBI_EXT_PMU_COUNTER_FW_READ 0x5 #define SBI_EXT_PMU_COUNTER_FW_READ 0x5
#define SBI_EXT_PMU_COUNTER_FW_READ_HI 0x6 #define SBI_EXT_PMU_COUNTER_FW_READ_HI 0x6
#define SBI_EXT_PMU_SNAPSHOT_SET_SHMEM 0x7 #define SBI_EXT_PMU_SNAPSHOT_SET_SHMEM 0x7
#define SBI_EXT_PMU_EVENT_GET_INFO 0x8
/* SBI function IDs for DBTR extension */ /* SBI function IDs for DBTR extension */
#define SBI_EXT_DBTR_NUM_TRIGGERS 0x0 #define SBI_EXT_DBTR_NUM_TRIGGERS 0x0
@@ -132,8 +128,7 @@ enum sbi_fwft_feature_t {
SBI_FWFT_SHADOW_STACK = 0x2, SBI_FWFT_SHADOW_STACK = 0x2,
SBI_FWFT_DOUBLE_TRAP = 0x3, SBI_FWFT_DOUBLE_TRAP = 0x3,
SBI_FWFT_PTE_AD_HW_UPDATING = 0x4, SBI_FWFT_PTE_AD_HW_UPDATING = 0x4,
SBI_FWFT_POINTER_MASKING_PMLEN = 0x5, SBI_FWFT_LOCAL_RESERVED_START = 0x5,
SBI_FWFT_LOCAL_RESERVED_START = 0x6,
SBI_FWFT_LOCAL_RESERVED_END = 0x3fffffff, SBI_FWFT_LOCAL_RESERVED_END = 0x3fffffff,
SBI_FWFT_LOCAL_PLATFORM_START = 0x40000000, SBI_FWFT_LOCAL_PLATFORM_START = 0x40000000,
SBI_FWFT_LOCAL_PLATFORM_END = 0x7fffffff, SBI_FWFT_LOCAL_PLATFORM_END = 0x7fffffff,
@@ -249,7 +244,6 @@ enum sbi_pmu_event_type_id {
SBI_PMU_EVENT_TYPE_HW = 0x0, SBI_PMU_EVENT_TYPE_HW = 0x0,
SBI_PMU_EVENT_TYPE_HW_CACHE = 0x1, SBI_PMU_EVENT_TYPE_HW_CACHE = 0x1,
SBI_PMU_EVENT_TYPE_HW_RAW = 0x2, 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_FW = 0xf,
SBI_PMU_EVENT_TYPE_MAX, SBI_PMU_EVENT_TYPE_MAX,
}; };
@@ -260,19 +254,12 @@ enum sbi_pmu_ctr_type {
SBI_PMU_CTR_TYPE_FW, 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 */ /* Helper macros to decode event idx */
#define SBI_PMU_EVENT_IDX_MASK 0xFFFFF #define SBI_PMU_EVENT_IDX_MASK 0xFFFFF
#define SBI_PMU_EVENT_IDX_TYPE_OFFSET 16 #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_TYPE_MASK (0xF << SBI_PMU_EVENT_IDX_TYPE_OFFSET)
#define SBI_PMU_EVENT_IDX_CODE_MASK 0xFFFF #define SBI_PMU_EVENT_IDX_CODE_MASK 0xFFFF
#define SBI_PMU_EVENT_RAW_IDX 0x20000 #define SBI_PMU_EVENT_RAW_IDX 0x20000
#define SBI_PMU_EVENT_RAW_V2_IDX 0x30000
#define SBI_PMU_EVENT_IDX_INVALID 0xFFFFFFFF #define SBI_PMU_EVENT_IDX_INVALID 0xFFFFFFFF
@@ -354,8 +341,6 @@ enum sbi_cppc_reg_id {
#define SBI_EXT_SSE_DISABLE 0x00000005 #define SBI_EXT_SSE_DISABLE 0x00000005
#define SBI_EXT_SSE_COMPLETE 0x00000006 #define SBI_EXT_SSE_COMPLETE 0x00000006
#define SBI_EXT_SSE_INJECT 0x00000007 #define SBI_EXT_SSE_INJECT 0x00000007
#define SBI_EXT_SSE_HART_UNMASK 0x00000008
#define SBI_EXT_SSE_HART_MASK 0x00000009
/* SBI SSE Event Attributes. */ /* SBI SSE Event Attributes. */
enum sbi_sse_attr_id { enum sbi_sse_attr_id {
@@ -394,12 +379,11 @@ enum sbi_sse_state {
/* SBI SSE Event IDs. */ /* SBI SSE Event IDs. */
#define SBI_SSE_EVENT_LOCAL_RAS 0x00000000 #define SBI_SSE_EVENT_LOCAL_RAS 0x00000000
#define SBI_SSE_EVENT_LOCAL_DOUBLE_TRAP 0x00000001
#define SBI_SSE_EVENT_LOCAL_PLAT_0_START 0x00004000 #define SBI_SSE_EVENT_LOCAL_PLAT_0_START 0x00004000
#define SBI_SSE_EVENT_LOCAL_PLAT_0_END 0x00007fff #define SBI_SSE_EVENT_LOCAL_PLAT_0_END 0x00007fff
#define SBI_SSE_EVENT_GLOBAL_RAS 0x00008000 #define SBI_SSE_EVENT_GLOBAL_RAS 0x00008000
#define SBI_SSE_EVENT_GLOBAL_PLAT_0_START 0x0000c000 #define SBI_SSE_EVENT_GLOBAL_PLAT_0_START 0x00004000
#define SBI_SSE_EVENT_GLOBAL_PLAT_0_END 0x0000ffff #define SBI_SSE_EVENT_GLOBAL_PLAT_0_END 0x00007fff
#define SBI_SSE_EVENT_LOCAL_PMU 0x00010000 #define SBI_SSE_EVENT_LOCAL_PMU 0x00010000
#define SBI_SSE_EVENT_LOCAL_PLAT_1_START 0x00014000 #define SBI_SSE_EVENT_LOCAL_PLAT_1_START 0x00014000
@@ -422,15 +406,6 @@ enum sbi_sse_state {
#define SBI_SSE_EVENT_GLOBAL_BIT (1 << 15) #define SBI_SSE_EVENT_GLOBAL_BIT (1 << 15)
#define SBI_SSE_EVENT_PLATFORM_BIT (1 << 14) #define SBI_SSE_EVENT_PLATFORM_BIT (1 << 14)
/* SBI function IDs for MPXY extension */
#define SBI_EXT_MPXY_SET_SHMEM 0x0
#define SBI_EXT_MPXY_GET_CHANNEL_IDS 0x1
#define SBI_EXT_MPXY_READ_ATTRS 0x2
#define SBI_EXT_MPXY_WRITE_ATTRS 0x3
#define SBI_EXT_MPXY_SEND_MSG_WITH_RESP 0x4
#define SBI_EXT_MPXY_SEND_MSG_NO_RESP 0x5
#define SBI_EXT_MPXY_GET_NOTIFICATION_EVENTS 0x6
/* SBI base specification related macros */ /* SBI base specification related macros */
#define SBI_SPEC_VERSION_MAJOR_OFFSET 24 #define SBI_SPEC_VERSION_MAJOR_OFFSET 24
#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f #define SBI_SPEC_VERSION_MAJOR_MASK 0x7f
@@ -453,8 +428,6 @@ enum sbi_sse_state {
#define SBI_ERR_NO_SHMEM -9 #define SBI_ERR_NO_SHMEM -9
#define SBI_ERR_INVALID_STATE -10 #define SBI_ERR_INVALID_STATE -10
#define SBI_ERR_BAD_RANGE -11 #define SBI_ERR_BAD_RANGE -11
#define SBI_ERR_TIMEOUT -12
#define SBI_ERR_IO -13
#define SBI_LAST_ERR SBI_ERR_BAD_RANGE #define SBI_LAST_ERR SBI_ERR_BAD_RANGE

View File

@@ -26,17 +26,16 @@
#define SBI_ENO_SHMEM SBI_ERR_NO_SHMEM #define SBI_ENO_SHMEM SBI_ERR_NO_SHMEM
#define SBI_EINVALID_STATE SBI_ERR_INVALID_STATE #define SBI_EINVALID_STATE SBI_ERR_INVALID_STATE
#define SBI_EBAD_RANGE SBI_ERR_BAD_RANGE #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_ENODEV -1000 #define SBI_ENODEV -1000
#define SBI_ENOSYS -1001 #define SBI_ENOSYS -1001
#define SBI_EILL -1002 #define SBI_ETIMEDOUT -1002
#define SBI_ENOSPC -1003 #define SBI_EIO -1003
#define SBI_ENOMEM -1004 #define SBI_EILL -1004
#define SBI_EUNKNOWN -1005 #define SBI_ENOSPC -1005
#define SBI_ENOENT -1006 #define SBI_ENOMEM -1006
#define SBI_EUNKNOWN -1007
#define SBI_ENOENT -1008
/* clang-format on */ /* clang-format on */

View File

@@ -67,14 +67,6 @@ enum sbi_hart_extensions {
SBI_HART_EXT_SVADE, SBI_HART_EXT_SVADE,
/** Hart has Svadu extension */ /** Hart has Svadu extension */
SBI_HART_EXT_SVADU, 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,
/** Maximum index of Hart extension */ /** Maximum index of Hart extension */
SBI_HART_EXT_MAX, SBI_HART_EXT_MAX,

View File

@@ -127,18 +127,6 @@ static inline void sbi_hartmask_clear_all(struct sbi_hartmask *dstp)
bitmap_zero(sbi_hartmask_bits(dstp), SBI_HARTMASK_MAX_BITS); 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 * *dstp = *src1p & *src2p
* @param dstp the hartmask result * @param dstp the hartmask result

View File

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

View File

@@ -16,9 +16,9 @@ struct sbi_scratch;
void __noreturn sbi_init(struct sbi_scratch *scratch); void __noreturn sbi_init(struct sbi_scratch *scratch);
unsigned long sbi_entry_count(u32 hartindex); unsigned long sbi_entry_count(u32 hartid);
unsigned long sbi_init_count(u32 hartindex); unsigned long sbi_init_count(u32 hartid);
void __noreturn sbi_exit(struct sbi_scratch *scratch); 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 */ /** Send IPI to a target HART index */
void (*ipi_send)(u32 hart_index); void (*ipi_send)(u32 hart_index);
/** Clear IPI for the current hart */ /** Clear IPI for a target HART index */
void (*ipi_clear)(void); void (*ipi_clear)(u32 hart_index);
}; };
enum sbi_ipi_update_type { enum sbi_ipi_update_type {
@@ -87,7 +87,7 @@ void sbi_ipi_process(void);
int sbi_ipi_raw_send(u32 hartindex); int sbi_ipi_raw_send(u32 hartindex);
void sbi_ipi_raw_clear(void); void sbi_ipi_raw_clear(u32 hartindex);
const struct sbi_ipi_device *sbi_ipi_get_device(void); const struct sbi_ipi_device *sbi_ipi_get_device(void);

View File

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

View File

@@ -1,183 +0,0 @@
/*
* 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);
/** Set Message proxy shared memory on the calling HART */
int sbi_mpxy_set_shmem(unsigned long shmem_size,
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

@@ -111,11 +111,15 @@ struct sbi_platform_operations {
/** Get platform specific mhpmevent value */ /** Get platform specific mhpmevent value */
uint64_t (*pmu_xlate_to_mhpmevent)(uint32_t event_idx, uint64_t data); uint64_t (*pmu_xlate_to_mhpmevent)(uint32_t event_idx, uint64_t data);
/** Initialize the platform interrupt controller during cold boot */ /** Initialize the platform interrupt controller for current HART */
int (*irqchip_init)(void); int (*irqchip_init)(bool cold_boot);
/** Exit the platform interrupt controller for current HART */
void (*irqchip_exit)(void);
/** Initialize IPI during cold boot */ /** Initialize IPI for current HART */
int (*ipi_init)(void); int (*ipi_init)(bool cold_boot);
/** Exit IPI for current HART */
void (*ipi_exit)(void);
/** Get tlb flush limit value **/ /** Get tlb flush limit value **/
u64 (*get_tlbr_flush_limit)(void); u64 (*get_tlbr_flush_limit)(void);
@@ -123,11 +127,10 @@ struct sbi_platform_operations {
/** Get tlb fifo num entries*/ /** Get tlb fifo num entries*/
u32 (*get_tlb_num_entries)(void); u32 (*get_tlb_num_entries)(void);
/** Initialize platform timer during cold boot */ /** Initialize platform timer for current HART */
int (*timer_init)(void); int (*timer_init)(bool cold_boot);
/** Exit platform timer for current HART */
/** Initialize the platform Message Proxy(MPXY) driver */ void (*timer_exit)(void);
int (*mpxy_init)(void);
/** Check if SBI vendor extension is implemented or not */ /** Check if SBI vendor extension is implemented or not */
bool (*vendor_ext_check)(void); bool (*vendor_ext_check)(void);
@@ -544,59 +547,84 @@ static inline uint64_t sbi_platform_pmu_xlate_to_mhpmevent(const struct sbi_plat
} }
/** /**
* Initialize the platform interrupt controller during cold boot * Initialize the platform interrupt controller for current HART
* *
* @param plat pointer to struct sbi_platform * @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 * @return 0 on success and negative error code on failure
*/ */
static inline int sbi_platform_irqchip_init(const struct sbi_platform *plat) static inline int sbi_platform_irqchip_init(const struct sbi_platform *plat,
bool cold_boot)
{ {
if (plat && sbi_platform_ops(plat)->irqchip_init) if (plat && sbi_platform_ops(plat)->irqchip_init)
return sbi_platform_ops(plat)->irqchip_init(); return sbi_platform_ops(plat)->irqchip_init(cold_boot);
return 0; return 0;
} }
/** /**
* Initialize the platform IPI support during cold boot * Exit the platform interrupt controller for current HART
* *
* @param plat pointer to struct sbi_platform * @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 * @return 0 on success and negative error code on failure
*/ */
static inline int sbi_platform_ipi_init(const struct sbi_platform *plat) static inline int sbi_platform_ipi_init(const struct sbi_platform *plat,
bool cold_boot)
{ {
if (plat && sbi_platform_ops(plat)->ipi_init) if (plat && sbi_platform_ops(plat)->ipi_init)
return sbi_platform_ops(plat)->ipi_init(); return sbi_platform_ops(plat)->ipi_init(cold_boot);
return 0; return 0;
} }
/** /**
* Initialize the platform timer during cold boot * Exit the platform IPI support for current HART
* *
* @param plat pointer to struct sbi_platform * @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 * @return 0 on success and negative error code on failure
*/ */
static inline int sbi_platform_timer_init(const struct sbi_platform *plat) static inline int sbi_platform_timer_init(const struct sbi_platform *plat,
bool cold_boot)
{ {
if (plat && sbi_platform_ops(plat)->timer_init) if (plat && sbi_platform_ops(plat)->timer_init)
return sbi_platform_ops(plat)->timer_init(); return sbi_platform_ops(plat)->timer_init(cold_boot);
return 0; return 0;
} }
/** /**
* Initialize the platform Message Proxy drivers * Exit the platform timer for current HART
* *
* @param plat pointer to struct sbi_platform * @param plat pointer to struct sbi_platform
*
* @return 0 on success and negative error code on failure
*/ */
static inline int sbi_platform_mpxy_init(const struct sbi_platform *plat) static inline void sbi_platform_timer_exit(const struct sbi_platform *plat)
{ {
if (plat && sbi_platform_ops(plat)->mpxy_init) if (plat && sbi_platform_ops(plat)->timer_exit)
return sbi_platform_ops(plat)->mpxy_init(); sbi_platform_ops(plat)->timer_exit();
return 0;
} }
/** /**

View File

@@ -142,8 +142,6 @@ int sbi_pmu_ctr_start(unsigned long cidx_base, unsigned long cidx_mask,
unsigned long flags, uint64_t ival); unsigned long flags, uint64_t ival);
int sbi_pmu_ctr_get_info(uint32_t cidx, unsigned long *ctr_info); 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); unsigned long sbi_pmu_num_ctr(void);

View File

@@ -22,7 +22,7 @@
#define SBI_SCRATCH_FW_RW_OFFSET (2 * __SIZEOF_POINTER__) #define SBI_SCRATCH_FW_RW_OFFSET (2 * __SIZEOF_POINTER__)
/** Offset of fw_heap_offset member in sbi_scratch */ /** Offset of fw_heap_offset member in sbi_scratch */
#define SBI_SCRATCH_FW_HEAP_OFFSET (3 * __SIZEOF_POINTER__) #define SBI_SCRATCH_FW_HEAP_OFFSET (3 * __SIZEOF_POINTER__)
/** Offset of fw_heap_size member in sbi_scratch */ /** Offset of fw_heap_size_offset member in sbi_scratch */
#define SBI_SCRATCH_FW_HEAP_SIZE_OFFSET (4 * __SIZEOF_POINTER__) #define SBI_SCRATCH_FW_HEAP_SIZE_OFFSET (4 * __SIZEOF_POINTER__)
/** Offset of next_arg1 member in sbi_scratch */ /** Offset of next_arg1 member in sbi_scratch */
#define SBI_SCRATCH_NEXT_ARG1_OFFSET (5 * __SIZEOF_POINTER__) #define SBI_SCRATCH_NEXT_ARG1_OFFSET (5 * __SIZEOF_POINTER__)
@@ -42,10 +42,8 @@
#define SBI_SCRATCH_TMP0_OFFSET (12 * __SIZEOF_POINTER__) #define SBI_SCRATCH_TMP0_OFFSET (12 * __SIZEOF_POINTER__)
/** Offset of options member in sbi_scratch */ /** Offset of options member in sbi_scratch */
#define SBI_SCRATCH_OPTIONS_OFFSET (13 * __SIZEOF_POINTER__) #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 */ /** Offset of extra space in sbi_scratch */
#define SBI_SCRATCH_EXTRA_SPACE_OFFSET (15 * __SIZEOF_POINTER__) #define SBI_SCRATCH_EXTRA_SPACE_OFFSET (14 * __SIZEOF_POINTER__)
/** Maximum size of sbi_scratch (4KB) */ /** Maximum size of sbi_scratch (4KB) */
#define SBI_SCRATCH_SIZE (0x1000) #define SBI_SCRATCH_SIZE (0x1000)
@@ -85,8 +83,6 @@ struct sbi_scratch {
unsigned long tmp0; unsigned long tmp0;
/** Options for OpenSBI library */ /** Options for OpenSBI library */
unsigned long options; unsigned long options;
/** Index of the hart */
unsigned long hartindex;
}; };
/** /**
@@ -159,7 +155,7 @@ enum sbi_scratch_options {
/** Get pointer to sbi_scratch for current HART */ /** Get pointer to sbi_scratch for current HART */
#define sbi_scratch_thishart_ptr() \ #define sbi_scratch_thishart_ptr() \
((struct sbi_scratch *)csr_read_relaxed(CSR_MSCRATCH)) ((struct sbi_scratch *)csr_read(CSR_MSCRATCH))
/** Get Arg1 of next booting stage for current HART */ /** Get Arg1 of next booting stage for current HART */
#define sbi_scratch_thishart_arg1_ptr() \ #define sbi_scratch_thishart_arg1_ptr() \
@@ -206,10 +202,6 @@ do { \
= (__type)(__ptr); \ = (__type)(__ptr); \
} while (0) } while (0)
/** Get the hart index of the current hart */
#define current_hartindex() \
(sbi_scratch_thishart_ptr()->hartindex)
/** Last HART index having a sbi_scratch pointer */ /** Last HART index having a sbi_scratch pointer */
extern u32 last_hartindex_having_scratch; extern u32 last_hartindex_having_scratch;

View File

@@ -78,8 +78,6 @@ void sbi_sse_exit(struct sbi_scratch *scratch);
int sbi_sse_register(uint32_t event_id, unsigned long handler_entry_pc, int sbi_sse_register(uint32_t event_id, unsigned long handler_entry_pc,
unsigned long handler_entry_arg); unsigned long handler_entry_arg);
int sbi_sse_unregister(uint32_t event_id); 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_enable(uint32_t event_id);
int sbi_sse_disable(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); int sbi_sse_complete(struct sbi_trap_regs *regs, struct sbi_ecall_return *out);

View File

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

View File

@@ -236,20 +236,6 @@ static inline unsigned long sbi_regs_gva(const struct sbi_trap_regs *regs)
#endif #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, int sbi_trap_redirect(struct sbi_trap_regs *regs,
const struct sbi_trap_info *trap); const struct sbi_trap_info *trap);

View File

@@ -28,15 +28,4 @@ int sbi_load_access_handler(struct sbi_trap_context *tcntx);
int sbi_store_access_handler(struct sbi_trap_context *tcntx); int sbi_store_access_handler(struct sbi_trap_context *tcntx);
int sbi_double_trap_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 #endif

View File

@@ -44,12 +44,7 @@ typedef unsigned long long uint64_t;
#error "Unexpected __riscv_xlen" #error "Unexpected __riscv_xlen"
#endif #endif
#if __STDC_VERSION__ < 202000L typedef int bool;
typedef _Bool bool;
#define true 1
#define false 0
#endif
typedef unsigned long ulong; typedef unsigned long ulong;
typedef unsigned long uintptr_t; typedef unsigned long uintptr_t;
typedef unsigned long size_t; typedef unsigned long size_t;
@@ -66,15 +61,15 @@ typedef uint32_t be32_t;
typedef uint64_t le64_t; typedef uint64_t le64_t;
typedef uint64_t be64_t; typedef uint64_t be64_t;
#define true 1
#define false 0
#define NULL ((void *)0) #define NULL ((void *)0)
#define __packed __attribute__((packed)) #define __packed __attribute__((packed))
#define __noreturn __attribute__((noreturn)) #define __noreturn __attribute__((noreturn))
#define __aligned(x) __attribute__((aligned(x))) #define __aligned(x) __attribute__((aligned(x)))
#ifndef __always_inline
#define __always_inline inline __attribute__((always_inline)) #define __always_inline inline __attribute__((always_inline))
#endif
#define likely(x) __builtin_expect((x), 1) #define likely(x) __builtin_expect((x), 1)
#define unlikely(x) __builtin_expect((x), 0) #define unlikely(x) __builtin_expect((x), 0)

View File

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

View File

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

View File

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

View File

@@ -1,60 +0,0 @@
/*
* 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;
};
/**
* 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,8 +9,6 @@
#ifndef __FDT_FIXUP_H__ #ifndef __FDT_FIXUP_H__
#define __FDT_FIXUP_H__ #define __FDT_FIXUP_H__
#include <sbi/sbi_list.h>
struct sbi_cpu_idle_state { struct sbi_cpu_idle_state {
const char *name; const char *name;
uint32_t suspend_param; uint32_t suspend_param;
@@ -32,7 +30,7 @@ struct sbi_cpu_idle_state {
* @param states: array of idle state descriptions, ending with empty element * @param states: array of idle state descriptions, ending with empty element
* @return zero on success and -ve on failure * @return zero on success and -ve on failure
*/ */
int fdt_add_cpu_idle_states(void *fdt, const struct sbi_cpu_idle_state *state); int fdt_add_cpu_idle_states(void *dtb, const struct sbi_cpu_idle_state *state);
/** /**
* Fix up the CPU node in the device tree * Fix up the CPU node in the device tree
@@ -95,19 +93,6 @@ void fdt_plic_fixup(void *fdt);
*/ */
int fdt_reserved_memory_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 * General device tree fix-up
* *

View File

@@ -34,92 +34,87 @@ struct platform_uart_data {
unsigned long reg_offset; unsigned long reg_offset;
}; };
const struct fdt_match *fdt_match_node(const void *fdt, int nodeoff, const struct fdt_match *fdt_match_node(void *fdt, int nodeoff,
const struct fdt_match *match_table); const struct fdt_match *match_table);
int fdt_find_match(const void *fdt, int startoff, int fdt_find_match(void *fdt, int startoff,
const struct fdt_match *match_table, const struct fdt_match *match_table,
const struct fdt_match **out_match); const struct fdt_match **out_match);
int fdt_parse_phandle_with_args(const void *fdt, int nodeoff, int fdt_parse_phandle_with_args(void *fdt, int nodeoff,
const char *prop, const char *cells_prop, const char *prop, const char *cells_prop,
int index, struct fdt_phandle_args *out_args); int index, struct fdt_phandle_args *out_args);
int fdt_get_node_addr_size(const void *fdt, int node, int index, int fdt_get_node_addr_size(void *fdt, int node, int index,
uint64_t *addr, uint64_t *size); uint64_t *addr, uint64_t *size);
int fdt_get_node_addr_size_by_name(const void *fdt, int node, const char *name, int fdt_get_node_addr_size_by_name(void *fdt, int node, const char *name,
uint64_t *addr, uint64_t *size); uint64_t *addr, uint64_t *size);
bool fdt_node_is_enabled(const void *fdt, int nodeoff); bool fdt_node_is_enabled(void *fdt, int nodeoff);
int fdt_parse_hart_id(const void *fdt, int cpu_offset, u32 *hartid); int fdt_parse_hart_id(void *fdt, int cpu_offset, u32 *hartid);
int fdt_parse_max_enabled_hart_id(const void *fdt, u32 *max_hartid); int fdt_parse_max_enabled_hart_id(void *fdt, u32 *max_hartid);
int fdt_parse_timebase_frequency(const void *fdt, unsigned long *freq); int fdt_parse_timebase_frequency(void *fdt, unsigned long *freq);
int fdt_parse_isa_extensions(const void *fdt, unsigned int hard_id, int fdt_parse_isa_extensions(void *fdt, unsigned int hard_id,
unsigned long *extensions); unsigned long *extensions);
int fdt_parse_gaisler_uart_node(const void *fdt, int nodeoffset, int fdt_parse_gaisler_uart_node(void *fdt, int nodeoffset,
struct platform_uart_data *uart); struct platform_uart_data *uart);
int fdt_parse_renesas_scif_node(const void *fdt, int nodeoffset, int fdt_parse_renesas_scif_node(void *fdt, int nodeoffset,
struct platform_uart_data *uart); struct platform_uart_data *uart);
int fdt_parse_shakti_uart_node(const void *fdt, int nodeoffset, int fdt_parse_shakti_uart_node(void *fdt, int nodeoffset,
struct platform_uart_data *uart); struct platform_uart_data *uart);
int fdt_parse_sifive_uart_node(const void *fdt, int nodeoffset, int fdt_parse_sifive_uart_node(void *fdt, int nodeoffset,
struct platform_uart_data *uart); struct platform_uart_data *uart);
int fdt_parse_uart_node(const void *fdt, int nodeoffset, int fdt_parse_uart_node(void *fdt, int nodeoffset,
struct platform_uart_data *uart); struct platform_uart_data *uart);
int fdt_parse_uart8250(const void *fdt, struct platform_uart_data *uart, int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
const char *compatible); const char *compatible);
int fdt_parse_xlnx_uartlite_node(const void *fdt, int nodeoffset, int fdt_parse_xlnx_uartlite_node(void *fdt, int nodeoffset,
struct platform_uart_data *uart); struct platform_uart_data *uart);
struct aplic_data; struct aplic_data;
int fdt_parse_aplic_node(const void *fdt, int nodeoff, struct aplic_data *aplic); int fdt_parse_aplic_node(void *fdt, int nodeoff, struct aplic_data *aplic);
struct imsic_data; struct imsic_data;
bool fdt_check_imsic_mlevel(const void *fdt); bool fdt_check_imsic_mlevel(void *fdt);
int fdt_parse_imsic_node(const void *fdt, int nodeoff, struct imsic_data *imsic); int fdt_parse_imsic_node(void *fdt, int nodeoff, struct imsic_data *imsic);
struct plic_data; struct plic_data;
int fdt_parse_plic_node(const void *fdt, int nodeoffset, struct plic_data *plic); int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic);
int fdt_parse_plic(const void *fdt, struct plic_data *plic, const char *compat); int fdt_parse_plic(void *fdt, struct plic_data *plic, const char *compat);
int fdt_parse_aclint_node(const void *fdt, int nodeoffset, int fdt_parse_aclint_node(void *fdt, int nodeoffset,
bool for_timer, bool allow_regname, bool for_timer, bool allow_regname,
unsigned long *out_addr1, unsigned long *out_size1, unsigned long *out_addr1, unsigned long *out_size1,
unsigned long *out_addr2, unsigned long *out_size2, unsigned long *out_addr2, unsigned long *out_size2,
u32 *out_first_hartid, u32 *out_hart_count); u32 *out_first_hartid, u32 *out_hart_count);
int fdt_parse_plmt_node(const void *fdt, int nodeoffset, unsigned long *plmt_base, int fdt_parse_plmt_node(void *fdt, int nodeoffset, unsigned long *plmt_base,
unsigned long *plmt_size, u32 *hart_count); unsigned long *plmt_size, u32 *hart_count);
int fdt_parse_plicsw_node(const void *fdt, int nodeoffset, unsigned long *plicsw_base, int fdt_parse_plicsw_node(void *fdt, int nodeoffset, unsigned long *plicsw_base,
unsigned long *size, u32 *hart_count); unsigned long *size, u32 *hart_count);
int fdt_parse_compat_addr(const void *fdt, uint64_t *addr, int fdt_parse_compat_addr(void *fdt, uint64_t *addr,
const char *compatible); const char *compatible);
static inline const void *fdt_get_address(void) static inline void *fdt_get_address(void)
{
return (const void *)root.next_arg1;
}
static inline void *fdt_get_address_rw(void)
{ {
return (void *)root.next_arg1; 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 * @return 0 on success and negative error code on failure
*/ */
int fdt_pmu_setup(const void *fdt); int fdt_pmu_setup(void *fdt);
/** /**
* Get the mhpmevent select value read from DT for a given event * Get the mhpmevent select value read from DT for a given event
@@ -70,7 +70,7 @@ extern uint32_t hw_event_count;
#else #else
static inline void fdt_pmu_fixup(void *fdt) { } static inline void fdt_pmu_fixup(void *fdt) { }
static inline int fdt_pmu_setup(const void *fdt) { return 0; } static inline int fdt_pmu_setup(void *fdt) { return 0; }
static inline uint64_t fdt_pmu_get_select_value(uint32_t event_idx) { return 0; } static inline uint64_t fdt_pmu_get_select_value(uint32_t event_idx) { return 0; }
#endif #endif

View File

@@ -10,21 +10,22 @@
#ifndef __FDT_GPIO_H__ #ifndef __FDT_GPIO_H__
#define __FDT_GPIO_H__ #define __FDT_GPIO_H__
#include <sbi_utils/fdt/fdt_driver.h>
#include <sbi_utils/gpio/gpio.h> #include <sbi_utils/gpio/gpio.h>
struct fdt_phandle_args; struct fdt_phandle_args;
/** FDT based GPIO driver */ /** FDT based GPIO driver */
struct fdt_gpio { struct fdt_gpio {
struct fdt_driver driver; const struct fdt_match *match_table;
int (*xlate)(struct gpio_chip *chip, int (*xlate)(struct gpio_chip *chip,
const struct fdt_phandle_args *pargs, const struct fdt_phandle_args *pargs,
struct gpio_pin *out_pin); 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 */ /** Get a GPIO pin using "gpios" DT property of client DT node */
int fdt_gpio_pin_get(const void *fdt, int nodeoff, int index, int fdt_gpio_pin_get(void *fdt, int nodeoff, int index,
struct gpio_pin *out_pin); struct gpio_pin *out_pin);
/** Simple xlate function to convert two GPIO FDT cells into GPIO 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 */ /** Representation of a GPIO chip */
struct gpio_chip { struct gpio_chip {
/** Pointer to GPIO driver owning this GPIO chip */ /** Pointer to GPIO driver owning this GPIO chip */
const void *driver; void *driver;
/** Uniquie ID of the GPIO chip assigned by the driver */ /** Uniquie ID of the GPIO chip assigned by the driver */
unsigned int id; unsigned int id;
/** Number of GPIOs supported by the GPIO chip */ /** Number of GPIOs supported by the GPIO chip */

View File

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

View File

@@ -10,11 +10,17 @@
#ifndef __FDT_I2C_H__ #ifndef __FDT_I2C_H__
#define __FDT_I2C_H__ #define __FDT_I2C_H__
#include <sbi_utils/fdt/fdt_driver.h>
#include <sbi_utils/i2c/i2c.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 */ /** Get I2C adapter identified by nodeoff */
int fdt_i2c_adapter_get(const void *fdt, int nodeoff, int fdt_i2c_adapter_get(void *fdt, int nodeoff,
struct i2c_adapter **out_adapter); struct i2c_adapter **out_adapter);
#endif #endif

View File

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

View File

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

View File

@@ -11,15 +11,24 @@
#define __FDT_IPI_H__ #define __FDT_IPI_H__
#include <sbi/sbi_types.h> #include <sbi/sbi_types.h>
#include <sbi_utils/fdt/fdt_driver.h>
#ifdef CONFIG_FDT_IPI #ifdef CONFIG_FDT_IPI
int fdt_ipi_init(void); 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);
#else #else
static inline int fdt_ipi_init(void) { return 0; } static inline void fdt_ipi_exit(void) { }
static inline int fdt_ipi_init(bool cold_boot) { return 0; }
#endif #endif

View File

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

View File

@@ -16,14 +16,20 @@
struct fdt_irqchip { struct fdt_irqchip {
const struct fdt_match *match_table; const struct fdt_match *match_table;
int (*cold_init)(const void *fdt, int nodeoff, const struct fdt_match *match); int (*cold_init)(void *fdt, int nodeoff, const struct fdt_match *match);
int (*warm_init)(void);
void (*exit)(void);
}; };
int fdt_irqchip_init(void); void fdt_irqchip_exit(void);
int fdt_irqchip_init(bool cold_boot);
#else #else
static inline int fdt_irqchip_init(void) { return 0; } static inline void fdt_irqchip_exit(void) { }
static inline int fdt_irqchip_init(bool cold_boot) { return 0; }
#endif #endif

View File

@@ -0,0 +1,33 @@
/*
* 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,12 +37,14 @@ struct imsic_data {
int imsic_map_hartid_to_data(u32 hartid, struct imsic_data *imsic, int file); int imsic_map_hartid_to_data(u32 hartid, struct imsic_data *imsic, int file);
struct imsic_data *imsic_get_data(u32 hartindex); struct imsic_data *imsic_get_data(u32 hartid);
int imsic_get_target_file(u32 hartindex); int imsic_get_target_file(u32 hartid);
void imsic_local_irqchip_init(void); void imsic_local_irqchip_init(void);
int imsic_warm_irqchip_init(void);
int imsic_data_check(struct imsic_data *imsic); int imsic_data_check(struct imsic_data *imsic);
int imsic_cold_irqchip_init(struct imsic_data *imsic); int imsic_cold_irqchip_init(struct imsic_data *imsic);

View File

@@ -11,41 +11,31 @@
#define __IRQCHIP_PLIC_H__ #define __IRQCHIP_PLIC_H__
#include <sbi/sbi_types.h> #include <sbi/sbi_types.h>
#include <sbi/sbi_irqchip.h>
struct plic_data { struct plic_data {
/* Private members */
struct sbi_irqchip_device irqchip;
/* Public members */
unsigned long addr; unsigned long addr;
unsigned long size; unsigned long size;
unsigned long num_src; unsigned long num_src;
unsigned long flags;
void *pm_data;
s16 context_map[][2];
}; };
/** Work around a bug on Ariane that requires enabling interrupts at boot */ /* So far, priorities on all consumers of these functions fit in 8 bits. */
#define PLIC_FLAG_ARIANE_BUG BIT(0) void plic_priority_save(const struct plic_data *plic, u8 *priority, u32 num);
/** 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)
#define PLIC_M_CONTEXT 0 void plic_priority_restore(const struct plic_data *plic, const u8 *priority,
#define PLIC_S_CONTEXT 1 u32 num);
#define PLIC_DATA_SIZE(__hart_count) (sizeof(struct plic_data) + \ void plic_context_save(const struct plic_data *plic, int context_id,
(__hart_count) * 2 * sizeof(s16)) u32 *enable, u32 *threshold, u32 num);
#define PLIC_IE_WORDS(__p) ((__p)->num_src / 32 + 1) void plic_context_restore(const struct plic_data *plic, int context_id,
const u32 *enable, u32 threshold, u32 num);
struct plic_data *plic_get(void); int plic_context_init(const struct plic_data *plic, int context_id,
bool enable, u32 threshold);
void plic_suspend(void); int plic_warm_irqchip_init(const struct plic_data *plic,
int m_cntx_id, int s_cntx_id);
void plic_resume(void); int plic_cold_irqchip_init(const struct plic_data *plic);
int plic_cold_irqchip_init(struct plic_data *plic);
#endif #endif

View File

@@ -1,35 +0,0 @@
/*
* 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

@@ -1,180 +0,0 @@
/*
* 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

@@ -1,32 +0,0 @@
/*
* 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/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

@@ -1,607 +0,0 @@
/*
* 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 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 SERVICEGROUPS AND SERVICES
*/
/** RPMI ServiceGroups IDs */
enum rpmi_servicegroup_id {
RPMI_SRVGRP_ID_MIN = 0,
RPMI_SRVGRP_BASE = 0x0001,
RPMI_SRVGRP_SYSTEM_RESET = 0x0002,
RPMI_SRVGRP_SYSTEM_SUSPEND = 0x0003,
RPMI_SRVGRP_HSM = 0x0004,
RPMI_SRVGRP_CPPC = 0x0005,
RPMI_SRVGRP_CLOCK = 0x0007,
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,
RPMI_BASE_SRV_SET_MSI = 0x08,
};
#define RPMI_BASE_FLAGS_F0_PRIVILEGE (1U << 2)
#define RPMI_BASE_FLAGS_F0_EV_NOTIFY (1U << 1)
#define RPMI_BASE_FLAGS_F0_MSI_EN (1U)
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 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

@@ -1,26 +0,0 @@
/*
* 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
void fdt_mpxy_init(const void *fdt);
#else
static inline void fdt_mpxy_init(const void *fdt) { }
#endif
#endif

View File

@@ -10,16 +10,22 @@
#ifndef __FDT_REGMAP_H__ #ifndef __FDT_REGMAP_H__
#define __FDT_REGMAP_H__ #define __FDT_REGMAP_H__
#include <sbi_utils/fdt/fdt_driver.h>
#include <sbi_utils/regmap/regmap.h> #include <sbi_utils/regmap/regmap.h>
struct fdt_phandle_args; 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 */ /** Get regmap instance based on phandle */
int fdt_regmap_get_by_phandle(const void *fdt, u32 phandle, int fdt_regmap_get_by_phandle(void *fdt, u32 phandle,
struct regmap **out_rmap); struct regmap **out_rmap);
/** Get regmap instance based on "regmap" property of the specified DT node */ /** 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); int fdt_regmap_get(void *fdt, int nodeoff, struct regmap **out_rmap);
#endif #endif

View File

@@ -11,20 +11,33 @@
#define __FDT_RESET_H__ #define __FDT_RESET_H__
#include <sbi/sbi_types.h> #include <sbi/sbi_types.h>
#include <sbi_utils/fdt/fdt_driver.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 #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 * fdt_reset_init() - initialize reset drivers based on the device-tree
* *
* This function shall be invoked in final init. * This function shall be invoked in final init.
*/ */
void fdt_reset_init(const void *fdt); void fdt_reset_init(void);
#else #else
static inline void fdt_reset_init(const void *fdt) { } 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,15 +11,19 @@
#define __FDT_SERIAL_H__ #define __FDT_SERIAL_H__
#include <sbi/sbi_types.h> #include <sbi/sbi_types.h>
#include <sbi_utils/fdt/fdt_driver.h>
#ifdef CONFIG_FDT_SERIAL #ifdef CONFIG_FDT_SERIAL
int fdt_serial_init(const void *fdt); 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);
#else #else
static inline int fdt_serial_init(const void *fdt) { return 0; } static inline int fdt_serial_init(void) { return 0; }
#endif #endif

View File

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

View File

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

View File

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

View File

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

View File

@@ -11,15 +11,24 @@
#define __FDT_TIMER_H__ #define __FDT_TIMER_H__
#include <sbi/sbi_types.h> #include <sbi/sbi_types.h>
#include <sbi_utils/fdt/fdt_driver.h>
#ifdef CONFIG_FDT_TIMER #ifdef CONFIG_FDT_TIMER
int fdt_timer_init(void); 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);
#else #else
static inline int fdt_timer_init(void) { return 0; } static inline void fdt_timer_exit(void) { }
static inline int fdt_timer_init(bool cold_boot) { return 0; }
#endif #endif

View File

@@ -66,7 +66,4 @@ config SBI_ECALL_SSE
bool "SSE extension" bool "SSE extension"
default y default y
config SBI_ECALL_MPXY
bool "MPXY extension"
default y
endmenu endmenu

View File

@@ -61,16 +61,11 @@ libsbi-objs-$(CONFIG_SBI_ECALL_DBTR) += sbi_ecall_dbtr.o
carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_SSE) += ecall_sse carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_SSE) += ecall_sse
libsbi-objs-$(CONFIG_SBI_ECALL_SSE) += sbi_ecall_sse.o 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_bitmap.o
libsbi-objs-y += sbi_bitops.o libsbi-objs-y += sbi_bitops.o
libsbi-objs-y += sbi_console.o libsbi-objs-y += sbi_console.o
libsbi-objs-y += sbi_domain_context.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_domain.o
libsbi-objs-y += sbi_double_trap.o
libsbi-objs-y += sbi_emulate_csr.o libsbi-objs-y += sbi_emulate_csr.o
libsbi-objs-y += sbi_fifo.o libsbi-objs-y += sbi_fifo.o
libsbi-objs-y += sbi_fwft.o libsbi-objs-y += sbi_fwft.o
@@ -86,7 +81,6 @@ libsbi-objs-y += sbi_irqchip.o
libsbi-objs-y += sbi_platform.o libsbi-objs-y += sbi_platform.o
libsbi-objs-y += sbi_pmu.o libsbi-objs-y += sbi_pmu.o
libsbi-objs-y += sbi_dbtr.o libsbi-objs-y += sbi_dbtr.o
libsbi-objs-y += sbi_mpxy.o
libsbi-objs-y += sbi_scratch.o libsbi-objs-y += sbi_scratch.o
libsbi-objs-y += sbi_sse.o libsbi-objs-y += sbi_sse.o
libsbi-objs-y += sbi_string.o libsbi-objs-y += sbi_string.o
@@ -95,7 +89,6 @@ libsbi-objs-y += sbi_timer.o
libsbi-objs-y += sbi_tlb.o libsbi-objs-y += sbi_tlb.o
libsbi-objs-y += sbi_trap.o libsbi-objs-y += sbi_trap.o
libsbi-objs-y += sbi_trap_ldst.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_unpriv.o
libsbi-objs-y += sbi_expected_trap.o libsbi-objs-y += sbi_expected_trap.o
libsbi-objs-y += sbi_cppc.o libsbi-objs-y += sbi_cppc.o

View File

@@ -167,11 +167,11 @@ int sbi_dbtr_init(struct sbi_scratch *scratch, bool coldboot)
goto _probed; goto _probed;
for (i = 0; i < RV_MAX_TRIGGERS; i++) { for (i = 0; i < RV_MAX_TRIGGERS; i++) {
csr_write_allowed(CSR_TSELECT, &trap, i); csr_write_allowed(CSR_TSELECT, (ulong)&trap, i);
if (trap.cause) if (trap.cause)
break; break;
val = csr_read_allowed(CSR_TSELECT, &trap); val = csr_read_allowed(CSR_TSELECT, (ulong)&trap);
if (trap.cause) if (trap.cause)
break; break;
@@ -182,7 +182,7 @@ int sbi_dbtr_init(struct sbi_scratch *scratch, bool coldboot)
if (val != i) if (val != i)
break; break;
val = csr_read_allowed(CSR_TINFO, &trap); val = csr_read_allowed(CSR_TINFO, (ulong)&trap);
if (trap.cause) { if (trap.cause) {
/* /*
* If reading tinfo caused an exception, the * If reading tinfo caused an exception, the
@@ -190,7 +190,7 @@ int sbi_dbtr_init(struct sbi_scratch *scratch, bool coldboot)
* type. * type.
*/ */
tdata1 = csr_read_allowed(CSR_TDATA1, tdata1 = csr_read_allowed(CSR_TDATA1,
&trap); (ulong)&trap);
if (trap.cause) if (trap.cause)
break; break;
@@ -243,9 +243,10 @@ int sbi_dbtr_setup_shmem(const struct sbi_domain *dom, unsigned long smode,
unsigned long shmem_phys_lo, unsigned long shmem_phys_lo,
unsigned long shmem_phys_hi) unsigned long shmem_phys_hi)
{ {
u32 hartid = current_hartid();
struct sbi_dbtr_hart_triggers_state *hart_state; struct sbi_dbtr_hart_triggers_state *hart_state;
if (dom && !sbi_domain_is_assigned_hart(dom, current_hartindex())) { if (dom && !sbi_domain_is_assigned_hart(dom, hartid)) {
sbi_dprintf("%s: calling hart not assigned to this domain\n", sbi_dprintf("%s: calling hart not assigned to this domain\n",
__func__); __func__);
return SBI_ERR_DENIED; return SBI_ERR_DENIED;

View File

@@ -13,18 +13,20 @@
#include <sbi/sbi_hartmask.h> #include <sbi/sbi_hartmask.h>
#include <sbi/sbi_heap.h> #include <sbi/sbi_heap.h>
#include <sbi/sbi_hsm.h> #include <sbi/sbi_hsm.h>
#include <sbi/sbi_list.h>
#include <sbi/sbi_math.h> #include <sbi/sbi_math.h>
#include <sbi/sbi_platform.h> #include <sbi/sbi_platform.h>
#include <sbi/sbi_scratch.h> #include <sbi/sbi_scratch.h>
#include <sbi/sbi_string.h> #include <sbi/sbi_string.h>
SBI_LIST_HEAD(domain_list); /*
* 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 };
static u32 domain_count = 0; static u32 domain_count = 0;
static bool domain_finalized = false; static bool domain_finalized = false;
#define ROOT_REGION_MAX 32 #define ROOT_REGION_MAX 16
static u32 root_memregs_count = 0; static u32 root_memregs_count = 0;
struct sbi_domain root = { struct sbi_domain root = {
@@ -60,7 +62,7 @@ void sbi_update_hartindex_to_domain(u32 hartindex, struct sbi_domain *dom)
sbi_scratch_write_type(scratch, void *, domain_hart_ptr_offset, dom); sbi_scratch_write_type(scratch, void *, domain_hart_ptr_offset, dom);
} }
bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartindex) bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartid)
{ {
bool ret; bool ret;
struct sbi_domain *tdom = (struct sbi_domain *)dom; struct sbi_domain *tdom = (struct sbi_domain *)dom;
@@ -69,25 +71,26 @@ bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartindex)
return false; return false;
spin_lock(&tdom->assigned_harts_lock); spin_lock(&tdom->assigned_harts_lock);
ret = sbi_hartmask_test_hartindex(hartindex, &tdom->assigned_harts); ret = sbi_hartmask_test_hartid(hartid, &tdom->assigned_harts);
spin_unlock(&tdom->assigned_harts_lock); spin_unlock(&tdom->assigned_harts_lock);
return ret; return ret;
} }
int sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom, ulong sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom,
struct sbi_hartmask *mask) ulong hbase)
{ {
ulong ret = 0; ulong ret = 0;
struct sbi_domain *tdom = (struct sbi_domain *)dom; struct sbi_domain *tdom = (struct sbi_domain *)dom;
if (!dom) { if (!dom)
sbi_hartmask_clear_all(mask);
return 0; return 0;
}
spin_lock(&tdom->assigned_harts_lock); spin_lock(&tdom->assigned_harts_lock);
sbi_hartmask_copy(mask, &tdom->assigned_harts); for (int i = 0; i < 8 * sizeof(ret); i++) {
if (sbi_hartmask_test_hartid(hbase + i, &tdom->assigned_harts))
ret |= 1UL << i;
}
spin_unlock(&tdom->assigned_harts_lock); spin_unlock(&tdom->assigned_harts_lock);
return ret; return ret;
@@ -446,7 +449,7 @@ void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix)
sbi_hartmask_for_each_hartindex(i, dom->possible_harts) { sbi_hartmask_for_each_hartindex(i, dom->possible_harts) {
j = sbi_hartindex_to_hartid(i); j = sbi_hartindex_to_hartid(i);
sbi_printf("%s%d%s", (k++) ? "," : "", sbi_printf("%s%d%s", (k++) ? "," : "",
j, sbi_domain_is_assigned_hart(dom, i) ? "*" : ""); j, sbi_domain_is_assigned_hart(dom, j) ? "*" : "");
} }
sbi_printf("\n"); sbi_printf("\n");
@@ -516,9 +519,10 @@ void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix)
void sbi_domain_dump_all(const char *suffix) void sbi_domain_dump_all(const char *suffix)
{ {
u32 i;
const struct sbi_domain *dom; const struct sbi_domain *dom;
sbi_domain_for_each(dom) { sbi_domain_for_each(i, dom) {
sbi_domain_dump(dom, suffix); sbi_domain_dump(dom, suffix);
sbi_printf("\n"); sbi_printf("\n");
} }
@@ -537,11 +541,21 @@ int sbi_domain_register(struct sbi_domain *dom,
return SBI_EINVAL; return SBI_EINVAL;
/* Check if domain already discovered */ /* Check if domain already discovered */
sbi_domain_for_each(tdom) { sbi_domain_for_each(i, tdom) {
if (tdom == dom) if (tdom == dom)
return SBI_EALREADY; 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 */ /* Sanitize discovered domain */
rc = sanitize_domain(dom); rc = sanitize_domain(dom);
if (rc) { if (rc) {
@@ -551,10 +565,9 @@ int sbi_domain_register(struct sbi_domain *dom,
return rc; return rc;
} }
sbi_list_add_tail(&dom->node, &domain_list);
/* Assign index to domain */ /* Assign index to domain */
dom->index = domain_count++; dom->index = domain_count++;
domidx_to_domain_table[dom->index] = dom;
/* Initialize spinlock for dom->assigned_harts */ /* Initialize spinlock for dom->assigned_harts */
SPIN_LOCK_INIT(dom->assigned_harts_lock); SPIN_LOCK_INIT(dom->assigned_harts_lock);
@@ -586,19 +599,10 @@ 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; return 0;
} }
static int root_add_memregion(const struct sbi_domain_memregion *reg) int sbi_domain_root_add_memregion(const struct sbi_domain_memregion *reg)
{ {
int rc; int rc;
bool reg_merged; bool reg_merged;
@@ -676,7 +680,7 @@ int sbi_domain_root_add_memrange(unsigned long addr, unsigned long size,
(end - pos) : align; (end - pos) : align;
sbi_domain_memregion_init(pos, rsize, region_flags, &reg); sbi_domain_memregion_init(pos, rsize, region_flags, &reg);
rc = root_add_memregion(&reg); rc = sbi_domain_root_add_memregion(&reg);
if (rc) if (rc)
return rc; return rc;
pos += rsize; pos += rsize;
@@ -688,7 +692,7 @@ int sbi_domain_root_add_memrange(unsigned long addr, unsigned long size,
int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid) int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid)
{ {
int rc; int rc;
u32 dhart; u32 i, dhart;
struct sbi_domain *dom; struct sbi_domain *dom;
const struct sbi_platform *plat = sbi_platform_ptr(scratch); const struct sbi_platform *plat = sbi_platform_ptr(scratch);
@@ -701,7 +705,7 @@ int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid)
} }
/* Startup boot HART of domains */ /* Startup boot HART of domains */
sbi_domain_for_each(dom) { sbi_domain_for_each(i, dom) {
/* Domain boot HART index */ /* Domain boot HART index */
dhart = sbi_hartid_to_hartindex(dom->boot_hartid); dhart = sbi_hartid_to_hartindex(dom->boot_hartid);
@@ -761,8 +765,6 @@ int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid)
struct sbi_domain_memregion *root_memregs; struct sbi_domain_memregion *root_memregs;
const struct sbi_platform *plat = sbi_platform_ptr(scratch); const struct sbi_platform *plat = sbi_platform_ptr(scratch);
SBI_INIT_LIST_HEAD(&domain_list);
if (scratch->fw_rw_offset == 0 || if (scratch->fw_rw_offset == 0 ||
(scratch->fw_rw_offset & (scratch->fw_rw_offset - 1)) != 0) { (scratch->fw_rw_offset & (scratch->fw_rw_offset - 1)) != 0) {
sbi_printf("%s: fw_rw_offset is not a power of 2 (0x%lx)\n", sbi_printf("%s: fw_rw_offset is not a power of 2 (0x%lx)\n",
@@ -780,16 +782,11 @@ int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid)
if (!domain_hart_ptr_offset) if (!domain_hart_ptr_offset)
return SBI_ENOMEM; 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); root_memregs = sbi_calloc(sizeof(*root_memregs), ROOT_REGION_MAX + 1);
if (!root_memregs) { if (!root_memregs) {
sbi_printf("%s: no memory for root regions\n", __func__); sbi_printf("%s: no memory for root regions\n", __func__);
rc = SBI_ENOMEM; rc = SBI_ENOMEM;
goto fail_deinit_context; goto fail_free_domain_hart_ptr_offset;
} }
root.regions = root_memregs; root.regions = root_memregs;
@@ -854,8 +851,6 @@ fail_free_root_hmask:
sbi_free(root_hmask); sbi_free(root_hmask);
fail_free_root_memregs: fail_free_root_memregs:
sbi_free(root_memregs); sbi_free(root_memregs);
fail_deinit_context:
sbi_domain_context_deinit();
fail_free_domain_hart_ptr_offset: fail_free_domain_hart_ptr_offset:
sbi_scratch_free_offset(domain_hart_ptr_offset); sbi_scratch_free_offset(domain_hart_ptr_offset);
return rc; return rc;

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

@@ -13,77 +13,7 @@
#include <sbi/sbi_heap.h> #include <sbi/sbi_heap.h>
#include <sbi/sbi_scratch.h> #include <sbi/sbi_scratch.h>
#include <sbi/sbi_string.h> #include <sbi/sbi_string.h>
#include <sbi/sbi_domain.h>
#include <sbi/sbi_domain_context.h> #include <sbi/sbi_domain_context.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;
};
struct domain_context_priv {
/** Contexts for possible HARTs indexed by hartindex */
struct hart_context *hartindex_to_context_table[SBI_HARTMASK_MAX_BITS];
};
static struct sbi_domain_data dcpriv = {
.data_size = sizeof(struct domain_context_priv),
};
static inline struct hart_context *hart_context_get(struct sbi_domain *dom,
u32 hartindex)
{
struct domain_context_priv *dcp = sbi_domain_data_ptr(dom, &dcpriv);
return (dcp && hartindex < SBI_HARTMASK_MAX_BITS) ?
dcp->hartindex_to_context_table[hartindex] : NULL;
}
static void hart_context_set(struct sbi_domain *dom, u32 hartindex,
struct hart_context *hc)
{
struct domain_context_priv *dcp = sbi_domain_data_ptr(dom, &dcpriv);
if (dcp && hartindex < SBI_HARTMASK_MAX_BITS)
dcp->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. * Switches the HART context from the current domain to the target domain.
@@ -93,10 +23,10 @@ static void hart_context_set(struct sbi_domain *dom, u32 hartindex,
* @param ctx pointer to the current HART context * @param ctx pointer to the current HART context
* @param dom_ctx pointer to the target domain context * @param dom_ctx pointer to the target domain context
*/ */
static void switch_to_next_domain_context(struct hart_context *ctx, static void switch_to_next_domain_context(struct sbi_context *ctx,
struct hart_context *dom_ctx) struct sbi_context *dom_ctx)
{ {
u32 hartindex = current_hartindex(); u32 hartindex = sbi_hartid_to_hartindex(current_hartid());
struct sbi_trap_context *trap_ctx; struct sbi_trap_context *trap_ctx;
struct sbi_domain *current_dom = ctx->dom; struct sbi_domain *current_dom = ctx->dom;
struct sbi_domain *target_dom = dom_ctx->dom; struct sbi_domain *target_dom = dom_ctx->dom;
@@ -159,8 +89,9 @@ static void switch_to_next_domain_context(struct hart_context *ctx,
int sbi_domain_context_enter(struct sbi_domain *dom) int sbi_domain_context_enter(struct sbi_domain *dom)
{ {
struct hart_context *ctx = hart_context_thishart_get(); struct sbi_context *ctx = sbi_domain_context_thishart_ptr();
struct hart_context *dom_ctx = hart_context_get(dom, current_hartindex()); struct sbi_context *dom_ctx = sbi_hartindex_to_domain_context(
sbi_hartid_to_hartindex(current_hartid()), dom);
/* Validate the domain context existence */ /* Validate the domain context existence */
if (!dom_ctx) if (!dom_ctx)
@@ -176,10 +107,10 @@ int sbi_domain_context_enter(struct sbi_domain *dom)
int sbi_domain_context_exit(void) int sbi_domain_context_exit(void)
{ {
u32 hartindex = current_hartindex(); u32 i, hartindex = sbi_hartid_to_hartindex(current_hartid());
struct sbi_domain *dom; struct sbi_domain *dom;
struct hart_context *ctx = hart_context_thishart_get(); struct sbi_context *ctx = sbi_domain_context_thishart_ptr();
struct hart_context *dom_ctx, *tmp; struct sbi_context *dom_ctx, *tmp;
/* /*
* If it's first time to call `exit` on the current hart, no * If it's first time to call `exit` on the current hart, no
@@ -187,21 +118,21 @@ int sbi_domain_context_exit(void)
* its context on the current hart if valid. * its context on the current hart if valid.
*/ */
if (!ctx) { if (!ctx) {
sbi_domain_for_each(dom) { sbi_domain_for_each(i, dom) {
if (!sbi_hartmask_test_hartindex(hartindex, if (!sbi_hartmask_test_hartindex(hartindex,
dom->possible_harts)) dom->possible_harts))
continue; continue;
dom_ctx = sbi_zalloc(sizeof(struct hart_context)); dom_ctx = sbi_zalloc(sizeof(struct sbi_context));
if (!dom_ctx) if (!dom_ctx)
return SBI_ENOMEM; return SBI_ENOMEM;
/* Bind context and domain */ /* Bind context and domain */
dom_ctx->dom = dom; dom_ctx->dom = dom;
hart_context_set(dom, hartindex, dom_ctx); dom->hartindex_to_context_table[hartindex] = dom_ctx;
} }
ctx = hart_context_thishart_get(); ctx = sbi_domain_context_thishart_ptr();
} }
dom_ctx = ctx->prev_ctx; dom_ctx = ctx->prev_ctx;
@@ -209,11 +140,11 @@ int sbi_domain_context_exit(void)
/* If no previous caller context */ /* If no previous caller context */
if (!dom_ctx) { if (!dom_ctx) {
/* Try to find next uninitialized user-defined domain's context */ /* Try to find next uninitialized user-defined domain's context */
sbi_domain_for_each(dom) { sbi_domain_for_each(i, dom) {
if (dom == &root || dom == sbi_domain_thishart_ptr()) if (dom == &root || dom == sbi_domain_thishart_ptr())
continue; continue;
tmp = hart_context_get(dom, hartindex); tmp = sbi_hartindex_to_domain_context(hartindex, dom);
if (tmp && !tmp->initialized) { if (tmp && !tmp->initialized) {
dom_ctx = tmp; dom_ctx = tmp;
break; break;
@@ -223,19 +154,9 @@ int sbi_domain_context_exit(void)
/* Take the root domain context if fail to find */ /* Take the root domain context if fail to find */
if (!dom_ctx) if (!dom_ctx)
dom_ctx = hart_context_get(&root, hartindex); dom_ctx = sbi_hartindex_to_domain_context(hartindex, &root);
switch_to_next_domain_context(ctx, dom_ctx); switch_to_next_domain_context(ctx, dom_ctx);
return 0; return 0;
} }
int sbi_domain_context_init(void)
{
return sbi_domain_register_data(&dcpriv);
}
void sbi_domain_context_deinit(void)
{
sbi_domain_unregister_data(&dcpriv);
}

View File

@@ -1,138 +0,0 @@
/*
* 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);
}

View File

@@ -1,30 +0,0 @@
/*
* 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_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);
}

View File

@@ -11,10 +11,10 @@
#include <sbi/sbi_ecall.h> #include <sbi/sbi_ecall.h>
#include <sbi/sbi_ecall_interface.h> #include <sbi/sbi_ecall_interface.h>
#include <sbi/sbi_error.h> #include <sbi/sbi_error.h>
#include <sbi/sbi_string.h>
#include <sbi/sbi_trap.h> #include <sbi/sbi_trap.h>
extern struct sbi_ecall_extension *const sbi_ecall_exts[]; extern struct sbi_ecall_extension *sbi_ecall_exts[];
extern unsigned long sbi_ecall_exts_size;
u16 sbi_ecall_version_major(void) u16 sbi_ecall_version_major(void)
{ {
@@ -54,29 +54,6 @@ struct sbi_ecall_extension *sbi_ecall_find_extension(unsigned long extid)
return ret; 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) int sbi_ecall_register_extension(struct sbi_ecall_extension *ext)
{ {
struct sbi_ecall_extension *t; struct sbi_ecall_extension *t;
@@ -171,7 +148,7 @@ int sbi_ecall_init(void)
struct sbi_ecall_extension *ext; struct sbi_ecall_extension *ext;
unsigned long i; unsigned long i;
for (i = 0; sbi_ecall_exts[i]; i++) { for (i = 0; i < sbi_ecall_exts_size; i++) {
ext = sbi_ecall_exts[i]; ext = sbi_ecall_exts[i];
ret = SBI_ENODEV; ret = SBI_ENODEV;

View File

@@ -79,7 +79,6 @@ static int sbi_ecall_base_register_extensions(void)
} }
struct sbi_ecall_extension ecall_base = { struct sbi_ecall_extension ecall_base = {
.name = "base",
.extid_start = SBI_EXT_BASE, .extid_start = SBI_EXT_BASE,
.extid_end = SBI_EXT_BASE, .extid_end = SBI_EXT_BASE,
.register_extensions = sbi_ecall_base_register_extensions, .register_extensions = sbi_ecall_base_register_extensions,

View File

@@ -32,13 +32,7 @@ static int sbi_ecall_cppc_handler(unsigned long extid, unsigned long funcid,
#endif #endif
break; break;
case SBI_EXT_CPPC_WRITE: case SBI_EXT_CPPC_WRITE:
#if __riscv_xlen == 32 ret = sbi_cppc_write(regs->a0, regs->a1);
temp = regs->a2;
temp = (temp << 32) | regs->a1;
#else
temp = regs->a1;
#endif
ret = sbi_cppc_write(regs->a0, temp);
break; break;
case SBI_EXT_CPPC_PROBE: case SBI_EXT_CPPC_PROBE:
ret = sbi_cppc_probe(regs->a0); ret = sbi_cppc_probe(regs->a0);
@@ -65,7 +59,6 @@ static int sbi_ecall_cppc_register_extensions(void)
} }
struct sbi_ecall_extension ecall_cppc = { struct sbi_ecall_extension ecall_cppc = {
.name = "cppc",
.extid_start = SBI_EXT_CPPC, .extid_start = SBI_EXT_CPPC,
.extid_end = SBI_EXT_CPPC, .extid_end = SBI_EXT_CPPC,
.register_extensions = sbi_ecall_cppc_register_extensions, .register_extensions = sbi_ecall_cppc_register_extensions,

View File

@@ -74,7 +74,6 @@ static int sbi_ecall_dbcn_register_extensions(void)
} }
struct sbi_ecall_extension ecall_dbcn = { struct sbi_ecall_extension ecall_dbcn = {
.name = "dbcn",
.extid_start = SBI_EXT_DBCN, .extid_start = SBI_EXT_DBCN,
.extid_end = SBI_EXT_DBCN, .extid_end = SBI_EXT_DBCN,
.register_extensions = sbi_ecall_dbcn_register_extensions, .register_extensions = sbi_ecall_dbcn_register_extensions,

View File

@@ -66,10 +66,8 @@ static int sbi_ecall_dbtr_register_extensions(void)
} }
struct sbi_ecall_extension ecall_dbtr = { struct sbi_ecall_extension ecall_dbtr = {
.name = "dbtr", .extid_start = SBI_EXT_DBTR,
.extid_start = SBI_EXT_DBTR, .extid_end = SBI_EXT_DBTR,
.extid_end = SBI_EXT_DBTR, .handle = sbi_ecall_dbtr_handler,
.experimental = true, .register_extensions = sbi_ecall_dbtr_register_extensions,
.handle = sbi_ecall_dbtr_handler,
.register_extensions = sbi_ecall_dbtr_register_extensions,
}; };

View File

@@ -42,10 +42,8 @@ static int sbi_ecall_fwft_register_extensions(void)
} }
struct sbi_ecall_extension ecall_fwft = { struct sbi_ecall_extension ecall_fwft = {
.name = "fwft", .extid_start = SBI_EXT_FWFT,
.extid_start = SBI_EXT_FWFT, .extid_end = SBI_EXT_FWFT,
.extid_end = SBI_EXT_FWFT, .register_extensions = sbi_ecall_fwft_register_extensions,
.experimental = true, .handle = sbi_ecall_fwft_handler,
.register_extensions = sbi_ecall_fwft_register_extensions,
.handle = sbi_ecall_fwft_handler,
}; };

View File

@@ -61,7 +61,6 @@ static int sbi_ecall_hsm_register_extensions(void)
} }
struct sbi_ecall_extension ecall_hsm = { struct sbi_ecall_extension ecall_hsm = {
.name = "hsm",
.extid_start = SBI_EXT_HSM, .extid_start = SBI_EXT_HSM,
.extid_end = SBI_EXT_HSM, .extid_end = SBI_EXT_HSM,
.register_extensions = sbi_ecall_hsm_register_extensions, .register_extensions = sbi_ecall_hsm_register_extensions,

View File

@@ -36,7 +36,6 @@ static int sbi_ecall_ipi_register_extensions(void)
} }
struct sbi_ecall_extension ecall_ipi = { struct sbi_ecall_extension ecall_ipi = {
.name = "ipi",
.extid_start = SBI_EXT_IPI, .extid_start = SBI_EXT_IPI,
.extid_end = SBI_EXT_IPI, .extid_end = SBI_EXT_IPI,
.register_extensions = sbi_ecall_ipi_register_extensions, .register_extensions = sbi_ecall_ipi_register_extensions,

View File

@@ -14,6 +14,7 @@
#include <sbi/sbi_ecall.h> #include <sbi/sbi_ecall.h>
#include <sbi/sbi_ecall_interface.h> #include <sbi/sbi_ecall_interface.h>
#include <sbi/sbi_error.h> #include <sbi/sbi_error.h>
#include <sbi/sbi_hsm.h>
#include <sbi/sbi_ipi.h> #include <sbi/sbi_ipi.h>
#include <sbi/sbi_platform.h> #include <sbi/sbi_platform.h>
#include <sbi/sbi_system.h> #include <sbi/sbi_system.h>
@@ -23,7 +24,7 @@
#include <sbi/sbi_unpriv.h> #include <sbi/sbi_unpriv.h>
#include <sbi/sbi_hart.h> #include <sbi/sbi_hart.h>
static bool sbi_load_hart_mask_unpriv(ulong *pmask, ulong *hmask, ulong *hbase, static bool sbi_load_hart_mask_unpriv(ulong *pmask, ulong *hmask,
struct sbi_trap_info *uptrap) struct sbi_trap_info *uptrap)
{ {
ulong mask = 0; ulong mask = 0;
@@ -32,9 +33,9 @@ static bool sbi_load_hart_mask_unpriv(ulong *pmask, ulong *hmask, ulong *hbase,
mask = sbi_load_ulong(pmask, uptrap); mask = sbi_load_ulong(pmask, uptrap);
if (uptrap->cause) if (uptrap->cause)
return false; return false;
*hbase = 0;
} else { } else {
*hbase = -1UL; sbi_hsm_hart_interruptible_mask(sbi_domain_thishart_ptr(),
0, &mask);
} }
*hmask = mask; *hmask = mask;
@@ -49,7 +50,7 @@ static int sbi_ecall_legacy_handler(unsigned long extid, unsigned long funcid,
struct sbi_tlb_info tlb_info; struct sbi_tlb_info tlb_info;
u32 source_hart = current_hartid(); u32 source_hart = current_hartid();
struct sbi_trap_info trap = {0}; struct sbi_trap_info trap = {0};
ulong hmask, hbase; ulong hmask = 0;
switch (extid) { switch (extid) {
case SBI_EXT_0_1_SET_TIMER: case SBI_EXT_0_1_SET_TIMER:
@@ -70,8 +71,8 @@ static int sbi_ecall_legacy_handler(unsigned long extid, unsigned long funcid,
break; break;
case SBI_EXT_0_1_SEND_IPI: case SBI_EXT_0_1_SEND_IPI:
if (sbi_load_hart_mask_unpriv((ulong *)regs->a0, if (sbi_load_hart_mask_unpriv((ulong *)regs->a0,
&hmask, &hbase, &trap)) { &hmask, &trap)) {
ret = sbi_ipi_send_smode(hmask, hbase); ret = sbi_ipi_send_smode(hmask, 0);
} else { } else {
sbi_trap_redirect(regs, &trap); sbi_trap_redirect(regs, &trap);
out->skip_regs_update = true; out->skip_regs_update = true;
@@ -79,10 +80,10 @@ static int sbi_ecall_legacy_handler(unsigned long extid, unsigned long funcid,
break; break;
case SBI_EXT_0_1_REMOTE_FENCE_I: case SBI_EXT_0_1_REMOTE_FENCE_I:
if (sbi_load_hart_mask_unpriv((ulong *)regs->a0, if (sbi_load_hart_mask_unpriv((ulong *)regs->a0,
&hmask, &hbase, &trap)) { &hmask, &trap)) {
SBI_TLB_INFO_INIT(&tlb_info, 0, 0, 0, 0, SBI_TLB_INFO_INIT(&tlb_info, 0, 0, 0, 0,
SBI_TLB_FENCE_I, source_hart); SBI_TLB_FENCE_I, source_hart);
ret = sbi_tlb_request(hmask, hbase, &tlb_info); ret = sbi_tlb_request(hmask, 0, &tlb_info);
} else { } else {
sbi_trap_redirect(regs, &trap); sbi_trap_redirect(regs, &trap);
out->skip_regs_update = true; out->skip_regs_update = true;
@@ -90,10 +91,10 @@ static int sbi_ecall_legacy_handler(unsigned long extid, unsigned long funcid,
break; break;
case SBI_EXT_0_1_REMOTE_SFENCE_VMA: case SBI_EXT_0_1_REMOTE_SFENCE_VMA:
if (sbi_load_hart_mask_unpriv((ulong *)regs->a0, if (sbi_load_hart_mask_unpriv((ulong *)regs->a0,
&hmask, &hbase, &trap)) { &hmask, &trap)) {
SBI_TLB_INFO_INIT(&tlb_info, regs->a1, regs->a2, 0, 0, SBI_TLB_INFO_INIT(&tlb_info, regs->a1, regs->a2, 0, 0,
SBI_TLB_SFENCE_VMA, source_hart); SBI_TLB_SFENCE_VMA, source_hart);
ret = sbi_tlb_request(hmask, hbase, &tlb_info); ret = sbi_tlb_request(hmask, 0, &tlb_info);
} else { } else {
sbi_trap_redirect(regs, &trap); sbi_trap_redirect(regs, &trap);
out->skip_regs_update = true; out->skip_regs_update = true;
@@ -101,12 +102,12 @@ static int sbi_ecall_legacy_handler(unsigned long extid, unsigned long funcid,
break; break;
case SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID: case SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID:
if (sbi_load_hart_mask_unpriv((ulong *)regs->a0, if (sbi_load_hart_mask_unpriv((ulong *)regs->a0,
&hmask, &hbase, &trap)) { &hmask, &trap)) {
SBI_TLB_INFO_INIT(&tlb_info, regs->a1, SBI_TLB_INFO_INIT(&tlb_info, regs->a1,
regs->a2, regs->a3, 0, regs->a2, regs->a3, 0,
SBI_TLB_SFENCE_VMA_ASID, SBI_TLB_SFENCE_VMA_ASID,
source_hart); source_hart);
ret = sbi_tlb_request(hmask, hbase, &tlb_info); ret = sbi_tlb_request(hmask, 0, &tlb_info);
} else { } else {
sbi_trap_redirect(regs, &trap); sbi_trap_redirect(regs, &trap);
out->skip_regs_update = true; out->skip_regs_update = true;
@@ -131,7 +132,6 @@ static int sbi_ecall_legacy_register_extensions(void)
} }
struct sbi_ecall_extension ecall_legacy = { struct sbi_ecall_extension ecall_legacy = {
.name = "legacy",
.extid_start = SBI_EXT_0_1_SET_TIMER, .extid_start = SBI_EXT_0_1_SET_TIMER,
.extid_end = SBI_EXT_0_1_SHUTDOWN, .extid_end = SBI_EXT_0_1_SHUTDOWN,
.register_extensions = sbi_ecall_legacy_register_extensions, .register_extensions = sbi_ecall_legacy_register_extensions,

View File

@@ -1,70 +0,0 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2024 Ventana Micro Systems Inc.
*
* Authors:
* Anup Patel <apatel@ventanamicro.com>
*/
#include <sbi/sbi_ecall.h>
#include <sbi/sbi_ecall_interface.h>
#include <sbi/sbi_error.h>
#include <sbi/sbi_trap.h>
#include <sbi/sbi_mpxy.h>
static int sbi_ecall_mpxy_handler(unsigned long extid, unsigned long funcid,
struct sbi_trap_regs *regs,
struct sbi_ecall_return *out)
{
int ret = 0;
switch (funcid) {
case SBI_EXT_MPXY_SET_SHMEM:
ret = sbi_mpxy_set_shmem(regs->a0, regs->a1, regs->a2, regs->a3);
break;
case SBI_EXT_MPXY_GET_CHANNEL_IDS:
ret = sbi_mpxy_get_channel_ids(regs->a0);
break;
case SBI_EXT_MPXY_READ_ATTRS:
ret = sbi_mpxy_read_attrs(regs->a0, regs->a1, regs->a2);
break;
case SBI_EXT_MPXY_WRITE_ATTRS:
ret = sbi_mpxy_write_attrs(regs->a0, regs->a1, regs->a2);
break;
case SBI_EXT_MPXY_SEND_MSG_WITH_RESP:
ret = sbi_mpxy_send_message(regs->a0, regs->a1,
regs->a2, &out->value);
break;
case SBI_EXT_MPXY_SEND_MSG_NO_RESP:
ret = sbi_mpxy_send_message(regs->a0, regs->a1, regs->a2,
NULL);
break;
case SBI_EXT_MPXY_GET_NOTIFICATION_EVENTS:
ret = sbi_mpxy_get_notification_events(regs->a0, &out->value);
break;
default:
ret = SBI_ENOTSUPP;
}
return ret;
}
struct sbi_ecall_extension ecall_mpxy;
static int sbi_ecall_mpxy_register_extensions(void)
{
if (!sbi_mpxy_channel_available())
return 0;
return sbi_ecall_register_extension(&ecall_mpxy);
}
struct sbi_ecall_extension ecall_mpxy = {
.name = "mpxy",
.extid_start = SBI_EXT_MPXY,
.extid_end = SBI_EXT_MPXY,
.experimental = true,
.register_extensions = sbi_ecall_mpxy_register_extensions,
.handle = sbi_ecall_mpxy_handler,
};

View File

@@ -73,9 +73,6 @@ static int sbi_ecall_pmu_handler(unsigned long extid, unsigned long funcid,
case SBI_EXT_PMU_COUNTER_STOP: case SBI_EXT_PMU_COUNTER_STOP:
ret = sbi_pmu_ctr_stop(regs->a0, regs->a1, regs->a2); ret = sbi_pmu_ctr_stop(regs->a0, regs->a1, regs->a2);
break; break;
case SBI_EXT_PMU_EVENT_GET_INFO:
ret = sbi_pmu_event_get_info(regs->a0, regs->a1, regs->a2, regs->a3);
break;
case SBI_EXT_PMU_SNAPSHOT_SET_SHMEM: case SBI_EXT_PMU_SNAPSHOT_SET_SHMEM:
/* fallthrough as OpenSBI doesn't support snapshot yet */ /* fallthrough as OpenSBI doesn't support snapshot yet */
default: default:
@@ -93,7 +90,6 @@ static int sbi_ecall_pmu_register_extensions(void)
} }
struct sbi_ecall_extension ecall_pmu = { struct sbi_ecall_extension ecall_pmu = {
.name = "pmu",
.extid_start = SBI_EXT_PMU, .extid_start = SBI_EXT_PMU,
.extid_end = SBI_EXT_PMU, .extid_end = SBI_EXT_PMU,
.register_extensions = sbi_ecall_pmu_register_extensions, .register_extensions = sbi_ecall_pmu_register_extensions,

View File

@@ -84,7 +84,6 @@ static int sbi_ecall_rfence_register_extensions(void)
} }
struct sbi_ecall_extension ecall_rfence = { struct sbi_ecall_extension ecall_rfence = {
.name = "rfnc",
.extid_start = SBI_EXT_RFENCE, .extid_start = SBI_EXT_RFENCE,
.extid_end = SBI_EXT_RFENCE, .extid_end = SBI_EXT_RFENCE,
.register_extensions = sbi_ecall_rfence_register_extensions, .register_extensions = sbi_ecall_rfence_register_extensions,

View File

@@ -75,7 +75,6 @@ static int sbi_ecall_srst_register_extensions(void)
} }
struct sbi_ecall_extension ecall_srst = { struct sbi_ecall_extension ecall_srst = {
.name = "srst",
.extid_start = SBI_EXT_SRST, .extid_start = SBI_EXT_SRST,
.extid_end = SBI_EXT_SRST, .extid_end = SBI_EXT_SRST,
.register_extensions = sbi_ecall_srst_register_extensions, .register_extensions = sbi_ecall_srst_register_extensions,

View File

@@ -36,12 +36,6 @@ static int sbi_ecall_sse_handler(unsigned long extid, unsigned long funcid,
case SBI_EXT_SSE_INJECT: case SBI_EXT_SSE_INJECT:
ret = sbi_sse_inject_from_ecall(regs->a0, regs->a1, out); ret = sbi_sse_inject_from_ecall(regs->a0, regs->a1, out);
break; break;
case SBI_EXT_SSE_HART_MASK:
ret = sbi_sse_hart_mask();
break;
case SBI_EXT_SSE_HART_UNMASK:
ret = sbi_sse_hart_unmask();
break;
default: default:
ret = SBI_ENOTSUPP; ret = SBI_ENOTSUPP;
} }
@@ -56,10 +50,8 @@ static int sbi_ecall_sse_register_extensions(void)
} }
struct sbi_ecall_extension ecall_sse = { struct sbi_ecall_extension ecall_sse = {
.name = "sse",
.extid_start = SBI_EXT_SSE, .extid_start = SBI_EXT_SSE,
.extid_end = SBI_EXT_SSE, .extid_end = SBI_EXT_SSE,
.experimental = true,
.register_extensions = sbi_ecall_sse_register_extensions, .register_extensions = sbi_ecall_sse_register_extensions,
.handle = sbi_ecall_sse_handler, .handle = sbi_ecall_sse_handler,
}; };

View File

@@ -49,7 +49,6 @@ static int sbi_ecall_susp_register_extensions(void)
} }
struct sbi_ecall_extension ecall_susp = { struct sbi_ecall_extension ecall_susp = {
.name = "susp",
.extid_start = SBI_EXT_SUSP, .extid_start = SBI_EXT_SUSP,
.extid_end = SBI_EXT_SUSP, .extid_end = SBI_EXT_SUSP,
.register_extensions = sbi_ecall_susp_register_extensions, .register_extensions = sbi_ecall_susp_register_extensions,

View File

@@ -40,7 +40,6 @@ static int sbi_ecall_time_register_extensions(void)
} }
struct sbi_ecall_extension ecall_time = { struct sbi_ecall_extension ecall_time = {
.name = "time",
.extid_start = SBI_EXT_TIME, .extid_start = SBI_EXT_TIME,
.extid_end = SBI_EXT_TIME, .extid_end = SBI_EXT_TIME,
.register_extensions = sbi_ecall_time_register_extensions, .register_extensions = sbi_ecall_time_register_extensions,

View File

@@ -46,7 +46,6 @@ static int sbi_ecall_vendor_register_extensions(void)
} }
struct sbi_ecall_extension ecall_vendor = { struct sbi_ecall_extension ecall_vendor = {
.name = "vendor",
.extid_start = SBI_EXT_VENDOR_START, .extid_start = SBI_EXT_VENDOR_START,
.extid_end = SBI_EXT_VENDOR_END, .extid_end = SBI_EXT_VENDOR_END,
.register_extensions = sbi_ecall_vendor_register_extensions, .register_extensions = sbi_ecall_vendor_register_extensions,

View File

@@ -46,8 +46,12 @@ int sbi_emulate_csr_read(int csr_num, struct sbi_trap_regs *regs,
{ {
int ret = 0; int ret = 0;
struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
ulong prev_mode = sbi_mstatus_prev_mode(regs->mstatus); ulong prev_mode = (regs->mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT;
bool virt = sbi_regs_from_virt(regs); #if __riscv_xlen == 32
bool virt = (regs->mstatusH & MSTATUSH_MPV) ? true : false;
#else
bool virt = (regs->mstatus & MSTATUS_MPV) ? true : false;
#endif
switch (csr_num) { switch (csr_num) {
case CSR_HTIMEDELTA: case CSR_HTIMEDELTA:
@@ -62,11 +66,12 @@ int sbi_emulate_csr_read(int csr_num, struct sbi_trap_regs *regs,
*csr_val = csr_read(CSR_MCYCLE); *csr_val = csr_read(CSR_MCYCLE);
break; break;
case CSR_TIME: case CSR_TIME:
if (!hpm_allowed(csr_num - CSR_CYCLE, prev_mode, virt))
return SBI_ENOTSUPP;
/* /*
* We emulate TIME CSR for both Host (HS/U-mode) and * We emulate TIME CSR for both Host (HS/U-mode) and
* Guest (VS/VU-mode). * Guest (VS/VU-mode).
*
* Faster TIME CSR reads are critical for good performance
* in S-mode software so we don't check CSR permissions.
*/ */
*csr_val = (virt) ? sbi_timer_virt_value(): *csr_val = (virt) ? sbi_timer_virt_value():
sbi_timer_value(); sbi_timer_value();
@@ -152,8 +157,12 @@ int sbi_emulate_csr_write(int csr_num, struct sbi_trap_regs *regs,
ulong csr_val) ulong csr_val)
{ {
int ret = 0; int ret = 0;
ulong prev_mode = sbi_mstatus_prev_mode(regs->mstatus); ulong prev_mode = (regs->mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT;
bool virt = sbi_regs_from_virt(regs); #if __riscv_xlen == 32
bool virt = (regs->mstatusH & MSTATUSH_MPV) ? true : false;
#else
bool virt = (regs->mstatus & MSTATUS_MPV) ? true : false;
#endif
switch (csr_num) { switch (csr_num) {
case CSR_HTIMEDELTA: case CSR_HTIMEDELTA:

View File

@@ -59,7 +59,6 @@ static const unsigned long fwft_defined_features[] = {
SBI_FWFT_SHADOW_STACK, SBI_FWFT_SHADOW_STACK,
SBI_FWFT_DOUBLE_TRAP, SBI_FWFT_DOUBLE_TRAP,
SBI_FWFT_PTE_AD_HW_UPDATING, SBI_FWFT_PTE_AD_HW_UPDATING,
SBI_FWFT_POINTER_MASKING_PMLEN,
}; };
static bool fwft_is_defined_feature(enum sbi_fwft_feature_t feature) static bool fwft_is_defined_feature(enum sbi_fwft_feature_t feature)
@@ -74,40 +73,6 @@ static bool fwft_is_defined_feature(enum sbi_fwft_feature_t feature)
return false; return false;
} }
static int fwft_menvcfg_set_bit(unsigned long value, unsigned long bit)
{
if (value == 1) {
if (bit >= 32 && __riscv_xlen == 32)
csr_set(CSR_MENVCFGH, _ULL(1) << (bit - 32));
else
csr_set(CSR_MENVCFG, _ULL(1) << bit);
} else if (value == 0) {
if (bit >= 32 && __riscv_xlen == 32)
csr_clear(CSR_MENVCFGH, _ULL(1) << (bit - 32));
else
csr_clear(CSR_MENVCFG, _ULL(1) << bit);
} else {
return SBI_EINVAL;
}
return SBI_OK;
}
static int fwft_menvcfg_read_bit(unsigned long *value, unsigned long bit)
{
unsigned long cfg;
if (bit >= 32 && __riscv_xlen == 32)
cfg = csr_read(CSR_MENVCFGH) & (_ULL(1) << (bit - 32));
else
cfg = csr_read(CSR_MENVCFG) & (_ULL(1) << bit);
*value = cfg != 0;
return SBI_OK;
}
static int fwft_misaligned_delegation_supported(struct fwft_config *conf) static int fwft_misaligned_delegation_supported(struct fwft_config *conf)
{ {
if (!misa_extension('S')) if (!misa_extension('S'))
@@ -137,25 +102,6 @@ static int fwft_get_misaligned_delegation(struct fwft_config *conf,
return SBI_OK; return SBI_OK;
} }
static int fwft_double_trap_supported(struct fwft_config *conf)
{
if (!sbi_hart_has_extension(sbi_scratch_thishart_ptr(),
SBI_HART_EXT_SSDBLTRP))
return SBI_ENOTSUPP;
return SBI_OK;
}
static int fwft_set_double_trap(struct fwft_config *conf, unsigned long value)
{
return fwft_menvcfg_set_bit(value, ENVCFG_DTE_SHIFT);
}
static int fwft_get_double_trap(struct fwft_config *conf, unsigned long *value)
{
return fwft_menvcfg_read_bit(value, ENVCFG_DTE_SHIFT);
}
static int fwft_adue_supported(struct fwft_config *conf) static int fwft_adue_supported(struct fwft_config *conf)
{ {
if (!sbi_hart_has_extension(sbi_scratch_thishart_ptr(), if (!sbi_hart_has_extension(sbi_scratch_thishart_ptr(),
@@ -167,109 +113,37 @@ static int fwft_adue_supported(struct fwft_config *conf)
static int fwft_set_adue(struct fwft_config *conf, unsigned long value) static int fwft_set_adue(struct fwft_config *conf, unsigned long value)
{ {
return fwft_menvcfg_set_bit(value, ENVCFG_ADUE_SHIFT); if (value == 1)
#if __riscv_xlen == 32
csr_set(CSR_MENVCFGH, ENVCFG_ADUE >> 32);
#else
csr_set(CSR_MENVCFG, ENVCFG_ADUE);
#endif
else if (value == 0)
#if __riscv_xlen == 32
csr_clear(CSR_MENVCFGH, ENVCFG_ADUE >> 32);
#else
csr_clear(CSR_MENVCFG, ENVCFG_ADUE);
#endif
else
return SBI_EINVAL;
return SBI_OK;
} }
static int fwft_get_adue(struct fwft_config *conf, unsigned long *value) static int fwft_get_adue(struct fwft_config *conf, unsigned long *value)
{ {
return fwft_menvcfg_read_bit(value, ENVCFG_ADUE_SHIFT); unsigned long cfg;
}
static int fwft_lpad_supported(struct fwft_config *conf) #if __riscv_xlen == 32
{ cfg = csr_read(CSR_MENVCFGH) & (ENVCFG_ADUE >> 32);
if (!sbi_hart_has_extension(sbi_scratch_thishart_ptr(), #else
SBI_HART_EXT_ZICFILP)) cfg = csr_read(CSR_MENVCFG) & ENVCFG_ADUE;
return SBI_ENOTSUPP;
return SBI_OK;
}
static int fwft_enable_lpad(struct fwft_config *conf, unsigned long value)
{
return fwft_menvcfg_set_bit(value, ENVCFG_LPE_SHIFT);
}
static int fwft_get_lpad(struct fwft_config *conf, unsigned long *value)
{
return fwft_menvcfg_read_bit(value, ENVCFG_LPE_SHIFT);
}
static int fwft_sstack_supported(struct fwft_config *conf)
{
if (!sbi_hart_has_extension(sbi_scratch_thishart_ptr(),
SBI_HART_EXT_ZICFISS))
return SBI_ENOTSUPP;
return SBI_OK;
}
static int fwft_enable_sstack(struct fwft_config *conf, unsigned long value)
{
return fwft_menvcfg_set_bit(value, ENVCFG_SSE_SHIFT);
}
static int fwft_get_sstack(struct fwft_config *conf, unsigned long *value)
{
return fwft_menvcfg_read_bit(value, ENVCFG_SSE_SHIFT);
}
#if __riscv_xlen > 32
static int fwft_pmlen_supported(struct fwft_config *conf)
{
if (!sbi_hart_has_extension(sbi_scratch_thishart_ptr(),
SBI_HART_EXT_SMNPM))
return SBI_ENOTSUPP;
return SBI_OK;
}
static bool fwft_try_to_set_pmm(unsigned long pmm)
{
csr_set(CSR_MENVCFG, pmm);
return (csr_read(CSR_MENVCFG) & ENVCFG_PMM) == pmm;
}
static int fwft_set_pmlen(struct fwft_config *conf, unsigned long value)
{
unsigned long prev;
if (value > 16)
return SBI_EINVAL;
prev = csr_read_clear(CSR_MENVCFG, ENVCFG_PMM);
if (value == 0)
return SBI_OK;
if (value <= 7) {
if (fwft_try_to_set_pmm(ENVCFG_PMM_PMLEN_7))
return SBI_OK;
csr_clear(CSR_MENVCFG, ENVCFG_PMM);
}
if (fwft_try_to_set_pmm(ENVCFG_PMM_PMLEN_16))
return SBI_OK;
csr_write(CSR_MENVCFG, prev);
return SBI_EINVAL;
}
static int fwft_get_pmlen(struct fwft_config *conf, unsigned long *value)
{
switch (csr_read(CSR_MENVCFG) & ENVCFG_PMM) {
case ENVCFG_PMM_PMLEN_0:
*value = 0;
break;
case ENVCFG_PMM_PMLEN_7:
*value = 7;
break;
case ENVCFG_PMM_PMLEN_16:
*value = 16;
break;
default:
return SBI_EFAIL;
}
return SBI_OK;
}
#endif #endif
*value = cfg != 0;
return SBI_OK;
}
static struct fwft_config* get_feature_config(enum sbi_fwft_feature_t feature) static struct fwft_config* get_feature_config(enum sbi_fwft_feature_t feature)
{ {
@@ -311,18 +185,6 @@ static int fwft_get_feature(enum sbi_fwft_feature_t feature,
return SBI_SUCCESS; return SBI_SUCCESS;
} }
static void fwft_clear_config_lock(enum sbi_fwft_feature_t feature)
{
int ret;
struct fwft_config *conf;
ret = fwft_get_feature(feature, &conf);
if (ret)
return;
conf->flags &= ~SBI_FWFT_SET_FLAG_LOCK;
}
int sbi_fwft_set(enum sbi_fwft_feature_t feature, unsigned long value, int sbi_fwft_set(enum sbi_fwft_feature_t feature, unsigned long value,
unsigned long flags) unsigned long flags)
{ {
@@ -368,38 +230,12 @@ static const struct fwft_feature features[] =
.set = fwft_set_misaligned_delegation, .set = fwft_set_misaligned_delegation,
.get = fwft_get_misaligned_delegation, .get = fwft_get_misaligned_delegation,
}, },
{
.id = SBI_FWFT_LANDING_PAD,
.supported = fwft_lpad_supported,
.set = fwft_enable_lpad,
.get = fwft_get_lpad,
},
{
.id = SBI_FWFT_SHADOW_STACK,
.supported = fwft_sstack_supported,
.set = fwft_enable_sstack,
.get = fwft_get_sstack,
},
{
.id = SBI_FWFT_DOUBLE_TRAP,
.supported = fwft_double_trap_supported,
.set = fwft_set_double_trap,
.get = fwft_get_double_trap,
},
{ {
.id = SBI_FWFT_PTE_AD_HW_UPDATING, .id = SBI_FWFT_PTE_AD_HW_UPDATING,
.supported = fwft_adue_supported, .supported = fwft_adue_supported,
.set = fwft_set_adue, .set = fwft_set_adue,
.get = fwft_get_adue, .get = fwft_get_adue,
}, },
#if __riscv_xlen > 32
{
.id = SBI_FWFT_POINTER_MASKING_PMLEN,
.supported = fwft_pmlen_supported,
.set = fwft_set_pmlen,
.get = fwft_get_pmlen,
},
#endif
}; };
int sbi_fwft_init(struct sbi_scratch *scratch, bool cold_boot) int sbi_fwft_init(struct sbi_scratch *scratch, bool cold_boot)
@@ -426,8 +262,5 @@ int sbi_fwft_init(struct sbi_scratch *scratch, bool cold_boot)
fwft_set_hart_state_ptr(scratch, fhs); fwft_set_hart_state_ptr(scratch, fhs);
} }
for (i = 0; i < array_size(features); i++)
fwft_clear_config_lock(features[i].id);
return 0; return 0;
} }

View File

@@ -117,9 +117,6 @@ static void mstatus_init(struct sbi_scratch *scratch)
menvcfg_val |= ((uint64_t)csr_read(CSR_MENVCFGH)) << 32; menvcfg_val |= ((uint64_t)csr_read(CSR_MENVCFGH)) << 32;
#endif #endif
/* Disable double trap by default */
menvcfg_val &= ~ENVCFG_DTE;
#define __set_menvcfg_ext(__ext, __bits) \ #define __set_menvcfg_ext(__ext, __bits) \
if (sbi_hart_has_extension(scratch, __ext)) \ if (sbi_hart_has_extension(scratch, __ext)) \
menvcfg_val |= __bits; menvcfg_val |= __bits;
@@ -210,8 +207,7 @@ static int delegate_traps(struct sbi_scratch *scratch)
if (sbi_platform_has_mfaults_delegation(plat)) if (sbi_platform_has_mfaults_delegation(plat))
exceptions |= (1U << CAUSE_FETCH_PAGE_FAULT) | exceptions |= (1U << CAUSE_FETCH_PAGE_FAULT) |
(1U << CAUSE_LOAD_PAGE_FAULT) | (1U << CAUSE_LOAD_PAGE_FAULT) |
(1U << CAUSE_STORE_PAGE_FAULT) | (1U << CAUSE_STORE_PAGE_FAULT);
(1U << CAUSE_SW_CHECK_EXCP);
/* /*
* If hypervisor extension available then we only handle hypervisor * If hypervisor extension available then we only handle hypervisor
@@ -684,10 +680,6 @@ const struct sbi_hart_ext_data sbi_hart_ext[] = {
__SBI_HART_EXT_DATA(ssccfg, SBI_HART_EXT_SSCCFG), __SBI_HART_EXT_DATA(ssccfg, SBI_HART_EXT_SSCCFG),
__SBI_HART_EXT_DATA(svade, SBI_HART_EXT_SVADE), __SBI_HART_EXT_DATA(svade, SBI_HART_EXT_SVADE),
__SBI_HART_EXT_DATA(svadu, SBI_HART_EXT_SVADU), __SBI_HART_EXT_DATA(svadu, SBI_HART_EXT_SVADU),
__SBI_HART_EXT_DATA(smnpm, SBI_HART_EXT_SMNPM),
__SBI_HART_EXT_DATA(zicfilp, SBI_HART_EXT_ZICFILP),
__SBI_HART_EXT_DATA(zicfiss, SBI_HART_EXT_ZICFISS),
__SBI_HART_EXT_DATA(ssdbltrp, SBI_HART_EXT_SSDBLTRP),
}; };
_Static_assert(SBI_HART_EXT_MAX == array_size(sbi_hart_ext), _Static_assert(SBI_HART_EXT_MAX == array_size(sbi_hart_ext),
@@ -731,13 +723,13 @@ static unsigned long hart_pmp_get_allowed_addr(void)
unsigned long val = 0; unsigned long val = 0;
struct sbi_trap_info trap = {0}; struct sbi_trap_info trap = {0};
csr_write_allowed(CSR_PMPCFG0, &trap, 0); csr_write_allowed(CSR_PMPCFG0, (ulong)&trap, 0);
if (trap.cause) if (trap.cause)
return 0; return 0;
csr_write_allowed(CSR_PMPADDR0, &trap, PMP_ADDR_MASK); csr_write_allowed(CSR_PMPADDR0, (ulong)&trap, PMP_ADDR_MASK);
if (!trap.cause) { if (!trap.cause) {
val = csr_read_allowed(CSR_PMPADDR0, &trap); val = csr_read_allowed(CSR_PMPADDR0, (ulong)&trap);
if (trap.cause) if (trap.cause)
val = 0; val = 0;
} }
@@ -755,17 +747,17 @@ static int hart_mhpm_get_allowed_bits(void)
* It is assumed that platforms will implement same number of bits for * It is assumed that platforms will implement same number of bits for
* all the performance counters including mcycle/minstret. * all the performance counters including mcycle/minstret.
*/ */
csr_write_allowed(CSR_MHPMCOUNTER3, &trap, val); csr_write_allowed(CSR_MHPMCOUNTER3, (ulong)&trap, val);
if (!trap.cause) { if (!trap.cause) {
val = csr_read_allowed(CSR_MHPMCOUNTER3, &trap); val = csr_read_allowed(CSR_MHPMCOUNTER3, (ulong)&trap);
if (trap.cause) if (trap.cause)
return 0; return 0;
} }
num_bits = sbi_fls(val) + 1; num_bits = sbi_fls(val) + 1;
#if __riscv_xlen == 32 #if __riscv_xlen == 32
csr_write_allowed(CSR_MHPMCOUNTER3H, &trap, val); csr_write_allowed(CSR_MHPMCOUNTER3H, (ulong)&trap, val);
if (!trap.cause) { if (!trap.cause) {
val = csr_read_allowed(CSR_MHPMCOUNTER3H, &trap); val = csr_read_allowed(CSR_MHPMCOUNTER3H, (ulong)&trap);
if (trap.cause) if (trap.cause)
return num_bits; return num_bits;
} }
@@ -796,9 +788,9 @@ static int hart_detect_features(struct sbi_scratch *scratch)
hfeatures->priv_version = SBI_HART_PRIV_VER_UNKNOWN; hfeatures->priv_version = SBI_HART_PRIV_VER_UNKNOWN;
#define __check_hpm_csr(__csr, __mask) \ #define __check_hpm_csr(__csr, __mask) \
oldval = csr_read_allowed(__csr, &trap); \ oldval = csr_read_allowed(__csr, (ulong)&trap); \
if (!trap.cause) { \ if (!trap.cause) { \
csr_write_allowed(__csr, &trap, 1UL); \ csr_write_allowed(__csr, (ulong)&trap, 1UL); \
if (!trap.cause && csr_swap(__csr, oldval) == 1UL) { \ if (!trap.cause && csr_swap(__csr, oldval) == 1UL) { \
(hfeatures->__mask) |= 1 << (__csr - CSR_MCYCLE); \ (hfeatures->__mask) |= 1 << (__csr - CSR_MCYCLE); \
} \ } \
@@ -817,15 +809,15 @@ static int hart_detect_features(struct sbi_scratch *scratch)
__check_hpm_csr_8(__csr + 0, __mask) \ __check_hpm_csr_8(__csr + 0, __mask) \
__check_hpm_csr_8(__csr + 8, __mask) __check_hpm_csr_8(__csr + 8, __mask)
#define __check_csr(__csr, __rdonly, __wrval, __field, __skip) \ #define __check_csr(__csr, __rdonly, __wrval, __field, __skip) \
oldval = csr_read_allowed(__csr, &trap); \ oldval = csr_read_allowed(__csr, (ulong)&trap); \
if (!trap.cause) { \ if (!trap.cause) { \
if (__rdonly) { \ if (__rdonly) { \
(hfeatures->__field)++; \ (hfeatures->__field)++; \
} else { \ } else { \
csr_write_allowed(__csr, &trap, __wrval); \ csr_write_allowed(__csr, (ulong)&trap, __wrval);\
if (!trap.cause) { \ if (!trap.cause) { \
if ((csr_swap(__csr, oldval) & __wrval) == __wrval) \ if (csr_swap(__csr, oldval) == __wrval) \
(hfeatures->__field)++; \ (hfeatures->__field)++; \
else \ else \
goto __skip; \ goto __skip; \
@@ -888,7 +880,7 @@ __pmp_skip:
#define __check_priv(__csr, __base_priv, __priv) \ #define __check_priv(__csr, __base_priv, __priv) \
val = csr_read_allowed(__csr, &trap); \ val = csr_read_allowed(__csr, (ulong)&trap); \
if (!trap.cause && (hfeatures->priv_version >= __base_priv)) { \ if (!trap.cause && (hfeatures->priv_version >= __base_priv)) { \
hfeatures->priv_version = __priv; \ hfeatures->priv_version = __priv; \
} }
@@ -907,7 +899,7 @@ __pmp_skip:
#define __check_ext_csr(__base_priv, __csr, __ext) \ #define __check_ext_csr(__base_priv, __csr, __ext) \
if (hfeatures->priv_version >= __base_priv) { \ if (hfeatures->priv_version >= __base_priv) { \
csr_read_allowed(__csr, &trap); \ csr_read_allowed(__csr, (ulong)&trap); \
if (!trap.cause) \ if (!trap.cause) \
__sbi_hart_update_extension(hfeatures, \ __sbi_hart_update_extension(hfeatures, \
__ext, true); \ __ext, true); \

View File

@@ -60,12 +60,12 @@ bool sbi_hsm_hart_change_state(struct sbi_scratch *scratch, long oldstate,
return __sbi_hsm_hart_change_state(hdata, oldstate, newstate); return __sbi_hsm_hart_change_state(hdata, oldstate, newstate);
} }
int __sbi_hsm_hart_get_state(u32 hartindex) int __sbi_hsm_hart_get_state(u32 hartid)
{ {
struct sbi_hsm_data *hdata; struct sbi_hsm_data *hdata;
struct sbi_scratch *scratch; struct sbi_scratch *scratch;
scratch = sbi_hartindex_to_scratch(hartindex); scratch = sbi_hartid_to_scratch(hartid);
if (!scratch) if (!scratch)
return SBI_EINVAL; return SBI_EINVAL;
@@ -75,12 +75,10 @@ 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_get_state(const struct sbi_domain *dom, u32 hartid)
{ {
u32 hartindex = sbi_hartid_to_hartindex(hartid); if (!sbi_domain_is_assigned_hart(dom, hartid))
if (!sbi_domain_is_assigned_hart(dom, hartindex))
return SBI_EINVAL; return SBI_EINVAL;
return __sbi_hsm_hart_get_state(hartindex); return __sbi_hsm_hart_get_state(hartid);
} }
/* /*
@@ -110,27 +108,34 @@ static void hsm_start_ticket_release(struct sbi_hsm_data *hdata)
} }
/** /**
* Get the mask of harts which are valid IPI targets * Get ulong HART mask for given HART base ID
* @param dom the domain to be used for output HART mask * @param dom the domain to be used for output HART mask
* @param mask the output hartmask to fill * @param hbase the HART base ID
* @param out_hmask the output ulong HART mask
* @return 0 on success and SBI_Exxx (< 0) on failure * @return 0 on success and SBI_Exxx (< 0) on failure
* Note: the output HART mask will be set to zero on failure as well.
*/ */
int sbi_hsm_hart_interruptible_mask(const struct sbi_domain *dom, int sbi_hsm_hart_interruptible_mask(const struct sbi_domain *dom,
struct sbi_hartmask *mask) ulong hbase, ulong *out_hmask)
{ {
int hstate, ret; int hstate;
u32 i; ulong i, hmask, dmask;
ret = sbi_domain_get_assigned_hartmask(dom, mask); *out_hmask = 0;
if (ret) if (!sbi_hartid_valid(hbase))
return ret; return SBI_EINVAL;
sbi_hartmask_for_each_hartindex(i, mask) { dmask = sbi_domain_get_assigned_hartmask(dom, hbase);
hstate = __sbi_hsm_hart_get_state(i); for (i = 0; i < BITS_PER_LONG; i++) {
if (hstate != SBI_HSM_STATE_STARTED && hmask = 1UL << i;
hstate != SBI_HSM_STATE_SUSPENDED && if (!(dmask & hmask))
hstate != SBI_HSM_STATE_RESUME_PENDING) continue;
sbi_hartmask_clear_hartindex(i, mask);
hstate = __sbi_hsm_hart_get_state(hbase + i);
if (hstate == SBI_HSM_STATE_STARTED ||
hstate == SBI_HSM_STATE_SUSPENDED ||
hstate == SBI_HSM_STATE_RESUME_PENDING)
*out_hmask |= hmask;
} }
return 0; return 0;
@@ -157,7 +162,7 @@ void __noreturn sbi_hsm_hart_start_finish(struct sbi_scratch *scratch,
sbi_hart_switch_mode(hartid, next_arg1, next_addr, next_mode, false); sbi_hart_switch_mode(hartid, next_arg1, next_addr, next_mode, false);
} }
static void sbi_hsm_hart_wait(struct sbi_scratch *scratch) static void sbi_hsm_hart_wait(struct sbi_scratch *scratch, u32 hartid)
{ {
unsigned long saved_mie; unsigned long saved_mie;
struct sbi_hsm_data *hdata = sbi_scratch_offset_ptr(scratch, struct sbi_hsm_data *hdata = sbi_scratch_offset_ptr(scratch,
@@ -178,7 +183,7 @@ static void sbi_hsm_hart_wait(struct sbi_scratch *scratch)
/* /*
* No need to clear IPI here because the sbi_ipi_init() will * No need to clear IPI here because the sbi_ipi_init() will
* clear it for current HART. * clear it for current HART via sbi_platform_ipi_init().
*/ */
} }
@@ -223,10 +228,10 @@ static int hsm_device_hart_stop(void)
return SBI_ENOTSUPP; return SBI_ENOTSUPP;
} }
static int hsm_device_hart_suspend(u32 suspend_type, ulong mmode_resume_addr) static int hsm_device_hart_suspend(u32 suspend_type)
{ {
if (hsm_dev && hsm_dev->hart_suspend) if (hsm_dev && hsm_dev->hart_suspend)
return hsm_dev->hart_suspend(suspend_type, mmode_resume_addr); return hsm_dev->hart_suspend(suspend_type);
return SBI_ENOTSUPP; return SBI_ENOTSUPP;
} }
@@ -236,7 +241,7 @@ static void hsm_device_hart_resume(void)
hsm_dev->hart_resume(); hsm_dev->hart_resume();
} }
int sbi_hsm_init(struct sbi_scratch *scratch, bool cold_boot) int sbi_hsm_init(struct sbi_scratch *scratch, u32 hartid, bool cold_boot)
{ {
u32 i; u32 i;
struct sbi_scratch *rscratch; struct sbi_scratch *rscratch;
@@ -256,13 +261,13 @@ int sbi_hsm_init(struct sbi_scratch *scratch, bool cold_boot)
hdata = sbi_scratch_offset_ptr(rscratch, hdata = sbi_scratch_offset_ptr(rscratch,
hart_data_offset); hart_data_offset);
ATOMIC_INIT(&hdata->state, ATOMIC_INIT(&hdata->state,
(i == current_hartindex()) ? (sbi_hartindex_to_hartid(i) == hartid) ?
SBI_HSM_STATE_START_PENDING : SBI_HSM_STATE_START_PENDING :
SBI_HSM_STATE_STOPPED); SBI_HSM_STATE_STOPPED);
ATOMIC_INIT(&hdata->start_ticket, 0); ATOMIC_INIT(&hdata->start_ticket, 0);
} }
} else { } else {
sbi_hsm_hart_wait(scratch); sbi_hsm_hart_wait(scratch, hartid);
} }
return 0; return 0;
@@ -300,7 +305,6 @@ int sbi_hsm_hart_start(struct sbi_scratch *scratch,
const struct sbi_domain *dom, const struct sbi_domain *dom,
u32 hartid, ulong saddr, ulong smode, ulong arg1) u32 hartid, ulong saddr, ulong smode, ulong arg1)
{ {
u32 hartindex = sbi_hartid_to_hartindex(hartid);
unsigned long init_count, entry_count; unsigned long init_count, entry_count;
unsigned int hstate; unsigned int hstate;
struct sbi_scratch *rscratch; struct sbi_scratch *rscratch;
@@ -310,13 +314,13 @@ int sbi_hsm_hart_start(struct sbi_scratch *scratch,
/* For now, we only allow start mode to be S-mode or U-mode. */ /* For now, we only allow start mode to be S-mode or U-mode. */
if (smode != PRV_S && smode != PRV_U) if (smode != PRV_S && smode != PRV_U)
return SBI_EINVAL; return SBI_EINVAL;
if (dom && !sbi_domain_is_assigned_hart(dom, hartindex)) if (dom && !sbi_domain_is_assigned_hart(dom, hartid))
return SBI_EINVAL; return SBI_EINVAL;
if (dom && !sbi_domain_check_addr(dom, saddr, smode, if (dom && !sbi_domain_check_addr(dom, saddr, smode,
SBI_DOMAIN_EXECUTE)) SBI_DOMAIN_EXECUTE))
return SBI_EINVALID_ADDR; return SBI_EINVALID_ADDR;
rscratch = sbi_hartindex_to_scratch(hartindex); rscratch = sbi_hartid_to_scratch(hartid);
if (!rscratch) if (!rscratch)
return SBI_EINVAL; return SBI_EINVAL;
@@ -324,8 +328,8 @@ int sbi_hsm_hart_start(struct sbi_scratch *scratch,
if (!hsm_start_ticket_acquire(hdata)) if (!hsm_start_ticket_acquire(hdata))
return SBI_EINVAL; return SBI_EINVAL;
init_count = sbi_init_count(hartindex); init_count = sbi_init_count(hartid);
entry_count = sbi_entry_count(hartindex); entry_count = sbi_entry_count(hartid);
rscratch->next_arg1 = arg1; rscratch->next_arg1 = arg1;
rscratch->next_addr = saddr; rscratch->next_addr = saddr;
@@ -356,7 +360,7 @@ int sbi_hsm_hart_start(struct sbi_scratch *scratch,
(hsm_device_has_hart_secondary_boot() && !init_count)) { (hsm_device_has_hart_secondary_boot() && !init_count)) {
rc = hsm_device_hart_start(hartid, scratch->warmboot_addr); rc = hsm_device_hart_start(hartid, scratch->warmboot_addr);
} else { } else {
rc = sbi_ipi_raw_send(hartindex); rc = sbi_ipi_raw_send(sbi_hartid_to_hartindex(hartid));
} }
if (!rc) if (!rc)
@@ -532,7 +536,7 @@ int sbi_hsm_hart_suspend(struct sbi_scratch *scratch, u32 suspend_type,
__sbi_hsm_suspend_non_ret_save(scratch); __sbi_hsm_suspend_non_ret_save(scratch);
/* Try platform specific suspend */ /* Try platform specific suspend */
ret = hsm_device_hart_suspend(suspend_type, scratch->warmboot_addr); ret = hsm_device_hart_suspend(suspend_type);
if (ret == SBI_ENOTSUPP) { if (ret == SBI_ENOTSUPP) {
/* Try generic implementation of default suspend types */ /* Try generic implementation of default suspend types */
if (suspend_type == SBI_HSM_SUSPEND_RET_DEFAULT || if (suspend_type == SBI_HSM_SUSPEND_RET_DEFAULT ||

View File

@@ -52,7 +52,7 @@ static int system_opcode_insn(ulong insn, struct sbi_trap_regs *regs)
int rs1_num = GET_RS1_NUM(insn); int rs1_num = GET_RS1_NUM(insn);
ulong rs1_val = GET_RS1(insn, regs); ulong rs1_val = GET_RS1(insn, regs);
int csr_num = GET_CSR_NUM((u32)insn); int csr_num = GET_CSR_NUM((u32)insn);
ulong prev_mode = sbi_mstatus_prev_mode(regs->mstatus); ulong prev_mode = (regs->mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT;
ulong csr_val, new_csr_val; ulong csr_val, new_csr_val;
if (prev_mode == PRV_M) { if (prev_mode == PRV_M) {

View File

@@ -24,7 +24,6 @@
#include <sbi/sbi_platform.h> #include <sbi/sbi_platform.h>
#include <sbi/sbi_pmu.h> #include <sbi/sbi_pmu.h>
#include <sbi/sbi_dbtr.h> #include <sbi/sbi_dbtr.h>
#include <sbi/sbi_mpxy.h>
#include <sbi/sbi_sse.h> #include <sbi/sbi_sse.h>
#include <sbi/sbi_system.h> #include <sbi/sbi_system.h>
#include <sbi/sbi_string.h> #include <sbi/sbi_string.h>
@@ -83,68 +82,64 @@ static void sbi_boot_print_general(struct sbi_scratch *scratch)
return; return;
/* Platform details */ /* Platform details */
sbi_printf("Platform Name : %s\n", sbi_printf("Platform Name : %s\n",
sbi_platform_name(plat)); sbi_platform_name(plat));
sbi_platform_get_features_str(plat, str, sizeof(str)); sbi_platform_get_features_str(plat, str, sizeof(str));
sbi_printf("Platform Features : %s\n", str); sbi_printf("Platform Features : %s\n", str);
sbi_printf("Platform HART Count : %u\n", sbi_printf("Platform HART Count : %u\n",
sbi_platform_hart_count(plat)); sbi_platform_hart_count(plat));
idev = sbi_ipi_get_device(); idev = sbi_ipi_get_device();
sbi_printf("Platform IPI Device : %s\n", sbi_printf("Platform IPI Device : %s\n",
(idev) ? idev->name : "---"); (idev) ? idev->name : "---");
tdev = sbi_timer_get_device(); tdev = sbi_timer_get_device();
sbi_printf("Platform Timer Device : %s @ %luHz\n", sbi_printf("Platform Timer Device : %s @ %luHz\n",
(tdev) ? tdev->name : "---", (tdev) ? tdev->name : "---",
(tdev) ? tdev->timer_freq : 0); (tdev) ? tdev->timer_freq : 0);
cdev = sbi_console_get_device(); cdev = sbi_console_get_device();
sbi_printf("Platform Console Device : %s\n", sbi_printf("Platform Console Device : %s\n",
(cdev) ? cdev->name : "---"); (cdev) ? cdev->name : "---");
hdev = sbi_hsm_get_device(); hdev = sbi_hsm_get_device();
sbi_printf("Platform HSM Device : %s\n", sbi_printf("Platform HSM Device : %s\n",
(hdev) ? hdev->name : "---"); (hdev) ? hdev->name : "---");
pdev = sbi_pmu_get_device(); pdev = sbi_pmu_get_device();
sbi_printf("Platform PMU Device : %s\n", sbi_printf("Platform PMU Device : %s\n",
(pdev) ? pdev->name : "---"); (pdev) ? pdev->name : "---");
srdev = sbi_system_reset_get_device(SBI_SRST_RESET_TYPE_COLD_REBOOT, 0); srdev = sbi_system_reset_get_device(SBI_SRST_RESET_TYPE_COLD_REBOOT, 0);
sbi_printf("Platform Reboot Device : %s\n", sbi_printf("Platform Reboot Device : %s\n",
(srdev) ? srdev->name : "---"); (srdev) ? srdev->name : "---");
srdev = sbi_system_reset_get_device(SBI_SRST_RESET_TYPE_SHUTDOWN, 0); srdev = sbi_system_reset_get_device(SBI_SRST_RESET_TYPE_SHUTDOWN, 0);
sbi_printf("Platform Shutdown Device : %s\n", sbi_printf("Platform Shutdown Device : %s\n",
(srdev) ? srdev->name : "---"); (srdev) ? srdev->name : "---");
susp_dev = sbi_system_suspend_get_device(); susp_dev = sbi_system_suspend_get_device();
sbi_printf("Platform Suspend Device : %s\n", sbi_printf("Platform Suspend Device : %s\n",
(susp_dev) ? susp_dev->name : "---"); (susp_dev) ? susp_dev->name : "---");
cppc_dev = sbi_cppc_get_device(); cppc_dev = sbi_cppc_get_device();
sbi_printf("Platform CPPC Device : %s\n", sbi_printf("Platform CPPC Device : %s\n",
(cppc_dev) ? cppc_dev->name : "---"); (cppc_dev) ? cppc_dev->name : "---");
/* Firmware details */ /* Firmware details */
sbi_printf("Firmware Base : 0x%lx\n", scratch->fw_start); sbi_printf("Firmware Base : 0x%lx\n", scratch->fw_start);
sbi_printf("Firmware Size : %d KB\n", sbi_printf("Firmware Size : %d KB\n",
(u32)(scratch->fw_size / 1024)); (u32)(scratch->fw_size / 1024));
sbi_printf("Firmware RW Offset : 0x%lx\n", scratch->fw_rw_offset); sbi_printf("Firmware RW Offset : 0x%lx\n", scratch->fw_rw_offset);
sbi_printf("Firmware RW Size : %d KB\n", sbi_printf("Firmware RW Size : %d KB\n",
(u32)((scratch->fw_size - scratch->fw_rw_offset) / 1024)); (u32)((scratch->fw_size - scratch->fw_rw_offset) / 1024));
sbi_printf("Firmware Heap Offset : 0x%lx\n", scratch->fw_heap_offset); sbi_printf("Firmware Heap Offset : 0x%lx\n", scratch->fw_heap_offset);
sbi_printf("Firmware Heap Size : " sbi_printf("Firmware Heap Size : "
"%d KB (total), %d KB (reserved), %d KB (used), %d KB (free)\n", "%d KB (total), %d KB (reserved), %d KB (used), %d KB (free)\n",
(u32)(scratch->fw_heap_size / 1024), (u32)(scratch->fw_heap_size / 1024),
(u32)(sbi_heap_reserved_space() / 1024), (u32)(sbi_heap_reserved_space() / 1024),
(u32)(sbi_heap_used_space() / 1024), (u32)(sbi_heap_used_space() / 1024),
(u32)(sbi_heap_free_space() / 1024)); (u32)(sbi_heap_free_space() / 1024));
sbi_printf("Firmware Scratch Size : " sbi_printf("Firmware Scratch Size : "
"%d B (total), %d B (used), %d B (free)\n", "%d B (total), %d B (used), %d B (free)\n",
SBI_SCRATCH_SIZE, SBI_SCRATCH_SIZE,
(u32)sbi_scratch_used_space(), (u32)sbi_scratch_used_space(),
(u32)(SBI_SCRATCH_SIZE - sbi_scratch_used_space())); (u32)(SBI_SCRATCH_SIZE - sbi_scratch_used_space()));
/* SBI details */ /* SBI details */
sbi_printf("Runtime SBI Version : %d.%d\n", sbi_printf("Runtime SBI Version : %d.%d\n",
sbi_ecall_version_major(), sbi_ecall_version_minor()); sbi_ecall_version_major(), sbi_ecall_version_minor());
sbi_ecall_get_extensions_str(str, sizeof(str), false);
sbi_printf("Standard SBI Extensions : %s\n", str);
sbi_ecall_get_extensions_str(str, sizeof(str), true);
sbi_printf("Experimental SBI Extensions : %s\n", str);
sbi_printf("\n"); sbi_printf("\n");
} }
@@ -154,7 +149,7 @@ static void sbi_boot_print_domains(struct sbi_scratch *scratch)
return; return;
/* Domain details */ /* Domain details */
sbi_domain_dump_all(" "); sbi_domain_dump_all(" ");
} }
static void sbi_boot_print_hart(struct sbi_scratch *scratch, u32 hartid) static void sbi_boot_print_hart(struct sbi_scratch *scratch, u32 hartid)
@@ -174,38 +169,38 @@ static void sbi_boot_print_hart(struct sbi_scratch *scratch, u32 hartid)
} }
/* Boot HART details */ /* Boot HART details */
sbi_printf("Boot HART ID : %u\n", hartid); sbi_printf("Boot HART ID : %u\n", hartid);
sbi_printf("Boot HART Domain : %s\n", dom->name); sbi_printf("Boot HART Domain : %s\n", dom->name);
sbi_hart_get_priv_version_str(scratch, str, sizeof(str)); sbi_hart_get_priv_version_str(scratch, str, sizeof(str));
sbi_printf("Boot HART Priv Version : %s\n", str); sbi_printf("Boot HART Priv Version : %s\n", str);
misa_string(xlen, str, sizeof(str)); misa_string(xlen, str, sizeof(str));
sbi_printf("Boot HART Base ISA : %s\n", str); sbi_printf("Boot HART Base ISA : %s\n", str);
sbi_hart_get_extensions_str(scratch, str, sizeof(str)); sbi_hart_get_extensions_str(scratch, str, sizeof(str));
sbi_printf("Boot HART ISA Extensions : %s\n", str); sbi_printf("Boot HART ISA Extensions : %s\n", str);
sbi_printf("Boot HART PMP Count : %d\n", sbi_printf("Boot HART PMP Count : %d\n",
sbi_hart_pmp_count(scratch)); sbi_hart_pmp_count(scratch));
sbi_printf("Boot HART PMP Granularity : %u bits\n", sbi_printf("Boot HART PMP Granularity : %u bits\n",
sbi_hart_pmp_log2gran(scratch)); sbi_hart_pmp_log2gran(scratch));
sbi_printf("Boot HART PMP Address Bits : %d\n", sbi_printf("Boot HART PMP Address Bits: %d\n",
sbi_hart_pmp_addrbits(scratch)); sbi_hart_pmp_addrbits(scratch));
sbi_printf("Boot HART MHPM Info : %lu (0x%08x)\n", sbi_printf("Boot HART MHPM Info : %lu (0x%08x)\n",
sbi_popcount(sbi_hart_mhpm_mask(scratch)), sbi_popcount(sbi_hart_mhpm_mask(scratch)),
sbi_hart_mhpm_mask(scratch)); sbi_hart_mhpm_mask(scratch));
sbi_printf("Boot HART Debug Triggers : %d triggers\n", sbi_printf("Boot HART Debug Triggers : %d triggers\n",
sbi_dbtr_get_total_triggers()); sbi_dbtr_get_total_triggers());
sbi_hart_delegation_dump(scratch, "Boot HART ", " "); sbi_hart_delegation_dump(scratch, "Boot HART ", " ");
} }
static unsigned long coldboot_done; static unsigned long coldboot_done;
static void wait_for_coldboot(struct sbi_scratch *scratch) static void wait_for_coldboot(struct sbi_scratch *scratch, u32 hartid)
{ {
/* Wait for coldboot to finish */ /* Wait for coldboot to finish */
while (!__smp_load_acquire(&coldboot_done)) while (!__smp_load_acquire(&coldboot_done))
cpu_relax(); cpu_relax();
} }
static void wake_coldboot_harts(struct sbi_scratch *scratch) static void wake_coldboot_harts(struct sbi_scratch *scratch, u32 hartid)
{ {
/* Mark coldboot done */ /* Mark coldboot done */
__smp_store_release(&coldboot_done, 1); __smp_store_release(&coldboot_done, 1);
@@ -246,7 +241,7 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
count = sbi_scratch_offset_ptr(scratch, entry_count_offset); count = sbi_scratch_offset_ptr(scratch, entry_count_offset);
(*count)++; (*count)++;
rc = sbi_hsm_init(scratch, true); rc = sbi_hsm_init(scratch, hartid, true);
if (rc) if (rc)
sbi_hart_hang(); sbi_hart_hang();
@@ -256,7 +251,7 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
* have these HARTs busy spin in wait_for_coldboot() until coldboot * have these HARTs busy spin in wait_for_coldboot() until coldboot
* path is completed. * path is completed.
*/ */
wake_coldboot_harts(scratch); wake_coldboot_harts(scratch, hartid);
rc = sbi_platform_early_init(plat, true); rc = sbi_platform_early_init(plat, true);
if (rc) if (rc)
@@ -316,11 +311,6 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
sbi_hart_hang(); sbi_hart_hang();
} }
rc = sbi_mpxy_init(scratch);
if (rc) {
sbi_printf("%s: mpxy init failed (error %d)\n", __func__, rc);
sbi_hart_hang();
}
/* /*
* Note: Finalize domains after HSM initialization so that we * Note: Finalize domains after HSM initialization so that we
* can startup non-root domains. * can startup non-root domains.
@@ -396,7 +386,7 @@ static void __noreturn init_warm_startup(struct sbi_scratch *scratch,
(*count)++; (*count)++;
/* Note: This has to be first thing in warmboot init sequence */ /* Note: This has to be first thing in warmboot init sequence */
rc = sbi_hsm_init(scratch, false); rc = sbi_hsm_init(scratch, hartid, false);
if (rc) if (rc)
sbi_hart_hang(); sbi_hart_hang();
@@ -480,7 +470,7 @@ static void __noreturn init_warmboot(struct sbi_scratch *scratch, u32 hartid)
{ {
int hstate; int hstate;
wait_for_coldboot(scratch); wait_for_coldboot(scratch, hartid);
hstate = sbi_hsm_hart_get_state(sbi_domain_thishart_ptr(), hartid); hstate = sbi_hsm_hart_get_state(sbi_domain_thishart_ptr(), hartid);
if (hstate < 0) if (hstate < 0)
@@ -489,7 +479,7 @@ static void __noreturn init_warmboot(struct sbi_scratch *scratch, u32 hartid)
if (hstate == SBI_HSM_STATE_SUSPENDED) { if (hstate == SBI_HSM_STATE_SUSPENDED) {
init_warm_resume(scratch, hartid); init_warm_resume(scratch, hartid);
} else { } else {
sbi_ipi_raw_clear(); sbi_ipi_raw_clear(sbi_hartid_to_hartindex(hartid));
init_warm_startup(scratch, hartid); init_warm_startup(scratch, hartid);
} }
} }
@@ -510,11 +500,21 @@ static atomic_t coldboot_lottery = ATOMIC_INITIALIZER(0);
*/ */
void __noreturn sbi_init(struct sbi_scratch *scratch) void __noreturn sbi_init(struct sbi_scratch *scratch)
{ {
u32 i, h;
bool hartid_valid = false;
bool next_mode_supported = false; bool next_mode_supported = false;
bool coldboot = false; bool coldboot = false;
u32 hartid = current_hartid(); u32 hartid = current_hartid();
const struct sbi_platform *plat = sbi_platform_ptr(scratch); const struct sbi_platform *plat = sbi_platform_ptr(scratch);
for (i = 0; i < plat->hart_count; i++) {
h = (plat->hart_index2id) ? plat->hart_index2id[i] : i;
if (h == hartid)
hartid_valid = true;
}
if (!hartid_valid)
sbi_hart_hang();
switch (scratch->next_mode) { switch (scratch->next_mode) {
case PRV_M: case PRV_M:
next_mode_supported = true; next_mode_supported = true;
@@ -561,7 +561,7 @@ void __noreturn sbi_init(struct sbi_scratch *scratch)
init_warmboot(scratch, hartid); init_warmboot(scratch, hartid);
} }
unsigned long sbi_entry_count(u32 hartindex) unsigned long sbi_entry_count(u32 hartid)
{ {
struct sbi_scratch *scratch; struct sbi_scratch *scratch;
unsigned long *entry_count; unsigned long *entry_count;
@@ -569,7 +569,7 @@ unsigned long sbi_entry_count(u32 hartindex)
if (!entry_count_offset) if (!entry_count_offset)
return 0; return 0;
scratch = sbi_hartindex_to_scratch(hartindex); scratch = sbi_hartid_to_scratch(hartid);
if (!scratch) if (!scratch)
return 0; return 0;
@@ -578,7 +578,7 @@ unsigned long sbi_entry_count(u32 hartindex)
return *entry_count; return *entry_count;
} }
unsigned long sbi_init_count(u32 hartindex) unsigned long sbi_init_count(u32 hartid)
{ {
struct sbi_scratch *scratch; struct sbi_scratch *scratch;
unsigned long *init_count; unsigned long *init_count;
@@ -586,7 +586,7 @@ unsigned long sbi_init_count(u32 hartindex)
if (!init_count_offset) if (!init_count_offset)
return 0; return 0;
scratch = sbi_hartindex_to_scratch(hartindex); scratch = sbi_hartid_to_scratch(hartid);
if (!scratch) if (!scratch)
return 0; return 0;

View File

@@ -111,25 +111,31 @@ int sbi_ipi_send_many(ulong hmask, ulong hbase, u32 event, void *data)
{ {
int rc = 0; int rc = 0;
bool retry_needed; bool retry_needed;
ulong i; ulong i, m;
struct sbi_hartmask target_mask; struct sbi_hartmask target_mask = {0};
struct sbi_domain *dom = sbi_domain_thishart_ptr(); struct sbi_domain *dom = sbi_domain_thishart_ptr();
struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
/* Find the target harts */ /* Find the target harts */
rc = sbi_hsm_hart_interruptible_mask(dom, &target_mask);
if (rc)
return rc;
if (hbase != -1UL) { if (hbase != -1UL) {
struct sbi_hartmask tmp_mask = { 0 }; rc = sbi_hsm_hart_interruptible_mask(dom, hbase, &m);
if (rc)
return rc;
m &= hmask;
for (i = hbase; hmask; i++, hmask >>= 1) { for (i = hbase; m; i++, m >>= 1) {
if (hmask & 1UL) if (m & 1UL)
sbi_hartmask_set_hartid(i, &tmp_mask); sbi_hartmask_set_hartid(i, &target_mask);
}
} else {
hbase = 0;
while (!sbi_hsm_hart_interruptible_mask(dom, hbase, &m)) {
for (i = hbase; m; i++, m >>= 1) {
if (m & 1UL)
sbi_hartmask_set_hartid(i, &target_mask);
}
hbase += BITS_PER_LONG;
} }
sbi_hartmask_and(&target_mask, &target_mask, &tmp_mask);
} }
/* Send IPIs */ /* Send IPIs */
@@ -202,15 +208,6 @@ void sbi_ipi_clear_smode(void)
csr_clear(CSR_MIP, MIP_SSIP); csr_clear(CSR_MIP, MIP_SSIP);
} }
static int sbi_ipi_update_halt(struct sbi_scratch *scratch,
struct sbi_scratch *remote_scratch,
u32 remote_hartindex, void *data)
{
/* Never send a halt IPI to the local hart. */
return scratch == remote_scratch ?
SBI_IPI_UPDATE_BREAK : SBI_IPI_UPDATE_SUCCESS;
}
static void sbi_ipi_process_halt(struct sbi_scratch *scratch) static void sbi_ipi_process_halt(struct sbi_scratch *scratch)
{ {
sbi_hsm_hart_stop(scratch, true); sbi_hsm_hart_stop(scratch, true);
@@ -218,7 +215,6 @@ static void sbi_ipi_process_halt(struct sbi_scratch *scratch)
static struct sbi_ipi_event_ops ipi_halt_ops = { static struct sbi_ipi_event_ops ipi_halt_ops = {
.name = "IPI_HALT", .name = "IPI_HALT",
.update = sbi_ipi_update_halt,
.process = sbi_ipi_process_halt, .process = sbi_ipi_process_halt,
}; };
@@ -237,9 +233,10 @@ void sbi_ipi_process(void)
struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
struct sbi_ipi_data *ipi_data = struct sbi_ipi_data *ipi_data =
sbi_scratch_offset_ptr(scratch, ipi_data_off); sbi_scratch_offset_ptr(scratch, ipi_data_off);
u32 hartindex = sbi_hartid_to_hartindex(current_hartid());
sbi_pmu_ctr_incr_fw(SBI_PMU_FW_IPI_RECVD); sbi_pmu_ctr_incr_fw(SBI_PMU_FW_IPI_RECVD);
sbi_ipi_raw_clear(); sbi_ipi_raw_clear(hartindex);
ipi_type = atomic_raw_xchg_ulong(&ipi_data->ipi_type, 0); ipi_type = atomic_raw_xchg_ulong(&ipi_data->ipi_type, 0);
ipi_event = 0; ipi_event = 0;
@@ -274,10 +271,10 @@ int sbi_ipi_raw_send(u32 hartindex)
return 0; return 0;
} }
void sbi_ipi_raw_clear(void) void sbi_ipi_raw_clear(u32 hartindex)
{ {
if (ipi_dev && ipi_dev->ipi_clear) if (ipi_dev && ipi_dev->ipi_clear)
ipi_dev->ipi_clear(); ipi_dev->ipi_clear(hartindex);
/* /*
* Ensure that memory or MMIO writes after this * Ensure that memory or MMIO writes after this
@@ -321,11 +318,6 @@ int sbi_ipi_init(struct sbi_scratch *scratch, bool cold_boot)
if (ret < 0) if (ret < 0)
return ret; return ret;
ipi_halt_event = ret; ipi_halt_event = ret;
/* Initialize platform IPI support */
ret = sbi_platform_ipi_init(sbi_platform_ptr(scratch));
if (ret)
return ret;
} else { } else {
if (!ipi_data_off) if (!ipi_data_off)
return SBI_ENOMEM; return SBI_ENOMEM;
@@ -337,8 +329,13 @@ int sbi_ipi_init(struct sbi_scratch *scratch, bool cold_boot)
ipi_data = sbi_scratch_offset_ptr(scratch, ipi_data_off); ipi_data = sbi_scratch_offset_ptr(scratch, ipi_data_off);
ipi_data->ipi_type = 0x00; ipi_data->ipi_type = 0x00;
/* Clear any pending IPIs for the current hart */ /*
sbi_ipi_raw_clear(); * Initialize platform IPI support. This will also clear any
* pending IPIs for current/calling HART.
*/
ret = sbi_platform_ipi_init(sbi_platform_ptr(scratch), cold_boot);
if (ret)
return ret;
/* Enable software interrupts */ /* Enable software interrupts */
csr_set(CSR_MIE, MIP_MSIP); csr_set(CSR_MIE, MIP_MSIP);
@@ -353,4 +350,7 @@ void sbi_ipi_exit(struct sbi_scratch *scratch)
/* Process pending IPIs */ /* Process pending IPIs */
sbi_ipi_process(); sbi_ipi_process();
/* Platform exit */
sbi_platform_ipi_exit(sbi_platform_ptr(scratch));
} }

View File

@@ -8,11 +8,8 @@
*/ */
#include <sbi/sbi_irqchip.h> #include <sbi/sbi_irqchip.h>
#include <sbi/sbi_list.h>
#include <sbi/sbi_platform.h> #include <sbi/sbi_platform.h>
static SBI_LIST_HEAD(irqchip_list);
static int default_irqfn(void) static int default_irqfn(void)
{ {
return SBI_ENODEV; return SBI_ENODEV;
@@ -20,38 +17,25 @@ static int default_irqfn(void)
static int (*ext_irqfn)(void) = default_irqfn; static int (*ext_irqfn)(void) = default_irqfn;
void sbi_irqchip_set_irqfn(int (*fn)(void))
{
if (fn)
ext_irqfn = fn;
}
int sbi_irqchip_process(void) int sbi_irqchip_process(void)
{ {
return ext_irqfn(); return ext_irqfn();
} }
void sbi_irqchip_add_device(struct sbi_irqchip_device *dev)
{
sbi_list_add_tail(&dev->node, &irqchip_list);
if (dev->irq_handle)
ext_irqfn = dev->irq_handle;
}
int sbi_irqchip_init(struct sbi_scratch *scratch, bool cold_boot) int sbi_irqchip_init(struct sbi_scratch *scratch, bool cold_boot)
{ {
int rc; int rc;
const struct sbi_platform *plat = sbi_platform_ptr(scratch); const struct sbi_platform *plat = sbi_platform_ptr(scratch);
struct sbi_irqchip_device *dev;
if (cold_boot) { rc = sbi_platform_irqchip_init(plat, cold_boot);
rc = sbi_platform_irqchip_init(plat); if (rc)
if (rc) return rc;
return rc;
}
sbi_list_for_each_entry(dev, &irqchip_list, node) {
if (!dev->warm_init)
continue;
rc = dev->warm_init(dev);
if (rc)
return rc;
}
if (ext_irqfn != default_irqfn) if (ext_irqfn != default_irqfn)
csr_set(CSR_MIE, MIP_MEIP); csr_set(CSR_MIE, MIP_MEIP);
@@ -61,6 +45,10 @@ int sbi_irqchip_init(struct sbi_scratch *scratch, bool cold_boot)
void sbi_irqchip_exit(struct sbi_scratch *scratch) void sbi_irqchip_exit(struct sbi_scratch *scratch)
{ {
const struct sbi_platform *plat = sbi_platform_ptr(scratch);
if (ext_irqfn != default_irqfn) if (ext_irqfn != default_irqfn)
csr_clear(CSR_MIE, MIP_MEIP); csr_clear(CSR_MIE, MIP_MEIP);
sbi_platform_irqchip_exit(plat);
} }

View File

@@ -1,698 +0,0 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2024 Ventana Micro Systems Inc.
*
* Authors:
* Rahul Pathak <rpathak@ventanamicro.com>
*/
#include <sbi/riscv_asm.h>
#include <sbi/sbi_domain.h>
#include <sbi/sbi_error.h>
#include <sbi/sbi_hart.h>
#include <sbi/sbi_platform.h>
#include <sbi/sbi_mpxy.h>
#include <sbi/sbi_scratch.h>
#include <sbi/sbi_string.h>
#include <sbi/sbi_bitops.h>
#include <sbi/sbi_console.h>
#include <sbi/sbi_byteorder.h>
/** Offset of pointer to MPXY state in scratch space */
static unsigned long mpxy_state_offset;
/** List of MPXY proxy channels */
static SBI_LIST_HEAD(mpxy_channel_list);
/** Invalid Physical Address(all bits 1) */
#define INVALID_ADDR (-1U)
/** MPXY Attribute size in bytes */
#define ATTR_SIZE (4)
/** Channel Capability - MSI */
#define CAP_MSI_POS 0
#define CAP_MSI_MASK (1U << CAP_MSI_POS)
/** Channel Capability - SSE */
#define CAP_SSE_POS 1
#define CAP_SSE_MASK (1U << CAP_SSE_POS)
/** Channel Capability - Events State */
#define CAP_EVENTSSTATE_POS 2
#define CAP_EVENTSSTATE_MASK (1U << CAP_EVENTSSTATE_POS)
/** Channel Capability - Get Notification function support */
#define CAP_GET_NOTIFICATIONS_POS 3
#define CAP_GET_NOTIFICATIONS_MASK (1U << CAP_GET_NOTIFICATIONS_POS)
/** Channel Capability - Send Message Without Response function support */
#define CAP_SEND_MSG_WITHOUT_RESP_POS 4
#define CAP_SEND_MSG_WITHOUT_RESP_MASK (1U << CAP_SEND_MSG_WITHOUT_RESP_POS)
/** Channel Capability - Send Message With Response function support */
#define CAP_SEND_MSG_WITH_RESP_POS 5
#define CAP_SEND_MSG_WITH_RESP_MASK (1U << CAP_SEND_MSG_WITH_RESP_POS)
/** Helpers to enable/disable channel capability bits
* _c: capability variable
* _m: capability mask
*/
#define CAP_ENABLE(_c, _m) INSERT_FIELD(_c, _m, 1)
#define CAP_DISABLE(_c, _m) INSERT_FIELD(_c, _m, 0)
#define CAP_GET(_c, _m) EXTRACT_FIELD(_c, _m)
#if __riscv_xlen == 64
#define SHMEM_PHYS_ADDR(_hi, _lo) (_lo)
#elif __riscv_xlen == 32
#define SHMEM_PHYS_ADDR(_hi, _lo) (((u64)(_hi) << 32) | (_lo))
#else
#error "Undefined XLEN"
#endif
/** Per hart shared memory */
struct mpxy_shmem {
unsigned long shmem_size;
unsigned long shmem_addr_lo;
unsigned long shmem_addr_hi;
};
struct mpxy_state {
/* MSI support in MPXY */
bool msi_avail;
/* SSE support in MPXY */
bool sse_avail;
/* MPXY Shared memory details */
struct mpxy_shmem shmem;
};
/** Disable hart shared memory */
static inline void sbi_mpxy_shmem_disable(struct mpxy_state *ms)
{
ms->shmem.shmem_size = 0;
ms->shmem.shmem_addr_lo = INVALID_ADDR;
ms->shmem.shmem_addr_hi = INVALID_ADDR;
}
/** Check if shared memory is already setup on hart */
static inline bool mpxy_shmem_enabled(struct mpxy_state *ms)
{
return (ms->shmem.shmem_addr_lo == INVALID_ADDR
&& ms->shmem.shmem_addr_hi == INVALID_ADDR) ?
false : true;
}
/** Get hart shared memory base address */
static inline void *hart_shmem_base(struct mpxy_state *ms)
{
return (void *)(unsigned long)SHMEM_PHYS_ADDR(ms->shmem.shmem_addr_hi,
ms->shmem.shmem_addr_lo);
}
/** Make sure all attributes are packed for direct memcpy in ATTR_READ */
#define assert_field_offset(field, attr_offset) \
_Static_assert( \
((offsetof(struct sbi_mpxy_channel_attrs, field)) / \
sizeof(u32)) == attr_offset, \
"field " #field \
" from struct sbi_mpxy_channel_attrs invalid offset, expected " #attr_offset)
assert_field_offset(msg_proto_id, SBI_MPXY_ATTR_MSG_PROT_ID);
assert_field_offset(msg_proto_version, SBI_MPXY_ATTR_MSG_PROT_VER);
assert_field_offset(msg_data_maxlen, SBI_MPXY_ATTR_MSG_MAX_LEN);
assert_field_offset(msg_send_timeout, SBI_MPXY_ATTR_MSG_SEND_TIMEOUT);
assert_field_offset(msg_completion_timeout, SBI_MPXY_ATTR_MSG_COMPLETION_TIMEOUT);
assert_field_offset(capability, SBI_MPXY_ATTR_CHANNEL_CAPABILITY);
assert_field_offset(sse_event_id, SBI_MPXY_ATTR_SSE_EVENT_ID);
assert_field_offset(msi_control, SBI_MPXY_ATTR_MSI_CONTROL);
assert_field_offset(msi_info.msi_addr_lo, SBI_MPXY_ATTR_MSI_ADDR_LO);
assert_field_offset(msi_info.msi_addr_hi, SBI_MPXY_ATTR_MSI_ADDR_HI);
assert_field_offset(msi_info.msi_data, SBI_MPXY_ATTR_MSI_DATA);
assert_field_offset(eventsstate_ctrl, SBI_MPXY_ATTR_EVENTS_STATE_CONTROL);
/**
* Check if the attribute is a standard attribute or
* a message protocol specific attribute
* attr_id[31] = 0 for standard
* attr_id[31] = 1 for message protocol specific
*/
static inline bool mpxy_is_std_attr(u32 attr_id)
{
return (attr_id >> 31) ? false : true;
}
/** Find channel_id in registered channels list */
static struct sbi_mpxy_channel *mpxy_find_channel(u32 channel_id)
{
struct sbi_mpxy_channel *channel;
sbi_list_for_each_entry(channel, &mpxy_channel_list, head)
if (channel->channel_id == channel_id)
return channel;
return NULL;
}
/** Copy attributes word size */
static void mpxy_copy_std_attrs(u32 *outmem, u32 *inmem, u32 count)
{
int idx;
for (idx = 0; idx < count; idx++)
outmem[idx] = cpu_to_le32(inmem[idx]);
}
/** Check if any channel is registered with mpxy framework */
bool sbi_mpxy_channel_available(void)
{
return sbi_list_empty(&mpxy_channel_list) ? false : true;
}
static void mpxy_std_attrs_init(struct sbi_mpxy_channel *channel)
{
u32 capability = 0;
struct mpxy_state *ms =
sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
/* Reset values */
channel->attrs.msi_control = 0;
channel->attrs.msi_info.msi_data = 0;
channel->attrs.msi_info.msi_addr_lo = 0;
channel->attrs.msi_info.msi_addr_hi = 0;
channel->attrs.capability = 0;
channel->attrs.eventsstate_ctrl = 0;
if (channel->send_message_with_response)
capability = CAP_ENABLE(capability, CAP_SEND_MSG_WITH_RESP_MASK);
if (channel->send_message_without_response)
capability = CAP_ENABLE(capability, CAP_SEND_MSG_WITHOUT_RESP_MASK);
if (channel->get_notification_events) {
capability = CAP_ENABLE(capability, CAP_GET_NOTIFICATIONS_MASK);
/**
* Check if MSI or SSE available for notification interrrupt.
* Priority given to MSI if both MSI and SSE are avaialble.
*/
if (ms->msi_avail)
capability = CAP_ENABLE(capability, CAP_MSI_MASK);
else if (ms->sse_avail) {
capability = CAP_ENABLE(capability, CAP_SSE_MASK);
/* TODO: Assign SSE EVENT_ID for the channel */
}
/**
* switch_eventstate callback support means support for events
* state reporting supoprt. Enable events state reporting in
* channel capability.
*/
if (channel->switch_eventsstate)
capability = CAP_ENABLE(capability, CAP_EVENTSSTATE_MASK);
}
channel->attrs.capability = capability;
}
/**
* Register a channel with MPXY framework.
* Called by message protocol drivers
*/
int sbi_mpxy_register_channel(struct sbi_mpxy_channel *channel)
{
if (!channel)
return SBI_EINVAL;
if (mpxy_find_channel(channel->channel_id))
return SBI_EALREADY;
/* Initialize channel specific attributes */
mpxy_std_attrs_init(channel);
SBI_INIT_LIST_HEAD(&channel->head);
sbi_list_add_tail(&channel->head, &mpxy_channel_list);
return SBI_OK;
}
int sbi_mpxy_init(struct sbi_scratch *scratch)
{
mpxy_state_offset = sbi_scratch_alloc_type_offset(struct mpxy_state);
if (!mpxy_state_offset)
return SBI_ENOMEM;
/**
* TODO: Proper support for checking msi support from platform.
* Currently disable msi and sse and use polling
*/
struct mpxy_state *ms =
sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
ms->msi_avail = false;
ms->sse_avail = false;
sbi_mpxy_shmem_disable(ms);
return sbi_platform_mpxy_init(sbi_platform_ptr(scratch));
}
int sbi_mpxy_set_shmem(unsigned long shmem_size, unsigned long shmem_phys_lo,
unsigned long shmem_phys_hi, unsigned long flags)
{
struct mpxy_state *ms =
sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
unsigned long *ret_buf;
/** Disable shared memory if both hi and lo have all bit 1s */
if (shmem_phys_lo == INVALID_ADDR &&
shmem_phys_hi == INVALID_ADDR) {
sbi_mpxy_shmem_disable(ms);
return SBI_SUCCESS;
}
if (flags >= SBI_EXT_MPXY_SHMEM_FLAG_MAX_IDX)
return SBI_ERR_INVALID_PARAM;
/** Check shared memory size and address aligned to 4K Page */
if (!shmem_size || (shmem_size & ~PAGE_MASK) ||
(shmem_phys_lo & ~PAGE_MASK))
return SBI_ERR_INVALID_PARAM;
if (!sbi_domain_check_addr_range(sbi_domain_thishart_ptr(),
SHMEM_PHYS_ADDR(shmem_phys_hi, shmem_phys_lo),
shmem_size, PRV_S,
SBI_DOMAIN_READ | SBI_DOMAIN_WRITE))
return SBI_ERR_INVALID_ADDRESS;
/** Save the current shmem details in new shmem region */
if (flags == SBI_EXT_MPXY_SHMEM_FLAG_OVERWRITE_RETURN) {
ret_buf = (unsigned long *)(ulong)SHMEM_PHYS_ADDR(shmem_phys_hi,
shmem_phys_lo);
sbi_hart_map_saddr((unsigned long)ret_buf, shmem_size);
ret_buf[0] = cpu_to_lle(ms->shmem.shmem_size);
ret_buf[1] = cpu_to_lle(ms->shmem.shmem_addr_lo);
ret_buf[2] = cpu_to_lle(ms->shmem.shmem_addr_hi);
sbi_hart_unmap_saddr();
}
/** Setup the new shared memory */
ms->shmem.shmem_size = shmem_size;
ms->shmem.shmem_addr_lo = shmem_phys_lo;
ms->shmem.shmem_addr_hi = shmem_phys_hi;
return SBI_SUCCESS;
}
int sbi_mpxy_get_channel_ids(u32 start_index)
{
u32 node_index = 0, node_ret = 0;
u32 remaining, returned, max_channelids;
u32 channels_count = 0;
u32 *shmem_base;
struct sbi_mpxy_channel *channel;
/* Check if the shared memory is being setup or not. */
struct mpxy_state *ms =
sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
if (!mpxy_shmem_enabled(ms))
return SBI_ERR_NO_SHMEM;
sbi_list_for_each_entry(channel, &mpxy_channel_list, head)
channels_count += 1;
if (start_index > channels_count)
return SBI_ERR_INVALID_PARAM;
shmem_base = hart_shmem_base(ms);
sbi_hart_map_saddr((unsigned long)hart_shmem_base(ms),
ms->shmem.shmem_size);
/** number of channel ids which can be stored in shmem adjusting
* for remaining and returned fields */
max_channelids = (ms->shmem.shmem_size / sizeof(u32)) - 2;
/* total remaining from the start index */
remaining = channels_count - start_index;
/* how many can be returned */
returned = (remaining > max_channelids)? max_channelids : remaining;
// Iterate over the list of channels to get the channel ids.
sbi_list_for_each_entry(channel, &mpxy_channel_list, head) {
if (node_index >= start_index &&
node_index < (start_index + returned)) {
shmem_base[2 + node_ret] = cpu_to_le32(channel->channel_id);
node_ret += 1;
}
node_index += 1;
}
/* final remaininig channel ids */
remaining = channels_count - (start_index + returned);
shmem_base[0] = cpu_to_le32(remaining);
shmem_base[1] = cpu_to_le32(returned);
sbi_hart_unmap_saddr();
return SBI_SUCCESS;
}
int sbi_mpxy_read_attrs(u32 channel_id, u32 base_attr_id, u32 attr_count)
{
int ret = SBI_SUCCESS;
u32 *attr_ptr, end_id;
void *shmem_base;
struct mpxy_state *ms =
sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
if (!mpxy_shmem_enabled(ms))
return SBI_ERR_NO_SHMEM;
struct sbi_mpxy_channel *channel = mpxy_find_channel(channel_id);
if (!channel)
return SBI_ERR_NOT_SUPPORTED;
/* base attribute id is not a defined std attribute or reserved */
if (base_attr_id >= SBI_MPXY_ATTR_STD_ATTR_MAX_IDX &&
base_attr_id < SBI_MPXY_ATTR_MSGPROTO_ATTR_START)
return SBI_ERR_INVALID_PARAM;
/* Sanity check for base_attr_id and attr_count */
if (!attr_count || (attr_count > (ms->shmem.shmem_size / ATTR_SIZE)))
return SBI_ERR_INVALID_PARAM;
shmem_base = hart_shmem_base(ms);
end_id = base_attr_id + attr_count - 1;
sbi_hart_map_saddr((unsigned long)hart_shmem_base(ms),
ms->shmem.shmem_size);
/* Standard attributes range check */
if (mpxy_is_std_attr(base_attr_id)) {
if (end_id >= SBI_MPXY_ATTR_STD_ATTR_MAX_IDX) {
ret = SBI_EBAD_RANGE;
goto out;
}
attr_ptr = (u32 *)&channel->attrs;
mpxy_copy_std_attrs((u32 *)shmem_base, &attr_ptr[base_attr_id],
attr_count);
} else {
/**
* Even if the message protocol driver does not provide
* read attribute callback, return bad range error instead
* of not supported to let client distinguish it from channel
* id not supported.
* Check the complate range supported for message protocol
* attributes. Actual supported attributes will be checked
* by the message protocol driver.
*/
if (!channel->read_attributes ||
end_id > SBI_MPXY_ATTR_MSGPROTO_ATTR_END) {
ret = SBI_ERR_BAD_RANGE;
goto out;
}
/**
* Function expected to return the SBI supported errors
* At this point both base attribute id and only the mpxy
* supported range been verified. Platform callback must
* check if the range requested is supported by message
* protocol driver */
ret = channel->read_attributes(channel,
(u32 *)shmem_base,
base_attr_id, attr_count);
}
out:
sbi_hart_unmap_saddr();
return ret;
}
/**
* Verify the channel standard attribute wrt to write permission
* and the value to be set if valid or not.
* Only attributes needs to be checked which are defined Read/Write
* permission. Other with Readonly permission will result in error.
*
* Attributes values to be written must also be checked because
* before writing a range of attributes, we need to make sure that
* either complete range of attributes is written successfully or not
* at all.
*/
static int mpxy_check_write_std_attr(struct sbi_mpxy_channel *channel,
u32 attr_id, u32 attr_val)
{
int ret = SBI_SUCCESS;
struct sbi_mpxy_channel_attrs *attrs = &channel->attrs;
switch(attr_id) {
case SBI_MPXY_ATTR_MSI_CONTROL:
if (attr_val > 1)
ret = SBI_ERR_INVALID_PARAM;
if (attr_val == 1 &&
(attrs->msi_info.msi_addr_lo == INVALID_ADDR) &&
(attrs->msi_info.msi_addr_hi == INVALID_ADDR))
ret = SBI_ERR_DENIED;
break;
case SBI_MPXY_ATTR_MSI_ADDR_LO:
case SBI_MPXY_ATTR_MSI_ADDR_HI:
case SBI_MPXY_ATTR_MSI_DATA:
ret = SBI_SUCCESS;
break;
case SBI_MPXY_ATTR_EVENTS_STATE_CONTROL:
if (attr_val > 1)
ret = SBI_ERR_INVALID_PARAM;
break;
default:
/** All RO access attributes falls under default */
ret = SBI_ERR_BAD_RANGE;
};
return ret;
}
/**
* Write the attribute value
*/
static void mpxy_write_std_attr(struct sbi_mpxy_channel *channel, u32 attr_id,
u32 attr_val)
{
struct mpxy_state *ms =
sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
struct sbi_mpxy_channel_attrs *attrs = &channel->attrs;
switch(attr_id) {
case SBI_MPXY_ATTR_MSI_CONTROL:
if (ms->msi_avail && attr_val <= 1)
attrs->msi_control = attr_val;
break;
case SBI_MPXY_ATTR_MSI_ADDR_LO:
if (ms->msi_avail)
attrs->msi_info.msi_addr_lo = attr_val;
break;
case SBI_MPXY_ATTR_MSI_ADDR_HI:
if (ms->msi_avail)
attrs->msi_info.msi_addr_hi = attr_val;
break;
case SBI_MPXY_ATTR_MSI_DATA:
if (ms->msi_avail)
attrs->msi_info.msi_data = attr_val;
break;
case SBI_MPXY_ATTR_EVENTS_STATE_CONTROL:
if (channel->switch_eventsstate && attr_val <= 1) {
attrs->eventsstate_ctrl = attr_val;
/* message protocol callback to enable/disable
* events state reporting. */
channel->switch_eventsstate(attr_val);
}
break;
};
}
int sbi_mpxy_write_attrs(u32 channel_id, u32 base_attr_id, u32 attr_count)
{
int ret, mem_idx;
void *shmem_base;
u32 *mem_ptr, attr_id, end_id, attr_val;
struct mpxy_state *ms =
sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
if (!mpxy_shmem_enabled(ms))
return SBI_ERR_NO_SHMEM;
struct sbi_mpxy_channel *channel = mpxy_find_channel(channel_id);
if (!channel)
return SBI_ERR_NOT_SUPPORTED;
/* base attribute id is not a defined std attribute or reserved */
if (base_attr_id >= SBI_MPXY_ATTR_STD_ATTR_MAX_IDX &&
base_attr_id < SBI_MPXY_ATTR_MSGPROTO_ATTR_START)
return SBI_ERR_INVALID_PARAM;
/* Sanity check for base_attr_id and attr_count */
if (!attr_count || (attr_count > (ms->shmem.shmem_size / ATTR_SIZE)))
return SBI_ERR_INVALID_PARAM;
shmem_base = hart_shmem_base(ms);
end_id = base_attr_id + attr_count - 1;
sbi_hart_map_saddr((unsigned long)shmem_base, ms->shmem.shmem_size);
mem_ptr = (u32 *)shmem_base;
if (mpxy_is_std_attr(base_attr_id)) {
if (end_id >= SBI_MPXY_ATTR_STD_ATTR_MAX_IDX) {
ret = SBI_ERR_BAD_RANGE;
goto out;
}
/** Verify the attribute ids range and values */
mem_idx = 0;
for (attr_id = base_attr_id; attr_id <= end_id; attr_id++) {
attr_val = le32_to_cpu(mem_ptr[mem_idx++]);
ret = mpxy_check_write_std_attr(channel,
attr_id, attr_val);
if (ret)
goto out;
}
/* Write the attribute ids values */
mem_idx = 0;
for (attr_id = base_attr_id; attr_id <= end_id; attr_id++) {
attr_val = le32_to_cpu(mem_ptr[mem_idx++]);
mpxy_write_std_attr(channel, attr_id, attr_val);
}
} else {/**
* Message protocol specific attributes:
* If attributes belong to message protocol, they
* are simply passed to the message protocol driver
* callback after checking the valid range.
* Attributes contiguous range & permission & other checks
* are done by the mpxy and message protocol glue layer.
*/
/**
* Even if the message protocol driver does not provide
* write attribute callback, return bad range error instead
* of not supported to let client distinguish it from channel
* id not supported.
*/
if (!channel->write_attributes ||
end_id > SBI_MPXY_ATTR_MSGPROTO_ATTR_END) {
ret = SBI_ERR_BAD_RANGE;
goto out;
}
/**
* Function expected to return the SBI supported errors
* At this point both base attribute id and only the mpxy
* supported range been verified. Platform callback must
* check if the range requested is supported by message
* protocol driver */
ret = channel->write_attributes(channel,
(u32 *)shmem_base,
base_attr_id, attr_count);
}
out:
sbi_hart_unmap_saddr();
return ret;
}
int sbi_mpxy_send_message(u32 channel_id, u8 msg_id,
unsigned long msg_data_len,
unsigned long *resp_data_len)
{
int ret;
void *shmem_base, *resp_buf;
u32 resp_bufsize;
struct mpxy_state *ms =
sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
if (!mpxy_shmem_enabled(ms))
return SBI_ERR_NO_SHMEM;
struct sbi_mpxy_channel *channel = mpxy_find_channel(channel_id);
if (!channel)
return SBI_ERR_NOT_SUPPORTED;
if (resp_data_len && !channel->send_message_with_response)
return SBI_ERR_NOT_SUPPORTED;
if (!resp_data_len && !channel->send_message_without_response)
return SBI_ERR_NOT_SUPPORTED;
if (msg_data_len > ms->shmem.shmem_size ||
msg_data_len > channel->attrs.msg_data_maxlen)
return SBI_ERR_INVALID_PARAM;
shmem_base = hart_shmem_base(ms);
sbi_hart_map_saddr((unsigned long)shmem_base, ms->shmem.shmem_size);
if (resp_data_len) {
resp_buf = shmem_base;
resp_bufsize = ms->shmem.shmem_size;
ret = channel->send_message_with_response(channel, msg_id,
shmem_base,
msg_data_len,
resp_buf,
resp_bufsize,
resp_data_len);
}
else {
ret = channel->send_message_without_response(channel, msg_id,
shmem_base,
msg_data_len);
}
sbi_hart_unmap_saddr();
if (ret == SBI_ERR_TIMEOUT || ret == SBI_ERR_IO)
return ret;
else if (ret)
return SBI_ERR_FAILED;
if (resp_data_len &&
(*resp_data_len > ms->shmem.shmem_size ||
*resp_data_len > channel->attrs.msg_data_maxlen))
return SBI_ERR_FAILED;
return SBI_SUCCESS;
}
int sbi_mpxy_get_notification_events(u32 channel_id, unsigned long *events_len)
{
int ret;
void *eventsbuf, *shmem_base;
struct mpxy_state *ms =
sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
if (!mpxy_shmem_enabled(ms))
return SBI_ERR_NO_SHMEM;
struct sbi_mpxy_channel *channel = mpxy_find_channel(channel_id);
if (!channel)
return SBI_ERR_NOT_SUPPORTED;
if (!channel->get_notification_events)
return SBI_ERR_NOT_SUPPORTED;
shmem_base = hart_shmem_base(ms);
sbi_hart_map_saddr((unsigned long)shmem_base, ms->shmem.shmem_size);
eventsbuf = shmem_base;
ret = channel->get_notification_events(channel, eventsbuf,
ms->shmem.shmem_size,
events_len);
sbi_hart_unmap_saddr();
if (ret)
return ret;
if (*events_len > ms->shmem.shmem_size)
return SBI_ERR_FAILED;
return SBI_SUCCESS;
}

View File

@@ -10,7 +10,6 @@
#include <sbi/riscv_asm.h> #include <sbi/riscv_asm.h>
#include <sbi/sbi_bitops.h> #include <sbi/sbi_bitops.h>
#include <sbi/sbi_console.h> #include <sbi/sbi_console.h>
#include <sbi/sbi_domain.h>
#include <sbi/sbi_ecall_interface.h> #include <sbi/sbi_ecall_interface.h>
#include <sbi/sbi_hart.h> #include <sbi/sbi_hart.h>
#include <sbi/sbi_heap.h> #include <sbi/sbi_heap.h>
@@ -173,7 +172,6 @@ static int pmu_event_validate(struct sbi_pmu_hart_state *phs,
return SBI_EINVAL; return SBI_EINVAL;
break; break;
case SBI_PMU_EVENT_TYPE_HW_RAW: case SBI_PMU_EVENT_TYPE_HW_RAW:
case SBI_PMU_EVENT_TYPE_HW_RAW_V2:
event_idx_code_max = 1; // event_idx.code should be zero event_idx_code_max = 1; // event_idx.code should be zero
break; break;
default: default:
@@ -261,8 +259,7 @@ static int pmu_add_hw_event_map(u32 eidx_start, u32 eidx_end, u32 cmap,
/* Sanity check */ /* Sanity check */
for (i = 0; i < num_hw_events; i++) { for (i = 0; i < num_hw_events; i++) {
if (eidx_start == SBI_PMU_EVENT_RAW_IDX || if (eidx_start == SBI_PMU_EVENT_RAW_IDX)
eidx_start == SBI_PMU_EVENT_RAW_V2_IDX)
/* All raw events have same event idx. Just do sanity check on select */ /* All raw events have same event idx. Just do sanity check on select */
is_overlap = pmu_event_select_overlap(&hw_event_map[i], is_overlap = pmu_event_select_overlap(&hw_event_map[i],
select, select_mask); select, select_mask);
@@ -293,8 +290,8 @@ reset_event:
*/ */
int sbi_pmu_add_hw_event_counter_map(u32 eidx_start, u32 eidx_end, u32 cmap) int sbi_pmu_add_hw_event_counter_map(u32 eidx_start, u32 eidx_end, u32 cmap)
{ {
if ((eidx_start > eidx_end) || eidx_start >= SBI_PMU_EVENT_RAW_IDX || if ((eidx_start > eidx_end) || eidx_start == SBI_PMU_EVENT_RAW_IDX ||
eidx_end >= SBI_PMU_EVENT_RAW_IDX) eidx_end == SBI_PMU_EVENT_RAW_IDX)
return SBI_EINVAL; return SBI_EINVAL;
return pmu_add_hw_event_map(eidx_start, eidx_end, cmap, 0, 0); return pmu_add_hw_event_map(eidx_start, eidx_end, cmap, 0, 0);
@@ -303,7 +300,7 @@ int sbi_pmu_add_hw_event_counter_map(u32 eidx_start, u32 eidx_end, u32 cmap)
int sbi_pmu_add_raw_event_counter_map(uint64_t select, uint64_t select_mask, u32 cmap) int sbi_pmu_add_raw_event_counter_map(uint64_t select, uint64_t select_mask, u32 cmap)
{ {
return pmu_add_hw_event_map(SBI_PMU_EVENT_RAW_IDX, return pmu_add_hw_event_map(SBI_PMU_EVENT_RAW_IDX,
SBI_PMU_EVENT_RAW_V2_IDX, cmap, select, select_mask); SBI_PMU_EVENT_RAW_IDX, cmap, select, select_mask);
} }
void sbi_pmu_ovf_irq() void sbi_pmu_ovf_irq()
@@ -739,8 +736,7 @@ static int pmu_ctr_find_hw(struct sbi_pmu_hart_state *phs,
continue; continue;
/* For raw events, event data is used as the select value */ /* For raw events, event data is used as the select value */
if (event_idx == SBI_PMU_EVENT_RAW_IDX || if (event_idx == SBI_PMU_EVENT_RAW_IDX) {
event_idx == SBI_PMU_EVENT_RAW_V2_IDX) {
uint64_t select_mask = temp->select_mask; uint64_t select_mask = temp->select_mask;
/* The non-event map bits of data should match the selector */ /* The non-event map bits of data should match the selector */
@@ -796,6 +792,11 @@ static int pmu_ctr_find_fw(struct sbi_pmu_hart_state *phs,
{ {
int i, cidx; int i, cidx;
if ((event_code >= SBI_PMU_FW_MAX &&
event_code <= SBI_PMU_FW_RESERVED_MAX) ||
event_code > SBI_PMU_FW_PLATFORM)
return SBI_EINVAL;
for_each_set_bit(i, &cmask, BITS_PER_LONG) { for_each_set_bit(i, &cmask, BITS_PER_LONG) {
cidx = i + cbase; cidx = i + cbase;
if (cidx < num_hw_ctrs || total_ctrs <= cidx) if (cidx < num_hw_ctrs || total_ctrs <= cidx)
@@ -968,80 +969,6 @@ int sbi_pmu_ctr_get_info(uint32_t cidx, unsigned long *ctr_info)
return 0; return 0;
} }
int sbi_pmu_event_get_info(unsigned long shmem_phys_lo, unsigned long shmem_phys_hi,
unsigned long num_events, unsigned long flags)
{
unsigned long shmem_size = num_events * sizeof(struct sbi_pmu_event_info);
int i, j, event_type;
struct sbi_pmu_event_info *einfo;
struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr();
uint32_t event_idx;
struct sbi_pmu_hw_event *temp;
bool found = false;
if (flags != 0)
return SBI_ERR_INVALID_PARAM;
/** Check shared memory size and address aligned to 16 byte */
if (!num_events || (shmem_phys_lo & 0xF))
return SBI_ERR_INVALID_PARAM;
/*
* On RV32, the M-mode can only access the first 4GB of
* the physical address space because M-mode does not have
* MMU to access full 34-bit physical address space.
*
* Based on above, we simply fail if the upper 32bits of
* the physical address (i.e. a2 register) is non-zero on
* RV32.
*/
if (shmem_phys_hi)
return SBI_EINVALID_ADDR;
if (!sbi_domain_check_addr_range(sbi_domain_thishart_ptr(),
shmem_phys_lo, shmem_size, PRV_S,
SBI_DOMAIN_READ | SBI_DOMAIN_WRITE))
return SBI_ERR_INVALID_ADDRESS;
sbi_hart_map_saddr(shmem_phys_lo, shmem_size);
einfo = (struct sbi_pmu_event_info *)(shmem_phys_lo);
for (i = 0; i < num_events; i++) {
event_idx = einfo[i].event_idx;
event_type = pmu_event_validate(phs, event_idx, einfo[i].event_data);
if (event_type < 0) {
einfo[i].output = 0;
} else {
for (j = 0; j < num_hw_events; j++) {
temp = &hw_event_map[j];
/* For raw events, event data is used as the select value */
if (event_idx == SBI_PMU_EVENT_RAW_IDX ||
event_idx == SBI_PMU_EVENT_RAW_V2_IDX) {
/* just match the selector */
if (temp->select == (einfo[i].event_data &
temp->select_mask)) {
found = true;
break;
}
} else if (temp->start_idx <= event_idx &&
event_idx <= temp->end_idx) {
found = true;
break;
}
}
if (found)
einfo[i].output = 1;
else
einfo[i].output = 0;
found = false;
}
}
sbi_hart_unmap_saddr();
return 0;
}
static void pmu_reset_event_map(struct sbi_pmu_hart_state *phs) static void pmu_reset_event_map(struct sbi_pmu_hart_state *phs)
{ {
int j; int j;

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