mirror of
https://github.com/riscv-software-src/opensbi
synced 2025-09-14 05:56:04 +01:00
Compare commits
No commits in common. "master" and "v0.2" have entirely different histories.
@ -1,16 +0,0 @@
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignEscapedNewlines: Left
|
||||
AlignTrailingComments: true
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
BraceWrapping:
|
||||
AfterFunction: true
|
||||
BreakBeforeBraces: Custom
|
||||
BreakStringLiterals: false
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
IndentWidth: 8
|
||||
ReflowComments: false
|
||||
SortIncludes: false
|
||||
SpacesInContainerLiterals: false
|
||||
TabWidth: 8
|
||||
UseTab: Always
|
@ -1,21 +0,0 @@
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
# See here for more information about the format and editor support:
|
||||
# https://editorconfig.org/
|
||||
|
||||
root = true
|
||||
|
||||
[{*.{c,dts,h,lds,ldS,mk,s,S},Kconfig,Makefile,Makefile.*}]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
|
||||
[*.py]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
26
.github/workflows/repo-lockdown.yml
vendored
26
.github/workflows/repo-lockdown.yml
vendored
@ -1,26 +0,0 @@
|
||||
name: 'Repo Lockdown'
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: opened
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
action:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/repo-lockdown@v4
|
||||
with:
|
||||
pr-comment: |
|
||||
We have mailing list based patch review so it would be great if you can send these patchs to OpenSBI mailing list.
|
||||
|
||||
You need to join OpenSBI mailing list using following link
|
||||
http://lists.infradead.org/mailman/listinfo/opensbi
|
||||
|
||||
Make sure you use "git send-email" to send the patches.
|
||||
|
||||
Thanks for your contribution to OpenSBI project.
|
||||
lock-pr: true
|
||||
close-pr: true
|
14
.gitignore
vendored
14
.gitignore
vendored
@ -1,12 +1,3 @@
|
||||
# ignore anything begin with dot
|
||||
.*
|
||||
|
||||
# exceptions we need even begin with dot
|
||||
!.clang-format
|
||||
!.gitignore
|
||||
!.github
|
||||
!.editorconfig
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.a
|
||||
@ -15,8 +6,3 @@
|
||||
#Build & install directories
|
||||
build/
|
||||
install/
|
||||
|
||||
# Development friendly files
|
||||
tags
|
||||
cscope*
|
||||
*~
|
||||
|
@ -1,27 +0,0 @@
|
||||
|
||||
List of OpenSBI Contributors (Alphabetically sorted)
|
||||
====================================================
|
||||
|
||||
* **[Western Digital Corporation](https://www.wdc.com/)**
|
||||
* Project initiator and maintainer
|
||||
* Copyright (c) 2019 Western Digital Corporation or its affiliates
|
||||
|
||||
* Alistair Francis <alistair@alistair23.me>
|
||||
|
||||
* Andreas Schwab <schwab@suse.de>
|
||||
|
||||
* Anup Patel <anup.patel@wdc.com>
|
||||
|
||||
* Atish Patra <atish.patra@wdc.com>
|
||||
|
||||
* Bin Meng <bmeng.cn@gmail.com>
|
||||
|
||||
* Damien Le Moal <damien.lemoal@wdc.com>
|
||||
|
||||
* Karsten Merker <merker@debian.org>
|
||||
|
||||
* Nick Kossifidis <mickflemm@gmail.com>
|
||||
|
||||
* Shawn Chang <citypw@gmail.com>
|
||||
|
||||
* Xiang Wang <wxjstz@126.com>
|
@ -1,8 +1,7 @@
|
||||
The 2-Clause BSD License
|
||||
SPDX short identifier: BSD-2-Clause
|
||||
|
||||
Copyright (c) 2019 Western Digital Corporation or its affiliates and other
|
||||
contributors.
|
||||
Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
@ -23,3 +22,4 @@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
25
Kconfig
25
Kconfig
@ -1,25 +0,0 @@
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
mainmenu "OpenSBI $(OPENSBI_PLATFORM) Configuration"
|
||||
|
||||
config OPENSBI_SRC_DIR
|
||||
string
|
||||
option env="OPENSBI_SRC_DIR"
|
||||
|
||||
config OPENSBI_PLATFORM
|
||||
string
|
||||
option env="OPENSBI_PLATFORM"
|
||||
|
||||
config OPENSBI_PLATFORM_SRC_DIR
|
||||
string
|
||||
option env="OPENSBI_PLATFORM_SRC_DIR"
|
||||
|
||||
menu "Platform Options"
|
||||
source "$(OPENSBI_PLATFORM_SRC_DIR)/Kconfig"
|
||||
endmenu
|
||||
|
||||
source "$(OPENSBI_SRC_DIR)/lib/sbi/Kconfig"
|
||||
|
||||
source "$(OPENSBI_SRC_DIR)/lib/utils/Kconfig"
|
||||
|
||||
source "$(OPENSBI_SRC_DIR)/firmware/Kconfig"
|
577
Makefile
577
Makefile
@ -12,48 +12,26 @@
|
||||
# o Do not print "Entering directory ...";
|
||||
MAKEFLAGS += -r --no-print-directory
|
||||
|
||||
# Readlink -f requires GNU readlink
|
||||
ifeq ($(shell uname -s),Darwin)
|
||||
READLINK ?= greadlink
|
||||
else
|
||||
READLINK ?= readlink
|
||||
endif
|
||||
|
||||
# Find out source, build, and install directories
|
||||
src_dir=$(CURDIR)
|
||||
ifdef O
|
||||
build_dir=$(shell $(READLINK) -f $(O))
|
||||
build_dir=$(shell readlink -f $(O))
|
||||
else
|
||||
build_dir=$(CURDIR)/build
|
||||
endif
|
||||
ifeq ($(build_dir),$(CURDIR))
|
||||
$(error Build directory is same as source directory.)
|
||||
endif
|
||||
install_root_dir_default=$(CURDIR)/install
|
||||
ifdef I
|
||||
install_root_dir=$(shell $(READLINK) -f $(I))
|
||||
install_dir=$(shell readlink -f $(I))
|
||||
else
|
||||
install_root_dir=$(install_root_dir_default)/usr
|
||||
install_dir=$(CURDIR)/install
|
||||
endif
|
||||
ifeq ($(install_root_dir),$(CURDIR))
|
||||
$(error Install root directory is same as source directory.)
|
||||
ifeq ($(install_dir),$(CURDIR))
|
||||
$(error Install directory is same as source directory.)
|
||||
endif
|
||||
ifeq ($(install_root_dir),$(build_dir))
|
||||
$(error Install root directory is same as build directory.)
|
||||
endif
|
||||
ifdef PLATFORM_DIR
|
||||
platform_dir_path=$(shell $(READLINK) -f $(PLATFORM_DIR))
|
||||
ifdef PLATFORM
|
||||
platform_parent_dir=$(platform_dir_path)
|
||||
else
|
||||
PLATFORM=$(shell basename $(platform_dir_path))
|
||||
platform_parent_dir=$(shell realpath ${platform_dir_path}/..)
|
||||
endif
|
||||
else
|
||||
platform_parent_dir=$(src_dir)/platform
|
||||
endif
|
||||
ifndef PLATFORM_DEFCONFIG
|
||||
PLATFORM_DEFCONFIG=defconfig
|
||||
ifeq ($(install_dir),$(build_dir))
|
||||
$(error Install directory is same as build directory.)
|
||||
endif
|
||||
|
||||
# Check if verbosity is ON for build process
|
||||
@ -65,100 +43,76 @@ else
|
||||
endif
|
||||
|
||||
# Setup path of directories
|
||||
export platform_subdir=$(PLATFORM)
|
||||
export platform_src_dir=$(platform_parent_dir)/$(platform_subdir)
|
||||
export platform_build_dir=$(build_dir)/platform/$(platform_subdir)
|
||||
export platform_subdir=platform/$(PLATFORM)
|
||||
export platform_dir=$(CURDIR)/$(platform_subdir)
|
||||
export platform_common_dir=$(CURDIR)/platform/common
|
||||
export include_dir=$(CURDIR)/include
|
||||
export libsbi_dir=$(CURDIR)/lib/sbi
|
||||
export libsbiutils_dir=$(CURDIR)/lib/utils
|
||||
export lib_dir=$(CURDIR)/lib
|
||||
export firmware_dir=$(CURDIR)/firmware
|
||||
|
||||
# Setup variables for kconfig
|
||||
ifdef PLATFORM
|
||||
export PYTHONDONTWRITEBYTECODE=1
|
||||
export KCONFIG_DIR=$(platform_build_dir)/kconfig
|
||||
export KCONFIG_AUTOLIST=$(KCONFIG_DIR)/auto.list
|
||||
export KCONFIG_AUTOHEADER=$(KCONFIG_DIR)/autoconf.h
|
||||
export KCONFIG_AUTOCONFIG=$(KCONFIG_DIR)/auto.conf
|
||||
export KCONFIG_AUTOCMD=$(KCONFIG_DIR)/auto.conf.cmd
|
||||
export KCONFIG_CONFIG=$(KCONFIG_DIR)/.config
|
||||
# Additional exports for include paths in Kconfig files
|
||||
export OPENSBI_SRC_DIR=$(src_dir)
|
||||
export OPENSBI_PLATFORM=$(PLATFORM)
|
||||
export OPENSBI_PLATFORM_SRC_DIR=$(platform_src_dir)
|
||||
endif
|
||||
|
||||
# Find library version
|
||||
OPENSBI_VERSION_MAJOR=`grep "define OPENSBI_VERSION_MAJOR" $(include_dir)/sbi/sbi_version.h | sed 's/.*MAJOR.*\([0-9][0-9]*\)/\1/'`
|
||||
OPENSBI_VERSION_MINOR=`grep "define OPENSBI_VERSION_MINOR" $(include_dir)/sbi/sbi_version.h | sed 's/.*MINOR.*\([0-9][0-9]*\)/\1/'`
|
||||
OPENSBI_VERSION_GIT=
|
||||
|
||||
# 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
|
||||
OPENSBI_VERSION_MAJOR=`grep MAJOR $(include_dir)/sbi/sbi_version.h | sed 's/.*MAJOR.*\([0-9][0-9]*\)/\1/'`
|
||||
OPENSBI_VERSION_MINOR=`grep MINOR $(include_dir)/sbi/sbi_version.h | sed 's/.*MINOR.*\([0-9][0-9]*\)/\1/'`
|
||||
|
||||
# Setup compilation commands
|
||||
ifneq ($(LLVM),)
|
||||
ifneq ($(filter %/,$(LLVM)),)
|
||||
LLVM_PREFIX := $(LLVM)
|
||||
else ifneq ($(filter -%,$(LLVM)),)
|
||||
LLVM_SUFFIX := $(LLVM)
|
||||
endif
|
||||
|
||||
CC = $(LLVM_PREFIX)clang$(LLVM_SUFFIX)
|
||||
AR = $(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX)
|
||||
LD = $(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX)
|
||||
OBJCOPY = $(LLVM_PREFIX)llvm-objcopy$(LLVM_SUFFIX)
|
||||
else
|
||||
ifdef CROSS_COMPILE
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
CPP = $(CROSS_COMPILE)cpp
|
||||
AR = $(CROSS_COMPILE)ar
|
||||
LD = $(CROSS_COMPILE)ld
|
||||
OBJCOPY = $(CROSS_COMPILE)objcopy
|
||||
else
|
||||
CC ?= gcc
|
||||
CPP ?= cpp
|
||||
AR ?= ar
|
||||
LD ?= ld
|
||||
OBJCOPY ?= objcopy
|
||||
endif
|
||||
endif
|
||||
CPP = $(CC) -E
|
||||
AS = $(CC)
|
||||
DTC = dtc
|
||||
|
||||
ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
|
||||
CC_IS_CLANG = y
|
||||
else
|
||||
CC_IS_CLANG = n
|
||||
# Guess the compillers xlen
|
||||
OPENSBI_CC_XLEN := $(shell TMP=`$(CC) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
|
||||
|
||||
# Setup list of objects.mk files
|
||||
ifdef PLATFORM
|
||||
platform-object-mks=$(shell if [ -d $(platform_dir) ]; then find $(platform_dir) -iname "objects.mk" | sort -r; fi)
|
||||
platform-common-object-mks=$(shell if [ -d $(platform_common_dir) ]; then find $(platform_common_dir) -iname "objects.mk" | sort -r; fi)
|
||||
endif
|
||||
lib-object-mks=$(shell if [ -d $(lib_dir) ]; then find $(lib_dir) -iname "objects.mk" | sort -r; fi)
|
||||
firmware-object-mks=$(shell if [ -d $(firmware_dir) ]; then find $(firmware_dir) -iname "objects.mk" | sort -r; fi)
|
||||
|
||||
# Include platform specifig config.mk
|
||||
ifdef PLATFORM
|
||||
include $(platform_dir)/config.mk
|
||||
endif
|
||||
|
||||
ifneq ($(shell $(LD) --version 2>&1 | head -n 1 | grep LLD),)
|
||||
LD_IS_LLD = y
|
||||
else
|
||||
LD_IS_LLD = n
|
||||
# Include all object.mk files
|
||||
ifdef PLATFORM
|
||||
include $(platform-object-mks)
|
||||
include $(platform-common-object-mks)
|
||||
endif
|
||||
include $(lib-object-mks)
|
||||
include $(firmware-object-mks)
|
||||
|
||||
ifeq ($(CC_IS_CLANG),y)
|
||||
ifneq ($(CROSS_COMPILE),)
|
||||
CLANG_TARGET = --target=$(notdir $(CROSS_COMPILE:%-=%))
|
||||
endif
|
||||
# Setup list of objects
|
||||
lib-objs-path-y=$(foreach obj,$(lib-objs-y),$(build_dir)/lib/$(obj))
|
||||
ifdef PLATFORM
|
||||
platform-objs-path-y=$(foreach obj,$(platform-objs-y),$(build_dir)/$(platform_subdir)/$(obj))
|
||||
platform-dtb-path-y=$(foreach obj,$(platform-dtb-y),$(build_dir)/$(platform_subdir)/$(obj))
|
||||
platform-common-objs-path-y=$(foreach obj,$(platform-common-objs-y),$(build_dir)/platform/common/$(obj))
|
||||
firmware-bins-path-y=$(foreach bin,$(firmware-bins-y),$(build_dir)/$(platform_subdir)/firmware/$(bin))
|
||||
endif
|
||||
firmware-elfs-path-y=$(firmware-bins-path-y:.bin=.elf)
|
||||
firmware-objs-path-y=$(firmware-bins-path-y:.bin=.o)
|
||||
|
||||
# Guess the compiler's XLEN
|
||||
OPENSBI_CC_XLEN := $(shell TMP=`$(CC) $(CLANG_TARGET) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
|
||||
# Setup list of deps files for objects
|
||||
deps-y=$(platform-objs-path-y:.o=.dep)
|
||||
deps-y+=$(platform-common-objs-path-y:.o=.dep)
|
||||
deps-y+=$(lib-objs-path-y:.o=.dep)
|
||||
deps-y+=$(firmware-objs-path-y:.o=.dep)
|
||||
|
||||
# Guess the compiler's ABI and ISA
|
||||
ifneq ($(CC_IS_CLANG),y)
|
||||
OPENSBI_CC_ABI := $(shell TMP=`$(CC) -v 2>&1 | sed -n 's/.*\(with\-abi=\([a-zA-Z0-9]*\)\).*/\2/p'`; echo $${TMP})
|
||||
OPENSBI_CC_ISA := $(shell TMP=`$(CC) -v 2>&1 | sed -n 's/.*\(with\-arch=\([a-zA-Z0-9]*\)\).*/\2/p'`; echo $${TMP})
|
||||
endif
|
||||
|
||||
# Setup platform XLEN
|
||||
# Setup platform XLEN, ABI, ISA and Code Model
|
||||
ifndef PLATFORM_RISCV_XLEN
|
||||
ifeq ($(OPENSBI_CC_XLEN), 32)
|
||||
PLATFORM_RISCV_XLEN = 32
|
||||
@ -166,288 +120,61 @@ ifndef PLATFORM_RISCV_XLEN
|
||||
PLATFORM_RISCV_XLEN = 64
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CC_IS_CLANG),y)
|
||||
ifeq ($(CROSS_COMPILE),)
|
||||
CLANG_TARGET = --target=riscv$(PLATFORM_RISCV_XLEN)-unknown-elf
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(LD_IS_LLD),y)
|
||||
RELAX_FLAG = -mno-relax
|
||||
USE_LD_FLAG = -fuse-ld=lld
|
||||
else
|
||||
USE_LD_FLAG = -fuse-ld=bfd
|
||||
endif
|
||||
|
||||
REPRODUCIBLE ?= n
|
||||
ifeq ($(REPRODUCIBLE),y)
|
||||
REPRODUCIBLE_FLAGS += -ffile-prefix-map=$(src_dir)=
|
||||
endif
|
||||
|
||||
# Check whether the linker supports creating PIEs
|
||||
OPENSBI_LD_PIE := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) $(USE_LD_FLAG) -fPIE -nostdlib -Wl,-pie -x c /dev/null -o /dev/null >/dev/null 2>&1 && echo y || echo n)
|
||||
|
||||
# Check whether the linker supports --exclude-libs
|
||||
OPENSBI_LD_EXCLUDE_LIBS := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) $(USE_LD_FLAG) "-Wl,--exclude-libs,ALL" -x c /dev/null -o /dev/null >/dev/null 2>&1 && echo y || echo n)
|
||||
|
||||
# Check whether the compiler supports -m(no-)save-restore
|
||||
CC_SUPPORT_SAVE_RESTORE := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib -mno-save-restore -x c /dev/null -o /dev/null 2>&1 | grep -e "-save-restore" >/dev/null && echo n || echo y)
|
||||
|
||||
# Check whether the compiler supports -m(no-)strict-align
|
||||
CC_SUPPORT_STRICT_ALIGN := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib -mstrict-align -x c /dev/null -o /dev/null 2>&1 | grep -e "-mstrict-align" -e "-mno-unaligned-access" >/dev/null && echo n || echo y)
|
||||
|
||||
# Check whether the assembler and the compiler support the Zicsr and Zifencei extensions
|
||||
CC_SUPPORT_ZICSR_ZIFENCEI := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib -march=rv$(OPENSBI_CC_XLEN)imafd_zicsr_zifencei -x c /dev/null -o /dev/null 2>&1 | grep -e "zicsr" -e "zifencei" > /dev/null && echo n || echo y)
|
||||
|
||||
# Check whether the assembler and the compiler support the Vector extension
|
||||
CC_SUPPORT_VECTOR := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib -march=rv$(OPENSBI_CC_XLEN)gv -dM -E -x c /dev/null 2>&1 | grep -q riscv.*vector && echo y || echo n)
|
||||
|
||||
ifneq ($(OPENSBI_LD_PIE),y)
|
||||
$(error Your linker does not support creating PIEs, opensbi requires this.)
|
||||
endif
|
||||
|
||||
# Build Info:
|
||||
# OPENSBI_BUILD_TIME_STAMP -- the compilation time stamp
|
||||
# OPENSBI_BUILD_COMPILER_VERSION -- the compiler version info
|
||||
BUILD_INFO ?= n
|
||||
ifeq ($(BUILD_INFO),y)
|
||||
OPENSBI_BUILD_DATE_FMT = +%Y-%m-%d %H:%M:%S %z
|
||||
ifndef OPENSBI_BUILD_TIME_STAMP
|
||||
ifdef SOURCE_DATE_EPOCH
|
||||
OPENSBI_BUILD_TIME_STAMP := $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" \
|
||||
"$(OPENSBI_BUILD_DATE_FMT)" 2>/dev/null || \
|
||||
date -u -r "$(SOURCE_DATE_EPOCH)" \
|
||||
"$(OPENSBI_BUILD_DATE_FMT)" 2>/dev/null || \
|
||||
date -u "$(OPENSBI_BUILD_DATE_FMT)")
|
||||
else
|
||||
OPENSBI_BUILD_TIME_STAMP := $(shell date "$(OPENSBI_BUILD_DATE_FMT)")
|
||||
endif
|
||||
endif
|
||||
OPENSBI_BUILD_COMPILER_VERSION := $(shell $(CC) -v 2>&1 | grep ' version ' | \
|
||||
sed 's/[[:space:]]*$$//')
|
||||
endif
|
||||
|
||||
# Setup list of objects.mk files
|
||||
ifdef PLATFORM
|
||||
platform-object-mks=$(shell if [ -d $(platform_src_dir)/ ]; then find $(platform_src_dir) -iname "objects.mk" | sort -r; fi)
|
||||
endif
|
||||
libsbi-object-mks=$(shell if [ -d $(libsbi_dir) ]; then find $(libsbi_dir) -iname "objects.mk" | sort -r; fi)
|
||||
libsbiutils-object-mks=$(shell if [ -d $(libsbiutils_dir) ]; then find $(libsbiutils_dir) -iname "objects.mk" | sort -r; fi)
|
||||
firmware-object-mks=$(shell if [ -d $(firmware_dir) ]; then find $(firmware_dir) -iname "objects.mk" | sort -r; fi)
|
||||
|
||||
# The "make all" rule should always be first rule
|
||||
.PHONY: all
|
||||
all:
|
||||
|
||||
# Include platform specific .config
|
||||
ifdef PLATFORM
|
||||
.PHONY: menuconfig
|
||||
menuconfig: $(platform_src_dir)/Kconfig $(src_dir)/Kconfig
|
||||
$(CMD_PREFIX)mkdir -p $(KCONFIG_DIR)
|
||||
$(CMD_PREFIX)$(src_dir)/scripts/Kconfiglib/menuconfig.py $(src_dir)/Kconfig
|
||||
|
||||
.PHONY: savedefconfig
|
||||
savedefconfig: $(platform_src_dir)/Kconfig $(src_dir)/Kconfig
|
||||
$(CMD_PREFIX)mkdir -p $(KCONFIG_DIR)
|
||||
$(CMD_PREFIX)$(src_dir)/scripts/Kconfiglib/savedefconfig.py --kconfig $(src_dir)/Kconfig --out $(KCONFIG_DIR)/defconfig
|
||||
|
||||
$(KCONFIG_CONFIG): $(platform_src_dir)/configs/$(PLATFORM_DEFCONFIG)
|
||||
$(CMD_PREFIX)mkdir -p $(KCONFIG_DIR)
|
||||
$(CMD_PREFIX)$(src_dir)/scripts/Kconfiglib/defconfig.py --kconfig $(src_dir)/Kconfig $(platform_src_dir)/configs/$(PLATFORM_DEFCONFIG)
|
||||
|
||||
$(KCONFIG_AUTOCONFIG): $(KCONFIG_CONFIG)
|
||||
$(CMD_PREFIX)$(src_dir)/scripts/Kconfiglib/genconfig.py --header-path $(KCONFIG_AUTOHEADER) --sync-deps $(KCONFIG_DIR) --file-list $(KCONFIG_AUTOLIST) $(src_dir)/Kconfig
|
||||
|
||||
$(KCONFIG_AUTOHEADER): $(KCONFIG_AUTOCONFIG);
|
||||
|
||||
$(KCONFIG_AUTOLIST): $(KCONFIG_AUTOCONFIG);
|
||||
|
||||
$(KCONFIG_AUTOCMD): $(KCONFIG_AUTOLIST)
|
||||
$(CMD_PREFIX)printf "%s: " $(KCONFIG_CONFIG) > $(KCONFIG_AUTOCMD)
|
||||
$(CMD_PREFIX)cat $(KCONFIG_AUTOLIST) | tr '\n' ' ' >> $(KCONFIG_AUTOCMD)
|
||||
|
||||
include $(KCONFIG_AUTOCONFIG)
|
||||
include $(KCONFIG_AUTOCMD)
|
||||
endif
|
||||
|
||||
# Include all objects.mk files
|
||||
ifdef PLATFORM
|
||||
include $(platform-object-mks)
|
||||
endif
|
||||
include $(libsbi-object-mks)
|
||||
include $(libsbiutils-object-mks)
|
||||
include $(firmware-object-mks)
|
||||
|
||||
# Setup list of objects
|
||||
libsbi-objs-path-y=$(foreach obj,$(libsbi-objs-y),$(build_dir)/lib/sbi/$(obj))
|
||||
ifdef PLATFORM
|
||||
libsbiutils-objs-path-y=$(foreach obj,$(libsbiutils-objs-y),$(platform_build_dir)/lib/utils/$(obj))
|
||||
platform-objs-path-y=$(foreach obj,$(platform-objs-y),$(platform_build_dir)/$(obj))
|
||||
firmware-bins-path-y=$(foreach bin,$(firmware-bins-y),$(platform_build_dir)/firmware/$(bin))
|
||||
endif
|
||||
firmware-elfs-path-y=$(firmware-bins-path-y:.bin=.elf)
|
||||
firmware-objs-path-y=$(firmware-bins-path-y:.bin=.o)
|
||||
|
||||
# Setup list of deps files for objects
|
||||
deps-y=$(platform-objs-path-y:.o=.dep)
|
||||
deps-y+=$(libsbi-objs-path-y:.o=.dep)
|
||||
deps-y+=$(libsbiutils-objs-path-y:.o=.dep)
|
||||
deps-y+=$(firmware-objs-path-y:.o=.dep)
|
||||
deps-y+=$(firmware-elfs-path-y:=.dep)
|
||||
|
||||
# Setup platform ABI, ISA and Code Model
|
||||
ifndef PLATFORM_RISCV_ABI
|
||||
ifneq ($(PLATFORM_RISCV_TOOLCHAIN_DEFAULT), 1)
|
||||
ifeq ($(PLATFORM_RISCV_XLEN), 32)
|
||||
PLATFORM_RISCV_ABI = ilp$(PLATFORM_RISCV_XLEN)
|
||||
else
|
||||
PLATFORM_RISCV_ABI = lp$(PLATFORM_RISCV_XLEN)
|
||||
endif
|
||||
ifeq ($(PLATFORM_RISCV_XLEN), 32)
|
||||
PLATFORM_RISCV_ABI = ilp$(PLATFORM_RISCV_XLEN)
|
||||
else
|
||||
PLATFORM_RISCV_ABI = $(OPENSBI_CC_ABI)
|
||||
PLATFORM_RISCV_ABI = lp$(PLATFORM_RISCV_XLEN)
|
||||
endif
|
||||
endif
|
||||
ifndef PLATFORM_RISCV_ISA
|
||||
ifneq ($(PLATFORM_RISCV_TOOLCHAIN_DEFAULT), 1)
|
||||
PLATFORM_RISCV_ISA := rv$(PLATFORM_RISCV_XLEN)imafdc
|
||||
ifeq ($(CC_SUPPORT_ZICSR_ZIFENCEI), y)
|
||||
PLATFORM_RISCV_ISA := $(PLATFORM_RISCV_ISA)_zicsr_zifencei
|
||||
endif
|
||||
else
|
||||
PLATFORM_RISCV_ISA = $(OPENSBI_CC_ISA)
|
||||
endif
|
||||
PLATFORM_RISCV_ISA = rv$(PLATFORM_RISCV_XLEN)imafdc
|
||||
endif
|
||||
ifndef PLATFORM_RISCV_CODE_MODEL
|
||||
PLATFORM_RISCV_CODE_MODEL = medany
|
||||
endif
|
||||
|
||||
# Setup install directories
|
||||
ifdef INSTALL_INCLUDE_PATH
|
||||
install_include_path=$(INSTALL_INCLUDE_PATH)
|
||||
else
|
||||
install_include_path=include
|
||||
endif
|
||||
ifdef INSTALL_LIB_PATH
|
||||
install_lib_path=$(INSTALL_LIB_PATH)
|
||||
else
|
||||
ifneq ($(origin INSTALL_LIB_SUBDIR), undefined)
|
||||
install_lib_subdir=$(INSTALL_LIB_SUBDIR)
|
||||
else
|
||||
install_lib_subdir=$(PLATFORM_RISCV_ABI)
|
||||
endif
|
||||
install_lib_path=lib$(subst 32,,$(PLATFORM_RISCV_XLEN))/$(install_lib_subdir)
|
||||
endif
|
||||
ifdef INSTALL_FIRMWARE_PATH
|
||||
install_firmware_path=$(INSTALL_FIRMWARE_PATH)
|
||||
else
|
||||
install_firmware_path=share/opensbi/$(PLATFORM_RISCV_ABI)
|
||||
endif
|
||||
ifdef INSTALL_DOCS_PATH
|
||||
install_docs_path=$(INSTALL_DOCS_PATH)
|
||||
else
|
||||
install_docs_path=share/opensbi/docs
|
||||
endif
|
||||
|
||||
# Setup compilation commands flags
|
||||
ifeq ($(CC_IS_CLANG),y)
|
||||
GENFLAGS += $(CLANG_TARGET)
|
||||
GENFLAGS += -Wno-unused-command-line-argument
|
||||
endif
|
||||
GENFLAGS += -I$(platform_src_dir)/include
|
||||
GENFLAGS = -I$(platform_dir)/include
|
||||
GENFLAGS += -I$(platform_common_dir)/include
|
||||
GENFLAGS += -I$(include_dir)
|
||||
ifneq ($(OPENSBI_VERSION_GIT),)
|
||||
GENFLAGS += -DOPENSBI_VERSION_GIT="\"$(OPENSBI_VERSION_GIT)\""
|
||||
endif
|
||||
ifeq ($(BUILD_INFO),y)
|
||||
GENFLAGS += -DOPENSBI_BUILD_TIME_STAMP="\"$(OPENSBI_BUILD_TIME_STAMP)\""
|
||||
GENFLAGS += -DOPENSBI_BUILD_COMPILER_VERSION="\"$(OPENSBI_BUILD_COMPILER_VERSION)\""
|
||||
endif
|
||||
GENFLAGS += -include $(include_dir)/sbi/sbi_visibility.h
|
||||
ifdef PLATFORM
|
||||
GENFLAGS += -include $(KCONFIG_AUTOHEADER)
|
||||
endif
|
||||
GENFLAGS += $(libsbiutils-genflags-y)
|
||||
GENFLAGS += $(platform-common-genflags-y)
|
||||
GENFLAGS += $(platform-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 -nostdlib -fno-strict-aliasing -O2
|
||||
CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
|
||||
CFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables
|
||||
CFLAGS += $(REPRODUCIBLE_FLAGS)
|
||||
# Optionally supported flags
|
||||
ifeq ($(CC_SUPPORT_VECTOR),y)
|
||||
CFLAGS += -DOPENSBI_CC_SUPPORT_VECTOR
|
||||
endif
|
||||
ifeq ($(CC_SUPPORT_SAVE_RESTORE),y)
|
||||
CFLAGS += -mno-save-restore
|
||||
endif
|
||||
ifeq ($(CC_SUPPORT_STRICT_ALIGN),y)
|
||||
CFLAGS += -mstrict-align
|
||||
endif
|
||||
CFLAGS += -mno-save-restore -mstrict-align
|
||||
CFLAGS += -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
|
||||
CFLAGS += -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
|
||||
CFLAGS += $(RELAX_FLAG)
|
||||
CFLAGS += $(GENFLAGS)
|
||||
CFLAGS += $(platform-cflags-y)
|
||||
CFLAGS += -fPIE -pie
|
||||
CFLAGS += $(firmware-cflags-y)
|
||||
|
||||
CPPFLAGS += $(GENFLAGS)
|
||||
CPPFLAGS += $(platform-cppflags-y)
|
||||
CPPFLAGS += $(firmware-cppflags-y)
|
||||
|
||||
ASFLAGS = -g -Wall -nostdlib
|
||||
ASFLAGS = -g -Wall -nostdlib -D__ASSEMBLY__
|
||||
ASFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
|
||||
ASFLAGS += -fPIE
|
||||
ASFLAGS += $(REPRODUCIBLE_FLAGS)
|
||||
# Optionally supported flags
|
||||
ifeq ($(CC_SUPPORT_SAVE_RESTORE),y)
|
||||
ASFLAGS += -mno-save-restore
|
||||
endif
|
||||
ifeq ($(CC_SUPPORT_STRICT_ALIGN),y)
|
||||
ASFLAGS += -mstrict-align
|
||||
endif
|
||||
ASFLAGS += -mno-save-restore -mstrict-align
|
||||
ASFLAGS += -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
|
||||
ASFLAGS += -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
|
||||
ASFLAGS += $(RELAX_FLAG)
|
||||
ifneq ($(CC_IS_CLANG),y)
|
||||
ifneq ($(RELAX_FLAG),)
|
||||
ASFLAGS += -Wa,$(RELAX_FLAG)
|
||||
endif
|
||||
endif
|
||||
ASFLAGS += $(GENFLAGS)
|
||||
ASFLAGS += $(platform-asflags-y)
|
||||
ASFLAGS += $(firmware-asflags-y)
|
||||
|
||||
ARFLAGS = rcs
|
||||
|
||||
ELFFLAGS += $(USE_LD_FLAG)
|
||||
ELFFLAGS += -Wl,--gc-sections
|
||||
ifeq ($(OPENSBI_LD_EXCLUDE_LIBS),y)
|
||||
ELFFLAGS += -Wl,--exclude-libs,ALL
|
||||
endif
|
||||
ELFFLAGS += -Wl,--build-id=none
|
||||
ELFFLAGS += -Wl,--no-dynamic-linker -Wl,-pie
|
||||
ELFFLAGS += -Wl,--build-id=none -N -static-libgcc -lgcc
|
||||
ELFFLAGS += $(platform-ldflags-y)
|
||||
ELFFLAGS += $(firmware-ldflags-y)
|
||||
|
||||
MERGEFLAGS += -r
|
||||
ifeq ($(LD_IS_LLD),y)
|
||||
MERGEFLAGS += -b elf
|
||||
else
|
||||
MERGEFLAGS += -b elf$(PLATFORM_RISCV_XLEN)-littleriscv
|
||||
endif
|
||||
MERGEFLAGS += -m elf$(PLATFORM_RISCV_XLEN)lriscv
|
||||
|
||||
DTSCPPFLAGS = $(CPPFLAGS) -nostdinc -nostdlib -fno-builtin -D__DTS__ -x assembler-with-cpp
|
||||
|
||||
ifneq ($(DEBUG),)
|
||||
CFLAGS += -O0
|
||||
ELFFLAGS += -Wl,--print-gc-sections
|
||||
else
|
||||
CFLAGS += -O2
|
||||
endif
|
||||
DTCFLAGS = -O dtb
|
||||
|
||||
# Setup functions for compilation
|
||||
define dynamic_flags
|
||||
@ -461,35 +188,30 @@ merge_deps = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||
cat $(2) > $(1)
|
||||
copy_file = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||
echo " COPY $(subst $(build_dir)/,,$(1))"; \
|
||||
cp -L -f $(2) $(1)
|
||||
cp -f $(2) $(1)
|
||||
inst_file = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||
echo " INSTALL $(subst $(install_root_dir)/,,$(1))"; \
|
||||
cp -L -f $(2) $(1)
|
||||
echo " INSTALL $(subst $(install_dir)/,,$(1))"; \
|
||||
cp -f $(2) $(1)
|
||||
inst_file_list = $(CMD_PREFIX)if [ ! -z "$(4)" ]; then \
|
||||
mkdir -p $(1)/$(3); \
|
||||
for file in $(4) ; do \
|
||||
rel_file=`echo $$file | sed -e 's@$(2)/$(subst $(install_firmware_path),platform,$(3))@@'`; \
|
||||
rel_file=`echo $$file | sed -e 's@$(2)/$(3)/@@'`; \
|
||||
dest_file=$(1)"/"$(3)"/"`echo $$rel_file`; \
|
||||
dest_dir=`dirname $$dest_file`; \
|
||||
echo " INSTALL "$(3)"/"`echo $$rel_file`; \
|
||||
mkdir -p $$dest_dir; \
|
||||
cp -L -f $$file $$dest_file; \
|
||||
cp -f $$file $$dest_file; \
|
||||
done \
|
||||
fi
|
||||
inst_header_dir = $(CMD_PREFIX)mkdir -p $(1); \
|
||||
echo " INSTALL $(subst $(install_root_dir)/,,$(1))"; \
|
||||
cp -L -rf $(2) $(1)
|
||||
compile_cpp_dep = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||
echo " CPP-DEP $(subst $(build_dir)/,,$(1))"; \
|
||||
printf %s `dirname $(1)`/ > $(1) && \
|
||||
$(CC) $(CPPFLAGS) -x c -MM $(3) \
|
||||
-MT `basename $(1:.dep=$(2))` >> $(1) || rm -f $(1)
|
||||
echo " INSTALL $(subst $(install_dir)/,,$(1))"; \
|
||||
cp -rf $(2) $(1)
|
||||
compile_cpp = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||
echo " CPP $(subst $(build_dir)/,,$(1))"; \
|
||||
$(CPP) $(CPPFLAGS) -x c $(2) | grep -v "\#" > $(1)
|
||||
compile_cc_dep = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||
echo " CC-DEP $(subst $(build_dir)/,,$(1))"; \
|
||||
printf %s `dirname $(1)`/ > $(1) && \
|
||||
echo `dirname $(1)`/ \\ > $(1) && \
|
||||
$(CC) $(CFLAGS) $(call dynamic_flags,$(1),$(2)) \
|
||||
-MM $(2) >> $(1) || rm -f $(1)
|
||||
compile_cc = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||
@ -497,7 +219,7 @@ compile_cc = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||
$(CC) $(CFLAGS) $(call dynamic_flags,$(1),$(2)) -c $(2) -o $(1)
|
||||
compile_as_dep = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||
echo " AS-DEP $(subst $(build_dir)/,,$(1))"; \
|
||||
printf %s `dirname $(1)`/ > $(1) && \
|
||||
echo `dirname $(1)`/ \\ > $(1) && \
|
||||
$(AS) $(ASFLAGS) $(call dynamic_flags,$(1),$(2)) \
|
||||
-MM $(2) >> $(1) || rm -f $(1)
|
||||
compile_as = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||
@ -514,131 +236,64 @@ compile_objcopy = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||
$(OBJCOPY) -S -O binary $(2) $(1)
|
||||
compile_dts = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||
echo " DTC $(subst $(build_dir)/,,$(1))"; \
|
||||
$(CPP) $(DTSCPPFLAGS) $(2) | $(DTC) -O dtb -i `dirname $(2)` -o $(1)
|
||||
compile_d2c = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||
echo " D2C $(subst $(build_dir)/,,$(1))"; \
|
||||
$(if $($(2)-varalign-$(3)),$(eval D2C_ALIGN_BYTES := $($(2)-varalign-$(3))),$(eval D2C_ALIGN_BYTES := $(4))) \
|
||||
$(if $($(2)-varprefix-$(3)),$(eval D2C_NAME_PREFIX := $($(2)-varprefix-$(3))),$(eval D2C_NAME_PREFIX := $(5))) \
|
||||
$(if $($(2)-padding-$(3)),$(eval D2C_PADDING_BYTES := $($(2)-padding-$(3))),$(eval D2C_PADDING_BYTES := 0)) \
|
||||
$(src_dir)/scripts/d2c.sh -i $(6) -a $(D2C_ALIGN_BYTES) -p $(D2C_NAME_PREFIX) -t $(D2C_PADDING_BYTES) > $(1)
|
||||
compile_carray = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||
echo " CARRAY $(subst $(build_dir)/,,$(1))"; \
|
||||
$(eval CARRAY_VAR_LIST := $(carray-$(subst .carray.c,,$(shell basename $(1)))-y)) \
|
||||
$(src_dir)/scripts/carray.sh -i $(2) -l "$(CARRAY_VAR_LIST)" > $(1) || rm $(1)
|
||||
compile_gen_dep = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||
echo " GEN-DEP $(subst $(build_dir)/,,$(1))"; \
|
||||
echo "$(1:.dep=$(2)): $(3)" >> $(1)
|
||||
$(DTC) $(DTCFLAGS) -o $(1) $(2)
|
||||
|
||||
targets-y = $(build_dir)/lib/libsbi.a
|
||||
ifdef PLATFORM
|
||||
targets-y += $(platform_build_dir)/lib/libplatsbi.a
|
||||
targets-y += $(build_dir)/$(platform_subdir)/lib/libplatsbi.a
|
||||
targets-y += $(platform-dtb-path-y)
|
||||
endif
|
||||
targets-y += $(firmware-bins-path-y)
|
||||
|
||||
# The default "make all" rule
|
||||
# Default rule "make" should always be first rule
|
||||
.PHONY: all
|
||||
all: $(targets-y)
|
||||
|
||||
# Preserve all intermediate files
|
||||
.SECONDARY:
|
||||
|
||||
# Rules for lib/sbi sources
|
||||
$(build_dir)/lib/libsbi.a: $(libsbi-objs-path-y)
|
||||
$(build_dir)/%.bin: $(build_dir)/%.elf
|
||||
$(call compile_objcopy,$@,$<)
|
||||
|
||||
$(build_dir)/%.elf: $(build_dir)/%.o $(build_dir)/%.elf.ld $(build_dir)/$(platform_subdir)/lib/libplatsbi.a
|
||||
$(call compile_elf,$@,$@.ld,$< $(build_dir)/$(platform_subdir)/lib/libplatsbi.a)
|
||||
|
||||
$(build_dir)/$(platform_subdir)/%.ld: $(src_dir)/%.ldS
|
||||
$(call compile_cpp,$@,$<)
|
||||
|
||||
$(build_dir)/lib/libsbi.a: $(lib-objs-path-y)
|
||||
$(call compile_ar,$@,$^)
|
||||
|
||||
$(platform_build_dir)/lib/libplatsbi.a: $(libsbi-objs-path-y) $(libsbiutils-objs-path-y) $(platform-objs-path-y)
|
||||
$(build_dir)/$(platform_subdir)/lib/libplatsbi.a: $(lib-objs-path-y) $(platform-common-objs-path-y) $(platform-objs-path-y)
|
||||
$(call compile_ar,$@,$^)
|
||||
|
||||
$(build_dir)/%.dep: $(src_dir)/%.carray $(KCONFIG_AUTOHEADER)
|
||||
$(call compile_gen_dep,$@,.c,$< $(KCONFIG_AUTOHEADER))
|
||||
$(call compile_gen_dep,$@,.o,$(@:.dep=.c))
|
||||
|
||||
$(build_dir)/%.carray.c: $(src_dir)/%.carray $(src_dir)/scripts/carray.sh
|
||||
$(call compile_carray,$@,$<)
|
||||
|
||||
$(build_dir)/%.dep: $(src_dir)/%.c $(KCONFIG_AUTOHEADER)
|
||||
$(build_dir)/%.dep: $(src_dir)/%.c
|
||||
$(call compile_cc_dep,$@,$<)
|
||||
|
||||
$(build_dir)/%.o: $(src_dir)/%.c
|
||||
$(call compile_cc,$@,$<)
|
||||
|
||||
$(build_dir)/%.o: $(build_dir)/%.c
|
||||
$(call compile_cc,$@,$<)
|
||||
|
||||
ifeq ($(BUILD_INFO),y)
|
||||
$(build_dir)/lib/sbi/sbi_init.o: $(libsbi_dir)/sbi_init.c FORCE
|
||||
$(call compile_cc,$@,$<)
|
||||
endif
|
||||
|
||||
$(build_dir)/%.dep: $(src_dir)/%.S $(KCONFIG_AUTOHEADER)
|
||||
$(build_dir)/%.dep: $(src_dir)/%.S
|
||||
$(call compile_as_dep,$@,$<)
|
||||
|
||||
$(build_dir)/%.o: $(src_dir)/%.S
|
||||
$(call compile_as,$@,$<)
|
||||
|
||||
# Rules for platform sources
|
||||
$(platform_build_dir)/%.dep: $(platform_src_dir)/%.carray $(KCONFIG_AUTOHEADER)
|
||||
$(call compile_gen_dep,$@,.c,$< $(KCONFIG_AUTOHEADER))
|
||||
$(call compile_gen_dep,$@,.o,$(@:.dep=.c))
|
||||
|
||||
$(platform_build_dir)/%.carray.c: $(platform_src_dir)/%.carray $(src_dir)/scripts/carray.sh
|
||||
$(call compile_carray,$@,$<)
|
||||
|
||||
$(platform_build_dir)/%.dep: $(platform_src_dir)/%.c $(KCONFIG_AUTOHEADER)
|
||||
$(build_dir)/$(platform_subdir)/%.dep: $(src_dir)/%.c
|
||||
$(call compile_cc_dep,$@,$<)
|
||||
|
||||
$(platform_build_dir)/%.o: $(platform_src_dir)/%.c $(KCONFIG_AUTOHEADER)
|
||||
$(build_dir)/$(platform_subdir)/%.o: $(src_dir)/%.c
|
||||
$(call compile_cc,$@,$<)
|
||||
|
||||
$(platform_build_dir)/%.dep: $(platform_src_dir)/%.S
|
||||
$(build_dir)/$(platform_subdir)/%.dep: $(src_dir)/%.S
|
||||
$(call compile_as_dep,$@,$<)
|
||||
|
||||
$(platform_build_dir)/%.o: $(platform_src_dir)/%.S
|
||||
$(build_dir)/$(platform_subdir)/%.o: $(src_dir)/%.S
|
||||
$(call compile_as,$@,$<)
|
||||
|
||||
$(platform_build_dir)/%.dep: $(platform_src_dir)/%.dts $(KCONFIG_AUTOHEADER)
|
||||
$(call compile_gen_dep,$@,.dtb,$< $(KCONFIG_AUTOHEADER))
|
||||
$(call compile_gen_dep,$@,.c,$(@:.dep=.dtb))
|
||||
$(call compile_gen_dep,$@,.o,$(@:.dep=.c))
|
||||
|
||||
$(platform_build_dir)/%.c: $(platform_build_dir)/%.dtb
|
||||
$(call compile_d2c,$@,platform,$(subst .dtb,.o,$(subst /,-,$(subst $(platform_build_dir)/,,$<))),16,dt,$<)
|
||||
|
||||
$(platform_build_dir)/%.dtb: $(platform_src_dir)/%.dts
|
||||
$(build_dir)/%.dtb: $(src_dir)/%.dts
|
||||
$(call compile_dts,$@,$<)
|
||||
|
||||
# Rules for lib/utils and firmware sources
|
||||
$(platform_build_dir)/%.bin: $(platform_build_dir)/%.elf
|
||||
$(call compile_objcopy,$@,$<)
|
||||
|
||||
$(platform_build_dir)/%.elf: $(platform_build_dir)/%.o $(platform_build_dir)/%.elf.ld $(platform_build_dir)/lib/libplatsbi.a
|
||||
$(call compile_elf,$@,$@.ld,$< $(platform_build_dir)/lib/libplatsbi.a)
|
||||
|
||||
$(platform_build_dir)/%.dep: $(src_dir)/%.ldS $(KCONFIG_AUTOHEADER)
|
||||
$(call compile_cpp_dep,$@,.ld,$<)
|
||||
|
||||
$(platform_build_dir)/%.ld: $(src_dir)/%.ldS
|
||||
$(call compile_cpp,$@,$<)
|
||||
|
||||
$(platform_build_dir)/%.dep: $(src_dir)/%.carray $(KCONFIG_AUTOHEADER)
|
||||
$(call compile_gen_dep,$@,.c,$< $(KCONFIG_AUTOHEADER))
|
||||
$(call compile_gen_dep,$@,.o,$(@:.dep=.c))
|
||||
|
||||
$(platform_build_dir)/%.carray.c: $(src_dir)/%.carray $(src_dir)/scripts/carray.sh
|
||||
$(call compile_carray,$@,$<)
|
||||
|
||||
$(platform_build_dir)/%.dep: $(src_dir)/%.c $(KCONFIG_AUTOHEADER)
|
||||
$(call compile_cc_dep,$@,$<)
|
||||
|
||||
$(platform_build_dir)/%.o: $(src_dir)/%.c
|
||||
$(call compile_cc,$@,$<)
|
||||
|
||||
$(platform_build_dir)/%.dep: $(src_dir)/%.S $(KCONFIG_AUTOHEADER)
|
||||
$(call compile_as_dep,$@,$<)
|
||||
|
||||
$(platform_build_dir)/%.o: $(src_dir)/%.S
|
||||
$(call compile_as,$@,$<)
|
||||
|
||||
# Rule for "make docs"
|
||||
$(build_dir)/docs/latex/refman.pdf: $(build_dir)/docs/latex/refman.tex
|
||||
$(CMD_PREFIX)mkdir -p $(build_dir)/docs
|
||||
@ -668,7 +323,7 @@ ifneq ($(platform-runcmd),)
|
||||
$(platform-runcmd) $(RUN_ARGS)
|
||||
else
|
||||
ifdef PLATFORM
|
||||
@echo "Platform $(PLATFORM) doesn't specify a run command"
|
||||
@echo Platform $(PLATFORM) doesn't specify a run command
|
||||
@false
|
||||
else
|
||||
@echo Run command only available when targeting a platform
|
||||
@ -688,32 +343,21 @@ install: $(install_targets-y)
|
||||
|
||||
.PHONY: install_libsbi
|
||||
install_libsbi: $(build_dir)/lib/libsbi.a
|
||||
$(call inst_header_dir,$(install_root_dir)/$(install_include_path),$(include_dir)/sbi)
|
||||
$(call inst_file,$(install_root_dir)/$(install_lib_path)/libsbi.a,$(build_dir)/lib/libsbi.a)
|
||||
$(call inst_header_dir,$(install_dir)/include,$(include_dir)/sbi)
|
||||
$(call inst_file,$(install_dir)/lib/libsbi.a,$(build_dir)/lib/libsbi.a)
|
||||
|
||||
.PHONY: install_libplatsbi
|
||||
install_libplatsbi: $(platform_build_dir)/lib/libplatsbi.a $(build_dir)/lib/libsbi.a
|
||||
$(call inst_file,$(install_root_dir)/$(install_lib_path)/opensbi/$(platform_subdir)/lib/libplatsbi.a,$(platform_build_dir)/lib/libplatsbi.a)
|
||||
install_libplatsbi: $(build_dir)/$(platform_subdir)/lib/libplatsbi.a $(build_dir)/lib/libsbi.a
|
||||
$(call inst_file,$(install_dir)/$(platform_subdir)/lib/libplatsbi.a,$(build_dir)/$(platform_subdir)/lib/libplatsbi.a)
|
||||
|
||||
.PHONY: install_firmwares
|
||||
install_firmwares: $(platform_build_dir)/lib/libplatsbi.a $(build_dir)/lib/libsbi.a $(firmware-bins-path-y)
|
||||
$(call inst_file_list,$(install_root_dir),$(build_dir),$(install_firmware_path)/$(platform_subdir)/firmware,$(firmware-elfs-path-y))
|
||||
$(call inst_file_list,$(install_root_dir),$(build_dir),$(install_firmware_path)/$(platform_subdir)/firmware,$(firmware-bins-path-y))
|
||||
install_firmwares: $(build_dir)/$(platform_subdir)/lib/libplatsbi.a $(build_dir)/lib/libsbi.a $(firmware-bins-path-y)
|
||||
$(call inst_file_list,$(install_dir),$(build_dir),$(platform_subdir)/firmware,$(firmware-elfs-path-y))
|
||||
$(call inst_file_list,$(install_dir),$(build_dir),$(platform_subdir)/firmware,$(firmware-bins-path-y))
|
||||
|
||||
.PHONY: install_docs
|
||||
install_docs: $(build_dir)/docs/latex/refman.pdf
|
||||
$(call inst_file,$(install_root_dir)/$(install_docs_path)/refman.pdf,$(build_dir)/docs/latex/refman.pdf)
|
||||
|
||||
.PHONY: cscope
|
||||
cscope:
|
||||
$(CMD_PREFIX)find \
|
||||
"$(src_dir)/firmware" \
|
||||
"$(src_dir)/include" \
|
||||
"$(src_dir)/lib" \
|
||||
"$(platform_src_dir)" \
|
||||
-name "*.[chS]" -print > cscope.files
|
||||
$(CMD_PREFIX)echo "$(KCONFIG_AUTOHEADER)" >> cscope.files
|
||||
$(CMD_PREFIX)cscope -bkq -i cscope.files -f cscope.out
|
||||
$(call inst_file,$(install_dir)/docs/refman.pdf,$(build_dir)/docs/latex/refman.pdf)
|
||||
|
||||
# Rule for "make clean"
|
||||
.PHONY: clean
|
||||
@ -721,16 +365,12 @@ clean:
|
||||
$(CMD_PREFIX)mkdir -p $(build_dir)
|
||||
$(if $(V), @echo " RM $(build_dir)/*.o")
|
||||
$(CMD_PREFIX)find $(build_dir) -type f -name "*.o" -exec rm -rf {} +
|
||||
$(if $(V), @echo " RM $(build_dir)/*.carray.c")
|
||||
$(CMD_PREFIX)find $(build_dir) -type f -name "*.carray.c" -exec rm -rf {} +
|
||||
$(if $(V), @echo " RM $(build_dir)/*.a")
|
||||
$(CMD_PREFIX)find $(build_dir) -type f -name "*.a" -exec rm -rf {} +
|
||||
$(if $(V), @echo " RM $(build_dir)/*.elf")
|
||||
$(CMD_PREFIX)find $(build_dir) -type f -name "*.elf" -exec rm -rf {} +
|
||||
$(if $(V), @echo " RM $(build_dir)/*.bin")
|
||||
$(CMD_PREFIX)find $(build_dir) -type f -name "*.bin" -exec rm -rf {} +
|
||||
$(if $(V), @echo " RM $(build_dir)/*.dtb")
|
||||
$(CMD_PREFIX)find $(build_dir) -type f -name "*.dtb" -exec rm -rf {} +
|
||||
|
||||
# Rule for "make distclean"
|
||||
.PHONY: distclean
|
||||
@ -742,12 +382,7 @@ ifeq ($(build_dir),$(CURDIR)/build)
|
||||
$(if $(V), @echo " RM $(build_dir)")
|
||||
$(CMD_PREFIX)rm -rf $(build_dir)
|
||||
endif
|
||||
ifeq ($(install_root_dir),$(install_root_dir_default)/usr)
|
||||
$(if $(V), @echo " RM $(install_root_dir_default)")
|
||||
$(CMD_PREFIX)rm -rf $(install_root_dir_default)
|
||||
ifeq ($(install_dir),$(CURDIR)/install)
|
||||
$(if $(V), @echo " RM $(install_dir)")
|
||||
$(CMD_PREFIX)rm -rf $(install_dir)
|
||||
endif
|
||||
$(if $(V), @echo " RM $(src_dir)/cscope*")
|
||||
$(CMD_PREFIX)rm -f $(src_dir)/cscope*
|
||||
|
||||
.PHONY: FORCE
|
||||
FORCE:
|
||||
|
447
README.md
447
README.md
@ -1,17 +1,135 @@
|
||||
RISC-V Open Source Supervisor Binary Interface (OpenSBI)
|
||||
========================================================
|
||||
|
||||

|
||||
The **RISC-V Supervisor Binary Interface (SBI)** is the recommended interface
|
||||
between:
|
||||
|
||||
Copyright and License
|
||||
---------------------
|
||||
1. A platform specific firmware running in M-mode and bootloader, hypervisor or
|
||||
a general purpose OS executing in S-mode or HS-mode.
|
||||
2. A hypervisor running in HS-mode and a bootloader or a general purpose OS
|
||||
executing in VS-mode.
|
||||
|
||||
The OpenSBI project is:
|
||||
The *RISC-V SBI specification* is maintained as an independent project by the
|
||||
RISC-V Foundation in [Github].
|
||||
|
||||
* Copyright (c) 2019 Western Digital Corporation or its affiliates
|
||||
* Copyright (c) 2023 RISC-V International
|
||||
The goal of the OpenSBI project is to provide an open-source reference
|
||||
implementation of the RISC-V SBI specifications for platform specific firmwares
|
||||
executing in M-mode (case 1 mentioned above). OpenSBI implementation can be
|
||||
easily extended by RISC-V platform and system-on-chip vendors to fit a
|
||||
particular hardware configuration.
|
||||
|
||||
It is distributed under the terms of the BSD 2-clause license
|
||||
The main component of OpenSBI is provided in the form of a platform independent
|
||||
static library **libsbi.a** implementing the SBI interface. A firmware or
|
||||
bootloader implementation can link against this library to ensure conformance
|
||||
with the SBI interface specifications. *libsbi.a* also defines an interface for
|
||||
integrating with platform specific operations provided by the platform firmware
|
||||
implementation (e.g. console access functions, inter-processor interrupts
|
||||
control, etc).
|
||||
|
||||
To illustrate the use of *libsbi.a* library, OpenSBI also provides a set of
|
||||
platform specific support examples. For each example, a platform
|
||||
specific static library *libplatsbi.a* can be compiled. This library implements
|
||||
SBI calls processing by integrating *libsbi.a* with necessary platform dependent
|
||||
hardware manipulation functions. For all supported platforms, OpenSBI also
|
||||
provides several runtime firmware examples built using the platform
|
||||
*libplatsbi.a*. These example firmwares can be used to replace the legacy
|
||||
*riskv-pk* bootloader (aka BBL) and enable the use of well known bootloaders
|
||||
such as [U-Boot].
|
||||
|
||||
Required Toolchain
|
||||
------------------
|
||||
|
||||
OpenSBI can be compiled natively or cross-compiled on a x86 host. For
|
||||
cross-compilation, you can build your tool chain or just download from
|
||||
the [bootlin] (https://toolchains.bootlin.com/).
|
||||
|
||||
Please note that only 64bit version of toolchain is available in bootlin
|
||||
for now.
|
||||
|
||||
Building and Installing OpenSBI Platform Independent Library
|
||||
------------------------------------------------------------
|
||||
|
||||
OpenSBI platform independent static library *libsbi.a* can be natively compiled
|
||||
or cross-compiled on a host with a different base architecture than RISC-V.
|
||||
|
||||
For cross-compiling, the environment variable *CROSS_COMPILE* must be defined
|
||||
to specify the name prefix of the RISC-V compiler toolchain executables, e.g.
|
||||
*riscv64-unknown-elf-* if the gcc executable used is *riscv64-unknown-elf-gcc*.
|
||||
|
||||
To build *libsbi.a* simply execute:
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
All compiled binaries as well as the result *libsbi.a* static library file will
|
||||
be placed in the *build/lib* directory. To specify an alternate build root
|
||||
directory path, run:
|
||||
```
|
||||
make O=<build_directory>
|
||||
```
|
||||
|
||||
To generate files to be installed for using *libsbi.a* in other projects, run:
|
||||
```
|
||||
make install
|
||||
```
|
||||
|
||||
This will create the *install* directory with all necessary include files
|
||||
copied under the *install/include* directory and library file copied in the
|
||||
*install/lib* directory. To specify an alternate installation root directory
|
||||
path, run:
|
||||
```
|
||||
make I=<install_directory> install
|
||||
```
|
||||
|
||||
Building and Installing a Reference Platform Static Library and Firmwares
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
When the *PLATFORM=<platform_subdir>* argument is specified on the make command
|
||||
line, the platform specific static library *libplatsbi.a* and firmware examples
|
||||
are built for the platform *<platform_subdir>* present in the directory
|
||||
*platform* in OpenSBI top directory. For example, to compile the platform
|
||||
library and firmware examples for QEMU RISC-V *virt* machine,
|
||||
*<platform_subdir>* should be *qemu/virt*.
|
||||
|
||||
To build *libsbi.a*, *libplatsbi.a* and the firmwares for one of the supported
|
||||
platform, run:
|
||||
```
|
||||
make PLATFORM=<platform_subdir>
|
||||
```
|
||||
|
||||
An alternate build directory path can also be specified.
|
||||
```
|
||||
make PLATFORM=<platform_subdir> O=<build_directory>
|
||||
```
|
||||
|
||||
The platform specific library *libplatsbi.a* will be generated in the
|
||||
*build/platform/<platform_subdir>/lib* directory. The platform firmware files
|
||||
will be under the *build/platform/<platform_subdir>/firmware* directory.
|
||||
The compiled firmwares will be available in two different format: an ELF file
|
||||
and an expanded image file.
|
||||
|
||||
To install *libsbi.a*, *libplatsbi.a*, and the compiled firmwares, run:
|
||||
```
|
||||
make PLATFORM=<platform_subdir> install
|
||||
```
|
||||
|
||||
This will copy the compiled platform specific libraries and firmware files
|
||||
under the *install/platform/<platform_subdir>/* directory. An alternate
|
||||
install root directory path can be specified as follows.
|
||||
```
|
||||
make PLATFORM=<platform_subdir> I=<install_directory> install
|
||||
```
|
||||
|
||||
In addition, platform specific configuration options can be specified with the
|
||||
top-level make command line. These options, such as *PLATFORM_<xyz>* or
|
||||
*FW_<abc>*, are platform specific and described in more details in the
|
||||
*docs/platform/<platform_name>.md* files and
|
||||
*docs/firmware/<firmware_name>.md* files.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
OpenSBI is distributed under the terms of the BSD 2-clause license
|
||||
("Simplified BSD License" or "FreeBSD License", SPDX: *BSD-2-Clause*).
|
||||
A copy of this license with OpenSBI copyright can be found in the file
|
||||
[COPYING.BSD].
|
||||
@ -30,308 +148,18 @@ OpenSBI source code also contains code reused from other projects as listed
|
||||
below. The original license text of these projects is included in the source
|
||||
files where the reused code is present.
|
||||
|
||||
* The libfdt source code is disjunctively dual licensed
|
||||
(GPL-2.0+ OR BSD-2-Clause). Some of this project code is used in OpenSBI
|
||||
under the terms of the BSD 2-Clause license. Any contributions to this
|
||||
code must be made under the terms of both licenses.
|
||||
|
||||
See also the [third party notices] file for more information.
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The **RISC-V Supervisor Binary Interface (SBI)** is the recommended interface
|
||||
between:
|
||||
|
||||
1. A platform-specific firmware running in M-mode and a bootloader, a
|
||||
hypervisor or a general-purpose OS executing in S-mode or HS-mode.
|
||||
2. A hypervisor running in HS-mode and a bootloader or a general-purpose OS
|
||||
executing in VS-mode.
|
||||
|
||||
The *RISC-V SBI specification* is maintained as an independent project by the
|
||||
RISC-V Foundation on [Github].
|
||||
|
||||
The goal of the OpenSBI project is to provide an open-source reference
|
||||
implementation of the RISC-V SBI specifications for platform-specific firmwares
|
||||
executing in M-mode (case 1 mentioned above). An OpenSBI implementation can be
|
||||
easily extended by RISC-V platform and system-on-chip vendors to fit a
|
||||
particular hardware configuration.
|
||||
|
||||
The main component of OpenSBI is provided in the form of a platform-independent
|
||||
static library **libsbi.a** implementing the SBI interface. A firmware or
|
||||
bootloader implementation can link against this library to ensure conformance
|
||||
with the SBI interface specifications. *libsbi.a* also defines an interface for
|
||||
integrating with platform-specific operations provided by the platform firmware
|
||||
implementation (e.g. console access functions, inter-processor interrupt
|
||||
control, etc).
|
||||
|
||||
To illustrate the use of the *libsbi.a* library, OpenSBI also provides a set of
|
||||
platform-specific support examples. For each example, a platform-specific
|
||||
static library *libplatsbi.a* can be compiled. This library implements
|
||||
SBI call processing by integrating *libsbi.a* with the necessary
|
||||
platform-dependent hardware manipulation functions. For all supported platforms,
|
||||
OpenSBI also provides several runtime firmware examples built using the platform
|
||||
*libplatsbi.a*. These example firmwares can be used to replace the legacy
|
||||
*riscv-pk* bootloader (aka BBL) and enable the use of well-known bootloaders
|
||||
such as [U-Boot].
|
||||
|
||||
Supported SBI version
|
||||
---------------------
|
||||
Currently, OpenSBI fully supports SBI specification *v0.2*. OpenSBI also
|
||||
supports Hart State Management (HSM) SBI extension starting from OpenSBI v0.7.
|
||||
HSM extension allows S-mode software to boot all the harts a defined order
|
||||
rather than legacy method of random booting of harts. As a result, many
|
||||
required features such as CPU hotplug, kexec/kdump can also be supported easily
|
||||
in S-mode. HSM extension in OpenSBI is implemented in a non-backward compatible
|
||||
manner to reduce the maintenance burden and avoid confusion. That's why, any
|
||||
S-mode software using OpenSBI will not be able to boot more than 1 hart if HSM
|
||||
extension is not supported in S-mode.
|
||||
|
||||
Linux kernel already supports SBI v0.2 and HSM SBI extension starting from
|
||||
**v5.7-rc1**. If you are using an Linux kernel older than **5.7-rc1** or any
|
||||
other S-mode software without HSM SBI extension, you should stick to OpenSBI
|
||||
v0.6 to boot all the harts. For a UMP systems, it doesn't matter.
|
||||
|
||||
N.B. Any S-mode boot loader (i.e. U-Boot) doesn't need to support HSM extension,
|
||||
as it doesn't need to boot all the harts. The operating system should be
|
||||
capable enough to bring up all other non-booting harts using HSM extension.
|
||||
|
||||
Required Toolchain and Packages
|
||||
-------------------------------
|
||||
|
||||
OpenSBI can be compiled natively or cross-compiled on a host machine. For
|
||||
cross-compilation, you can build your own toolchain, download a prebuilt one
|
||||
from the [Bootlin toolchain repository] or install a distribution-provided
|
||||
toolchain; if you opt to use LLVM/Clang, most distribution toolchains will
|
||||
support cross-compiling for RISC-V using the same toolchain as your native
|
||||
LLVM/Clang toolchain due to LLVM's ability to support multiple backends in the
|
||||
same binary, so is often an easy way to obtain a working cross-compilation
|
||||
toolchain.
|
||||
|
||||
Toolchains with Position Independent Executable (PIE) support like
|
||||
*riscv64-linux-gnu-gcc*, *riscv64-unknown-freebsd-gcc*, or *Clang/LLVM* are
|
||||
required in order to generate PIE firmware images that can run at arbitrary
|
||||
address with appropriate alignment. Bare-metal GNU toolchains (e.g.
|
||||
*riscv64-unknown-elf-gcc*) cannot be used. *Clang/LLVM* can still generate PIE
|
||||
images if a bare-metal triple is used (e.g. *-target riscv64-unknown-elf*).
|
||||
|
||||
In addition to a toolchain, OpenSBI also requires the following packages on
|
||||
the host:
|
||||
|
||||
1. device-tree-compiler: The device tree compiler for compiling device
|
||||
tree sources (DTS files).
|
||||
2. python3: The python 3.0 (or compatible) language support for various
|
||||
scripts.
|
||||
|
||||
Building and Installing the OpenSBI Platform-Independent Library
|
||||
----------------------------------------------------------------
|
||||
|
||||
The OpenSBI platform-independent static library *libsbi.a* can be compiled
|
||||
natively or it can be cross-compiled on a host with a different base
|
||||
architecture than RISC-V.
|
||||
|
||||
For cross-compiling, the environment variable *CROSS_COMPILE* must be defined
|
||||
to specify the name prefix of the RISC-V compiler toolchain executables, e.g.
|
||||
*riscv64-linux-gnu-* if the gcc executable used is *riscv64-linux-gnu-gcc*.
|
||||
|
||||
To build *libsbi.a* simply execute:
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
All compiled binaries as well as the resulting *libsbi.a* static library file
|
||||
will be placed in the *build/lib* directory. To specify an alternate build root
|
||||
directory path, run:
|
||||
```
|
||||
make O=<build_directory>
|
||||
```
|
||||
|
||||
To generate files to be installed for using *libsbi.a* in other projects, run:
|
||||
```
|
||||
make install
|
||||
```
|
||||
|
||||
This will create the *install* directory with all necessary include files
|
||||
copied under the *install/include* directory and the library file copied into
|
||||
the *install/lib* directory. To specify an alternate installation root
|
||||
directory path, run:
|
||||
```
|
||||
make I=<install_directory> install
|
||||
```
|
||||
|
||||
Building and Installing a Reference Platform Static Library and Firmware
|
||||
------------------------------------------------------------------------
|
||||
|
||||
When the *PLATFORM=<platform_subdir>* argument is specified on the make command
|
||||
line, the platform-specific static library *libplatsbi.a* and firmware examples
|
||||
are built for the platform *<platform_subdir>* present in the directory
|
||||
*platform* in the OpenSBI top directory. For example, to compile the platform
|
||||
library and the firmware examples for the QEMU RISC-V *virt* machine,
|
||||
*<platform_subdir>* should be *generic*.
|
||||
|
||||
To build *libsbi.a*, *libplatsbi.a* and the firmware for one of the supported
|
||||
platforms, run:
|
||||
```
|
||||
make PLATFORM=<platform_subdir>
|
||||
```
|
||||
|
||||
An alternate build directory path can also be specified:
|
||||
```
|
||||
make PLATFORM=<platform_subdir> O=<build_directory>
|
||||
```
|
||||
|
||||
The platform-specific library *libplatsbi.a* will be generated in the
|
||||
*build/platform/<platform_subdir>/lib* directory. The platform firmware files
|
||||
will be under the *build/platform/<platform_subdir>/firmware* directory.
|
||||
The compiled firmwares will be available in two different formats: an ELF file
|
||||
and an expanded image file.
|
||||
|
||||
To install *libsbi.a*, *libplatsbi.a*, and the compiled firmwares, run:
|
||||
```
|
||||
make PLATFORM=<platform_subdir> install
|
||||
```
|
||||
|
||||
This will copy the compiled platform-specific libraries and firmware files
|
||||
under the *install/platform/<platform_subdir>/* directory. An alternate
|
||||
install root directory path can be specified as follows:
|
||||
```
|
||||
make PLATFORM=<platform_subdir> I=<install_directory> install
|
||||
```
|
||||
|
||||
In addition, platform-specific configuration options can be specified with the
|
||||
top-level make command line. These options, such as *PLATFORM_<xyz>* or
|
||||
*FW_<abc>*, are platform-specific and described in more details in the
|
||||
*docs/platform/<platform_name>.md* files and
|
||||
*docs/firmware/<firmware_name>.md* files.
|
||||
|
||||
All OpenSBI platforms support Kconfig style build-time configuration. Users
|
||||
can change the build-time configuration of a platform using a graphical
|
||||
interface as follows:
|
||||
```
|
||||
make PLATFORM=<platform_subdir> menuconfig
|
||||
```
|
||||
|
||||
Alternately, an OpenSBI platform can have multiple default configurations
|
||||
and users can select a custom default configuration as follows:
|
||||
```
|
||||
make PLATFORM=<platform_subdir> PLATFORM_DEFCONFIG=<platform_custom_defconfig>
|
||||
```
|
||||
|
||||
Building 32-bit / 64-bit OpenSBI Images
|
||||
---------------------------------------
|
||||
By default, building OpenSBI generates 32-bit or 64-bit images based on the
|
||||
supplied RISC-V cross-compile toolchain. For example if *CROSS_COMPILE* is set
|
||||
to *riscv64-linux-gnu-*, 64-bit OpenSBI images will be generated. If building
|
||||
32-bit OpenSBI images, *CROSS_COMPILE* should be set to a toolchain that is
|
||||
pre-configured to generate 32-bit RISC-V codes, like *riscv32-linux-gnu-*.
|
||||
|
||||
However it's possible to explicitly specify the image bits we want to build with
|
||||
a given RISC-V toolchain. This can be done by setting the environment variable
|
||||
*PLATFORM_RISCV_XLEN* to the desired width, for example:
|
||||
|
||||
```
|
||||
export CROSS_COMPILE=riscv64-linux-gnu-
|
||||
export PLATFORM_RISCV_XLEN=32
|
||||
```
|
||||
|
||||
will generate 32-bit OpenSBI images. And vice vesa.
|
||||
|
||||
Building with Clang/LLVM
|
||||
------------------------
|
||||
|
||||
OpenSBI can also be built with Clang/LLVM. To build with just Clang but keep
|
||||
the default binutils (which will still use the *CROSS_COMPILE* prefix if
|
||||
defined), override the *CC* make variable with:
|
||||
```
|
||||
make CC=clang
|
||||
```
|
||||
|
||||
To build with a full LLVM-based toolchain, not just Clang, enable the *LLVM*
|
||||
option with:
|
||||
```
|
||||
make LLVM=1
|
||||
```
|
||||
|
||||
To build with a specific version of LLVM, a path to a directory containing the
|
||||
LLVM tools can be provided:
|
||||
```
|
||||
make LLVM=/path/to/llvm/
|
||||
```
|
||||
|
||||
If you have versioned llvm tools you would like to use, such as `clang-17`, the LLVM variable can
|
||||
be set as:
|
||||
```
|
||||
make LLVM=-17
|
||||
```
|
||||
|
||||
When using Clang, *CROSS_COMPILE* often does not need to be defined unless
|
||||
using GNU binutils with prefixed binary names. *PLATFORM_RISCV_XLEN* will be
|
||||
used to infer a default triple to pass to Clang, so if *PLATFORM_RISCV_XLEN*
|
||||
itself defaults to an undesired value then prefer setting that rather than the
|
||||
full triple via *CROSS_COMPILE*. If *CROSS_COMPILE* is nonetheless defined,
|
||||
rather than being used as a prefix for the executable name, it will instead be
|
||||
passed via the `--target` option with the trailing `-` removed, so must be a
|
||||
valid triple.
|
||||
|
||||
These can also be mixed; for example using a GCC cross-compiler but LLVM
|
||||
binutils would be:
|
||||
```
|
||||
make CC=riscv64-linux-gnu-gcc LLVM=1
|
||||
```
|
||||
|
||||
These variables must be passed for all the make invocations described in this
|
||||
document.
|
||||
|
||||
NOTE: Using Clang with a `riscv*-linux-gnu` GNU binutils linker has been seen
|
||||
to produce broken binaries with missing relocations; it is therefore currently
|
||||
recommended that this combination be avoided.
|
||||
|
||||
Building with timestamp and compiler info
|
||||
-----------------------------------------
|
||||
|
||||
When doing development, we may want to know the build time and compiler info
|
||||
for debug purpose. OpenSBI can also be built with timestamp and compiler info.
|
||||
To build with those info and print it out at boot time, we can just simply add
|
||||
`BUILD_INFO=y`, like:
|
||||
```
|
||||
make BUILD_INFO=y
|
||||
```
|
||||
|
||||
But if you have used `BUILD_INFO=y`, and want to switch back to `BUILD_INFO=n`,
|
||||
you must do
|
||||
```
|
||||
make clean
|
||||
```
|
||||
before the next build.
|
||||
|
||||
NOTE: Using `BUILD_INFO=y` without specifying SOURCE_DATE_EPOCH will violate
|
||||
[reproducible builds]. This definition is ONLY for development and debug
|
||||
purpose, and should NOT be used in a product which follows "reproducible
|
||||
builds".
|
||||
|
||||
Building with optimization off for debugging
|
||||
--------------------------------------------
|
||||
|
||||
When debugging OpenSBI, we may want to turn off the compiler optimization and
|
||||
make debugging produce the expected results for a better debugging experience.
|
||||
To build with optimization off we can just simply add `DEBUG=1`, like:
|
||||
```
|
||||
make DEBUG=1
|
||||
```
|
||||
|
||||
This definition is ONLY for development and debug purpose, and should NOT be
|
||||
used in a product build.
|
||||
1. The libfdt source code is disjunctively dual licensed
|
||||
(GPL-2.0+ OR BSD-2-Clause). Some of this project code is used in OpenSBI
|
||||
under the terms of the BSD 2-Clause license. Any contributions to this
|
||||
code must be made under the terms of both licenses.
|
||||
|
||||
Contributing to OpenSBI
|
||||
-----------------------
|
||||
|
||||
The OpenSBI project encourages and welcomes contributions. Contributions should
|
||||
follow the rules described in the OpenSBI [Contribution Guideline] document.
|
||||
follow the rules described in OpenSBI [Contribution Guideline] document.
|
||||
In particular, all patches sent should contain a Signed-off-by tag.
|
||||
|
||||
The [Contributors List] document provides a list of individuals and
|
||||
organizations actively contributing to the OpenSBI project.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
@ -340,16 +168,13 @@ Detailed documentation of various aspects of OpenSBI can be found under the
|
||||
|
||||
* [Contribution Guideline]: Guideline for contributing code to OpenSBI project
|
||||
* [Library Usage]: API documentation of OpenSBI static library *libsbi.a*
|
||||
* [Platform Requirements]: Requirements for using OpenSBI on a platform
|
||||
* [Platform Support Guide]: Guideline for implementing support for new platforms
|
||||
* [Platform Documentation]: Documentation of the platforms currently supported.
|
||||
* [Firmware Documentation]: Documentation for the different types of firmware
|
||||
examples build supported by OpenSBI.
|
||||
* [Domain Support]: Documentation for the OpenSBI domain support which helps
|
||||
users achieve system-level partitioning using OpenSBI.
|
||||
|
||||
OpenSBI source code is also well documented. For source level documentation,
|
||||
doxygen style is used. Please refer to the [Doxygen manual] for details on this
|
||||
doxygen style is used. Please refer to [Doxygen manual] for details on this
|
||||
format.
|
||||
|
||||
Doxygen can be installed on Linux distributions using *.deb* packages using
|
||||
@ -390,18 +215,12 @@ make I=<install_directory> install_docs
|
||||
|
||||
[Github]: https://github.com/riscv/riscv-sbi-doc
|
||||
[U-Boot]: https://www.denx.de/wiki/U-Boot/SourceCode
|
||||
[Bootlin toolchain repository]: https://toolchains.bootlin.com/
|
||||
[COPYING.BSD]: COPYING.BSD
|
||||
[SPDX]: http://spdx.org/licenses/
|
||||
[Contribution Guideline]: docs/contributing.md
|
||||
[Contributors List]: CONTRIBUTORS.md
|
||||
[Library Usage]: docs/library_usage.md
|
||||
[Platform Requirements]: docs/platform_requirements.md
|
||||
[Platform Support Guide]: docs/platform_guide.md
|
||||
[Platform Documentation]: docs/platform/platform.md
|
||||
[Firmware Documentation]: docs/firmware/fw.md
|
||||
[Domain Support]: docs/domain_support.md
|
||||
[Doxygen manual]: http://www.doxygen.nl/manual/index.html
|
||||
[Kendryte standalone SDK]: https://github.com/kendryte/kendryte-standalone-sdk
|
||||
[third party notices]: ThirdPartyNotices.md
|
||||
[reproducible builds]: https://reproducible-builds.org
|
||||
[Doxygen manual]: http://www.stack.nl/~dimitri/doxygen/manual.html
|
||||
|
||||
|
@ -1,18 +0,0 @@
|
||||
Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||
|
||||
Third Party Notices
|
||||
===================
|
||||
|
||||
This project includes or partly uses code from the following open source
|
||||
software subject to the following open source licenses.
|
||||
|
||||
libfdt
|
||||
------
|
||||
|
||||
Copyright (C) 2016 Free Electrons
|
||||
Copyright (C) 2016 NextThing Co.
|
||||
|
||||
The libfdt source code is disjunctively dual licensed (GPL-2.0+ or
|
||||
BSD-2-Clause). Some of this project code is used in OpenSBI under the terms of
|
||||
the BSD 2-Clause license. The full text of this license can be found in the
|
||||
file [COPYING.BSD](COPYING.BSD).
|
@ -1,18 +1,11 @@
|
||||
OpenSBI Contribution Guideline
|
||||
==============================
|
||||
|
||||
All contributions to OpenSBI must be sent via email patches to the OpenSBI
|
||||
mailing list at `opensbi@lists.infradead.org`
|
||||
|
||||
To join the OpenSBI mailing list, please visit the [OpenSBI infradead page].
|
||||
|
||||
The mailing list based patch approach is preferred over github PRs so that they
|
||||
are visible to a wider audience. All accepted patches on the OpenSBI mailing
|
||||
list will be taken by one of the OpenSBI maintainers and merged into the
|
||||
All contributions to OpenSBI should be sent as GitHub Pull Requests (PRs) to
|
||||
[OpenSBI main repository].
|
||||
|
||||
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 [Linux coding style].
|
||||
2. This project embraces the [Developer Certificate of Origin (DCO)] for
|
||||
contributions. This means that you must agree to the following prior to
|
||||
submitting patches: if you agree with this developer certificate you
|
||||
@ -22,15 +15,17 @@ Every submitted patch must have this tag.
|
||||
followed by a description of the patch content. A blank line and the author
|
||||
Signed-off-by tag must follow this description.
|
||||
4. A commit subject line must start with a prefix followed by a ":". Common
|
||||
prefixes are for example "lib:", "platform:", "firmware:", "docs:", "utils:"
|
||||
and "top:".
|
||||
prefixes are for example "lib:", "platform:", "firmware:", "docs:" and "top:".
|
||||
5. Maintainers should use "Rebase and Merge" when using GitHub to merge pull
|
||||
requests to avoid creating unnecessary merge commits.
|
||||
6. Maintainers should avoid creating branches directly in the main
|
||||
riscv/opensbi repository. Instead, prefer using a fork of the riscv/opensbi main
|
||||
riscv/opensbi repository. Instead prefer using a fork of riscv/opensbi main
|
||||
repository and branches within that fork to create pull requests.
|
||||
7. A maintainer cannot merge his own pull requests in the riscv/opensbi main
|
||||
7. A maintainer cannot merge his own pull requests in riscv/opensbi main
|
||||
repository.
|
||||
8. A pull request must get at least one review from a maintainer.
|
||||
9. A pull request must spend at least 24 hours in review to allow for other
|
||||
developers to review.
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
@ -74,6 +69,6 @@ By making a contribution to this project, I certify that:
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
[OpenSBI main repository]: https://github.com/riscv/opensbi
|
||||
[OpenSBI infradead page]: http://lists.infradead.org/mailman/listinfo/opensbi
|
||||
[Linux coding style]: https://www.kernel.org/doc/html/v4.10/process/coding-style.html
|
||||
[Developer Certificate of Origin (DCO)]: http://developercertificate.org/
|
||||
|
||||
|
@ -1,325 +0,0 @@
|
||||
OpenSBI Domain Support
|
||||
======================
|
||||
|
||||
An OpenSBI domain is a system-level partition (subset) of underlying hardware
|
||||
having its own memory regions (RAM and MMIO devices) and HARTs. The OpenSBI
|
||||
will try to achieve secure isolation between domains using RISC-V platform
|
||||
features such as PMP, ePMP, IOPMP, SiFive Shield, etc.
|
||||
|
||||
Important entities which help implement OpenSBI domain support are:
|
||||
|
||||
* **struct sbi_domain_memregion** - Representation of a domain memory region
|
||||
* **struct sbi_hartmask** - Representation of domain HART set
|
||||
* **struct sbi_domain** - Representation of a domain instance
|
||||
|
||||
Each HART of a RISC-V platform must have an OpenSBI domain assigned to it.
|
||||
The OpenSBI platform support is responsible for populating domains and
|
||||
providing HART id to domain mapping. The OpenSBI domain support will by
|
||||
default assign **the ROOT domain** to all HARTs of a RISC-V platform, so
|
||||
it is not mandatory for the OpenSBI platform support to populate domains.
|
||||
|
||||
Domain Memory Region
|
||||
--------------------
|
||||
|
||||
A domain memory region is represented by **struct sbi_domain_memregion** in
|
||||
OpenSBI and has following details:
|
||||
|
||||
* **order** - The size of a memory region is **2 ^ order** where **order**
|
||||
must be **3 <= order <= __riscv_xlen**
|
||||
* **base** - The base address of a memory region is **2 ^ order**
|
||||
aligned start address
|
||||
* **flags** - The flags of a memory region represent memory type (i.e.
|
||||
RAM or MMIO) and allowed accesses (i.e. READ, WRITE, EXECUTE, etc.)
|
||||
|
||||
Domain Instance
|
||||
---------------
|
||||
|
||||
A domain instance is represented by **struct sbi_domain** in OpenSBI and
|
||||
has following details:
|
||||
|
||||
* **index** - Logical index of this domain
|
||||
* **name** - Name of this domain
|
||||
* **assigned_harts** - HARTs assigned to this domain
|
||||
* **possible_harts** - HARTs possible in this domain
|
||||
* **regions** - Array of memory regions terminated by a memory region
|
||||
with order zero
|
||||
* **boot_hartid** - HART id of the HART booting this domain. The domain
|
||||
boot HART will be started at boot-time if boot HART is possible and
|
||||
assigned for this domain.
|
||||
* **next_addr** - Address of the next booting stage for this domain
|
||||
* **next_arg1** - Arg1 (or 'a1' register) of the next booting stage for
|
||||
this domain
|
||||
* **next_mode** - Privilege mode of the next booting stage for this
|
||||
domain. This can be either S-mode or U-mode.
|
||||
* **system_reset_allowed** - Is domain allowed to reset the system?
|
||||
* **system_suspend_allowed** - Is domain allowed to suspend the system?
|
||||
|
||||
The memory regions represented by **regions** in **struct sbi_domain** have
|
||||
following additional constraints to align with RISC-V PMP requirements:
|
||||
|
||||
* A memory region to protect OpenSBI firmware from S-mode and U-mode
|
||||
should always be present
|
||||
* For two overlapping memory regions, one should be sub-region of another
|
||||
* Two overlapping memory regions should not be of same size
|
||||
* Two overlapping memory regions cannot have same flags
|
||||
* Memory access checks on overlapping address should prefer smallest
|
||||
overlapping memory region flags.
|
||||
|
||||
ROOT Domain
|
||||
-----------
|
||||
|
||||
**The ROOT domain** is the default OpenSBI domain which is assigned by
|
||||
default to all HARTs of a RISC-V platform. The OpenSBI domain support
|
||||
will hand-craft **the ROOT domain** very early at boot-time in the
|
||||
following manner:
|
||||
|
||||
* **index** - Logical index of the ROOT domain is always zero
|
||||
* **name** - Name of the ROOT domain is "root"
|
||||
* **assigned_harts** - At boot-time all valid HARTs of a RISC-V platform
|
||||
are assigned the ROOT domain which changes later based on OpenSBI
|
||||
platform support
|
||||
* **possible_harts** - All valid HARTs of a RISC-V platform are possible
|
||||
HARTs of 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
|
||||
**B)** A memory region of **order=__riscv_xlen** allowing S-mode and
|
||||
U-mode access to full memory address space
|
||||
* **boot_hartid** - Coldboot HART is the HART booting the ROOT domain
|
||||
* **next_addr** - Next booting stage address in coldboot HART scratch
|
||||
space is the next address for the ROOT domain
|
||||
* **next_arg1** - Next booting stage arg1 in coldboot HART scratch space
|
||||
is the next arg1 for the ROOT domain
|
||||
* **next_mode** - Next booting stage mode in coldboot HART scratch space
|
||||
is the next mode for the ROOT domain
|
||||
* **system_reset_allowed** - The ROOT domain is allowed to reset the system
|
||||
* **system_suspend_allowed** - The ROOT domain is allowed to suspend the system
|
||||
|
||||
Domain Effects
|
||||
--------------
|
||||
|
||||
Few noteworthy effects of a system partitioned into domains are as follows:
|
||||
|
||||
* At any point in time, a HART is running in exactly one OpenSBI domain context
|
||||
* The SBI IPI and RFENCE calls from HART A are restricted to the HARTs in
|
||||
domain assigned to HART A
|
||||
* The SBI HSM calls which try to change/read state of HART B from HART A will
|
||||
only work if both HART A and HART B are assigned same domain
|
||||
* A HART running in S-mode or U-mode can only access memory based on the
|
||||
memory regions of the domain assigned to the HART
|
||||
|
||||
Domain Device Tree Bindings
|
||||
---------------------------
|
||||
|
||||
The OpenSBI domains can be described in the **device tree (DT) blob** (or
|
||||
flattened device tree) passed to the OpenSBI firmwares by the previous
|
||||
booting stage. This allows OpenSBI platform support to parse and populate
|
||||
OpenSBI domains from the device tree blob (or flattened device tree).
|
||||
|
||||
### Domain Configuration Node
|
||||
|
||||
All OpenSBI domain description related DT nodes should be under the domain
|
||||
configuration DT node. The **/chosen** DT node is the preferred parent of
|
||||
the domain configuration DT node.
|
||||
|
||||
The DT properties of a domain configuration DT node are as follows:
|
||||
|
||||
* **compatible** (Mandatory) - The compatible string of the domain
|
||||
configuration. This DT property should have value *"opensbi,domain,config"*
|
||||
|
||||
### Domain Memory Region Node
|
||||
|
||||
The domain memory region DT node describes details of a memory region and
|
||||
can be pointed by multiple domain instance DT nodes. The access permissions
|
||||
of the memory region are specified separately in domain instance node.
|
||||
|
||||
The DT properties of a domain memory region DT node are as follows:
|
||||
|
||||
* **compatible** (Mandatory) - The compatible string of the domain memory
|
||||
region. This DT property should have value *"opensbi,domain,memregion"*
|
||||
* **base** (Mandatory) - The base address of the domain memory region. This
|
||||
DT property should have a **2 ^ order** aligned 64 bit address (i.e. two
|
||||
DT cells).
|
||||
* **order** (Mandatory) - The order of the domain memory region. This DT
|
||||
property should have a 32 bit value (i.e. one DT cell) in the range
|
||||
**3 <= order <= __riscv_xlen**.
|
||||
* **mmio** (Optional) - A boolean flag representing whether the domain
|
||||
memory region is a memory-mapped I/O (MMIO) region.
|
||||
* **devices** (Optional) - The list of device DT node phandles for devices
|
||||
which fall under this domain memory region.
|
||||
|
||||
### Domain Instance Node
|
||||
|
||||
The domain instance DT node describes set of possible HARTs, set of memory
|
||||
regions, and other details of a domain instance.
|
||||
|
||||
The DT properties of a domain instance DT node are as follows:
|
||||
|
||||
* **compatible** (Mandatory) - The compatible string of the domain instance.
|
||||
This DT property should have value *"opensbi,domain,instance"*
|
||||
* **possible-harts** (Optional) - The list of CPU DT node phandles for the
|
||||
the domain instance. This list represents the possible HARTs of the
|
||||
domain instance.
|
||||
* **regions** (Optional) - The list of domain memory region DT node phandle
|
||||
and access permissions for the domain instance. Each list entry is a pair
|
||||
of DT node phandle and access permissions. The access permissions are
|
||||
represented as a 32bit bitmask having bits: **M readable** (BIT[0]),
|
||||
**M writeable** (BIT[1]), **M executable** (BIT[2]), **SU readable**
|
||||
(BIT[3]), **SU writable** (BIT[4]), and **SU executable** (BIT[5]).
|
||||
The enforce permission bit (BIT[6]), if set, will lock the permissions
|
||||
in the PMP. This will enforce the permissions on M-mode as well which
|
||||
otherwise will have unrestricted access. This bit must be used with
|
||||
caution because no changes can be made to a PMP entry once its locked
|
||||
until the hart is reset.
|
||||
Any region of a domain defined in DT node cannot have only M-bits set
|
||||
in access permissions i.e. it cannot be an m-mode only accessible region.
|
||||
* **boot-hart** (Optional) - The DT node phandle of the HART booting the
|
||||
domain instance. If coldboot HART is assigned to the domain instance then
|
||||
this DT property is ignored and the coldboot HART is assumed to be the
|
||||
boot HART of the domain instance.
|
||||
* **next-arg1** (Optional) - The 64 bit next booting stage arg1 for the
|
||||
domain instance. If this DT property is not available and coldboot HART
|
||||
is not assigned to the domain instance then **next booting stage arg1 of coldboot HART**
|
||||
is used as default value.
|
||||
* **next-addr** (Optional) - The 64 bit next booting stage address for the
|
||||
domain instance. If this DT property is not available and coldboot HART
|
||||
is not assigned to the domain instance then **0x0** is used as default
|
||||
value. If this DT property is not available and coldboot HART is assigned
|
||||
to the domain instance then **next booting stage address of coldboot HART**
|
||||
is used as default value.
|
||||
* **next-mode** (Optional) - The 32 bit next booting stage mode for the
|
||||
domain instance. The possible values of this DT property are: **0x1**
|
||||
(S-mode), and **0x0** (U-mode). If this DT property is not available
|
||||
and coldboot HART is not assigned to the domain instance then **0x1**
|
||||
is used as default value. If this DT property is not available and
|
||||
coldboot HART is assigned to the domain instance then **next booting
|
||||
stage mode of coldboot HART** is used as default value.
|
||||
* **system-reset-allowed** (Optional) - A boolean flag representing
|
||||
whether the domain instance is allowed to do system reset.
|
||||
* **system-suspend-allowed** (Optional) - A boolean flag representing
|
||||
whether the domain instance is allowed to do system suspend.
|
||||
|
||||
### Assigning HART To Domain Instance
|
||||
|
||||
By default, all HARTs are assigned to **the ROOT domain**. The OpenSBI
|
||||
platform support can provide the HART to domain instance assignment using
|
||||
platform specific callback.
|
||||
|
||||
The HART to domain instance assignment can be parsed from the device tree
|
||||
using optional DT property **opensbi-domain** in each CPU DT node. The
|
||||
value of DT property **opensbi-domain** is the DT phandle of the domain
|
||||
instance DT node. If **opensbi-domain** DT property is not specified then
|
||||
corresponding HART is assigned to **the ROOT domain**.
|
||||
|
||||
### Domain Configuration Only Accessible to OpenSBI
|
||||
|
||||
The software running inside a domain instance should only be aware of
|
||||
devices and hardware resources accessible to itself.
|
||||
|
||||
To hide domain configuration from domain instances, the following should
|
||||
be done:
|
||||
|
||||
* The previous booting stage should preferably provide a separate device
|
||||
tree for each domain instance and mention location of device tree in
|
||||
respective domain instance DT nodes using **next-arg1** DT property.
|
||||
* If domain assigned to a HART does not have separate device tree then
|
||||
OpenSBI platform support should remove all domain configuration details
|
||||
from the device tree passed by previous booting stage before passing it
|
||||
to the next booting stage.
|
||||
|
||||
### Example
|
||||
|
||||
```
|
||||
chosen {
|
||||
opensbi-domains {
|
||||
compatible = "opensbi,domain,config";
|
||||
|
||||
tmem: tmem {
|
||||
compatible = "opensbi,domain,memregion";
|
||||
base = <0x0 0x80100000>;
|
||||
order = <20>;
|
||||
};
|
||||
|
||||
tuart: tuart {
|
||||
compatible = "opensbi,domain,memregion";
|
||||
base = <0x0 0x10011000>;
|
||||
order = <12>;
|
||||
mmio;
|
||||
devices = <&uart1>;
|
||||
};
|
||||
|
||||
allmem: allmem {
|
||||
compatible = "opensbi,domain,memregion";
|
||||
base = <0x0 0x0>;
|
||||
order = <64>;
|
||||
};
|
||||
|
||||
tdomain: trusted-domain {
|
||||
compatible = "opensbi,domain,instance";
|
||||
possible-harts = <&cpu0>;
|
||||
regions = <&tmem 0x3f>, <&tuart 0x3f>;
|
||||
boot-hart = <&cpu0>;
|
||||
next-arg1 = <0x0 0x0>;
|
||||
next-addr = <0x0 0x80100000>;
|
||||
next-mode = <0x0>;
|
||||
system-reset-allowed;
|
||||
system-suspend-allowed;
|
||||
};
|
||||
|
||||
udomain: untrusted-domain {
|
||||
compatible = "opensbi,domain,instance";
|
||||
possible-harts = <&cpu1 &cpu2 &cpu3 &cpu4>;
|
||||
regions = <&tmem 0x0>, <&tuart 0x0>, <&allmem 0x3f>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
timebase-frequency = <10000000>;
|
||||
|
||||
cpu0: cpu@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0x00>;
|
||||
compatible = "riscv";
|
||||
opensbi-domain = <&tdomain>;
|
||||
...
|
||||
};
|
||||
|
||||
cpu1: cpu@1 {
|
||||
device_type = "cpu";
|
||||
reg = <0x01>;
|
||||
compatible = "riscv";
|
||||
opensbi-domain = <&udomain>;
|
||||
...
|
||||
};
|
||||
|
||||
cpu2: cpu@2 {
|
||||
device_type = "cpu";
|
||||
reg = <0x02>;
|
||||
compatible = "riscv";
|
||||
opensbi-domain = <&udomain>;
|
||||
...
|
||||
};
|
||||
|
||||
cpu3: cpu@3 {
|
||||
device_type = "cpu";
|
||||
reg = <0x03>;
|
||||
compatible = "riscv";
|
||||
opensbi-domain = <&udomain>;
|
||||
...
|
||||
};
|
||||
|
||||
cpu4: cpu@4 {
|
||||
device_type = "cpu";
|
||||
reg = <0x04>;
|
||||
compatible = "riscv";
|
||||
opensbi-domain = <&udomain>;
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
uart1: serial@10011000 {
|
||||
...
|
||||
};
|
||||
```
|
@ -44,7 +44,7 @@ PROJECT_NUMBER = "v@@OPENSBI_MAJOR@@.@@OPENSBI_MINOR@@"
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
# quick idea about the purpose of the project. Keep the description short.
|
||||
|
||||
PROJECT_BRIEF = "Open source implemenation of the supervisor binary interface"
|
||||
PROJECT_BRIEF = "Open source implemenation of supervisor binary interface"
|
||||
|
||||
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
|
||||
# in the documentation. The maximum height of the logo should not exceed 55
|
||||
@ -793,11 +793,7 @@ WARN_LOGFILE =
|
||||
INPUT = @@SRC_DIR@@/README.md \
|
||||
@@SRC_DIR@@/docs/contributing.md \
|
||||
@@SRC_DIR@@/docs/platform_guide.md \
|
||||
@@SRC_DIR@@/docs/platform_requirements.md \
|
||||
@@SRC_DIR@@/docs/library_usage.md \
|
||||
@@SRC_DIR@@/docs/domain_support.md \
|
||||
@@SRC_DIR@@/docs/opensbi_config.md \
|
||||
@@SRC_DIR@@/docs/writing_tests.md \
|
||||
@@SRC_DIR@@/docs/firmware \
|
||||
@@SRC_DIR@@/docs/platform \
|
||||
@@SRC_DIR@@/include \
|
||||
@ -952,7 +948,7 @@ FILTER_SOURCE_PATTERNS =
|
||||
# (index.html). This can be useful if you have a project on for instance GitHub
|
||||
# and want to reuse the introduction page also for the doxygen output.
|
||||
|
||||
USE_MDFILE_AS_MAINPAGE = README.md
|
||||
USE_MDFILE_AS_MAINPAGE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to source browsing
|
||||
@ -1448,7 +1444,7 @@ DISABLE_INDEX = NO
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
GENERATE_TREEVIEW = YES
|
||||
GENERATE_TREEVIEW = NO
|
||||
|
||||
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
|
||||
# doxygen will group on one line in the generated HTML documentation.
|
||||
|
32
docs/external/coreboot.md
vendored
32
docs/external/coreboot.md
vendored
@ -1,32 +0,0 @@
|
||||
OpenSBI as coreboot payload
|
||||
===========================
|
||||
|
||||
[coreboot] is a free/libre and open source firmware platform support multiple
|
||||
hardware architectures(x86, ARMv7, arm64, PowerPC64, MIPS and RISC-V) and
|
||||
diverse hardware models. In RISC-V world, coreboot currently support HiFive
|
||||
Unleashed with OpenSBI as a payload to boot GNU/Linux:
|
||||
|
||||
```
|
||||
SiFive HiFive unleashed's original firmware boot process:
|
||||
+-----------+
|
||||
+------+ +------+ +------+ | BBL |
|
||||
| MSEL |--->| ZSBL |--->| FSBL |--->| +-------+
|
||||
+------+ +------+ +------+ | | linux |
|
||||
+---+-------+
|
||||
|
||||
coreboot boot process:
|
||||
+---------------------------------------------------------------------+
|
||||
| coreboot |
|
||||
+------+ +------+ | +-----------+ +----------+ +----------+ +-----------------------+
|
||||
| MSEL |-->| ZSBL |-->| | bootblock |->| romstage |->| ramstage |->| payload ( OpenSBI) |
|
||||
+------+ +------+ | +-----------+ +----------+ +----------+ | +-------+ |
|
||||
| | | linux | |
|
||||
+---------------------------------------------+-------------+-------+-+
|
||||
```
|
||||
|
||||
The upstreaming work is still in progress. There's a [documentation] about how
|
||||
to build [out-of-tree code] to load OpenSBI.
|
||||
|
||||
[coreboot]: https://www.coreboot.org/
|
||||
[documentation]: https://github.com/hardenedlinux/embedded-iot_profile/blob/master/docs/riscv/hifiveunleashed_coreboot_notes-en.md
|
||||
[out-of-tree code]: https://github.com/hardenedlinux/coreboot-HiFiveUnleashed
|
@ -9,29 +9,12 @@ OpenSBI generic library code. The supported firmwares type will differ in how
|
||||
the arguments passed by the platform early boot stage are handled, as well as
|
||||
how the boot stage following the firmware will be handled and executed.
|
||||
|
||||
The previous booting stage will pass information via the following registers
|
||||
of RISC-V CPU:
|
||||
|
||||
* hartid via *a0* register
|
||||
* device tree blob address in memory via *a1* register. The address must
|
||||
be aligned to 8 bytes.
|
||||
|
||||
OpenSBI currently supports three different types of firmwares.
|
||||
|
||||
Firmware with Dynamic Information (*FW_DYNAMIC*)
|
||||
------------------------------------------------
|
||||
|
||||
The *FW_DYNAMIC* firmware gets information about the next booting stage entry,
|
||||
e.g. a bootloader or an OS kernel, from previous booting stage at runtime.
|
||||
|
||||
A *FW_DYNAMIC* firmware is particularly useful when the booting stage executed
|
||||
prior to OpenSBI firmware is capable of loading both the OpenSBI firmware
|
||||
and the booting stage binary to follow OpenSBI firmware.
|
||||
OpenSBI currently supports two different types of firmwares.
|
||||
|
||||
Firmware with Jump Address (*FW_JUMP*)
|
||||
--------------------------------------
|
||||
|
||||
The *FW_JUMP* firmware assumes a fixed address of the next booting stage
|
||||
The *FW_JUMP* firmware only handles the address of the next booting stage
|
||||
entry, e.g. a bootloader or an OS kernel, without directly including the
|
||||
binary code for this next stage.
|
||||
|
||||
@ -53,36 +36,26 @@ the booting stage to follow OpenSBI firmware.
|
||||
A *FW_PAYLOAD* firmware is also useful for cases where the booting stage prior
|
||||
to OpenSBI firmware does not pass a *flattened device tree (FDT file)*. In such
|
||||
case, a *FW_PAYLOAD* firmware allows embedding a flattened device tree in the
|
||||
.rodata section of the final firmware.
|
||||
.text section of the final firmware.
|
||||
|
||||
Firmware Configuration and Compilation
|
||||
--------------------------------------
|
||||
|
||||
All firmware types support the following common compile time configuration
|
||||
parameters:
|
||||
All firmware types mandate the definition of the following compile time
|
||||
configuration parameter.
|
||||
|
||||
* **FW_TEXT_START** - Defines the compile time address of the OpenSBI
|
||||
firmware. This configuration parameter is optional and assumed to be
|
||||
`0` if not specified.
|
||||
* **FW_FDT_PATH** - Path to an external flattened device tree binary file to
|
||||
be embedded in the *.rodata* section of the final firmware. If this option
|
||||
is not provided then the firmware will expect the FDT to be passed as an
|
||||
argument by the prior booting stage.
|
||||
* **FW_FDT_PADDING** - Optional zero bytes padding to the embedded flattened
|
||||
device tree binary file specified by **FW_FDT_PATH** option.
|
||||
* **FW_TEXT_ADDR** - Defines the address at which the previous booting stage
|
||||
loads OpenSBI firmware.
|
||||
|
||||
Additionally, each firmware type as a set of type specific configuration
|
||||
parameters. Detailed information for each firmware type can be found in the
|
||||
following documents.
|
||||
|
||||
* *[FW_DYNAMIC]*: The *Firmware with Dynamic Information (FW_DYNAMIC)* is
|
||||
described in more details in the file *fw_dynamic.md*.
|
||||
* *[FW_JUMP]*: The *Firmware with Jump Address (FW_JUMP)* is described in more
|
||||
details in the file *fw_jump.md*.
|
||||
* *[FW_PAYLOAD]*: The *Firmware with Payload (FW_PAYLOAD)* is described in more
|
||||
details in the file *fw_payload.md*.
|
||||
|
||||
[FW_DYNAMIC]: fw_dynamic.md
|
||||
[FW_JUMP]: fw_jump.md
|
||||
[FW_PAYLOAD]: fw_payload.md
|
||||
|
||||
@ -102,18 +75,3 @@ make PLATFORM=<platform_subdir> FW_PAYLOAD_PATH=<payload path>
|
||||
The instructions to build each payload is different and the details can
|
||||
be found in the
|
||||
*docs/firmware/payload_<payload_name>.md* files.
|
||||
|
||||
Options for OpenSBI Firmware behaviors
|
||||
--------------------------------------
|
||||
An optional compile time flag FW_OPTIONS can be used to control the OpenSBI
|
||||
firmware run-time behaviors.
|
||||
|
||||
```
|
||||
make PLATFORM=<platform_subdir> FW_OPTIONS=<options>
|
||||
```
|
||||
|
||||
FW_OPTIONS is a bitwise or'ed value of various options, eg: *FW_OPTIONS=0x1*
|
||||
stands for disabling boot prints from the OpenSBI library.
|
||||
|
||||
For all supported options, please check "enum sbi_scratch_options" in the
|
||||
*include/sbi/sbi_scratch.h* header file.
|
||||
|
@ -1,36 +0,0 @@
|
||||
OpenSBI Firmware with Dynamic Information (FW_DYNAMIC)
|
||||
======================================================
|
||||
|
||||
OpenSBI **firmware with dynamic info (FW_DYNAMIC)** is a firmware which gets
|
||||
information about next booting stage (e.g. a bootloader or an OS) and runtime
|
||||
OpenSBI library options from previous booting stage.
|
||||
|
||||
The previous booting stage will pass information to *FW_DYNAMIC* by creating
|
||||
*struct fw_dynamic_info* in memory and passing its address to *FW_DYNAMIC*
|
||||
via *a2* register of RISC-V CPU. The address must be aligned to 8 bytes on
|
||||
RV64 and 4 bytes on RV32.
|
||||
|
||||
A *FW_DYNAMIC* firmware is particularly useful when the booting stage executed
|
||||
prior to OpenSBI firmware is capable of loading both the OpenSBI firmware and
|
||||
the booting stage binary to follow OpenSBI firmware.
|
||||
|
||||
*FW_DYNAMIC* Compilation
|
||||
------------------------
|
||||
|
||||
A platform can enable *FW_DYNAMIC* firmware using any of the following methods.
|
||||
|
||||
1. Specifying `FW_DYNAMIC=y` on the top level `make` command line.
|
||||
2. Specifying `FW_DYNAMIC=y` in the target platform *objects.mk* configuration
|
||||
file.
|
||||
|
||||
The compiled *FW_DYNAMIC* firmware ELF file is named *fw_dynamic.elf*. It's
|
||||
expanded image file is *fw_dynamic.bin*. Both files are created in the platform
|
||||
specific build directory under the *build/platform/<platform_subdir>/firmware*
|
||||
directory.
|
||||
|
||||
*FW_DYNAMIC* Firmware Configuration Options
|
||||
-------------------------------------------
|
||||
|
||||
The *FW_DYNAMIC* firmware does not require any platform specific configuration
|
||||
parameters because all required information is passed by previous booting stage
|
||||
at runtime via *struct fw_dynamic_info*.
|
@ -1,4 +1,4 @@
|
||||
OpenSBI Firmware with Jump Address (FW_JUMP)
|
||||
OpenSBI Firmware with Jump Address *FW_JUMP*
|
||||
============================================
|
||||
|
||||
OpenSBI **firmware with Jump Address (FW_JUMP)** is a firmware which only
|
||||
@ -6,19 +6,19 @@ handles the address of the next booting stage entry, e.g. a bootloader or an OS
|
||||
kernel, without directly including the binary code for this next stage.
|
||||
|
||||
A *FW_JUMP* firmware is particularly useful when the booting stage executed
|
||||
prior to the OpenSBI firmware is capable of loading both the OpenSBI firmware
|
||||
and the booting stage binary to follow the OpenSBI firmware.
|
||||
prior to OpenSBI firmware is capable of loading both the OpenSBI firmware and
|
||||
the booting stage binary to follow OpenSBI firmware.
|
||||
|
||||
*FW_JUMP* Compilation
|
||||
---------------------
|
||||
|
||||
A platform *FW_JUMP* firmware can be enabled by any of the following methods:
|
||||
A platform *FW_JUMP* firmware can be enabled by any of the following methods.
|
||||
|
||||
1. Specifying `FW_JUMP=y` on the top level `make` command line.
|
||||
2. Specifying `FW_JUMP=y` in the target platform *objects.mk* configuration file.
|
||||
2. Specifying `FW_JUMP=y` in the target platform *config.mk* configuration file.
|
||||
|
||||
The compiled *FW_JUMP* firmware ELF file is named *fw_jump.elf*. Its expanded
|
||||
image file is *fw_jump.bin*. Both files are created in the platform-specific
|
||||
image file is *fw_jump.bin*. Both files are created in the platform specific
|
||||
build directory under the *build/platform/<platform_subdir>/firmware* directory.
|
||||
|
||||
*FW_JUMP* Firmware Configuration Options
|
||||
@ -26,53 +26,27 @@ build directory under the *build/platform/<platform_subdir>/firmware* directory.
|
||||
|
||||
To operate correctly, a *FW_JUMP* firmware requires some configuration
|
||||
parameters to be defined using either the top level `make` command line or the
|
||||
target platform *objects.mk* configuration file. The possible parameters are as
|
||||
follows:
|
||||
target platform *config.mk* configuration file. The possible parameters are as
|
||||
follows.
|
||||
|
||||
* **FW_JUMP_ADDR** - Address of the entry point of the booting stage to be
|
||||
executed following OpenSBI firmware. This address generally corresponds
|
||||
exactly to the address where this next booting stage was loaded.
|
||||
At least one of *FW_JUMP_ADDR* and *FW_JUMP_OFFSET* (see below) should be
|
||||
defined. Compilation errors will result from not defining one of them.
|
||||
|
||||
* **FW_JUMP_OFFSET** - Address offset from the opensbi load address where the
|
||||
entry point of the next booting stage is located. This offset is used as
|
||||
relocatable address of the next booting stage entry point. If *FW_JUMP_ADDR*
|
||||
is also defined, the firmware will prefer *FW_JUMP_ADDR*.
|
||||
executed following OpenSBI firmware. This address generally correspond
|
||||
exactly to the address where this next booting stage was loaded. This is a
|
||||
mandatory parameter. Compilation errors will result from not defining this
|
||||
address.
|
||||
|
||||
* **FW_JUMP_FDT_ADDR** - Address where the *flattened device tree (FDT file)*
|
||||
passed by the prior booting stage will be placed in memory before executing
|
||||
the booting stage following the OpenSBI firmware. If this option is not
|
||||
provided, then the OpenSBI firmware will pass the FDT address passed by the
|
||||
previous booting stage to the next booting stage.
|
||||
|
||||
When using the default *FW_JUMP_FDT_ADDR* with *PLATFORM=generic*, you must
|
||||
ensure *FW_JUMP_FDT_ADDR* is set high enough to avoid overwriting the kernel.
|
||||
You can use the following method (e.g., using bash or zsh):
|
||||
|
||||
```
|
||||
${CROSS_COMPILE}objdump -h $KERNEL_ELF | sort -k 5,5 | awk -n '
|
||||
/^ +[0-9]+ / {addr="0x"$3; size="0x"$5; printf "0x""%x\n",addr+size}' |
|
||||
(( `tail -1` > (FW_JUMP_FDT_ADDR - FW_JUMP_ADDR) )) &&
|
||||
echo fdt overlaps kernel, increase FW_JUMP_FDT_ADDR
|
||||
|
||||
${LLVM}objdump -h --show-lma $KERNEL_ELF | sort -k 5,5 | awk -n '
|
||||
/^ +[0-9]+ / {addr="0x"$3; size="0x"$5; printf "0x""%x\n",addr+size}' |
|
||||
(( `tail -1` > (FW_JUMP_FDT_ADDR - FW_JUMP_ADDR) )) &&
|
||||
echo fdt overlaps kernel, increase FW_JUMP_FDT_ADDR
|
||||
```
|
||||
|
||||
* **FW_JUMP_FDT_OFFSET** - Address offset from the opensbi load address where
|
||||
the FDT will be passed to the next booting stage. This offset is used
|
||||
as relocatable address of the FDT passed to the next booting stage. If
|
||||
*FW_JUMP_FDT_ADDR* is also defined, the firmware will prefer
|
||||
*FW_JUMP_FDT_ADDR*.
|
||||
the booting stage following OpenSBI firmware. If this option is not provided,
|
||||
then OpenSBI firmware will pass zero as the FDT address to the following
|
||||
booting stage.
|
||||
|
||||
*FW_JUMP* Example
|
||||
-----------------
|
||||
|
||||
The *[qemu/virt]* platform illustrates how to configure and use a *FW_JUMP*
|
||||
firmware. Detailed information regarding these platforms can be found in the
|
||||
platform documentation files.
|
||||
The *[qemu/virt]* and *[qemu/sifive_u]* platforms illustrates how to configure
|
||||
and use a *FW_JUMP* firmware. Detailed information regarding these platforms
|
||||
can be found in the platforms documentation files.
|
||||
|
||||
[qemu/virt]: ../platform/qemu_virt.md
|
||||
[qemu/sifive_u]: ../platform/qemu_sifive_u.md
|
||||
|
@ -1,31 +1,31 @@
|
||||
OpenSBI Firmware with Payload (FW_PAYLOAD)
|
||||
OpenSBI Firmware with Payload *FW_PAYLOAD*
|
||||
==========================================
|
||||
|
||||
OpenSBI **firmware with Payload (FW_PAYLOAD)** is a firmware which directly
|
||||
includes the binary for the booting stage to follow the OpenSBI firmware
|
||||
execution. Typically, this payload will be a bootloader or an OS kernel.
|
||||
includes the binary for the booting stage to follow OpenSBI firmware execution.
|
||||
Typically, this payload will be a bootloader or an OS kernel.
|
||||
|
||||
A *FW_PAYLOAD* firmware is particularly useful when the booting stage executed
|
||||
prior to the OpenSBI firmware is not capable of loading both the OpenSBI
|
||||
firmware and the booting stage to follow OpenSBI firmware.
|
||||
prior to OpenSBI firmware is not capable of loading both OpenSBI firmware and
|
||||
the booting stage to follow OpenSBI firmware.
|
||||
|
||||
A *FW_PAYLOAD* firmware is also useful for cases where the booting stage prior
|
||||
to the OpenSBI firmware does not pass a *flattened device tree (FDT file)*. In
|
||||
such a case, a *FW_PAYLOAD* firmware allows embedding a flattened device tree
|
||||
in the .rodata section of the final firmware.
|
||||
to OpenSBI firmware does not pass a *flattened device tree (FDT file)*. In such
|
||||
case, a *FW_PAYLOAD* firmware allows embedding a flattened device tree in the
|
||||
.text section of the final firmware.
|
||||
|
||||
Enabling *FW_PAYLOAD* compilation
|
||||
---------------------------------
|
||||
|
||||
The *FW_PAYLOAD* firmware can be enabled by any of the following methods:
|
||||
The *FW_PAYLOAD* firmware can be enabled by any of the following methods.
|
||||
|
||||
1. Specifying `FW_PAYLOAD=y` on the top level `make` command line.
|
||||
2. Specifying `FW_PAYLOAD=y` in the target platform *objects.mk* configuration
|
||||
2. Specifying `FW_PAYLOAD=y` in the target platform *config.mk* configuration
|
||||
file.
|
||||
|
||||
The compiled *FW_PAYLOAD* firmware ELF file is named *fw_payload.elf*. Its
|
||||
The compiled *FW_PAYLOAD* firmware ELF file is named *fw_jump.elf*. Its
|
||||
expanded image file is *fw_payload.bin*. Both files are created in the
|
||||
platform-specific build directory under the
|
||||
platform specific build directory under the
|
||||
*build/platform/<platform_subdir>/firmware* directory.
|
||||
|
||||
Configuration Options
|
||||
@ -33,11 +33,11 @@ Configuration Options
|
||||
|
||||
A *FW_PAYLOAD* firmware is built according to configuration parameters and
|
||||
options. These configuration parameters can be defined using either the top
|
||||
level `make` command line or the target platform *objects.mk* configuration
|
||||
file. The parameters currently defined are as follows:
|
||||
level `make` command line or the target platform *config.mk* configuration
|
||||
file. The parameters currently defined are as follows.
|
||||
|
||||
* **FW_PAYLOAD_OFFSET** - Offset from the opensbi load address where the payload
|
||||
binary will be linked in the final *FW_PAYLOAD* firmware binary image. This
|
||||
* **FW_PAYLOAD_OFFSET** - Offset from *FW_TEXT_BASE* where the payload binary
|
||||
will be linked in the final *FW_PAYLOAD* firmware binary image. This
|
||||
configuration parameter is mandatory if *FW_PAYLOAD_ALIGN* is not defined.
|
||||
Compilation errors will result from an incorrect definition of
|
||||
*FW_PAYLOAD_OFFSET* or of *FW_PAYLOAD_ALIGN*, or if neither of these
|
||||
@ -48,30 +48,43 @@ file. The parameters currently defined are as follows:
|
||||
*FW_PAYLOAD* firmware binary image. This configuration parameter is mandatory
|
||||
if *FW_PAYLOAD_OFFSET* is not defined. If both *FW_PAYLOAD_OFFSET* and
|
||||
*FW_PAYLOAD_ALIGN* are defined, *FW_PAYLOAD_OFFSET* is used and
|
||||
*FW_PAYLOAD_ALIGN* is ignored.
|
||||
*FW_PAYLOAD_ALIGN* ignored.
|
||||
|
||||
* **FW_PAYLOAD_PATH** - Path to the image file of the next booting stage
|
||||
binary. If this option is not provided then a simple test payload is
|
||||
automatically generated and used as a payload. This test payload executes
|
||||
an infinite `while (1)` loop after printing a message on the platform console.
|
||||
|
||||
* **FW_PAYLOAD_FDT_ADDR** - Address where the FDT passed by the prior booting
|
||||
stage or specified by the *FW_FDT_PATH* parameter and embedded in the
|
||||
*.rodata* section will be placed before executing the next booting stage,
|
||||
that is, the payload firmware. If this option is not provided, then the
|
||||
firmware will pass the FDT address passed by the previous booting stage
|
||||
to the next booting stage.
|
||||
* **FW_PAYLOAD_FDT_PATH** - Path to an external flattened device tree binary
|
||||
file to be embedded in the *.text* section of the final firmware. If this
|
||||
option is not provided and no internal device tree file is specified by the
|
||||
platform (c.f. *FW_PAYLOAD_FDT*), then the firmware will expect the FDT to
|
||||
be passed as an argument by the prior booting stage.
|
||||
|
||||
* **FW_PAYLOAD_FDT_OFFSET** - Address offset from the opensbi load address where
|
||||
the FDT will be passed to the next booting stage. This offset is used as
|
||||
relocatable address of the FDT passed to the next booting stage. If
|
||||
*FW_PAYLOAD_FDT_ADDR* is also defined, the firmware will prefer *FW_PAYLOAD_FDT_ADDR*.
|
||||
* **FW_PAYLOAD_FDT** - Path to an internal flattened device tree binary file
|
||||
defined by the platform code. The file name must match the DTB file name
|
||||
specified in the platform *objects.mk* file with the *platform-dtb-y* entry.
|
||||
This option results in *FW_PAYLOAD_FDT_PATH* to be automatically set.
|
||||
Specifying *FW_PAYLOAD_FDT_PATH* on the `make` command line disables
|
||||
*FW_PAYLOAD_FDT* and the command line specified device tree binary file is
|
||||
used for building the final firmware.
|
||||
|
||||
* **FW_PAYLOAD_FDT_ADDR** - Address where the FDT passed by the prior booting
|
||||
stage or specified by the *FW_PAYLOAD_FDT_PATH* parameter and embedded in
|
||||
the *.text* section will be placed before executing the next booting stage,
|
||||
that is, the payload firmware. If this option is not provided, then the
|
||||
firmware will pass zero as the FDT address to the next booting stage.
|
||||
|
||||
*FW_PAYLOAD* Example
|
||||
--------------------
|
||||
|
||||
The *[qemu/virt]* platforms illustrate how to configure and use a *FW_PAYLOAD*
|
||||
firmware. Detailed information regarding these platforms can be found in the
|
||||
platform documentation files.
|
||||
The *[qemu/virt]* and *[qemu/sifive_u]* platforms illustrates how to configure
|
||||
and use a *FW_PAYLOAD* firmware. Detailed information regarding these platforms
|
||||
can be found in the platforms documentation files.
|
||||
|
||||
The *kendryte/k210* platform also enables build of a *FW_PAYLOAD* using an
|
||||
internally defined device tree file (*FW_PAYLOAD_FDT*).
|
||||
|
||||
[qemu/virt]: ../platform/qemu_virt.md
|
||||
[qemu/sifive_u]: ../platform/qemu_sifive_u.md
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
Linux as a direct payload to OpenSBI
|
||||
====================================
|
||||
|
||||
OpenSBI has the capability to load a Linux kernel image directly in supervisor
|
||||
OpenSBI has the capability to load Linux kernel image directly in supervisor
|
||||
mode. The flattened image generated by the Linux kernel build process can be
|
||||
provided as a payload to OpenSBI.
|
||||
provided as payload to OpenSBI.
|
||||
|
||||
Detailed examples and platform guides can be found in both [QEMU](
|
||||
../platform/qemu_virt.md) and [HiFive Unleashed](../platform/sifive_fu540.md)
|
||||
platform guide respectively.
|
||||
|
||||
Detailed examples can be found in both the [QEMU](../platform/qemu_virt.md)
|
||||
and the [HiFive Unleashed](../platform/sifive_fu540.md) platform guides.
|
||||
|
@ -3,13 +3,36 @@ U-Boot as a payload to OpenSBI
|
||||
|
||||
[U-Boot](https://www.denx.de/wiki/U-Boot) is an open-source primary boot loader.
|
||||
It can be used as first and/or second stage boot loader in an embedded
|
||||
environment. In the context of OpenSBI, U-Boot can be specified as a payload to
|
||||
the OpenSBI firmware, becoming the boot stage following the OpenSBI firmware
|
||||
environment. In the context of OpenSBI, U-boot can be specified as a payload to
|
||||
OpenSBI firmware, becoming the boot stage following OpenSBI firmware
|
||||
execution.
|
||||
|
||||
The current stable upstream code of U-boot does not yet include all patches
|
||||
necessary to fully support OpenSBI. To use U-Boot as an OpenSBI payload, the
|
||||
following out-of-tree patch series must be applied to the upstream U-Boot source
|
||||
code.
|
||||
|
||||
HiFive Unleashed support for U-Boot
|
||||
|
||||
https://lists.denx.de/pipermail/u-boot/2019-February/358058.html
|
||||
|
||||
This patch series enables a single CPU to execute U-Boot. As a result, the next
|
||||
stage boot code such as Linux kernel can also only execute a single CPU. U-Boot
|
||||
SMP support for RISC-V can be enabled with the following additional patches.
|
||||
|
||||
https://lists.denx.de/pipermail/u-boot/2019-February/358393.html
|
||||
|
||||
Building and Generating U-Boot images
|
||||
=====================================
|
||||
Please refer to the U-Boot build documentation for detailed instructions on
|
||||
how to build U-Boot image and boot high level operating systems from U-Boot
|
||||
prompt.
|
||||
Please refer to U-Boot build documentation for detailed instructions on how to build U-Boot images.
|
||||
|
||||
Once U-Boot images are built, Linux kernel image need to be converted to a format
|
||||
that U-Boot understands.
|
||||
|
||||
```
|
||||
<uboot-dir>/tools/mkimage -A riscv -O linux -T kernel -C none -a 0x80200000 -e 0x80200000 -n Linux -d \
|
||||
<linux_build_directory>arch/riscv/boot/Image \
|
||||
<linux_build_directory>/arch/riscv/boot/uImage
|
||||
```
|
||||
|
||||
Copy the uImage to your tftpboot server path if network boot is required.
|
||||
|
@ -3,46 +3,46 @@ OpenSBI Library Usage
|
||||
|
||||
OpenSBI provides two types of static libraries:
|
||||
|
||||
1. *libsbi.a* - A platform-independent generic static library implementing the
|
||||
interface defined by the SBI specifications. Platform-specific processing
|
||||
1. *libsbi.a* - A platform independent generic static library implementing the
|
||||
interface defined by the SBI specifications. Platform specific processing
|
||||
hooks for the execution of this interface must be provided by the firmware or
|
||||
bootloader linking with this library. This library is installed as
|
||||
*<install_directory>/lib/libsbi.a*
|
||||
2. *libplatsbi.a* - An example platform-specific static library integrating
|
||||
*libsbi.a* with platform-specific hooks. This library is available only for
|
||||
2. *libplatsbi.a* - An example platform specific static library integrating
|
||||
*libsbi.a* with platform specific hooks. This library is available only for
|
||||
the platforms supported by OpenSBI. This library is installed as
|
||||
*<install_directory>/platform/<platform_subdir>/lib/libplatsbi.a*
|
||||
|
||||
Implementations may choose either *libsbi.a* or *libplatsbi.a* to link with
|
||||
their firmware or bootloader. In the case of *libsbi.a*, platform-specific
|
||||
hooks in the form of a *struct sbi_platform* instance need to be provided.
|
||||
their firmware or bootloader. In the case of *libsbi.a*, platform specific
|
||||
hooks in the form of a *struct sbi_platform* instance needs to be provided.
|
||||
|
||||
The platform-specific example firmwares provided by OpenSBI are not mandatory.
|
||||
An implementation may choose to link the OpenSBI generic static library together
|
||||
with an M-mode firmware or bootloader providing the hardware-specific hooks.
|
||||
Since OpenSBI is a statically linked library, users must ensure that the
|
||||
license of these external components is compatible with the OpenSBI license.
|
||||
The platform specific example firmwares provided by OpenSBI are not mandatory.
|
||||
An implementation may choose to link OpenSBI generic static library together
|
||||
with an M-mode firmware or bootloader providing hardware specific hooks. Since
|
||||
OpenSBI is a statically linked library, users must ensure that the license of
|
||||
these external components is compatible with OpenSBI license.
|
||||
|
||||
Constraints on OpenSBI usage from external firmware
|
||||
---------------------------------------------------
|
||||
|
||||
Users have to ensure that an external firmware or bootloader linking against
|
||||
OpenSBI static libraries (*libsbi.a* or *libplatsbi.a*) is compiled with the
|
||||
OpenSBI static libraries (*libsbi.a* or *libplatsbi.a*) are compiled with the
|
||||
same GCC target options *-mabi*, *-march*, and *-mcmodel*.
|
||||
|
||||
There are only two constraints on calling any OpenSBI library function from an
|
||||
external M-mode firmware or bootloader:
|
||||
|
||||
1. The RISC-V *MSCRATCH* CSR must point to a valid OpenSBI scratch space
|
||||
(i.e. a *struct sbi_scratch* instance).
|
||||
2. The RISC-V *SP* register (i.e. the stack pointer) must be set per-HART
|
||||
pointing to distinct non-overlapping stacks.
|
||||
(i.e. *struct sbi_scratch* instance)
|
||||
2. The RISC-V *SP* register (i.e. stack pointer) must be set per-HART
|
||||
pointing to distinct non-overlapping stacks
|
||||
|
||||
The most important functions from an external firmware or bootloader
|
||||
perspective are *sbi_init()* and *sbi_trap_handler()*.
|
||||
|
||||
In addition to the above constraints, the external firmware or bootloader must
|
||||
ensure that interrupts are disabled in the *MSTATUS* and *MIE* CSRs when calling
|
||||
ensure that interrupts are disabled in *MSTATUS* and *MIE* CSRs when calling
|
||||
the functions *sbi_init()* and *sbi_trap_handler()*.
|
||||
|
||||
The *sbi_init()* function should be called by the external firmware or
|
||||
@ -63,23 +63,3 @@ bootloader to service the following interrupts and traps:
|
||||
**Note:** external firmwares or bootloaders can be more conservative by
|
||||
forwarding all traps and interrupts to *sbi_trap_handler()*.
|
||||
|
||||
Definitions of OpenSBI Data Types for the External Firmware
|
||||
-----------------------------------------------------------
|
||||
|
||||
OpenSBI can be built as library using external firmware build system such as EDK2
|
||||
code base (The open source of UEFI firmware implementation) and linked with external
|
||||
firmware drivers based on the external firmware architecture.
|
||||
|
||||
**OPENSBI_EXTERNAL_SBI_TYPES** identifier is introduced to *sbi_types.h* for selecting
|
||||
external header file during the build preprocess in order to define OpensSBI data types
|
||||
based on external firmware data type binding.
|
||||
For example, *bool* is declared as *int* in sbi_types.h. However, in EDK2 build system,
|
||||
*bool* is declared as *BOOLEAN* which is defined as *unsigned char* data type.
|
||||
|
||||
External firmware can define **OPENSBI_EXTERNAL_SBI_TYPES** in CFLAGS and specify it to the
|
||||
header file maintained in its code tree. However, the external build system has to address
|
||||
the additional include directory for the external header file based on its own build system.
|
||||
For example,
|
||||
*-D***OPENSBI_EXTERNAL_SBI_TYPES***=OpensbiTypes.h*
|
||||
Above tells *sbi_types.h* to refer to *OpensbiTypes.h* instead of using original definitions of
|
||||
data types.
|
||||
|
@ -1,91 +0,0 @@
|
||||
OpenSBI Device Tree Configuration Guideline
|
||||
==================================
|
||||
|
||||
Some configurations of OpenSBI's Generic Platform can be described
|
||||
in the **device tree (DT) blob** (or flattened device tree) passed
|
||||
to the OpenSBI firmwares by the previous booting stage. OpenSBI will
|
||||
parse and use these configurations during the boot phase, but delete
|
||||
them from the device tree at the end of cold boot.
|
||||
|
||||
### OpenSBI Configuration Node
|
||||
|
||||
All nodes related to OpenSBI configuration should be under the OpenSBI
|
||||
configuration DT node. The **/chosen** DT node is the preferred parent
|
||||
of the OpenSBI configuration DT node.
|
||||
|
||||
The DT properties of a domain configuration DT node are as follows:
|
||||
|
||||
* **compatible** (Mandatory) - The compatible string of the OpenSBI
|
||||
configuration. This DT property should have value *"opensbi,config"*
|
||||
|
||||
* **cold-boot-harts** (Optional) - If a platform lacks an override
|
||||
cold_boot_allowed() mechanism, this DT property specifies that a
|
||||
set of harts is permitted to perform a cold boot. Otherwise, all
|
||||
harts are allowed to cold boot.
|
||||
|
||||
* **heap-size** (Optional) - When present, the specified value is used
|
||||
as the size of the heap in bytes.
|
||||
|
||||
* **system-suspend-test** (Optional) - When present, enable a system
|
||||
suspend test implementation which simply waits five seconds and issues a WFI.
|
||||
|
||||
The OpenSBI Configuration Node will be deleted at the end of cold boot
|
||||
(replace the node (subtree) with nop tags).
|
||||
|
||||
### Example
|
||||
|
||||
```text
|
||||
chosen {
|
||||
opensbi-config {
|
||||
compatible = "opensbi,config";
|
||||
cold-boot-harts = <&cpu1 &cpu2 &cpu3 &cpu4>;
|
||||
heap-size = <0x400000>;
|
||||
system-suspend-test;
|
||||
};
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
timebase-frequency = <10000000>;
|
||||
|
||||
cpu0: cpu@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0x00>;
|
||||
compatible = "riscv";
|
||||
...
|
||||
};
|
||||
|
||||
cpu1: cpu@1 {
|
||||
device_type = "cpu";
|
||||
reg = <0x01>;
|
||||
compatible = "riscv";
|
||||
...
|
||||
};
|
||||
|
||||
cpu2: cpu@2 {
|
||||
device_type = "cpu";
|
||||
reg = <0x02>;
|
||||
compatible = "riscv";
|
||||
...
|
||||
};
|
||||
|
||||
cpu3: cpu@3 {
|
||||
device_type = "cpu";
|
||||
reg = <0x03>;
|
||||
compatible = "riscv";
|
||||
...
|
||||
};
|
||||
|
||||
cpu4: cpu@4 {
|
||||
device_type = "cpu";
|
||||
reg = <0x04>;
|
||||
compatible = "riscv";
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
uart1: serial@10011000 {
|
||||
...
|
||||
};
|
||||
```
|
@ -1,207 +0,0 @@
|
||||
Andes AE350 SoC Platform
|
||||
========================
|
||||
The AE350 AXI/AHB-based platform N25(F)/NX25(F)/D25F/A25/AX25 CPU with level-one
|
||||
memories, interrupt controller, debug module, AXI and AHB Bus Matrix Controller,
|
||||
AXI-to-AHB Bridge and a collection of fundamental AHB/APB bus IP components
|
||||
pre-integrated together as a system design. The high-quality and configurable
|
||||
AHB/APB IPs suites a majority embedded systems, and the verified platform serves
|
||||
as a starting point to jump start SoC designs.
|
||||
|
||||
To build platform specific library and firmwares, provide the
|
||||
*PLATFORM=generic* parameter to the top level `make` command.
|
||||
|
||||
Platform Options
|
||||
----------------
|
||||
|
||||
The Andes AE350 platform does not have any platform-specific options.
|
||||
|
||||
Building Andes AE350 Platform
|
||||
-----------------------------
|
||||
|
||||
AE350's dts is included in https://github.com/andestech/linux/tree/RISCV-Linux-5.4-ast-v5_1_0-branch
|
||||
|
||||
**Linux Kernel Payload**
|
||||
|
||||
```
|
||||
make PLATFORM=generic FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image FW_FDT_PATH=<ae350.dtb path>
|
||||
```
|
||||
|
||||
DTS Example: (Quad-core AX45MP)
|
||||
-------------------------------
|
||||
|
||||
```
|
||||
compatible = "andestech,ae350";
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
timebase-frequency = <60000000>;
|
||||
|
||||
CPU0: cpu@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0>;
|
||||
status = "okay";
|
||||
compatible = "riscv";
|
||||
riscv,isa = "rv64imafdc";
|
||||
riscv,priv-major = <1>;
|
||||
riscv,priv-minor = <10>;
|
||||
mmu-type = "riscv,sv48";
|
||||
clock-frequency = <60000000>;
|
||||
i-cache-size = <0x8000>;
|
||||
i-cache-sets = <256>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-block-size = <64>;
|
||||
d-cache-size = <0x8000>;
|
||||
d-cache-sets = <128>;
|
||||
d-cache-line-size = <64>;
|
||||
d-cache-block-size = <64>;
|
||||
next-level-cache = <&L2>;
|
||||
CPU0_intc: interrupt-controller {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
compatible = "riscv,cpu-intc";
|
||||
};
|
||||
};
|
||||
CPU1: cpu@1 {
|
||||
device_type = "cpu";
|
||||
reg = <1>;
|
||||
status = "okay";
|
||||
compatible = "riscv";
|
||||
riscv,isa = "rv64imafdc";
|
||||
riscv,priv-major = <1>;
|
||||
riscv,priv-minor = <10>;
|
||||
mmu-type = "riscv,sv48";
|
||||
clock-frequency = <60000000>;
|
||||
i-cache-size = <0x8000>;
|
||||
i-cache-sets = <256>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-block-size = <64>;
|
||||
d-cache-size = <0x8000>;
|
||||
d-cache-sets = <128>;
|
||||
d-cache-line-size = <64>;
|
||||
d-cache-block-size = <64>;
|
||||
next-level-cache = <&L2>;
|
||||
CPU1_intc: interrupt-controller {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
compatible = "riscv,cpu-intc";
|
||||
};
|
||||
};
|
||||
CPU2: cpu@2 {
|
||||
device_type = "cpu";
|
||||
reg = <2>;
|
||||
status = "okay";
|
||||
compatible = "riscv";
|
||||
riscv,isa = "rv64imafdc";
|
||||
riscv,priv-major = <1>;
|
||||
riscv,priv-minor = <10>;
|
||||
mmu-type = "riscv,sv48";
|
||||
clock-frequency = <60000000>;
|
||||
i-cache-size = <0x8000>;
|
||||
i-cache-sets = <256>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-block-size = <64>;
|
||||
d-cache-size = <0x8000>;
|
||||
d-cache-sets = <128>;
|
||||
d-cache-line-size = <64>;
|
||||
d-cache-block-size = <64>;
|
||||
next-level-cache = <&L2>;
|
||||
CPU2_intc: interrupt-controller {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
compatible = "riscv,cpu-intc";
|
||||
};
|
||||
};
|
||||
CPU3: cpu@3 {
|
||||
device_type = "cpu";
|
||||
reg = <3>;
|
||||
status = "okay";
|
||||
compatible = "riscv";
|
||||
riscv,isa = "rv64imafdc";
|
||||
riscv,priv-major = <1>;
|
||||
riscv,priv-minor = <10>;
|
||||
mmu-type = "riscv,sv48";
|
||||
clock-frequency = <60000000>;
|
||||
i-cache-size = <0x8000>;
|
||||
i-cache-sets = <256>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-block-size = <64>;
|
||||
d-cache-size = <0x8000>;
|
||||
d-cache-sets = <128>;
|
||||
d-cache-line-size = <64>;
|
||||
d-cache-block-size = <64>;
|
||||
next-level-cache = <&L2>;
|
||||
CPU3_intc: interrupt-controller {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
compatible = "riscv,cpu-intc";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
compatible = "andestech,riscv-ae350-soc", "simple-bus";
|
||||
ranges;
|
||||
|
||||
plic0: interrupt-controller@e4000000 {
|
||||
compatible = "riscv,plic0";
|
||||
reg = <0x00000000 0xe4000000 0x00000000 0x02000000>;
|
||||
interrupts-extended = < &CPU0_intc 11 &CPU0_intc 9
|
||||
&CPU1_intc 11 &CPU1_intc 9
|
||||
&CPU2_intc 11 &CPU2_intc 9
|
||||
&CPU3_intc 11 &CPU3_intc 9 >;
|
||||
interrupt-controller;
|
||||
#address-cells = <2>;
|
||||
#interrupt-cells = <2>;
|
||||
riscv,ndev = <71>;
|
||||
};
|
||||
|
||||
plicsw: interrupt-controller@e6400000 {
|
||||
compatible = "andestech,plicsw";
|
||||
reg = <0x00000000 0xe6400000 0x00000000 0x00400000>;
|
||||
interrupts-extended = < &CPU0_intc 3
|
||||
&CPU1_intc 3
|
||||
&CPU2_intc 3
|
||||
&CPU3_intc 3 >;
|
||||
interrupt-controller;
|
||||
#address-cells = <2>;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
plmt0: plmt0@e6000000 {
|
||||
compatible = "andestech,plmt0";
|
||||
reg = <0x00000000 0xe6000000 0x00000000 0x00100000>;
|
||||
interrupts-extended = < &CPU0_intc 7
|
||||
&CPU1_intc 7
|
||||
&CPU2_intc 7
|
||||
&CPU3_intc 7 >;
|
||||
};
|
||||
|
||||
wdt: watchdog@f0500000 {
|
||||
compatible = "andestech,atcwdt200";
|
||||
reg = <0x00000000 0xf0500000 0x00000000 0x00001000>;
|
||||
interrupts = <3 4>;
|
||||
interrupt-parent = <&plic0>;
|
||||
clock-frequency = <15000000>;
|
||||
};
|
||||
|
||||
serial0: serial@f0300000 {
|
||||
compatible = "andestech,uart16550", "ns16550a";
|
||||
reg = <0x00000000 0xf0300000 0x00000000 0x00001000>;
|
||||
interrupts = <9 4>;
|
||||
interrupt-parent = <&plic0>;
|
||||
clock-frequency = <19660800>;
|
||||
current-speed = <38400>;
|
||||
reg-shift = <2>;
|
||||
reg-offset = <32>;
|
||||
reg-io-width = <4>;
|
||||
no-loopback-test = <1>;
|
||||
};
|
||||
|
||||
smu: smu@f0100000 {
|
||||
compatible = "andestech,atcsmu";
|
||||
reg = <0x00000000 0xf0100000 0x00000000 0x00001000>;
|
||||
};
|
||||
};
|
||||
```
|
@ -1,38 +0,0 @@
|
||||
Ariane FPGA SoC Platform
|
||||
========================
|
||||
Ariane is a 6-stage, single issue, in-order CPU which implements the 64-bit
|
||||
RISC-V instruction set. The Ariane FPGA development platform is based on FPGA
|
||||
SoC (which currently supports only Genesys 2 board) and is capable of running
|
||||
Linux.
|
||||
|
||||
The FPGA SoC currently contains the following peripherals:
|
||||
- DDR3 memory controller
|
||||
- SPI controller to connect to an SDCard
|
||||
- Ethernet controller
|
||||
- JTAG port (see debugging section below)
|
||||
- Bootrom containing zero stage bootloader and device tree.
|
||||
|
||||
To build platform specific library and firmwares, provide the
|
||||
*PLATFORM=fpga/ariane* parameter to the top level `make` command.
|
||||
|
||||
Platform Options
|
||||
----------------
|
||||
|
||||
The *Ariane FPGA* platform does not have any platform-specific options.
|
||||
|
||||
Building Ariane FPGA Platform
|
||||
-----------------------------
|
||||
|
||||
**Linux Kernel Payload**
|
||||
|
||||
```
|
||||
make PLATFORM=fpga/ariane FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
||||
```
|
||||
|
||||
Booting Ariane FPGA Platform
|
||||
----------------------------
|
||||
|
||||
**Linux Kernel Payload**
|
||||
|
||||
As Linux kernel image is embedded in the OpenSBI firmware binary, Ariane will
|
||||
directly boot into Linux directly after powered on.
|
@ -1,33 +0,0 @@
|
||||
OpenPiton FPGA SoC Platform
|
||||
========================
|
||||
OpenPiton is the world's first open source, general purpose, multithreaded
|
||||
manycore processor. It is a tiled manycore framework scalable from one to
|
||||
1/2 billion cores. Currently, OpenPiton supports the 64bit Ariane RISC-V
|
||||
processor from ETH Zurich. To this end, Ariane has been equipped with a
|
||||
different L1 cache subsystem that follows a write-through protocol and that has
|
||||
support for cache invalidations and atomics.
|
||||
|
||||
To build platform specific library and firmwares, provide the *PLATFORM=generic*
|
||||
parameter to the top level `make` command.
|
||||
|
||||
Platform Options
|
||||
----------------
|
||||
|
||||
The *OpenPiton* platform does not have any platform-specific options.
|
||||
|
||||
Building Ariane FPGA Platform
|
||||
-----------------------------
|
||||
|
||||
**Linux Kernel Payload**
|
||||
|
||||
```
|
||||
make PLATFORM=generic FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
||||
```
|
||||
|
||||
Booting Ariane FPGA Platform
|
||||
----------------------------
|
||||
|
||||
**Linux Kernel Payload**
|
||||
|
||||
As Linux kernel image is embedded in the OpenSBI firmware binary, Ariane will
|
||||
directly boot into Linux directly after powered on.
|
@ -1,59 +0,0 @@
|
||||
Generic Platform
|
||||
================
|
||||
|
||||
The **Generic** platform is a flattened device tree (FDT) based platform
|
||||
where all platform specific functionality is provided based on FDT passed
|
||||
by previous booting stage. The **Generic** platform allows us to use same
|
||||
OpenSBI firmware binaries on various emulators, simulators, FPGAs, and
|
||||
boards.
|
||||
|
||||
By default, the generic FDT platform makes following assumptions:
|
||||
|
||||
1. platform features are default
|
||||
2. platform stack size is default
|
||||
3. platform has no quirks or work-arounds
|
||||
|
||||
The above assumptions (except 1) can be overridden by adding special platform
|
||||
callbacks which will be called based on FDT root node compatible string.
|
||||
|
||||
Users of the generic FDT platform will have to ensure that:
|
||||
|
||||
1. Various FDT based drivers under lib/utils directory are upto date
|
||||
based on their platform requirements
|
||||
2. The FDT passed by previous booting stage has DT compatible strings and
|
||||
DT properties in sync with the FDT based drivers under lib/utils directory
|
||||
3. The FDT must have "stdout-path" DT property in the "/chosen" DT node when
|
||||
a platform has multiple serial ports or consoles
|
||||
4. On multi-HART platform, the FDT must have a DT node for IPI device and
|
||||
lib/utils/ipi directory must have corresponding FDT based IPI driver
|
||||
5. The FDT must have a DT node for timer device and lib/utils/timer directory
|
||||
must have corresponding FDT based timer driver
|
||||
|
||||
To build the platform-specific library and firmware images, provide the
|
||||
*PLATFORM=generic* parameter to the top level `make` command.
|
||||
|
||||
Platform Options
|
||||
----------------
|
||||
|
||||
The *Generic* platform does not have any platform-specific options.
|
||||
|
||||
RISC-V Platforms Using Generic Platform
|
||||
---------------------------------------
|
||||
|
||||
* **Andes AE350 Platform** (*[andes-ae350.md]*)
|
||||
* **QEMU RISC-V Virt Machine** (*[qemu_virt.md]*)
|
||||
* **Renesas RZ/Five SoC** (*[renesas-rzfive.md]*)
|
||||
* **Shakti C-class SoC Platform** (*[shakti_cclass.md]*)
|
||||
* **SiFive HiFive Unleashed** (*[sifive_fu540.md]*)
|
||||
* **Spike** (*[spike.md]*)
|
||||
* **T-HEAD C9xx series Processors** (*[thead-c9xx.md]*)
|
||||
* **OpenPiton FPGA SoC** (*[fpga-openpiton.md]*)
|
||||
|
||||
[andes-ae350.md]: andes-ae350.md
|
||||
[qemu_virt.md]: qemu_virt.md
|
||||
[renesas-rzfive.md]: renesas-rzfive.md
|
||||
[shakti_cclass.md]: shakti_cclass.md
|
||||
[sifive_fu540.md]: sifive_fu540.md
|
||||
[spike.md]: spike.md
|
||||
[thead-c9xx.md]: thead-c9xx.md
|
||||
[fpga-openpiton.md]: fpga-openpiton.md
|
@ -1,22 +0,0 @@
|
||||
|
||||
Nuclei UX600 Platform
|
||||
=====================
|
||||
|
||||
The **Nuclei UX600** is a 64-bit RISC-V Core which is capable of running Linux.
|
||||
|
||||
> Nuclei UX600: single core, pipeline as single-issue and 6~9 variable stages, in-order dispatch and out-of-order write-back, running up to >1.2GHz
|
||||
|
||||
To build the platform-specific library and firmware images, provide the
|
||||
*PLATFORM=nuclei/ux600* parameter to the top level `make` command.
|
||||
|
||||
Platform Options
|
||||
----------------
|
||||
|
||||
The *Nuclei UX600* platform does not have any platform-specific options.
|
||||
|
||||
Building Nuclei UX600 Platform
|
||||
------------------------------
|
||||
|
||||
```
|
||||
make PLATFORM=nuclei/ux600 clean all
|
||||
```
|
@ -1,56 +1,30 @@
|
||||
OpenSBI Supported Platforms
|
||||
===========================
|
||||
|
||||
OpenSBI currently supports the following virtual and hardware platforms:
|
||||
OpenSBI currently supports the following virtual and hardware platforms.
|
||||
|
||||
* **Generic**: Flattened device tree (FDT) based platform where platform
|
||||
specific functionality is provided based on the FDT passed by previous
|
||||
booting stage. More details on this platform can be found in the file
|
||||
*[generic.md]*.
|
||||
* **QEMU RISC-V Virt Machine**: Platform support for QEMU *virt* virtual RISC-V
|
||||
machine. This virtual machine is intended for RISC-V software development and
|
||||
test. More details on this platform can be found in the file *[qemu_virt.md]*.
|
||||
|
||||
* **QEMU RISC-V Virt Machine**: Platform support for the QEMU *virt* virtual
|
||||
RISC-V machine. This virtual machine is intended for RISC-V software
|
||||
development and tests. More details on this platform can be found in the
|
||||
file *[qemu_virt.md]*.
|
||||
* **QEMU SiFive Unleashed Machine**: Platform support for the *sifive_u* QEMU
|
||||
virtual RISC-V machine. This is an emulation machine of the HiFive Unleashed
|
||||
board by SiFive. More details on this platform can be found in the file
|
||||
*[qemu_sifive_u.md]*.
|
||||
|
||||
* **SiFive FU540 SoC**: Platform support for SiFive FU540 SoC used on the
|
||||
HiFive Unleashed board, as well as the *sifive_u* QEMU virtual RISC-V
|
||||
machine. More details on this platform can be found in the file
|
||||
HiFive Unleashed board. This platform is very similar to the *QEMU sifive_u*
|
||||
platform. More details on this platform can be found in the file
|
||||
*[sifive_fu540.md]*.
|
||||
|
||||
* **Kendryte K210 SoC**: Platform support for the Kendryte K210 SoC used on
|
||||
boards such as the Kendryte KD233 or the Sipeed MAIX Dock.
|
||||
|
||||
* **Ariane FPGA SoC**: Platform support for the Ariane FPGA SoC used on
|
||||
Genesys 2 board. More details on this platform can be found in the file
|
||||
*[fpga-ariane.md]*.
|
||||
|
||||
* **Andes AE350 SoC**: Platform support for the Andes's SoC (AE350). More
|
||||
details on this platform can be found in the file *[andes-ae350.md]*.
|
||||
|
||||
* **Spike**: Platform support for the Spike emulator. More
|
||||
details on this platform can be found in the file *[spike.md]*.
|
||||
|
||||
* **Shakti C-class SoC Platform**: Platform support for Shakti C-class
|
||||
processor based SOCs. More details on this platform can be found in the
|
||||
file *[shakti_cclass.md]*.
|
||||
|
||||
* **Renesas RZ/Five SoC**: Platform support for Renesas RZ/Five (R9A07G043F) SoC
|
||||
used on the Renesas RZ/Five SMARC EVK board. More details on this platform can
|
||||
be found in the file *[renesas-rzfive.md]*.
|
||||
boards such as the Kendryte KD233 and Sipeed MAIX Dock boards.
|
||||
|
||||
The code for these supported platforms can be used as example to implement
|
||||
support for other platforms. The *platform/template* directory also provides
|
||||
template files for implementing support for a new platform. The *objects.mk*,
|
||||
*Kconfig*, *configs/defconfig* and *platform.c* template files provides enough
|
||||
comments to facilitate the implementation.
|
||||
template files for implementing support for a new platform. The *object.mk*,
|
||||
*config.mk* and *platform.c* template files provides enough comments to facilitate
|
||||
the implementation.
|
||||
|
||||
[generic.md]: generic.md
|
||||
[qemu_virt.md]: qemu_virt.md
|
||||
[sifive_fu540.md]: sifive_fu540.md
|
||||
[fpga-ariane.md]: fpga-ariane.md
|
||||
[andes-ae350.md]: andes-ae350.md
|
||||
[thead-c910.md]: thead-c910.md
|
||||
[spike.md]: spike.md
|
||||
[shakti_cclass.md]: shakti_cclass.md
|
||||
[renesas-rzfive.md]: renesas-rzfive.md
|
||||
[qemu_sifive_u.md]: qemu_sifive_u.md
|
||||
|
52
docs/platform/qemu_sifive_u.md
Normal file
52
docs/platform/qemu_sifive_u.md
Normal file
@ -0,0 +1,52 @@
|
||||
QEMU SiFive Unleashed Machine Platform
|
||||
======================================
|
||||
|
||||
The **QEMU SiFive Unleashed Machine** is an emulation of the SiFive Unleashed
|
||||
platform.
|
||||
|
||||
To build this platform specific library and firmwares, provide the
|
||||
*PLATFORM=qemu/sifive_u* parameter to the top level `make` command line.
|
||||
|
||||
Platform Options
|
||||
----------------
|
||||
|
||||
The *QEMU SiFive Unleashed Machine* platform does not have any platform specific
|
||||
options.
|
||||
|
||||
Executing on QEMU RISC-V 64bit
|
||||
------------------------------
|
||||
|
||||
**No Payload Case**
|
||||
|
||||
Build:
|
||||
```
|
||||
make PLATFORM=qemu/virt
|
||||
```
|
||||
|
||||
Run:
|
||||
```
|
||||
qemu-system-riscv64 -M sifive_u -m 256M -display none -serial stdio \
|
||||
-kernel build/platform/qemu/sifive_u/firmware/fw_payload.elf
|
||||
```
|
||||
|
||||
**U-Boot as a Payload**
|
||||
|
||||
Note: the command line examples here assume that U-Boot was compiled using
|
||||
the `qemu-riscv64_smode_defconfig` configuration.
|
||||
|
||||
Build:
|
||||
```
|
||||
make PLATFORM=qemu/virt FW_PAYLOAD_PATH=<uboot_build_directory>/u-boot.bin
|
||||
```
|
||||
|
||||
Run:
|
||||
```
|
||||
qemu-system-riscv64 -M sifive_u -m 256M -display none -serial stdio \
|
||||
-kernel build/platform/qemu/sifive_u/firmware/fw_payload.elf
|
||||
```
|
||||
or
|
||||
```
|
||||
qemu-system-riscv64 -M sifive_u -m 256M -display none -serial stdio \
|
||||
-kernel build/platform/qemu/sifive_u/firmware/fw_jump.elf \
|
||||
-device loader,file=<uboot_build_directory>/u-boot.bin,addr=0x80200000
|
||||
```
|
@ -1,34 +1,34 @@
|
||||
QEMU RISC-V Virt Machine Platform
|
||||
=================================
|
||||
|
||||
The **QEMU RISC-V Virt Machine** is a virtual platform created for RISC-V
|
||||
software development and testing. It is also referred to as
|
||||
The **QEMU RISC-V Virt Machine** is virtual platform created for RISC-V
|
||||
software development and testing. It is also referred as
|
||||
*QEMU RISC-V VirtIO machine* because it uses VirtIO devices for network,
|
||||
storage, and other types of IO.
|
||||
|
||||
To build the platform-specific library and firmware images, provide the
|
||||
*PLATFORM=generic* parameter to the top level `make` command.
|
||||
To build platform specific library and firmwares, provide the
|
||||
*PLATFORM=qemu/virt* parameter to the top level `make` command.
|
||||
|
||||
Platform Options
|
||||
----------------
|
||||
|
||||
The *QEMU RISC-V Virt Machine* platform does not have any platform-specific
|
||||
The *QEMU RISC-V Virt Machine* platform does not have any platform specific
|
||||
options.
|
||||
|
||||
Execution on QEMU RISC-V 64-bit
|
||||
-------------------------------
|
||||
Execution on QEMU RISC-V 64bit
|
||||
------------------------------
|
||||
|
||||
**No Payload Case**
|
||||
|
||||
Build:
|
||||
```
|
||||
make PLATFORM=generic
|
||||
make PLATFORM=qemu/virt
|
||||
```
|
||||
|
||||
Run:
|
||||
```
|
||||
qemu-system-riscv64 -M virt -m 256M -nographic \
|
||||
-bios build/platform/generic/firmware/fw_payload.bin
|
||||
qemu-system-riscv64 -M virt -m 256M -display none -serial stdio \
|
||||
-kernel build/platform/qemu/virt/firmware/fw_payload.elf
|
||||
```
|
||||
|
||||
**U-Boot Payload**
|
||||
@ -38,143 +38,46 @@ the `qemu-riscv64_smode_defconfig` configuration.
|
||||
|
||||
Build:
|
||||
```
|
||||
make PLATFORM=generic FW_PAYLOAD_PATH=<uboot_build_directory>/u-boot.bin
|
||||
make PLATFORM=qemu/virt FW_PAYLOAD_PATH=<uboot_build_directory>/u-boot.bin
|
||||
```
|
||||
|
||||
Run:
|
||||
```
|
||||
qemu-system-riscv64 -M virt -m 256M -nographic \
|
||||
-bios build/platform/generic/firmware/fw_payload.elf
|
||||
qemu-system-riscv64 -M virt -m 256M -display none -serial stdio \
|
||||
-kernel build/platform/qemu/virt/firmware/fw_payload.elf
|
||||
```
|
||||
or
|
||||
```
|
||||
qemu-system-riscv64 -M virt -m 256M -nographic \
|
||||
-bios build/platform/generic/firmware/fw_jump.bin \
|
||||
-kernel <uboot_build_directory>/u-boot.bin
|
||||
qemu-system-riscv64 -M virt -m 256M -display none -serial stdio \
|
||||
-kernel build/platform/qemu/virt/firmware/fw_jump.elf \
|
||||
-device loader,file=<uboot_build_directory>/u-boot.bin,addr=0x80400000
|
||||
```
|
||||
|
||||
**Linux Kernel Payload**
|
||||
|
||||
Note: We assume that the Linux kernel is compiled using
|
||||
*arch/riscv/configs/defconfig*. The kernel must be a flattened image (a file
|
||||
called `Image`) rather than an ELF (`vmlinux`).
|
||||
|
||||
Example of building a Linux kernel:
|
||||
```
|
||||
make ARCH=riscv CROSS_COMPILE=riscv64-linux- defconfig
|
||||
make ARCH=riscv CROSS_COMPILE=riscv64-linux- Image
|
||||
```
|
||||
Note: We assume that Linux kernel is compiled using
|
||||
*arch/riscv/configs/defconfig*.
|
||||
|
||||
Build:
|
||||
```
|
||||
make PLATFORM=generic FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
||||
make PLATFORM=qemu/virt FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
||||
```
|
||||
|
||||
Run:
|
||||
```
|
||||
qemu-system-riscv64 -M virt -m 256M -nographic \
|
||||
-bios build/platform/generic/firmware/fw_payload.elf \
|
||||
qemu-system-riscv64 -M virt -m 256M -display none -serial stdio \
|
||||
-kernel build/platform/qemu/virt/firmware/fw_payload.elf \
|
||||
-drive file=<path_to_linux_rootfs>,format=raw,id=hd0 \
|
||||
-device virtio-blk-device,drive=hd0 \
|
||||
-append "root=/dev/vda rw console=ttyS0"
|
||||
```
|
||||
or
|
||||
```
|
||||
qemu-system-riscv64 -M virt -m 256M -nographic \
|
||||
-bios build/platform/generic/firmware/fw_jump.bin \
|
||||
-kernel <linux_build_directory>/arch/riscv/boot/Image \
|
||||
qemu-system-riscv64 -M virt -m 256M -display none -serial stdio \
|
||||
-kernel build/platform/qemu/virt/firmware/fw_jump.elf \
|
||||
-device loader,file=<linux_build_directory>/arch/riscv/boot/Image,addr=0x80400000 \
|
||||
-drive file=<path_to_linux_rootfs>,format=raw,id=hd0 \
|
||||
-device virtio-blk-device,drive=hd0 \
|
||||
-append "root=/dev/vda rw console=ttyS0"
|
||||
```
|
||||
|
||||
|
||||
Execution on QEMU RISC-V 32-bit
|
||||
-------------------------------
|
||||
|
||||
**No Payload Case**
|
||||
|
||||
Build:
|
||||
```
|
||||
make PLATFORM=generic PLATFORM_RISCV_XLEN=32
|
||||
```
|
||||
|
||||
Run:
|
||||
```
|
||||
qemu-system-riscv32 -M virt -m 256M -nographic \
|
||||
-bios build/platform/generic/firmware/fw_payload.bin
|
||||
```
|
||||
|
||||
**U-Boot Payload**
|
||||
|
||||
Note: the command line examples here assume that U-Boot was compiled using
|
||||
the `qemu-riscv32_smode_defconfig` configuration.
|
||||
|
||||
Build:
|
||||
```
|
||||
make PLATFORM=generic PLATFORM_RISCV_XLEN=32 FW_PAYLOAD_PATH=<uboot_build_directory>/u-boot.bin
|
||||
```
|
||||
|
||||
Run:
|
||||
```
|
||||
qemu-system-riscv32 -M virt -m 256M -nographic \
|
||||
-bios build/platform/generic/firmware/fw_payload.elf
|
||||
```
|
||||
or
|
||||
```
|
||||
qemu-system-riscv32 -M virt -m 256M -nographic \
|
||||
-bios build/platform/generic/firmware/fw_jump.bin \
|
||||
-kernel <uboot_build_directory>/u-boot.bin
|
||||
```
|
||||
|
||||
**Linux Kernel Payload**
|
||||
|
||||
Note: We assume that the Linux kernel is compiled using
|
||||
*arch/riscv/configs/rv32_defconfig*.
|
||||
|
||||
Build:
|
||||
```
|
||||
make PLATFORM=generic PLATFORM_RISCV_XLEN=32 FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
||||
```
|
||||
|
||||
Run:
|
||||
```
|
||||
qemu-system-riscv32 -M virt -m 256M -nographic \
|
||||
-bios build/platform/generic/firmware/fw_payload.elf \
|
||||
-drive file=<path_to_linux_rootfs>,format=raw,id=hd0 \
|
||||
-device virtio-blk-device,drive=hd0 \
|
||||
-append "root=/dev/vda rw console=ttyS0"
|
||||
```
|
||||
or
|
||||
```
|
||||
qemu-system-riscv32 -M virt -m 256M -nographic \
|
||||
-bios build/platform/generic/firmware/fw_jump.bin \
|
||||
-kernel <linux_build_directory>/arch/riscv/boot/Image \
|
||||
-drive file=<path_to_linux_rootfs>,format=raw,id=hd0 \
|
||||
-device virtio-blk-device,drive=hd0 \
|
||||
-append "root=/dev/vda rw console=ttyS0"
|
||||
```
|
||||
|
||||
Debugging with GDB
|
||||
------------------
|
||||
|
||||
In a first console start OpenSBI with QEMU:
|
||||
|
||||
```
|
||||
qemu-system-riscv64 -M virt -m 256M -nographic \
|
||||
-bios build/platform/generic/firmware/fw_payload.bin \
|
||||
-gdb tcp::1234 \
|
||||
-S
|
||||
|
||||
```
|
||||
|
||||
Parameter *-gdb tcp::1234* specifies 1234 as the debug port.
|
||||
Parameter *-S* lets QEMU wait at the first instruction.
|
||||
|
||||
In a second console start GDB:
|
||||
|
||||
```
|
||||
gdb build/platform/generic/firmware/fw_payload.elf \
|
||||
-ex 'target remote localhost:1234'
|
||||
|
||||
```
|
||||
|
@ -1,160 +0,0 @@
|
||||
Renesas RZ/Five SoC (R9A07G043F) Platform
|
||||
=========================================
|
||||
The RZ/Five microprocessor includes a single RISC-V CPU Core (Andes AX45MP)
|
||||
1.0 GHz, 16-bit DDR3L/DDR4 interface. Supported interfaces include:
|
||||
- Memory controller for DDR4-1600 / DDR3L-1333 with 16 bits
|
||||
- System RAM (RAM of 128 Kbytes (ECC))
|
||||
- SPI Multi I/O Bus Controller 1ch
|
||||
- SD Card Host Interface/Multimedia Card Interface (SD/MMC) 2ch
|
||||
- Serial Sound Interface (SSI) 4ch
|
||||
- Sampling Rate Converter (SRC) 1ch
|
||||
- USB2.0 host/function interface 2ch (ch0: Host-Function ch1: Host only)
|
||||
- Gigabit Ethernet Interface (GbE) 2ch
|
||||
- Controller Area Network Interface (CAN) 2ch (CAN-FD ISO 11898-1 (CD2014) compliant)
|
||||
- Multi-function Timer Pulse Unit 3 (MTU3a) 9 ch (16 bits × 8 channels, 32 bits × 1 channel)
|
||||
- Port Output Enable 3 (POE3)
|
||||
- Watchdog Timer (WDT) 1ch
|
||||
- General Timer (GTM) 3ch (32bits)
|
||||
- I2C Bus Interface (I2C) 4ch
|
||||
- Serial Communication Interface with FIFO (SCIFA) 5ch
|
||||
- Serial Communication Interface (SCI) 2ch
|
||||
- Renesas Serial Peripheral Interface (RSPI) 3ch
|
||||
- A/D Converter (ADC) 2ch
|
||||
making it ideal for applications such as entry-class social infrastructure
|
||||
gateway control and industrial gateway control. More details can be found at
|
||||
below link [0].
|
||||
|
||||
[0] https://www.renesas.com/us/en/products/microcontrollers-microprocessors/rz-mpus/rzfive-general-purpose-microprocessors-risc-v-cpu-core-andes-ax45mp-single-10-ghz-2ch-gigabit-ethernet
|
||||
|
||||
To build platform specific library and firmwares, provide the
|
||||
*PLATFORM=generic* parameter to the top level make command.
|
||||
|
||||
Platform Options
|
||||
----------------
|
||||
|
||||
The Renesas RZ/Five platform does not have any platform-specific options.
|
||||
|
||||
Building Renesas RZ/Five Platform
|
||||
---------------------------------
|
||||
|
||||
```
|
||||
make PLATFORM=generic
|
||||
```
|
||||
|
||||
DTS Example: (RZ/Five AX45MP)
|
||||
-----------------------------
|
||||
|
||||
```
|
||||
compatible = "renesas,r9a07g043f01", "renesas,r9a07g043";
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
timebase-frequency = <12000000>;
|
||||
|
||||
cpu0: cpu@0 {
|
||||
compatible = "andestech,ax45mp", "riscv";
|
||||
device_type = "cpu";
|
||||
reg = <0x0>;
|
||||
status = "okay";
|
||||
riscv,isa = "rv64imafdc";
|
||||
mmu-type = "riscv,sv39";
|
||||
i-cache-size = <0x8000>;
|
||||
i-cache-line-size = <0x40>;
|
||||
d-cache-size = <0x8000>;
|
||||
d-cache-line-size = <0x40>;
|
||||
clocks = <&cpg CPG_CORE R9A07G043_CLK_I>;
|
||||
|
||||
cpu0_intc: interrupt-controller {
|
||||
#interrupt-cells = <1>;
|
||||
compatible = "riscv,cpu-intc";
|
||||
interrupt-controller;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
soc {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
ranges;
|
||||
|
||||
scif0: serial@1004b800 {
|
||||
compatible = "renesas,scif-r9a07g043",
|
||||
"renesas,scif-r9a07g044";
|
||||
reg = <0 0x1004b800 0 0x400>;
|
||||
interrupts = <412 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<414 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<415 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<413 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<416 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<416 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "eri", "rxi", "txi",
|
||||
"bri", "dri", "tei";
|
||||
clocks = <&cpg CPG_MOD R9A07G043_SCIF0_CLK_PCK>;
|
||||
clock-names = "fck";
|
||||
power-domains = <&cpg>;
|
||||
resets = <&cpg R9A07G043_SCIF0_RST_SYSTEM_N>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
cpg: clock-controller@11010000 {
|
||||
compatible = "renesas,r9a07g043-cpg";
|
||||
reg = <0 0x11010000 0 0x10000>;
|
||||
clocks = <&extal_clk>;
|
||||
clock-names = "extal";
|
||||
#clock-cells = <2>;
|
||||
#reset-cells = <1>;
|
||||
#power-domain-cells = <0>;
|
||||
};
|
||||
|
||||
sysc: system-controller@11020000 {
|
||||
compatible = "renesas,r9a07g043-sysc";
|
||||
reg = <0 0x11020000 0 0x10000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pinctrl: pinctrl@11030000 {
|
||||
compatible = "renesas,r9a07g043-pinctrl";
|
||||
reg = <0 0x11030000 0 0x10000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
gpio-ranges = <&pinctrl 0 0 152>;
|
||||
clocks = <&cpg CPG_MOD R9A07G043_GPIO_HCLK>;
|
||||
power-domains = <&cpg>;
|
||||
resets = <&cpg R9A07G043_GPIO_RSTN>,
|
||||
<&cpg R9A07G043_GPIO_PORT_RESETN>,
|
||||
<&cpg R9A07G043_GPIO_SPARE_RESETN>;
|
||||
};
|
||||
|
||||
plmt0: plmt0@110c0000 {
|
||||
compatible = "andestech,plmt0", "riscv,plmt0";
|
||||
reg = <0x0 0x110c0000 0x0 0x10000>;
|
||||
interrupts-extended = <&cpu0_intc 7>;
|
||||
};
|
||||
|
||||
plic: interrupt-controller@12c00000 {
|
||||
compatible = "renesas,r9a07g043-plic", "andestech,nceplic100";
|
||||
#interrupt-cells = <2>;
|
||||
#address-cells = <0>;
|
||||
riscv,ndev = <511>;
|
||||
interrupt-controller;
|
||||
reg = <0x0 0x12c00000 0x0 0x400000>;
|
||||
clocks = <&cpg CPG_MOD R9A07G043_NCEPLIC_ACLK>;
|
||||
power-domains = <&cpg>;
|
||||
resets = <&cpg R9A07G043_NCEPLIC_ARESETN>;
|
||||
interrupts-extended = <&cpu0_intc 11 &cpu0_intc 9>;
|
||||
};
|
||||
|
||||
plicsw: interrupt-controller@13000000 {
|
||||
compatible = "andestech,plicsw";
|
||||
reg = <0x0 0x13000000 0x0 0x400000>;
|
||||
interrupts-extended = <&cpu0_intc 3>;
|
||||
interrupt-controller;
|
||||
#address-cells = <2>;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
};
|
||||
```
|
@ -1,33 +0,0 @@
|
||||
Shakti C-class SoC Platform
|
||||
===========================
|
||||
C-Class is a member of the SHAKTI family of processors from
|
||||
Indian Institute of Technology - Madras (IIT-M).
|
||||
|
||||
It is an extremely configurable and commercial-grade 5-stage
|
||||
in-order core supporting the standard RV64GCSUN ISA extensions.
|
||||
|
||||
For more details, refer:
|
||||
* https://gitlab.com/shaktiproject/cores/c-class/blob/master/README.md
|
||||
* https://c-class.readthedocs.io/en/latest
|
||||
* https://shakti.org.in
|
||||
|
||||
Platform Options
|
||||
----------------
|
||||
|
||||
The *Shakti C-class SoC* platform does not have any platform-specific
|
||||
options.
|
||||
|
||||
Building Shakti C-class Platform
|
||||
--------------------------------
|
||||
|
||||
**Linux Kernel Payload**
|
||||
|
||||
```
|
||||
make PLATFORM=generic FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image FW_FDT_PATH=<shakti.dtb path>
|
||||
```
|
||||
|
||||
**Test Payload**
|
||||
|
||||
```
|
||||
make PLATFORM=generic FW_FDT_PATH=<shakti.dtb path>
|
||||
```
|
@ -1,74 +1,105 @@
|
||||
SiFive FU540 SoC Platform
|
||||
=========================
|
||||
==========================
|
||||
The FU540-C000 is the world’s first 4+1 64-bit RISC-V SoC from SiFive.
|
||||
The HiFive Unleashed development platform is based on FU540-C000 and capable
|
||||
of running Linux.
|
||||
|
||||
With QEMU v4.2 or above release, the 'sifive_u' machine can be used to test
|
||||
OpenSBI image built for the real hardware as well.
|
||||
|
||||
To build platform specific library and firmwares, provide the
|
||||
*PLATFORM=generic* parameter to the top level `make` command.
|
||||
*PLATFORM=sifive/fu540* parameter to the top level `make` command.
|
||||
|
||||
Platform Options
|
||||
----------------
|
||||
|
||||
The *SiFive FU540 SoC* platform does not have any platform-specific
|
||||
options.
|
||||
As hart0 in the FU540 doesn't have an MMU, only harts 1-4 boot by default.
|
||||
A hart mask i.e. *FU540_ENABLED_HART_MASK* compile time option is provided to
|
||||
select any other hart for booting. Please keep in mind that this is not
|
||||
platform wide option. It can only be specified for FU540 platform in following way.
|
||||
|
||||
```
|
||||
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=Image FU540_ENABLED_HART_MASK=0x02
|
||||
```
|
||||
This will let the board boot only hart1 instead of default 1-4.
|
||||
|
||||
Building SiFive Fu540 Platform
|
||||
------------------------------
|
||||
-----------------------------
|
||||
|
||||
In order to boot SMP Linux in U-Boot, Linux v5.1 (or higher) and latest
|
||||
U-Boot v2020.01 (or higher) should be used.
|
||||
As of this writing, the required Linux kernel and U-Boot patches are not
|
||||
accepted in mainline. Please follow the below instructions to cherry-pick
|
||||
them into your repository.
|
||||
|
||||
[U-Boot patches](../firmware/payload_uboot.md)
|
||||
|
||||
[Linux kernel patches](../firmware/payload_linux.md)
|
||||
|
||||
**Linux Kernel Payload**
|
||||
|
||||
The HiFive Unleashed device tree(DT) is merged in Linux v5.2 release. This
|
||||
DT (device tree) is not backward compatible with the DT passed from FSBL.
|
||||
|
||||
To use Linux v5.2 (or higher), the pre-built DTB (DT binary) from Linux v5.2
|
||||
(or higher) should be used to build SiFive FU540 OpenSBI binaries by using
|
||||
the compile time option *FW_FDT_PATH*.
|
||||
|
||||
```
|
||||
make PLATFORM=generic FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
||||
or
|
||||
(For Linux v5.2 or higher)
|
||||
make PLATFORM=generic FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image FW_FDT_PATH=<hifive-unleashed-a00.dtb path from Linux kernel>
|
||||
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
||||
```
|
||||
|
||||
**U-Boot Payload**
|
||||
|
||||
The command-line example here assumes that U-Boot was compiled using the
|
||||
sifive_fu540_defconfig configuration and with U-Boot v2020.01, and up to
|
||||
v2021.04. sifive_unleashed_defconfig shall be used with v2021.07 or above.
|
||||
|
||||
The command-line example here assumes that U-Boot was compiled using sifive_fu540_defconfig configuration.
|
||||
|
||||
With SMP support enabled in U-Boot:
|
||||
|
||||
```
|
||||
make PLATFORM=generic FW_PAYLOAD_PATH=<u-boot_build_dir>/u-boot-dtb.bin
|
||||
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<u-boot_build_dir>/u-boot.bin
|
||||
```
|
||||
|
||||
Without SMP support enabled in U-Boot:
|
||||
```
|
||||
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<u-boot_build_dir>/u-boot.bin FU540_ENABLED_HART_MASK=0x02
|
||||
```
|
||||
|
||||
**U-Boot & Linux Kernel as a single payload**
|
||||
|
||||
A single monolithic image containing both U-Boot & Linux can also be used if network boot setup is
|
||||
not available.
|
||||
|
||||
1. Generate the uImage from Linux Image.
|
||||
```
|
||||
mkimage -A riscv -O linux -T kernel -C none -a 0x80200000 -e 0x80200000 -n Linux -d \
|
||||
<linux_build_directory>arch/riscv/boot/Image \
|
||||
<linux_build_directory>/arch/riscv/boot/uImage
|
||||
```
|
||||
|
||||
2. Create a temporary image with u-boot.bin as the first payload. The command-line
|
||||
example here assumes that U-Boot was compiled using sifive_fu540_defconfig
|
||||
configuration.
|
||||
```
|
||||
dd if=~/workspace/u-boot-riscv/u-boot.bin of=/tmp/temp.bin bs=1M
|
||||
```
|
||||
3. Append the Linux Kernel image generated in step 1.
|
||||
```
|
||||
dd if=<linux_build_directory>/arch/riscv/boot/uImage of=/tmp/temp.bin bs=1M seek=4
|
||||
```
|
||||
4. Compile OpenSBI with temp.bin (generated in step 3) as payload.
|
||||
```
|
||||
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=/tmp/temp.bin
|
||||
```
|
||||
For U-Boot v2020.07-rc4 or later releases, SPL support was added in U-Boot.
|
||||
Please refer to the detailed U-Boot booting guide available at [U-Boot].
|
||||
|
||||
Flashing the OpenSBI firmware binary to storage media:
|
||||
------------------------------------------------------
|
||||
The first stage boot loader ([FSBL]) expects the storage media to have a GPT
|
||||
partition table. It tries to look for a partition with following GUID to load
|
||||
the next stage boot loader (OpenSBI in this case).
|
||||
-----------------------------------------------------
|
||||
The first stage boot loader([FSBL](https://github.com/sifive/freedom-u540-c000-bootloader))
|
||||
expects the storage media to have a GPT partition table. It tries to look for a
|
||||
partition with following GUID to load the next stage boot loader (OpenSBI in this case).
|
||||
|
||||
```
|
||||
2E54B353-1271-4842-806F-E436D6AF6985
|
||||
```
|
||||
|
||||
That's why the generated firmware binary in above steps should be copied to
|
||||
the partition of the sdcard with above GUID.
|
||||
That's why the generated firmware binary in above steps should be copied to the
|
||||
partition of the sdcard with above GUID.
|
||||
|
||||
```
|
||||
dd if=build/platform/generic/firmware/fw_payload.bin of=/dev/disk2s1 bs=1024
|
||||
dd if=build/platform/sifive/fu540/firmware/fw_payload.bin of=/dev/disk2s1 bs=1024
|
||||
```
|
||||
|
||||
In my case, it is the first partition is **disk2s1** that has been formatted
|
||||
with the above specified GUID.
|
||||
In my case, it is the first partition is **disk2s1** that has been formatted with the
|
||||
above specified GUID.
|
||||
|
||||
In case of a brand new sdcard, it should be formatted with below partition
|
||||
tables as described here.
|
||||
@ -77,7 +108,7 @@ tables as described here.
|
||||
sgdisk --clear \
|
||||
--new=1:2048:67583 --change-name=1:bootloader --typecode=1:2E54B353-1271-4842-806F-E436D6AF6985 \
|
||||
--new=2:264192: --change-name=2:root --typecode=2:0FC63DAF-8483-4772-8E79-3D69D8477DE4 \
|
||||
${DISK}
|
||||
$(DISK)
|
||||
```
|
||||
|
||||
Booting SiFive Fu540 Platform
|
||||
@ -85,55 +116,67 @@ Booting SiFive Fu540 Platform
|
||||
|
||||
**Linux Kernel Payload**
|
||||
|
||||
As Linux kernel image is embedded in the OpenSBI firmware binary, HiFive
|
||||
Unleashed will directly boot into Linux directly after powered on.
|
||||
As Linux kernel image is embedded in the OpenSBI firmware binary, HiFive Unleashed will directly
|
||||
boot into Linux directly after powered on.
|
||||
|
||||
**U-Boot Payload**
|
||||
|
||||
As U-Boot image is used as payload, HiFive Unleashed will boot into a U-Boot
|
||||
prompt. U-Boot tftp boot method can be used to load kernel image in U-Boot
|
||||
prompt. Here are the steps do a tftpboot.
|
||||
As U-Boot image is used as payload, HiFive Unleashed will boot into a U-Boot prompt.
|
||||
U-Boot tftp boot method can be used to load kernel image in U-Boot prompt.
|
||||
Here are the steps do a tftpboot.
|
||||
|
||||
1. Set the mac address of the board.
|
||||
|
||||
```
|
||||
setenv ethaddr <mac address of the board>
|
||||
```
|
||||
2. Set the ip address of the board.
|
||||
|
||||
1. Set the ip address of the board.
|
||||
```
|
||||
setenv ipaddr <ipaddr of the board>
|
||||
```
|
||||
2. Set the tftpboot server IP.
|
||||
3. Set the tftpboot server IP.
|
||||
|
||||
```
|
||||
setenv serverip <ipaddr of the tftp server>
|
||||
```
|
||||
3. Set the network gateway address.
|
||||
4. Set the network gateway address.
|
||||
|
||||
```
|
||||
setenv gatewayip <ipaddress of the network gateway>
|
||||
```
|
||||
4. Load the Linux kernel image from the tftp server.
|
||||
5. Load the Linux kernel image from the tftp server.
|
||||
|
||||
```
|
||||
tftpboot ${kernel_addr_r} <Image path in tftpboot directory>
|
||||
tftpboot ${kernel_addr_r} /sifive/fu540/uImage
|
||||
```
|
||||
5. Load the ramdisk image from the tftp server. This is only required if
|
||||
ramdisk is loaded from tftp server. This step is optional, if rootfs is
|
||||
already part of the kernel or loaded from an external storage by kernel.
|
||||
|
||||
6. Load the ramdisk image from the tftp server. This is only required if ramdisk
|
||||
is loaded from tftp server. This step is optional, if rootfs is already part
|
||||
of the kernel or loaded from an external storage by kernel.
|
||||
|
||||
```
|
||||
tftpboot ${ramdisk_addr_r} <ramdisk path in tftpboot directory>
|
||||
```
|
||||
6. Load the pre-compiled device tree via tftpboot.
|
||||
```
|
||||
tftpboot ${fdt_addr_r} <hifive-unleashed-a00.dtb path in tftpboot directory>
|
||||
tftpboot ${ramdisk_addr_r} /sifive/fu540/uRamdisk
|
||||
```
|
||||
7. Set the boot command-line arguments.
|
||||
|
||||
```
|
||||
setenv bootargs "root=<root partition> rw console=ttySIF0 earlycon=sbi"
|
||||
```
|
||||
(Note: root partition should point to
|
||||
** /dev/ram ** - If a ramdisk is used
|
||||
** root=/dev/mmcblk0pX ** - If a rootfs is already on some other partition
|
||||
of sdcard)
|
||||
|
||||
N.B. root partition should point to
|
||||
** /dev/ram ** - If a ramdisk is used
|
||||
** root=/dev/mmcblk0pX ** - If a rootfs is already on some other partition of sdcard
|
||||
|
||||
8. Now boot into Linux.
|
||||
|
||||
```
|
||||
booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}
|
||||
or
|
||||
(If ramdisk is not loaded from network)
|
||||
booti ${kernel_addr_r} - ${fdt_addr_r}
|
||||
bootm ${kernel_addr_r} ${ramdisk_addr_r} ${fdtcontroladdr}
|
||||
|
||||
```
|
||||
or (if ramdisk is not loaded from network)
|
||||
```
|
||||
bootm ${kernel_addr_r} - ${fdtcontroladdr}
|
||||
```
|
||||
|
||||
**U-Boot & Linux Kernel as a single payload**
|
||||
@ -141,56 +184,19 @@ booti ${kernel_addr_r} - ${fdt_addr_r}
|
||||
At U-Boot prompt execute the following boot command to boot Linux.
|
||||
|
||||
```
|
||||
booti ${kernel_addr_r} - ${fdt_addr_r}
|
||||
bootm ${kernel_addr_r} - ${fdtcontroladdr}
|
||||
```
|
||||
Booting SiFive Fu540 Platform with Microsemi Expansion board
|
||||
------------------------------------------------------------
|
||||
|
||||
QEMU Specific Instructions
|
||||
--------------------------
|
||||
If you want to test OpenSBI with QEMU 'sifive_u' machine, please follow the
|
||||
same instructions above, with the exception of not passing FW_FDT_PATH.
|
||||
|
||||
This is because QEMU generates a device tree blob on the fly based on the
|
||||
command line parameters, and it's compatible with the one used in the upstream
|
||||
Linux kernel.
|
||||
|
||||
When U-Boot v2021.07 (or higher) is used as the payload, as the SiFive FU540
|
||||
DTB for the real hardware is embedded in U-Boot binary itself, due to the same
|
||||
reason above, we need to switch the U-Boot sifive_unleashed_defconfig
|
||||
configuration from **CONFIG_OF_SEPARATE** to **CONFIG_OF_PRIOR_STAGE** so that
|
||||
U-Boot uses the DTB generated by QEMU, and u-boot.bin should be used as the
|
||||
payload image, like:
|
||||
Until the Linux kernel has in-tree support for device trees and mainline u-boot
|
||||
is fully supported on the HiFive Unleashed you can follow these steps to boot
|
||||
Linux with the Microsemi expansion board. This method should not be copied on
|
||||
future boards and is considered a temporary solution until we can use a more
|
||||
standardised boot flow.
|
||||
|
||||
To boot the Linux kernel with a device tree that has support for the Microsemi
|
||||
Expansion board you can include the following line when compiling the firmware:
|
||||
```
|
||||
make PLATFORM=generic FW_PAYLOAD_PATH=<u-boot_build_dir>/u-boot.bin
|
||||
FW_PAYLOAD_FDT="HiFiveUnleashed-MicroSemi-Expansion.dtb"
|
||||
```
|
||||
|
||||
U-Boot v2020.07 release added SPL support to SiFive HiFive Unleashed board,
|
||||
hence a build error will be seen after you switch to **CONFIG_OF_PRIOR_STAGE**.
|
||||
|
||||
```
|
||||
./tools/mkimage: Can't open arch/riscv/dts/hifive-unleashed-a00.dtb: No such file or directory
|
||||
./tools/mkimage: failed to build FIT
|
||||
Makefile:1402: recipe for target 'u-boot.img' failed
|
||||
make: *** [u-boot.img] Error 1
|
||||
```
|
||||
|
||||
The above errors can be safely ignored as we don't run U-Boot SPL under QEMU.
|
||||
|
||||
Run:
|
||||
```
|
||||
qemu-system-riscv64 -M sifive_u -m 256M -nographic \
|
||||
-bios build/platform/generic/firmware/fw_payload.bin
|
||||
```
|
||||
or
|
||||
```
|
||||
qemu-system-riscv64 -M sifive_u -m 256M -nographic \
|
||||
-bios build/platform/generic/firmware/fw_jump.bin \
|
||||
-kernel <uboot_build_dir>/u-boot.bin
|
||||
```
|
||||
|
||||
While the real hardware operates at the 64-bit mode, it's possible for QEMU to
|
||||
test the 32-bit OpenSBI firmware. This can be helpful for testing 32-bit SiFive
|
||||
specific drivers.
|
||||
|
||||
[U-Boot]: https://gitlab.denx.de/u-boot/u-boot/blob/master/doc/board/sifive/fu540.rst
|
||||
[FSBL]: https://github.com/sifive/freedom-u540-c000-bootloader
|
||||
|
@ -1,100 +0,0 @@
|
||||
Spike Simulator Platform
|
||||
========================
|
||||
|
||||
The **Spike** is a RISC-V ISA simulator which implements a functional model
|
||||
of one or more RISC-V harts. The **Spike** compatible virtual platform is
|
||||
also available on QEMU. In fact, we can use same OpenSBI firmware binaries
|
||||
on **Spike** simulator and QEMU Spike machine.
|
||||
|
||||
For more details, refer [Spike on GitHub](https://github.com/riscv/riscv-isa-sim)
|
||||
|
||||
To build the platform-specific library and firmware images, provide the
|
||||
*PLATFORM=generic* parameter to the top level `make` command.
|
||||
|
||||
Platform Options
|
||||
----------------
|
||||
|
||||
The *Spike* platform does not have any platform-specific options.
|
||||
|
||||
Execution on Spike Simulator
|
||||
----------------------------
|
||||
|
||||
**No Payload Case**
|
||||
|
||||
Build:
|
||||
```
|
||||
make PLATFORM=generic
|
||||
```
|
||||
|
||||
Run:
|
||||
```
|
||||
spike build/platform/generic/firmware/fw_payload.elf
|
||||
```
|
||||
|
||||
**Linux Kernel Payload**
|
||||
|
||||
Note: We assume that the Linux kernel is compiled using
|
||||
*arch/riscv/configs/defconfig*.
|
||||
|
||||
Build:
|
||||
```
|
||||
make PLATFORM=generic FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
||||
```
|
||||
|
||||
Run:
|
||||
```
|
||||
spike -m256 \
|
||||
--initrd <path_to_cpio_ramdisk> \
|
||||
--bootargs 'root=/dev/ram rw console=hvc0 earlycon=sbi' \
|
||||
build/platform/generic/firmware/fw_payload.elf
|
||||
```
|
||||
or
|
||||
```
|
||||
spike -m256 \
|
||||
--kernel <linux_build_directory>/arch/riscv/boot/Image \
|
||||
--initrd <path_to_cpio_ramdisk> \
|
||||
--bootargs 'root=/dev/ram rw console=hvc0 earlycon=sbi' \
|
||||
build/platform/generic/firmware/fw_jump.elf
|
||||
```
|
||||
|
||||
Execution on QEMU RISC-V 64-bit
|
||||
-------------------------------
|
||||
|
||||
**No Payload Case**
|
||||
|
||||
Build:
|
||||
```
|
||||
make PLATFORM=generic
|
||||
```
|
||||
|
||||
Run:
|
||||
```
|
||||
qemu-system-riscv64 -M spike -m 256M -nographic \
|
||||
-bios build/platform/generic/firmware/fw_payload.elf
|
||||
```
|
||||
|
||||
**Linux Kernel Payload**
|
||||
|
||||
Note: We assume that the Linux kernel is compiled using
|
||||
*arch/riscv/configs/defconfig*.
|
||||
|
||||
Build:
|
||||
```
|
||||
make PLATFORM=generic FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
||||
```
|
||||
|
||||
Run:
|
||||
```
|
||||
qemu-system-riscv64 -M spike -m 256M -nographic \
|
||||
-bios build/platform/generic/firmware/fw_payload.elf \
|
||||
-initrd <path_to_cpio_ramdisk> \
|
||||
-append "root=/dev/ram rw console=hvc0 earlycon=sbi"
|
||||
```
|
||||
or
|
||||
```
|
||||
qemu-system-riscv64 -M spike -m 256M -nographic \
|
||||
-bios build/platform/generic/firmware/fw_jump.elf \
|
||||
-kernel <linux_build_directory>/arch/riscv/boot/Image \
|
||||
-initrd <path_to_cpio_ramdisk> \
|
||||
-append "root=/dev/ram rw console=hvc0 earlycon=sbi"
|
||||
```
|
@ -1,27 +0,0 @@
|
||||
T-HEAD C9xx Series Processors
|
||||
=============================
|
||||
|
||||
The C9xx series processors are high-performance RISC-V architecture
|
||||
multi-core processors with AI vector acceleration engine.
|
||||
|
||||
For more details, refer [T-HEAD.CN](https://www.t-head.cn/)
|
||||
|
||||
To build the platform-specific library and firmware images, provide the
|
||||
*PLATFORM=generic* parameter to the top level `make` command.
|
||||
|
||||
Platform Options
|
||||
----------------
|
||||
|
||||
The T-HEAD C9xx does not have any platform-specific compile options
|
||||
because it uses generic platform.
|
||||
|
||||
```
|
||||
CROSS_COMPILE=riscv64-linux-gnu- PLATFORM=generic make
|
||||
```
|
||||
|
||||
Here is the simplest boot flow for a fpga prototype:
|
||||
|
||||
(Jtag gdbinit) -> (zsb) -> (opensbi) -> (linux)
|
||||
|
||||
For more details, refer:
|
||||
[zero stage boot](https://github.com/c-sky/zero_stage_boot)
|
@ -1,15 +1,15 @@
|
||||
OpenSBI Platform Support Guideline
|
||||
==================================
|
||||
|
||||
The OpenSBI platform support allows an implementation to define a set of
|
||||
platform-specific hooks (hardware manipulation functions) in the form of a
|
||||
OpenSBI platform support allows an implementation to define a set of platform
|
||||
specific hooks (hardware manipulation functions) in the form of a
|
||||
*struct sbi_platform* data structure instance. This instance is required by
|
||||
the platform-independent *libsbi.a* to execute platform-specific operations.
|
||||
platform independent *libsbi.a* to execute platform specific operations.
|
||||
|
||||
Each of the reference platform supports provided by OpenSBI defines an instance
|
||||
Each of the reference platform support provided by OpenSBI define an instance
|
||||
of the *struct sbi_platform* data structure. For each supported platform,
|
||||
*libplatsbi.a* integrates this instance with *libsbi.a* to create a
|
||||
platform-specific OpenSBI static library. This library is installed
|
||||
*libplatsbi.a* integrates this instance with *libsbi.a* to create a platform
|
||||
specific OpenSBI static library. This library is installed
|
||||
in *<install_directory>/platform/<platform_subdir>/lib/libplatsbi.a*
|
||||
|
||||
OpenSBI also provides implementation examples of bootable runtime firmwares for
|
||||
@ -17,27 +17,26 @@ the supported platforms. These firmwares are linked against *libplatsbi.a*.
|
||||
Firmware binaries are installed in
|
||||
*<install_directory>/platform/<platform_subdir>/bin*. These firmwares can be
|
||||
used as executable runtime firmwares on the supported platforms as a replacement
|
||||
for the legacy *riscv-pk* boot loader (BBL).
|
||||
for the legacy *riskv-pk* boot loader (BBL).
|
||||
|
||||
A complete doxygen-style documentation of *struct sbi_platform* and related
|
||||
APIs is available in the file *include/sbi/sbi_platform.h*.
|
||||
|
||||
Adding support for a new platform
|
||||
---------------------------------
|
||||
Adding a new platform support
|
||||
-----------------------------
|
||||
|
||||
Support for a new platform named *<xyz>* can be added as follows:
|
||||
Support for a new platform named *<xyz>* can be added as follows:
|
||||
|
||||
1. Create a directory named *<xyz>* under the *platform/* directory.
|
||||
2. Create platform configuration files named *Kconfig* and *configs/defconfig*
|
||||
under the *platform/<xyz>/* directory. These configuration files will
|
||||
provide the build time configuration for the sources to be compiled.
|
||||
3. Create a *platform/<xyz>/objects.mk* file for listing the platform
|
||||
object files to be compiled. This file also provides platform-specific
|
||||
compiler flags, and select firmware options.
|
||||
4. Create a *platform/<xyz>/platform.c* file providing a
|
||||
*struct sbi_platform* instance.
|
||||
1. Create a directory named *<xyz>* under *platform/* directory
|
||||
2. Create a platform configuration file named *config.mk* under
|
||||
*platform/<xyz>/* directory. This configuration file will provide
|
||||
compiler flags, select common drivers, and select firmware options
|
||||
3. Create *platform/<xyz>/objects.mk* file for listing the platform
|
||||
specific object files to be compiled
|
||||
4. Create *platform/<xyz>/platform.c* file providing a *struct sbi_platform*
|
||||
instance
|
||||
|
||||
A platform support code template is available under the *platform/template*
|
||||
A template platform support code is available under the *platform/template*
|
||||
directory. Copying this directory and its content as a new directory named
|
||||
*<xyz>* under the *platform/* directory will create all the files
|
||||
mentioned above.
|
||||
*<xyz>* under the *platform/* directory will create all the files mentioned
|
||||
above.
|
||||
|
@ -1,48 +0,0 @@
|
||||
OpenSBI Platform Requirements
|
||||
=============================
|
||||
|
||||
The RISC-V platform requirements for OpenSBI can change over time
|
||||
with advances in RISC-V specifications and ecosystem.
|
||||
|
||||
To handle this, we have two types of RISC-V platform requirements:
|
||||
|
||||
1. **Base platform requirements** which apply to all OpenSBI releases
|
||||
2. **Release specific platform requirements** which apply to a OpenSBI
|
||||
release and later releases
|
||||
|
||||
Currently, we don't have any **Release specific platform requirements**,
|
||||
but such platform requirements will be added in future.
|
||||
|
||||
Base Platform Requirements
|
||||
--------------------------
|
||||
|
||||
The base RISC-V platform requirements for OpenSBI are as follows:
|
||||
|
||||
1. At least rv32ima_zicsr or rv64ima_zicsr required on all HARTs
|
||||
|
||||
* Users may restrict the usage of atomic instructions to lr/sc
|
||||
via rv32im_zalrsc_zicsr or rv64im_zalrsc_zicsr if preferred
|
||||
|
||||
2. At least one HART should have S-mode support because:
|
||||
|
||||
* SBI calls are meant for RISC-V S-mode (Supervisor mode)
|
||||
* OpenSBI implements SBI calls for S-mode software
|
||||
|
||||
3. The MTVEC CSR on all HARTs must support direct mode
|
||||
4. The PMP CSRs are optional. If PMP CSRs are not implemented then
|
||||
OpenSBI cannot protect M-mode firmware and secured memory regions
|
||||
5. The TIME CSR is optional. If TIME CSR is not implemented in
|
||||
hardware then a 64-bit MMIO counter is required to track time
|
||||
and emulate TIME CSR
|
||||
6. Hardware support for injecting M-mode software interrupts on
|
||||
a multi-HART platform
|
||||
|
||||
The RISC-V extensions not covered by rv32ima_zicsr or rv64ima_zicsr are optional
|
||||
for OpenSBI. Although, OpenSBI will detect and handle some of these
|
||||
optional RISC-V extensions at runtime.
|
||||
|
||||
The optional RISC-V extensions handled by OpenSBI at runtime are:
|
||||
|
||||
* D-extension: Double precision floating point
|
||||
* F-extension: Single precision floating point
|
||||
* H-extension: Hypervisor
|
@ -1,209 +0,0 @@
|
||||
OpenSBI SBI PMU extension support
|
||||
==================================
|
||||
SBI PMU extension supports allow supervisor software to configure/start/stop
|
||||
any performance counter at anytime. Thus, a user can leverage full
|
||||
capability of performance analysis tools such as perf if SBI PMU extension is
|
||||
enabled. The OpenSBI implementation makes the following assumptions about the
|
||||
hardware platform.
|
||||
|
||||
* The platform must provide information about PMU event to counter mapping
|
||||
via device tree or platform specific hooks. Otherwise, SBI PMU extension will
|
||||
not be enabled.
|
||||
|
||||
* The platforms should provide information about the PMU event selector values
|
||||
that should be encoded in the expected value of MHPMEVENTx while configuring
|
||||
MHPMCOUNTERx for that specific event. This can be done via a device tree or
|
||||
platform specific hooks. The exact value to be written to he MHPMEVENTx is
|
||||
completely depends on platform. Generic platform writes the zero-extended event_idx
|
||||
as the expected value for hardware cache/generic events as suggested by the SBI
|
||||
specification.
|
||||
|
||||
SBI PMU Device Tree Bindings
|
||||
----------------------------
|
||||
|
||||
Platforms may choose to describe PMU event selector and event to counter mapping
|
||||
values via device tree. The following sections describe the PMU DT node
|
||||
bindings in details.
|
||||
|
||||
* **compatible** (Mandatory) - The compatible string of SBI PMU device tree node.
|
||||
This DT property must have the value **riscv,pmu**.
|
||||
|
||||
* **riscv,event-to-mhpmevent**(Optional) - It represents an ONE-to-ONE mapping
|
||||
between a PMU event and the event selector value that platform expects to be
|
||||
written to the MHPMEVENTx CSR for that event. The mapping is encoded in a
|
||||
table format where each row represents an event. The first column represent the
|
||||
event idx where the 2nd & 3rd column represent the event selector value that
|
||||
should be encoded in the expected value to be written in MHPMEVENTx.
|
||||
This property shouldn't encode any raw hardware event.
|
||||
|
||||
* **riscv,event-to-mhpmcounters**(Optional) - It represents a MANY-to-MANY
|
||||
mapping between a range of events and all the MHPMCOUNTERx in a bitmap format
|
||||
that can be used to monitor these range of events. The information is encoded in
|
||||
a table format where each row represents a certain range of events and
|
||||
corresponding counters. The first column represents starting of the pmu event id
|
||||
and 2nd column represents the end of the pmu event id. The third column
|
||||
represent a bitmap of all the MHPMCOUNTERx. This property is mandatory if
|
||||
riscv,event-to-mhpmevent is present. Otherwise, it can be omitted. This property
|
||||
shouldn't encode any raw event.
|
||||
|
||||
* **riscv,raw-event-to-mhpmcounters**(Optional) - It represents an ONE-to-MANY
|
||||
or MANY-to-MANY mapping between the raw event(s) and all the MHPMCOUNTERx in
|
||||
a bitmap format that can be used to monitor that raw event. The encoding of the
|
||||
raw events are platform specific. The information is encoded in a table format
|
||||
where each row represents the specific raw event(s). The first column is a 64bit
|
||||
match value where the invariant bits of range of events are set. The second
|
||||
column is a 64 bit mask that will have all the variant bits of the range of
|
||||
events cleared. All other bits should be set in the mask.
|
||||
The third column is a 32bit value to represent bitmap of all MHPMCOUNTERx that
|
||||
can monitor these set of event(s).
|
||||
If a platform directly encodes each raw PMU event as a unique ID, the value of
|
||||
select_mask must be 0xffffffff_ffffffff.
|
||||
|
||||
*Note:* A platform may choose to provide the mapping between event & counters
|
||||
via platform hooks rather than the device tree.
|
||||
|
||||
### Example 1
|
||||
|
||||
```
|
||||
pmu {
|
||||
compatible = "riscv,pmu";
|
||||
riscv,event-to-mhpmevent = <0x0000B 0x0000 0x0001>;
|
||||
riscv,event-to-mhpmcounters = <0x00001 0x00001 0x00000001>,
|
||||
<0x00002 0x00002 0x00000004>,
|
||||
<0x00003 0x0000A 0x00000ff8>,
|
||||
<0x10000 0x10033 0x000ff000>;
|
||||
/* For event ID 0x0002 */
|
||||
riscv,raw-event-to-mhpmcounters = <0x0000 0x0002 0xffffffff 0xffffffff 0x00000f8>,
|
||||
/* For event ID 0-15 */
|
||||
<0x0 0x0 0xffffffff 0xfffffff0 0x00000ff0>,
|
||||
/* For event ID 0xffffffff0000000f - 0xffffffff000000ff */
|
||||
<0xffffffff 0xf 0xffffffff 0xffffff0f 0x00000ff0>;
|
||||
};
|
||||
```
|
||||
|
||||
### Example 2
|
||||
|
||||
```
|
||||
/*
|
||||
* For HiFive Unmatched board. The encodings can be found here
|
||||
* https://sifive.cdn.prismic.io/sifive/1a82e600-1f93-4f41-b2d8-86ed8b16acba_fu740-c000-manual-v1p6.pdf
|
||||
* This example also binds standard SBI PMU hardware id's to U74 PMU event codes, U74 uses bitfield for
|
||||
* events encoding, so several U74 events can be bound to single perf id.
|
||||
* See SBI PMU hardware id's in include/sbi/sbi_ecall_interface.h
|
||||
*/
|
||||
pmu {
|
||||
compatible = "riscv,pmu";
|
||||
riscv,event-to-mhpmevent =
|
||||
/* SBI_PMU_HW_CACHE_REFERENCES -> Instruction cache/ITIM busy | Data cache/DTIM busy */
|
||||
<0x00003 0x00000000 0x1801>,
|
||||
/* SBI_PMU_HW_CACHE_MISSES -> Instruction cache miss | Data cache miss or memory-mapped I/O access */
|
||||
<0x00004 0x00000000 0x0302>,
|
||||
/* SBI_PMU_HW_BRANCH_INSTRUCTIONS -> Conditional branch retired */
|
||||
<0x00005 0x00000000 0x4000>,
|
||||
/* SBI_PMU_HW_BRANCH_MISSES -> Branch direction misprediction | Branch/jump target misprediction */
|
||||
<0x00006 0x00000000 0x6001>,
|
||||
/* L1D_READ_MISS -> Data cache miss or memory-mapped I/O access */
|
||||
<0x10001 0x00000000 0x0202>,
|
||||
/* L1D_WRITE_ACCESS -> Data cache write-back */
|
||||
<0x10002 0x00000000 0x0402>,
|
||||
/* L1I_READ_ACCESS -> Instruction cache miss */
|
||||
<0x10009 0x00000000 0x0102>,
|
||||
/* LL_READ_MISS -> UTLB miss */
|
||||
<0x10011 0x00000000 0x2002>,
|
||||
/* DTLB_READ_MISS -> Data TLB miss */
|
||||
<0x10019 0x00000000 0x1002>,
|
||||
/* ITLB_READ_MISS-> Instruction TLB miss */
|
||||
<0x10021 0x00000000 0x0802>;
|
||||
riscv,event-to-mhpmcounters = <0x00003 0x00006 0x18>,
|
||||
<0x10001 0x10002 0x18>,
|
||||
<0x10009 0x10009 0x18>,
|
||||
<0x10011 0x10011 0x18>,
|
||||
<0x10019 0x10019 0x18>,
|
||||
<0x10021 0x10021 0x18>;
|
||||
riscv,raw-event-to-mhpmcounters = <0x0 0x0 0xffffffff 0xfc0000ff 0x18>,
|
||||
<0x0 0x1 0xffffffff 0xfff800ff 0x18>,
|
||||
<0x0 0x2 0xffffffff 0xffffe0ff 0x18>;
|
||||
};
|
||||
```
|
||||
|
||||
### Example 3
|
||||
|
||||
```
|
||||
/*
|
||||
* For Andes 45-series platforms. The encodings can be found in the
|
||||
* "Machine Performance Monitoring Event Selector" section
|
||||
* http://www.andestech.com/wp-content/uploads/AX45MP-1C-Rev.-5.0.0-Datasheet.pdf
|
||||
*/
|
||||
pmu {
|
||||
compatible = "riscv,pmu";
|
||||
riscv,event-to-mhpmevent =
|
||||
<0x1 0x0000 0x10>, /* CPU_CYCLES -> Cycle count */
|
||||
<0x2 0x0000 0x20>, /* INSTRUCTIONS -> Retired instruction count */
|
||||
<0x3 0x0000 0x41>, /* CACHE_REFERENCES -> D-Cache access */
|
||||
<0x4 0x0000 0x51>, /* CACHE_MISSES -> D-Cache miss */
|
||||
<0x5 0x0000 0x80>, /* BRANCH_INSTRUCTIONS -> Conditional branch instruction count */
|
||||
<0x6 0x0000 0x02>, /* BRANCH_MISSES -> Misprediction of conditional branches */
|
||||
<0x10000 0x0000 0x61>, /* L1D_READ_ACCESS -> D-Cache load access */
|
||||
<0x10001 0x0000 0x71>, /* L1D_READ_MISS -> D-Cache load miss */
|
||||
<0x10002 0x0000 0x81>, /* L1D_WRITE_ACCESS -> D-Cache store access */
|
||||
<0x10003 0x0000 0x91>, /* L1D_WRITE_MISS -> D-Cache store miss */
|
||||
<0x10008 0x0000 0x21>, /* L1I_READ_ACCESS -> I-Cache access */
|
||||
<0x10009 0x0000 0x31>; /* L1I_READ_MISS -> I-Cache miss */
|
||||
riscv,event-to-mhpmcounters = <0x1 0x6 0x78>,
|
||||
<0x10000 0x10003 0x78>,
|
||||
<0x10008 0x10009 0x78>;
|
||||
riscv,raw-event-to-mhpmcounters =
|
||||
<0x0 0x10 0xffffffff 0xffffffff 0x78>, /* Cycle count */
|
||||
<0x0 0x20 0xffffffff 0xffffffff 0x78>, /* Retired instruction count */
|
||||
<0x0 0x30 0xffffffff 0xffffffff 0x78>, /* Integer load instruction count */
|
||||
<0x0 0x40 0xffffffff 0xffffffff 0x78>, /* Integer store instruction count */
|
||||
<0x0 0x50 0xffffffff 0xffffffff 0x78>, /* Atomic instruction count */
|
||||
<0x0 0x60 0xffffffff 0xffffffff 0x78>, /* System instruction count */
|
||||
<0x0 0x70 0xffffffff 0xffffffff 0x78>, /* Integer computational instruction count */
|
||||
<0x0 0x80 0xffffffff 0xffffffff 0x78>, /* Conditional branch instruction count */
|
||||
<0x0 0x90 0xffffffff 0xffffffff 0x78>, /* Taken conditional branch instruction count */
|
||||
<0x0 0xA0 0xffffffff 0xffffffff 0x78>, /* JAL instruction count */
|
||||
<0x0 0xB0 0xffffffff 0xffffffff 0x78>, /* JALR instruction count */
|
||||
<0x0 0xC0 0xffffffff 0xffffffff 0x78>, /* Return instruction count */
|
||||
<0x0 0xD0 0xffffffff 0xffffffff 0x78>, /* Control transfer instruction count */
|
||||
<0x0 0xE0 0xffffffff 0xffffffff 0x78>, /* EXEC.IT instruction count */
|
||||
<0x0 0xF0 0xffffffff 0xffffffff 0x78>, /* Integer multiplication instruction count */
|
||||
<0x0 0x100 0xffffffff 0xffffffff 0x78>, /* Integer division instruction count */
|
||||
<0x0 0x110 0xffffffff 0xffffffff 0x78>, /* Floating-point load instruction count */
|
||||
<0x0 0x120 0xffffffff 0xffffffff 0x78>, /* Floating-point store instruction count */
|
||||
<0x0 0x130 0xffffffff 0xffffffff 0x78>, /* Floating-point addition/subtraction instruction count */
|
||||
<0x0 0x140 0xffffffff 0xffffffff 0x78>, /* Floating-point multiplication instruction count */
|
||||
<0x0 0x150 0xffffffff 0xffffffff 0x78>, /* Floating-point fused multiply-add instruction count */
|
||||
<0x0 0x160 0xffffffff 0xffffffff 0x78>, /* Floating-point division or square-root instruction count */
|
||||
<0x0 0x170 0xffffffff 0xffffffff 0x78>, /* Other floating-point instruction count */
|
||||
<0x0 0x180 0xffffffff 0xffffffff 0x78>, /* Integer multiplication and add/sub instruction count */
|
||||
<0x0 0x190 0xffffffff 0xffffffff 0x78>, /* Retired operation count */
|
||||
<0x0 0x01 0xffffffff 0xffffffff 0x78>, /* ILM access */
|
||||
<0x0 0x11 0xffffffff 0xffffffff 0x78>, /* DLM access */
|
||||
<0x0 0x21 0xffffffff 0xffffffff 0x78>, /* I-Cache access */
|
||||
<0x0 0x31 0xffffffff 0xffffffff 0x78>, /* I-Cache miss */
|
||||
<0x0 0x41 0xffffffff 0xffffffff 0x78>, /* D-Cache access */
|
||||
<0x0 0x51 0xffffffff 0xffffffff 0x78>, /* D-Cache miss */
|
||||
<0x0 0x61 0xffffffff 0xffffffff 0x78>, /* D-Cache load access */
|
||||
<0x0 0x71 0xffffffff 0xffffffff 0x78>, /* D-Cache load miss */
|
||||
<0x0 0x81 0xffffffff 0xffffffff 0x78>, /* D-Cache store access */
|
||||
<0x0 0x91 0xffffffff 0xffffffff 0x78>, /* D-Cache store miss */
|
||||
<0x0 0xA1 0xffffffff 0xffffffff 0x78>, /* D-Cache writeback */
|
||||
<0x0 0xB1 0xffffffff 0xffffffff 0x78>, /* Cycles waiting for I-Cache fill data */
|
||||
<0x0 0xC1 0xffffffff 0xffffffff 0x78>, /* Cycles waiting for D-Cache fill data */
|
||||
<0x0 0xD1 0xffffffff 0xffffffff 0x78>, /* Uncached fetch data access from bus */
|
||||
<0x0 0xE1 0xffffffff 0xffffffff 0x78>, /* Uncached load data access from bus */
|
||||
<0x0 0xF1 0xffffffff 0xffffffff 0x78>, /* Cycles waiting for uncached fetch data from bus */
|
||||
<0x0 0x101 0xffffffff 0xffffffff 0x78>, /* Cycles waiting for uncached load data from bus */
|
||||
<0x0 0x111 0xffffffff 0xffffffff 0x78>, /* Main ITLB access */
|
||||
<0x0 0x121 0xffffffff 0xffffffff 0x78>, /* Main ITLB miss */
|
||||
<0x0 0x131 0xffffffff 0xffffffff 0x78>, /* Main DTLB access */
|
||||
<0x0 0x141 0xffffffff 0xffffffff 0x78>, /* Main DTLB miss */
|
||||
<0x0 0x151 0xffffffff 0xffffffff 0x78>, /* Cycles waiting for Main ITLB fill data */
|
||||
<0x0 0x161 0xffffffff 0xffffffff 0x78>, /* Pipeline stall cycles caused by Main DTLB miss */
|
||||
<0x0 0x171 0xffffffff 0xffffffff 0x78>, /* Hardware prefetch bus access */
|
||||
<0x0 0x02 0xffffffff 0xffffffff 0x78>, /* Misprediction of conditional branches */
|
||||
<0x0 0x12 0xffffffff 0xffffffff 0x78>, /* Misprediction of taken conditional branches */
|
||||
<0x0 0x22 0xffffffff 0xffffffff 0x78>; /* Misprediction of targets of Return instructions */
|
||||
};
|
||||
```
|
Binary file not shown.
Before Width: | Height: | Size: 7.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 8.9 KiB |
@ -1,127 +0,0 @@
|
||||
Writing tests for OpenSBI
|
||||
=========================
|
||||
|
||||
SBIUnit
|
||||
-------
|
||||
SBIUnit is a set of macros and functions which simplify the test development and
|
||||
automate the test execution and evaluation. All of the SBIUnit definitions are
|
||||
in the `include/sbi/sbi_unit_test.h` header file, and implementations are
|
||||
available in `lib/sbi/tests/sbi_unit_test.c`.
|
||||
|
||||
Simple SBIUnit test
|
||||
-------------------
|
||||
|
||||
For instance, we would like to test the following function from
|
||||
`lib/sbi/sbi_string.c`:
|
||||
|
||||
```c
|
||||
size_t sbi_strlen(const char *str)
|
||||
{
|
||||
unsigned long ret = 0;
|
||||
|
||||
while (*str != '\0') {
|
||||
ret++;
|
||||
str++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
```
|
||||
|
||||
which calculates the string length.
|
||||
|
||||
Create the file `lib/sbi/tests/sbi_string_test.c` with the following content:
|
||||
|
||||
```c
|
||||
#include <sbi/sbi_unit_test.h>
|
||||
#include <sbi/sbi_string.h>
|
||||
|
||||
static void strlen_test(struct sbiunit_test_case *test)
|
||||
{
|
||||
SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 5);
|
||||
SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hell\0o"), 4);
|
||||
}
|
||||
|
||||
static struct sbiunit_test_case string_test_cases[] = {
|
||||
SBIUNIT_TEST_CASE(strlen_test),
|
||||
SBIUNIT_END_CASE,
|
||||
};
|
||||
|
||||
SBIUNIT_TEST_SUITE(string_test_suite, string_test_cases);
|
||||
```
|
||||
|
||||
Then, add the corresponding Makefile entries to `lib/sbi/tests/objects.mk`:
|
||||
```lang-makefile
|
||||
...
|
||||
carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += string_test_suite
|
||||
libsbi-objs-$(CONFIG_SBIUNIT) += tests/sbi_string_test.o
|
||||
```
|
||||
|
||||
Now, run `make clean` in order to regenerate the carray-related files.
|
||||
|
||||
Recompile OpenSBI with the CONFIG_SBIUNIT option enabled and run it in QEMU.
|
||||
You will see something like this:
|
||||
```
|
||||
# make PLATFORM=generic run
|
||||
...
|
||||
# Running SBIUNIT tests #
|
||||
...
|
||||
## Running test suite: string_test_suite
|
||||
[PASSED] strlen_test
|
||||
1 PASSED / 0 FAILED / 1 TOTAL
|
||||
```
|
||||
|
||||
Now let's try to change this test in the way that it will fail:
|
||||
|
||||
```c
|
||||
- SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 5);
|
||||
+ SBIUNIT_EXPECT_EQ(test, sbi_strlen("Hello"), 100);
|
||||
```
|
||||
|
||||
`make all` and `make run` it again:
|
||||
```
|
||||
...
|
||||
# Running SBIUNIT tests #
|
||||
...
|
||||
## Running test suite: string_test_suite
|
||||
[SBIUnit] [.../opensbi/lib/sbi/tests/sbi_string_test.c:6]: strlen_test: Condition "(sbi_strlen("Hello")) == (100)" expected to be true!
|
||||
[FAILED] strlen_test
|
||||
0 PASSED / 1 FAILED / 1 TOTAL
|
||||
```
|
||||
Covering the static functions / using the static definitions
|
||||
------------------------------------------------------------
|
||||
|
||||
SBIUnit also allows you to test static functions. In order to do so, simply
|
||||
include your test source in the file you would like to test. Complementing the
|
||||
example above, just add this to the `lib/sbi/sbi_string.c` file:
|
||||
|
||||
```c
|
||||
#ifdef CONFIG_SBIUNIT
|
||||
#include "tests/sbi_string_test.c"
|
||||
#endif
|
||||
```
|
||||
|
||||
In this case you should only add a new carray entry pointing to the test suite
|
||||
to `lib/sbi/tests/objects.mk`:
|
||||
```lang-makefile
|
||||
...
|
||||
carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += string_test_suite
|
||||
```
|
||||
|
||||
You don't have to compile the `sbi_string_test.o` separately, because the
|
||||
test code will be included into the `sbi_string` object file.
|
||||
|
||||
"Mocking" the structures
|
||||
------------------------
|
||||
See the example of structure "mocking" in `lib/sbi/tests/sbi_console_test.c`,
|
||||
where the sbi_console_device structure was mocked to be used in various
|
||||
console-related functions in order to test them.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
All of the `SBIUNIT_EXPECT_*` macros will cause a test case to fail if the
|
||||
corresponding conditions are not met, however, the execution of a particular
|
||||
test case will not be stopped.
|
||||
|
||||
All of the `SBIUNIT_ASSERT_*` macros will cause a test case to fail and stop
|
||||
immediately, triggering a panic.
|
@ -1,28 +0,0 @@
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
menu "Stack Protector Support"
|
||||
|
||||
config STACK_PROTECTOR
|
||||
bool "Stack Protector buffer overflow detection"
|
||||
default n
|
||||
help
|
||||
This option turns on the "stack-protector" compiler feature.
|
||||
|
||||
config STACK_PROTECTOR_STRONG
|
||||
bool "Strong Stack Protector"
|
||||
depends on STACK_PROTECTOR
|
||||
default n
|
||||
help
|
||||
Turn on the "stack-protector" with "-fstack-protector-strong" option.
|
||||
Like -fstack-protector but includes additional functions to be
|
||||
protected.
|
||||
|
||||
config STACK_PROTECTOR_ALL
|
||||
bool "Almighty Stack Protector"
|
||||
depends on STACK_PROTECTOR
|
||||
default n
|
||||
help
|
||||
Turn on the "stack-protector" with "-fstack-protector-all" option.
|
||||
Like -fstack-protector except that all functions are protected.
|
||||
|
||||
endmenu
|
@ -7,8 +7,5 @@
|
||||
# Anup Patel <anup.patel@wdc.com>
|
||||
#
|
||||
|
||||
$(platform_build_dir)/firmware/fw_dynamic.o: $(FW_FDT_PATH)
|
||||
$(platform_build_dir)/firmware/fw_jump.o: $(FW_FDT_PATH)
|
||||
$(platform_build_dir)/firmware/fw_payload.o: $(FW_FDT_PATH)
|
||||
|
||||
$(platform_build_dir)/firmware/fw_payload.o: $(FW_PAYLOAD_PATH_FINAL)
|
||||
$(build_dir)/$(platform_subdir)/firmware/fw_payload.o: $(FW_PAYLOAD_PATH_FINAL)
|
||||
$(build_dir)/$(platform_subdir)/firmware/fw_payload.o: $(FW_PAYLOAD_FDT_PATH)
|
||||
|
@ -9,248 +9,40 @@
|
||||
|
||||
#include <sbi/riscv_asm.h>
|
||||
#include <sbi/riscv_encoding.h>
|
||||
#include <sbi/riscv_elf.h>
|
||||
#include <sbi/sbi_platform.h>
|
||||
#include <sbi/sbi_scratch.h>
|
||||
#include <sbi/sbi_trap.h>
|
||||
|
||||
#define BOOT_LOTTERY_ACQUIRED 1
|
||||
#define BOOT_STATUS_BOOT_HART_DONE 1
|
||||
|
||||
.macro MOV_3R __d0, __s0, __d1, __s1, __d2, __s2
|
||||
add \__d0, \__s0, zero
|
||||
add \__d1, \__s1, zero
|
||||
add \__d2, \__s2, zero
|
||||
.endm
|
||||
|
||||
.macro MOV_5R __d0, __s0, __d1, __s1, __d2, __s2, __d3, __s3, __d4, __s4
|
||||
add \__d0, \__s0, zero
|
||||
add \__d1, \__s1, zero
|
||||
add \__d2, \__s2, zero
|
||||
add \__d3, \__s3, zero
|
||||
add \__d4, \__s4, zero
|
||||
.endm
|
||||
|
||||
.macro CLEAR_MDT tmp
|
||||
#if __riscv_xlen == 32
|
||||
li \tmp, MSTATUSH_MDT
|
||||
csrc CSR_MSTATUSH, \tmp
|
||||
#else
|
||||
li \tmp, MSTATUS_MDT
|
||||
csrc CSR_MSTATUS, \tmp
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.globl _start
|
||||
.globl _start_warm
|
||||
_start:
|
||||
/* Find preferred boot HART id */
|
||||
MOV_3R s0, a0, s1, a1, s2, a2
|
||||
call fw_boot_hart
|
||||
add a6, a0, zero
|
||||
MOV_3R a0, s0, a1, s1, a2, s2
|
||||
li a7, -1
|
||||
beq a6, a7, _try_lottery
|
||||
/* Jump to relocation wait loop if we are not boot hart */
|
||||
bne a0, a6, _wait_for_boot_hart
|
||||
_try_lottery:
|
||||
/* Jump to relocation wait loop if we don't get relocation lottery */
|
||||
lla a6, _boot_lottery
|
||||
li a7, BOOT_LOTTERY_ACQUIRED
|
||||
#ifdef __riscv_atomic
|
||||
amoswap.w a6, a7, (a6)
|
||||
bnez a6, _wait_for_boot_hart
|
||||
#elif __riscv_zalrsc
|
||||
_sc_fail:
|
||||
lr.w t0, (a6)
|
||||
sc.w t1, a7, (a6)
|
||||
bnez t1, _sc_fail
|
||||
bnez t0, _wait_for_boot_hart
|
||||
#else
|
||||
#error "need a or zalrsc"
|
||||
#endif
|
||||
|
||||
/* relocate the global table content */
|
||||
li t0, FW_TEXT_START /* link start */
|
||||
lla t1, _fw_start /* load start */
|
||||
sub t2, t1, t0 /* load offset */
|
||||
lla t0, __rela_dyn_start
|
||||
lla t1, __rela_dyn_end
|
||||
beq t0, t1, _relocate_done
|
||||
2:
|
||||
REG_L t5, __SIZEOF_LONG__(t0) /* t5 <-- relocation info:type */
|
||||
li t3, R_RISCV_RELATIVE /* reloc type R_RISCV_RELATIVE */
|
||||
bne t5, t3, 3f
|
||||
REG_L t3, 0(t0)
|
||||
REG_L t5, (__SIZEOF_LONG__ * 2)(t0) /* t5 <-- addend */
|
||||
add t5, t5, t2
|
||||
add t3, t3, t2
|
||||
REG_S t5, 0(t3) /* store runtime address to the GOT entry */
|
||||
|
||||
3:
|
||||
addi t0, t0, (__SIZEOF_LONG__ * 3)
|
||||
blt t0, t1, 2b
|
||||
_relocate_done:
|
||||
/* At this point we are running from link address */
|
||||
|
||||
/* Reset all registers except ra, a0, a1, a2, a3 and a4 for boot HART */
|
||||
li ra, 0
|
||||
call _reset_regs
|
||||
/*
|
||||
* Jump to warm-boot if this is not the first core booting,
|
||||
* that is, for mhartid != 0
|
||||
*/
|
||||
csrr a6, CSR_MHARTID
|
||||
blt zero, a6, _wait_for_boot_hart
|
||||
|
||||
/* Zero-out BSS */
|
||||
lla s4, _bss_start
|
||||
lla s5, _bss_end
|
||||
la a4, _bss_start
|
||||
la a5, _bss_end
|
||||
_bss_zero:
|
||||
REG_S zero, (s4)
|
||||
add s4, s4, __SIZEOF_POINTER__
|
||||
blt s4, s5, _bss_zero
|
||||
REG_S zero, (a4)
|
||||
add a4, a4, __SIZEOF_POINTER__
|
||||
blt a4, a5, _bss_zero
|
||||
|
||||
/* Setup temporary trap handler */
|
||||
lla s4, _start_hang
|
||||
csrw CSR_MTVEC, s4
|
||||
|
||||
/*
|
||||
* While at this point, trap handling is rudimentary, if a trap happens,
|
||||
* it will end up in _start_hang which is enough to hook up a GDB. Clear
|
||||
* MDT to avoid generating a double trap and thus entering a
|
||||
* critical-error state.
|
||||
*/
|
||||
CLEAR_MDT t0
|
||||
|
||||
/* Setup temporary stack */
|
||||
lla s4, _fw_end
|
||||
li s5, (SBI_SCRATCH_SIZE * 2)
|
||||
add sp, s4, s5
|
||||
|
||||
/* Allow main firmware to save info */
|
||||
MOV_5R s0, a0, s1, a1, s2, a2, s3, a3, s4, a4
|
||||
call fw_save_info
|
||||
MOV_5R a0, s0, a1, s1, a2, s2, a3, s3, a4, s4
|
||||
|
||||
#ifdef FW_FDT_PATH
|
||||
/* Override previous arg1 */
|
||||
lla a1, fw_fdt_bin
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialize platform
|
||||
* Note: The a0 to a4 registers passed to the
|
||||
* firmware are parameters to this function.
|
||||
*/
|
||||
MOV_5R s0, a0, s1, a1, s2, a2, s3, a3, s4, a4
|
||||
call fw_platform_init
|
||||
add t0, a0, zero
|
||||
MOV_5R a0, s0, a1, s1, a2, s2, a3, s3, a4, s4
|
||||
add a1, t0, zero
|
||||
|
||||
/* Preload HART details
|
||||
* s7 -> HART Count
|
||||
* s8 -> HART Stack Size
|
||||
* s9 -> Heap Size
|
||||
* s10 -> Heap Offset
|
||||
*/
|
||||
lla a4, platform
|
||||
#if __riscv_xlen > 32
|
||||
lwu s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
|
||||
lwu s8, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(a4)
|
||||
lwu s9, SBI_PLATFORM_HEAP_SIZE_OFFSET(a4)
|
||||
#else
|
||||
lw s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
|
||||
lw s8, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(a4)
|
||||
lw s9, SBI_PLATFORM_HEAP_SIZE_OFFSET(a4)
|
||||
#endif
|
||||
|
||||
/* Setup scratch space for all the HARTs*/
|
||||
lla tp, _fw_end
|
||||
mul a5, s7, s8
|
||||
add tp, tp, a5
|
||||
/* Setup heap base address */
|
||||
lla s10, _fw_start
|
||||
sub s10, tp, s10
|
||||
add tp, tp, s9
|
||||
/* Keep a copy of tp */
|
||||
add t3, tp, zero
|
||||
/* Counter */
|
||||
li t2, 1
|
||||
/* hartid 0 is mandated by ISA */
|
||||
li t1, 0
|
||||
_scratch_init:
|
||||
/*
|
||||
* The following registers hold values that are computed before
|
||||
* entering this block, and should remain unchanged.
|
||||
*
|
||||
* t3 -> the firmware end address
|
||||
* s7 -> HART count
|
||||
* s8 -> HART stack size
|
||||
* s9 -> Heap Size
|
||||
* s10 -> Heap Offset
|
||||
*/
|
||||
add tp, t3, zero
|
||||
sub tp, tp, s9
|
||||
mul a5, s8, t1
|
||||
sub tp, tp, a5
|
||||
li a5, SBI_SCRATCH_SIZE
|
||||
sub tp, tp, a5
|
||||
|
||||
/* Initialize scratch space */
|
||||
/* Store fw_start and fw_size in scratch space */
|
||||
lla a4, _fw_start
|
||||
sub a5, t3, a4
|
||||
REG_S a4, SBI_SCRATCH_FW_START_OFFSET(tp)
|
||||
REG_S a5, SBI_SCRATCH_FW_SIZE_OFFSET(tp)
|
||||
|
||||
/* Store R/W section's offset in scratch space */
|
||||
lla a5, _fw_rw_start
|
||||
sub a5, a5, a4
|
||||
REG_S a5, SBI_SCRATCH_FW_RW_OFFSET(tp)
|
||||
|
||||
/* Store fw_heap_offset and fw_heap_size in scratch space */
|
||||
REG_S s10, SBI_SCRATCH_FW_HEAP_OFFSET(tp)
|
||||
REG_S s9, SBI_SCRATCH_FW_HEAP_SIZE_OFFSET(tp)
|
||||
|
||||
/* Store next arg1 in scratch space */
|
||||
MOV_3R s0, a0, s1, a1, s2, a2
|
||||
call fw_next_arg1
|
||||
REG_S a0, SBI_SCRATCH_NEXT_ARG1_OFFSET(tp)
|
||||
MOV_3R a0, s0, a1, s1, a2, s2
|
||||
/* Store next address in scratch space */
|
||||
MOV_3R s0, a0, s1, a1, s2, a2
|
||||
call fw_next_addr
|
||||
REG_S a0, SBI_SCRATCH_NEXT_ADDR_OFFSET(tp)
|
||||
MOV_3R a0, s0, a1, s1, a2, s2
|
||||
/* Store next mode in scratch space */
|
||||
MOV_3R s0, a0, s1, a1, s2, a2
|
||||
call fw_next_mode
|
||||
REG_S a0, SBI_SCRATCH_NEXT_MODE_OFFSET(tp)
|
||||
MOV_3R a0, s0, a1, s1, a2, s2
|
||||
/* Store warm_boot address in scratch space */
|
||||
lla a4, _start_warm
|
||||
REG_S a4, SBI_SCRATCH_WARMBOOT_ADDR_OFFSET(tp)
|
||||
/* Store platform address in scratch space */
|
||||
lla a4, platform
|
||||
REG_S a4, SBI_SCRATCH_PLATFORM_ADDR_OFFSET(tp)
|
||||
/* Store hartid-to-scratch function address in scratch space */
|
||||
lla a4, _hartid_to_scratch
|
||||
REG_S a4, SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET(tp)
|
||||
/* Clear trap_context and tmp0 in scratch space */
|
||||
REG_S zero, SBI_SCRATCH_TRAP_CONTEXT_OFFSET(tp)
|
||||
REG_S zero, SBI_SCRATCH_TMP0_OFFSET(tp)
|
||||
/* Store firmware options in scratch space */
|
||||
MOV_3R s0, a0, s1, a1, s2, a2
|
||||
#ifdef FW_OPTIONS
|
||||
li a0, FW_OPTIONS
|
||||
#else
|
||||
call fw_options
|
||||
#endif
|
||||
REG_S a0, SBI_SCRATCH_OPTIONS_OFFSET(tp)
|
||||
MOV_3R a0, s0, a1, s1, a2, s2
|
||||
/* Store hart index in scratch space */
|
||||
REG_S t1, SBI_SCRATCH_HARTINDEX_OFFSET(tp)
|
||||
/* Move to next scratch space */
|
||||
add t1, t1, t2
|
||||
blt t1, s7, _scratch_init
|
||||
/* Override pervious arg1 */
|
||||
add s0, a0, zero
|
||||
add s1, a1, zero
|
||||
call fw_prev_arg1
|
||||
add t1, a0, zero
|
||||
add a0, s0, zero
|
||||
add a1, s1, zero
|
||||
beqz t1, _prev_arg1_override_done
|
||||
add a1, t1, zero
|
||||
_prev_arg1_override_done:
|
||||
|
||||
/*
|
||||
* Relocate Flatened Device Tree (FDT)
|
||||
@ -261,25 +53,45 @@ _scratch_init:
|
||||
* previous booting stage.
|
||||
*/
|
||||
beqz a1, _fdt_reloc_done
|
||||
/* Mask values in a4 */
|
||||
/* Mask values in a3 and a4 */
|
||||
li a3, ~0xf
|
||||
li a4, 0xff
|
||||
/* t1 = destination FDT start address */
|
||||
MOV_3R s0, a0, s1, a1, s2, a2
|
||||
add s0, a0, zero
|
||||
add s1, a1, zero
|
||||
call fw_next_arg1
|
||||
add t1, a0, zero
|
||||
MOV_3R a0, s0, a1, s1, a2, s2
|
||||
add a0, s0, zero
|
||||
add a1, s1, zero
|
||||
beqz t1, _fdt_reloc_done
|
||||
beq t1, a1, _fdt_reloc_done
|
||||
and t1, t1, a3
|
||||
/* t0 = source FDT start address */
|
||||
add t0, a1, zero
|
||||
/* t2 = source FDT size (convert from big-endian) */
|
||||
lbu t2, 7(t0)
|
||||
lbu t3, 6(t0)
|
||||
lbu t4, 5(t0)
|
||||
lbu t5, 4(t0)
|
||||
and t0, t0, a3
|
||||
/* t2 = source FDT size in big-endian */
|
||||
#if __riscv_xlen == 64
|
||||
lwu t2, 4(t0)
|
||||
#else
|
||||
lw t2, 4(t0)
|
||||
#endif
|
||||
/* t3 = bit[15:8] of FDT size */
|
||||
add t3, t2, zero
|
||||
srli t3, t3, 16
|
||||
and t3, t3, a4
|
||||
slli t3, t3, 8
|
||||
/* t4 = bit[23:16] of FDT size */
|
||||
add t4, t2, zero
|
||||
srli t4, t4, 8
|
||||
and t4, t4, a4
|
||||
slli t4, t4, 16
|
||||
/* t5 = bit[31:24] of FDT size */
|
||||
add t5, t2, zero
|
||||
and t5, t5, a4
|
||||
slli t5, t5, 24
|
||||
/* t2 = bit[7:0] of FDT size */
|
||||
srli t2, t2, 24
|
||||
and t2, t2, a4
|
||||
/* t2 = FDT size in little-endian */
|
||||
or t2, t2, t3
|
||||
or t2, t2, t4
|
||||
or t2, t2, t5
|
||||
@ -295,204 +107,177 @@ _fdt_reloc_again:
|
||||
blt t1, t2, _fdt_reloc_again
|
||||
_fdt_reloc_done:
|
||||
|
||||
/* mark boot hart done */
|
||||
li t0, BOOT_STATUS_BOOT_HART_DONE
|
||||
lla t1, _boot_status
|
||||
fence rw, rw
|
||||
REG_S t0, 0(t1)
|
||||
j _start_warm
|
||||
/* Update boot hart flag */
|
||||
la a4, _boot_hart_done
|
||||
li a5, 1
|
||||
REG_S a5, (a4)
|
||||
j _wait_for_boot_hart
|
||||
|
||||
/* waiting for boot hart to be done (_boot_status == BOOT_STATUS_BOOT_HART_DONE) */
|
||||
.align 3
|
||||
_boot_hart_done:
|
||||
RISCV_PTR 0
|
||||
.align 3
|
||||
|
||||
/* Wait for boot hart */
|
||||
_wait_for_boot_hart:
|
||||
li t0, BOOT_STATUS_BOOT_HART_DONE
|
||||
lla t1, _boot_status
|
||||
REG_L t1, 0(t1)
|
||||
/* Reduce the bus traffic so that boot hart may proceed faster */
|
||||
div t2, t2, zero
|
||||
div t2, t2, zero
|
||||
div t2, t2, zero
|
||||
bne t0, t1, _wait_for_boot_hart
|
||||
la a4, _boot_hart_done
|
||||
REG_L a5, (a4)
|
||||
beqz a5, _wait_for_boot_hart
|
||||
|
||||
_start_warm:
|
||||
/* Reset all registers except ra, a0, a1, a2, a3 and a4 for non-boot HART */
|
||||
li ra, 0
|
||||
call _reset_regs
|
||||
|
||||
/* Disable all interrupts */
|
||||
/* Disable and clear all interrupts */
|
||||
csrw CSR_MIE, zero
|
||||
csrw CSR_MIP, zero
|
||||
|
||||
/* Find HART count and HART stack size */
|
||||
lla a4, platform
|
||||
#if __riscv_xlen > 32
|
||||
/* Preload per-HART details
|
||||
* s6 -> HART ID
|
||||
* s7 -> HART Count
|
||||
* s8 -> HART Stack Size
|
||||
*/
|
||||
csrr s6, CSR_MHARTID
|
||||
la a4, platform
|
||||
#if __riscv_xlen == 64
|
||||
lwu s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
|
||||
lwu s8, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(a4)
|
||||
#else
|
||||
lw s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
|
||||
lw s8, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(a4)
|
||||
#endif
|
||||
REG_L s9, SBI_PLATFORM_HART_INDEX2ID_OFFSET(a4)
|
||||
|
||||
/* Find HART id */
|
||||
/* HART ID should be within expected limit */
|
||||
csrr s6, CSR_MHARTID
|
||||
bge s6, s7, _start_hang
|
||||
|
||||
/* Find HART index */
|
||||
beqz s9, 3f
|
||||
li a4, 0
|
||||
1:
|
||||
#if __riscv_xlen > 32
|
||||
lwu a5, (s9)
|
||||
#else
|
||||
lw a5, (s9)
|
||||
#endif
|
||||
beq a5, s6, 2f
|
||||
add s9, s9, 4
|
||||
add a4, a4, 1
|
||||
blt a4, s7, 1b
|
||||
2: add s6, a4, zero
|
||||
3: bge s6, s7, _start_hang
|
||||
|
||||
/* Find the scratch space based on HART index */
|
||||
lla tp, _fw_end
|
||||
/* Setup scratch space */
|
||||
la tp, _fw_end
|
||||
mul a5, s7, s8
|
||||
add tp, tp, a5
|
||||
mul a5, s8, s6
|
||||
sub tp, tp, a5
|
||||
li a5, SBI_SCRATCH_SIZE
|
||||
sub tp, tp, a5
|
||||
|
||||
/* update the mscratch */
|
||||
csrw CSR_MSCRATCH, tp
|
||||
|
||||
/* Initialize scratch space */
|
||||
la a4, _fw_start
|
||||
la a5, _fw_end
|
||||
mul t0, s7, s8
|
||||
add a5, a5, t0
|
||||
sub a5, a5, a4
|
||||
REG_S a4, SBI_SCRATCH_FW_START_OFFSET(tp)
|
||||
REG_S a5, SBI_SCRATCH_FW_SIZE_OFFSET(tp)
|
||||
/* Note: fw_next_arg1() uses a0, a1, and ra */
|
||||
call fw_next_arg1
|
||||
REG_S a0, SBI_SCRATCH_NEXT_ARG1_OFFSET(tp)
|
||||
/* Note: fw_next_addr() uses a0, a1, and ra */
|
||||
call fw_next_addr
|
||||
REG_S a0, SBI_SCRATCH_NEXT_ADDR_OFFSET(tp)
|
||||
li a4, PRV_S
|
||||
REG_S a4, SBI_SCRATCH_NEXT_MODE_OFFSET(tp)
|
||||
la a4, _start_warm
|
||||
REG_S a4, SBI_SCRATCH_WARMBOOT_ADDR_OFFSET(tp)
|
||||
la a4, platform
|
||||
REG_S a4, SBI_SCRATCH_PLATFORM_ADDR_OFFSET(tp)
|
||||
la a4, _hartid_to_scratch
|
||||
REG_S a4, SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET(tp)
|
||||
REG_S zero, SBI_SCRATCH_IPI_TYPE_OFFSET(tp)
|
||||
REG_S zero, SBI_SCRATCH_TMP0_OFFSET(tp)
|
||||
|
||||
/* Setup stack */
|
||||
add sp, tp, zero
|
||||
|
||||
/* Setup trap handler */
|
||||
lla a4, _trap_handler
|
||||
csrr a5, CSR_MISA
|
||||
srli a5, a5, ('H' - 'A')
|
||||
andi a5, a5, 0x1
|
||||
beq a5, zero, _skip_trap_handler_hyp
|
||||
lla a4, _trap_handler_hyp
|
||||
_skip_trap_handler_hyp:
|
||||
la a4, _trap_handler
|
||||
csrw CSR_MTVEC, a4
|
||||
|
||||
/* Clear MDT here again for all harts */
|
||||
CLEAR_MDT t0
|
||||
|
||||
/* Initialize SBI runtime */
|
||||
csrr a0, CSR_MSCRATCH
|
||||
call sbi_init
|
||||
Call sbi_init
|
||||
|
||||
/* We don't expect to reach here hence just hang */
|
||||
j _start_hang
|
||||
|
||||
.data
|
||||
.align 3
|
||||
_boot_lottery:
|
||||
RISCV_PTR 0
|
||||
_boot_status:
|
||||
RISCV_PTR 0
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.globl _hartid_to_scratch
|
||||
_hartid_to_scratch:
|
||||
add sp, sp, -(3 * __SIZEOF_POINTER__)
|
||||
REG_S s0, (sp)
|
||||
REG_S s1, (__SIZEOF_POINTER__)(sp)
|
||||
REG_S s2, (__SIZEOF_POINTER__ * 2)(sp)
|
||||
/*
|
||||
* a0 -> HART ID (passed by caller)
|
||||
* a1 -> HART Index (passed by caller)
|
||||
* t0 -> HART Stack Size
|
||||
* t1 -> HART Stack End
|
||||
* t2 -> Temporary
|
||||
* s0 -> HART Stack Size
|
||||
* s1 -> HART Stack End
|
||||
* s2 -> Temporary
|
||||
*/
|
||||
lla t2, platform
|
||||
#if __riscv_xlen > 32
|
||||
lwu t0, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(t2)
|
||||
lwu t2, SBI_PLATFORM_HART_COUNT_OFFSET(t2)
|
||||
la s2, platform
|
||||
#if __riscv_xlen == 64
|
||||
lwu s0, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(s2)
|
||||
lwu s2, SBI_PLATFORM_HART_COUNT_OFFSET(s2)
|
||||
#else
|
||||
lw t0, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(t2)
|
||||
lw t2, SBI_PLATFORM_HART_COUNT_OFFSET(t2)
|
||||
lw s0, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(s2)
|
||||
lw s2, SBI_PLATFORM_HART_COUNT_OFFSET(s2)
|
||||
#endif
|
||||
sub t2, t2, a1
|
||||
mul t2, t2, t0
|
||||
lla t1, _fw_end
|
||||
add t1, t1, t2
|
||||
li t2, SBI_SCRATCH_SIZE
|
||||
sub a0, t1, t2
|
||||
mul s2, s2, s0
|
||||
la s1, _fw_end
|
||||
add s1, s1, s2
|
||||
mul s2, s0, a0
|
||||
sub s1, s1, s2
|
||||
li s2, SBI_SCRATCH_SIZE
|
||||
sub a0, s1, s2
|
||||
REG_L s0, (sp)
|
||||
REG_L s1, (__SIZEOF_POINTER__)(sp)
|
||||
REG_L s2, (__SIZEOF_POINTER__ * 2)(sp)
|
||||
add sp, sp, (3 * __SIZEOF_POINTER__)
|
||||
ret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.globl _start_hang
|
||||
_start_hang:
|
||||
wfi
|
||||
j _start_hang
|
||||
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.weak fw_platform_init
|
||||
fw_platform_init:
|
||||
add a0, a1, zero
|
||||
ret
|
||||
|
||||
/* Map implicit memcpy() added by compiler to sbi_memcpy() */
|
||||
.section .text
|
||||
.align 3
|
||||
.globl memcpy
|
||||
memcpy:
|
||||
tail sbi_memcpy
|
||||
|
||||
/* Map implicit memset() added by compiler to sbi_memset() */
|
||||
.section .text
|
||||
.align 3
|
||||
.globl memset
|
||||
memset:
|
||||
tail sbi_memset
|
||||
|
||||
/* Map implicit memmove() added by compiler to sbi_memmove() */
|
||||
.section .text
|
||||
.align 3
|
||||
.globl memmove
|
||||
memmove:
|
||||
tail sbi_memmove
|
||||
|
||||
/* Map implicit memcmp() added by compiler to sbi_memcmp() */
|
||||
.section .text
|
||||
.align 3
|
||||
.globl memcmp
|
||||
memcmp:
|
||||
tail sbi_memcmp
|
||||
|
||||
.macro TRAP_SAVE_AND_SETUP_SP_T0
|
||||
.globl _trap_handler
|
||||
_trap_handler:
|
||||
/* Swap TP and MSCRATCH */
|
||||
csrrw tp, CSR_MSCRATCH, tp
|
||||
|
||||
/* Save T0 in scratch space */
|
||||
REG_S t0, SBI_SCRATCH_TMP0_OFFSET(tp)
|
||||
|
||||
/*
|
||||
* Set T0 to appropriate exception stack
|
||||
*
|
||||
* Came_From_M_Mode = ((MSTATUS.MPP < PRV_M) ? 1 : 0) - 1;
|
||||
* Exception_Stack = TP ^ (Came_From_M_Mode & (SP ^ TP))
|
||||
*
|
||||
* Came_From_M_Mode = 0 ==> Exception_Stack = TP
|
||||
* Came_From_M_Mode = -1 ==> Exception_Stack = SP
|
||||
*/
|
||||
/* Check which mode we came from */
|
||||
csrr t0, CSR_MSTATUS
|
||||
srl t0, t0, MSTATUS_MPP_SHIFT
|
||||
and t0, t0, PRV_M
|
||||
slti t0, t0, PRV_M
|
||||
add t0, t0, -1
|
||||
xor sp, sp, tp
|
||||
and t0, t0, sp
|
||||
xor sp, sp, tp
|
||||
xor t0, tp, t0
|
||||
xori t0, t0, PRV_M
|
||||
beq t0, zero, _trap_handler_m_mode
|
||||
|
||||
/* Save original SP on exception stack */
|
||||
REG_S sp, (SBI_TRAP_REGS_OFFSET(sp) - SBI_TRAP_CONTEXT_SIZE)(t0)
|
||||
/* We came from S-mode or U-mode */
|
||||
_trap_handler_s_mode:
|
||||
/* Set T0 to original SP */
|
||||
add t0, sp, zero
|
||||
|
||||
/* Set SP to exception stack and make room for trap context */
|
||||
add sp, t0, -(SBI_TRAP_CONTEXT_SIZE)
|
||||
/* Setup exception stack */
|
||||
add sp, tp, -(SBI_TRAP_REGS_SIZE)
|
||||
|
||||
/* Jump to code common for all modes */
|
||||
j _trap_handler_all_mode
|
||||
|
||||
/* We came from M-mode */
|
||||
_trap_handler_m_mode:
|
||||
/* Set T0 to original SP */
|
||||
add t0, sp, zero
|
||||
|
||||
/* Re-use current SP as exception stack */
|
||||
add sp, sp, -(SBI_TRAP_REGS_SIZE)
|
||||
|
||||
_trap_handler_all_mode:
|
||||
/* Save original SP (from T0) on stack */
|
||||
REG_S t0, SBI_TRAP_REGS_OFFSET(sp)(sp)
|
||||
|
||||
/* Restore T0 from scratch space */
|
||||
REG_L t0, SBI_SCRATCH_TMP0_OFFSET(tp)
|
||||
@ -502,23 +287,13 @@ memcmp:
|
||||
|
||||
/* Swap TP and MSCRATCH */
|
||||
csrrw tp, CSR_MSCRATCH, tp
|
||||
.endm
|
||||
|
||||
.macro TRAP_SAVE_MEPC_MSTATUS have_mstatush
|
||||
/* Save MEPC and MSTATUS CSRs */
|
||||
csrr t0, CSR_MEPC
|
||||
REG_S t0, SBI_TRAP_REGS_OFFSET(mepc)(sp)
|
||||
csrr t0, CSR_MSTATUS
|
||||
REG_S t0, SBI_TRAP_REGS_OFFSET(mstatus)(sp)
|
||||
.if \have_mstatush
|
||||
csrr t0, CSR_MSTATUSH
|
||||
REG_S t0, SBI_TRAP_REGS_OFFSET(mstatusH)(sp)
|
||||
.else
|
||||
REG_S zero, SBI_TRAP_REGS_OFFSET(mstatusH)(sp)
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro TRAP_SAVE_GENERAL_REGS_EXCEPT_SP_T0
|
||||
/* Save all general regisers except SP and T0 */
|
||||
REG_S zero, SBI_TRAP_REGS_OFFSET(zero)(sp)
|
||||
REG_S ra, SBI_TRAP_REGS_OFFSET(ra)(sp)
|
||||
@ -550,220 +325,53 @@ memcmp:
|
||||
REG_S t4, SBI_TRAP_REGS_OFFSET(t4)(sp)
|
||||
REG_S t5, SBI_TRAP_REGS_OFFSET(t5)(sp)
|
||||
REG_S t6, SBI_TRAP_REGS_OFFSET(t6)(sp)
|
||||
.endm
|
||||
|
||||
.macro TRAP_SAVE_INFO have_mstatush have_h_extension
|
||||
csrr t0, CSR_MCAUSE
|
||||
REG_S t0, (SBI_TRAP_REGS_SIZE + SBI_TRAP_INFO_OFFSET(cause))(sp)
|
||||
csrr t0, CSR_MTVAL
|
||||
REG_S t0, (SBI_TRAP_REGS_SIZE + SBI_TRAP_INFO_OFFSET(tval))(sp)
|
||||
.if \have_h_extension
|
||||
csrr t0, CSR_MTVAL2
|
||||
REG_S t0, (SBI_TRAP_REGS_SIZE + SBI_TRAP_INFO_OFFSET(tval2))(sp)
|
||||
csrr t0, CSR_MTINST
|
||||
REG_S t0, (SBI_TRAP_REGS_SIZE + SBI_TRAP_INFO_OFFSET(tinst))(sp)
|
||||
.if \have_mstatush
|
||||
csrr t0, CSR_MSTATUSH
|
||||
srli t0, t0, MSTATUSH_GVA_SHIFT
|
||||
.else
|
||||
csrr t0, CSR_MSTATUS
|
||||
srli t0, t0, MSTATUS_GVA_SHIFT
|
||||
.endif
|
||||
and t0, t0, 0x1
|
||||
.else
|
||||
REG_S zero, (SBI_TRAP_REGS_SIZE + SBI_TRAP_INFO_OFFSET(tval2))(sp)
|
||||
REG_S zero, (SBI_TRAP_REGS_SIZE + SBI_TRAP_INFO_OFFSET(tinst))(sp)
|
||||
li t0, 0
|
||||
.endif
|
||||
REG_S t0, (SBI_TRAP_REGS_SIZE + SBI_TRAP_INFO_OFFSET(gva))(sp)
|
||||
|
||||
/* We are ready to take another trap, clear MDT */
|
||||
CLEAR_MDT t0
|
||||
.endm
|
||||
|
||||
.macro TRAP_CALL_C_ROUTINE
|
||||
/* Call C routine */
|
||||
add a0, sp, zero
|
||||
csrr a1, CSR_MSCRATCH
|
||||
call sbi_trap_handler
|
||||
.endm
|
||||
|
||||
.macro TRAP_RESTORE_GENERAL_REGS_EXCEPT_A0_T0
|
||||
/* Restore all general regisers except A0 and T0 */
|
||||
REG_L ra, SBI_TRAP_REGS_OFFSET(ra)(a0)
|
||||
REG_L sp, SBI_TRAP_REGS_OFFSET(sp)(a0)
|
||||
REG_L gp, SBI_TRAP_REGS_OFFSET(gp)(a0)
|
||||
REG_L tp, SBI_TRAP_REGS_OFFSET(tp)(a0)
|
||||
REG_L t1, SBI_TRAP_REGS_OFFSET(t1)(a0)
|
||||
REG_L t2, SBI_TRAP_REGS_OFFSET(t2)(a0)
|
||||
REG_L s0, SBI_TRAP_REGS_OFFSET(s0)(a0)
|
||||
REG_L s1, SBI_TRAP_REGS_OFFSET(s1)(a0)
|
||||
REG_L a1, SBI_TRAP_REGS_OFFSET(a1)(a0)
|
||||
REG_L a2, SBI_TRAP_REGS_OFFSET(a2)(a0)
|
||||
REG_L a3, SBI_TRAP_REGS_OFFSET(a3)(a0)
|
||||
REG_L a4, SBI_TRAP_REGS_OFFSET(a4)(a0)
|
||||
REG_L a5, SBI_TRAP_REGS_OFFSET(a5)(a0)
|
||||
REG_L a6, SBI_TRAP_REGS_OFFSET(a6)(a0)
|
||||
REG_L a7, SBI_TRAP_REGS_OFFSET(a7)(a0)
|
||||
REG_L s2, SBI_TRAP_REGS_OFFSET(s2)(a0)
|
||||
REG_L s3, SBI_TRAP_REGS_OFFSET(s3)(a0)
|
||||
REG_L s4, SBI_TRAP_REGS_OFFSET(s4)(a0)
|
||||
REG_L s5, SBI_TRAP_REGS_OFFSET(s5)(a0)
|
||||
REG_L s6, SBI_TRAP_REGS_OFFSET(s6)(a0)
|
||||
REG_L s7, SBI_TRAP_REGS_OFFSET(s7)(a0)
|
||||
REG_L s8, SBI_TRAP_REGS_OFFSET(s8)(a0)
|
||||
REG_L s9, SBI_TRAP_REGS_OFFSET(s9)(a0)
|
||||
REG_L s10, SBI_TRAP_REGS_OFFSET(s10)(a0)
|
||||
REG_L s11, SBI_TRAP_REGS_OFFSET(s11)(a0)
|
||||
REG_L t3, SBI_TRAP_REGS_OFFSET(t3)(a0)
|
||||
REG_L t4, SBI_TRAP_REGS_OFFSET(t4)(a0)
|
||||
REG_L t5, SBI_TRAP_REGS_OFFSET(t5)(a0)
|
||||
REG_L t6, SBI_TRAP_REGS_OFFSET(t6)(a0)
|
||||
.endm
|
||||
/* Restore all general regisers except SP and T0 */
|
||||
REG_L ra, SBI_TRAP_REGS_OFFSET(ra)(sp)
|
||||
REG_L gp, SBI_TRAP_REGS_OFFSET(gp)(sp)
|
||||
REG_L tp, SBI_TRAP_REGS_OFFSET(tp)(sp)
|
||||
REG_L t1, SBI_TRAP_REGS_OFFSET(t1)(sp)
|
||||
REG_L t2, SBI_TRAP_REGS_OFFSET(t2)(sp)
|
||||
REG_L s0, SBI_TRAP_REGS_OFFSET(s0)(sp)
|
||||
REG_L s1, SBI_TRAP_REGS_OFFSET(s1)(sp)
|
||||
REG_L a0, SBI_TRAP_REGS_OFFSET(a0)(sp)
|
||||
REG_L a1, SBI_TRAP_REGS_OFFSET(a1)(sp)
|
||||
REG_L a2, SBI_TRAP_REGS_OFFSET(a2)(sp)
|
||||
REG_L a3, SBI_TRAP_REGS_OFFSET(a3)(sp)
|
||||
REG_L a4, SBI_TRAP_REGS_OFFSET(a4)(sp)
|
||||
REG_L a5, SBI_TRAP_REGS_OFFSET(a5)(sp)
|
||||
REG_L a6, SBI_TRAP_REGS_OFFSET(a6)(sp)
|
||||
REG_L a7, SBI_TRAP_REGS_OFFSET(a7)(sp)
|
||||
REG_L s2, SBI_TRAP_REGS_OFFSET(s2)(sp)
|
||||
REG_L s3, SBI_TRAP_REGS_OFFSET(s3)(sp)
|
||||
REG_L s4, SBI_TRAP_REGS_OFFSET(s4)(sp)
|
||||
REG_L s5, SBI_TRAP_REGS_OFFSET(s5)(sp)
|
||||
REG_L s6, SBI_TRAP_REGS_OFFSET(s6)(sp)
|
||||
REG_L s7, SBI_TRAP_REGS_OFFSET(s7)(sp)
|
||||
REG_L s8, SBI_TRAP_REGS_OFFSET(s8)(sp)
|
||||
REG_L s9, SBI_TRAP_REGS_OFFSET(s9)(sp)
|
||||
REG_L s10, SBI_TRAP_REGS_OFFSET(s10)(sp)
|
||||
REG_L s11, SBI_TRAP_REGS_OFFSET(s11)(sp)
|
||||
REG_L t3, SBI_TRAP_REGS_OFFSET(t3)(sp)
|
||||
REG_L t4, SBI_TRAP_REGS_OFFSET(t4)(sp)
|
||||
REG_L t5, SBI_TRAP_REGS_OFFSET(t5)(sp)
|
||||
REG_L t6, SBI_TRAP_REGS_OFFSET(t6)(sp)
|
||||
|
||||
.macro TRAP_RESTORE_MEPC_MSTATUS have_mstatush
|
||||
/*
|
||||
* Restore MSTATUS and MEPC CSRs starting with MSTATUS/H to set MDT
|
||||
* flags since we can not take a trap now or MEPC would be cloberred
|
||||
*/
|
||||
.if \have_mstatush
|
||||
REG_L t0, SBI_TRAP_REGS_OFFSET(mstatusH)(a0)
|
||||
csrw CSR_MSTATUSH, t0
|
||||
.endif
|
||||
REG_L t0, SBI_TRAP_REGS_OFFSET(mstatus)(a0)
|
||||
csrw CSR_MSTATUS, t0
|
||||
REG_L t0, SBI_TRAP_REGS_OFFSET(mepc)(a0)
|
||||
/* Restore MEPC and MSTATUS CSRs */
|
||||
REG_L t0, SBI_TRAP_REGS_OFFSET(mepc)(sp)
|
||||
csrw CSR_MEPC, t0
|
||||
.endm
|
||||
REG_L t0, SBI_TRAP_REGS_OFFSET(mstatus)(sp)
|
||||
csrw CSR_MSTATUS, t0
|
||||
|
||||
.macro TRAP_RESTORE_A0_T0
|
||||
/* Restore T0 */
|
||||
REG_L t0, SBI_TRAP_REGS_OFFSET(t0)(a0)
|
||||
REG_L t0, SBI_TRAP_REGS_OFFSET(t0)(sp)
|
||||
|
||||
/* Restore A0 */
|
||||
REG_L a0, SBI_TRAP_REGS_OFFSET(a0)(a0)
|
||||
.endm
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.globl _trap_handler
|
||||
_trap_handler:
|
||||
TRAP_SAVE_AND_SETUP_SP_T0
|
||||
|
||||
TRAP_SAVE_MEPC_MSTATUS 0
|
||||
|
||||
TRAP_SAVE_GENERAL_REGS_EXCEPT_SP_T0
|
||||
|
||||
TRAP_SAVE_INFO 0 0
|
||||
|
||||
TRAP_CALL_C_ROUTINE
|
||||
|
||||
TRAP_RESTORE_GENERAL_REGS_EXCEPT_A0_T0
|
||||
|
||||
TRAP_RESTORE_MEPC_MSTATUS 0
|
||||
|
||||
TRAP_RESTORE_A0_T0
|
||||
/* Restore SP */
|
||||
REG_L sp, SBI_TRAP_REGS_OFFSET(sp)(sp)
|
||||
|
||||
mret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.globl _trap_handler_hyp
|
||||
_trap_handler_hyp:
|
||||
TRAP_SAVE_AND_SETUP_SP_T0
|
||||
|
||||
#if __riscv_xlen == 32
|
||||
TRAP_SAVE_MEPC_MSTATUS 1
|
||||
#else
|
||||
TRAP_SAVE_MEPC_MSTATUS 0
|
||||
#endif
|
||||
|
||||
TRAP_SAVE_GENERAL_REGS_EXCEPT_SP_T0
|
||||
|
||||
#if __riscv_xlen == 32
|
||||
TRAP_SAVE_INFO 1 1
|
||||
#else
|
||||
TRAP_SAVE_INFO 0 1
|
||||
#endif
|
||||
|
||||
TRAP_CALL_C_ROUTINE
|
||||
|
||||
TRAP_RESTORE_GENERAL_REGS_EXCEPT_A0_T0
|
||||
|
||||
#if __riscv_xlen == 32
|
||||
TRAP_RESTORE_MEPC_MSTATUS 1
|
||||
#else
|
||||
TRAP_RESTORE_MEPC_MSTATUS 0
|
||||
#endif
|
||||
|
||||
TRAP_RESTORE_A0_T0
|
||||
|
||||
mret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.globl _reset_regs
|
||||
_reset_regs:
|
||||
|
||||
/* flush the instruction cache */
|
||||
fence.i
|
||||
/* Reset all registers except ra, a0, a1, a2, a3 and a4 */
|
||||
li sp, 0
|
||||
li gp, 0
|
||||
li tp, 0
|
||||
li t0, 0
|
||||
li t1, 0
|
||||
li t2, 0
|
||||
li s0, 0
|
||||
li s1, 0
|
||||
li a5, 0
|
||||
li a6, 0
|
||||
li a7, 0
|
||||
li s2, 0
|
||||
li s3, 0
|
||||
li s4, 0
|
||||
li s5, 0
|
||||
li s6, 0
|
||||
li s7, 0
|
||||
li s8, 0
|
||||
li s9, 0
|
||||
li s10, 0
|
||||
li s11, 0
|
||||
li t3, 0
|
||||
li t4, 0
|
||||
li t5, 0
|
||||
li t6, 0
|
||||
csrw CSR_MSCRATCH, 0
|
||||
|
||||
ret
|
||||
|
||||
.section .rodata
|
||||
.Lstack_corrupt_msg:
|
||||
.string "stack smashing detected\n"
|
||||
|
||||
/* This will be called when the stack corruption is detected */
|
||||
.section .text
|
||||
.align 3
|
||||
.globl __stack_chk_fail
|
||||
.type __stack_chk_fail, %function
|
||||
__stack_chk_fail:
|
||||
la a0, .Lstack_corrupt_msg
|
||||
call sbi_panic
|
||||
|
||||
/* Initial value of the stack guard variable */
|
||||
.section .data
|
||||
.align 3
|
||||
.globl __stack_chk_guard
|
||||
.type __stack_chk_guard, %object
|
||||
__stack_chk_guard:
|
||||
RISCV_PTR 0x95B5FF5A
|
||||
|
||||
#ifdef FW_FDT_PATH
|
||||
.section .rodata
|
||||
.align 4
|
||||
.globl fw_fdt_bin
|
||||
fw_fdt_bin:
|
||||
.incbin FW_FDT_PATH
|
||||
#ifdef FW_FDT_PADDING
|
||||
.fill FW_FDT_PADDING, 1, 0
|
||||
#endif
|
||||
#endif
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
. = FW_TEXT_START;
|
||||
/* Don't add any section between FW_TEXT_START and _fw_start */
|
||||
|
||||
PROVIDE(_fw_start = .);
|
||||
|
||||
. = ALIGN(0x1000); /* Need this to create proper sections */
|
||||
@ -20,59 +20,36 @@
|
||||
PROVIDE(_text_start = .);
|
||||
*(.entry)
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
. = ALIGN(8);
|
||||
PROVIDE(_text_end = .);
|
||||
}
|
||||
|
||||
/* End of the code sections */
|
||||
|
||||
. = ALIGN(0x1000); /* Ensure next section is page aligned */
|
||||
|
||||
/* End of the code sections */
|
||||
|
||||
/* Beginning of the read-only data sections */
|
||||
|
||||
PROVIDE(_rodata_start = .);
|
||||
. = ALIGN(0x1000); /* Ensure next section is page aligned */
|
||||
|
||||
.rodata :
|
||||
{
|
||||
PROVIDE(_rodata_start = .);
|
||||
*(.rodata .rodata.*)
|
||||
. = ALIGN(8);
|
||||
PROVIDE(_rodata_end = .);
|
||||
}
|
||||
|
||||
.dynsym :
|
||||
{
|
||||
*(.dynsym)
|
||||
}
|
||||
|
||||
. = ALIGN(0x1000); /* Ensure next section is page aligned */
|
||||
|
||||
.rela.dyn : {
|
||||
PROVIDE(__rela_dyn_start = .);
|
||||
*(.rela*)
|
||||
PROVIDE(__rela_dyn_end = .);
|
||||
}
|
||||
|
||||
PROVIDE(_rodata_end = .);
|
||||
|
||||
/* End of the read-only data sections */
|
||||
|
||||
/*
|
||||
* PMP regions must be to be power-of-2. RX/RW will have separate
|
||||
* regions, so ensure that the split is power-of-2.
|
||||
*/
|
||||
. = ALIGN(1 << LOG2CEIL((SIZEOF(.rodata) + SIZEOF(.text)
|
||||
+ SIZEOF(.dynsym) + SIZEOF(.rela.dyn))));
|
||||
|
||||
PROVIDE(_fw_rw_start = .);
|
||||
|
||||
/* Beginning of the read-write data sections */
|
||||
|
||||
. = ALIGN(0x1000); /* Ensure next section is page aligned */
|
||||
|
||||
.data :
|
||||
{
|
||||
PROVIDE(_data_start = .);
|
||||
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.readmostly.data)
|
||||
@ -87,8 +64,6 @@
|
||||
.bss :
|
||||
{
|
||||
PROVIDE(_bss_start = .);
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
. = ALIGN(8);
|
||||
|
@ -1,137 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Anup Patel <anup.patel@wdc.com>
|
||||
*/
|
||||
|
||||
#include <sbi/fw_dynamic.h>
|
||||
|
||||
#include "fw_base.S"
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_boot_hart
|
||||
/*
|
||||
* This function is called very early even before
|
||||
* fw_save_info() is called.
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The boot HART id should be returned in 'a0'.
|
||||
*/
|
||||
fw_boot_hart:
|
||||
/* Sanity checks */
|
||||
li a1, FW_DYNAMIC_INFO_MAGIC_VALUE
|
||||
REG_L a0, FW_DYNAMIC_INFO_MAGIC_OFFSET(a2)
|
||||
bne a0, a1, _start_hang
|
||||
li a1, FW_DYNAMIC_INFO_VERSION_MAX
|
||||
REG_L a0, FW_DYNAMIC_INFO_VERSION_OFFSET(a2)
|
||||
bgt a0, a1, _start_hang
|
||||
|
||||
/* Read boot HART id */
|
||||
li a1, FW_DYNAMIC_INFO_VERSION_2
|
||||
blt a0, a1, 2f
|
||||
REG_L a0, FW_DYNAMIC_INFO_BOOT_HART_OFFSET(a2)
|
||||
ret
|
||||
2: li a0, -1
|
||||
ret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_save_info
|
||||
/*
|
||||
* We can only use a0, a1, a2, a3, and a4 registers here.
|
||||
* The a0, a1, and a2 registers will be same as passed by
|
||||
* previous booting stage.
|
||||
* Nothing to be returned here.
|
||||
*/
|
||||
fw_save_info:
|
||||
/* Save next arg1 in 'a1' */
|
||||
lla a4, _dynamic_next_arg1
|
||||
REG_S a1, (a4)
|
||||
|
||||
/* Save version == 0x1 fields */
|
||||
lla a4, _dynamic_next_addr
|
||||
REG_L a3, FW_DYNAMIC_INFO_NEXT_ADDR_OFFSET(a2)
|
||||
REG_S a3, (a4)
|
||||
lla a4, _dynamic_next_mode
|
||||
REG_L a3, FW_DYNAMIC_INFO_NEXT_MODE_OFFSET(a2)
|
||||
REG_S a3, (a4)
|
||||
lla a4, _dynamic_options
|
||||
REG_L a3, FW_DYNAMIC_INFO_OPTIONS_OFFSET(a2)
|
||||
REG_S a3, (a4)
|
||||
|
||||
/* Save version == 0x2 fields */
|
||||
li a4, FW_DYNAMIC_INFO_VERSION_2
|
||||
REG_L a3, FW_DYNAMIC_INFO_VERSION_OFFSET(a2)
|
||||
blt a3, a4, 2f
|
||||
lla a4, _dynamic_boot_hart
|
||||
REG_L a3, FW_DYNAMIC_INFO_BOOT_HART_OFFSET(a2)
|
||||
REG_S a3, (a4)
|
||||
2:
|
||||
ret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_next_arg1
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The a0, a1, and a2 registers will be same as passed by
|
||||
* previous booting stage.
|
||||
* The next arg1 should be returned in 'a0'.
|
||||
*/
|
||||
fw_next_arg1:
|
||||
lla a0, _dynamic_next_arg1
|
||||
REG_L a0, (a0)
|
||||
ret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_next_addr
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The next address should be returned in 'a0'.
|
||||
*/
|
||||
fw_next_addr:
|
||||
lla a0, _dynamic_next_addr
|
||||
REG_L a0, (a0)
|
||||
ret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_next_mode
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The next address should be returned in 'a0'
|
||||
*/
|
||||
fw_next_mode:
|
||||
lla a0, _dynamic_next_mode
|
||||
REG_L a0, (a0)
|
||||
ret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_options
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The 'a4' register will have default options.
|
||||
* The next address should be returned in 'a0'.
|
||||
*/
|
||||
fw_options:
|
||||
lla a0, _dynamic_options
|
||||
REG_L a0, (a0)
|
||||
ret
|
||||
|
||||
.section .data
|
||||
.align 3
|
||||
_dynamic_next_arg1:
|
||||
RISCV_PTR 0x0
|
||||
_dynamic_next_addr:
|
||||
RISCV_PTR 0x0
|
||||
_dynamic_next_mode:
|
||||
RISCV_PTR PRV_S
|
||||
_dynamic_options:
|
||||
RISCV_PTR 0x0
|
||||
_dynamic_boot_hart:
|
||||
RISCV_PTR -1
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Anup Patel <anup.patel@wdc.com>
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH(riscv)
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
#include "fw_base.ldS"
|
||||
|
||||
PROVIDE(_fw_reloc_end = .);
|
||||
}
|
@ -9,98 +9,40 @@
|
||||
|
||||
#include "fw_base.S"
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_boot_hart
|
||||
/*
|
||||
* This function is called very early even before
|
||||
* fw_save_info() is called.
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The boot HART id should be returned in 'a0'.
|
||||
*/
|
||||
fw_boot_hart:
|
||||
li a0, -1
|
||||
ret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_save_info
|
||||
/*
|
||||
* We can only use a0, a1, a2, a3, and a4 registers here.
|
||||
* The a0, a1, and a2 registers will be same as passed by
|
||||
* previous booting stage.
|
||||
* Nothing to be returned here.
|
||||
*/
|
||||
fw_save_info:
|
||||
ret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_next_arg1
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The a0, a1, and a2 registers will be same as passed by
|
||||
* previous booting stage.
|
||||
* The next arg1 should be returned in 'a0'.
|
||||
*/
|
||||
fw_next_arg1:
|
||||
#ifdef FW_JUMP_FDT_ADDR
|
||||
li a0, FW_JUMP_FDT_ADDR
|
||||
#elif defined(FW_JUMP_FDT_OFFSET)
|
||||
lla a0, _fw_start
|
||||
li a1, FW_JUMP_FDT_OFFSET
|
||||
add a0, a0, a1
|
||||
#else
|
||||
add a0, a1, zero
|
||||
#endif
|
||||
ret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_next_addr
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The next address should be returned in 'a0'.
|
||||
*/
|
||||
fw_next_addr:
|
||||
#ifdef FW_JUMP_ADDR
|
||||
lla a0, _jump_addr
|
||||
REG_L a0, (a0)
|
||||
#elif defined(FW_JUMP_OFFSET)
|
||||
lla a0, _fw_start
|
||||
li a1, FW_JUMP_OFFSET
|
||||
add a0, a0, a1
|
||||
#else
|
||||
#error "Must define at least FW_JUMP_ADDR or FW_JUMP_OFFSET"
|
||||
#endif
|
||||
ret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_next_mode
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The next address should be returned in 'a0'
|
||||
*/
|
||||
fw_next_mode:
|
||||
li a0, PRV_S
|
||||
ret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_options
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The 'a4' register will have default options.
|
||||
* The next address should be returned in 'a0'.
|
||||
*/
|
||||
fw_options:
|
||||
.global fw_prev_arg1
|
||||
fw_prev_arg1:
|
||||
/* We return previous arg1 in 'a0' */
|
||||
add a0, zero, zero
|
||||
ret
|
||||
|
||||
#ifdef FW_JUMP_ADDR
|
||||
.section .rodata
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.global fw_next_arg1
|
||||
fw_next_arg1:
|
||||
/* We return next arg1 in 'a0' */
|
||||
#ifdef FW_JUMP_FDT_ADDR
|
||||
li a0, FW_JUMP_FDT_ADDR
|
||||
#else
|
||||
add a0, zero, zero
|
||||
#endif
|
||||
ret
|
||||
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.global fw_next_addr
|
||||
fw_next_addr:
|
||||
/* We return next address in 'a0' */
|
||||
la a0, _jump_addr
|
||||
REG_L a0, (a0)
|
||||
ret
|
||||
|
||||
#ifndef FW_JUMP_ADDR
|
||||
#error "Must define FW_JUMP_ADDR"
|
||||
#endif
|
||||
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
_jump_addr:
|
||||
RISCV_PTR FW_JUMP_ADDR
|
||||
#endif
|
||||
|
@ -13,6 +13,4 @@ ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
#include "fw_base.ldS"
|
||||
|
||||
PROVIDE(_fw_reloc_end = .);
|
||||
}
|
||||
|
@ -9,88 +9,48 @@
|
||||
|
||||
#include "fw_base.S"
|
||||
|
||||
.align 4
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_boot_hart
|
||||
/*
|
||||
* This function is called very early even before
|
||||
* fw_save_info() is called.
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The boot HART id should be returned in 'a0'.
|
||||
*/
|
||||
fw_boot_hart:
|
||||
li a0, -1
|
||||
ret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_save_info
|
||||
/*
|
||||
* We can only use a0, a1, a2, a3, and a4 registers here.
|
||||
* The a0, a1, and a2 registers will be same as passed by
|
||||
* previous booting stage.
|
||||
* Nothing to be returned here.
|
||||
*/
|
||||
fw_save_info:
|
||||
ret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_next_arg1
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The a0, a1, and a2 registers will be same as passed by
|
||||
* previous booting stage.
|
||||
* The next arg1 should be returned in 'a0'.
|
||||
*/
|
||||
fw_next_arg1:
|
||||
#ifdef FW_PAYLOAD_FDT_ADDR
|
||||
li a0, FW_PAYLOAD_FDT_ADDR
|
||||
#elif defined(FW_PAYLOAD_FDT_OFFSET)
|
||||
lla a0, _fw_start
|
||||
li a1, FW_PAYLOAD_FDT_OFFSET
|
||||
add a0, a0, a1
|
||||
.global fw_prev_arg1
|
||||
fw_prev_arg1:
|
||||
/* We return previous arg1 in 'a0' */
|
||||
#ifdef FW_PAYLOAD_FDT_PATH
|
||||
la a0, fdt_bin
|
||||
#else
|
||||
add a0, a1, zero
|
||||
add a0, zero, zero
|
||||
#endif
|
||||
ret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_next_addr
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The next address should be returned in 'a0'.
|
||||
*/
|
||||
fw_next_addr:
|
||||
lla a0, payload_bin
|
||||
ret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_next_mode
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The next address should be returned in 'a0'.
|
||||
*/
|
||||
fw_next_mode:
|
||||
li a0, PRV_S
|
||||
ret
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.global fw_options
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The 'a4' register will have default options.
|
||||
* The next address should be returned in 'a0'.
|
||||
*/
|
||||
fw_options:
|
||||
add a0, zero, zero
|
||||
ret
|
||||
|
||||
.section .payload, "ax", %progbits
|
||||
.align 4
|
||||
.section .entry, "ax", %progbits
|
||||
.global fw_next_arg1
|
||||
fw_next_arg1:
|
||||
/* We return next arg1 in 'a0' */
|
||||
#ifdef FW_PAYLOAD_FDT_ADDR
|
||||
li a0, FW_PAYLOAD_FDT_ADDR
|
||||
#else
|
||||
add a0, zero, zero
|
||||
#endif
|
||||
ret
|
||||
|
||||
.align 4
|
||||
.section .entry, "ax", %progbits
|
||||
.global fw_next_addr
|
||||
fw_next_addr:
|
||||
/* We return next address in 'a0' */
|
||||
la a0, payload_bin
|
||||
ret
|
||||
|
||||
#ifdef FW_PAYLOAD_FDT_PATH
|
||||
.align 4
|
||||
.section .text, "ax", %progbits
|
||||
.globl fdt_bin
|
||||
fdt_bin:
|
||||
.incbin FW_PAYLOAD_FDT_PATH
|
||||
#endif
|
||||
|
||||
.align 4
|
||||
.section .payload, "ax", %progbits
|
||||
.globl payload_bin
|
||||
payload_bin:
|
||||
#ifndef FW_PAYLOAD_PATH
|
||||
|
@ -27,6 +27,4 @@ SECTIONS
|
||||
. = ALIGN(8);
|
||||
PROVIDE(_payload_end = .);
|
||||
}
|
||||
|
||||
PROVIDE(_fw_reloc_end = .);
|
||||
}
|
||||
|
@ -15,29 +15,12 @@ firmware-ldflags-y +=
|
||||
|
||||
ifdef FW_TEXT_START
|
||||
firmware-genflags-y += -DFW_TEXT_START=$(FW_TEXT_START)
|
||||
else
|
||||
firmware-genflags-y += -DFW_TEXT_START=0x0
|
||||
endif
|
||||
|
||||
ifdef FW_FDT_PATH
|
||||
firmware-genflags-y += -DFW_FDT_PATH=\"$(FW_FDT_PATH)\"
|
||||
ifdef FW_FDT_PADDING
|
||||
firmware-genflags-y += -DFW_FDT_PADDING=$(FW_FDT_PADDING)
|
||||
endif
|
||||
endif
|
||||
|
||||
firmware-bins-$(FW_DYNAMIC) += fw_dynamic.bin
|
||||
|
||||
firmware-bins-$(FW_JUMP) += fw_jump.bin
|
||||
ifdef FW_JUMP_OFFSET
|
||||
firmware-genflags-$(FW_JUMP) += -DFW_JUMP_OFFSET=$(FW_JUMP_OFFSET)
|
||||
endif
|
||||
ifdef FW_JUMP_ADDR
|
||||
firmware-genflags-$(FW_JUMP) += -DFW_JUMP_ADDR=$(FW_JUMP_ADDR)
|
||||
endif
|
||||
ifdef FW_JUMP_FDT_OFFSET
|
||||
firmware-genflags-$(FW_JUMP) += -DFW_JUMP_FDT_OFFSET=$(FW_JUMP_FDT_OFFSET)
|
||||
endif
|
||||
ifdef FW_JUMP_FDT_ADDR
|
||||
firmware-genflags-$(FW_JUMP) += -DFW_JUMP_FDT_ADDR=$(FW_JUMP_FDT_ADDR)
|
||||
endif
|
||||
@ -46,7 +29,7 @@ firmware-bins-$(FW_PAYLOAD) += fw_payload.bin
|
||||
ifdef FW_PAYLOAD_PATH
|
||||
FW_PAYLOAD_PATH_FINAL=$(FW_PAYLOAD_PATH)
|
||||
else
|
||||
FW_PAYLOAD_PATH_FINAL=$(platform_build_dir)/firmware/payloads/test.bin
|
||||
FW_PAYLOAD_PATH_FINAL=$(build_dir)/$(platform_subdir)/firmware/payloads/test.bin
|
||||
endif
|
||||
firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_PATH=\"$(FW_PAYLOAD_PATH_FINAL)\"
|
||||
ifdef FW_PAYLOAD_OFFSET
|
||||
@ -56,22 +39,14 @@ ifdef FW_PAYLOAD_ALIGN
|
||||
firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_ALIGN=$(FW_PAYLOAD_ALIGN)
|
||||
endif
|
||||
|
||||
ifdef FW_PAYLOAD_FDT_OFFSET
|
||||
firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_OFFSET=$(FW_PAYLOAD_FDT_OFFSET)
|
||||
ifndef FW_PAYLOAD_FDT_PATH
|
||||
ifdef FW_PAYLOAD_FDT
|
||||
FW_PAYLOAD_FDT_PATH=$(build_dir)/$(platform_subdir)/$(FW_PAYLOAD_FDT)
|
||||
endif
|
||||
endif
|
||||
ifdef FW_PAYLOAD_FDT_PATH
|
||||
firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_PATH=\"$(FW_PAYLOAD_FDT_PATH)\"
|
||||
endif
|
||||
ifdef FW_PAYLOAD_FDT_ADDR
|
||||
firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_ADDR=$(FW_PAYLOAD_FDT_ADDR)
|
||||
endif
|
||||
|
||||
ifdef FW_OPTIONS
|
||||
firmware-genflags-y += -DFW_OPTIONS=$(FW_OPTIONS)
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_STACK_PROTECTOR),y)
|
||||
stack-protector-cflags-$(CONFIG_STACK_PROTECTOR) := -fstack-protector
|
||||
stack-protector-cflags-$(CONFIG_STACK_PROTECTOR_STRONG) := -fstack-protector-strong
|
||||
stack-protector-cflags-$(CONFIG_STACK_PROTECTOR_ALL) := -fstack-protector-all
|
||||
else
|
||||
stack-protector-cflags-y := -fno-stack-protector
|
||||
endif
|
||||
firmware-cflags-y += $(stack-protector-cflags-y)
|
||||
|
@ -33,12 +33,14 @@ SECTIONS
|
||||
PROVIDE(_text_end = .);
|
||||
}
|
||||
|
||||
/* End of the code sections */
|
||||
|
||||
. = ALIGN(0x1000); /* Ensure next section is page aligned */
|
||||
|
||||
/* End of the code sections */
|
||||
|
||||
/* Beginning of the read-only data sections */
|
||||
|
||||
. = ALIGN(0x1000); /* Ensure next section is page aligned */
|
||||
|
||||
.rodata :
|
||||
{
|
||||
PROVIDE(_rodata_start = .);
|
||||
@ -49,10 +51,10 @@ SECTIONS
|
||||
|
||||
/* End of the read-only data sections */
|
||||
|
||||
. = ALIGN(0x1000); /* Ensure next section is page aligned */
|
||||
|
||||
/* Beginning of the read-write data sections */
|
||||
|
||||
. = ALIGN(0x1000); /* Ensure next section is page aligned */
|
||||
|
||||
.data :
|
||||
{
|
||||
PROVIDE(_data_start = .);
|
||||
|
@ -23,36 +23,25 @@
|
||||
#define REG_L __REG_SEL(ld, lw)
|
||||
#define REG_S __REG_SEL(sd, sw)
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.globl _start
|
||||
_start:
|
||||
/* Pick one hart to run the main boot sequence */
|
||||
lla a3, _hart_lottery
|
||||
la a3, _hart_lottery
|
||||
li a2, 1
|
||||
#ifdef __riscv_atomic
|
||||
amoadd.w a3, a2, (a3)
|
||||
#elif __riscv_zalrsc
|
||||
_sc_fail:
|
||||
lr.w t0, (a3)
|
||||
addw t1, t0, a2
|
||||
sc.w t1, t1, (a3)
|
||||
bnez t1, _sc_fail
|
||||
move a3, t0
|
||||
#else
|
||||
#error "need a or zalrsc"
|
||||
#endif
|
||||
bnez a3, _start_hang
|
||||
|
||||
/* Save a0 and a1 */
|
||||
lla a3, _boot_a0
|
||||
la a3, _boot_a0
|
||||
REG_S a0, 0(a3)
|
||||
lla a3, _boot_a1
|
||||
la a3, _boot_a1
|
||||
REG_S a1, 0(a3)
|
||||
|
||||
/* Zero-out BSS */
|
||||
lla a4, _bss_start
|
||||
lla a5, _bss_end
|
||||
la a4, _bss_start
|
||||
la a5, _bss_end
|
||||
_bss_zero:
|
||||
REG_S zero, (a4)
|
||||
add a4, a4, __SIZEOF_POINTER__
|
||||
@ -64,51 +53,36 @@ _start_warm:
|
||||
csrw CSR_SIP, zero
|
||||
|
||||
/* Setup exception vectors */
|
||||
lla a3, _start_hang
|
||||
la a3, _start_hang
|
||||
csrw CSR_STVEC, a3
|
||||
|
||||
/* Setup stack */
|
||||
lla a3, _payload_end
|
||||
la a3, _payload_end
|
||||
li a4, 0x2000
|
||||
add sp, a3, a4
|
||||
|
||||
/* Jump to C main */
|
||||
lla a3, _boot_a0
|
||||
la a3, _boot_a0
|
||||
REG_L a0, 0(a3)
|
||||
lla a3, _boot_a1
|
||||
la a3, _boot_a1
|
||||
REG_L a1, 0(a3)
|
||||
call test_main
|
||||
|
||||
/* We don't expect to reach here hence just hang */
|
||||
j _start_hang
|
||||
|
||||
.section .entry, "ax", %progbits
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.globl _start_hang
|
||||
_start_hang:
|
||||
wfi
|
||||
j _start_hang
|
||||
|
||||
.section .data
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
_hart_lottery:
|
||||
RISCV_PTR 0
|
||||
_boot_a0:
|
||||
RISCV_PTR 0
|
||||
_boot_a1:
|
||||
RISCV_PTR 0
|
||||
|
||||
/* This will be called when the stack corruption is detected */
|
||||
.section .text
|
||||
.align 3
|
||||
.globl __stack_chk_fail
|
||||
.type __stack_chk_fail, %function
|
||||
.equ __stack_chk_fail, _start_hang
|
||||
|
||||
/* Initial value of the stack guard variable */
|
||||
.section .data
|
||||
.align 3
|
||||
.globl __stack_chk_guard
|
||||
.type __stack_chk_guard, %object
|
||||
__stack_chk_guard:
|
||||
RISCV_PTR 0x95B5FF5A
|
||||
|
@ -8,59 +8,16 @@
|
||||
*/
|
||||
|
||||
#include <sbi/sbi_ecall_interface.h>
|
||||
#include <sbi/sbi_string.h>
|
||||
|
||||
struct sbiret {
|
||||
unsigned long error;
|
||||
unsigned long value;
|
||||
};
|
||||
|
||||
struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
|
||||
unsigned long arg1, unsigned long arg2,
|
||||
unsigned long arg3, unsigned long arg4,
|
||||
unsigned long arg5)
|
||||
{
|
||||
struct sbiret ret;
|
||||
|
||||
register unsigned long a0 asm ("a0") = (unsigned long)(arg0);
|
||||
register unsigned long a1 asm ("a1") = (unsigned long)(arg1);
|
||||
register unsigned long a2 asm ("a2") = (unsigned long)(arg2);
|
||||
register unsigned long a3 asm ("a3") = (unsigned long)(arg3);
|
||||
register unsigned long a4 asm ("a4") = (unsigned long)(arg4);
|
||||
register unsigned long a5 asm ("a5") = (unsigned long)(arg5);
|
||||
register unsigned long a6 asm ("a6") = (unsigned long)(fid);
|
||||
register unsigned long a7 asm ("a7") = (unsigned long)(ext);
|
||||
asm volatile ("ecall"
|
||||
: "+r" (a0), "+r" (a1)
|
||||
: "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7)
|
||||
: "memory");
|
||||
ret.error = a0;
|
||||
ret.value = a1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void sbi_ecall_console_puts(const char *str)
|
||||
{
|
||||
sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE,
|
||||
sbi_strlen(str), (unsigned long)str, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static inline void sbi_ecall_shutdown(void)
|
||||
{
|
||||
sbi_ecall(SBI_EXT_SRST, SBI_EXT_SRST_RESET,
|
||||
SBI_SRST_RESET_TYPE_SHUTDOWN, SBI_SRST_RESET_REASON_NONE,
|
||||
0, 0, 0, 0);
|
||||
}
|
||||
|
||||
#define wfi() \
|
||||
do { \
|
||||
__asm__ __volatile__("wfi" ::: "memory"); \
|
||||
} while (0)
|
||||
#define wfi() \
|
||||
do { \
|
||||
__asm__ __volatile__ ("wfi" ::: "memory"); \
|
||||
} while (0)
|
||||
|
||||
void test_main(unsigned long a0, unsigned long a1)
|
||||
{
|
||||
sbi_ecall_console_puts("\nTest payload running\n");
|
||||
sbi_ecall_shutdown();
|
||||
sbi_ecall_console_puts("sbi_ecall_shutdown failed to execute.\n");
|
||||
|
||||
while (1)
|
||||
wfi();
|
||||
}
|
||||
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Anup Patel <anup.patel@wdc.com>
|
||||
*/
|
||||
|
||||
#ifndef __FW_DYNAMIC_H__
|
||||
#define __FW_DYNAMIC_H__
|
||||
|
||||
#include <sbi/riscv_asm.h>
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
/** Offset of magic member in fw_dynamic_info */
|
||||
#define FW_DYNAMIC_INFO_MAGIC_OFFSET (0 * __SIZEOF_LONG__)
|
||||
/** Offset of version member in fw_dynamic_info */
|
||||
#define FW_DYNAMIC_INFO_VERSION_OFFSET (1 * __SIZEOF_LONG__)
|
||||
/** Offset of next_addr member in fw_dynamic_info (version >= 1) */
|
||||
#define FW_DYNAMIC_INFO_NEXT_ADDR_OFFSET (2 * __SIZEOF_LONG__)
|
||||
/** Offset of next_mode member in fw_dynamic_info (version >= 1) */
|
||||
#define FW_DYNAMIC_INFO_NEXT_MODE_OFFSET (3 * __SIZEOF_LONG__)
|
||||
/** Offset of options member in fw_dynamic_info (version >= 1) */
|
||||
#define FW_DYNAMIC_INFO_OPTIONS_OFFSET (4 * __SIZEOF_LONG__)
|
||||
/** Offset of boot_hart member in fw_dynamic_info (version >= 2) */
|
||||
#define FW_DYNAMIC_INFO_BOOT_HART_OFFSET (5 * __SIZEOF_LONG__)
|
||||
|
||||
/** Expected value of info magic ('OSBI' ascii string in hex) */
|
||||
#define FW_DYNAMIC_INFO_MAGIC_VALUE 0x4942534f
|
||||
|
||||
/** Maximum supported info version */
|
||||
#define FW_DYNAMIC_INFO_VERSION_2 0x2
|
||||
#define FW_DYNAMIC_INFO_VERSION_MAX FW_DYNAMIC_INFO_VERSION_2
|
||||
|
||||
/** Possible next mode values */
|
||||
#define FW_DYNAMIC_INFO_NEXT_MODE_U 0x0
|
||||
#define FW_DYNAMIC_INFO_NEXT_MODE_S 0x1
|
||||
#define FW_DYNAMIC_INFO_NEXT_MODE_M 0x3
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
/** Representation dynamic info passed by previous booting stage */
|
||||
struct fw_dynamic_info {
|
||||
/** Info magic */
|
||||
unsigned long magic;
|
||||
/** Info version */
|
||||
unsigned long version;
|
||||
/** Next booting stage address */
|
||||
unsigned long next_addr;
|
||||
/** Next booting stage mode */
|
||||
unsigned long next_mode;
|
||||
/** Options for OpenSBI library */
|
||||
unsigned long options;
|
||||
/**
|
||||
* Preferred boot HART id
|
||||
*
|
||||
* It is possible that the previous booting stage uses same link
|
||||
* address as the FW_DYNAMIC firmware. In this case, the relocation
|
||||
* lottery mechanism can potentially overwrite the previous booting
|
||||
* stage while other HARTs are still running in the previous booting
|
||||
* stage leading to boot-time crash. To avoid this boot-time crash,
|
||||
* the previous booting stage can specify last HART that will jump
|
||||
* to the FW_DYNAMIC firmware as the preferred boot HART.
|
||||
*
|
||||
* To avoid specifying a preferred boot HART, the previous booting
|
||||
* stage can set it to -1UL which will force the FW_DYNAMIC firmware
|
||||
* to use the relocation lottery mechanism.
|
||||
*/
|
||||
unsigned long boot_hart;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* Prevent modification of struct fw_dynamic_info from affecting
|
||||
* FW_DYNAMIC_INFO_xxx_OFFSET
|
||||
*/
|
||||
assert_member_offset(struct fw_dynamic_info, magic, FW_DYNAMIC_INFO_MAGIC_OFFSET);
|
||||
assert_member_offset(struct fw_dynamic_info, version, FW_DYNAMIC_INFO_VERSION_OFFSET);
|
||||
assert_member_offset(struct fw_dynamic_info, next_addr, FW_DYNAMIC_INFO_NEXT_ADDR_OFFSET);
|
||||
assert_member_offset(struct fw_dynamic_info, next_mode, FW_DYNAMIC_INFO_NEXT_MODE_OFFSET);
|
||||
assert_member_offset(struct fw_dynamic_info, options, FW_DYNAMIC_INFO_OPTIONS_OFFSET);
|
||||
assert_member_offset(struct fw_dynamic_info, boot_hart, FW_DYNAMIC_INFO_BOOT_HART_OFFSET);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -12,9 +12,7 @@
|
||||
|
||||
#include <sbi/riscv_encoding.h>
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
#ifdef __ASSEMBLY__
|
||||
#define __ASM_STR(x) x
|
||||
#else
|
||||
#define __ASM_STR(x) #x
|
||||
@ -28,17 +26,14 @@
|
||||
#error "Unexpected __riscv_xlen"
|
||||
#endif
|
||||
|
||||
#define PAGE_SHIFT (12)
|
||||
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
|
||||
#define PAGE_MASK (~(PAGE_SIZE - 1))
|
||||
|
||||
#define REG_L __REG_SEL(ld, lw)
|
||||
#define REG_S __REG_SEL(sd, sw)
|
||||
#define SZREG __REG_SEL(8, 4)
|
||||
#define LGREG __REG_SEL(3, 2)
|
||||
|
||||
#if __SIZEOF_POINTER__ == 8
|
||||
#ifdef __ASSEMBLER__
|
||||
#define BITS_PER_LONG 64
|
||||
#ifdef __ASSEMBLY__
|
||||
#define RISCV_PTR .dword
|
||||
#define RISCV_SZPTR 8
|
||||
#define RISCV_LGPTR 3
|
||||
@ -48,7 +43,8 @@
|
||||
#define RISCV_LGPTR "3"
|
||||
#endif
|
||||
#elif __SIZEOF_POINTER__ == 4
|
||||
#ifdef __ASSEMBLER__
|
||||
#define BITS_PER_LONG 32
|
||||
#ifdef __ASSEMBLY__
|
||||
#define RISCV_PTR .word
|
||||
#define RISCV_SZPTR 4
|
||||
#define RISCV_LGPTR 2
|
||||
@ -77,150 +73,107 @@
|
||||
#error "Unexpected __SIZEOF_SHORT__"
|
||||
#endif
|
||||
|
||||
/* clang-format on */
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#define csr_swap(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrrw %0, " __ASM_STR(csr) ", %1"\
|
||||
: "=r" (__v) : "rK" (__v) \
|
||||
: "memory"); \
|
||||
__v; \
|
||||
})
|
||||
|
||||
#define csr_swap(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__("csrrw %0, " __ASM_STR(csr) ", %1" \
|
||||
: "=r"(__v) \
|
||||
: "rK"(__v) \
|
||||
: "memory"); \
|
||||
__v; \
|
||||
})
|
||||
#define csr_read(csr) \
|
||||
({ \
|
||||
register unsigned long __v; \
|
||||
__asm__ __volatile__ ("csrr %0, " __ASM_STR(csr) \
|
||||
: "=r" (__v) : \
|
||||
: "memory"); \
|
||||
__v; \
|
||||
})
|
||||
|
||||
#define csr_read(csr) \
|
||||
({ \
|
||||
register unsigned long __v; \
|
||||
__asm__ __volatile__("csrr %0, " __ASM_STR(csr) \
|
||||
: "=r"(__v) \
|
||||
: \
|
||||
: "memory"); \
|
||||
__v; \
|
||||
})
|
||||
#define csr_write(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrw " __ASM_STR(csr) ", %0" \
|
||||
: : "rK" (__v) \
|
||||
: "memory"); \
|
||||
})
|
||||
|
||||
/* 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_read_set(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrrs %0, " __ASM_STR(csr) ", %1"\
|
||||
: "=r" (__v) : "rK" (__v) \
|
||||
: "memory"); \
|
||||
__v; \
|
||||
})
|
||||
|
||||
#define csr_write(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__("csrw " __ASM_STR(csr) ", %0" \
|
||||
: \
|
||||
: "rK"(__v) \
|
||||
: "memory"); \
|
||||
})
|
||||
#define csr_set(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrs " __ASM_STR(csr) ", %0" \
|
||||
: : "rK" (__v) \
|
||||
: "memory"); \
|
||||
})
|
||||
|
||||
#define csr_read_set(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__("csrrs %0, " __ASM_STR(csr) ", %1" \
|
||||
: "=r"(__v) \
|
||||
: "rK"(__v) \
|
||||
: "memory"); \
|
||||
__v; \
|
||||
})
|
||||
#define csr_read_clear(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrrc %0, " __ASM_STR(csr) ", %1"\
|
||||
: "=r" (__v) : "rK" (__v) \
|
||||
: "memory"); \
|
||||
__v; \
|
||||
})
|
||||
|
||||
#define csr_set(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__("csrs " __ASM_STR(csr) ", %0" \
|
||||
: \
|
||||
: "rK"(__v) \
|
||||
: "memory"); \
|
||||
})
|
||||
|
||||
#define csr_read_clear(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__("csrrc %0, " __ASM_STR(csr) ", %1" \
|
||||
: "=r"(__v) \
|
||||
: "rK"(__v) \
|
||||
: "memory"); \
|
||||
__v; \
|
||||
})
|
||||
|
||||
#define csr_clear(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__("csrc " __ASM_STR(csr) ", %0" \
|
||||
: \
|
||||
: "rK"(__v) \
|
||||
: "memory"); \
|
||||
})
|
||||
|
||||
#if __riscv_xlen == 64
|
||||
#define __csrrw64(op, csr, csrh, val) (true ? op(csr, val) : (uint64_t)csrh)
|
||||
#define __csrr64( op, csr, csrh) (true ? op(csr) : (uint64_t)csrh)
|
||||
#define __csrw64( op, csr, csrh, val) (true ? op(csr, val) : (uint64_t)csrh)
|
||||
#elif __riscv_xlen == 32
|
||||
#define __csrrw64(op, csr, csrh, val) ( op(csr, val) | (uint64_t)op(csrh, val >> 32) << 32)
|
||||
#define __csrr64( op, csr, csrh) ( op(csr) | (uint64_t)op(csrh) << 32)
|
||||
#define __csrw64( op, csr, csrh, val) ({ op(csr, val); op(csrh, val >> 32); })
|
||||
#endif
|
||||
|
||||
#define csr_swap64( csr, val) __csrrw64(csr_swap, csr, csr ## H, val)
|
||||
#define csr_read64( csr) __csrr64 (csr_read, csr, csr ## H)
|
||||
#define csr_read_relaxed64(csr) __csrr64 (csr_read_relaxed, csr, csr ## H)
|
||||
#define csr_write64( csr, val) __csrw64 (csr_write, csr, csr ## H, val)
|
||||
#define csr_read_set64( csr, val) __csrrw64(csr_read_set, csr, csr ## H, val)
|
||||
#define csr_set64( csr, val) __csrw64 (csr_set, csr, csr ## H, val)
|
||||
#define csr_clear64( csr, val) __csrw64 (csr_clear, csr, csr ## H, val)
|
||||
#define csr_read_clear64( csr, val) __csrrw64(csr_read_clear, csr, csr ## H, val)
|
||||
#define csr_clear64( csr, val) __csrw64 (csr_clear, csr, csr ## H, val)
|
||||
#define csr_clear(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrc " __ASM_STR(csr) ", %0" \
|
||||
: : "rK" (__v) \
|
||||
: "memory"); \
|
||||
})
|
||||
|
||||
unsigned long csr_read_num(int csr_num);
|
||||
|
||||
void csr_write_num(int csr_num, unsigned long val);
|
||||
|
||||
#define wfi() \
|
||||
do { \
|
||||
__asm__ __volatile__("wfi" ::: "memory"); \
|
||||
} while (0)
|
||||
#define wfi() \
|
||||
do { \
|
||||
__asm__ __volatile__ ("wfi" ::: "memory"); \
|
||||
} while (0)
|
||||
|
||||
#define ebreak() \
|
||||
do { \
|
||||
__asm__ __volatile__("ebreak" ::: "memory"); \
|
||||
} while (0)
|
||||
static inline int misa_extension(char ext)
|
||||
{
|
||||
return csr_read(CSR_MISA) & (1 << (ext - 'A'));
|
||||
}
|
||||
|
||||
/* Get current HART id */
|
||||
#define current_hartid() ((unsigned int)csr_read_relaxed(CSR_MHARTID))
|
||||
static inline int misa_xlen(void)
|
||||
{
|
||||
return ((long)csr_read(CSR_MISA) < 0) ? 64 : 32;
|
||||
}
|
||||
|
||||
/* determine CPU extension, return non-zero support */
|
||||
int misa_extension_imp(char ext);
|
||||
static inline void misa_string(char *out, unsigned int out_sz)
|
||||
{
|
||||
unsigned long i, val = csr_read(CSR_MISA);
|
||||
|
||||
#define misa_extension(c)\
|
||||
({\
|
||||
_Static_assert(((c >= 'A') && (c <= 'Z')),\
|
||||
"The parameter of misa_extension must be [A-Z]");\
|
||||
misa_extension_imp(c);\
|
||||
})
|
||||
for (i = 0; i < 26; i++) {
|
||||
if (val & (1 << i)) {
|
||||
*out = 'A' + i;
|
||||
out++;
|
||||
}
|
||||
}
|
||||
*out = '\0';
|
||||
out++;
|
||||
}
|
||||
|
||||
/* Get MXL field of misa, return -1 on error */
|
||||
int misa_xlen(void);
|
||||
int pmp_set(unsigned int n, unsigned long prot,
|
||||
unsigned long addr, unsigned long log2len);
|
||||
|
||||
/* Get RISC-V ISA string representation */
|
||||
void misa_string(int xlen, char *out, unsigned int out_sz);
|
||||
int pmp_get(unsigned int n, unsigned long *prot_out,
|
||||
unsigned long *addr_out, unsigned long *log2len_out);
|
||||
|
||||
/* Disable pmp entry at a given index */
|
||||
int pmp_disable(unsigned int n);
|
||||
|
||||
/* Check if the matching field is set */
|
||||
int is_pmp_entry_mapped(unsigned long entry);
|
||||
|
||||
int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
|
||||
unsigned long log2len);
|
||||
|
||||
int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
|
||||
unsigned long *log2len);
|
||||
|
||||
#endif /* !__ASSEMBLER__ */
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif
|
||||
|
@ -14,12 +14,11 @@ typedef struct {
|
||||
volatile long counter;
|
||||
} atomic_t;
|
||||
|
||||
#define ATOMIC_INIT(_lptr, val) (_lptr)->counter = (val)
|
||||
#define ATOMIC_INIT(_lptr, val) \
|
||||
(_lptr)->counter = (val)
|
||||
|
||||
#define ATOMIC_INITIALIZER(val) \
|
||||
{ \
|
||||
.counter = (val), \
|
||||
}
|
||||
#define ATOMIC_INITIALIZER(val) \
|
||||
{ .counter = (val), }
|
||||
|
||||
long atomic_read(atomic_t *atom);
|
||||
|
||||
@ -29,24 +28,21 @@ long atomic_add_return(atomic_t *atom, long value);
|
||||
|
||||
long atomic_sub_return(atomic_t *atom, long value);
|
||||
|
||||
long atomic_cmpxchg(atomic_t *atom, long oldval, long newval);
|
||||
long arch_atomic_cmpxchg(atomic_t *atom, long oldval, long newval);
|
||||
|
||||
long atomic_xchg(atomic_t *atom, long newval);
|
||||
long arch_atomic_xchg(atomic_t *atom, long newval);
|
||||
|
||||
unsigned int atomic_raw_xchg_uint(volatile unsigned int *ptr,
|
||||
unsigned int newval);
|
||||
|
||||
unsigned long atomic_raw_xchg_ulong(volatile unsigned long *ptr,
|
||||
unsigned long newval);
|
||||
/**
|
||||
* Set a bit in an atomic variable and return the value of bit before modify.
|
||||
* Set a bit in an atomic variable and return the new value.
|
||||
* @nr : Bit to set.
|
||||
* @atom: atomic variable to modify
|
||||
*/
|
||||
int atomic_set_bit(int nr, atomic_t *atom);
|
||||
|
||||
/**
|
||||
* Clear a bit in an atomic variable and return the value of bit before modify.
|
||||
* Clear a bit in an atomic variable and return the new value.
|
||||
* @nr : Bit to set.
|
||||
* @atom: atomic variable to modify
|
||||
*/
|
||||
@ -54,14 +50,14 @@ int atomic_set_bit(int nr, atomic_t *atom);
|
||||
int atomic_clear_bit(int nr, atomic_t *atom);
|
||||
|
||||
/**
|
||||
* Set a bit in any address and return the value of bit before modify.
|
||||
* Set a bit in any address and return the new value .
|
||||
* @nr : Bit to set.
|
||||
* @addr: Address to modify
|
||||
*/
|
||||
int atomic_raw_set_bit(int nr, volatile unsigned long *addr);
|
||||
|
||||
/**
|
||||
* Clear a bit in any address and return the value of bit before modify.
|
||||
* Clear a bit in any address and return the new value .
|
||||
* @nr : Bit to set.
|
||||
* @addr: Address to modify
|
||||
*/
|
||||
|
@ -10,17 +10,12 @@
|
||||
#ifndef __RISCV_BARRIER_H__
|
||||
#define __RISCV_BARRIER_H__
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#define RISCV_ACQUIRE_BARRIER "\tfence r , rw\n"
|
||||
#define RISCV_RELEASE_BARRIER "\tfence rw, w\n"
|
||||
|
||||
#define RISCV_FENCE(p, s) \
|
||||
__asm__ __volatile__ ("fence " #p "," #s : : : "memory")
|
||||
|
||||
#define RISCV_FENCE_I \
|
||||
__asm__ __volatile__ ("fence.i" : : : "memory")
|
||||
|
||||
/* Read & Write Memory barrier */
|
||||
#define mb() RISCV_FENCE(iorw,iorw)
|
||||
|
||||
@ -40,25 +35,19 @@
|
||||
#define smp_wmb() RISCV_FENCE(w,w)
|
||||
|
||||
/* CPU relax for busy loop */
|
||||
#define cpu_relax() \
|
||||
#define cpu_relax() asm volatile ("" : : : "memory")
|
||||
|
||||
#define __smp_store_release(p, v) \
|
||||
do { \
|
||||
unsigned long __t; \
|
||||
__asm__ __volatile__ ("div %0, %0, zero" : "=r" (__t)); \
|
||||
RISCV_FENCE(rw,w); \
|
||||
*(p) = (v); \
|
||||
} while (0)
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#define __smp_store_release(p, v) \
|
||||
do { \
|
||||
RISCV_FENCE(rw, w); \
|
||||
*(p) = (v); \
|
||||
} while (0)
|
||||
|
||||
#define __smp_load_acquire(p) \
|
||||
({ \
|
||||
typeof(*p) ___p1 = *(p); \
|
||||
RISCV_FENCE(r, rw); \
|
||||
___p1; \
|
||||
})
|
||||
#define __smp_load_acquire(p) \
|
||||
({ \
|
||||
typeof(*p) ___p1 = *(p); \
|
||||
RISCV_FENCE(r,rw); \
|
||||
___p1; \
|
||||
})
|
||||
|
||||
#endif
|
||||
|
@ -1,293 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2023 Ventana Micro System, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Himanshu Chauhan <hchauhan@ventanamicro.com>
|
||||
*/
|
||||
|
||||
#ifndef __RISCV_DBTR_H__
|
||||
#define __RISCV_DBTR_H__
|
||||
|
||||
#define RV_MAX_TRIGGERS 32
|
||||
|
||||
enum {
|
||||
RISCV_DBTR_TRIG_NONE = 0,
|
||||
RISCV_DBTR_TRIG_LEGACY,
|
||||
RISCV_DBTR_TRIG_MCONTROL,
|
||||
RISCV_DBTR_TRIG_ICOUNT,
|
||||
RISCV_DBTR_TRIG_ITRIGGER,
|
||||
RISCV_DBTR_TRIG_ETRIGGER,
|
||||
RISCV_DBTR_TRIG_MCONTROL6,
|
||||
};
|
||||
|
||||
#define RV_DBTR_BIT(_prefix, _name) \
|
||||
RV_DBTR_##_prefix##_##_name##_BIT
|
||||
|
||||
#define RV_DBTR_BIT_MASK(_prefix, _name) \
|
||||
RV_DBTR_##_prefix##_name##_BIT_MASK
|
||||
|
||||
#define RV_DBTR_DECLARE_BIT(_prefix, _name, _val) \
|
||||
RV_DBTR_BIT(_prefix, _name) = _val
|
||||
|
||||
#define RV_DBTR_DECLARE_BIT_MASK(_prefix, _name, _width) \
|
||||
RV_DBTR_BIT_MASK(_prefix, _name) = \
|
||||
(((1UL << _width) - 1) << RV_DBTR_BIT(_prefix, _name))
|
||||
|
||||
#define CLEAR_DBTR_BIT(_target, _prefix, _bit_name) \
|
||||
__clear_bit(RV_DBTR_BIT(_prefix, _bit_name), &_target)
|
||||
|
||||
#define SET_DBTR_BIT(_target, _prefix, _bit_name) \
|
||||
__set_bit(RV_DBTR_BIT(_prefix, _bit_name), &_target)
|
||||
|
||||
/* Trigger Data 1 */
|
||||
enum {
|
||||
RV_DBTR_DECLARE_BIT(TDATA1, DATA, 0),
|
||||
#if __riscv_xlen == 64
|
||||
RV_DBTR_DECLARE_BIT(TDATA1, DMODE, 59),
|
||||
RV_DBTR_DECLARE_BIT(TDATA1, TYPE, 60),
|
||||
#elif __riscv_xlen == 32
|
||||
RV_DBTR_DECLARE_BIT(TDATA1, DMODE, 27),
|
||||
RV_DBTR_DECLARE_BIT(TDATA1, TYPE, 28),
|
||||
#else
|
||||
#error "Unknown __riscv_xlen"
|
||||
#endif
|
||||
};
|
||||
|
||||
enum {
|
||||
#if __riscv_xlen == 64
|
||||
RV_DBTR_DECLARE_BIT_MASK(TDATA1, DATA, 59),
|
||||
#elif __riscv_xlen == 32
|
||||
RV_DBTR_DECLARE_BIT_MASK(TDATA1, DATA, 27),
|
||||
#else
|
||||
#error "Unknown __riscv_xlen"
|
||||
#endif
|
||||
RV_DBTR_DECLARE_BIT_MASK(TDATA1, DMODE, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(TDATA1, TYPE, 4),
|
||||
};
|
||||
|
||||
/* MC - Match Control Type Register */
|
||||
enum {
|
||||
RV_DBTR_DECLARE_BIT(MC, LOAD, 0),
|
||||
RV_DBTR_DECLARE_BIT(MC, STORE, 1),
|
||||
RV_DBTR_DECLARE_BIT(MC, EXEC, 2),
|
||||
RV_DBTR_DECLARE_BIT(MC, U, 3),
|
||||
RV_DBTR_DECLARE_BIT(MC, S, 4),
|
||||
RV_DBTR_DECLARE_BIT(MC, RES2, 5),
|
||||
RV_DBTR_DECLARE_BIT(MC, M, 6),
|
||||
RV_DBTR_DECLARE_BIT(MC, MATCH, 7),
|
||||
RV_DBTR_DECLARE_BIT(MC, CHAIN, 11),
|
||||
RV_DBTR_DECLARE_BIT(MC, ACTION, 12),
|
||||
RV_DBTR_DECLARE_BIT(MC, SIZELO, 16),
|
||||
RV_DBTR_DECLARE_BIT(MC, TIMING, 18),
|
||||
RV_DBTR_DECLARE_BIT(MC, SELECT, 19),
|
||||
RV_DBTR_DECLARE_BIT(MC, HIT, 20),
|
||||
#if __riscv_xlen >= 64
|
||||
RV_DBTR_DECLARE_BIT(MC, SIZEHI, 21),
|
||||
#endif
|
||||
#if __riscv_xlen == 64
|
||||
RV_DBTR_DECLARE_BIT(MC, MASKMAX, 53),
|
||||
RV_DBTR_DECLARE_BIT(MC, DMODE, 59),
|
||||
RV_DBTR_DECLARE_BIT(MC, TYPE, 60),
|
||||
#elif __riscv_xlen == 32
|
||||
RV_DBTR_DECLARE_BIT(MC, MASKMAX, 21),
|
||||
RV_DBTR_DECLARE_BIT(MC, DMODE, 27),
|
||||
RV_DBTR_DECLARE_BIT(MC, TYPE, 28),
|
||||
#else
|
||||
#error "Unknown __riscv_xlen"
|
||||
#endif
|
||||
};
|
||||
|
||||
enum {
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, LOAD, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, STORE, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, EXEC, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, U, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, S, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, RES2, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, M, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, MATCH, 4),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, CHAIN, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, ACTION, 4),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, SIZELO, 2),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, TIMING, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, SELECT, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, HIT, 1),
|
||||
#if __riscv_xlen >= 64
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, SIZEHI, 2),
|
||||
#endif
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, MASKMAX, 6),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, DMODE, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC, TYPE, 4),
|
||||
};
|
||||
|
||||
|
||||
/* ICOUNT - Match Control Type Register */
|
||||
enum {
|
||||
RV_DBTR_DECLARE_BIT(ICOUNT, ACTION, 0),
|
||||
RV_DBTR_DECLARE_BIT(ICOUNT, U, 6),
|
||||
RV_DBTR_DECLARE_BIT(ICOUNT, S, 7),
|
||||
RV_DBTR_DECLARE_BIT(ICOUNT, PENDING, 8),
|
||||
RV_DBTR_DECLARE_BIT(ICOUNT, M, 9),
|
||||
RV_DBTR_DECLARE_BIT(ICOUNT, COUNT, 10),
|
||||
RV_DBTR_DECLARE_BIT(ICOUNT, HIT, 24),
|
||||
RV_DBTR_DECLARE_BIT(ICOUNT, VU, 25),
|
||||
RV_DBTR_DECLARE_BIT(ICOUNT, VS, 26),
|
||||
#if __riscv_xlen == 64
|
||||
RV_DBTR_DECLARE_BIT(ICOUNT, DMODE, 59),
|
||||
RV_DBTR_DECLARE_BIT(ICOUNT, TYPE, 60),
|
||||
#elif __riscv_xlen == 32
|
||||
RV_DBTR_DECLARE_BIT(ICOUNT, DMODE, 27),
|
||||
RV_DBTR_DECLARE_BIT(ICOUNT, TYPE, 28),
|
||||
#else
|
||||
#error "Unknown __riscv_xlen"
|
||||
#endif
|
||||
};
|
||||
|
||||
enum {
|
||||
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, ACTION, 6),
|
||||
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, U, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, S, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, PENDING, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, M, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, COUNT, 14),
|
||||
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, HIT, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, VU, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, VS, 1),
|
||||
#if __riscv_xlen == 64
|
||||
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, DMODE, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, TYPE, 4),
|
||||
#elif __riscv_xlen == 32
|
||||
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, DMODE, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(ICOUNT, TYPE, 4),
|
||||
#else
|
||||
#error "Unknown __riscv_xlen"
|
||||
#endif
|
||||
};
|
||||
|
||||
/* MC6 - Match Control 6 Type Register */
|
||||
enum {
|
||||
RV_DBTR_DECLARE_BIT(MC6, LOAD, 0),
|
||||
RV_DBTR_DECLARE_BIT(MC6, STORE, 1),
|
||||
RV_DBTR_DECLARE_BIT(MC6, EXEC, 2),
|
||||
RV_DBTR_DECLARE_BIT(MC6, U, 3),
|
||||
RV_DBTR_DECLARE_BIT(MC6, S, 4),
|
||||
RV_DBTR_DECLARE_BIT(MC6, RES2, 5),
|
||||
RV_DBTR_DECLARE_BIT(MC6, M, 6),
|
||||
RV_DBTR_DECLARE_BIT(MC6, MATCH, 7),
|
||||
RV_DBTR_DECLARE_BIT(MC6, CHAIN, 11),
|
||||
RV_DBTR_DECLARE_BIT(MC6, ACTION, 12),
|
||||
RV_DBTR_DECLARE_BIT(MC6, SIZE, 16),
|
||||
RV_DBTR_DECLARE_BIT(MC6, TIMING, 20),
|
||||
RV_DBTR_DECLARE_BIT(MC6, SELECT, 21),
|
||||
RV_DBTR_DECLARE_BIT(MC6, HIT, 22),
|
||||
RV_DBTR_DECLARE_BIT(MC6, VU, 23),
|
||||
RV_DBTR_DECLARE_BIT(MC6, VS, 24),
|
||||
#if __riscv_xlen == 64
|
||||
RV_DBTR_DECLARE_BIT(MC6, DMODE, 59),
|
||||
RV_DBTR_DECLARE_BIT(MC6, TYPE, 60),
|
||||
#elif __riscv_xlen == 32
|
||||
RV_DBTR_DECLARE_BIT(MC6, DMODE, 27),
|
||||
RV_DBTR_DECLARE_BIT(MC6, TYPE, 28),
|
||||
#else
|
||||
#error "Unknown __riscv_xlen"
|
||||
#endif
|
||||
};
|
||||
|
||||
enum {
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, LOAD, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, STORE, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, EXEC, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, U, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, S, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, RES2, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, M, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, MATCH, 4),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, CHAIN, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, ACTION, 4),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, SIZE, 4),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, TIMING, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, SELECT, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, HIT, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, VU, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, VS, 1),
|
||||
#if __riscv_xlen == 64
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, DMODE, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, TYPE, 4),
|
||||
#elif __riscv_xlen == 32
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, DMODE, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(MC6, TYPE, 4),
|
||||
#else
|
||||
#error "Unknown __riscv_xlen"
|
||||
#endif
|
||||
};
|
||||
|
||||
#define RV_DBTR_SET_TDATA1_TYPE(_t1, _type) \
|
||||
do { \
|
||||
_t1 &= ~RV_DBTR_BIT_MASK(TDATA1, TYPE); \
|
||||
_t1 |= (((unsigned long)_type \
|
||||
<< RV_DBTR_BIT(TDATA1, TYPE)) \
|
||||
& RV_DBTR_BIT_MASK(TDATA1, TYPE)); \
|
||||
}while (0);
|
||||
|
||||
#define RV_DBTR_SET_MC_TYPE(_t1, _type) \
|
||||
do { \
|
||||
_t1 &= ~RV_DBTR_BIT_MASK(MC, TYPE); \
|
||||
_t1 |= (((unsigned long)_type \
|
||||
<< RV_DBTR_BIT(MC, TYPE)) \
|
||||
& RV_DBTR_BIT_MASK(MC, TYPE)); \
|
||||
}while (0);
|
||||
|
||||
#define RV_DBTR_SET_MC6_TYPE(_t1, _type) \
|
||||
do { \
|
||||
_t1 &= ~RV_DBTR_BIT_MASK(MC6, TYPE); \
|
||||
_t1 |= (((unsigned long)_type \
|
||||
<< RV_DBTR_BIT(MC6, TYPE)) \
|
||||
& RV_DBTR_BIT_MASK(MC6, TYPE)); \
|
||||
}while (0);
|
||||
|
||||
#define RV_DBTR_SET_MC_EXEC(_t1) \
|
||||
SET_DBTR_BIT(_t1, MC, EXEC)
|
||||
|
||||
#define RV_DBTR_SET_MC_LOAD(_t1) \
|
||||
SET_DBTR_BIT(_t1, MC, LOAD)
|
||||
|
||||
#define RV_DBTR_SET_MC_STORE(_t1) \
|
||||
SET_DBTR_BIT(_t1, MC, STORE)
|
||||
|
||||
#define RV_DBTR_SET_MC_SIZELO(_t1, _val) \
|
||||
do { \
|
||||
_t1 &= ~RV_DBTR_BIT_MASK(MC, SIZELO); \
|
||||
_t1 |= ((_val << RV_DBTR_BIT(MC, SIZELO)) \
|
||||
& RV_DBTR_BIT_MASK(MC, SIZELO)); \
|
||||
} while(0);
|
||||
|
||||
#define RV_DBTR_SET_MC_SIZEHI(_t1, _val) \
|
||||
do { \
|
||||
_t1 &= ~RV_DBTR_BIT_MASK(MC, SIZEHI); \
|
||||
_t1 |= ((_val << RV_DBTR_BIT(MC, SIZEHI)) \
|
||||
& RV_DBTR_BIT_MASK(MC, SIZEHI)); \
|
||||
} while(0);
|
||||
|
||||
#define RV_DBTR_SET_MC6_EXEC(_t1) \
|
||||
SET_DBTR_BIT(_t1, MC6, EXEC)
|
||||
|
||||
#define RV_DBTR_SET_MC6_LOAD(_t1) \
|
||||
SET_DBTR_BIT(_t1, MC6, LOAD)
|
||||
|
||||
#define RV_DBTR_SET_MC6_STORE(_t1) \
|
||||
SET_DBTR_BIT(_t1, MC6, STORE)
|
||||
|
||||
#define RV_DBTR_SET_MC6_SIZE(_t1, _val) \
|
||||
do { \
|
||||
_t1 &= ~RV_DBTR_BIT_MASK(MC6, SIZE); \
|
||||
_t1 |= ((_val << RV_DBTR_BIT(MC6, SIZE)) \
|
||||
& RV_DBTR_BIT_MASK(MC6, SIZE)); \
|
||||
} while(0);
|
||||
|
||||
typedef unsigned long riscv_dbtr_tdata1_mcontrol_t;
|
||||
typedef unsigned long riscv_dbtr_tdata1_mcontrol6_t;
|
||||
typedef unsigned long riscv_dbtr_tdata1_t;
|
||||
|
||||
#endif /* __RISCV_DBTR_H__ */
|
@ -1,6 +0,0 @@
|
||||
#ifndef __RISCV_ELF_H__
|
||||
#define __RISCV_ELF_H__
|
||||
|
||||
#define R_RISCV_RELATIVE 3
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -15,67 +15,34 @@
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
#define GET_PRECISION(insn) (((insn) >> 25) & 3)
|
||||
#define GET_RM(insn) (((insn) >> 12) & 7)
|
||||
#define PRECISION_S 0
|
||||
#define PRECISION_D 1
|
||||
|
||||
#ifdef __riscv_flen
|
||||
|
||||
#define GET_F32_REG(insn, pos, regs) \
|
||||
({ \
|
||||
register s32 value asm("a0") = \
|
||||
SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \
|
||||
ulong tmp; \
|
||||
asm("1: auipc %0, %%pcrel_hi(get_f32_reg); add %0, %0, %1; jalr t0, %0, %%pcrel_lo(1b)" \
|
||||
: "=&r"(tmp), "+&r"(value)::"t0"); \
|
||||
value; \
|
||||
})
|
||||
#define SET_F32_REG(insn, pos, regs, val) \
|
||||
({ \
|
||||
register u32 value asm("a0") = (val); \
|
||||
ulong offset = SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \
|
||||
ulong tmp; \
|
||||
asm volatile( \
|
||||
"1: auipc %0, %%pcrel_hi(put_f32_reg); add %0, %0, %2; jalr t0, %0, %%pcrel_lo(1b)" \
|
||||
: "=&r"(tmp) \
|
||||
: "r"(value), "r"(offset) \
|
||||
: "t0"); \
|
||||
})
|
||||
#define GET_F32_REG(insn, pos, regs) ({ \
|
||||
register s32 value asm("a0") = SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \
|
||||
ulong tmp; \
|
||||
asm ("1: auipc %0, %%pcrel_hi(get_f32_reg); add %0, %0, %1; jalr t0, %0, %%pcrel_lo(1b)" : "=&r"(tmp), "+&r"(value) :: "t0"); \
|
||||
value; })
|
||||
#define SET_F32_REG(insn, pos, regs, val) ({ \
|
||||
register u32 value asm("a0") = (val); \
|
||||
ulong offset = SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \
|
||||
ulong tmp; \
|
||||
asm volatile ("1: auipc %0, %%pcrel_hi(put_f32_reg); add %0, %0, %2; jalr t0, %0, %%pcrel_lo(1b)" : "=&r"(tmp) : "r"(value), "r"(offset) : "t0"); })
|
||||
#define init_fp_reg(i) SET_F32_REG((i) << 3, 3, 0, 0)
|
||||
|
||||
#if __riscv_xlen == 64
|
||||
#define GET_F64_REG(insn, pos, regs) \
|
||||
({ \
|
||||
register ulong value asm("a0") = SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \
|
||||
ulong tmp; \
|
||||
asm("1: auipc %0, %%pcrel_hi(get_f64_reg); add %0, %0, %1; jalr t0, %0, %%pcrel_lo(1b)" \
|
||||
: "=&r"(tmp), "+&r"(value)::"t0"); \
|
||||
value; \
|
||||
})
|
||||
#else
|
||||
#define GET_F64_REG(insn, pos, regs) \
|
||||
({ \
|
||||
u64 value; \
|
||||
ulong offset = SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \
|
||||
register ulong ptr asm("a0") = (ulong)&value; \
|
||||
asm ("1: auipc t1, %%pcrel_hi(get_f64_reg); add t1, t1, %2; jalr t0, t1, %%pcrel_lo(1b)" \
|
||||
: "=m"(value) : "r"(ptr), "r"(offset) : "t0", "t1"); \
|
||||
value; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#define SET_F64_REG(insn, pos, regs, val) \
|
||||
({ \
|
||||
uint64_t __val = (val); \
|
||||
register ulong value asm("a0") = \
|
||||
sizeof(ulong) == 4 ? (ulong)&__val : (ulong)__val; \
|
||||
ulong offset = SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \
|
||||
ulong tmp; \
|
||||
asm volatile( \
|
||||
"1: auipc %0, %%pcrel_hi(put_f64_reg); add %0, %0, %2; jalr t0, %0, %%pcrel_lo(1b)" \
|
||||
: "=&r"(tmp) \
|
||||
: "r"(value), "r"(offset) \
|
||||
: "t0"); \
|
||||
})
|
||||
#define GET_F64_REG(insn, pos, regs) ({ \
|
||||
register ulong value asm("a0") = SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \
|
||||
ulong tmp; \
|
||||
asm ("1: auipc %0, %%pcrel_hi(get_f64_reg); add %0, %0, %1; jalr t0, %0, %%pcrel_lo(1b)" : "=&r"(tmp), "+&r"(value) :: "t0"); \
|
||||
sizeof(ulong) == 4 ? *(int64_t*)value : (int64_t)value; })
|
||||
#define SET_F64_REG(insn, pos, regs, val) ({ \
|
||||
uint64_t __val = (val); \
|
||||
register ulong value asm("a0") = sizeof(ulong) == 4 ? (ulong)&__val : (ulong)__val; \
|
||||
ulong offset = SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \
|
||||
ulong tmp; \
|
||||
asm volatile ("1: auipc %0, %%pcrel_hi(put_f64_reg); add %0, %0, %2; jalr t0, %0, %%pcrel_lo(1b)" : "=&r"(tmp) : "r"(value), "r"(offset) : "t0"); })
|
||||
#define GET_FCSR() csr_read(CSR_FCSR)
|
||||
#define SET_FCSR(value) csr_write(CSR_FCSR, (value))
|
||||
#define GET_FRM() csr_read(CSR_FRM)
|
||||
@ -83,7 +50,11 @@
|
||||
#define GET_FFLAGS() csr_read(CSR_FFLAGS)
|
||||
#define SET_FFLAGS(value) csr_write(CSR_FFLAGS, (value))
|
||||
|
||||
#define SET_FS_DIRTY(regs) (regs->mstatus |= MSTATUS_FS)
|
||||
#define SET_FS_DIRTY() ((void) 0)
|
||||
|
||||
#else
|
||||
#error "Floating point emulation not supported.\n"
|
||||
#endif
|
||||
|
||||
#define GET_F32_RS1(insn, regs) (GET_F32_REG(insn, 15, regs))
|
||||
#define GET_F32_RS2(insn, regs) (GET_F32_REG(insn, 20, regs))
|
||||
@ -91,10 +62,8 @@
|
||||
#define GET_F64_RS1(insn, regs) (GET_F64_REG(insn, 15, regs))
|
||||
#define GET_F64_RS2(insn, regs) (GET_F64_REG(insn, 20, regs))
|
||||
#define GET_F64_RS3(insn, regs) (GET_F64_REG(insn, 27, regs))
|
||||
#define SET_F32_RD(insn, regs, val) \
|
||||
(SET_F32_REG(insn, 7, regs, val), SET_FS_DIRTY(regs))
|
||||
#define SET_F64_RD(insn, regs, val) \
|
||||
(SET_F64_REG(insn, 7, regs, val), SET_FS_DIRTY(regs))
|
||||
#define SET_F32_RD(insn, regs, val) (SET_F32_REG(insn, 7, regs, val), SET_FS_DIRTY())
|
||||
#define SET_F64_RD(insn, regs, val) (SET_F64_REG(insn, 7, regs, val), SET_FS_DIRTY())
|
||||
|
||||
#define GET_F32_RS2C(insn, regs) (GET_F32_REG(insn, 2, regs))
|
||||
#define GET_F32_RS2S(insn, regs) (GET_F32_REG(RVC_RS2S(insn), 0, regs))
|
||||
@ -102,5 +71,3 @@
|
||||
#define GET_F64_RS2S(insn, regs) (GET_F64_REG(RVC_RS2S(insn), 0, regs))
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -15,23 +15,23 @@
|
||||
|
||||
static inline void __raw_writeb(u8 val, volatile void *addr)
|
||||
{
|
||||
asm volatile("sb %0, 0(%1)" : : "r"(val), "r"(addr));
|
||||
asm volatile("sb %0, 0(%1)" : : "r" (val), "r" (addr));
|
||||
}
|
||||
|
||||
static inline void __raw_writew(u16 val, volatile void *addr)
|
||||
{
|
||||
asm volatile("sh %0, 0(%1)" : : "r"(val), "r"(addr));
|
||||
asm volatile("sh %0, 0(%1)" : : "r" (val), "r" (addr));
|
||||
}
|
||||
|
||||
static inline void __raw_writel(u32 val, volatile void *addr)
|
||||
{
|
||||
asm volatile("sw %0, 0(%1)" : : "r"(val), "r"(addr));
|
||||
asm volatile("sw %0, 0(%1)" : : "r" (val), "r" (addr));
|
||||
}
|
||||
|
||||
#if __riscv_xlen != 32
|
||||
static inline void __raw_writeq(u64 val, volatile void *addr)
|
||||
{
|
||||
asm volatile("sd %0, 0(%1)" : : "r"(val), "r"(addr));
|
||||
asm volatile("sd %0, 0(%1)" : : "r" (val), "r" (addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -39,7 +39,7 @@ static inline u8 __raw_readb(const volatile void *addr)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
asm volatile("lb %0, 0(%1)" : "=r"(val) : "r"(addr));
|
||||
asm volatile("lb %0, 0(%1)" : "=r" (val) : "r" (addr));
|
||||
return val;
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ static inline u16 __raw_readw(const volatile void *addr)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
asm volatile("lh %0, 0(%1)" : "=r"(val) : "r"(addr));
|
||||
asm volatile("lh %0, 0(%1)" : "=r" (val) : "r" (addr));
|
||||
return val;
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ static inline u32 __raw_readl(const volatile void *addr)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
asm volatile("lw %0, 0(%1)" : "=r"(val) : "r"(addr));
|
||||
asm volatile("lw %0, 0(%1)" : "=r" (val) : "r" (addr));
|
||||
return val;
|
||||
}
|
||||
|
||||
@ -64,15 +64,12 @@ static inline u64 __raw_readq(const volatile void *addr)
|
||||
{
|
||||
u64 val;
|
||||
|
||||
asm volatile("ld %0, 0(%1)" : "=r"(val) : "r"(addr));
|
||||
asm volatile("ld %0, 0(%1)" : "=r" (val) : "r" (addr));
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* FIXME: These are now the same as asm-generic */
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#define __io_rbr() do {} while (0)
|
||||
#define __io_rar() do {} while (0)
|
||||
#define __io_rbw() do {} while (0)
|
||||
@ -109,6 +106,4 @@ static inline u64 __raw_readq(const volatile void *addr)
|
||||
#define writeq(v,c) ({ __io_bw(); __raw_writeq((v),(c)); __io_aw(); })
|
||||
#endif
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#endif
|
||||
|
@ -2,41 +2,29 @@
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||
* Copyright (c) 2021 Christoph Müllner <cmuellner@linux.com>
|
||||
*
|
||||
* Authors:
|
||||
* Anup Patel <anup.patel@wdc.com>
|
||||
*/
|
||||
|
||||
#ifndef __RISCV_LOCKS_H__
|
||||
#define __RISCV_LOCKS_H__
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
#define TICKET_SHIFT 16
|
||||
|
||||
typedef struct {
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
u16 next;
|
||||
u16 owner;
|
||||
#else
|
||||
u16 owner;
|
||||
u16 next;
|
||||
#endif
|
||||
} __aligned(4) spinlock_t;
|
||||
volatile long lock;
|
||||
} spinlock_t;
|
||||
|
||||
#define __SPIN_LOCK_UNLOCKED \
|
||||
(spinlock_t) { 0, 0 }
|
||||
#define __RISCV_SPIN_UNLOCKED 0
|
||||
|
||||
#define SPIN_LOCK_INIT(x) \
|
||||
x = __SPIN_LOCK_UNLOCKED
|
||||
#define SPIN_LOCK_INIT(_lptr) \
|
||||
(_lptr)->lock = __RISCV_SPIN_UNLOCKED
|
||||
|
||||
#define SPIN_LOCK_INITIALIZER \
|
||||
__SPIN_LOCK_UNLOCKED
|
||||
#define SPIN_LOCK_INITIALIZER \
|
||||
{ .lock = __RISCV_SPIN_UNLOCKED, }
|
||||
|
||||
#define DEFINE_SPIN_LOCK(x) \
|
||||
spinlock_t SPIN_LOCK_INIT(x)
|
||||
int spin_lock_check(spinlock_t *lock);
|
||||
|
||||
bool spin_lock_check(spinlock_t *lock);
|
||||
|
||||
bool spin_trylock(spinlock_t *lock);
|
||||
int spin_trylock(spinlock_t *lock);
|
||||
|
||||
void spin_lock(spinlock_t *lock);
|
||||
|
||||
|
@ -1,146 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Anup Patel <anup.patel@wdc.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_BITMAP_H__
|
||||
#define __SBI_BITMAP_H__
|
||||
|
||||
#include <sbi/sbi_bitops.h>
|
||||
|
||||
#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
|
||||
#define BITMAP_LAST_WORD_MASK(nbits) \
|
||||
( \
|
||||
((nbits) % BITS_PER_LONG) ? \
|
||||
((1UL << ((nbits) % BITS_PER_LONG)) - 1) : ~0UL \
|
||||
)
|
||||
|
||||
#define small_const_nbits(nbits) \
|
||||
(__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG)
|
||||
|
||||
#define DECLARE_BITMAP(name, nbits) unsigned long name[BITS_TO_LONGS(nbits)]
|
||||
#define DEFINE_BITMAP(name) extern unsigned long name[]
|
||||
|
||||
static inline unsigned long bitmap_estimate_size(int nbits)
|
||||
{
|
||||
return (BITS_TO_LONGS(nbits) * sizeof(unsigned long));
|
||||
}
|
||||
|
||||
void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, int bits);
|
||||
void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, int bits);
|
||||
void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, int bits);
|
||||
|
||||
static inline void bitmap_set(unsigned long *bmap, int start, int len)
|
||||
{
|
||||
int bit;
|
||||
for (bit = start; bit < (start + len); bit++)
|
||||
bmap[BIT_WORD(bit)] |= (0x1UL << BIT_WORD_OFFSET(bit));
|
||||
}
|
||||
|
||||
static inline void bitmap_clear(unsigned long *bmap, int start, int len)
|
||||
{
|
||||
int bit;
|
||||
for (bit = start; bit < (start + len); bit++)
|
||||
bmap[BIT_WORD(bit)] &= ~(0x1UL << BIT_WORD_OFFSET(bit));
|
||||
}
|
||||
|
||||
static inline void bitmap_zero(unsigned long *dst, int nbits)
|
||||
{
|
||||
if (small_const_nbits(nbits))
|
||||
*dst = 0UL;
|
||||
else {
|
||||
size_t i, len = BITS_TO_LONGS(nbits);
|
||||
for (i = 0; i < len; i++)
|
||||
dst[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_test(unsigned long *bmap, int bit)
|
||||
{
|
||||
return __test_bit(bit, bmap);
|
||||
}
|
||||
|
||||
static inline void bitmap_zero_except(unsigned long *dst,
|
||||
int exception, int nbits)
|
||||
{
|
||||
if (small_const_nbits(nbits))
|
||||
*dst = 0UL;
|
||||
else {
|
||||
size_t i, len = BITS_TO_LONGS(nbits);
|
||||
for (i = 0; i < len; i++)
|
||||
dst[i] = 0;
|
||||
}
|
||||
if (exception < nbits)
|
||||
__set_bit(exception, dst);
|
||||
}
|
||||
|
||||
static inline void bitmap_fill(unsigned long *dst, int nbits)
|
||||
{
|
||||
size_t i, nlongs = BITS_TO_LONGS(nbits);
|
||||
if (!small_const_nbits(nbits)) {
|
||||
for (i = 0; i < (nlongs - 1); i++)
|
||||
dst[i] = -1UL;
|
||||
}
|
||||
dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits);
|
||||
}
|
||||
|
||||
static inline void bitmap_copy(unsigned long *dst,
|
||||
const unsigned long *src, int nbits)
|
||||
{
|
||||
if (small_const_nbits(nbits))
|
||||
*dst = *src;
|
||||
else {
|
||||
size_t i, len = BITS_TO_LONGS(nbits);
|
||||
for (i = 0; i < len; i++)
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bitmap_and(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, int nbits)
|
||||
{
|
||||
if (small_const_nbits(nbits))
|
||||
*dst = *src1 & *src2;
|
||||
else
|
||||
__bitmap_and(dst, src1, src2, nbits);
|
||||
}
|
||||
|
||||
static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, int nbits)
|
||||
{
|
||||
if (small_const_nbits(nbits))
|
||||
*dst = *src1 | *src2;
|
||||
else
|
||||
__bitmap_or(dst, src1, src2, nbits);
|
||||
}
|
||||
|
||||
static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, int nbits)
|
||||
{
|
||||
if (small_const_nbits(nbits))
|
||||
*dst = *src1 ^ *src2;
|
||||
else
|
||||
__bitmap_xor(dst, src1, src2, nbits);
|
||||
}
|
||||
|
||||
static inline int bitmap_weight(const unsigned long *src, int nbits)
|
||||
{
|
||||
int i, res = 0;
|
||||
|
||||
for (i = 0; i < nbits / BITS_PER_LONG; i++)
|
||||
res += sbi_popcount(src[i]);
|
||||
|
||||
if (nbits % BITS_PER_LONG)
|
||||
res += sbi_popcount(src[i] & BITMAP_LAST_WORD_MASK(nbits));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
@ -4,46 +4,59 @@
|
||||
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Atish Patra <atish.patra@wdc.com>
|
||||
* Atish Patra<atish.patra@wdc.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_BITOPS_H__
|
||||
#define __SBI_BITOPS_H__
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
#include <sbi/sbi_bits.h>
|
||||
#include <sbi/riscv_asm.h>
|
||||
|
||||
#define BITS_PER_LONG (8 * __SIZEOF_LONG__)
|
||||
|
||||
#define BITS_PER_LONG_LONG 64
|
||||
|
||||
#define EXTRACT_FIELD(val, which) \
|
||||
(((val) & (which)) / ((which) & ~((which)-1)))
|
||||
#define INSERT_FIELD(val, which, fieldval) \
|
||||
(((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1))))
|
||||
|
||||
#define BITS_TO_LONGS(nbits) (((nbits) + BITS_PER_LONG - 1) / \
|
||||
BITS_PER_LONG)
|
||||
|
||||
#define BIT(nr) (1UL << (nr))
|
||||
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
||||
#define BIT_WORD(bit) ((bit) / BITS_PER_LONG)
|
||||
#define BIT_WORD_OFFSET(bit) ((bit) & (BITS_PER_LONG - 1))
|
||||
#define BIT_ALIGN(bit, align) (((bit) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
#define BIT_ULL(nr) (1ULL << (nr))
|
||||
|
||||
#define GENMASK(h, l) \
|
||||
(((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
|
||||
|
||||
#define GENMASK_ULL(h, l) \
|
||||
(((~0ULL) - (1ULL << (l)) + 1) & (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h))))
|
||||
/**
|
||||
* sbi_ffs - find first (less-significant) set bit in a long word.
|
||||
* ffs - Find first bit set
|
||||
* @x: the word to search
|
||||
*
|
||||
* This is defined the same way as
|
||||
* the libc and compiler builtin ffs routines, therefore
|
||||
* differs in spirit from the above ffz (man ffs).
|
||||
*/
|
||||
static inline int ffs(int x)
|
||||
{
|
||||
int r = 1;
|
||||
|
||||
if (!x)
|
||||
return 0;
|
||||
if (!(x & 0xffff)) {
|
||||
x >>= 16;
|
||||
r += 16;
|
||||
}
|
||||
if (!(x & 0xff)) {
|
||||
x >>= 8;
|
||||
r += 8;
|
||||
}
|
||||
if (!(x & 0xf)) {
|
||||
x >>= 4;
|
||||
r += 4;
|
||||
}
|
||||
if (!(x & 3)) {
|
||||
x >>= 2;
|
||||
r += 2;
|
||||
}
|
||||
if (!(x & 1)) {
|
||||
x >>= 1;
|
||||
r += 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* __ffs - find first bit in word.
|
||||
* @word: The word to search
|
||||
*
|
||||
* Undefined if no bit exists, so code should check against 0 first.
|
||||
*/
|
||||
static inline int sbi_ffs(unsigned long word)
|
||||
static inline int __ffs(unsigned long word)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
@ -75,201 +88,11 @@ static inline int sbi_ffs(unsigned long word)
|
||||
}
|
||||
|
||||
/*
|
||||
* sbi_ffz - find first zero in word.
|
||||
* ffz - find first zero in word.
|
||||
* @word: The word to search
|
||||
*
|
||||
* Undefined if no zero exists, so code should check against ~0UL first.
|
||||
*/
|
||||
#define sbi_ffz(x) sbi_ffs(~(x))
|
||||
|
||||
/**
|
||||
* sbi_fls - find last (most-significant) set bit in a long word
|
||||
* @word: the word to search
|
||||
*
|
||||
* Undefined if no set bit exists, so code should check against 0 first.
|
||||
*/
|
||||
static inline unsigned long sbi_fls(unsigned long word)
|
||||
{
|
||||
int num = BITS_PER_LONG - 1;
|
||||
|
||||
#if BITS_PER_LONG == 64
|
||||
if (!(word & (~0ul << 32))) {
|
||||
num -= 32;
|
||||
word <<= 32;
|
||||
}
|
||||
#endif
|
||||
if (!(word & (~0ul << (BITS_PER_LONG-16)))) {
|
||||
num -= 16;
|
||||
word <<= 16;
|
||||
}
|
||||
if (!(word & (~0ul << (BITS_PER_LONG-8)))) {
|
||||
num -= 8;
|
||||
word <<= 8;
|
||||
}
|
||||
if (!(word & (~0ul << (BITS_PER_LONG-4)))) {
|
||||
num -= 4;
|
||||
word <<= 4;
|
||||
}
|
||||
if (!(word & (~0ul << (BITS_PER_LONG-2)))) {
|
||||
num -= 2;
|
||||
word <<= 2;
|
||||
}
|
||||
if (!(word & (~0ul << (BITS_PER_LONG-1))))
|
||||
num -= 1;
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* sbi_popcount - find the number of set bit in a long word
|
||||
* @word: the word to search
|
||||
*/
|
||||
static inline unsigned long sbi_popcount(unsigned long word)
|
||||
{
|
||||
unsigned long count;
|
||||
|
||||
#if BITS_PER_LONG == 64
|
||||
count = word - ((word >> 1) & 0x5555555555555555ul);
|
||||
count = (count & 0x3333333333333333ul) + ((count >> 2) & 0x3333333333333333ul);
|
||||
count = (count + (count >> 4)) & 0x0F0F0F0F0F0F0F0Ful;
|
||||
count = count + (count >> 8);
|
||||
count = count + (count >> 16);
|
||||
return (count + (count >> 32)) & 0x00000000000000FFul;
|
||||
#else
|
||||
count = word - ((word >> 1) & 0x55555555);
|
||||
count = (count & 0x33333333) + ((count >> 2) & 0x33333333);
|
||||
count = (count + (count >> 4)) & 0x0F0F0F0F;
|
||||
count = count + (count >> 8);
|
||||
return (count + (count >> 16)) & 0x000000FF;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define for_each_set_bit(bit, addr, size) \
|
||||
for ((bit) = find_first_bit((addr), (size)); \
|
||||
(bit) < (size); \
|
||||
(bit) = find_next_bit((addr), (size), (bit) + 1))
|
||||
|
||||
/* same as for_each_set_bit() but use bit as value to start with */
|
||||
#define for_each_set_bit_from(bit, addr, size) \
|
||||
for ((bit) = find_next_bit((addr), (size), (bit)); \
|
||||
(bit) < (size); \
|
||||
(bit) = find_next_bit((addr), (size), (bit) + 1))
|
||||
|
||||
#define for_each_clear_bit(bit, addr, size) \
|
||||
for ((bit) = find_first_zero_bit((addr), (size)); \
|
||||
(bit) < (size); \
|
||||
(bit) = find_next_zero_bit((addr), (size), (bit) + 1))
|
||||
|
||||
/* same as for_each_clear_bit() but use bit as value to start with */
|
||||
#define for_each_clear_bit_from(bit, addr, size) \
|
||||
for ((bit) = find_next_zero_bit((addr), (size), (bit)); \
|
||||
(bit) < (size); \
|
||||
(bit) = find_next_zero_bit((addr), (size), (bit) + 1))
|
||||
|
||||
unsigned long find_first_bit(const unsigned long *addr,
|
||||
unsigned long size);
|
||||
|
||||
unsigned long find_first_zero_bit(const unsigned long *addr,
|
||||
unsigned long size);
|
||||
|
||||
unsigned long find_last_bit(const unsigned long *addr,
|
||||
unsigned long size);
|
||||
|
||||
unsigned long find_next_bit(const unsigned long *addr,
|
||||
unsigned long size, unsigned long offset);
|
||||
|
||||
unsigned long find_next_zero_bit(const unsigned long *addr,
|
||||
unsigned long size,
|
||||
unsigned long offset);
|
||||
|
||||
/**
|
||||
* __set_bit - Set a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
* This function is non-atomic and may be reordered.
|
||||
*/
|
||||
static inline void __set_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
|
||||
*p |= mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* __clear_bit - Clear a bit in memory
|
||||
* @nr: the bit to clear
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
* This function is non-atomic and may be reordered.
|
||||
*/
|
||||
static inline void __clear_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
|
||||
*p &= ~mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* __change_bit - Toggle a bit in memory
|
||||
* @nr: the bit to change
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
* This function is non-atomic and may be reordered.
|
||||
*/
|
||||
static inline void __change_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
|
||||
*p ^= mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* __test_and_set_bit - Set a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is non-atomic and can be reordered.
|
||||
*/
|
||||
static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
unsigned long old = *p;
|
||||
|
||||
*p = old | mask;
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* __test_and_clear_bit - Clear a bit and return its old value
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is non-atomic and can be reordered.
|
||||
*/
|
||||
static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
unsigned long old = *p;
|
||||
|
||||
*p = old & ~mask;
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* __test_bit - Determine whether a bit is set
|
||||
* @nr: bit number to test
|
||||
* @addr: Address to start counting from
|
||||
*
|
||||
* This operation is non-atomic and can be reordered.
|
||||
*/
|
||||
static inline int __test_bit(int nr, const volatile unsigned long *addr)
|
||||
{
|
||||
return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
|
||||
}
|
||||
#define ffz(x) __ffs(~(x))
|
||||
|
||||
#endif
|
||||
|
31
include/sbi/sbi_bits.h
Normal file
31
include/sbi/sbi_bits.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Anup Patel <anup.patel@wdc.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_BITS_H__
|
||||
#define __SBI_BITS_H__
|
||||
|
||||
#define likely(x) __builtin_expect((x), 1)
|
||||
#define unlikely(x) __builtin_expect((x), 0)
|
||||
|
||||
#define ROUNDUP(a, b) ((((a)-1)/(b)+1)*(b))
|
||||
#define ROUNDDOWN(a, b) ((a)/(b)*(b))
|
||||
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define CLAMP(a, lo, hi) MIN(MAX(a, lo), hi)
|
||||
|
||||
#define EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1)))
|
||||
#define INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1))))
|
||||
|
||||
#define STR(x) XSTR(x)
|
||||
#define XSTR(x) #x
|
||||
|
||||
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
||||
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||
#endif
|
@ -1,80 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2023 Ventana Micro Systems Inc.
|
||||
*/
|
||||
|
||||
#ifndef __SBI_BYTEORDER_H__
|
||||
#define __SBI_BYTEORDER_H__
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
# define _conv_cast(type, val) (val)
|
||||
#else
|
||||
# include <sbi/sbi_types.h>
|
||||
# define _conv_cast(type, val) ((type)(val))
|
||||
#endif
|
||||
|
||||
#define __BSWAP16(x) ((((x) & 0x00ff) << 8) | \
|
||||
(((x) & 0xff00) >> 8))
|
||||
#define __BSWAP32(x) ((((x) & 0x000000ff) << 24) | \
|
||||
(((x) & 0x0000ff00) << 8) | \
|
||||
(((x) & 0x00ff0000) >> 8) | \
|
||||
(((x) & 0xff000000) >> 24))
|
||||
#define __BSWAP64(x) ((((x) & 0x00000000000000ffULL) << 56) | \
|
||||
(((x) & 0x000000000000ff00ULL) << 40) | \
|
||||
(((x) & 0x0000000000ff0000ULL) << 24) | \
|
||||
(((x) & 0x00000000ff000000ULL) << 8) | \
|
||||
(((x) & 0x000000ff00000000ULL) >> 8) | \
|
||||
(((x) & 0x0000ff0000000000ULL) >> 24) | \
|
||||
(((x) & 0x00ff000000000000ULL) >> 40) | \
|
||||
(((x) & 0xff00000000000000ULL) >> 56))
|
||||
|
||||
#define BSWAP64(x) ({ uint64_t _sv = (x); __BSWAP64(_sv); })
|
||||
#define BSWAP32(x) ({ uint32_t _sv = (x); __BSWAP32(_sv); })
|
||||
#define BSWAP16(x) ({ uint16_t _sv = (x); __BSWAP16(_sv); })
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* CPU(little-endian) */
|
||||
#define cpu_to_be16(x) _conv_cast(uint16_t, BSWAP16(x))
|
||||
#define cpu_to_be32(x) _conv_cast(uint32_t, BSWAP32(x))
|
||||
#define cpu_to_be64(x) _conv_cast(uint64_t, BSWAP64(x))
|
||||
|
||||
#define be16_to_cpu(x) _conv_cast(uint16_t, BSWAP16(x))
|
||||
#define be32_to_cpu(x) _conv_cast(uint32_t, BSWAP32(x))
|
||||
#define be64_to_cpu(x) _conv_cast(uint64_t, BSWAP64(x))
|
||||
|
||||
#define cpu_to_le16(x) _conv_cast(uint16_t, (x))
|
||||
#define cpu_to_le32(x) _conv_cast(uint32_t, (x))
|
||||
#define cpu_to_le64(x) _conv_cast(uint64_t, (x))
|
||||
|
||||
#define le16_to_cpu(x) _conv_cast(uint16_t, (x))
|
||||
#define le32_to_cpu(x) _conv_cast(uint32_t, (x))
|
||||
#define le64_to_cpu(x) _conv_cast(uint64_t, (x))
|
||||
#else /* CPU(big-endian) */
|
||||
#define cpu_to_be16(x) _conv_cast(uint16_t, (x))
|
||||
#define cpu_to_be32(x) _conv_cast(uint32_t, (x))
|
||||
#define cpu_to_be64(x) _conv_cast(uint64_t, (x))
|
||||
|
||||
#define be16_to_cpu(x) _conv_cast(uint16_t, (x))
|
||||
#define be32_to_cpu(x) _conv_cast(uint32_t, (x))
|
||||
#define be64_to_cpu(x) _conv_cast(uint64_t, (x))
|
||||
|
||||
#define cpu_to_le16(x) _conv_cast(uint16_t, BSWAP16(x))
|
||||
#define cpu_to_le32(x) _conv_cast(uint32_t, BSWAP32(x))
|
||||
#define cpu_to_le64(x) _conv_cast(uint64_t, BSWAP64(x))
|
||||
|
||||
#define le16_to_cpu(x) _conv_cast(uint16_t, BSWAP16(x))
|
||||
#define le32_to_cpu(x) _conv_cast(uint32_t, BSWAP32(x))
|
||||
#define le64_to_cpu(x) _conv_cast(uint64_t, BSWAP64(x))
|
||||
#endif
|
||||
|
||||
#if __riscv_xlen == 64
|
||||
#define cpu_to_lle cpu_to_le64
|
||||
#define lle_to_cpu le64_to_cpu
|
||||
#elif __riscv_xlen == 32
|
||||
#define cpu_to_lle cpu_to_le32
|
||||
#define lle_to_cpu le32_to_cpu
|
||||
#else
|
||||
#error "Unknown __riscv_xlen"
|
||||
#endif
|
||||
|
||||
#endif /* __SBI_BYTEORDER_H__ */
|
@ -12,55 +12,26 @@
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
struct sbi_console_device {
|
||||
/** Name of the console device */
|
||||
char name[32];
|
||||
|
||||
/** Write a character to the console output */
|
||||
void (*console_putc)(char ch);
|
||||
|
||||
/** Write a character string to the console output */
|
||||
unsigned long (*console_puts)(const char *str, unsigned long len);
|
||||
|
||||
/** Read a character from the console input */
|
||||
int (*console_getc)(void);
|
||||
};
|
||||
|
||||
#define __printf(a, b) __attribute__((format(printf, a, b)))
|
||||
#define __printf(a, b) __attribute__((format(printf, a, b)))
|
||||
|
||||
bool sbi_isprintable(char ch);
|
||||
|
||||
int sbi_getc(void);
|
||||
char sbi_getc(void);
|
||||
|
||||
void sbi_putc(char ch);
|
||||
|
||||
void sbi_puts(const char *str);
|
||||
|
||||
unsigned long sbi_nputs(const char *str, unsigned long len);
|
||||
|
||||
void sbi_gets(char *s, int maxwidth, char endchar);
|
||||
|
||||
unsigned long sbi_ngets(char *str, unsigned long len);
|
||||
|
||||
int __printf(2, 3) sbi_sprintf(char *out, const char *format, ...);
|
||||
|
||||
int __printf(3, 4) sbi_snprintf(char *out, u32 out_sz, const char *format, ...);
|
||||
int __printf(3, 4) sbi_snprintf(char *out, u32 out_sz,
|
||||
const char *format, ...);
|
||||
|
||||
int __printf(1, 2) sbi_printf(const char *format, ...);
|
||||
|
||||
int __printf(1, 2) sbi_dprintf(const char *format, ...);
|
||||
|
||||
void __printf(1, 2) __attribute__((noreturn)) sbi_panic(const char *format, ...);
|
||||
|
||||
const struct sbi_console_device *sbi_console_get_device(void);
|
||||
|
||||
void sbi_console_set_device(const struct sbi_console_device *dev);
|
||||
|
||||
struct sbi_scratch;
|
||||
|
||||
#define SBI_ASSERT(cond, args) do { \
|
||||
if (unlikely(!(cond))) \
|
||||
sbi_panic args; \
|
||||
} while (0)
|
||||
int sbi_console_init(struct sbi_scratch *scratch);
|
||||
|
||||
#endif
|
||||
|
@ -10,8 +10,7 @@
|
||||
#ifndef __SBI_CONST_H__
|
||||
#define __SBI_CONST_H__
|
||||
|
||||
/*
|
||||
* Some constant macros are used in both assembler and
|
||||
/* Some constant macros are used in both assembler and
|
||||
* C code. Therefore we cannot annotate them always with
|
||||
* 'UL' and other type specifiers unilaterally. We
|
||||
* use the following macros to deal with this.
|
||||
@ -20,9 +19,7 @@
|
||||
* leave it unchanged in asm.
|
||||
*/
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
#ifdef __ASSEMBLY__
|
||||
#define _AC(X,Y) X
|
||||
#define _AT(T,X) X
|
||||
#else
|
||||
@ -40,9 +37,7 @@
|
||||
#define UL(x) (_UL(x))
|
||||
#define ULL(x) (_ULL(x))
|
||||
|
||||
#define __STR(s) #s
|
||||
#define STRINGIFY(s) __STR(s)
|
||||
|
||||
/* clang-format on */
|
||||
#define __STR(s) #s
|
||||
#define STRINGIFY(s) __STR(s)
|
||||
|
||||
#endif
|
||||
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2023 Ventana Micro Systems Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SBI_CPPC_H__
|
||||
#define __SBI_CPPC_H__
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
/** CPPC device */
|
||||
struct sbi_cppc_device {
|
||||
/** Name of the CPPC device */
|
||||
char name[32];
|
||||
|
||||
/** probe - returns register width if implemented, 0 otherwise */
|
||||
int (*cppc_probe)(unsigned long reg);
|
||||
|
||||
/** read the cppc register*/
|
||||
int (*cppc_read)(unsigned long reg, uint64_t *val);
|
||||
|
||||
/** write to the cppc register*/
|
||||
int (*cppc_write)(unsigned long reg, uint64_t val);
|
||||
};
|
||||
|
||||
int sbi_cppc_probe(unsigned long reg);
|
||||
int sbi_cppc_read(unsigned long reg, uint64_t *val);
|
||||
int sbi_cppc_write(unsigned long reg, uint64_t val);
|
||||
|
||||
const struct sbi_cppc_device *sbi_cppc_get_device(void);
|
||||
void sbi_cppc_set_device(const struct sbi_cppc_device *dev);
|
||||
|
||||
#endif
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Atish Patra <atish.patra@wdc.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_CSR_DETECT__H
|
||||
#define __SBI_CSR_DETECT__H
|
||||
|
||||
#include <sbi/riscv_encoding.h>
|
||||
#include <sbi/sbi_hart.h>
|
||||
#include <sbi/sbi_trap.h>
|
||||
|
||||
#define csr_read_allowed(csr_num, trap) \
|
||||
({ \
|
||||
register ulong tinfo asm("a3") = (ulong)trap; \
|
||||
register ulong ttmp asm("a4"); \
|
||||
register ulong mtvec = (ulong)sbi_hart_expected_trap; \
|
||||
register ulong ret = 0; \
|
||||
((struct sbi_trap_info *)(trap))->cause = 0; \
|
||||
asm volatile( \
|
||||
"add %[ttmp], %[tinfo], zero\n" \
|
||||
"csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n" \
|
||||
"csrr %[ret], %[csr]\n" \
|
||||
"csrw " STR(CSR_MTVEC) ", %[mtvec]" \
|
||||
: [mtvec] "+&r"(mtvec), [tinfo] "+&r"(tinfo), \
|
||||
[ttmp] "+&r"(ttmp), [ret] "=&r" (ret) \
|
||||
: [csr] "i" (csr_num) \
|
||||
: "memory"); \
|
||||
ret; \
|
||||
}) \
|
||||
|
||||
#define csr_write_allowed(csr_num, trap, value) \
|
||||
({ \
|
||||
register ulong tinfo asm("a3") = (ulong)trap; \
|
||||
register ulong ttmp asm("a4"); \
|
||||
register ulong mtvec = (ulong)sbi_hart_expected_trap; \
|
||||
((struct sbi_trap_info *)(trap))->cause = 0; \
|
||||
asm volatile( \
|
||||
"add %[ttmp], %[tinfo], zero\n" \
|
||||
"csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n" \
|
||||
"csrw %[csr], %[val]\n" \
|
||||
"csrw " STR(CSR_MTVEC) ", %[mtvec]" \
|
||||
: [mtvec] "+&r"(mtvec), \
|
||||
[tinfo] "+&r"(tinfo), [ttmp] "+&r"(ttmp) \
|
||||
: [csr] "i" (csr_num), [val] "r" (value) \
|
||||
: "memory"); \
|
||||
}) \
|
||||
|
||||
#endif
|
@ -1,124 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2023 Ventana Micro Systems, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Himanshu Chauhan <hchauhan@ventanamicro.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_DBTR_H__
|
||||
#define __SBI_DBTR_H__
|
||||
|
||||
#include <sbi/riscv_dbtr.h>
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
struct sbi_domain;
|
||||
|
||||
enum {
|
||||
RV_DBTR_DECLARE_BIT(TS, MAPPED, 0), /* trigger mapped to hw trigger */
|
||||
RV_DBTR_DECLARE_BIT(TS, U, 1),
|
||||
RV_DBTR_DECLARE_BIT(TS, S, 2),
|
||||
RV_DBTR_DECLARE_BIT(TS, VU, 3),
|
||||
RV_DBTR_DECLARE_BIT(TS, VS, 4),
|
||||
RV_DBTR_DECLARE_BIT(TS, HAVE_TRIG, 5), /* H/w dbtr details available */
|
||||
RV_DBTR_DECLARE_BIT(TS, HW_IDX, 8), /* Hardware index of trigger */
|
||||
};
|
||||
|
||||
enum {
|
||||
RV_DBTR_DECLARE_BIT_MASK(TS, MAPPED, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(TS, U, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(TS, S, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(TS, VU, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(TS, VS, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(TS, HAVE_TRIG, 1),
|
||||
RV_DBTR_DECLARE_BIT_MASK(TS, HW_IDX, (__riscv_xlen-9)),
|
||||
};
|
||||
|
||||
#if __riscv_xlen == 64
|
||||
#define SBI_DBTR_SHMEM_INVALID_ADDR 0xFFFFFFFFFFFFFFFFUL
|
||||
#elif __riscv_xlen == 32
|
||||
#define SBI_DBTR_SHMEM_INVALID_ADDR 0xFFFFFFFFUL
|
||||
#else
|
||||
#error "Unexpected __riscv_xlen"
|
||||
#endif
|
||||
|
||||
struct sbi_dbtr_shmem {
|
||||
unsigned long phys_lo;
|
||||
unsigned long phys_hi;
|
||||
};
|
||||
|
||||
struct sbi_dbtr_trigger {
|
||||
unsigned long index;
|
||||
unsigned long type_mask;
|
||||
unsigned long state;
|
||||
unsigned long tdata1;
|
||||
unsigned long tdata2;
|
||||
unsigned long tdata3;
|
||||
};
|
||||
|
||||
struct sbi_dbtr_data_msg {
|
||||
unsigned long tstate;
|
||||
unsigned long tdata1;
|
||||
unsigned long tdata2;
|
||||
unsigned long tdata3;
|
||||
};
|
||||
|
||||
struct sbi_dbtr_id_msg {
|
||||
unsigned long idx;
|
||||
};
|
||||
|
||||
struct sbi_dbtr_hart_triggers_state {
|
||||
struct sbi_dbtr_trigger triggers[RV_MAX_TRIGGERS];
|
||||
struct sbi_dbtr_shmem shmem;
|
||||
u32 total_trigs;
|
||||
u32 available_trigs;
|
||||
u32 hartid;
|
||||
u32 probed;
|
||||
};
|
||||
|
||||
#define TDATA1_GET_TYPE(_t1) \
|
||||
EXTRACT_FIELD(_t1, RV_DBTR_BIT_MASK(TDATA1, TYPE))
|
||||
|
||||
/* Set the hardware index of trigger in logical trigger state */
|
||||
#define SET_TRIG_HW_INDEX(_state, _idx) \
|
||||
do { \
|
||||
_state &= ~RV_DBTR_BIT_MASK(TS, HW_IDX); \
|
||||
_state |= (((unsigned long)_idx \
|
||||
<< RV_DBTR_BIT(TS, HW_IDX)) \
|
||||
& RV_DBTR_BIT_MASK(TS, HW_IDX)); \
|
||||
}while (0);
|
||||
|
||||
/** SBI shared mem messages layout */
|
||||
union sbi_dbtr_shmem_entry {
|
||||
struct sbi_dbtr_data_msg data;
|
||||
struct sbi_dbtr_id_msg id;
|
||||
};
|
||||
|
||||
#define SBI_DBTR_SHMEM_ALIGN_MASK ((__riscv_xlen / 8) - 1)
|
||||
|
||||
/** Initialize debug triggers */
|
||||
int sbi_dbtr_init(struct sbi_scratch *scratch, bool coldboot);
|
||||
|
||||
/** SBI DBTR extension functions */
|
||||
int sbi_dbtr_supported(void);
|
||||
int sbi_dbtr_setup_shmem(const struct sbi_domain *dom, unsigned long smode,
|
||||
unsigned long shmem_phys_lo,
|
||||
unsigned long shmem_phys_hi);
|
||||
int sbi_dbtr_num_trig(unsigned long trig_tdata1, unsigned long *out);
|
||||
int sbi_dbtr_read_trig(unsigned long smode,
|
||||
unsigned long trig_idx_base, unsigned long trig_count);
|
||||
int sbi_dbtr_install_trig(unsigned long smode,
|
||||
unsigned long trig_count, unsigned long *out);
|
||||
int sbi_dbtr_uninstall_trig(unsigned long trig_idx_base,
|
||||
unsigned long trig_idx_mask);
|
||||
int sbi_dbtr_enable_trig(unsigned long trig_idx_base,
|
||||
unsigned long trig_idx_mask);
|
||||
int sbi_dbtr_update_trig(unsigned long smode,
|
||||
unsigned long trig_count);
|
||||
int sbi_dbtr_disable_trig(unsigned long trig_idx_base,
|
||||
unsigned long trig_idx_mask);
|
||||
|
||||
int sbi_dbtr_get_total_triggers(void);
|
||||
|
||||
#endif
|
@ -1,319 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Anup Patel <anup.patel@wdc.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_DOMAIN_H__
|
||||
#define __SBI_DOMAIN_H__
|
||||
|
||||
#include <sbi/riscv_locks.h>
|
||||
#include <sbi/sbi_list.h>
|
||||
#include <sbi/sbi_types.h>
|
||||
#include <sbi/sbi_hartmask.h>
|
||||
#include <sbi/sbi_domain_context.h>
|
||||
#include <sbi/sbi_domain_data.h>
|
||||
|
||||
struct sbi_scratch;
|
||||
|
||||
/** Domain access types */
|
||||
enum sbi_domain_access {
|
||||
SBI_DOMAIN_READ = (1UL << 0),
|
||||
SBI_DOMAIN_WRITE = (1UL << 1),
|
||||
SBI_DOMAIN_EXECUTE = (1UL << 2),
|
||||
SBI_DOMAIN_MMIO = (1UL << 3)
|
||||
};
|
||||
|
||||
/** Representation of OpenSBI domain memory region */
|
||||
struct sbi_domain_memregion {
|
||||
/**
|
||||
* Size of memory region as power of 2
|
||||
* It has to be minimum 3 and maximum __riscv_xlen
|
||||
*/
|
||||
unsigned long order;
|
||||
/**
|
||||
* Base address of memory region
|
||||
* It must be 2^order aligned address
|
||||
*/
|
||||
unsigned long base;
|
||||
/** Flags representing memory region attributes */
|
||||
#define SBI_DOMAIN_MEMREGION_M_READABLE (1UL << 0)
|
||||
#define SBI_DOMAIN_MEMREGION_M_WRITABLE (1UL << 1)
|
||||
#define SBI_DOMAIN_MEMREGION_M_EXECUTABLE (1UL << 2)
|
||||
#define SBI_DOMAIN_MEMREGION_SU_READABLE (1UL << 3)
|
||||
#define SBI_DOMAIN_MEMREGION_SU_WRITABLE (1UL << 4)
|
||||
#define SBI_DOMAIN_MEMREGION_SU_EXECUTABLE (1UL << 5)
|
||||
|
||||
#define SBI_DOMAIN_MEMREGION_ACCESS_MASK (0x3fUL)
|
||||
#define SBI_DOMAIN_MEMREGION_M_ACCESS_MASK (0x7UL)
|
||||
#define SBI_DOMAIN_MEMREGION_SU_ACCESS_MASK (0x38UL)
|
||||
|
||||
#define SBI_DOMAIN_MEMREGION_SU_ACCESS_SHIFT (3)
|
||||
|
||||
#define SBI_DOMAIN_MEMREGION_SHARED_RDONLY \
|
||||
(SBI_DOMAIN_MEMREGION_M_READABLE | \
|
||||
SBI_DOMAIN_MEMREGION_SU_READABLE)
|
||||
|
||||
#define SBI_DOMAIN_MEMREGION_SHARED_SUX_MRX \
|
||||
(SBI_DOMAIN_MEMREGION_M_READABLE | \
|
||||
SBI_DOMAIN_MEMREGION_M_EXECUTABLE | \
|
||||
SBI_DOMAIN_MEMREGION_SU_EXECUTABLE)
|
||||
|
||||
#define SBI_DOMAIN_MEMREGION_SHARED_SUX_MX \
|
||||
(SBI_DOMAIN_MEMREGION_M_EXECUTABLE | \
|
||||
SBI_DOMAIN_MEMREGION_SU_EXECUTABLE)
|
||||
|
||||
#define SBI_DOMAIN_MEMREGION_SHARED_SURW_MRW \
|
||||
(SBI_DOMAIN_MEMREGION_M_READABLE | \
|
||||
SBI_DOMAIN_MEMREGION_M_WRITABLE | \
|
||||
SBI_DOMAIN_MEMREGION_SU_READABLE| \
|
||||
SBI_DOMAIN_MEMREGION_SU_WRITABLE)
|
||||
|
||||
#define SBI_DOMAIN_MEMREGION_SHARED_SUR_MRW \
|
||||
(SBI_DOMAIN_MEMREGION_M_READABLE | \
|
||||
SBI_DOMAIN_MEMREGION_M_WRITABLE | \
|
||||
SBI_DOMAIN_MEMREGION_SU_READABLE)
|
||||
|
||||
/* Shared read-only region between M and SU mode */
|
||||
#define SBI_DOMAIN_MEMREGION_IS_SUR_MR(__flags) \
|
||||
((__flags & SBI_DOMAIN_MEMREGION_ACCESS_MASK) == \
|
||||
SBI_DOMAIN_MEMREGION_SHARED_RDONLY)
|
||||
|
||||
/* Shared region: SU execute-only and M read/execute */
|
||||
#define SBI_DOMAIN_MEMREGION_IS_SUX_MRX(__flags) \
|
||||
((__flags & SBI_DOMAIN_MEMREGION_ACCESS_MASK) == \
|
||||
SBI_DOMAIN_MEMREGION_SHARED_SUX_MRX)
|
||||
|
||||
/* Shared region: SU and M execute-only */
|
||||
#define SBI_DOMAIN_MEMREGION_IS_SUX_MX(__flags) \
|
||||
((__flags & SBI_DOMAIN_MEMREGION_ACCESS_MASK) == \
|
||||
SBI_DOMAIN_MEMREGION_SHARED_SUX_MX)
|
||||
|
||||
/* Shared region: SU and M read/write */
|
||||
#define SBI_DOMAIN_MEMREGION_IS_SURW_MRW(__flags) \
|
||||
((__flags & SBI_DOMAIN_MEMREGION_ACCESS_MASK) == \
|
||||
SBI_DOMAIN_MEMREGION_SHARED_SURW_MRW)
|
||||
|
||||
/* Shared region: SU read-only and M read/write */
|
||||
#define SBI_DOMAIN_MEMREGION_IS_SUR_MRW(__flags) \
|
||||
((__flags & SBI_DOMAIN_MEMREGION_ACCESS_MASK) == \
|
||||
SBI_DOMAIN_MEMREGION_SHARED_SUR_MRW)
|
||||
|
||||
/*
|
||||
* Check if region flags match with any of the above
|
||||
* mentioned shared region type
|
||||
*/
|
||||
#define SBI_DOMAIN_MEMREGION_IS_SHARED(_flags) \
|
||||
(SBI_DOMAIN_MEMREGION_IS_SUR_MR(_flags) || \
|
||||
SBI_DOMAIN_MEMREGION_IS_SUX_MRX(_flags) || \
|
||||
SBI_DOMAIN_MEMREGION_IS_SUX_MX(_flags) || \
|
||||
SBI_DOMAIN_MEMREGION_IS_SURW_MRW(_flags)|| \
|
||||
SBI_DOMAIN_MEMREGION_IS_SUR_MRW(_flags))
|
||||
|
||||
#define SBI_DOMAIN_MEMREGION_M_ONLY_ACCESS(__flags) \
|
||||
((__flags & SBI_DOMAIN_MEMREGION_M_ACCESS_MASK) && \
|
||||
!(__flags & SBI_DOMAIN_MEMREGION_SU_ACCESS_MASK))
|
||||
|
||||
#define SBI_DOMAIN_MEMREGION_SU_ONLY_ACCESS(__flags) \
|
||||
((__flags & SBI_DOMAIN_MEMREGION_SU_ACCESS_MASK) && \
|
||||
!(__flags & SBI_DOMAIN_MEMREGION_M_ACCESS_MASK))
|
||||
|
||||
/** Bit to control if permissions are enforced on all modes */
|
||||
#define SBI_DOMAIN_MEMREGION_ENF_PERMISSIONS (1UL << 6)
|
||||
|
||||
#define SBI_DOMAIN_MEMREGION_M_RWX \
|
||||
(SBI_DOMAIN_MEMREGION_M_READABLE | \
|
||||
SBI_DOMAIN_MEMREGION_M_WRITABLE | \
|
||||
SBI_DOMAIN_MEMREGION_M_EXECUTABLE)
|
||||
|
||||
#define SBI_DOMAIN_MEMREGION_SU_RWX \
|
||||
(SBI_DOMAIN_MEMREGION_SU_READABLE | \
|
||||
SBI_DOMAIN_MEMREGION_SU_WRITABLE | \
|
||||
SBI_DOMAIN_MEMREGION_SU_EXECUTABLE)
|
||||
|
||||
/* Unrestricted M-mode accesses but enfoced on SU-mode */
|
||||
#define SBI_DOMAIN_MEMREGION_READABLE \
|
||||
(SBI_DOMAIN_MEMREGION_SU_READABLE | \
|
||||
SBI_DOMAIN_MEMREGION_M_RWX)
|
||||
#define SBI_DOMAIN_MEMREGION_WRITEABLE \
|
||||
(SBI_DOMAIN_MEMREGION_SU_WRITABLE | \
|
||||
SBI_DOMAIN_MEMREGION_M_RWX)
|
||||
#define SBI_DOMAIN_MEMREGION_EXECUTABLE \
|
||||
(SBI_DOMAIN_MEMREGION_SU_EXECUTABLE | \
|
||||
SBI_DOMAIN_MEMREGION_M_RWX)
|
||||
|
||||
/* Enforced accesses across all modes */
|
||||
#define SBI_DOMAIN_MEMREGION_ENF_READABLE \
|
||||
(SBI_DOMAIN_MEMREGION_SU_READABLE | \
|
||||
SBI_DOMAIN_MEMREGION_M_READABLE)
|
||||
#define SBI_DOMAIN_MEMREGION_ENF_WRITABLE \
|
||||
(SBI_DOMAIN_MEMREGION_SU_WRITABLE | \
|
||||
SBI_DOMAIN_MEMREGION_M_WRITABLE)
|
||||
#define SBI_DOMAIN_MEMREGION_ENF_EXECUTABLE \
|
||||
(SBI_DOMAIN_MEMREGION_SU_EXECUTABLE | \
|
||||
SBI_DOMAIN_MEMREGION_M_EXECUTABLE)
|
||||
|
||||
#define SBI_DOMAIN_MEMREGION_MMIO (1UL << 31)
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
/** Representation of OpenSBI domain */
|
||||
struct sbi_domain {
|
||||
/** Node in linked list of domains */
|
||||
struct sbi_dlist node;
|
||||
/** Internal state of per-domain data */
|
||||
struct sbi_domain_data_priv data_priv;
|
||||
/** Logical index of this domain */
|
||||
u32 index;
|
||||
/** HARTs assigned to this domain */
|
||||
struct sbi_hartmask assigned_harts;
|
||||
/** Spinlock for accessing assigned_harts */
|
||||
spinlock_t assigned_harts_lock;
|
||||
/** Name of this domain */
|
||||
char name[64];
|
||||
/** Possible HARTs in this domain */
|
||||
const struct sbi_hartmask *possible_harts;
|
||||
/** Array of memory regions terminated by a region with order zero */
|
||||
struct sbi_domain_memregion *regions;
|
||||
/** HART id of the HART booting this domain */
|
||||
u32 boot_hartid;
|
||||
/** Arg1 (or 'a1' register) of next booting stage for this domain */
|
||||
unsigned long next_arg1;
|
||||
/** Address of next booting stage for this domain */
|
||||
unsigned long next_addr;
|
||||
/** Privilege mode of next booting stage for this domain */
|
||||
unsigned long next_mode;
|
||||
/** Is domain allowed to reset the system */
|
||||
bool system_reset_allowed;
|
||||
/** Is domain allowed to suspend the system */
|
||||
bool system_suspend_allowed;
|
||||
/** Identifies whether to include the firmware region */
|
||||
bool fw_region_inited;
|
||||
};
|
||||
|
||||
/** The root domain instance */
|
||||
extern struct sbi_domain root;
|
||||
|
||||
/** Get pointer to sbi_domain from HART index */
|
||||
struct sbi_domain *sbi_hartindex_to_domain(u32 hartindex);
|
||||
|
||||
/** Update HART local pointer to point to specified domain */
|
||||
void sbi_update_hartindex_to_domain(u32 hartindex, struct sbi_domain *dom);
|
||||
|
||||
/** Get pointer to sbi_domain for current HART */
|
||||
#define sbi_domain_thishart_ptr() \
|
||||
sbi_hartindex_to_domain(current_hartindex())
|
||||
|
||||
/** Head of linked list of domains */
|
||||
extern struct sbi_dlist domain_list;
|
||||
|
||||
/** Iterate over each domain */
|
||||
#define sbi_domain_for_each(__d) \
|
||||
sbi_list_for_each_entry(__d, &domain_list, node)
|
||||
|
||||
/** Iterate over each memory region of a domain */
|
||||
#define sbi_domain_for_each_memregion(__d, __r) \
|
||||
for ((__r) = (__d)->regions; (__r)->order; (__r)++)
|
||||
|
||||
/**
|
||||
* Check whether given HART is assigned to specified domain
|
||||
* @param dom pointer to domain
|
||||
* @param hartindex the HART index
|
||||
* @return true if HART is assigned to domain otherwise false
|
||||
*/
|
||||
bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartindex);
|
||||
|
||||
/**
|
||||
* Get the assigned HART mask for given domain
|
||||
* @param dom pointer to domain
|
||||
* @param mask the output hartmask to fill
|
||||
* @return 0 on success and SBI_Exxx (< 0) on failure
|
||||
*/
|
||||
int sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom,
|
||||
struct sbi_hartmask *mask);
|
||||
|
||||
/**
|
||||
* Initialize a domain memory region based on it's physical
|
||||
* address and size.
|
||||
*
|
||||
* @param addr start physical address of memory region
|
||||
* @param size physical size of memory region
|
||||
* @param flags memory region flags
|
||||
* @param reg pointer to memory region being initialized
|
||||
*/
|
||||
void sbi_domain_memregion_init(unsigned long addr,
|
||||
unsigned long size,
|
||||
unsigned long flags,
|
||||
struct sbi_domain_memregion *reg);
|
||||
|
||||
/**
|
||||
* Check whether we can access specified address for given mode and
|
||||
* memory region flags under a domain
|
||||
* @param dom pointer to domain
|
||||
* @param addr the address to be checked
|
||||
* @param mode the privilege mode of access
|
||||
* @param access_flags bitmask of domain access types (enum sbi_domain_access)
|
||||
* @return true if access allowed otherwise false
|
||||
*/
|
||||
bool sbi_domain_check_addr(const struct sbi_domain *dom,
|
||||
unsigned long addr, unsigned long mode,
|
||||
unsigned long access_flags);
|
||||
|
||||
/**
|
||||
* Check whether we can access specified address range for given mode and
|
||||
* memory region flags under a domain
|
||||
* @param dom pointer to domain
|
||||
* @param addr the start of the address range to be checked
|
||||
* @param size the size of the address range to be checked
|
||||
* @param mode the privilege mode of access
|
||||
* @param access_flags bitmask of domain access types (enum sbi_domain_access)
|
||||
* @return TRUE if access allowed otherwise FALSE
|
||||
*/
|
||||
bool sbi_domain_check_addr_range(const struct sbi_domain *dom,
|
||||
unsigned long addr, unsigned long size,
|
||||
unsigned long mode,
|
||||
unsigned long access_flags);
|
||||
|
||||
/** Dump domain details on the console */
|
||||
void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix);
|
||||
|
||||
/** Dump all domain details on the console */
|
||||
void sbi_domain_dump_all(const char *suffix);
|
||||
|
||||
/**
|
||||
* Register a new domain
|
||||
* @param dom pointer to domain
|
||||
* @param assign_mask pointer to HART mask of HARTs assigned to the domain
|
||||
*
|
||||
* @return 0 on success and negative error code on failure
|
||||
*/
|
||||
int sbi_domain_register(struct sbi_domain *dom,
|
||||
const struct sbi_hartmask *assign_mask);
|
||||
|
||||
/**
|
||||
* Add a memory range with its flags to the root domain
|
||||
* @param addr start physical address of memory range
|
||||
* @param size physical size of memory range
|
||||
* @param align alignment of memory region
|
||||
* @param region_flags memory range flags
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return SBI_EALREADY if memory region conflicts with the existing one
|
||||
* @return SBI_EINVAL otherwise
|
||||
*/
|
||||
int sbi_domain_root_add_memrange(unsigned long addr, unsigned long size,
|
||||
unsigned long align, unsigned long region_flags);
|
||||
|
||||
/** Startup non-root domains */
|
||||
int sbi_domain_startup(struct sbi_scratch *scratch, u32 cold_hartid);
|
||||
|
||||
/** Finalize domain tables */
|
||||
int sbi_domain_finalize(struct sbi_scratch *scratch);
|
||||
|
||||
/** Initialize domains */
|
||||
int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid);
|
||||
|
||||
#endif
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) IPADS@SJTU 2023. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __SBI_DOMAIN_CONTEXT_H__
|
||||
#define __SBI_DOMAIN_CONTEXT_H__
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
struct sbi_domain;
|
||||
|
||||
/**
|
||||
* Enter a specific domain context synchronously
|
||||
* @param dom pointer to domain
|
||||
*
|
||||
* @return 0 on success and negative error code on failure
|
||||
*/
|
||||
int sbi_domain_context_enter(struct sbi_domain *dom);
|
||||
|
||||
/**
|
||||
* Exit the current domain context, and then return to the caller
|
||||
* of sbi_domain_context_enter or attempt to start the next domain
|
||||
* context to be initialized
|
||||
*
|
||||
* @return 0 on success and negative error code on failure
|
||||
*/
|
||||
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__
|
@ -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
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 Rivos Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Clément Léger <cleger@rivosinc.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_DOUBLE_TRAP_H__
|
||||
#define __SBI_DOUBLE_TRAP_H__
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
#include <sbi/sbi_trap.h>
|
||||
|
||||
int sbi_double_trap_handler(struct sbi_trap_context *tcntx);
|
||||
|
||||
void sbi_double_trap_init(struct sbi_scratch *scratch);
|
||||
|
||||
#endif
|
@ -11,90 +11,16 @@
|
||||
#define __SBI_ECALL_H__
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
#include <sbi/sbi_list.h>
|
||||
|
||||
#define SBI_ECALL_VERSION_MAJOR 3
|
||||
#define SBI_ECALL_VERSION_MINOR 0
|
||||
#define SBI_OPENSBI_IMPID 1
|
||||
|
||||
struct sbi_trap_regs;
|
||||
struct sbi_trap_context;
|
||||
|
||||
struct sbi_ecall_return {
|
||||
/* Return flag to skip register update */
|
||||
bool skip_regs_update;
|
||||
/* Return value */
|
||||
unsigned long value;
|
||||
};
|
||||
|
||||
struct sbi_ecall_extension {
|
||||
/* head is used by the extension list */
|
||||
struct sbi_dlist head;
|
||||
/* short name of the extension */
|
||||
char name[8];
|
||||
/*
|
||||
* extid_start and extid_end specify the range for this extension. As
|
||||
* the initial range may be wider than the valid runtime range, the
|
||||
* register_extensions callback is responsible for narrowing the range
|
||||
* before other callbacks may be invoked.
|
||||
*/
|
||||
unsigned long extid_start;
|
||||
unsigned long extid_end;
|
||||
/* flag showing whether given extension is experimental or not */
|
||||
bool experimental;
|
||||
/*
|
||||
* register_extensions
|
||||
*
|
||||
* Calls sbi_ecall_register_extension() one or more times to register
|
||||
* extension ID range(s) which should be handled by this extension.
|
||||
* More than one sbi_ecall_extension struct and
|
||||
* sbi_ecall_register_extension() call is necessary when the supported
|
||||
* extension ID ranges have gaps. Additionally, extension availability
|
||||
* must be checked before registering, which means, when this callback
|
||||
* returns, only valid extension IDs from the initial range, which are
|
||||
* also available, have been registered.
|
||||
*/
|
||||
int (* register_extensions)(void);
|
||||
/*
|
||||
* probe
|
||||
*
|
||||
* Implements the Base extension's probe function for the extension. As
|
||||
* the register_extensions callback ensures that no other extension
|
||||
* callbacks will be invoked when the extension is not available, then
|
||||
* probe can never fail. However, an extension may choose to set
|
||||
* out_val to a nonzero value other than one. In those cases, it should
|
||||
* implement this callback.
|
||||
*/
|
||||
int (* probe)(unsigned long extid, unsigned long *out_val);
|
||||
/*
|
||||
* handle
|
||||
*
|
||||
* This is the extension handler. register_extensions ensures it is
|
||||
* never invoked with an invalid or unavailable extension ID.
|
||||
*/
|
||||
int (* handle)(unsigned long extid, unsigned long funcid,
|
||||
struct sbi_trap_regs *regs,
|
||||
struct sbi_ecall_return *out);
|
||||
};
|
||||
struct sbi_scratch;
|
||||
|
||||
u16 sbi_ecall_version_major(void);
|
||||
|
||||
u16 sbi_ecall_version_minor(void);
|
||||
|
||||
unsigned long sbi_ecall_get_impid(void);
|
||||
|
||||
void sbi_ecall_set_impid(unsigned long impid);
|
||||
|
||||
struct sbi_ecall_extension *sbi_ecall_find_extension(unsigned long extid);
|
||||
|
||||
void sbi_ecall_get_extensions_str(char *exts_str, int exts_str_size, bool experimental);
|
||||
|
||||
int sbi_ecall_register_extension(struct sbi_ecall_extension *ext);
|
||||
|
||||
void sbi_ecall_unregister_extension(struct sbi_ecall_extension *ext);
|
||||
|
||||
int sbi_ecall_handler(struct sbi_trap_context *tcntx);
|
||||
|
||||
int sbi_ecall_init(void);
|
||||
int sbi_ecall_handler(u32 hartid, ulong mcause,
|
||||
struct sbi_trap_regs *regs,
|
||||
struct sbi_scratch *scratch);
|
||||
|
||||
#endif
|
||||
|
@ -10,486 +10,39 @@
|
||||
#ifndef __SBI_ECALL_INTERFACE_H__
|
||||
#define __SBI_ECALL_INTERFACE_H__
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
/* SBI Extension IDs */
|
||||
#define SBI_EXT_0_1_SET_TIMER 0x0
|
||||
#define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1
|
||||
#define SBI_EXT_0_1_CONSOLE_GETCHAR 0x2
|
||||
#define SBI_EXT_0_1_CLEAR_IPI 0x3
|
||||
#define SBI_EXT_0_1_SEND_IPI 0x4
|
||||
#define SBI_EXT_0_1_REMOTE_FENCE_I 0x5
|
||||
#define SBI_EXT_0_1_REMOTE_SFENCE_VMA 0x6
|
||||
#define SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID 0x7
|
||||
#define SBI_EXT_0_1_SHUTDOWN 0x8
|
||||
#define SBI_EXT_BASE 0x10
|
||||
#define SBI_EXT_TIME 0x54494D45
|
||||
#define SBI_EXT_IPI 0x735049
|
||||
#define SBI_EXT_RFENCE 0x52464E43
|
||||
#define SBI_EXT_HSM 0x48534D
|
||||
#define SBI_EXT_SRST 0x53525354
|
||||
#define SBI_EXT_PMU 0x504D55
|
||||
#define SBI_EXT_DBCN 0x4442434E
|
||||
#define SBI_EXT_SUSP 0x53555350
|
||||
#define SBI_EXT_CPPC 0x43505043
|
||||
#define SBI_EXT_DBTR 0x44425452
|
||||
#define SBI_EXT_SSE 0x535345
|
||||
#define SBI_EXT_FWFT 0x46574654
|
||||
#define SBI_EXT_MPXY 0x4D505859
|
||||
|
||||
/* SBI function IDs for BASE extension*/
|
||||
#define SBI_EXT_BASE_GET_SPEC_VERSION 0x0
|
||||
#define SBI_EXT_BASE_GET_IMP_ID 0x1
|
||||
#define SBI_EXT_BASE_GET_IMP_VERSION 0x2
|
||||
#define SBI_EXT_BASE_PROBE_EXT 0x3
|
||||
#define SBI_EXT_BASE_GET_MVENDORID 0x4
|
||||
#define SBI_EXT_BASE_GET_MARCHID 0x5
|
||||
#define SBI_EXT_BASE_GET_MIMPID 0x6
|
||||
|
||||
/* SBI function IDs for TIME extension*/
|
||||
#define SBI_EXT_TIME_SET_TIMER 0x0
|
||||
|
||||
/* SBI function IDs for IPI extension*/
|
||||
#define SBI_EXT_IPI_SEND_IPI 0x0
|
||||
|
||||
/* SBI function IDs for RFENCE extension*/
|
||||
#define SBI_EXT_RFENCE_REMOTE_FENCE_I 0x0
|
||||
#define SBI_EXT_RFENCE_REMOTE_SFENCE_VMA 0x1
|
||||
#define SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID 0x2
|
||||
#define SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID 0x3
|
||||
#define SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA 0x4
|
||||
#define SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID 0x5
|
||||
#define SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA 0x6
|
||||
|
||||
/* SBI function IDs for HSM extension */
|
||||
#define SBI_EXT_HSM_HART_START 0x0
|
||||
#define SBI_EXT_HSM_HART_STOP 0x1
|
||||
#define SBI_EXT_HSM_HART_GET_STATUS 0x2
|
||||
#define SBI_EXT_HSM_HART_SUSPEND 0x3
|
||||
|
||||
#define SBI_HSM_STATE_STARTED 0x0
|
||||
#define SBI_HSM_STATE_STOPPED 0x1
|
||||
#define SBI_HSM_STATE_START_PENDING 0x2
|
||||
#define SBI_HSM_STATE_STOP_PENDING 0x3
|
||||
#define SBI_HSM_STATE_SUSPENDED 0x4
|
||||
#define SBI_HSM_STATE_SUSPEND_PENDING 0x5
|
||||
#define SBI_HSM_STATE_RESUME_PENDING 0x6
|
||||
|
||||
#define SBI_HSM_SUSP_BASE_MASK 0x7fffffff
|
||||
#define SBI_HSM_SUSP_NON_RET_BIT 0x80000000
|
||||
#define SBI_HSM_SUSP_PLAT_BASE 0x10000000
|
||||
|
||||
#define SBI_HSM_SUSPEND_RET_DEFAULT 0x00000000
|
||||
#define SBI_HSM_SUSPEND_RET_PLATFORM SBI_HSM_SUSP_PLAT_BASE
|
||||
#define SBI_HSM_SUSPEND_RET_LAST SBI_HSM_SUSP_BASE_MASK
|
||||
#define SBI_HSM_SUSPEND_NON_RET_DEFAULT SBI_HSM_SUSP_NON_RET_BIT
|
||||
#define SBI_HSM_SUSPEND_NON_RET_PLATFORM (SBI_HSM_SUSP_NON_RET_BIT | \
|
||||
SBI_HSM_SUSP_PLAT_BASE)
|
||||
#define SBI_HSM_SUSPEND_NON_RET_LAST (SBI_HSM_SUSP_NON_RET_BIT | \
|
||||
SBI_HSM_SUSP_BASE_MASK)
|
||||
|
||||
/* SBI function IDs for SRST extension */
|
||||
#define SBI_EXT_SRST_RESET 0x0
|
||||
|
||||
#define SBI_SRST_RESET_TYPE_SHUTDOWN 0x0
|
||||
#define SBI_SRST_RESET_TYPE_COLD_REBOOT 0x1
|
||||
#define SBI_SRST_RESET_TYPE_WARM_REBOOT 0x2
|
||||
#define SBI_SRST_RESET_TYPE_LAST SBI_SRST_RESET_TYPE_WARM_REBOOT
|
||||
|
||||
#define SBI_SRST_RESET_REASON_NONE 0x0
|
||||
#define SBI_SRST_RESET_REASON_SYSFAIL 0x1
|
||||
|
||||
/* SBI function IDs for PMU extension */
|
||||
#define SBI_EXT_PMU_NUM_COUNTERS 0x0
|
||||
#define SBI_EXT_PMU_COUNTER_GET_INFO 0x1
|
||||
#define SBI_EXT_PMU_COUNTER_CFG_MATCH 0x2
|
||||
#define SBI_EXT_PMU_COUNTER_START 0x3
|
||||
#define SBI_EXT_PMU_COUNTER_STOP 0x4
|
||||
#define SBI_EXT_PMU_COUNTER_FW_READ 0x5
|
||||
#define SBI_EXT_PMU_COUNTER_FW_READ_HI 0x6
|
||||
#define SBI_EXT_PMU_SNAPSHOT_SET_SHMEM 0x7
|
||||
#define SBI_EXT_PMU_EVENT_GET_INFO 0x8
|
||||
|
||||
/* SBI function IDs for DBTR extension */
|
||||
#define SBI_EXT_DBTR_NUM_TRIGGERS 0x0
|
||||
#define SBI_EXT_DBTR_SETUP_SHMEM 0x1
|
||||
#define SBI_EXT_DBTR_TRIGGER_READ 0x2
|
||||
#define SBI_EXT_DBTR_TRIGGER_INSTALL 0x3
|
||||
#define SBI_EXT_DBTR_TRIGGER_UPDATE 0x4
|
||||
#define SBI_EXT_DBTR_TRIGGER_UNINSTALL 0x5
|
||||
#define SBI_EXT_DBTR_TRIGGER_ENABLE 0x6
|
||||
#define SBI_EXT_DBTR_TRIGGER_DISABLE 0x7
|
||||
|
||||
/* SBI function IDs for FW feature extension */
|
||||
#define SBI_EXT_FWFT_SET 0x0
|
||||
#define SBI_EXT_FWFT_GET 0x1
|
||||
|
||||
enum sbi_fwft_feature_t {
|
||||
SBI_FWFT_MISALIGNED_EXC_DELEG = 0x0,
|
||||
SBI_FWFT_LANDING_PAD = 0x1,
|
||||
SBI_FWFT_SHADOW_STACK = 0x2,
|
||||
SBI_FWFT_DOUBLE_TRAP = 0x3,
|
||||
SBI_FWFT_PTE_AD_HW_UPDATING = 0x4,
|
||||
SBI_FWFT_POINTER_MASKING_PMLEN = 0x5,
|
||||
SBI_FWFT_LOCAL_RESERVED_START = 0x6,
|
||||
SBI_FWFT_LOCAL_RESERVED_END = 0x3fffffff,
|
||||
SBI_FWFT_LOCAL_PLATFORM_START = 0x40000000,
|
||||
SBI_FWFT_LOCAL_PLATFORM_END = 0x7fffffff,
|
||||
|
||||
SBI_FWFT_GLOBAL_RESERVED_START = 0x80000000,
|
||||
SBI_FWFT_GLOBAL_RESERVED_END = 0xbfffffff,
|
||||
SBI_FWFT_GLOBAL_PLATFORM_START = 0xc0000000,
|
||||
SBI_FWFT_GLOBAL_PLATFORM_END = 0xffffffff,
|
||||
};
|
||||
|
||||
#define SBI_FWFT_GLOBAL_FEATURE_BIT (1 << 31)
|
||||
#define SBI_FWFT_PLATFORM_FEATURE_BIT (1 << 30)
|
||||
|
||||
#define SBI_FWFT_SET_FLAG_LOCK (1 << 0)
|
||||
|
||||
/** General pmu event codes specified in SBI PMU extension */
|
||||
enum sbi_pmu_hw_generic_events_t {
|
||||
SBI_PMU_HW_NO_EVENT = 0,
|
||||
SBI_PMU_HW_CPU_CYCLES = 1,
|
||||
SBI_PMU_HW_INSTRUCTIONS = 2,
|
||||
SBI_PMU_HW_CACHE_REFERENCES = 3,
|
||||
SBI_PMU_HW_CACHE_MISSES = 4,
|
||||
SBI_PMU_HW_BRANCH_INSTRUCTIONS = 5,
|
||||
SBI_PMU_HW_BRANCH_MISSES = 6,
|
||||
SBI_PMU_HW_BUS_CYCLES = 7,
|
||||
SBI_PMU_HW_STALLED_CYCLES_FRONTEND = 8,
|
||||
SBI_PMU_HW_STALLED_CYCLES_BACKEND = 9,
|
||||
SBI_PMU_HW_REF_CPU_CYCLES = 10,
|
||||
|
||||
SBI_PMU_HW_GENERAL_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* Generalized hardware cache events:
|
||||
*
|
||||
* { L1-D, L1-I, LLC, ITLB, DTLB, BPU, NODE } x
|
||||
* { read, write, prefetch } x
|
||||
* { accesses, misses }
|
||||
*/
|
||||
enum sbi_pmu_hw_cache_id {
|
||||
SBI_PMU_HW_CACHE_L1D = 0,
|
||||
SBI_PMU_HW_CACHE_L1I = 1,
|
||||
SBI_PMU_HW_CACHE_LL = 2,
|
||||
SBI_PMU_HW_CACHE_DTLB = 3,
|
||||
SBI_PMU_HW_CACHE_ITLB = 4,
|
||||
SBI_PMU_HW_CACHE_BPU = 5,
|
||||
SBI_PMU_HW_CACHE_NODE = 6,
|
||||
|
||||
SBI_PMU_HW_CACHE_MAX,
|
||||
};
|
||||
|
||||
enum sbi_pmu_hw_cache_op_id {
|
||||
SBI_PMU_HW_CACHE_OP_READ = 0,
|
||||
SBI_PMU_HW_CACHE_OP_WRITE = 1,
|
||||
SBI_PMU_HW_CACHE_OP_PREFETCH = 2,
|
||||
|
||||
SBI_PMU_HW_CACHE_OP_MAX,
|
||||
};
|
||||
|
||||
enum sbi_pmu_hw_cache_op_result_id {
|
||||
SBI_PMU_HW_CACHE_RESULT_ACCESS = 0,
|
||||
SBI_PMU_HW_CACHE_RESULT_MISS = 1,
|
||||
|
||||
SBI_PMU_HW_CACHE_RESULT_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* Special "firmware" events provided by the OpenSBI, even if the hardware
|
||||
* does not support performance events. These events are encoded as a raw
|
||||
* event type in Linux kernel perf framework.
|
||||
*/
|
||||
enum sbi_pmu_fw_event_code_id {
|
||||
SBI_PMU_FW_MISALIGNED_LOAD = 0,
|
||||
SBI_PMU_FW_MISALIGNED_STORE = 1,
|
||||
SBI_PMU_FW_ACCESS_LOAD = 2,
|
||||
SBI_PMU_FW_ACCESS_STORE = 3,
|
||||
SBI_PMU_FW_ILLEGAL_INSN = 4,
|
||||
SBI_PMU_FW_SET_TIMER = 5,
|
||||
SBI_PMU_FW_IPI_SENT = 6,
|
||||
SBI_PMU_FW_IPI_RECVD = 7,
|
||||
SBI_PMU_FW_FENCE_I_SENT = 8,
|
||||
SBI_PMU_FW_FENCE_I_RECVD = 9,
|
||||
SBI_PMU_FW_SFENCE_VMA_SENT = 10,
|
||||
SBI_PMU_FW_SFENCE_VMA_RCVD = 11,
|
||||
SBI_PMU_FW_SFENCE_VMA_ASID_SENT = 12,
|
||||
SBI_PMU_FW_SFENCE_VMA_ASID_RCVD = 13,
|
||||
|
||||
SBI_PMU_FW_HFENCE_GVMA_SENT = 14,
|
||||
SBI_PMU_FW_HFENCE_GVMA_RCVD = 15,
|
||||
SBI_PMU_FW_HFENCE_GVMA_VMID_SENT = 16,
|
||||
SBI_PMU_FW_HFENCE_GVMA_VMID_RCVD = 17,
|
||||
|
||||
SBI_PMU_FW_HFENCE_VVMA_SENT = 18,
|
||||
SBI_PMU_FW_HFENCE_VVMA_RCVD = 19,
|
||||
SBI_PMU_FW_HFENCE_VVMA_ASID_SENT = 20,
|
||||
SBI_PMU_FW_HFENCE_VVMA_ASID_RCVD = 21,
|
||||
SBI_PMU_FW_MAX,
|
||||
/*
|
||||
* Event codes 22 to 255 are reserved for future use.
|
||||
* Event codes 256 to 65534 are reserved for SBI implementation
|
||||
* specific custom firmware events.
|
||||
*/
|
||||
SBI_PMU_FW_RESERVED_MAX = 0xFFFE,
|
||||
/*
|
||||
* Event code 0xFFFF is used for platform specific firmware
|
||||
* events where the event data contains any event specific information.
|
||||
*/
|
||||
SBI_PMU_FW_PLATFORM = 0xFFFF,
|
||||
};
|
||||
|
||||
/** SBI PMU event idx type */
|
||||
enum sbi_pmu_event_type_id {
|
||||
SBI_PMU_EVENT_TYPE_HW = 0x0,
|
||||
SBI_PMU_EVENT_TYPE_HW_CACHE = 0x1,
|
||||
SBI_PMU_EVENT_TYPE_HW_RAW = 0x2,
|
||||
SBI_PMU_EVENT_TYPE_HW_RAW_V2 = 0x3,
|
||||
SBI_PMU_EVENT_TYPE_FW = 0xf,
|
||||
SBI_PMU_EVENT_TYPE_MAX,
|
||||
};
|
||||
|
||||
/** SBI PMU counter type */
|
||||
enum sbi_pmu_ctr_type {
|
||||
SBI_PMU_CTR_TYPE_HW = 0,
|
||||
SBI_PMU_CTR_TYPE_FW,
|
||||
};
|
||||
|
||||
struct sbi_pmu_event_info {
|
||||
uint32_t event_idx;
|
||||
uint32_t output;
|
||||
uint64_t event_data;
|
||||
};
|
||||
|
||||
/* Helper macros to decode event idx */
|
||||
#define SBI_PMU_EVENT_IDX_MASK 0xFFFFF
|
||||
#define SBI_PMU_EVENT_IDX_TYPE_OFFSET 16
|
||||
#define SBI_PMU_EVENT_IDX_TYPE_MASK (0xF << SBI_PMU_EVENT_IDX_TYPE_OFFSET)
|
||||
#define SBI_PMU_EVENT_IDX_CODE_MASK 0xFFFF
|
||||
#define SBI_PMU_EVENT_RAW_IDX 0x20000
|
||||
#define SBI_PMU_EVENT_RAW_V2_IDX 0x30000
|
||||
|
||||
#define SBI_PMU_EVENT_IDX_INVALID 0xFFFFFFFF
|
||||
|
||||
#define SBI_PMU_EVENT_HW_CACHE_OPS_RESULT 0x1
|
||||
#define SBI_PMU_EVENT_HW_CACHE_OPS_ID_MASK 0x6
|
||||
#define SBI_PMU_EVENT_HW_CACHE_OPS_ID_OFFSET 1
|
||||
#define SBI_PMU_EVENT_HW_CACHE_ID_MASK 0xfff8
|
||||
#define SBI_PMU_EVENT_HW_CACHE_ID_OFFSET 3
|
||||
|
||||
/* Flags defined for config matching function */
|
||||
#define SBI_PMU_CFG_FLAG_SKIP_MATCH (1 << 0)
|
||||
#define SBI_PMU_CFG_FLAG_CLEAR_VALUE (1 << 1)
|
||||
#define SBI_PMU_CFG_FLAG_AUTO_START (1 << 2)
|
||||
#define SBI_PMU_CFG_FLAG_SET_VUINH (1 << 3)
|
||||
#define SBI_PMU_CFG_FLAG_SET_VSINH (1 << 4)
|
||||
#define SBI_PMU_CFG_FLAG_SET_UINH (1 << 5)
|
||||
#define SBI_PMU_CFG_FLAG_SET_SINH (1 << 6)
|
||||
#define SBI_PMU_CFG_FLAG_SET_MINH (1 << 7)
|
||||
|
||||
/* Flags defined for counter start function */
|
||||
#define SBI_PMU_START_FLAG_SET_INIT_VALUE (1 << 0)
|
||||
#define SBI_PMU_START_FLAG_INIT_FROM_SNAPSHOT (1 << 1)
|
||||
|
||||
/* Flags defined for counter stop function */
|
||||
#define SBI_PMU_STOP_FLAG_RESET (1 << 0)
|
||||
#define SBI_PMU_STOP_FLAG_TAKE_SNAPSHOT (1 << 1)
|
||||
|
||||
/* SBI function IDs for DBCN extension */
|
||||
#define SBI_EXT_DBCN_CONSOLE_WRITE 0x0
|
||||
#define SBI_EXT_DBCN_CONSOLE_READ 0x1
|
||||
#define SBI_EXT_DBCN_CONSOLE_WRITE_BYTE 0x2
|
||||
|
||||
/* SBI function IDs for SUSP extension */
|
||||
#define SBI_EXT_SUSP_SUSPEND 0x0
|
||||
|
||||
#define SBI_SUSP_SLEEP_TYPE_SUSPEND 0x0
|
||||
#define SBI_SUSP_SLEEP_TYPE_LAST SBI_SUSP_SLEEP_TYPE_SUSPEND
|
||||
#define SBI_SUSP_PLATFORM_SLEEP_START 0x80000000
|
||||
|
||||
/* SBI function IDs for CPPC extension */
|
||||
#define SBI_EXT_CPPC_PROBE 0x0
|
||||
#define SBI_EXT_CPPC_READ 0x1
|
||||
#define SBI_EXT_CPPC_READ_HI 0x2
|
||||
#define SBI_EXT_CPPC_WRITE 0x3
|
||||
|
||||
enum sbi_cppc_reg_id {
|
||||
SBI_CPPC_HIGHEST_PERF = 0x00000000,
|
||||
SBI_CPPC_NOMINAL_PERF = 0x00000001,
|
||||
SBI_CPPC_LOW_NON_LINEAR_PERF = 0x00000002,
|
||||
SBI_CPPC_LOWEST_PERF = 0x00000003,
|
||||
SBI_CPPC_GUARANTEED_PERF = 0x00000004,
|
||||
SBI_CPPC_DESIRED_PERF = 0x00000005,
|
||||
SBI_CPPC_MIN_PERF = 0x00000006,
|
||||
SBI_CPPC_MAX_PERF = 0x00000007,
|
||||
SBI_CPPC_PERF_REDUC_TOLERANCE = 0x00000008,
|
||||
SBI_CPPC_TIME_WINDOW = 0x00000009,
|
||||
SBI_CPPC_CTR_WRAP_TIME = 0x0000000A,
|
||||
SBI_CPPC_REFERENCE_CTR = 0x0000000B,
|
||||
SBI_CPPC_DELIVERED_CTR = 0x0000000C,
|
||||
SBI_CPPC_PERF_LIMITED = 0x0000000D,
|
||||
SBI_CPPC_ENABLE = 0x0000000E,
|
||||
SBI_CPPC_AUTO_SEL_ENABLE = 0x0000000F,
|
||||
SBI_CPPC_AUTO_ACT_WINDOW = 0x00000010,
|
||||
SBI_CPPC_ENERGY_PERF_PREFERENCE = 0x00000011,
|
||||
SBI_CPPC_REFERENCE_PERF = 0x00000012,
|
||||
SBI_CPPC_LOWEST_FREQ = 0x00000013,
|
||||
SBI_CPPC_NOMINAL_FREQ = 0x00000014,
|
||||
SBI_CPPC_ACPI_LAST = SBI_CPPC_NOMINAL_FREQ,
|
||||
SBI_CPPC_TRANSITION_LATENCY = 0x80000000,
|
||||
SBI_CPPC_NON_ACPI_LAST = SBI_CPPC_TRANSITION_LATENCY,
|
||||
};
|
||||
|
||||
/* SBI Function IDs for SSE extension */
|
||||
#define SBI_EXT_SSE_READ_ATTR 0x00000000
|
||||
#define SBI_EXT_SSE_WRITE_ATTR 0x00000001
|
||||
#define SBI_EXT_SSE_REGISTER 0x00000002
|
||||
#define SBI_EXT_SSE_UNREGISTER 0x00000003
|
||||
#define SBI_EXT_SSE_ENABLE 0x00000004
|
||||
#define SBI_EXT_SSE_DISABLE 0x00000005
|
||||
#define SBI_EXT_SSE_COMPLETE 0x00000006
|
||||
#define SBI_EXT_SSE_INJECT 0x00000007
|
||||
#define SBI_EXT_SSE_HART_UNMASK 0x00000008
|
||||
#define SBI_EXT_SSE_HART_MASK 0x00000009
|
||||
|
||||
/* SBI SSE Event Attributes. */
|
||||
enum sbi_sse_attr_id {
|
||||
SBI_SSE_ATTR_STATUS = 0x00000000,
|
||||
SBI_SSE_ATTR_PRIO = 0x00000001,
|
||||
SBI_SSE_ATTR_CONFIG = 0x00000002,
|
||||
SBI_SSE_ATTR_PREFERRED_HART = 0x00000003,
|
||||
SBI_SSE_ATTR_ENTRY_PC = 0x00000004,
|
||||
SBI_SSE_ATTR_ENTRY_ARG = 0x00000005,
|
||||
SBI_SSE_ATTR_INTERRUPTED_SEPC = 0x00000006,
|
||||
SBI_SSE_ATTR_INTERRUPTED_FLAGS = 0x00000007,
|
||||
SBI_SSE_ATTR_INTERRUPTED_A6 = 0x00000008,
|
||||
SBI_SSE_ATTR_INTERRUPTED_A7 = 0x00000009,
|
||||
|
||||
SBI_SSE_ATTR_MAX = 0x0000000A
|
||||
};
|
||||
|
||||
#define SBI_SSE_ATTR_STATUS_STATE_OFFSET 0
|
||||
#define SBI_SSE_ATTR_STATUS_STATE_MASK 0x3
|
||||
#define SBI_SSE_ATTR_STATUS_PENDING_OFFSET 2
|
||||
#define SBI_SSE_ATTR_STATUS_INJECT_OFFSET 3
|
||||
|
||||
#define SBI_SSE_ATTR_CONFIG_ONESHOT (1 << 0)
|
||||
|
||||
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPP BIT(0)
|
||||
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPIE BIT(1)
|
||||
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_HSTATUS_SPV BIT(2)
|
||||
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_HSTATUS_SPVP BIT(3)
|
||||
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPELP BIT(4)
|
||||
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SDT BIT(5)
|
||||
|
||||
enum sbi_sse_state {
|
||||
SBI_SSE_STATE_UNUSED = 0,
|
||||
SBI_SSE_STATE_REGISTERED = 1,
|
||||
SBI_SSE_STATE_ENABLED = 2,
|
||||
SBI_SSE_STATE_RUNNING = 3,
|
||||
};
|
||||
|
||||
/* SBI SSE Event IDs. */
|
||||
/* Range 0x00000000 - 0x0000ffff */
|
||||
#define SBI_SSE_EVENT_LOCAL_HIGH_PRIO_RAS 0x00000000
|
||||
#define SBI_SSE_EVENT_LOCAL_DOUBLE_TRAP 0x00000001
|
||||
#define SBI_SSE_EVENT_LOCAL_RESERVED_0_START 0x00000002
|
||||
#define SBI_SSE_EVENT_LOCAL_RESERVED_0_END 0x00003fff
|
||||
#define SBI_SSE_EVENT_LOCAL_PLAT_0_START 0x00004000
|
||||
#define SBI_SSE_EVENT_LOCAL_PLAT_0_END 0x00007fff
|
||||
|
||||
#define SBI_SSE_EVENT_GLOBAL_HIGH_PRIO_RAS 0x00008000
|
||||
#define SBI_SSE_EVENT_GLOBAL_RESERVED_0_START 0x00008001
|
||||
#define SBI_SSE_EVENT_GLOBAL_RESERVED_0_END 0x0000bfff
|
||||
#define SBI_SSE_EVENT_GLOBAL_PLAT_0_START 0x0000c000
|
||||
#define SBI_SSE_EVENT_GLOBAL_PLAT_0_END 0x0000ffff
|
||||
|
||||
/* Range 0x00010000 - 0x0001ffff */
|
||||
#define SBI_SSE_EVENT_LOCAL_PMU_OVERFLOW 0x00010000
|
||||
#define SBI_SSE_EVENT_LOCAL_RESERVED_1_START 0x00010001
|
||||
#define SBI_SSE_EVENT_LOCAL_RESERVED_1_END 0x00013fff
|
||||
#define SBI_SSE_EVENT_LOCAL_PLAT_1_START 0x00014000
|
||||
#define SBI_SSE_EVENT_LOCAL_PLAT_1_END 0x00017fff
|
||||
|
||||
#define SBI_SSE_EVENT_GLOBAL_RESERVED_1_START 0x00018000
|
||||
#define SBI_SSE_EVENT_GLOBAL_RESERVED_1_END 0x0001bfff
|
||||
#define SBI_SSE_EVENT_GLOBAL_PLAT_1_START 0x0001c000
|
||||
#define SBI_SSE_EVENT_GLOBAL_PLAT_1_END 0x0001ffff
|
||||
|
||||
/* Range 0x00100000 - 0x0010ffff */
|
||||
#define SBI_SSE_EVENT_LOCAL_LOW_PRIO_RAS 0x00100000
|
||||
#define SBI_SSE_EVENT_LOCAL_RESERVED_2_START 0x00100001
|
||||
#define SBI_SSE_EVENT_LOCAL_RESERVED_2_END 0x00103fff
|
||||
#define SBI_SSE_EVENT_LOCAL_PLAT_2_START 0x00104000
|
||||
#define SBI_SSE_EVENT_LOCAL_PLAT_2_END 0x00107fff
|
||||
|
||||
#define SBI_SSE_EVENT_GLOBAL_LOW_PRIO_RAS 0x00108000
|
||||
#define SBI_SSE_EVENT_GLOBAL_RESERVED_2_START 0x00108001
|
||||
#define SBI_SSE_EVENT_GLOBAL_RESERVED_2_END 0x0010bfff
|
||||
#define SBI_SSE_EVENT_GLOBAL_PLAT_2_START 0x0010c000
|
||||
#define SBI_SSE_EVENT_GLOBAL_PLAT_2_END 0x0010ffff
|
||||
|
||||
/* Range 0xffff0000 - 0xffffffff */
|
||||
#define SBI_SSE_EVENT_LOCAL_SOFTWARE 0xffff0000
|
||||
#define SBI_SSE_EVENT_LOCAL_RESERVED_3_START 0xffff0001
|
||||
#define SBI_SSE_EVENT_LOCAL_RESERVED_3_END 0xffff3fff
|
||||
#define SBI_SSE_EVENT_LOCAL_PLAT_3_START 0xffff4000
|
||||
#define SBI_SSE_EVENT_LOCAL_PLAT_3_END 0xffff7fff
|
||||
|
||||
#define SBI_SSE_EVENT_GLOBAL_SOFTWARE 0xffff8000
|
||||
#define SBI_SSE_EVENT_GLOBAL_RESERVED_3_START 0xffff8001
|
||||
#define SBI_SSE_EVENT_GLOBAL_RESERVED_3_END 0xffffbfff
|
||||
#define SBI_SSE_EVENT_GLOBAL_PLAT_3_START 0xffffc000
|
||||
#define SBI_SSE_EVENT_GLOBAL_PLAT_3_END 0xffffffff
|
||||
|
||||
#define SBI_SSE_EVENT_GLOBAL_BIT BIT(15)
|
||||
#define SBI_SSE_EVENT_PLATFORM_BIT BIT(14)
|
||||
|
||||
/* SBI function IDs for MPXY extension */
|
||||
#define SBI_EXT_MPXY_GET_SHMEM_SIZE 0x0
|
||||
#define SBI_EXT_MPXY_SET_SHMEM 0x1
|
||||
#define SBI_EXT_MPXY_GET_CHANNEL_IDS 0x2
|
||||
#define SBI_EXT_MPXY_READ_ATTRS 0x3
|
||||
#define SBI_EXT_MPXY_WRITE_ATTRS 0x4
|
||||
#define SBI_EXT_MPXY_SEND_MSG_WITH_RESP 0x5
|
||||
#define SBI_EXT_MPXY_SEND_MSG_WITHOUT_RESP 0x6
|
||||
#define SBI_EXT_MPXY_GET_NOTIFICATION_EVENTS 0x7
|
||||
|
||||
/* SBI base specification related macros */
|
||||
#define SBI_SPEC_VERSION_MAJOR_OFFSET 24
|
||||
#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f
|
||||
#define SBI_SPEC_VERSION_MINOR_MASK 0xffffff
|
||||
#define SBI_EXT_EXPERIMENTAL_START 0x08000000
|
||||
#define SBI_EXT_EXPERIMENTAL_END 0x08FFFFFF
|
||||
#define SBI_EXT_VENDOR_START 0x09000000
|
||||
#define SBI_EXT_VENDOR_END 0x09FFFFFF
|
||||
#define SBI_EXT_FIRMWARE_START 0x0A000000
|
||||
#define SBI_EXT_FIRMWARE_END 0x0AFFFFFF
|
||||
|
||||
/* SBI return error codes */
|
||||
#define SBI_SUCCESS 0
|
||||
#define SBI_ERR_FAILED -1
|
||||
#define SBI_ERR_NOT_SUPPORTED -2
|
||||
#define SBI_ERR_INVALID_PARAM -3
|
||||
#define SBI_ERR_DENIED -4
|
||||
#define SBI_ERR_INVALID_ADDRESS -5
|
||||
#define SBI_ERR_ALREADY_AVAILABLE -6
|
||||
#define SBI_ERR_ALREADY_STARTED -7
|
||||
#define SBI_ERR_ALREADY_STOPPED -8
|
||||
#define SBI_ERR_NO_SHMEM -9
|
||||
#define SBI_ERR_INVALID_STATE -10
|
||||
#define SBI_ERR_BAD_RANGE -11
|
||||
#define SBI_ERR_TIMEOUT -12
|
||||
#define SBI_ERR_IO -13
|
||||
#define SBI_ERR_DENIED_LOCKED -14
|
||||
|
||||
#define SBI_LAST_ERR SBI_ERR_DENIED_LOCKED
|
||||
|
||||
/* clang-format on */
|
||||
#define SBI_ECALL_SET_TIMER 0
|
||||
#define SBI_ECALL_CONSOLE_PUTCHAR 1
|
||||
#define SBI_ECALL_CONSOLE_GETCHAR 2
|
||||
#define SBI_ECALL_CLEAR_IPI 3
|
||||
#define SBI_ECALL_SEND_IPI 4
|
||||
#define SBI_ECALL_REMOTE_FENCE_I 5
|
||||
#define SBI_ECALL_REMOTE_SFENCE_VMA 6
|
||||
#define SBI_ECALL_REMOTE_SFENCE_VMA_ASID 7
|
||||
#define SBI_ECALL_SHUTDOWN 8
|
||||
|
||||
#define SBI_ECALL(__num, __a0, __a1, __a2) ({ \
|
||||
register unsigned long a0 asm ("a0") = (unsigned long)(__a0); \
|
||||
register unsigned long a1 asm ("a1") = (unsigned long)(__a1); \
|
||||
register unsigned long a2 asm ("a2") = (unsigned long)(__a2); \
|
||||
register unsigned long a7 asm ("a7") = (unsigned long)(__num); \
|
||||
asm volatile ("ecall" \
|
||||
: "+r" (a0) \
|
||||
: "r" (a1), "r" (a2), "r" (a7) \
|
||||
: "memory"); \
|
||||
a0; \
|
||||
})
|
||||
|
||||
#define SBI_ECALL_0(__num) SBI_ECALL(__num, 0, 0, 0)
|
||||
#define SBI_ECALL_1(__num, __a0) SBI_ECALL(__num, __a0, 0, 0)
|
||||
#define SBI_ECALL_2(__num, __a0, __a1) SBI_ECALL(__num, __a0, __a1, 0)
|
||||
|
||||
#define sbi_ecall_console_putc(c) \
|
||||
SBI_ECALL_1(SBI_ECALL_CONSOLE_PUTCHAR, (c));
|
||||
|
||||
static inline void sbi_ecall_console_puts(const char *str)
|
||||
{
|
||||
while (str && *str)
|
||||
sbi_ecall_console_putc(*str++);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -12,12 +12,16 @@
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
struct sbi_trap_regs;
|
||||
struct sbi_scratch;
|
||||
|
||||
int sbi_emulate_csr_read(int csr_num, struct sbi_trap_regs *regs,
|
||||
int sbi_emulate_csr_read(int csr_num,
|
||||
u32 hartid, ulong mstatus,
|
||||
struct sbi_scratch *scratch,
|
||||
ulong *csr_val);
|
||||
|
||||
int sbi_emulate_csr_write(int csr_num, struct sbi_trap_regs *regs,
|
||||
int sbi_emulate_csr_write(int csr_num,
|
||||
u32 hartid, ulong mstatus,
|
||||
struct sbi_scratch *scratch,
|
||||
ulong csr_val);
|
||||
|
||||
#endif
|
||||
|
@ -10,35 +10,16 @@
|
||||
#ifndef __SBI_ERROR_H__
|
||||
#define __SBI_ERROR_H__
|
||||
|
||||
#include <sbi/sbi_ecall_interface.h>
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#define SBI_OK 0
|
||||
#define SBI_EFAIL SBI_ERR_FAILED
|
||||
#define SBI_ENOTSUPP SBI_ERR_NOT_SUPPORTED
|
||||
#define SBI_EINVAL SBI_ERR_INVALID_PARAM
|
||||
#define SBI_EDENIED SBI_ERR_DENIED
|
||||
#define SBI_EINVALID_ADDR SBI_ERR_INVALID_ADDRESS
|
||||
#define SBI_EALREADY SBI_ERR_ALREADY_AVAILABLE
|
||||
#define SBI_EALREADY_STARTED SBI_ERR_ALREADY_STARTED
|
||||
#define SBI_EALREADY_STOPPED SBI_ERR_ALREADY_STOPPED
|
||||
#define SBI_ENO_SHMEM SBI_ERR_NO_SHMEM
|
||||
#define SBI_EINVALID_STATE SBI_ERR_INVALID_STATE
|
||||
#define SBI_EBAD_RANGE SBI_ERR_BAD_RANGE
|
||||
#define SBI_ETIMEOUT SBI_ERR_TIMEOUT
|
||||
#define SBI_ETIMEDOUT SBI_ERR_TIMEOUT
|
||||
#define SBI_EIO SBI_ERR_IO
|
||||
#define SBI_EDENIED_LOCKED SBI_ERR_DENIED_LOCKED
|
||||
|
||||
#define SBI_ENODEV -1000
|
||||
#define SBI_ENOSYS -1001
|
||||
#define SBI_EILL -1002
|
||||
#define SBI_ENOSPC -1003
|
||||
#define SBI_ENOMEM -1004
|
||||
#define SBI_EUNKNOWN -1005
|
||||
#define SBI_ENOENT -1006
|
||||
|
||||
/* clang-format on */
|
||||
#define SBI_OK 0
|
||||
#define SBI_EUNKNOWN -1
|
||||
#define SBI_EFAIL -2
|
||||
#define SBI_EINVAL -3
|
||||
#define SBI_ENOENT -4
|
||||
#define SBI_ENOTSUPP -5
|
||||
#define SBI_ENODEV -6
|
||||
#define SBI_ENOSYS -7
|
||||
#define SBI_ETIMEDOUT -8
|
||||
#define SBI_EIO -9
|
||||
#define SBI_EILL -10
|
||||
|
||||
#endif
|
||||
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Atish Patra<atish.patra@wdc.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SBI_FIFO_H__
|
||||
#define __SBI_FIFO_H__
|
||||
|
||||
#include <sbi/riscv_locks.h>
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
struct sbi_fifo {
|
||||
void *queue;
|
||||
spinlock_t qlock;
|
||||
u16 entry_size;
|
||||
u16 num_entries;
|
||||
u16 avail;
|
||||
u16 tail;
|
||||
};
|
||||
|
||||
#define SBI_FIFO_INITIALIZER(__queue_mem, __entries, __entry_size) \
|
||||
{ .queue = __queue_mem, \
|
||||
.qlock = SPIN_LOCK_INITIALIZER, \
|
||||
.num_entries = __entries, \
|
||||
.entry_size = __entry_size, \
|
||||
.avail = 0, \
|
||||
.tail = 0, \
|
||||
}
|
||||
|
||||
#define SBI_FIFO_DEFINE(__name, __queue_mem, __entries, __entry_size) \
|
||||
struct sbi_fifo __name = SBI_FIFO_INITIALIZER(__queue_mem, __entries, __entry_size)
|
||||
|
||||
enum sbi_fifo_inplace_update_types {
|
||||
SBI_FIFO_SKIP,
|
||||
SBI_FIFO_UPDATED,
|
||||
SBI_FIFO_UNCHANGED,
|
||||
};
|
||||
|
||||
int sbi_fifo_dequeue(struct sbi_fifo *fifo, void *data);
|
||||
int sbi_fifo_enqueue(struct sbi_fifo *fifo, void *data, bool force);
|
||||
void sbi_fifo_init(struct sbi_fifo *fifo, void *queue_mem, u16 entries,
|
||||
u16 entry_size);
|
||||
int sbi_fifo_is_empty(struct sbi_fifo *fifo);
|
||||
int sbi_fifo_is_full(struct sbi_fifo *fifo);
|
||||
int sbi_fifo_inplace_update(struct sbi_fifo *fifo, void *in,
|
||||
int (*fptr)(void *in, void *data));
|
||||
u16 sbi_fifo_avail(struct sbi_fifo *fifo);
|
||||
|
||||
#endif
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2024 Rivos Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Clément Léger <cleger@rivosinc.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_FW_FEATURE_H__
|
||||
#define __SBI_FW_FEATURE_H__
|
||||
|
||||
#include <sbi/sbi_ecall_interface.h>
|
||||
|
||||
struct sbi_scratch;
|
||||
|
||||
int sbi_fwft_set(enum sbi_fwft_feature_t feature, unsigned long value,
|
||||
unsigned long flags);
|
||||
int sbi_fwft_get(enum sbi_fwft_feature_t feature, unsigned long *out_val);
|
||||
|
||||
int sbi_fwft_init(struct sbi_scratch *scratch, bool cold_boot);
|
||||
|
||||
#endif
|
@ -11,157 +11,33 @@
|
||||
#define __SBI_HART_H__
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
#include <sbi/sbi_bitops.h>
|
||||
|
||||
/** Possible privileged specification versions of a hart */
|
||||
enum sbi_hart_priv_versions {
|
||||
/** Unknown privileged specification */
|
||||
SBI_HART_PRIV_VER_UNKNOWN = 0,
|
||||
/** Privileged specification v1.10 */
|
||||
SBI_HART_PRIV_VER_1_10 = 1,
|
||||
/** Privileged specification v1.11 */
|
||||
SBI_HART_PRIV_VER_1_11 = 2,
|
||||
/** Privileged specification v1.12 */
|
||||
SBI_HART_PRIV_VER_1_12 = 3,
|
||||
};
|
||||
|
||||
/** Possible ISA extensions of a hart */
|
||||
enum sbi_hart_extensions {
|
||||
/** HART has AIA M-mode CSRs */
|
||||
SBI_HART_EXT_SMAIA = 0,
|
||||
/** HART has Smepmp */
|
||||
SBI_HART_EXT_SMEPMP,
|
||||
/** HART has Smstateen extension **/
|
||||
SBI_HART_EXT_SMSTATEEN,
|
||||
/** Hart has Sscofpmt extension */
|
||||
SBI_HART_EXT_SSCOFPMF,
|
||||
/** HART has Sstc extension */
|
||||
SBI_HART_EXT_SSTC,
|
||||
/** HART has Zicntr extension (i.e. HW cycle, time & instret CSRs) */
|
||||
SBI_HART_EXT_ZICNTR,
|
||||
/** HART has Zihpm extension */
|
||||
SBI_HART_EXT_ZIHPM,
|
||||
/** HART has Zkr extension */
|
||||
SBI_HART_EXT_ZKR,
|
||||
/** Hart has Smcntrpmf extension */
|
||||
SBI_HART_EXT_SMCNTRPMF,
|
||||
/** Hart has Xandespmu extension */
|
||||
SBI_HART_EXT_XANDESPMU,
|
||||
/** Hart has Zicboz extension */
|
||||
SBI_HART_EXT_ZICBOZ,
|
||||
/** Hart has Zicbom extension */
|
||||
SBI_HART_EXT_ZICBOM,
|
||||
/** Hart has Svpbmt extension */
|
||||
SBI_HART_EXT_SVPBMT,
|
||||
/** Hart has debug trigger extension */
|
||||
SBI_HART_EXT_SDTRIG,
|
||||
/** Hart has Smcsrind extension */
|
||||
SBI_HART_EXT_SMCSRIND,
|
||||
/** Hart has Smcdeleg extension */
|
||||
SBI_HART_EXT_SMCDELEG,
|
||||
/** Hart has Sscsrind extension */
|
||||
SBI_HART_EXT_SSCSRIND,
|
||||
/** Hart has Ssccfg extension */
|
||||
SBI_HART_EXT_SSCCFG,
|
||||
/** Hart has Svade extension */
|
||||
SBI_HART_EXT_SVADE,
|
||||
/** Hart has Svadu extension */
|
||||
SBI_HART_EXT_SVADU,
|
||||
/** Hart has Smnpm extension */
|
||||
SBI_HART_EXT_SMNPM,
|
||||
/** HART has zicfilp extension */
|
||||
SBI_HART_EXT_ZICFILP,
|
||||
/** HART has zicfiss extension */
|
||||
SBI_HART_EXT_ZICFISS,
|
||||
/** Hart has Ssdbltrp extension */
|
||||
SBI_HART_EXT_SSDBLTRP,
|
||||
/** HART has CTR M-mode CSRs */
|
||||
SBI_HART_EXT_SMCTR,
|
||||
/** HART has CTR S-mode CSRs */
|
||||
SBI_HART_EXT_SSCTR,
|
||||
/** HART has Ssstateen extension **/
|
||||
SBI_HART_EXT_SSSTATEEN,
|
||||
|
||||
/** Maximum index of Hart extension */
|
||||
SBI_HART_EXT_MAX,
|
||||
};
|
||||
|
||||
struct sbi_hart_ext_data {
|
||||
const unsigned int id;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
extern const struct sbi_hart_ext_data sbi_hart_ext[];
|
||||
|
||||
/** CSRs should be detected by access and trapping */
|
||||
enum sbi_hart_csrs {
|
||||
SBI_HART_CSR_CYCLE = 0,
|
||||
SBI_HART_CSR_TIME,
|
||||
SBI_HART_CSR_INSTRET,
|
||||
SBI_HART_CSR_MAX,
|
||||
};
|
||||
|
||||
/*
|
||||
* Smepmp enforces access boundaries between M-mode and
|
||||
* S/U-mode. When it is enabled, the PMPs are programmed
|
||||
* such that M-mode doesn't have access to S/U-mode memory.
|
||||
*
|
||||
* To give M-mode R/W access to the shared memory between M and
|
||||
* S/U-mode, first entry is reserved. It is disabled at boot.
|
||||
* When shared memory access is required, the physical address
|
||||
* should be programmed into the first PMP entry with R/W
|
||||
* permissions to the M-mode. Once the work is done, it should be
|
||||
* unmapped. sbi_hart_map_saddr/sbi_hart_unmap_saddr function
|
||||
* pair should be used to map/unmap the shared memory.
|
||||
*/
|
||||
#define SBI_SMEPMP_RESV_ENTRY 0
|
||||
|
||||
struct sbi_hart_features {
|
||||
bool detected;
|
||||
int priv_version;
|
||||
unsigned long extensions[BITS_TO_LONGS(SBI_HART_EXT_MAX)];
|
||||
unsigned long csrs[BITS_TO_LONGS(SBI_HART_CSR_MAX)];
|
||||
unsigned int pmp_count;
|
||||
unsigned int pmp_addr_bits;
|
||||
unsigned int pmp_log2gran;
|
||||
unsigned int mhpm_mask;
|
||||
unsigned int mhpm_bits;
|
||||
};
|
||||
|
||||
struct sbi_scratch;
|
||||
|
||||
int sbi_hart_reinit(struct sbi_scratch *scratch);
|
||||
int sbi_hart_init(struct sbi_scratch *scratch, bool cold_boot);
|
||||
int sbi_hart_init(struct sbi_scratch *scratch, u32 hartid);
|
||||
|
||||
extern void (*sbi_hart_expected_trap)(void);
|
||||
|
||||
unsigned int sbi_hart_mhpm_mask(struct sbi_scratch *scratch);
|
||||
void sbi_hart_delegation_dump(struct sbi_scratch *scratch,
|
||||
const char *prefix, const char *suffix);
|
||||
unsigned int sbi_hart_pmp_count(struct sbi_scratch *scratch);
|
||||
unsigned int sbi_hart_pmp_log2gran(struct sbi_scratch *scratch);
|
||||
unsigned int sbi_hart_pmp_addrbits(struct sbi_scratch *scratch);
|
||||
unsigned int sbi_hart_mhpm_bits(struct sbi_scratch *scratch);
|
||||
int sbi_hart_pmp_configure(struct sbi_scratch *scratch);
|
||||
int sbi_hart_map_saddr(unsigned long base, unsigned long size);
|
||||
int sbi_hart_unmap_saddr(void);
|
||||
int sbi_hart_priv_version(struct sbi_scratch *scratch);
|
||||
void sbi_hart_get_priv_version_str(struct sbi_scratch *scratch,
|
||||
char *version_str, int nvstr);
|
||||
void sbi_hart_update_extension(struct sbi_scratch *scratch,
|
||||
enum sbi_hart_extensions ext,
|
||||
bool enable);
|
||||
bool sbi_hart_has_extension(struct sbi_scratch *scratch,
|
||||
enum sbi_hart_extensions ext);
|
||||
void sbi_hart_get_extensions_str(struct sbi_scratch *scratch,
|
||||
char *extension_str, int nestr);
|
||||
bool sbi_hart_has_csr(struct sbi_scratch *scratch, enum sbi_hart_csrs csr);
|
||||
void sbi_hart_pmp_dump(struct sbi_scratch *scratch);
|
||||
|
||||
void __attribute__((noreturn)) sbi_hart_hang(void);
|
||||
|
||||
void __attribute__((noreturn))
|
||||
sbi_hart_switch_mode(unsigned long arg0, unsigned long arg1,
|
||||
unsigned long next_addr, unsigned long next_mode,
|
||||
bool next_virt);
|
||||
void __attribute__((noreturn)) sbi_hart_switch_mode(unsigned long arg0,
|
||||
unsigned long arg1,
|
||||
unsigned long next_addr,
|
||||
unsigned long next_mode);
|
||||
|
||||
void sbi_hart_mark_available(u32 hartid);
|
||||
|
||||
ulong sbi_hart_available_mask(void);
|
||||
|
||||
void sbi_hart_unmark_available(u32 hartid);
|
||||
|
||||
struct sbi_scratch *sbi_hart_id_to_scratch(struct sbi_scratch *scratch,
|
||||
u32 hartid);
|
||||
|
||||
void sbi_hart_wait_for_coldboot(struct sbi_scratch *scratch, u32 hartid);
|
||||
|
||||
void sbi_hart_wake_coldboot_harts(struct sbi_scratch *scratch, u32 hartid);
|
||||
|
||||
u32 sbi_current_hartid(void);
|
||||
|
||||
#endif
|
||||
|
@ -1,205 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Anup Patel <anup.patel@wdc.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_HARTMASK_H__
|
||||
#define __SBI_HARTMASK_H__
|
||||
|
||||
#include <sbi/sbi_bitmap.h>
|
||||
#include <sbi/sbi_scratch.h>
|
||||
|
||||
/**
|
||||
* Maximum number of bits in a hartmask
|
||||
*
|
||||
* The hartmask is indexed using physical HART id so this define
|
||||
* also represents the maximum number of HART ids generic OpenSBI
|
||||
* can handle.
|
||||
*/
|
||||
#define SBI_HARTMASK_MAX_BITS 128
|
||||
|
||||
/** Representation of hartmask */
|
||||
struct sbi_hartmask {
|
||||
DECLARE_BITMAP(bits, SBI_HARTMASK_MAX_BITS);
|
||||
};
|
||||
|
||||
/** Initialize hartmask to zero */
|
||||
#define SBI_HARTMASK_INIT(__m) \
|
||||
bitmap_zero(((__m)->bits), SBI_HARTMASK_MAX_BITS)
|
||||
|
||||
/** Initialize hartmask to zero except a particular HART id */
|
||||
#define SBI_HARTMASK_INIT_EXCEPT(__m, __h) \
|
||||
do { \
|
||||
u32 __i = sbi_hartid_to_hartindex(__h); \
|
||||
bitmap_zero_except(((__m)->bits), __i, SBI_HARTMASK_MAX_BITS); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* Get underlying bitmap of hartmask
|
||||
* @param m the hartmask pointer
|
||||
*/
|
||||
#define sbi_hartmask_bits(__m) ((__m)->bits)
|
||||
|
||||
/**
|
||||
* Set a HART index in hartmask
|
||||
* @param i HART index to set
|
||||
* @param m the hartmask pointer
|
||||
*/
|
||||
static inline void sbi_hartmask_set_hartindex(u32 i, struct sbi_hartmask *m)
|
||||
{
|
||||
if (i < SBI_HARTMASK_MAX_BITS)
|
||||
__set_bit(i, m->bits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a HART id in hartmask
|
||||
* @param h HART id to set
|
||||
* @param m the hartmask pointer
|
||||
*/
|
||||
static inline void sbi_hartmask_set_hartid(u32 h, struct sbi_hartmask *m)
|
||||
{
|
||||
sbi_hartmask_set_hartindex(sbi_hartid_to_hartindex(h), m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear a HART index in hartmask
|
||||
* @param i HART index to clear
|
||||
* @param m the hartmask pointer
|
||||
*/
|
||||
static inline void sbi_hartmask_clear_hartindex(u32 i, struct sbi_hartmask *m)
|
||||
{
|
||||
if (i < SBI_HARTMASK_MAX_BITS)
|
||||
__clear_bit(i, m->bits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear a HART id in hartmask
|
||||
* @param h HART id to clear
|
||||
* @param m the hartmask pointer
|
||||
*/
|
||||
static inline void sbi_hartmask_clear_hartid(u32 h, struct sbi_hartmask *m)
|
||||
{
|
||||
sbi_hartmask_clear_hartindex(sbi_hartid_to_hartindex(h), m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a HART index in hartmask
|
||||
* @param i HART index to test
|
||||
* @param m the hartmask pointer
|
||||
*/
|
||||
static inline int sbi_hartmask_test_hartindex(u32 i,
|
||||
const struct sbi_hartmask *m)
|
||||
{
|
||||
if (i < SBI_HARTMASK_MAX_BITS)
|
||||
return __test_bit(i, m->bits);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a HART id in hartmask
|
||||
* @param h HART id to test
|
||||
* @param m the hartmask pointer
|
||||
*/
|
||||
static inline int sbi_hartmask_test_hartid(u32 h, const struct sbi_hartmask *m)
|
||||
{
|
||||
return sbi_hartmask_test_hartindex(sbi_hartid_to_hartindex(h), m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all HARTs in a hartmask
|
||||
* @param dstp the hartmask pointer
|
||||
*/
|
||||
static inline void sbi_hartmask_set_all(struct sbi_hartmask *dstp)
|
||||
{
|
||||
bitmap_fill(sbi_hartmask_bits(dstp), SBI_HARTMASK_MAX_BITS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all HARTs in a hartmask
|
||||
* @param dstp the hartmask pointer
|
||||
*/
|
||||
static inline void sbi_hartmask_clear_all(struct sbi_hartmask *dstp)
|
||||
{
|
||||
bitmap_zero(sbi_hartmask_bits(dstp), SBI_HARTMASK_MAX_BITS);
|
||||
}
|
||||
|
||||
/**
|
||||
* *dstp = *srcp
|
||||
* @param dstp the hartmask destination
|
||||
* @param srcp the hartmask source
|
||||
*/
|
||||
static inline void sbi_hartmask_copy(struct sbi_hartmask *dstp,
|
||||
const struct sbi_hartmask *srcp)
|
||||
{
|
||||
bitmap_copy(sbi_hartmask_bits(dstp), sbi_hartmask_bits(srcp),
|
||||
SBI_HARTMASK_MAX_BITS);
|
||||
}
|
||||
|
||||
/**
|
||||
* *dstp = *src1p & *src2p
|
||||
* @param dstp the hartmask result
|
||||
* @param src1p the first input
|
||||
* @param src2p the second input
|
||||
*/
|
||||
static inline void sbi_hartmask_and(struct sbi_hartmask *dstp,
|
||||
const struct sbi_hartmask *src1p,
|
||||
const struct sbi_hartmask *src2p)
|
||||
{
|
||||
bitmap_and(sbi_hartmask_bits(dstp), sbi_hartmask_bits(src1p),
|
||||
sbi_hartmask_bits(src2p), SBI_HARTMASK_MAX_BITS);
|
||||
}
|
||||
|
||||
/**
|
||||
* *dstp = *src1p | *src2p
|
||||
* @param dstp the hartmask result
|
||||
* @param src1p the first input
|
||||
* @param src2p the second input
|
||||
*/
|
||||
static inline void sbi_hartmask_or(struct sbi_hartmask *dstp,
|
||||
const struct sbi_hartmask *src1p,
|
||||
const struct sbi_hartmask *src2p)
|
||||
{
|
||||
bitmap_or(sbi_hartmask_bits(dstp), sbi_hartmask_bits(src1p),
|
||||
sbi_hartmask_bits(src2p), SBI_HARTMASK_MAX_BITS);
|
||||
}
|
||||
|
||||
/**
|
||||
* *dstp = *src1p ^ *src2p
|
||||
* @param dstp the hartmask result
|
||||
* @param src1p the first input
|
||||
* @param src2p the second input
|
||||
*/
|
||||
static inline void sbi_hartmask_xor(struct sbi_hartmask *dstp,
|
||||
const struct sbi_hartmask *src1p,
|
||||
const struct sbi_hartmask *src2p)
|
||||
{
|
||||
bitmap_xor(sbi_hartmask_bits(dstp), sbi_hartmask_bits(src1p),
|
||||
sbi_hartmask_bits(src2p), SBI_HARTMASK_MAX_BITS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Count of bits in *srcp
|
||||
* @param srcp the hartmask to count bits in
|
||||
*
|
||||
* Return: count of bits set in *srcp
|
||||
*/
|
||||
static inline int sbi_hartmask_weight(const struct sbi_hartmask *srcp)
|
||||
{
|
||||
return bitmap_weight(sbi_hartmask_bits(srcp), SBI_HARTMASK_MAX_BITS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over each HART index in hartmask
|
||||
* __i hart index
|
||||
* __m hartmask
|
||||
*/
|
||||
#define sbi_hartmask_for_each_hartindex(__i, __m) \
|
||||
for((__i) = find_first_bit((__m)->bits, SBI_HARTMASK_MAX_BITS); \
|
||||
(__i) < SBI_HARTMASK_MAX_BITS; \
|
||||
(__i) = find_next_bit((__m)->bits, SBI_HARTMASK_MAX_BITS, (__i) + 1))
|
||||
|
||||
#endif
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2023 Ventana Micro Systems Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Anup Patel<apatel@ventanamicro.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_HEAP_H__
|
||||
#define __SBI_HEAP_H__
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
/* Opaque declaration of heap control struct */
|
||||
struct sbi_heap_control;
|
||||
|
||||
/* Global heap control structure */
|
||||
extern struct sbi_heap_control global_hpctrl;
|
||||
|
||||
/* Alignment of heap base address and size */
|
||||
#define HEAP_BASE_ALIGN 1024
|
||||
|
||||
struct sbi_scratch;
|
||||
|
||||
/** Allocate from heap area */
|
||||
void *sbi_malloc_from(struct sbi_heap_control *hpctrl, size_t size);
|
||||
|
||||
static inline void *sbi_malloc(size_t size)
|
||||
{
|
||||
return sbi_malloc_from(&global_hpctrl, size);
|
||||
}
|
||||
|
||||
/** Allocate aligned from heap area */
|
||||
void *sbi_aligned_alloc_from(struct sbi_heap_control *hpctrl,
|
||||
size_t alignment,size_t size);
|
||||
|
||||
static inline void *sbi_aligned_alloc(size_t alignment, size_t size)
|
||||
{
|
||||
return sbi_aligned_alloc_from(&global_hpctrl, alignment, size);
|
||||
}
|
||||
|
||||
/** Zero allocate from heap area */
|
||||
void *sbi_zalloc_from(struct sbi_heap_control *hpctrl, size_t size);
|
||||
|
||||
static inline void *sbi_zalloc(size_t size)
|
||||
{
|
||||
return sbi_zalloc_from(&global_hpctrl, size);
|
||||
}
|
||||
|
||||
/** Allocate array from heap area */
|
||||
static inline void *sbi_calloc(size_t nitems, size_t size)
|
||||
{
|
||||
return sbi_zalloc(nitems * size);
|
||||
}
|
||||
|
||||
static inline void *sbi_calloc_from(struct sbi_heap_control *hpctrl,
|
||||
size_t nitems, size_t size)
|
||||
{
|
||||
return sbi_zalloc_from(hpctrl, nitems * size);
|
||||
}
|
||||
|
||||
/** Free-up to heap area */
|
||||
void sbi_free_from(struct sbi_heap_control *hpctrl, void *ptr);
|
||||
|
||||
static inline void sbi_free(void *ptr)
|
||||
{
|
||||
return sbi_free_from(&global_hpctrl, ptr);
|
||||
}
|
||||
|
||||
/** Amount (in bytes) of free space in the heap area */
|
||||
unsigned long sbi_heap_free_space_from(struct sbi_heap_control *hpctrl);
|
||||
|
||||
static inline unsigned long sbi_heap_free_space(void)
|
||||
{
|
||||
return sbi_heap_free_space_from(&global_hpctrl);
|
||||
}
|
||||
|
||||
/** Amount (in bytes) of used space in the heap area */
|
||||
unsigned long sbi_heap_used_space_from(struct sbi_heap_control *hpctrl);
|
||||
|
||||
static inline unsigned long sbi_heap_used_space(void)
|
||||
{
|
||||
return sbi_heap_used_space_from(&global_hpctrl);
|
||||
}
|
||||
|
||||
/** Amount (in bytes) of reserved space in the heap area */
|
||||
unsigned long sbi_heap_reserved_space_from(struct sbi_heap_control *hpctrl);
|
||||
|
||||
static inline unsigned long sbi_heap_reserved_space(void)
|
||||
{
|
||||
return sbi_heap_reserved_space_from(&global_hpctrl);
|
||||
}
|
||||
|
||||
/** Initialize heap area */
|
||||
int sbi_heap_init(struct sbi_scratch *scratch);
|
||||
int sbi_heap_init_new(struct sbi_heap_control *hpctrl, unsigned long base,
|
||||
unsigned long size);
|
||||
int sbi_heap_alloc_new(struct sbi_heap_control **hpctrl);
|
||||
|
||||
#endif
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Atish Patra <atish.patra@wdc.com>
|
||||
* Anup Patel <anup.patel@wdc.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_FENCE_H__
|
||||
#define __SBI_FENCE_H__
|
||||
|
||||
/** Invalidate Stage2 TLBs for given VMID and guest physical address */
|
||||
void __sbi_hfence_gvma_vmid_gpa(unsigned long gpa_divby_4,
|
||||
unsigned long vmid);
|
||||
|
||||
/** Invalidate Stage2 TLBs for given VMID */
|
||||
void __sbi_hfence_gvma_vmid(unsigned long vmid);
|
||||
|
||||
/** Invalidate Stage2 TLBs for given guest physical address */
|
||||
void __sbi_hfence_gvma_gpa(unsigned long gpa_divby_4);
|
||||
|
||||
/** Invalidate all possible Stage2 TLBs */
|
||||
void __sbi_hfence_gvma_all(void);
|
||||
|
||||
/** Invalidate unified TLB entries for given asid and guest virtual address */
|
||||
void __sbi_hfence_vvma_asid_va(unsigned long va, unsigned long asid);
|
||||
|
||||
/** Invalidate unified TLB entries for given ASID for a guest*/
|
||||
void __sbi_hfence_vvma_asid(unsigned long asid);
|
||||
|
||||
/** Invalidate unified TLB entries for a given guest virtual address */
|
||||
void __sbi_hfence_vvma_va(unsigned long va);
|
||||
|
||||
/** Invalidate all possible Stage2 TLBs */
|
||||
void __sbi_hfence_vvma_all(void);
|
||||
|
||||
#endif
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Atish Patra <atish.patra@wdc.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_HSM_H__
|
||||
#define __SBI_HSM_H__
|
||||
|
||||
#include <sbi/sbi_hartmask.h>
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
/** Hart state managment device */
|
||||
struct sbi_hsm_device {
|
||||
/** Name of the hart state managment device */
|
||||
char name[32];
|
||||
|
||||
/** Start (or power-up) the given hart */
|
||||
int (*hart_start)(u32 hartid, ulong saddr);
|
||||
|
||||
/**
|
||||
* Stop (or power-down) the current hart from running.
|
||||
*
|
||||
* Return SBI_ENOTSUPP if the hart does not support platform-specific
|
||||
* stop actions.
|
||||
*
|
||||
* For successful stop, the call won't return.
|
||||
*/
|
||||
int (*hart_stop)(void);
|
||||
|
||||
/**
|
||||
* Put the current hart in platform specific suspend (or low-power)
|
||||
* state.
|
||||
*
|
||||
* For successful retentive suspend, the call will return 0 when
|
||||
* the hart resumes normal execution.
|
||||
*
|
||||
* For successful non-retentive suspend, the hart will resume from
|
||||
* the warm boot entry point.
|
||||
*
|
||||
* NOTE: mmode_resume_addr(resume address) is optional hence it
|
||||
* may or may not be honored by the platform. If its not honored
|
||||
* then platform must ensure to resume from the warmboot address.
|
||||
*/
|
||||
int (*hart_suspend)(u32 suspend_type, ulong mmode_resume_addr);
|
||||
|
||||
/**
|
||||
* Perform platform-specific actions to resume from a suspended state.
|
||||
*
|
||||
* This includes restoring any platform state that was lost during
|
||||
* non-retentive suspend.
|
||||
*/
|
||||
void (*hart_resume)(void);
|
||||
};
|
||||
|
||||
struct sbi_domain;
|
||||
struct sbi_scratch;
|
||||
|
||||
const struct sbi_hsm_device *sbi_hsm_get_device(void);
|
||||
|
||||
void sbi_hsm_set_device(const struct sbi_hsm_device *dev);
|
||||
|
||||
int sbi_hsm_init(struct sbi_scratch *scratch, bool cold_boot);
|
||||
void __noreturn sbi_hsm_exit(struct sbi_scratch *scratch);
|
||||
|
||||
int sbi_hsm_hart_start(struct sbi_scratch *scratch,
|
||||
const struct sbi_domain *dom,
|
||||
u32 hartid, ulong saddr, ulong smode, ulong arg1);
|
||||
int sbi_hsm_hart_stop(struct sbi_scratch *scratch, bool exitnow);
|
||||
void sbi_hsm_hart_resume_start(struct sbi_scratch *scratch);
|
||||
void __noreturn sbi_hsm_hart_resume_finish(struct sbi_scratch *scratch,
|
||||
u32 hartid);
|
||||
int sbi_hsm_hart_suspend(struct sbi_scratch *scratch, u32 suspend_type,
|
||||
ulong raddr, ulong rmode, ulong arg1);
|
||||
bool sbi_hsm_hart_change_state(struct sbi_scratch *scratch, long oldstate,
|
||||
long newstate);
|
||||
int __sbi_hsm_hart_get_state(u32 hartindex);
|
||||
int sbi_hsm_hart_get_state(const struct sbi_domain *dom, u32 hartid);
|
||||
int sbi_hsm_hart_interruptible_mask(const struct sbi_domain *dom,
|
||||
struct sbi_hartmask *mask);
|
||||
void __sbi_hsm_suspend_non_ret_save(struct sbi_scratch *scratch);
|
||||
void __noreturn sbi_hsm_hart_start_finish(struct sbi_scratch *scratch,
|
||||
u32 hartid);
|
||||
|
||||
#endif
|
@ -1,17 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 MIPS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SBI_ILLEGAL_ATOMIC_H__
|
||||
#define __SBI_ILLEGAL_ATOMIC_H__
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
struct sbi_trap_regs;
|
||||
|
||||
int sbi_illegal_atomic(ulong insn, struct sbi_trap_regs *regs);
|
||||
|
||||
#endif
|
@ -12,12 +12,11 @@
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
struct sbi_trap_context;
|
||||
struct sbi_trap_regs;
|
||||
struct sbi_scratch;
|
||||
|
||||
typedef int (*illegal_insn_func)(ulong insn, struct sbi_trap_regs *regs);
|
||||
|
||||
int truly_illegal_insn(ulong insn, struct sbi_trap_regs *regs);
|
||||
|
||||
int sbi_illegal_insn_handler(struct sbi_trap_context *tcntx);
|
||||
int sbi_illegal_insn_handler(u32 hartid, ulong mcause,
|
||||
struct sbi_trap_regs *regs,
|
||||
struct sbi_scratch *scratch);
|
||||
|
||||
#endif
|
||||
|
@ -16,12 +16,4 @@ struct sbi_scratch;
|
||||
|
||||
void __noreturn sbi_init(struct sbi_scratch *scratch);
|
||||
|
||||
void sbi_revert_entry_count(struct sbi_scratch *scratch);
|
||||
|
||||
unsigned long sbi_entry_count(u32 hartindex);
|
||||
|
||||
unsigned long sbi_init_count(u32 hartindex);
|
||||
|
||||
void __noreturn sbi_exit(struct sbi_scratch *scratch);
|
||||
|
||||
#endif
|
||||
|
@ -12,89 +12,20 @@
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#define SBI_IPI_EVENT_MAX (8 * __SIZEOF_LONG__)
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
/** IPI hardware device */
|
||||
struct sbi_ipi_device {
|
||||
/** Name of the IPI device */
|
||||
char name[32];
|
||||
|
||||
/** Send IPI to a target HART index */
|
||||
void (*ipi_send)(u32 hart_index);
|
||||
|
||||
/** Clear IPI for the current hart */
|
||||
void (*ipi_clear)(void);
|
||||
};
|
||||
|
||||
enum sbi_ipi_update_type {
|
||||
SBI_IPI_UPDATE_SUCCESS,
|
||||
SBI_IPI_UPDATE_BREAK,
|
||||
SBI_IPI_UPDATE_RETRY,
|
||||
};
|
||||
#define SBI_IPI_EVENT_SOFT 0x1
|
||||
#define SBI_IPI_EVENT_FENCE_I 0x2
|
||||
#define SBI_IPI_EVENT_SFENCE_VMA 0x4
|
||||
#define SBI_IPI_EVENT_HALT 0x8
|
||||
|
||||
struct sbi_scratch;
|
||||
|
||||
/** IPI event operations or callbacks */
|
||||
struct sbi_ipi_event_ops {
|
||||
/** Name of the IPI event operations */
|
||||
char name[32];
|
||||
int sbi_ipi_send_many(struct sbi_scratch *scratch,
|
||||
ulong *pmask, u32 event);
|
||||
|
||||
/**
|
||||
* Update callback to save/enqueue data for remote HART
|
||||
* Note: This is an optional callback and it is called just before
|
||||
* triggering IPI to remote HART.
|
||||
* @return < 0, error or failure
|
||||
* @return SBI_IPI_UPDATE_SUCCESS, success
|
||||
* @return SBI_IPI_UPDATE_BREAK, break IPI, done on local hart
|
||||
* @return SBI_IPI_UPDATE_RETRY, need retry
|
||||
*/
|
||||
int (* update)(struct sbi_scratch *scratch,
|
||||
struct sbi_scratch *remote_scratch,
|
||||
u32 remote_hartindex, void *data);
|
||||
void sbi_ipi_clear_smode(struct sbi_scratch *scratch);
|
||||
|
||||
/**
|
||||
* Sync callback to wait for remote HART
|
||||
* Note: This is an optional callback and it is called just after
|
||||
* triggering IPI to remote HART.
|
||||
*/
|
||||
void (* sync)(struct sbi_scratch *scratch);
|
||||
|
||||
/**
|
||||
* Process callback to handle IPI event
|
||||
* Note: This is a mandatory callback and it is called on the
|
||||
* remote HART after IPI is triggered.
|
||||
*/
|
||||
void (* process)(struct sbi_scratch *scratch);
|
||||
};
|
||||
|
||||
int sbi_ipi_send_many(ulong hmask, ulong hbase, u32 event, void *data);
|
||||
|
||||
int sbi_ipi_event_create(const struct sbi_ipi_event_ops *ops);
|
||||
|
||||
void sbi_ipi_event_destroy(u32 event);
|
||||
|
||||
int sbi_ipi_send_smode(ulong hmask, ulong hbase);
|
||||
|
||||
void sbi_ipi_clear_smode(void);
|
||||
|
||||
int sbi_ipi_send_halt(ulong hmask, ulong hbase);
|
||||
|
||||
void sbi_ipi_process(void);
|
||||
|
||||
int sbi_ipi_raw_send(u32 hartindex);
|
||||
|
||||
void sbi_ipi_raw_clear(void);
|
||||
|
||||
const struct sbi_ipi_device *sbi_ipi_get_device(void);
|
||||
|
||||
void sbi_ipi_set_device(const struct sbi_ipi_device *dev);
|
||||
void sbi_ipi_process(struct sbi_scratch *scratch);
|
||||
|
||||
int sbi_ipi_init(struct sbi_scratch *scratch, bool cold_boot);
|
||||
|
||||
void sbi_ipi_exit(struct sbi_scratch *scratch);
|
||||
|
||||
#endif
|
||||
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2022 Ventana Micro Systems Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Anup Patel <apatel@ventanamicro.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_IRQCHIP_H__
|
||||
#define __SBI_IRQCHIP_H__
|
||||
|
||||
#include <sbi/sbi_list.h>
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
struct sbi_scratch;
|
||||
|
||||
/** irqchip hardware device */
|
||||
struct sbi_irqchip_device {
|
||||
/** Node in the list of irqchip devices */
|
||||
struct sbi_dlist node;
|
||||
|
||||
/** Initialize per-hart state for the current hart */
|
||||
int (*warm_init)(struct sbi_irqchip_device *dev);
|
||||
|
||||
/** Handle an IRQ from this irqchip */
|
||||
int (*irq_handle)(void);
|
||||
};
|
||||
|
||||
/**
|
||||
* Process external interrupts
|
||||
*
|
||||
* This function is called by sbi_trap_handler() to handle external
|
||||
* interrupts.
|
||||
*
|
||||
* @param regs pointer for trap registers
|
||||
*/
|
||||
int sbi_irqchip_process(void);
|
||||
|
||||
/** Register an irqchip device to receive callbacks */
|
||||
void sbi_irqchip_add_device(struct sbi_irqchip_device *dev);
|
||||
|
||||
/** Initialize interrupt controllers */
|
||||
int sbi_irqchip_init(struct sbi_scratch *scratch, bool cold_boot);
|
||||
|
||||
/** Exit interrupt controllers */
|
||||
void sbi_irqchip_exit(struct sbi_scratch *scratch);
|
||||
|
||||
#endif
|
@ -1,187 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Simple doubly-linked list library.
|
||||
*
|
||||
* Adapted from Xvisor source file libs/include/libs/list.h
|
||||
*
|
||||
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Anup Patel <anup.patel@wdc.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_LIST_H__
|
||||
#define __SBI_LIST_H__
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
#define SBI_LIST_POISON_PREV 0xDEADBEEF
|
||||
#define SBI_LIST_POISON_NEXT 0xFADEBABE
|
||||
|
||||
struct sbi_dlist {
|
||||
struct sbi_dlist *next, *prev;
|
||||
};
|
||||
|
||||
#define SBI_LIST_HEAD_INIT(__lname) { &(__lname), &(__lname) }
|
||||
|
||||
#define SBI_LIST_HEAD(_lname) \
|
||||
struct sbi_dlist _lname = SBI_LIST_HEAD_INIT(_lname)
|
||||
|
||||
#define SBI_INIT_LIST_HEAD(ptr) \
|
||||
do { \
|
||||
(ptr)->next = ptr; (ptr)->prev = ptr; \
|
||||
} while (0)
|
||||
|
||||
static inline void __sbi_list_add(struct sbi_dlist *new,
|
||||
struct sbi_dlist *prev,
|
||||
struct sbi_dlist *next)
|
||||
{
|
||||
new->prev = prev;
|
||||
new->next = next;
|
||||
prev->next = new;
|
||||
next->prev = new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the list is empty or not.
|
||||
* @param head List head
|
||||
*
|
||||
* Returns true if list is empty, false otherwise.
|
||||
*/
|
||||
static inline bool sbi_list_empty(struct sbi_dlist *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the new node after the given head.
|
||||
* @param new New node that needs to be added to list.
|
||||
* @param head List head after which the "new" node should be added.
|
||||
* Note: the new node is added after the head.
|
||||
*/
|
||||
static inline void sbi_list_add(struct sbi_dlist *new, struct sbi_dlist *head)
|
||||
{
|
||||
__sbi_list_add(new, head, head->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a node at the tail where tnode points to tail node.
|
||||
* @param new The new node to be added before tail.
|
||||
* @param tnode The current tail node.
|
||||
* Note: the new node is added before tail node.
|
||||
*/
|
||||
static inline void sbi_list_add_tail(struct sbi_dlist *new,
|
||||
struct sbi_dlist *tnode)
|
||||
{
|
||||
__sbi_list_add(new, tnode->prev, tnode);
|
||||
}
|
||||
|
||||
static inline void __sbi_list_del(struct sbi_dlist *prev,
|
||||
struct sbi_dlist *next)
|
||||
{
|
||||
prev->next = next;
|
||||
next->prev = prev;
|
||||
}
|
||||
|
||||
static inline void __sbi_list_del_entry(struct sbi_dlist *entry)
|
||||
{
|
||||
__sbi_list_del(entry->prev, entry->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a given entry from list.
|
||||
* @param node Node to be deleted.
|
||||
*/
|
||||
static inline void sbi_list_del(struct sbi_dlist *entry)
|
||||
{
|
||||
__sbi_list_del(entry->prev, entry->next);
|
||||
entry->next = (void *)SBI_LIST_POISON_NEXT;
|
||||
entry->prev = (void *)SBI_LIST_POISON_PREV;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes entry from list and reinitialize it.
|
||||
* @param entry the element to delete from the list.
|
||||
*/
|
||||
static inline void sbi_list_del_init(struct sbi_dlist *entry)
|
||||
{
|
||||
__sbi_list_del_entry(entry);
|
||||
SBI_INIT_LIST_HEAD(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the struct for this entry
|
||||
* @param ptr the &struct list_head pointer.
|
||||
* @param type the type of the struct this is embedded in.
|
||||
* @param member the name of the list_struct within the struct.
|
||||
*/
|
||||
#define sbi_list_entry(ptr, type, member) \
|
||||
container_of(ptr, type, member)
|
||||
|
||||
/**
|
||||
* Get the first element from a list
|
||||
* @param ptr the list head to take the element from.
|
||||
* @param type the type of the struct this is embedded in.
|
||||
* @param member the name of the list_struct within the struct.
|
||||
*
|
||||
* Note: that list is expected to be not empty.
|
||||
*/
|
||||
#define sbi_list_first_entry(ptr, type, member) \
|
||||
sbi_list_entry((ptr)->next, type, member)
|
||||
|
||||
/**
|
||||
* Get the last element from a list
|
||||
* @param ptr the list head to take the element from.
|
||||
* @param type the type of the struct this is embedded in.
|
||||
* @param member the name of the list_head within the struct.
|
||||
*
|
||||
* Note: that list is expected to be not empty.
|
||||
*/
|
||||
#define sbi_list_last_entry(ptr, type, member) \
|
||||
sbi_list_entry((ptr)->prev, type, member)
|
||||
|
||||
/**
|
||||
* Iterate over a list
|
||||
* @param pos the &struct list_head to use as a loop cursor.
|
||||
* @param head the head for your list.
|
||||
*/
|
||||
#define sbi_list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
|
||||
/**
|
||||
* Iterate over list of given type
|
||||
* @param pos the type * to use as a loop cursor.
|
||||
* @param head the head for your list.
|
||||
* @param member the name of the list_struct within the struct.
|
||||
*/
|
||||
#define sbi_list_for_each_entry(pos, head, member) \
|
||||
for (pos = sbi_list_entry((head)->next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = sbi_list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* Iterate over list of given type safe against removal of list entry
|
||||
* @param pos the type * to use as a loop cursor.
|
||||
* @param n another type * to use as temporary storage.
|
||||
* @param head the head for your list.
|
||||
* @param member the name of the list_struct within the struct.
|
||||
*/
|
||||
#define sbi_list_for_each_entry_safe(pos, n, head, member) \
|
||||
for (pos = sbi_list_entry((head)->next, typeof(*pos), member), \
|
||||
n = sbi_list_entry(pos->member.next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = sbi_list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* Iterate over list of given type in reverse order
|
||||
* @param pos the type * to use as a loop cursor.
|
||||
* @param head the head for your list.
|
||||
* @param member the name of the list_struct within the struct.
|
||||
*/
|
||||
#define sbi_list_for_each_entry_reverse(pos, head, member) \
|
||||
for (pos = sbi_list_entry((head)->prev, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = sbi_list_entry(pos->member.prev, typeof(*pos), member))
|
||||
|
||||
#endif
|
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Atish Patra <atish.patra@wdc.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_MATH_H__
|
||||
#define __SBI_MATH_H__
|
||||
|
||||
unsigned long log2roundup(unsigned long x);
|
||||
|
||||
#endif
|
26
include/sbi/sbi_misaligned_ldst.h
Normal file
26
include/sbi/sbi_misaligned_ldst.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Anup Patel <anup.patel@wdc.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_MISALIGNED_LDST_H__
|
||||
#define __SBI_MISALIGNED_LDST_H__
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
|
||||
struct sbi_trap_regs;
|
||||
struct sbi_scratch;
|
||||
|
||||
int sbi_misaligned_load_handler(u32 hartid, ulong mcause,
|
||||
struct sbi_trap_regs *regs,
|
||||
struct sbi_scratch *scratch);
|
||||
|
||||
int sbi_misaligned_store_handler(u32 hartid, ulong mcause,
|
||||
struct sbi_trap_regs *regs,
|
||||
struct sbi_scratch *scratch);
|
||||
|
||||
#endif
|
@ -1,185 +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);
|
||||
|
||||
/** Get message proxy shared memory size */
|
||||
unsigned long sbi_mpxy_get_shmem_size(void);
|
||||
|
||||
/** Set message proxy shared memory on the calling HART */
|
||||
int sbi_mpxy_set_shmem(unsigned long shmem_phys_lo,
|
||||
unsigned long shmem_phys_hi,
|
||||
unsigned long flags);
|
||||
|
||||
/** Get channel IDs list */
|
||||
int sbi_mpxy_get_channel_ids(u32 start_index);
|
||||
|
||||
/** Read MPXY channel attributes */
|
||||
int sbi_mpxy_read_attrs(u32 channel_id, u32 base_attr_id, u32 attr_count);
|
||||
|
||||
/** Write MPXY channel attributes */
|
||||
int sbi_mpxy_write_attrs(u32 channel_id, u32 base_attr_id, u32 attr_count);
|
||||
|
||||
/**
|
||||
* Send a message over a MPXY channel.
|
||||
* In case if response is not expected, resp_data_len will be NULL.
|
||||
*/
|
||||
int sbi_mpxy_send_message(u32 channel_id, u8 msg_id,
|
||||
unsigned long msg_data_len,
|
||||
unsigned long *resp_data_len);
|
||||
|
||||
/** Get Message proxy notification events */
|
||||
int sbi_mpxy_get_notification_events(u32 channel_id,
|
||||
unsigned long *events_len);
|
||||
|
||||
#endif
|
@ -10,299 +10,157 @@
|
||||
#ifndef __SBI_PLATFORM_H__
|
||||
#define __SBI_PLATFORM_H__
|
||||
|
||||
/**
|
||||
* OpenSBI 32-bit platform version with:
|
||||
* 1. upper 16-bits as major number
|
||||
* 2. lower 16-bits as minor number
|
||||
*/
|
||||
#define SBI_PLATFORM_VERSION(Major, Minor) ((Major << 16) | Minor)
|
||||
|
||||
/** Offset of opensbi_version in struct sbi_platform */
|
||||
#define SBI_PLATFORM_OPENSBI_VERSION_OFFSET (0x00)
|
||||
/** Offset of platform_version in struct sbi_platform */
|
||||
#define SBI_PLATFORM_VERSION_OFFSET (0x04)
|
||||
/** Offset of name in struct sbi_platform */
|
||||
#define SBI_PLATFORM_NAME_OFFSET (0x08)
|
||||
#define SBI_PLATFORM_NAME_OFFSET (0x0)
|
||||
/** Offset of features in struct sbi_platform */
|
||||
#define SBI_PLATFORM_FEATURES_OFFSET (0x48)
|
||||
#define SBI_PLATFORM_FEATURES_OFFSET (0x40)
|
||||
/** Offset of hart_count in struct sbi_platform */
|
||||
#define SBI_PLATFORM_HART_COUNT_OFFSET (0x50)
|
||||
#define SBI_PLATFORM_HART_COUNT_OFFSET (0x48)
|
||||
/** Offset of hart_stack_size in struct sbi_platform */
|
||||
#define SBI_PLATFORM_HART_STACK_SIZE_OFFSET (0x54)
|
||||
/** Offset of heap_size in struct sbi_platform */
|
||||
#define SBI_PLATFORM_HEAP_SIZE_OFFSET (0x58)
|
||||
/** Offset of reserved in struct sbi_platform */
|
||||
#define SBI_PLATFORM_RESERVED_OFFSET (0x5c)
|
||||
/** Offset of platform_ops_addr in struct sbi_platform */
|
||||
#define SBI_PLATFORM_OPS_OFFSET (0x60)
|
||||
/** Offset of firmware_context in struct sbi_platform */
|
||||
#define SBI_PLATFORM_FIRMWARE_CONTEXT_OFFSET (0x60 + __SIZEOF_POINTER__)
|
||||
/** Offset of hart_index2id in struct sbi_platform */
|
||||
#define SBI_PLATFORM_HART_INDEX2ID_OFFSET (0x60 + (__SIZEOF_POINTER__ * 2))
|
||||
/** Offset of cbom_block_size in struct sbi_platform */
|
||||
#define SBI_PLATFORM_CBOM_BLOCK_SIZE_OFFSET (0x60 + (__SIZEOF_POINTER__ * 3))
|
||||
#define SBI_PLATFORM_HART_STACK_SIZE_OFFSET (0x4c)
|
||||
|
||||
#define SBI_PLATFORM_TLB_RANGE_FLUSH_LIMIT_DEFAULT (1UL << 12)
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <sbi/sbi_ecall_interface.h>
|
||||
#include <sbi/sbi_error.h>
|
||||
#include <sbi/sbi_scratch.h>
|
||||
#include <sbi/sbi_version.h>
|
||||
#include <sbi/sbi_trap_ldst.h>
|
||||
|
||||
struct sbi_domain_memregion;
|
||||
struct sbi_ecall_return;
|
||||
struct sbi_trap_regs;
|
||||
struct sbi_hart_features;
|
||||
union sbi_ldst_data;
|
||||
|
||||
/** Possible feature flags of a platform */
|
||||
enum sbi_platform_features {
|
||||
/** Platform has timer value */
|
||||
SBI_PLATFORM_HAS_TIMER_VALUE = (1 << 0),
|
||||
/** Platform has HART hotplug support */
|
||||
SBI_PLATFORM_HAS_HART_HOTPLUG = (1 << 1),
|
||||
/** Platform has PMP support */
|
||||
SBI_PLATFORM_HAS_PMP = (1 << 2),
|
||||
/** Platform has S-mode counter enable */
|
||||
SBI_PLATFORM_HAS_SCOUNTEREN = (1 << 3),
|
||||
/** Platform has M-mode counter enable */
|
||||
SBI_PLATFORM_HAS_MCOUNTEREN = (1 << 4),
|
||||
/** Platform has fault delegation support */
|
||||
SBI_PLATFORM_HAS_MFAULTS_DELEGATION = (1 << 1),
|
||||
|
||||
/** Last index of Platform features*/
|
||||
SBI_PLATFORM_HAS_LAST_FEATURE = SBI_PLATFORM_HAS_MFAULTS_DELEGATION,
|
||||
SBI_PLATFORM_HAS_MFAULTS_DELEGATION = (1 << 5),
|
||||
};
|
||||
|
||||
/** Default feature set for a platform */
|
||||
#define SBI_PLATFORM_DEFAULT_FEATURES \
|
||||
(SBI_PLATFORM_HAS_MFAULTS_DELEGATION)
|
||||
#define SBI_PLATFORM_DEFAULT_FEATURES \
|
||||
(SBI_PLATFORM_HAS_TIMER_VALUE | \
|
||||
SBI_PLATFORM_HAS_PMP | \
|
||||
SBI_PLATFORM_HAS_SCOUNTEREN | \
|
||||
SBI_PLATFORM_HAS_MCOUNTEREN | \
|
||||
SBI_PLATFORM_HAS_MFAULTS_DELEGATION)
|
||||
|
||||
/** Platform functions */
|
||||
struct sbi_platform_operations {
|
||||
/* Check if specified HART is allowed to do cold boot */
|
||||
bool (*cold_boot_allowed)(u32 hartid);
|
||||
|
||||
/* Platform nascent initialization */
|
||||
int (*nascent_init)(void);
|
||||
/** Representation of a platform */
|
||||
struct sbi_platform {
|
||||
/** Name of the platform */
|
||||
char name[64];
|
||||
/** Supported features */
|
||||
u64 features;
|
||||
/** Total number of HARTs */
|
||||
u32 hart_count;
|
||||
/** Per-HART stack size for exception/interrupt handling */
|
||||
u32 hart_stack_size;
|
||||
/** Mask representing the set of disabled HARTs */
|
||||
u64 disabled_hart_mask;
|
||||
|
||||
/** Platform early initialization */
|
||||
int (*early_init)(bool cold_boot);
|
||||
/** Platform final initialization */
|
||||
int (*final_init)(bool cold_boot);
|
||||
|
||||
/** Platform early exit */
|
||||
void (*early_exit)(void);
|
||||
/** Platform final exit */
|
||||
void (*final_exit)(void);
|
||||
|
||||
/** Get number of PMP regions for given HART */
|
||||
u32 (*pmp_region_count)(u32 hartid);
|
||||
/**
|
||||
* For platforms that do not implement misa, non-standard
|
||||
* methods are needed to determine cpu extension.
|
||||
* Get PMP regions details (namely: protection, base address,
|
||||
* and size) for given HART
|
||||
*/
|
||||
int (*misa_check_extension)(char ext);
|
||||
int (*pmp_region_info)(u32 hartid, u32 index,
|
||||
ulong *prot, ulong *addr, ulong *log2size);
|
||||
|
||||
/**
|
||||
* For platforms that do not implement misa, non-standard
|
||||
* methods are needed to get MXL field of misa.
|
||||
*/
|
||||
int (*misa_get_xlen)(void);
|
||||
/** Write a character to the platform console output */
|
||||
void (*console_putc)(char ch);
|
||||
/** Read a character from the platform console input */
|
||||
char (*console_getc)(void);
|
||||
/** Initialize the platform console */
|
||||
int (*console_init)(void);
|
||||
|
||||
/** Initialize (or populate) HART extensions for the platform */
|
||||
int (*extensions_init)(struct sbi_hart_features *hfeatures);
|
||||
/** Initialize the platform interrupt controller for current HART */
|
||||
int (*irqchip_init)(bool cold_boot);
|
||||
|
||||
/** Initialize (or populate) domains for the platform */
|
||||
int (*domains_init)(void);
|
||||
/** Send IPI to a target HART */
|
||||
void (*ipi_send)(u32 target_hart);
|
||||
/** Wait for target HART to acknowledge IPI */
|
||||
void (*ipi_sync)(u32 target_hart);
|
||||
/** Clear IPI for a target HART */
|
||||
void (*ipi_clear)(u32 target_hart);
|
||||
/** Initialize IPI for current HART */
|
||||
int (*ipi_init)(bool cold_boot);
|
||||
|
||||
/** Initialize hw performance counters */
|
||||
int (*pmu_init)(void);
|
||||
/** Get platform timer value */
|
||||
u64 (*timer_value)(void);
|
||||
/** Start platform timer event for current HART */
|
||||
void (*timer_event_start)(u64 next_event);
|
||||
/** Stop platform timer event for current HART */
|
||||
void (*timer_event_stop)(void);
|
||||
/** Initialize platform timer for current HART */
|
||||
int (*timer_init)(bool cold_boot);
|
||||
|
||||
/** Get platform specific mhpmevent value */
|
||||
uint64_t (*pmu_xlate_to_mhpmevent)(uint32_t event_idx, uint64_t data);
|
||||
|
||||
/** Initialize the platform interrupt controller during cold boot */
|
||||
int (*irqchip_init)(void);
|
||||
|
||||
/** Initialize IPI during cold boot */
|
||||
int (*ipi_init)(void);
|
||||
|
||||
/** Get tlb flush limit value **/
|
||||
u64 (*get_tlbr_flush_limit)(void);
|
||||
|
||||
/** Get tlb fifo num entries*/
|
||||
u32 (*get_tlb_num_entries)(void);
|
||||
|
||||
/** Initialize platform timer during cold boot */
|
||||
int (*timer_init)(void);
|
||||
|
||||
/** Initialize the platform Message Proxy(MPXY) driver */
|
||||
int (*mpxy_init)(void);
|
||||
|
||||
/** platform specific SBI extension implementation provider */
|
||||
int (*vendor_ext_provider)(long funcid,
|
||||
struct sbi_trap_regs *regs,
|
||||
struct sbi_ecall_return *out);
|
||||
|
||||
/** platform specific handler to fixup load fault */
|
||||
int (*emulate_load)(int rlen, unsigned long addr,
|
||||
union sbi_ldst_data *out_val);
|
||||
/** platform specific handler to fixup store fault */
|
||||
int (*emulate_store)(int wlen, unsigned long addr,
|
||||
union sbi_ldst_data in_val);
|
||||
|
||||
/** platform specific pmp setup on current HART */
|
||||
void (*pmp_set)(unsigned int n, unsigned long flags,
|
||||
unsigned long prot, unsigned long addr,
|
||||
unsigned long log2len);
|
||||
/** platform specific pmp disable on current HART */
|
||||
void (*pmp_disable)(unsigned int n);
|
||||
};
|
||||
|
||||
/** Platform default per-HART stack size for exception/interrupt handling */
|
||||
#define SBI_PLATFORM_DEFAULT_HART_STACK_SIZE 8192
|
||||
|
||||
/** Platform default heap size */
|
||||
#define SBI_PLATFORM_DEFAULT_HEAP_SIZE(__num_hart) \
|
||||
(0x8000 + 0x1000 * (__num_hart))
|
||||
|
||||
/** Representation of a platform */
|
||||
struct sbi_platform {
|
||||
/**
|
||||
* OpenSBI version this sbi_platform is based on.
|
||||
* It's a 32-bit value where upper 16-bits are major number
|
||||
* and lower 16-bits are minor number
|
||||
*/
|
||||
u32 opensbi_version;
|
||||
/**
|
||||
* OpenSBI platform version released by vendor.
|
||||
* It's a 32-bit value where upper 16-bits are major number
|
||||
* and lower 16-bits are minor number
|
||||
*/
|
||||
u32 platform_version;
|
||||
/** Name of the platform */
|
||||
char name[64];
|
||||
/** Supported features */
|
||||
u64 features;
|
||||
/** Total number of HARTs (at most SBI_HARTMASK_MAX_BITS) */
|
||||
u32 hart_count;
|
||||
/** Per-HART stack size for exception/interrupt handling */
|
||||
u32 hart_stack_size;
|
||||
/** Size of heap shared by all HARTs */
|
||||
u32 heap_size;
|
||||
/** Reserved for future use */
|
||||
u32 reserved;
|
||||
/** Pointer to sbi platform operations */
|
||||
unsigned long platform_ops_addr;
|
||||
/** Pointer to system firmware specific context */
|
||||
unsigned long firmware_context;
|
||||
/**
|
||||
* HART index to HART id table
|
||||
*
|
||||
* If hart_index2id != NULL then the table must contain a mapping
|
||||
* for each HART index 0 <= <abc> < hart_count:
|
||||
* hart_index2id[<abc>] = some HART id
|
||||
*
|
||||
* If hart_index2id == NULL then we assume identity mapping
|
||||
* hart_index2id[<abc>] = <abc>
|
||||
*/
|
||||
const u32 *hart_index2id;
|
||||
/** Allocation alignment for Scratch */
|
||||
unsigned long cbom_block_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Prevent modification of struct sbi_platform from affecting
|
||||
* SBI_PLATFORM_xxx_OFFSET
|
||||
*/
|
||||
assert_member_offset(struct sbi_platform, opensbi_version, SBI_PLATFORM_OPENSBI_VERSION_OFFSET);
|
||||
assert_member_offset(struct sbi_platform, platform_version, SBI_PLATFORM_VERSION_OFFSET);
|
||||
assert_member_offset(struct sbi_platform, name, SBI_PLATFORM_NAME_OFFSET);
|
||||
assert_member_offset(struct sbi_platform, features, SBI_PLATFORM_FEATURES_OFFSET);
|
||||
assert_member_offset(struct sbi_platform, hart_count, SBI_PLATFORM_HART_COUNT_OFFSET);
|
||||
assert_member_offset(struct sbi_platform, hart_stack_size, SBI_PLATFORM_HART_STACK_SIZE_OFFSET);
|
||||
assert_member_offset(struct sbi_platform, heap_size, SBI_PLATFORM_HEAP_SIZE_OFFSET);
|
||||
assert_member_offset(struct sbi_platform, reserved, SBI_PLATFORM_RESERVED_OFFSET);
|
||||
assert_member_offset(struct sbi_platform, platform_ops_addr, SBI_PLATFORM_OPS_OFFSET);
|
||||
assert_member_offset(struct sbi_platform, firmware_context, SBI_PLATFORM_FIRMWARE_CONTEXT_OFFSET);
|
||||
assert_member_offset(struct sbi_platform, hart_index2id, SBI_PLATFORM_HART_INDEX2ID_OFFSET);
|
||||
assert_member_offset(struct sbi_platform, cbom_block_size, SBI_PLATFORM_CBOM_BLOCK_SIZE_OFFSET);
|
||||
/** Reboot the platform */
|
||||
int (*system_reboot)(u32 type);
|
||||
/** Shutdown or poweroff the platform */
|
||||
int (*system_shutdown)(u32 type);
|
||||
} __packed;
|
||||
|
||||
/** Get pointer to sbi_platform for sbi_scratch pointer */
|
||||
#define sbi_platform_ptr(__s) \
|
||||
((const struct sbi_platform *)((__s)->platform_addr))
|
||||
#define sbi_platform_ptr(__s) \
|
||||
((struct sbi_platform *)((__s)->platform_addr))
|
||||
/** Get pointer to sbi_platform for current HART */
|
||||
#define sbi_platform_thishart_ptr() ((const struct sbi_platform *) \
|
||||
(sbi_scratch_thishart_ptr()->platform_addr))
|
||||
/** Get pointer to platform_ops_addr from platform pointer **/
|
||||
#define sbi_platform_ops(__p) \
|
||||
((const struct sbi_platform_operations *)(__p)->platform_ops_addr)
|
||||
|
||||
#define sbi_platform_thishart_ptr() \
|
||||
((struct sbi_platform *)(sbi_scratch_thishart_ptr()->platform_addr))
|
||||
/** Check whether the platform supports timer value */
|
||||
#define sbi_platform_has_timer_value(__p) \
|
||||
((__p)->features & SBI_PLATFORM_HAS_TIMER_VALUE)
|
||||
/** Check whether the platform supports HART hotplug */
|
||||
#define sbi_platform_has_hart_hotplug(__p) \
|
||||
((__p)->features & SBI_PLATFORM_HAS_HART_HOTPLUG)
|
||||
/** Check whether the platform has PMP support */
|
||||
#define sbi_platform_has_pmp(__p) \
|
||||
((__p)->features & SBI_PLATFORM_HAS_PMP)
|
||||
/** Check whether the platform supports scounteren CSR */
|
||||
#define sbi_platform_has_scounteren(__p) \
|
||||
((__p)->features & SBI_PLATFORM_HAS_SCOUNTEREN)
|
||||
/** Check whether the platform supports mcounteren CSR */
|
||||
#define sbi_platform_has_mcounteren(__p) \
|
||||
((__p)->features & SBI_PLATFORM_HAS_MCOUNTEREN)
|
||||
/** Check whether the platform supports fault delegation */
|
||||
#define sbi_platform_has_mfaults_delegation(__p) \
|
||||
#define sbi_platform_has_mfaults_delegation(__p) \
|
||||
((__p)->features & SBI_PLATFORM_HAS_MFAULTS_DELEGATION)
|
||||
|
||||
/**
|
||||
* Get the platform features in string format
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param features_str pointer to a char array where the features string will be
|
||||
* updated
|
||||
* @param nfstr length of the features_str. The feature string will be truncated
|
||||
* if nfstr is not long enough.
|
||||
*/
|
||||
void sbi_platform_get_features_str(const struct sbi_platform *plat,
|
||||
char *features_str, int nfstr);
|
||||
|
||||
/**
|
||||
* Get name of the platform
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
*
|
||||
* @return pointer to platform name on success and "Unknown" on failure
|
||||
* @return pointer to platform name on success and NULL on failure
|
||||
*/
|
||||
static inline const char *sbi_platform_name(const struct sbi_platform *plat)
|
||||
static inline const char *sbi_platform_name(struct sbi_platform *plat)
|
||||
{
|
||||
if (plat)
|
||||
return plat->name;
|
||||
return "Unknown";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the platform features
|
||||
* Check whether the given HART is disabled
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param hartid HART ID
|
||||
*
|
||||
* @return the features value currently set for the given platform
|
||||
* @return TRUE if HART is disabled and FALSE otherwise
|
||||
*/
|
||||
static inline unsigned long sbi_platform_get_features(
|
||||
const struct sbi_platform *plat)
|
||||
static inline bool sbi_platform_hart_disabled(struct sbi_platform *plat,
|
||||
u32 hartid)
|
||||
{
|
||||
if (plat)
|
||||
return plat->features;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get platform specific tlb range flush maximum value. Any request with size
|
||||
* higher than this is upgraded to a full flush.
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
*
|
||||
* @return tlb range flush limit value. Returns a default (page size) if not
|
||||
* defined by platform.
|
||||
*/
|
||||
static inline u64 sbi_platform_tlbr_flush_limit(const struct sbi_platform *plat)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->get_tlbr_flush_limit)
|
||||
return sbi_platform_ops(plat)->get_tlbr_flush_limit();
|
||||
return SBI_PLATFORM_TLB_RANGE_FLUSH_LIMIT_DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get platform specific tlb fifo num entries.
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
*
|
||||
* @return number of tlb fifo entries
|
||||
*/
|
||||
static inline u32 sbi_platform_tlb_fifo_num_entries(const struct sbi_platform *plat)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->get_tlb_num_entries)
|
||||
return sbi_platform_ops(plat)->get_tlb_num_entries();
|
||||
return sbi_hart_count();
|
||||
if (plat && (plat->disabled_hart_mask & (1 << hartid)))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -312,7 +170,7 @@ static inline u32 sbi_platform_tlb_fifo_num_entries(const struct sbi_platform *p
|
||||
*
|
||||
* @return total number of HARTs
|
||||
*/
|
||||
static inline u32 sbi_platform_hart_count(const struct sbi_platform *plat)
|
||||
static inline u32 sbi_platform_hart_count(struct sbi_platform *plat)
|
||||
{
|
||||
if (plat)
|
||||
return plat->hart_count;
|
||||
@ -326,60 +184,26 @@ static inline u32 sbi_platform_hart_count(const struct sbi_platform *plat)
|
||||
*
|
||||
* @return stack size in bytes
|
||||
*/
|
||||
static inline u32 sbi_platform_hart_stack_size(const struct sbi_platform *plat)
|
||||
static inline u32 sbi_platform_hart_stack_size(struct sbi_platform *plat)
|
||||
{
|
||||
if (plat)
|
||||
return plat->hart_stack_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether given HART is allowed to do cold boot
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param hartid HART ID
|
||||
*
|
||||
* @return true if HART is allowed to do cold boot and false otherwise
|
||||
*/
|
||||
static inline bool sbi_platform_cold_boot_allowed(
|
||||
const struct sbi_platform *plat,
|
||||
u32 hartid)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->cold_boot_allowed)
|
||||
return sbi_platform_ops(plat)->cold_boot_allowed(hartid);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nascent (very early) initialization for current HART
|
||||
*
|
||||
* NOTE: This function can be used to do very early initialization of
|
||||
* platform specific per-HART CSRs and devices.
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
*
|
||||
* @return 0 on success and negative error code on failure
|
||||
*/
|
||||
static inline int sbi_platform_nascent_init(const struct sbi_platform *plat)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->nascent_init)
|
||||
return sbi_platform_ops(plat)->nascent_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Early initialization for current HART
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param cold_boot whether cold boot (true) or warm_boot (false)
|
||||
* @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE)
|
||||
*
|
||||
* @return 0 on success and negative error code on failure
|
||||
*/
|
||||
static inline int sbi_platform_early_init(const struct sbi_platform *plat,
|
||||
static inline int sbi_platform_early_init(struct sbi_platform *plat,
|
||||
bool cold_boot)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->early_init)
|
||||
return sbi_platform_ops(plat)->early_init(cold_boot);
|
||||
if (plat && plat->early_init)
|
||||
return plat->early_init(cold_boot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -387,302 +211,256 @@ static inline int sbi_platform_early_init(const struct sbi_platform *plat,
|
||||
* Final initialization for current HART
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param cold_boot whether cold boot (true) or warm_boot (false)
|
||||
* @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE)
|
||||
*
|
||||
* @return 0 on success and negative error code on failure
|
||||
*/
|
||||
static inline int sbi_platform_final_init(const struct sbi_platform *plat,
|
||||
static inline int sbi_platform_final_init(struct sbi_platform *plat,
|
||||
bool cold_boot)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->final_init)
|
||||
return sbi_platform_ops(plat)->final_init(cold_boot);
|
||||
if (plat && plat->final_init)
|
||||
return plat->final_init(cold_boot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Early exit for current HART
|
||||
* Get the number of PMP regions of a HART
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
*/
|
||||
static inline void sbi_platform_early_exit(const struct sbi_platform *plat)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->early_exit)
|
||||
sbi_platform_ops(plat)->early_exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Final exit for current HART
|
||||
* @param hartid HART ID
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @return number of PMP regions
|
||||
*/
|
||||
static inline void sbi_platform_final_exit(const struct sbi_platform *plat)
|
||||
static inline u32 sbi_platform_pmp_region_count(struct sbi_platform *plat,
|
||||
u32 hartid)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->final_exit)
|
||||
sbi_platform_ops(plat)->final_exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check CPU extension in MISA
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param ext shorthand letter for CPU extensions
|
||||
*
|
||||
* @return zero for not-supported and non-zero for supported
|
||||
*/
|
||||
static inline int sbi_platform_misa_extension(const struct sbi_platform *plat,
|
||||
char ext)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->misa_check_extension)
|
||||
return sbi_platform_ops(plat)->misa_check_extension(ext);
|
||||
if (plat && plat->pmp_region_count)
|
||||
return plat->pmp_region_count(hartid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get MXL field of MISA
|
||||
* Get PMP regions details (namely: protection, base address,
|
||||
* and size) of a HART
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param hartid HART ID
|
||||
* @param index index of PMP region for which we want details
|
||||
* @param prot output pointer for PMP region protection
|
||||
* @param addr output pointer for PMP region base address
|
||||
* @param log2size output pointer for log-of-2 PMP region size
|
||||
*
|
||||
* @return 1/2/3 on success and error code on failure
|
||||
* @return 0 on success and negative error code on failure
|
||||
*/
|
||||
static inline int sbi_platform_misa_xlen(const struct sbi_platform *plat)
|
||||
static inline int sbi_platform_pmp_region_info(struct sbi_platform *plat,
|
||||
u32 hartid, u32 index,
|
||||
ulong *prot, ulong *addr,
|
||||
ulong *log2size)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->misa_get_xlen)
|
||||
return sbi_platform_ops(plat)->misa_get_xlen();
|
||||
return -1;
|
||||
if (plat && plat->pmp_region_info)
|
||||
return plat->pmp_region_info(hartid, index,
|
||||
prot, addr, log2size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize (or populate) HART extensions for the platform
|
||||
* Write a character to the platform console output
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param ch character to write
|
||||
*/
|
||||
static inline void sbi_platform_console_putc(struct sbi_platform *plat,
|
||||
char ch)
|
||||
{
|
||||
if (plat && plat->console_putc)
|
||||
plat->console_putc(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a character from the platform console input
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
*
|
||||
* @return character read from console input
|
||||
*/
|
||||
static inline char sbi_platform_console_getc(struct sbi_platform *plat)
|
||||
{
|
||||
if (plat && plat->console_getc)
|
||||
return plat->console_getc();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the platform console
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
*
|
||||
* @return 0 on success and negative error code on failure
|
||||
*/
|
||||
static inline int sbi_platform_extensions_init(
|
||||
const struct sbi_platform *plat,
|
||||
struct sbi_hart_features *hfeatures)
|
||||
static inline int sbi_platform_console_init(struct sbi_platform *plat)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->extensions_init)
|
||||
return sbi_platform_ops(plat)->extensions_init(hfeatures);
|
||||
if (plat && plat->console_init)
|
||||
return plat->console_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize (or populate) domains for the platform
|
||||
* Initialize the platform interrupt controller for current HART
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE)
|
||||
*
|
||||
* @return 0 on success and negative error code on failure
|
||||
*/
|
||||
static inline int sbi_platform_domains_init(const struct sbi_platform *plat)
|
||||
static inline int sbi_platform_irqchip_init(struct sbi_platform *plat,
|
||||
bool cold_boot)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->domains_init)
|
||||
return sbi_platform_ops(plat)->domains_init();
|
||||
if (plat && plat->irqchip_init)
|
||||
return plat->irqchip_init(cold_boot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup hw PMU events for the platform
|
||||
* Send IPI to a target HART
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param target_hart HART ID of IPI target
|
||||
*/
|
||||
static inline void sbi_platform_ipi_send(struct sbi_platform *plat,
|
||||
u32 target_hart)
|
||||
{
|
||||
if (plat && plat->ipi_send)
|
||||
plat->ipi_send(target_hart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for target HART to acknowledge IPI
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param target_hart HART ID of IPI target
|
||||
*/
|
||||
static inline void sbi_platform_ipi_sync(struct sbi_platform *plat,
|
||||
u32 target_hart)
|
||||
{
|
||||
if (plat && plat->ipi_sync)
|
||||
plat->ipi_sync(target_hart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear IPI for a target HART
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param target_hart HART ID of IPI target
|
||||
*/
|
||||
static inline void sbi_platform_ipi_clear(struct sbi_platform *plat,
|
||||
u32 target_hart)
|
||||
{
|
||||
if (plat && plat->ipi_clear)
|
||||
plat->ipi_clear(target_hart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the platform IPI support for current HART
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE)
|
||||
*
|
||||
* @return 0 on success and negative error code on failure
|
||||
*/
|
||||
static inline int sbi_platform_pmu_init(const struct sbi_platform *plat)
|
||||
static inline int sbi_platform_ipi_init(struct sbi_platform *plat,
|
||||
bool cold_boot)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->pmu_init)
|
||||
return sbi_platform_ops(plat)->pmu_init();
|
||||
if (plat && plat->ipi_init)
|
||||
return plat->ipi_init(cold_boot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value to be written in mhpmeventx for event_idx
|
||||
* Get platform timer value
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param event_idx ID of the PMU event
|
||||
* @param data Additional configuration data passed from supervisor software
|
||||
*
|
||||
* @return expected value by the platform or 0 if platform doesn't know about
|
||||
* the event
|
||||
* @return 64bit timer value
|
||||
*/
|
||||
static inline uint64_t sbi_platform_pmu_xlate_to_mhpmevent(const struct sbi_platform *plat,
|
||||
uint32_t event_idx, uint64_t data)
|
||||
static inline u64 sbi_platform_timer_value(struct sbi_platform *plat)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->pmu_xlate_to_mhpmevent)
|
||||
return sbi_platform_ops(plat)->pmu_xlate_to_mhpmevent(event_idx,
|
||||
data);
|
||||
if (plat && plat->timer_value)
|
||||
return plat->timer_value();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the platform interrupt controller during cold boot
|
||||
* Start platform timer event for current HART
|
||||
*
|
||||
* @param plat pointer to struct struct sbi_platform
|
||||
* @param next_event timer value when timer event will happen
|
||||
*/
|
||||
static inline void sbi_platform_timer_event_start(struct sbi_platform *plat,
|
||||
u64 next_event)
|
||||
{
|
||||
if (plat && plat->timer_event_start)
|
||||
plat->timer_event_start(next_event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop platform timer event for current HART
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
*/
|
||||
static inline void sbi_platform_timer_event_stop(struct sbi_platform *plat)
|
||||
{
|
||||
if (plat && plat->timer_event_stop)
|
||||
plat->timer_event_stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the platform timer for current HART
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE)
|
||||
*
|
||||
* @return 0 on success and negative error code on failure
|
||||
*/
|
||||
static inline int sbi_platform_irqchip_init(const struct sbi_platform *plat)
|
||||
static inline int sbi_platform_timer_init(struct sbi_platform *plat,
|
||||
bool cold_boot)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->irqchip_init)
|
||||
return sbi_platform_ops(plat)->irqchip_init();
|
||||
if (plat && plat->timer_init)
|
||||
return plat->timer_init(cold_boot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the platform IPI support during cold boot
|
||||
* Reboot the platform
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param type type of reboot
|
||||
*
|
||||
* @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_system_reboot(struct sbi_platform *plat,
|
||||
u32 type)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->ipi_init)
|
||||
return sbi_platform_ops(plat)->ipi_init();
|
||||
if (plat && plat->system_reboot)
|
||||
return plat->system_reboot(type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the platform timer during cold boot
|
||||
* Shutdown or poweroff the platform
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param type type of shutdown or poweroff
|
||||
*
|
||||
* @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_system_shutdown(struct sbi_platform *plat,
|
||||
u32 type)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->timer_init)
|
||||
return sbi_platform_ops(plat)->timer_init();
|
||||
if (plat && plat->system_shutdown)
|
||||
return plat->system_shutdown(type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the platform Message Proxy drivers
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
*
|
||||
* @return 0 on success and negative error code on failure
|
||||
*/
|
||||
static inline int sbi_platform_mpxy_init(const struct sbi_platform *plat)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->mpxy_init)
|
||||
return sbi_platform_ops(plat)->mpxy_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if SBI vendor extension is implemented or not.
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
*
|
||||
* @return false if not implemented and true if implemented
|
||||
*/
|
||||
static inline bool sbi_platform_vendor_ext_check(
|
||||
const struct sbi_platform *plat)
|
||||
{
|
||||
return plat && sbi_platform_ops(plat)->vendor_ext_provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke platform specific vendor SBI extension implementation.
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param funcid SBI function id within the extension id
|
||||
* @param regs pointer to trap registers passed by the caller
|
||||
* @param out_value output value that can be filled by the callee
|
||||
* @param out_trap trap info that can be filled by the callee
|
||||
*
|
||||
* @return 0 on success and negative error code on failure
|
||||
*/
|
||||
static inline int sbi_platform_vendor_ext_provider(
|
||||
const struct sbi_platform *plat,
|
||||
long funcid,
|
||||
struct sbi_trap_regs *regs,
|
||||
struct sbi_ecall_return *out)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->vendor_ext_provider)
|
||||
return sbi_platform_ops(plat)->vendor_ext_provider(funcid,
|
||||
regs, out);
|
||||
|
||||
return SBI_ENOTSUPP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask platform to emulate the trapped load
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param rlen length of the load: 1/2/4/8...
|
||||
* @param addr virtual address of the load. Platform needs to page-walk and
|
||||
* find the physical address if necessary
|
||||
* @param out_val value loaded
|
||||
*
|
||||
* @return 0 on success and negative error code on failure
|
||||
*/
|
||||
static inline int sbi_platform_emulate_load(const struct sbi_platform *plat,
|
||||
int rlen, unsigned long addr,
|
||||
union sbi_ldst_data *out_val)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->emulate_load) {
|
||||
return sbi_platform_ops(plat)->emulate_load(rlen, addr,
|
||||
out_val);
|
||||
}
|
||||
return SBI_ENOTSUPP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask platform to emulate the trapped store
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param wlen length of the store: 1/2/4/8...
|
||||
* @param addr virtual address of the store. Platform needs to page-walk and
|
||||
* find the physical address if necessary
|
||||
* @param in_val value to store
|
||||
*
|
||||
* @return 0 on success and negative error code on failure
|
||||
*/
|
||||
static inline int sbi_platform_emulate_store(const struct sbi_platform *plat,
|
||||
int wlen, unsigned long addr,
|
||||
union sbi_ldst_data in_val)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->emulate_store) {
|
||||
return sbi_platform_ops(plat)->emulate_store(wlen, addr,
|
||||
in_val);
|
||||
}
|
||||
return SBI_ENOTSUPP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Platform specific PMP setup on current HART
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param n index of the pmp entry
|
||||
* @param flags domain memregion flags
|
||||
* @param prot attribute of the pmp entry
|
||||
* @param addr address of the pmp entry
|
||||
* @param log2len size of the pmp entry as power-of-2
|
||||
*/
|
||||
static inline void sbi_platform_pmp_set(const struct sbi_platform *plat,
|
||||
unsigned int n, unsigned long flags,
|
||||
unsigned long prot, unsigned long addr,
|
||||
unsigned long log2len)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->pmp_set)
|
||||
sbi_platform_ops(plat)->pmp_set(n, flags, prot, addr, log2len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Platform specific PMP disable on current HART
|
||||
*
|
||||
* @param plat pointer to struct sbi_platform
|
||||
* @param n index of the pmp entry
|
||||
*/
|
||||
static inline void sbi_platform_pmp_disable(const struct sbi_platform *plat,
|
||||
unsigned int n)
|
||||
{
|
||||
if (plat && sbi_platform_ops(plat)->pmp_disable)
|
||||
sbi_platform_ops(plat)->pmp_disable(n);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,161 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2021 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Atish Patra <atish.patra@wdc.com>
|
||||
*/
|
||||
|
||||
#ifndef __SBI_PMU_H__
|
||||
#define __SBI_PMU_H__
|
||||
|
||||
#include <sbi/sbi_types.h>
|
||||
#include <sbi/sbi_trap.h>
|
||||
|
||||
struct sbi_scratch;
|
||||
|
||||
/* Event related macros */
|
||||
/* Maximum number of hardware events that can mapped by OpenSBI */
|
||||
#define SBI_PMU_HW_EVENT_MAX 256
|
||||
|
||||
/* Counter related macros */
|
||||
#define SBI_PMU_FW_CTR_MAX 16
|
||||
#define SBI_PMU_HW_CTR_MAX 32
|
||||
#define SBI_PMU_CTR_MAX (SBI_PMU_HW_CTR_MAX + SBI_PMU_FW_CTR_MAX)
|
||||
#define SBI_PMU_FIXED_CTR_MASK 0x07
|
||||
#define SBI_PMU_CY_IR_MASK 0x05
|
||||
|
||||
struct sbi_pmu_device {
|
||||
/** Name of the PMU platform device */
|
||||
char name[32];
|
||||
|
||||
/**
|
||||
* Validate event code of custom firmware event
|
||||
*/
|
||||
int (*fw_event_validate_encoding)(uint32_t hartid, uint64_t event_data);
|
||||
|
||||
/**
|
||||
* Match custom firmware counter with custom firmware event
|
||||
* Note: 0 <= counter_index < SBI_PMU_FW_CTR_MAX
|
||||
*/
|
||||
bool (*fw_counter_match_encoding)(uint32_t hartid,
|
||||
uint32_t counter_index,
|
||||
uint64_t event_data);
|
||||
|
||||
/**
|
||||
* Fetch the max width of this counter in number of bits.
|
||||
*/
|
||||
int (*fw_counter_width)(void);
|
||||
|
||||
/**
|
||||
* Read value of custom firmware counter
|
||||
* Note: 0 <= counter_index < SBI_PMU_FW_CTR_MAX
|
||||
*/
|
||||
uint64_t (*fw_counter_read_value)(uint32_t hartid,
|
||||
uint32_t counter_index);
|
||||
|
||||
/**
|
||||
* Write value to custom firmware counter
|
||||
* Note: 0 <= counter_index < SBI_PMU_FW_CTR_MAX
|
||||
*/
|
||||
void (*fw_counter_write_value)(uint32_t hartid, uint32_t counter_index,
|
||||
uint64_t value);
|
||||
|
||||
/**
|
||||
* Start custom firmware counter
|
||||
* Note: 0 <= counter_index < SBI_PMU_FW_CTR_MAX
|
||||
*/
|
||||
int (*fw_counter_start)(uint32_t hartid, uint32_t counter_index,
|
||||
uint64_t event_data);
|
||||
|
||||
/**
|
||||
* Stop custom firmware counter
|
||||
* Note: 0 <= counter_index < SBI_PMU_FW_CTR_MAX
|
||||
*/
|
||||
int (*fw_counter_stop)(uint32_t hartid, uint32_t counter_index);
|
||||
|
||||
/**
|
||||
* Custom enable irq for hardware counter
|
||||
* Note: 0 <= counter_index < SBI_PMU_HW_CTR_MAX
|
||||
*/
|
||||
void (*hw_counter_enable_irq)(uint32_t counter_index);
|
||||
|
||||
/**
|
||||
* Custom disable irq for hardware counter
|
||||
* Note: 0 <= counter_index < SBI_PMU_HW_CTR_MAX
|
||||
*/
|
||||
void (*hw_counter_disable_irq)(uint32_t counter_index);
|
||||
|
||||
/**
|
||||
* Custom function returning the machine-specific irq-bit.
|
||||
*/
|
||||
int (*hw_counter_irq_bit)(void);
|
||||
|
||||
/**
|
||||
* Custom function to inhibit counting of events while in
|
||||
* specified mode.
|
||||
*/
|
||||
void (*hw_counter_filter_mode)(unsigned long flags, int counter_index);
|
||||
};
|
||||
|
||||
/** Get the PMU platform device */
|
||||
const struct sbi_pmu_device *sbi_pmu_get_device(void);
|
||||
|
||||
/** Set the PMU platform device */
|
||||
void sbi_pmu_set_device(const struct sbi_pmu_device *dev);
|
||||
|
||||
/** Initialize PMU */
|
||||
int sbi_pmu_init(struct sbi_scratch *scratch, bool cold_boot);
|
||||
|
||||
/** Reset PMU during hart exit */
|
||||
void sbi_pmu_exit(struct sbi_scratch *scratch);
|
||||
|
||||
/** Return the pmu irq bit depending on extension existence */
|
||||
int sbi_pmu_irq_bit(void);
|
||||
|
||||
/** Return the pmu irq mask or 0 if the pmu overflow irq is not supported */
|
||||
unsigned long sbi_pmu_irq_mask(void);
|
||||
|
||||
/**
|
||||
* Add the hardware event to counter mapping information. This should be called
|
||||
* from the platform code to update the mapping table.
|
||||
* @param eidx_start Start of the event idx range for supported counters
|
||||
* @param eidx_end End of the event idx range for supported counters
|
||||
* @param cmap A bitmap representing counters supporting the event range
|
||||
* @return 0 on success, error otherwise.
|
||||
*/
|
||||
int sbi_pmu_add_hw_event_counter_map(u32 eidx_start, u32 eidx_end, u32 cmap);
|
||||
|
||||
/**
|
||||
* Add the raw hardware event selector and supported counter information. This
|
||||
* should be called from the platform code to update the mapping table.
|
||||
* @param info a pointer to the hardware event info
|
||||
* @return 0 on success, error otherwise.
|
||||
*/
|
||||
|
||||
int sbi_pmu_add_raw_event_counter_map(uint64_t select, uint64_t select_mask, u32 cmap);
|
||||
|
||||
int sbi_pmu_ctr_fw_read(uint32_t cidx, uint64_t *cval);
|
||||
|
||||
int sbi_pmu_ctr_stop(unsigned long cidx_base, unsigned long cidx_mask,
|
||||
unsigned long flag);
|
||||
|
||||
int sbi_pmu_ctr_start(unsigned long cidx_base, unsigned long cidx_mask,
|
||||
unsigned long flags, uint64_t ival);
|
||||
|
||||
int sbi_pmu_ctr_get_info(uint32_t cidx, unsigned long *ctr_info);
|
||||
int sbi_pmu_event_get_info(unsigned long shmem_lo, unsigned long shmem_high,
|
||||
unsigned long num_events, unsigned long flags);
|
||||
|
||||
unsigned long sbi_pmu_num_ctr(void);
|
||||
|
||||
int sbi_pmu_ctr_cfg_match(unsigned long cidx_base, unsigned long cidx_mask,
|
||||
unsigned long flags, unsigned long event_idx,
|
||||
uint64_t event_data);
|
||||
|
||||
int sbi_pmu_ctr_incr_fw(enum sbi_pmu_fw_event_code_id fw_id);
|
||||
|
||||
void sbi_pmu_ovf_irq();
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user