mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2025-08-24 23:41:23 +01:00
Compare commits
50 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a1ffba1ac9 | ||
![]() |
d022c5d3ae | ||
![]() |
889e746fd7 | ||
![]() |
fde1c42db3 | ||
![]() |
122d00ba67 | ||
![]() |
ce6189f7a5 | ||
![]() |
db5b25af49 | ||
![]() |
72a8272066 | ||
![]() |
4b92518959 | ||
![]() |
d046974cf6 | ||
![]() |
0db43770b3 | ||
![]() |
3265310b05 | ||
![]() |
34bf6d4a0f | ||
![]() |
6a3dc84f66 | ||
![]() |
f4a17177ce | ||
![]() |
4e774f5470 | ||
![]() |
148423d141 | ||
![]() |
918c1354b7 | ||
![]() |
51e543511a | ||
![]() |
b44878b773 | ||
![]() |
16426420b5 | ||
![]() |
3c53950b00 | ||
![]() |
868e20df8b | ||
![]() |
5cd69a496b | ||
![]() |
ae4e0de700 | ||
![]() |
afbb0cdf80 | ||
![]() |
d369e721e8 | ||
![]() |
286b80768b | ||
![]() |
35e617385f | ||
![]() |
28d1dd2430 | ||
![]() |
70a474d2c2 | ||
![]() |
4cb4d46875 | ||
![]() |
c5467fce46 | ||
![]() |
84169e2e69 | ||
![]() |
ab12d6ef8f | ||
![]() |
01fe779113 | ||
![]() |
b1b7e49c63 | ||
![]() |
7b3da0ef0d | ||
![]() |
76c759df6a | ||
![]() |
4f32b13802 | ||
![]() |
f9b033e577 | ||
![]() |
f4cf6da7ff | ||
![]() |
9f44d07df5 | ||
![]() |
a5f06b30c1 | ||
![]() |
5a91fec1a8 | ||
![]() |
b4c72deba9 | ||
![]() |
93f806af32 | ||
![]() |
190a80dc40 | ||
![]() |
9a72e5006c | ||
![]() |
c0addfe751 |
108
Makefile
108
Makefile
@@ -8,9 +8,9 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
# Select Make Options:
|
# Select Make Options:
|
||||||
# o Do not use make's built-in rules and variables
|
# o Do not use make's built-in rules
|
||||||
# o Do not print "Entering directory ...";
|
# o Do not print "Entering directory ...";
|
||||||
MAKEFLAGS += -rR --no-print-directory
|
MAKEFLAGS += -r --no-print-directory
|
||||||
|
|
||||||
# Find out source, build, and install directories
|
# Find out source, build, and install directories
|
||||||
src_dir=$(CURDIR)
|
src_dir=$(CURDIR)
|
||||||
@@ -51,8 +51,28 @@ export lib_dir=$(CURDIR)/lib
|
|||||||
export firmware_dir=$(CURDIR)/firmware
|
export firmware_dir=$(CURDIR)/firmware
|
||||||
|
|
||||||
# Find library version
|
# Find library version
|
||||||
OPENSBI_VERSION_MAJOR=`grep MAJOR $(include_dir)/sbi/sbi_version.h | awk '{ print $$3 }'`
|
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 | awk '{ print $$3 }'`
|
OPENSBI_VERSION_MINOR=`grep MINOR $(include_dir)/sbi/sbi_version.h | sed 's/.*MINOR.*\([0-9][0-9]*\)/\1/'`
|
||||||
|
|
||||||
|
# Setup compilation commands
|
||||||
|
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
|
||||||
|
AS = $(CC)
|
||||||
|
DTC = dtc
|
||||||
|
|
||||||
|
# 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
|
# Setup list of objects.mk files
|
||||||
ifdef PLATFORM
|
ifdef PLATFORM
|
||||||
@@ -92,6 +112,29 @@ deps-y+=$(platform-common-objs-path-y:.o=.dep)
|
|||||||
deps-y+=$(lib-objs-path-y:.o=.dep)
|
deps-y+=$(lib-objs-path-y:.o=.dep)
|
||||||
deps-y+=$(firmware-objs-path-y:.o=.dep)
|
deps-y+=$(firmware-objs-path-y:.o=.dep)
|
||||||
|
|
||||||
|
# Setup platform XLEN, ABI, ISA and Code Model
|
||||||
|
ifndef PLATFORM_RISCV_XLEN
|
||||||
|
ifeq ($(OPENSBI_CC_XLEN), 32)
|
||||||
|
PLATFORM_RISCV_XLEN = 32
|
||||||
|
else
|
||||||
|
PLATFORM_RISCV_XLEN = 64
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
ifndef PLATFORM_RISCV_ABI
|
||||||
|
ifeq ($(PLATFORM_RISCV_XLEN), 32)
|
||||||
|
PLATFORM_RISCV_ABI = ilp$(PLATFORM_RISCV_XLEN)
|
||||||
|
else
|
||||||
|
PLATFORM_RISCV_ABI = lp$(PLATFORM_RISCV_XLEN)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
ifndef PLATFORM_RISCV_ISA
|
||||||
|
PLATFORM_RISCV_ISA = rv$(PLATFORM_RISCV_XLEN)imafdc
|
||||||
|
endif
|
||||||
|
ifndef PLATFORM_RISCV_CODE_MODEL
|
||||||
|
PLATFORM_RISCV_CODE_MODEL = medany
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Setup compilation commands flags
|
||||||
GENFLAGS = -I$(platform_dir)/include
|
GENFLAGS = -I$(platform_dir)/include
|
||||||
GENFLAGS += -I$(platform_common_dir)/include
|
GENFLAGS += -I$(platform_common_dir)/include
|
||||||
GENFLAGS += -I$(include_dir)
|
GENFLAGS += -I$(include_dir)
|
||||||
@@ -99,27 +142,11 @@ GENFLAGS += $(platform-common-genflags-y)
|
|||||||
GENFLAGS += $(platform-genflags-y)
|
GENFLAGS += $(platform-genflags-y)
|
||||||
GENFLAGS += $(firmware-genflags-y)
|
GENFLAGS += $(firmware-genflags-y)
|
||||||
|
|
||||||
# Setup compilation commands
|
|
||||||
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
|
|
||||||
AS = $(CC)
|
|
||||||
DTC = dtc
|
|
||||||
|
|
||||||
# Setup compilation commands flags
|
|
||||||
CFLAGS = -g -Wall -Werror -nostdlib -fno-strict-aliasing -O2
|
CFLAGS = -g -Wall -Werror -nostdlib -fno-strict-aliasing -O2
|
||||||
CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
|
CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
|
||||||
CFLAGS += -mno-save-restore -mstrict-align
|
CFLAGS += -mno-save-restore -mstrict-align
|
||||||
|
CFLAGS += -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
|
||||||
|
CFLAGS += -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
|
||||||
CFLAGS += $(GENFLAGS)
|
CFLAGS += $(GENFLAGS)
|
||||||
CFLAGS += $(platform-cflags-y)
|
CFLAGS += $(platform-cflags-y)
|
||||||
CFLAGS += $(firmware-cflags-y)
|
CFLAGS += $(firmware-cflags-y)
|
||||||
@@ -131,17 +158,21 @@ CPPFLAGS += $(firmware-cppflags-y)
|
|||||||
ASFLAGS = -g -Wall -nostdlib -D__ASSEMBLY__
|
ASFLAGS = -g -Wall -nostdlib -D__ASSEMBLY__
|
||||||
ASFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
|
ASFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
|
||||||
ASFLAGS += -mno-save-restore -mstrict-align
|
ASFLAGS += -mno-save-restore -mstrict-align
|
||||||
|
ASFLAGS += -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
|
||||||
|
ASFLAGS += -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
|
||||||
ASFLAGS += $(GENFLAGS)
|
ASFLAGS += $(GENFLAGS)
|
||||||
ASFLAGS += $(platform-asflags-y)
|
ASFLAGS += $(platform-asflags-y)
|
||||||
ASFLAGS += $(firmware-asflags-y)
|
ASFLAGS += $(firmware-asflags-y)
|
||||||
|
|
||||||
ARFLAGS = rcs
|
ARFLAGS = rcs
|
||||||
|
|
||||||
LDFLAGS += -g -Wall -nostdlib -Wl,--build-id=none -N
|
ELFFLAGS += -Wl,--build-id=none -N -static-libgcc -lgcc
|
||||||
LDFLAGS += $(platform-ldflags-y)
|
ELFFLAGS += $(platform-ldflags-y)
|
||||||
LDFLAGS += $(firmware-ldflags-y)
|
ELFFLAGS += $(firmware-ldflags-y)
|
||||||
|
|
||||||
MERGEFLAGS += -r
|
MERGEFLAGS += -r
|
||||||
|
MERGEFLAGS += -b elf$(PLATFORM_RISCV_XLEN)-littleriscv
|
||||||
|
MERGEFLAGS += -m elf$(PLATFORM_RISCV_XLEN)lriscv
|
||||||
|
|
||||||
DTCFLAGS = -O dtb
|
DTCFLAGS = -O dtb
|
||||||
|
|
||||||
@@ -180,7 +211,7 @@ compile_cpp = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
|||||||
$(CPP) $(CPPFLAGS) -x c $(2) | grep -v "\#" > $(1)
|
$(CPP) $(CPPFLAGS) -x c $(2) | grep -v "\#" > $(1)
|
||||||
compile_cc_dep = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
compile_cc_dep = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||||
echo " CC-DEP $(subst $(build_dir)/,,$(1))"; \
|
echo " CC-DEP $(subst $(build_dir)/,,$(1))"; \
|
||||||
echo -n `dirname $(1)`/ > $(1) && \
|
echo `dirname $(1)`/ \\ > $(1) && \
|
||||||
$(CC) $(CFLAGS) $(call dynamic_flags,$(1),$(2)) \
|
$(CC) $(CFLAGS) $(call dynamic_flags,$(1),$(2)) \
|
||||||
-MM $(2) >> $(1) || rm -f $(1)
|
-MM $(2) >> $(1) || rm -f $(1)
|
||||||
compile_cc = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
compile_cc = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||||
@@ -188,15 +219,15 @@ compile_cc = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
|||||||
$(CC) $(CFLAGS) $(call dynamic_flags,$(1),$(2)) -c $(2) -o $(1)
|
$(CC) $(CFLAGS) $(call dynamic_flags,$(1),$(2)) -c $(2) -o $(1)
|
||||||
compile_as_dep = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
compile_as_dep = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||||
echo " AS-DEP $(subst $(build_dir)/,,$(1))"; \
|
echo " AS-DEP $(subst $(build_dir)/,,$(1))"; \
|
||||||
echo -n `dirname $(1)`/ > $(1) && \
|
echo `dirname $(1)`/ \\ > $(1) && \
|
||||||
$(AS) $(ASFLAGS) $(call dynamic_flags,$(1),$(2)) \
|
$(AS) $(ASFLAGS) $(call dynamic_flags,$(1),$(2)) \
|
||||||
-MM $(2) >> $(1) || rm -f $(1)
|
-MM $(2) >> $(1) || rm -f $(1)
|
||||||
compile_as = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
compile_as = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||||
echo " AS $(subst $(build_dir)/,,$(1))"; \
|
echo " AS $(subst $(build_dir)/,,$(1))"; \
|
||||||
$(AS) $(ASFLAGS) $(call dynamic_flags,$(1),$(2)) -c $(2) -o $(1)
|
$(AS) $(ASFLAGS) $(call dynamic_flags,$(1),$(2)) -c $(2) -o $(1)
|
||||||
compile_ld = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
compile_elf = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||||
echo " LD $(subst $(build_dir)/,,$(1))"; \
|
echo " ELF $(subst $(build_dir)/,,$(1))"; \
|
||||||
$(CC) $(3) $(LDFLAGS) -Wl,-T$(2) -o $(1)
|
$(CC) $(CFLAGS) $(3) $(ELFFLAGS) -Wl,-T$(2) -o $(1)
|
||||||
compile_ar = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
compile_ar = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||||
echo " AR $(subst $(build_dir)/,,$(1))"; \
|
echo " AR $(subst $(build_dir)/,,$(1))"; \
|
||||||
$(AR) $(ARFLAGS) $(1) $(2)
|
$(AR) $(ARFLAGS) $(1) $(2)
|
||||||
@@ -225,7 +256,7 @@ $(build_dir)/%.bin: $(build_dir)/%.elf
|
|||||||
$(call compile_objcopy,$@,$<)
|
$(call compile_objcopy,$@,$<)
|
||||||
|
|
||||||
$(build_dir)/%.elf: $(build_dir)/%.o $(build_dir)/%.elf.ld $(build_dir)/$(platform_subdir)/lib/libplatsbi.a
|
$(build_dir)/%.elf: $(build_dir)/%.o $(build_dir)/%.elf.ld $(build_dir)/$(platform_subdir)/lib/libplatsbi.a
|
||||||
$(call compile_ld,$@,$@.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
|
$(build_dir)/$(platform_subdir)/%.ld: $(src_dir)/%.ldS
|
||||||
$(call compile_cpp,$@,$<)
|
$(call compile_cpp,$@,$<)
|
||||||
@@ -285,6 +316,21 @@ all-deps-2 = $(if $(findstring clean,$(MAKECMDGOALS)),,$(all-deps-1))
|
|||||||
# Include external dependency of firmwares after default Makefile rules
|
# Include external dependency of firmwares after default Makefile rules
|
||||||
include $(src_dir)/firmware/external_deps.mk
|
include $(src_dir)/firmware/external_deps.mk
|
||||||
|
|
||||||
|
# Convenient "make run" command for emulated platforms
|
||||||
|
.PHONY: run
|
||||||
|
run: all
|
||||||
|
ifneq ($(platform-runcmd),)
|
||||||
|
$(platform-runcmd) $(RUN_ARGS)
|
||||||
|
else
|
||||||
|
ifdef PLATFORM
|
||||||
|
@echo Platform $(PLATFORM) doesn't specify a run command
|
||||||
|
@false
|
||||||
|
else
|
||||||
|
@echo Run command only available when targeting a platform
|
||||||
|
@false
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
install_targets-y = install_libsbi
|
install_targets-y = install_libsbi
|
||||||
ifdef PLATFORM
|
ifdef PLATFORM
|
||||||
install_targets-y += install_libplatsbi
|
install_targets-y += install_libplatsbi
|
||||||
|
88
README.md
88
README.md
@@ -1,39 +1,62 @@
|
|||||||
RISC-V Open Source Supervisor Binary Interface (OpenSBI)
|
RISC-V Open Source Supervisor Binary Interface (OpenSBI)
|
||||||
========================================================
|
========================================================
|
||||||
|
|
||||||
The **RISC-V Supervisor Binary Interface (SBI)** is a recommended interface
|
The **RISC-V Supervisor Binary Interface (SBI)** is the recommended interface
|
||||||
between:
|
between:
|
||||||
|
|
||||||
1. A platform specific firmware running in M-mode and a general purpose OS,
|
1. A platform specific firmware running in M-mode and bootloader, hypervisor or
|
||||||
hypervisor or bootloader running in S-mode or HS-mode.
|
a general purpose OS executing in S-mode or HS-mode.
|
||||||
2. A hypervisor running in HS-mode and a general purpose OS or bootloader
|
2. A hypervisor running in HS-mode and a bootloader or a general purpose OS
|
||||||
executed in VS-mode.
|
executing in VS-mode.
|
||||||
|
|
||||||
The *RISC-V SBI specification* is maintained as an independent project by the
|
The *RISC-V SBI specification* is maintained as an independent project by the
|
||||||
RISC-V Foundation in [Github].
|
RISC-V Foundation in [Github].
|
||||||
|
|
||||||
OpenSBI aims to provides an open-source and extensible implementation of the
|
The goal of the OpenSBI project is to provide an open-source reference
|
||||||
RISC-V SBI specification for case 1 mentioned above. OpenSBI implementation
|
implementation of the RISC-V SBI specifications for platform specific firmwares
|
||||||
can be easily extended by RISC-V platform or System-on-Chip vendors to fit a
|
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.
|
particular hardware configuration.
|
||||||
|
|
||||||
OpenSBI provides three different components:
|
The main component of OpenSBI is provided in the form of a platform independent
|
||||||
1. *libsbi.a* - A generic OpenSBI static library
|
static library **libsbi.a** implementing the SBI interface. A firmware or
|
||||||
2. *libplatsbi.a* - A platform specific OpenSBI static library, that is,
|
bootloader implementation can link against this library to ensure conformance
|
||||||
libsbi.a plus platform specific hooks
|
with the SBI interface specifications. *libsbi.a* also defines an interface for
|
||||||
3. *firmwares* - Platform specific bootable firmware binaries
|
integrating with platform specific operations provided by the platform firmware
|
||||||
|
implementation (e.g. console access functions, inter-processor interrupts
|
||||||
|
control, etc).
|
||||||
|
|
||||||
Building and Installing the generic OpenSBI static library
|
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].
|
||||||
|
|
||||||
*libsbi.a* can be natively compiled or cross-compiled on a host with a
|
Required Toolchain
|
||||||
different base architecture than RISC-V.
|
------------------
|
||||||
|
|
||||||
|
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
|
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.
|
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*.
|
*riscv64-unknown-elf-* if the gcc executable used is *riscv64-unknown-elf-gcc*.
|
||||||
|
|
||||||
To build the generic OpenSBI library *libsbi.a*, simply execute:
|
To build *libsbi.a* simply execute:
|
||||||
```
|
```
|
||||||
make
|
make
|
||||||
```
|
```
|
||||||
@@ -58,18 +81,18 @@ path, run:
|
|||||||
make I=<install_directory> install
|
make I=<install_directory> install
|
||||||
```
|
```
|
||||||
|
|
||||||
Building and Installing the platform specific static library and firmwares
|
Building and Installing a Reference Platform Static Library and Firmwares
|
||||||
--------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
|
|
||||||
The platform specific *libplatsbi.a* static library and the platform firmwares
|
When the *PLATFORM=<platform_subdir>* argument is specified on the make command
|
||||||
are only built if the *PLATFORM=<platform_subdir>* argument is specified on
|
line, the platform specific static library *libplatsbi.a* and firmware examples
|
||||||
the make command line. *<platform_subdir>* must specify the relative path from
|
are built for the platform *<platform_subdir>* present in the directory
|
||||||
OpenSBI code directory to one of the leaf directories under the *platform*
|
*platform* in OpenSBI top directory. For example, to compile the platform
|
||||||
directory. For example, to compile the platform library and firmwares for QEMU
|
library and firmware examples for QEMU RISC-V *virt* machine,
|
||||||
RISC-V *virt* machine, *<platform_subdir>* should be *qemu/virt*.
|
*<platform_subdir>* should be *qemu/virt*.
|
||||||
|
|
||||||
To build *libsbi.a*, *libplatsbi.a* and the firmwares for a specific platform,
|
To build *libsbi.a*, *libplatsbi.a* and the firmwares for one of the supported
|
||||||
run:
|
platform, run:
|
||||||
```
|
```
|
||||||
make PLATFORM=<platform_subdir>
|
make PLATFORM=<platform_subdir>
|
||||||
```
|
```
|
||||||
@@ -112,7 +135,7 @@ A copy of this license with OpenSBI copyright can be found in the file
|
|||||||
[COPYING.BSD].
|
[COPYING.BSD].
|
||||||
|
|
||||||
All source files in OpenSBI contain the 2-Clause BSD license SPDX short
|
All source files in OpenSBI contain the 2-Clause BSD license SPDX short
|
||||||
indentifier in place of the full license text.
|
identifier in place of the full license text.
|
||||||
|
|
||||||
```
|
```
|
||||||
SPDX-License-Identifier: BSD-2-Clause
|
SPDX-License-Identifier: BSD-2-Clause
|
||||||
@@ -144,11 +167,11 @@ Detailed documentation of various aspects of OpenSBI can be found under the
|
|||||||
*docs* directory. The documentation covers the following topics.
|
*docs* directory. The documentation covers the following topics.
|
||||||
|
|
||||||
* [Contribution Guideline]: Guideline for contributing code to OpenSBI project
|
* [Contribution Guideline]: Guideline for contributing code to OpenSBI project
|
||||||
* [Platform Support Guide]: Guideline for implementing support for new platforms
|
|
||||||
* [Library Usage]: API documentation of OpenSBI static library *libsbi.a*
|
* [Library Usage]: API documentation of OpenSBI static library *libsbi.a*
|
||||||
|
* [Platform Support Guide]: Guideline for implementing support for new platforms
|
||||||
* [Platform Documentation]: Documentation of the platforms currently supported.
|
* [Platform Documentation]: Documentation of the platforms currently supported.
|
||||||
* [Firmware Documentation]: Documentation for the different types of firmware
|
* [Firmware Documentation]: Documentation for the different types of firmware
|
||||||
build supported by OpenSBI.
|
examples build supported by OpenSBI.
|
||||||
|
|
||||||
OpenSBI source code is also well documented. For source level documentation,
|
OpenSBI source code is also well documented. For source level documentation,
|
||||||
doxygen style is used. Please refer to [Doxygen manual] for details on this
|
doxygen style is used. Please refer to [Doxygen manual] for details on this
|
||||||
@@ -191,11 +214,12 @@ make I=<install_directory> install_docs
|
|||||||
*refman.pdf* will be installed under *<install_directory>/docs*.
|
*refman.pdf* will be installed under *<install_directory>/docs*.
|
||||||
|
|
||||||
[Github]: https://github.com/riscv/riscv-sbi-doc
|
[Github]: https://github.com/riscv/riscv-sbi-doc
|
||||||
|
[U-Boot]: https://www.denx.de/wiki/U-Boot/SourceCode
|
||||||
[COPYING.BSD]: COPYING.BSD
|
[COPYING.BSD]: COPYING.BSD
|
||||||
[SPDX]: http://spdx.org/licenses/
|
[SPDX]: http://spdx.org/licenses/
|
||||||
[Contribution Guideline]: docs/contributing.md
|
[Contribution Guideline]: docs/contributing.md
|
||||||
[Platform Support Guide]: docs/platform_guide.md
|
|
||||||
[Library Usage]: docs/library_usage.md
|
[Library Usage]: docs/library_usage.md
|
||||||
|
[Platform Support Guide]: docs/platform_guide.md
|
||||||
[Platform Documentation]: docs/platform/platform.md
|
[Platform Documentation]: docs/platform/platform.md
|
||||||
[Firmware Documentation]: docs/firmware/fw.md
|
[Firmware Documentation]: docs/firmware/fw.md
|
||||||
[Doxygen manual]: http://www.stack.nl/~dimitri/doxygen/manual.html
|
[Doxygen manual]: http://www.stack.nl/~dimitri/doxygen/manual.html
|
||||||
|
@@ -5,7 +5,7 @@ OpenSBI provides firmware builds for specific platforms. Different types of
|
|||||||
firmwares are supported to deal with the differences between different platforms
|
firmwares are supported to deal with the differences between different platforms
|
||||||
early boot stage. All firmwares will execute the same initialization procedure
|
early boot stage. All firmwares will execute the same initialization procedure
|
||||||
of the platform hardware according to the platform specific code as well as
|
of the platform hardware according to the platform specific code as well as
|
||||||
OpenSBI generic library code. The supported firmwares types will differ in how
|
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
|
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.
|
how the boot stage following the firmware will be handled and executed.
|
||||||
|
|
||||||
@@ -58,3 +58,20 @@ following documents.
|
|||||||
|
|
||||||
[FW_JUMP]: fw_jump.md
|
[FW_JUMP]: fw_jump.md
|
||||||
[FW_PAYLOAD]: fw_payload.md
|
[FW_PAYLOAD]: fw_payload.md
|
||||||
|
|
||||||
|
Providing different payloads to OpenSBI Firmware
|
||||||
|
------------------------------------------------
|
||||||
|
OpenSBI firmware can accept various payloads using a compile time option.
|
||||||
|
Typically, these payloads refer to the next stage boot loader (e.g. U-Boot)
|
||||||
|
or operating system kernel images (e.g. Linux). By default, OpenSBI
|
||||||
|
automatically provides a test payload if no specific payload is specified
|
||||||
|
at compile time.
|
||||||
|
|
||||||
|
To specify a payload at compile time, the make variable _FW_PAYLOAD_PATH_ is
|
||||||
|
used.
|
||||||
|
```
|
||||||
|
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.
|
||||||
|
11
docs/firmware/payload_linux.md
Normal file
11
docs/firmware/payload_linux.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Linux as a direct payload to OpenSBI
|
||||||
|
====================================
|
||||||
|
|
||||||
|
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 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.
|
||||||
|
|
38
docs/firmware/payload_uboot.md
Normal file
38
docs/firmware/payload_uboot.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
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
|
||||||
|
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 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.
|
@@ -1,30 +1,36 @@
|
|||||||
OpenSBI Library Usage Guideline
|
OpenSBI Library Usage
|
||||||
===============================
|
=====================
|
||||||
|
|
||||||
OpenSBI provides two types of static libraries:
|
OpenSBI provides two types of static libraries:
|
||||||
|
|
||||||
1. *libsbi.a* - A generic OpenSBI static library installed at
|
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*
|
*<install_directory>/lib/libsbi.a*
|
||||||
2. *libplatsbi.a* - A platform specific OpenSBI static library, that is,
|
2. *libplatsbi.a* - An example platform specific static library integrating
|
||||||
libsbi.a plus platform specific hooks installed at
|
*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*
|
*<install_directory>/platform/<platform_subdir>/lib/libplatsbi.a*
|
||||||
|
|
||||||
The platform specific firmwares provided by OpenSBI are not mandatory. Users
|
Implementations may choose either *libsbi.a* or *libplatsbi.a* to link with
|
||||||
can always link OpenSBI as static library to their favorite M-mode firmware
|
their firmware or bootloader. In the case of *libsbi.a*, platform specific
|
||||||
or bootloader provided that it has a license compatible with OpenSBI license.
|
hooks in the form of a *struct sbi_platform* instance needs to be provided.
|
||||||
|
|
||||||
Users can choose either *libsbi.a* or *libplatsbi.a* to link with their
|
The platform specific example firmwares provided by OpenSBI are not mandatory.
|
||||||
firmware or bootloader but with *libsbi.a* platform specific hooks (i.e.
|
An implementation may choose to link OpenSBI generic static library together
|
||||||
*struct sbi_platform* instance) will have to be provided.
|
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
|
Constraints on OpenSBI usage from external firmware
|
||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
|
|
||||||
Users have to ensure that external firmware or bootloader and OpenSBI static
|
Users have to ensure that an external firmware or bootloader linking against
|
||||||
library (*libsbi.a* or *libplatsbi.a*) are compiled with the same GCC target
|
OpenSBI static libraries (*libsbi.a* or *libplatsbi.a*) are compiled with the
|
||||||
options *-mabi*, *-march*, and *-mcmodel*.
|
same GCC target options *-mabi*, *-march*, and *-mcmodel*.
|
||||||
|
|
||||||
There are only two constraints on calling any OpenSBI function from an
|
There are only two constraints on calling any OpenSBI library function from an
|
||||||
external M-mode firmware or bootloader:
|
external M-mode firmware or bootloader:
|
||||||
|
|
||||||
1. The RISC-V *MSCRATCH* CSR must point to a valid OpenSBI scratch space
|
1. The RISC-V *MSCRATCH* CSR must point to a valid OpenSBI scratch space
|
||||||
@@ -35,15 +41,16 @@ external M-mode firmware or bootloader:
|
|||||||
The most important functions from an external firmware or bootloader
|
The most important functions from an external firmware or bootloader
|
||||||
perspective are *sbi_init()* and *sbi_trap_handler()*.
|
perspective are *sbi_init()* and *sbi_trap_handler()*.
|
||||||
|
|
||||||
In addition to above constraints, the external firmware or bootloader must
|
In addition to the above constraints, the external firmware or bootloader must
|
||||||
ensure that interrupts are disabled in *MSTATUS* and *MIE* CSRs when calling
|
ensure that interrupts are disabled in *MSTATUS* and *MIE* CSRs when calling
|
||||||
*sbi_init()* and *sbi_trap_handler()* functions.
|
the functions *sbi_init()* and *sbi_trap_handler()*.
|
||||||
|
|
||||||
The *sbi_init()* should be called by the external firmware or bootloader
|
The *sbi_init()* function should be called by the external firmware or
|
||||||
when a HART is powered-up at boot-time or in response to a CPU hotplug event.
|
bootloader for each HART that is powered-up at boot-time or in response to a
|
||||||
|
CPU hotplug event.
|
||||||
|
|
||||||
The *sbi_trap_handler()* should be called by the external firmware or
|
The *sbi_trap_handler()* function should be called by the external firmware or
|
||||||
bootloader for the following interrupts and traps:
|
bootloader to service the following interrupts and traps:
|
||||||
|
|
||||||
1. M-mode timer interrupt
|
1. M-mode timer interrupt
|
||||||
2. M-mode software interrupt
|
2. M-mode software interrupt
|
||||||
@@ -54,4 +61,5 @@ bootloader for the following interrupts and traps:
|
|||||||
7. Hypervisor ecall trap
|
7. Hypervisor ecall trap
|
||||||
|
|
||||||
**Note:** external firmwares or bootloaders can be more conservative by
|
**Note:** external firmwares or bootloaders can be more conservative by
|
||||||
forwarding all traps and interrupts to *sbi_trap_handler()*
|
forwarding all traps and interrupts to *sbi_trap_handler()*.
|
||||||
|
|
||||||
|
@@ -50,7 +50,7 @@ or
|
|||||||
```
|
```
|
||||||
qemu-system-riscv64 -M virt -m 256M -display none -serial stdio \
|
qemu-system-riscv64 -M virt -m 256M -display none -serial stdio \
|
||||||
-kernel build/platform/qemu/virt/firmware/fw_jump.elf \
|
-kernel build/platform/qemu/virt/firmware/fw_jump.elf \
|
||||||
-device loader,file=<uboot_build_directory>/u-boot.bin,addr=0x80200000
|
-device loader,file=<uboot_build_directory>/u-boot.bin,addr=0x80400000
|
||||||
```
|
```
|
||||||
|
|
||||||
**Linux Kernel Payload**
|
**Linux Kernel Payload**
|
||||||
@@ -75,7 +75,7 @@ or
|
|||||||
```
|
```
|
||||||
qemu-system-riscv64 -M virt -m 256M -display none -serial stdio \
|
qemu-system-riscv64 -M virt -m 256M -display none -serial stdio \
|
||||||
-kernel build/platform/qemu/virt/firmware/fw_jump.elf \
|
-kernel build/platform/qemu/virt/firmware/fw_jump.elf \
|
||||||
-device loader,file=<linux_build_directory>/arch/riscv/boot/Image,addr=0x80200000 \
|
-device loader,file=<linux_build_directory>/arch/riscv/boot/Image,addr=0x80400000 \
|
||||||
-drive file=<path_to_linux_rootfs>,format=raw,id=hd0 \
|
-drive file=<path_to_linux_rootfs>,format=raw,id=hd0 \
|
||||||
-device virtio-blk-device,drive=hd0 \
|
-device virtio-blk-device,drive=hd0 \
|
||||||
-append "root=/dev/vda rw console=ttyS0"
|
-append "root=/dev/vda rw console=ttyS0"
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
SiFive FU540 SoC Platform
|
SiFive FU540 SoC Platform
|
||||||
==========================
|
==========================
|
||||||
The FU540-C000 is the world’s first 4+1 64-bit RISC‑V SoC from SiFive.
|
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
|
The HiFive Unleashed development platform is based on FU540-C000 and capable
|
||||||
of running Linux.
|
of running Linux.
|
||||||
|
|
||||||
@@ -13,59 +13,47 @@ Platform Options
|
|||||||
As hart0 in the FU540 doesn't have an MMU, only harts 1-4 boot by default.
|
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
|
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
|
select any other hart for booting. Please keep in mind that this is not
|
||||||
platform wide option. It can only be specificd for FU540 platform in following way.
|
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
|
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.
|
This will let the board boot only hart1 instead of default 1-4.
|
||||||
|
|
||||||
Booting SiFive Fu540 Platform
|
Building SiFive Fu540 Platform
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
|
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**
|
**Linux Kernel Payload**
|
||||||
|
|
||||||
Build:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
||||||
```
|
```
|
||||||
|
|
||||||
Flash:
|
|
||||||
The generated firmware binary should be copied to the first partition of the sdcard.
|
|
||||||
|
|
||||||
```
|
|
||||||
dd if=build/platform/sifive/fu540/firmware/fw_payload.bin of=/dev/disk2s1 bs=1024
|
|
||||||
```
|
|
||||||
|
|
||||||
**U-Boot Payload**
|
**U-Boot Payload**
|
||||||
|
|
||||||
Note: U-Boot doesn't have SMP support. So you can only boot single cpu with non-smp
|
|
||||||
kernel configuration using U-Boot.
|
|
||||||
|
|
||||||
Build:
|
The command-line example here assumes that U-Boot was compiled using sifive_fu540_defconfig configuration.
|
||||||
|
|
||||||
The commandline example here assumes that U-Boot was compiled using sifive_fu540_defconfig configuration.
|
With SMP support enabled in U-Boot:
|
||||||
|
|
||||||
|
```
|
||||||
|
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
|
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<u-boot_build_dir>/u-boot.bin FU540_ENABLED_HART_MASK=0x02
|
||||||
```
|
```
|
||||||
|
|
||||||
Flash:
|
|
||||||
The generated firmware binary should be copied to the first partition of the sdcard.
|
|
||||||
|
|
||||||
```
|
|
||||||
dd if=build/platform/sifive/fu540/firmware/fw_payload.bin of=/dev/disk2s1 bs=1024
|
|
||||||
```
|
|
||||||
U-Boot tftp boot method can be used to load kernel image in U-Boot prompt.
|
|
||||||
|
|
||||||
Note: As the U-Boot & Linux kernel patches are not in upstream it, you can cherry-pick from here.
|
|
||||||
|
|
||||||
U-Boot patchset:
|
|
||||||
https://lists.denx.de/pipermail/u-boot/2019-January/355941.html
|
|
||||||
|
|
||||||
Linux kernel patchset:
|
|
||||||
https://lkml.org/lkml/2019/1/8/192
|
|
||||||
|
|
||||||
**U-Boot & Linux Kernel as a single payload**
|
**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
|
A single monolithic image containing both U-Boot & Linux can also be used if network boot setup is
|
||||||
@@ -78,8 +66,9 @@ mkimage -A riscv -O linux -T kernel -C none -a 0x80200000 -e 0x80200000 -n Linux
|
|||||||
<linux_build_directory>/arch/riscv/boot/uImage
|
<linux_build_directory>/arch/riscv/boot/uImage
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Create a temporary image with u-boot.bin as the first payload. The commandline example here assumes
|
2. Create a temporary image with u-boot.bin as the first payload. The command-line
|
||||||
that U-Boot was compiled using sifive_fu540_defconfig configuration.
|
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
|
dd if=~/workspace/u-boot-riscv/u-boot.bin of=/tmp/temp.bin bs=1M
|
||||||
```
|
```
|
||||||
@@ -87,16 +76,127 @@ dd if=~/workspace/u-boot-riscv/u-boot.bin of=/tmp/temp.bin bs=1M
|
|||||||
```
|
```
|
||||||
dd if=<linux_build_directory>/arch/riscv/boot/uImage of=/tmp/temp.bin bs=1M seek=4
|
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 and single hart enabled.
|
4. Compile OpenSBI with temp.bin (generated in step 3) as payload.
|
||||||
```
|
```
|
||||||
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=/tmp/temp.bin FU540_ENABLED_HART_MASK=0x02
|
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=/tmp/temp.bin
|
||||||
```
|
```
|
||||||
5. The generated firmware binary should be copied to the first partition of the sdcard.
|
|
||||||
|
Flashing the OpenSBI firmware binary to storage media:
|
||||||
|
-----------------------------------------------------
|
||||||
|
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.
|
||||||
|
|
||||||
```
|
```
|
||||||
dd if=build/platform/sifive/fu540/firmware/fw_payload.bin of=/dev/disk2s1 bs=1024
|
dd if=build/platform/sifive/fu540/firmware/fw_payload.bin of=/dev/disk2s1 bs=1024
|
||||||
```
|
```
|
||||||
6. At U-Boot prompt execute following boot command to boot non-SMP linux.
|
|
||||||
|
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.
|
||||||
|
|
||||||
```
|
```
|
||||||
bootm 0x80600000 - 0x82200000
|
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)
|
||||||
|
```
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
**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.
|
||||||
|
|
||||||
|
1. Set the mac address of the board.
|
||||||
|
|
||||||
|
```
|
||||||
|
setenv ethaddr <mac address of the board>
|
||||||
|
```
|
||||||
|
2. Set the ip address of the board.
|
||||||
|
|
||||||
|
```
|
||||||
|
setenv ipaddr <ipaddr of the board>
|
||||||
|
```
|
||||||
|
3. Set the tftpboot server IP.
|
||||||
|
|
||||||
|
```
|
||||||
|
setenv serverip <ipaddr of the tftp server>
|
||||||
|
```
|
||||||
|
4. Set the network gateway address.
|
||||||
|
|
||||||
|
```
|
||||||
|
setenv gatewayip <ipaddress of the network gateway>
|
||||||
|
```
|
||||||
|
5. Load the Linux kernel image from the tftp server.
|
||||||
|
|
||||||
|
```
|
||||||
|
tftpboot ${kernel_addr_r} /sifive/fu540/uImage
|
||||||
|
```
|
||||||
|
|
||||||
|
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} /sifive/fu540/uRamdisk
|
||||||
|
```
|
||||||
|
7. Set the boot command-line arguments.
|
||||||
|
|
||||||
|
```
|
||||||
|
setenv bootargs "root=<root partition> rw console=ttySIF0 earlycon=sbi"
|
||||||
|
```
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
```
|
||||||
|
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**
|
||||||
|
|
||||||
|
At U-Boot prompt execute the following boot command to boot Linux.
|
||||||
|
|
||||||
|
```
|
||||||
|
bootm ${kernel_addr_r} - ${fdtcontroladdr}
|
||||||
|
```
|
||||||
|
Booting SiFive Fu540 Platform with Microsemi Expansion board
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
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:
|
||||||
|
```
|
||||||
|
FW_PAYLOAD_FDT="HiFiveUnleashed-MicroSemi-Expansion.dtb"
|
||||||
```
|
```
|
||||||
|
@@ -1,22 +1,31 @@
|
|||||||
OpenSBI Platform Support Guideline
|
OpenSBI Platform Support Guideline
|
||||||
==================================
|
==================================
|
||||||
|
|
||||||
The OpenSBI platform support is a set of platform specific hooks provided
|
OpenSBI platform support allows an implementation to define a set of platform
|
||||||
in the form of a *struct sbi_platform* instance. It is required by:
|
specific hooks (hardware manipulation functions) in the form of a
|
||||||
|
*struct sbi_platform* data structure instance. This instance is required by
|
||||||
|
platform independent *libsbi.a* to execute platform specific operations.
|
||||||
|
|
||||||
1. *libplatsbi.a* - A platform specific OpenSBI static library, that is,
|
Each of the reference platform support provided by OpenSBI define an instance
|
||||||
libsbi.a plus a *struct sbi_platform* instance installed at
|
of the *struct sbi_platform* data structure. For each supported platform,
|
||||||
*<install_directory>/platform/<platform_subdir>/lib/libplatsbi.a*
|
*libplatsbi.a* integrates this instance with *libsbi.a* to create a platform
|
||||||
2. *firmwares* - Platform specific bootable firmware binaries installed at
|
specific OpenSBI static library. This library is installed
|
||||||
*<install_directory>/platform/<platform_subdir>/bin*
|
in *<install_directory>/platform/<platform_subdir>/lib/libplatsbi.a*
|
||||||
|
|
||||||
|
OpenSBI also provides implementation examples of bootable runtime firmwares for
|
||||||
|
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 *riskv-pk* boot loader (BBL).
|
||||||
|
|
||||||
A complete doxygen-style documentation of *struct sbi_platform* and related
|
A complete doxygen-style documentation of *struct sbi_platform* and related
|
||||||
APIs is available in sbi/sbi_platform.h.
|
APIs is available in the file *include/sbi/sbi_platform.h*.
|
||||||
|
|
||||||
Adding a new platform support
|
Adding a new platform support
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
The support of 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 *platform/* directory
|
1. Create a directory named *<xyz>* under *platform/* directory
|
||||||
2. Create a platform configuration file named *config.mk* under
|
2. Create a platform configuration file named *config.mk* under
|
||||||
@@ -27,6 +36,7 @@ The support of a new platform named *<xyz>* can be added as follows:
|
|||||||
4. Create *platform/<xyz>/platform.c* file providing a *struct sbi_platform*
|
4. Create *platform/<xyz>/platform.c* file providing a *struct sbi_platform*
|
||||||
instance
|
instance
|
||||||
|
|
||||||
A template platform support code is available under the *platform/template*.
|
A template platform support code is available under the *platform/template*
|
||||||
Copying this directory as new directory named *<xyz>* under *platform/*
|
directory. Copying this directory and its content as a new directory named
|
||||||
directory will create all the files mentioned above.
|
*<xyz>* under the *platform/* directory will create all the files mentioned
|
||||||
|
above.
|
||||||
|
@@ -22,7 +22,7 @@ _start:
|
|||||||
* Jump to warm-boot if this is not the first core booting,
|
* Jump to warm-boot if this is not the first core booting,
|
||||||
* that is, for mhartid != 0
|
* that is, for mhartid != 0
|
||||||
*/
|
*/
|
||||||
csrr a6, mhartid
|
csrr a6, CSR_MHARTID
|
||||||
blt zero, a6, _wait_for_boot_hart
|
blt zero, a6, _wait_for_boot_hart
|
||||||
|
|
||||||
/* Zero-out BSS */
|
/* Zero-out BSS */
|
||||||
@@ -69,7 +69,11 @@ _prev_arg1_override_done:
|
|||||||
add t0, a1, zero
|
add t0, a1, zero
|
||||||
and t0, t0, a3
|
and t0, t0, a3
|
||||||
/* t2 = source FDT size in big-endian */
|
/* t2 = source FDT size in big-endian */
|
||||||
|
#if __riscv_xlen == 64
|
||||||
lwu t2, 4(t0)
|
lwu t2, 4(t0)
|
||||||
|
#else
|
||||||
|
lw t2, 4(t0)
|
||||||
|
#endif
|
||||||
/* t3 = bit[15:8] of FDT size */
|
/* t3 = bit[15:8] of FDT size */
|
||||||
add t3, t2, zero
|
add t3, t2, zero
|
||||||
srli t3, t3, 16
|
srli t3, t3, 16
|
||||||
@@ -122,21 +126,26 @@ _wait_for_boot_hart:
|
|||||||
|
|
||||||
_start_warm:
|
_start_warm:
|
||||||
/* Disable and clear all interrupts */
|
/* Disable and clear all interrupts */
|
||||||
csrw mie, zero
|
csrw CSR_MIE, zero
|
||||||
csrw mip, zero
|
csrw CSR_MIP, zero
|
||||||
|
|
||||||
/* Preload per-HART details
|
/* Preload per-HART details
|
||||||
* s6 -> HART ID
|
* s6 -> HART ID
|
||||||
* s7 -> HART Count
|
* s7 -> HART Count
|
||||||
* s8 -> HART Stack Size
|
* s8 -> HART Stack Size
|
||||||
*/
|
*/
|
||||||
csrr s6, mhartid
|
csrr s6, CSR_MHARTID
|
||||||
la a4, platform
|
la a4, platform
|
||||||
|
#if __riscv_xlen == 64
|
||||||
lwu s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
|
lwu s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
|
||||||
lwu s8, SBI_PLATFORM_HART_STACK_SIZE_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
|
||||||
|
|
||||||
/* HART ID should be within expected limit */
|
/* HART ID should be within expected limit */
|
||||||
csrr s6, mhartid
|
csrr s6, CSR_MHARTID
|
||||||
bge s6, s7, _start_hang
|
bge s6, s7, _start_hang
|
||||||
|
|
||||||
/* Setup scratch space */
|
/* Setup scratch space */
|
||||||
@@ -147,7 +156,7 @@ _start_warm:
|
|||||||
sub tp, tp, a5
|
sub tp, tp, a5
|
||||||
li a5, SBI_SCRATCH_SIZE
|
li a5, SBI_SCRATCH_SIZE
|
||||||
sub tp, tp, a5
|
sub tp, tp, a5
|
||||||
csrw mscratch, tp
|
csrw CSR_MSCRATCH, tp
|
||||||
|
|
||||||
/* Initialize scratch space */
|
/* Initialize scratch space */
|
||||||
la a4, _fw_start
|
la a4, _fw_start
|
||||||
@@ -172,17 +181,18 @@ _start_warm:
|
|||||||
la a4, _hartid_to_scratch
|
la a4, _hartid_to_scratch
|
||||||
REG_S a4, SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET(tp)
|
REG_S a4, SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET(tp)
|
||||||
REG_S zero, SBI_SCRATCH_IPI_TYPE_OFFSET(tp)
|
REG_S zero, SBI_SCRATCH_IPI_TYPE_OFFSET(tp)
|
||||||
|
REG_S zero, SBI_SCRATCH_TMP0_OFFSET(tp)
|
||||||
|
|
||||||
/* Setup stack */
|
/* Setup stack */
|
||||||
add sp, tp, zero
|
add sp, tp, zero
|
||||||
|
|
||||||
/* Setup trap handler */
|
/* Setup trap handler */
|
||||||
la a4, _trap_handler
|
la a4, _trap_handler
|
||||||
csrw mtvec, a4
|
csrw CSR_MTVEC, a4
|
||||||
|
|
||||||
/* Initialize SBI runtime */
|
/* Initialize SBI runtime */
|
||||||
csrr a0, mscratch
|
csrr a0, CSR_MSCRATCH
|
||||||
call sbi_init
|
Call sbi_init
|
||||||
|
|
||||||
/* We don't expect to reach here hence just hang */
|
/* We don't expect to reach here hence just hang */
|
||||||
j _start_hang
|
j _start_hang
|
||||||
@@ -202,8 +212,13 @@ _hartid_to_scratch:
|
|||||||
* s2 -> Temporary
|
* s2 -> Temporary
|
||||||
*/
|
*/
|
||||||
la s2, platform
|
la s2, platform
|
||||||
|
#if __riscv_xlen == 64
|
||||||
lwu s0, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(s2)
|
lwu s0, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(s2)
|
||||||
lwu s2, SBI_PLATFORM_HART_COUNT_OFFSET(s2)
|
lwu s2, SBI_PLATFORM_HART_COUNT_OFFSET(s2)
|
||||||
|
#else
|
||||||
|
lw s0, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(s2)
|
||||||
|
lw s2, SBI_PLATFORM_HART_COUNT_OFFSET(s2)
|
||||||
|
#endif
|
||||||
mul s2, s2, s0
|
mul s2, s2, s0
|
||||||
la s1, _fw_end
|
la s1, _fw_end
|
||||||
add s1, s1, s2
|
add s1, s1, s2
|
||||||
@@ -228,42 +243,64 @@ _start_hang:
|
|||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
.globl _trap_handler
|
.globl _trap_handler
|
||||||
_trap_handler:
|
_trap_handler:
|
||||||
/* Swap SP and MSCRATCH */
|
/* Swap TP and MSCRATCH */
|
||||||
csrrw sp, mscratch, sp
|
csrrw tp, CSR_MSCRATCH, tp
|
||||||
|
|
||||||
|
/* Save T0 in scratch space */
|
||||||
|
REG_S t0, SBI_SCRATCH_TMP0_OFFSET(tp)
|
||||||
|
|
||||||
|
/* Check which mode we came from */
|
||||||
|
csrr t0, CSR_MSTATUS
|
||||||
|
srl t0, t0, MSTATUS_MPP_SHIFT
|
||||||
|
and t0, t0, PRV_M
|
||||||
|
xori t0, t0, PRV_M
|
||||||
|
beq t0, zero, _trap_handler_m_mode
|
||||||
|
|
||||||
|
/* We came from S-mode or U-mode */
|
||||||
|
_trap_handler_s_mode:
|
||||||
|
/* Set T0 to original SP */
|
||||||
|
add t0, sp, zero
|
||||||
|
|
||||||
/* Setup exception stack */
|
/* 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)
|
add sp, sp, -(SBI_TRAP_REGS_SIZE)
|
||||||
|
|
||||||
/* Save RA, T0, T1, and T2 */
|
_trap_handler_all_mode:
|
||||||
REG_S ra, SBI_TRAP_REGS_OFFSET(ra)(sp)
|
/* Save original SP (from T0) on stack */
|
||||||
REG_S t0, SBI_TRAP_REGS_OFFSET(t0)(sp)
|
|
||||||
REG_S t1, SBI_TRAP_REGS_OFFSET(t1)(sp)
|
|
||||||
REG_S t2, SBI_TRAP_REGS_OFFSET(t2)(sp)
|
|
||||||
|
|
||||||
/* Save original SP and restore MSCRATCH */
|
|
||||||
add t0, sp, SBI_TRAP_REGS_SIZE
|
|
||||||
csrrw t0, mscratch, t0
|
|
||||||
REG_S t0, SBI_TRAP_REGS_OFFSET(sp)(sp)
|
REG_S t0, SBI_TRAP_REGS_OFFSET(sp)(sp)
|
||||||
|
|
||||||
/* Save MEPC and MSTATUS CSRs */
|
/* Restore T0 from scratch space */
|
||||||
csrr t0, mepc
|
REG_L t0, SBI_SCRATCH_TMP0_OFFSET(tp)
|
||||||
csrr t1, mstatus
|
|
||||||
|
|
||||||
/*
|
/* Save T0 on stack */
|
||||||
* Note: Fast path trap handling can be done here
|
REG_S t0, SBI_TRAP_REGS_OFFSET(t0)(sp)
|
||||||
* using SP, RA, T0, T1, and T2 registers where
|
|
||||||
* T0 <- MEPC
|
/* Swap TP and MSCRATCH */
|
||||||
* T1 <- MSTATUS
|
csrrw tp, CSR_MSCRATCH, tp
|
||||||
*/
|
|
||||||
|
|
||||||
/* Save MEPC and MSTATUS CSRs */
|
/* Save MEPC and MSTATUS CSRs */
|
||||||
|
csrr t0, CSR_MEPC
|
||||||
REG_S t0, SBI_TRAP_REGS_OFFSET(mepc)(sp)
|
REG_S t0, SBI_TRAP_REGS_OFFSET(mepc)(sp)
|
||||||
REG_S t1, SBI_TRAP_REGS_OFFSET(mstatus)(sp)
|
csrr t0, CSR_MSTATUS
|
||||||
|
REG_S t0, SBI_TRAP_REGS_OFFSET(mstatus)(sp)
|
||||||
|
|
||||||
/* Save all general regisers except SP, RA, T0, T1, and T2 */
|
/* Save all general regisers except SP and T0 */
|
||||||
REG_S zero, SBI_TRAP_REGS_OFFSET(zero)(sp)
|
REG_S zero, SBI_TRAP_REGS_OFFSET(zero)(sp)
|
||||||
|
REG_S ra, SBI_TRAP_REGS_OFFSET(ra)(sp)
|
||||||
REG_S gp, SBI_TRAP_REGS_OFFSET(gp)(sp)
|
REG_S gp, SBI_TRAP_REGS_OFFSET(gp)(sp)
|
||||||
REG_S tp, SBI_TRAP_REGS_OFFSET(tp)(sp)
|
REG_S tp, SBI_TRAP_REGS_OFFSET(tp)(sp)
|
||||||
|
REG_S t1, SBI_TRAP_REGS_OFFSET(t1)(sp)
|
||||||
|
REG_S t2, SBI_TRAP_REGS_OFFSET(t2)(sp)
|
||||||
REG_S s0, SBI_TRAP_REGS_OFFSET(s0)(sp)
|
REG_S s0, SBI_TRAP_REGS_OFFSET(s0)(sp)
|
||||||
REG_S s1, SBI_TRAP_REGS_OFFSET(s1)(sp)
|
REG_S s1, SBI_TRAP_REGS_OFFSET(s1)(sp)
|
||||||
REG_S a0, SBI_TRAP_REGS_OFFSET(a0)(sp)
|
REG_S a0, SBI_TRAP_REGS_OFFSET(a0)(sp)
|
||||||
@@ -291,12 +328,15 @@ _trap_handler:
|
|||||||
|
|
||||||
/* Call C routine */
|
/* Call C routine */
|
||||||
add a0, sp, zero
|
add a0, sp, zero
|
||||||
csrr a1, mscratch
|
csrr a1, CSR_MSCRATCH
|
||||||
call sbi_trap_handler
|
call sbi_trap_handler
|
||||||
|
|
||||||
/* Restore all general regisers except SP, RA, T0, T1, T2, and T3 */
|
/* 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 gp, SBI_TRAP_REGS_OFFSET(gp)(sp)
|
||||||
REG_L tp, SBI_TRAP_REGS_OFFSET(tp)(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 s0, SBI_TRAP_REGS_OFFSET(s0)(sp)
|
||||||
REG_L s1, SBI_TRAP_REGS_OFFSET(s1)(sp)
|
REG_L s1, SBI_TRAP_REGS_OFFSET(s1)(sp)
|
||||||
REG_L a0, SBI_TRAP_REGS_OFFSET(a0)(sp)
|
REG_L a0, SBI_TRAP_REGS_OFFSET(a0)(sp)
|
||||||
@@ -322,26 +362,14 @@ _trap_handler:
|
|||||||
REG_L t5, SBI_TRAP_REGS_OFFSET(t5)(sp)
|
REG_L t5, SBI_TRAP_REGS_OFFSET(t5)(sp)
|
||||||
REG_L t6, SBI_TRAP_REGS_OFFSET(t6)(sp)
|
REG_L t6, SBI_TRAP_REGS_OFFSET(t6)(sp)
|
||||||
|
|
||||||
/* Load T0 and T1 with MEPC and MSTATUS */
|
|
||||||
REG_L t0, SBI_TRAP_REGS_OFFSET(mepc)(sp)
|
|
||||||
REG_L t1, SBI_TRAP_REGS_OFFSET(mstatus)(sp)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note: Jump here after fast trap handling
|
|
||||||
* using SP, RA, T0, T1, and T2
|
|
||||||
* T0 <- MEPC
|
|
||||||
* T1 <- MSTATUS
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Restore MEPC and MSTATUS CSRs */
|
/* Restore MEPC and MSTATUS CSRs */
|
||||||
csrw mepc, t0
|
REG_L t0, SBI_TRAP_REGS_OFFSET(mepc)(sp)
|
||||||
csrw mstatus, t1
|
csrw CSR_MEPC, t0
|
||||||
|
REG_L t0, SBI_TRAP_REGS_OFFSET(mstatus)(sp)
|
||||||
|
csrw CSR_MSTATUS, t0
|
||||||
|
|
||||||
/* Restore RA, T0, T1, and T2 */
|
/* Restore T0 */
|
||||||
REG_L ra, SBI_TRAP_REGS_OFFSET(ra)(sp)
|
|
||||||
REG_L t0, SBI_TRAP_REGS_OFFSET(t0)(sp)
|
REG_L t0, SBI_TRAP_REGS_OFFSET(t0)(sp)
|
||||||
REG_L t1, SBI_TRAP_REGS_OFFSET(t1)(sp)
|
|
||||||
REG_L t2, SBI_TRAP_REGS_OFFSET(t2)(sp)
|
|
||||||
|
|
||||||
/* Restore SP */
|
/* Restore SP */
|
||||||
REG_L sp, SBI_TRAP_REGS_OFFSET(sp)(sp)
|
REG_L sp, SBI_TRAP_REGS_OFFSET(sp)(sp)
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include "fw_base.S"
|
#include "fw_base.S"
|
||||||
|
|
||||||
.align 3
|
.align 4
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
.global fw_prev_arg1
|
.global fw_prev_arg1
|
||||||
fw_prev_arg1:
|
fw_prev_arg1:
|
||||||
@@ -21,7 +21,7 @@ fw_prev_arg1:
|
|||||||
#endif
|
#endif
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.align 3
|
.align 4
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
.global fw_next_arg1
|
.global fw_next_arg1
|
||||||
fw_next_arg1:
|
fw_next_arg1:
|
||||||
@@ -33,7 +33,7 @@ fw_next_arg1:
|
|||||||
#endif
|
#endif
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.align 3
|
.align 4
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
.global fw_next_addr
|
.global fw_next_addr
|
||||||
fw_next_addr:
|
fw_next_addr:
|
||||||
@@ -41,17 +41,15 @@ fw_next_addr:
|
|||||||
la a0, payload_bin
|
la a0, payload_bin
|
||||||
ret
|
ret
|
||||||
|
|
||||||
#define str(s) #s
|
|
||||||
#define stringify(s) str(s)
|
|
||||||
|
|
||||||
#ifdef FW_PAYLOAD_FDT_PATH
|
#ifdef FW_PAYLOAD_FDT_PATH
|
||||||
.align 3
|
.align 4
|
||||||
.section .text, "ax", %progbits
|
.section .text, "ax", %progbits
|
||||||
.globl fdt_bin
|
.globl fdt_bin
|
||||||
fdt_bin:
|
fdt_bin:
|
||||||
.incbin stringify(FW_PAYLOAD_FDT_PATH)
|
.incbin FW_PAYLOAD_FDT_PATH
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
.align 4
|
||||||
.section .payload, "ax", %progbits
|
.section .payload, "ax", %progbits
|
||||||
.globl payload_bin
|
.globl payload_bin
|
||||||
payload_bin:
|
payload_bin:
|
||||||
@@ -59,5 +57,5 @@ payload_bin:
|
|||||||
wfi
|
wfi
|
||||||
j payload_bin
|
j payload_bin
|
||||||
#else
|
#else
|
||||||
.incbin stringify(FW_PAYLOAD_PATH)
|
.incbin FW_PAYLOAD_PATH
|
||||||
#endif
|
#endif
|
||||||
|
@@ -31,7 +31,7 @@ FW_PAYLOAD_PATH_FINAL=$(FW_PAYLOAD_PATH)
|
|||||||
else
|
else
|
||||||
FW_PAYLOAD_PATH_FINAL=$(build_dir)/$(platform_subdir)/firmware/payloads/test.bin
|
FW_PAYLOAD_PATH_FINAL=$(build_dir)/$(platform_subdir)/firmware/payloads/test.bin
|
||||||
endif
|
endif
|
||||||
firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_PATH=$(FW_PAYLOAD_PATH_FINAL)
|
firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_PATH=\"$(FW_PAYLOAD_PATH_FINAL)\"
|
||||||
ifdef FW_PAYLOAD_OFFSET
|
ifdef FW_PAYLOAD_OFFSET
|
||||||
firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_OFFSET=$(FW_PAYLOAD_OFFSET)
|
firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_OFFSET=$(FW_PAYLOAD_OFFSET)
|
||||||
endif
|
endif
|
||||||
@@ -45,7 +45,7 @@ FW_PAYLOAD_FDT_PATH=$(build_dir)/$(platform_subdir)/$(FW_PAYLOAD_FDT)
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
ifdef FW_PAYLOAD_FDT_PATH
|
ifdef FW_PAYLOAD_FDT_PATH
|
||||||
firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_PATH=$(FW_PAYLOAD_FDT_PATH)
|
firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_PATH=\"$(FW_PAYLOAD_FDT_PATH)\"
|
||||||
endif
|
endif
|
||||||
ifdef FW_PAYLOAD_FDT_ADDR
|
ifdef FW_PAYLOAD_FDT_ADDR
|
||||||
firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_ADDR=$(FW_PAYLOAD_FDT_ADDR)
|
firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_ADDR=$(FW_PAYLOAD_FDT_ADDR)
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
* Anup Patel <anup.patel@wdc.com>
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sbi/riscv_encoding.h>
|
||||||
#define __ASM_STR(x) x
|
#define __ASM_STR(x) x
|
||||||
|
|
||||||
#if __riscv_xlen == 64
|
#if __riscv_xlen == 64
|
||||||
@@ -48,12 +49,12 @@ _bss_zero:
|
|||||||
|
|
||||||
_start_warm:
|
_start_warm:
|
||||||
/* Disable and clear all interrupts */
|
/* Disable and clear all interrupts */
|
||||||
csrw sie, zero
|
csrw CSR_SIE, zero
|
||||||
csrw sip, zero
|
csrw CSR_SIP, zero
|
||||||
|
|
||||||
/* Setup exception vectors */
|
/* Setup exception vectors */
|
||||||
la a3, _start_hang
|
la a3, _start_hang
|
||||||
csrw stvec, a3
|
csrw CSR_STVEC, a3
|
||||||
|
|
||||||
/* Setup stack */
|
/* Setup stack */
|
||||||
la a3, _payload_end
|
la a3, _payload_end
|
||||||
|
@@ -10,6 +10,8 @@
|
|||||||
#ifndef __RISCV_ASM_H__
|
#ifndef __RISCV_ASM_H__
|
||||||
#define __RISCV_ASM_H__
|
#define __RISCV_ASM_H__
|
||||||
|
|
||||||
|
#include <sbi/riscv_encoding.h>
|
||||||
|
|
||||||
#ifdef __ASSEMBLY__
|
#ifdef __ASSEMBLY__
|
||||||
#define __ASM_STR(x) x
|
#define __ASM_STR(x) x
|
||||||
#else
|
#else
|
||||||
@@ -144,17 +146,17 @@ do { \
|
|||||||
|
|
||||||
static inline int misa_extension(char ext)
|
static inline int misa_extension(char ext)
|
||||||
{
|
{
|
||||||
return csr_read(misa) & (1 << (ext - 'A'));
|
return csr_read(CSR_MISA) & (1 << (ext - 'A'));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int misa_xlen(void)
|
static inline int misa_xlen(void)
|
||||||
{
|
{
|
||||||
return ((long)csr_read(misa) < 0) ? 64 : 32;
|
return ((long)csr_read(CSR_MISA) < 0) ? 64 : 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void misa_string(char *out, unsigned int out_sz)
|
static inline void misa_string(char *out, unsigned int out_sz)
|
||||||
{
|
{
|
||||||
unsigned long i, val = csr_read(misa);
|
unsigned long i, val = csr_read(CSR_MISA);
|
||||||
|
|
||||||
for (i = 0; i < 26; i++) {
|
for (i = 0; i < 26; i++) {
|
||||||
if (val & (1 << i)) {
|
if (val & (1 << i)) {
|
||||||
|
@@ -195,10 +195,18 @@
|
|||||||
#define RISCV_PGSHIFT 12
|
#define RISCV_PGSHIFT 12
|
||||||
#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)
|
#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)
|
||||||
|
|
||||||
|
#define CSR_USTATUS 0x0
|
||||||
#define CSR_FFLAGS 0x1
|
#define CSR_FFLAGS 0x1
|
||||||
#define CSR_FRM 0x2
|
#define CSR_FRM 0x2
|
||||||
#define CSR_FCSR 0x3
|
#define CSR_FCSR 0x3
|
||||||
#define CSR_CYCLE 0xc00
|
#define CSR_CYCLE 0xc00
|
||||||
|
#define CSR_UIE 0x4
|
||||||
|
#define CSR_UTVEC 0x5
|
||||||
|
#define CSR_USCRATCH 0x40
|
||||||
|
#define CSR_UEPC 0x41
|
||||||
|
#define CSR_UCAUSE 0x42
|
||||||
|
#define CSR_UTVAL 0x43
|
||||||
|
#define CSR_UIP 0x44
|
||||||
#define CSR_TIME 0xc01
|
#define CSR_TIME 0xc01
|
||||||
#define CSR_INSTRET 0xc02
|
#define CSR_INSTRET 0xc02
|
||||||
#define CSR_HPMCOUNTER3 0xc03
|
#define CSR_HPMCOUNTER3 0xc03
|
||||||
|
@@ -43,12 +43,12 @@
|
|||||||
ulong offset = SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \
|
ulong offset = SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \
|
||||||
ulong tmp; \
|
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"); })
|
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(fcsr)
|
#define GET_FCSR() csr_read(CSR_FCSR)
|
||||||
#define SET_FCSR(value) csr_write(fcsr, (value))
|
#define SET_FCSR(value) csr_write(CSR_FCSR, (value))
|
||||||
#define GET_FRM() csr_read(frm)
|
#define GET_FRM() csr_read(CSR_FRM)
|
||||||
#define SET_FRM(value) csr_write(frm, (value))
|
#define SET_FRM(value) csr_write(CSR_FRM, (value))
|
||||||
#define GET_FFLAGS() csr_read(fflags)
|
#define GET_FFLAGS() csr_read(CSR_FFLAGS)
|
||||||
#define SET_FFLAGS(value) csr_write(fflags, (value))
|
#define SET_FFLAGS(value) csr_write(CSR_FFLAGS, (value))
|
||||||
|
|
||||||
#define SET_FS_DIRTY() ((void) 0)
|
#define SET_FS_DIRTY() ((void) 0)
|
||||||
|
|
||||||
|
@@ -30,6 +30,8 @@
|
|||||||
#define SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET (7 * __SIZEOF_POINTER__)
|
#define SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET (7 * __SIZEOF_POINTER__)
|
||||||
/** Offset of ipi_type member in sbi_scratch */
|
/** Offset of ipi_type member in sbi_scratch */
|
||||||
#define SBI_SCRATCH_IPI_TYPE_OFFSET (8 * __SIZEOF_POINTER__)
|
#define SBI_SCRATCH_IPI_TYPE_OFFSET (8 * __SIZEOF_POINTER__)
|
||||||
|
/** Offset of tmp0 member in sbi_scratch */
|
||||||
|
#define SBI_SCRATCH_TMP0_OFFSET (9 * __SIZEOF_POINTER__)
|
||||||
/** Maximum size of sbi_scratch */
|
/** Maximum size of sbi_scratch */
|
||||||
#define SBI_SCRATCH_SIZE 256
|
#define SBI_SCRATCH_SIZE 256
|
||||||
|
|
||||||
@@ -57,11 +59,13 @@ struct sbi_scratch {
|
|||||||
unsigned long hartid_to_scratch;
|
unsigned long hartid_to_scratch;
|
||||||
/** IPI type (or flags) */
|
/** IPI type (or flags) */
|
||||||
unsigned long ipi_type;
|
unsigned long ipi_type;
|
||||||
|
/** Temporary storage */
|
||||||
|
unsigned long tmp0;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
/** Get pointer to sbi_scratch for current HART */
|
/** Get pointer to sbi_scratch for current HART */
|
||||||
#define sbi_scratch_thishart_ptr() \
|
#define sbi_scratch_thishart_ptr() \
|
||||||
((struct sbi_scratch *)csr_read(mscratch))
|
((struct sbi_scratch *)csr_read(CSR_MSCRATCH))
|
||||||
|
|
||||||
/** Get Arg1 of next booting stage for current HART */
|
/** Get Arg1 of next booting stage for current HART */
|
||||||
#define sbi_scratch_thishart_arg1_ptr() \
|
#define sbi_scratch_thishart_arg1_ptr() \
|
||||||
|
@@ -29,11 +29,13 @@ typedef long s64;
|
|||||||
typedef unsigned long u64;
|
typedef unsigned long u64;
|
||||||
typedef long int64_t;
|
typedef long int64_t;
|
||||||
typedef unsigned long uint64_t;
|
typedef unsigned long uint64_t;
|
||||||
|
#define PRILX "016lx"
|
||||||
#elif __riscv_xlen == 32
|
#elif __riscv_xlen == 32
|
||||||
typedef long long s64;
|
typedef long long s64;
|
||||||
typedef unsigned long long u64;
|
typedef unsigned long long u64;
|
||||||
typedef long long int64_t;
|
typedef long long int64_t;
|
||||||
typedef unsigned long long uint64_t;
|
typedef unsigned long long uint64_t;
|
||||||
|
#define PRILX "08lx"
|
||||||
#else
|
#else
|
||||||
#error "Unexpected __riscv_xlen"
|
#error "Unexpected __riscv_xlen"
|
||||||
#endif
|
#endif
|
||||||
|
@@ -20,9 +20,9 @@ static inline type load_##type(const type *addr, ulong mepc) \
|
|||||||
register ulong __mepc asm ("a2") = mepc; \
|
register ulong __mepc asm ("a2") = mepc; \
|
||||||
register ulong __mstatus asm ("a3"); \
|
register ulong __mstatus asm ("a3"); \
|
||||||
type val; \
|
type val; \
|
||||||
asm ("csrrs %0, mstatus, %3\n" \
|
asm ("csrrs %0, "STR(CSR_MSTATUS)", %3\n" \
|
||||||
#insn " %1, %2\n" \
|
#insn " %1, %2\n" \
|
||||||
"csrw mstatus, %0" \
|
"csrw "STR(CSR_MSTATUS)", %0" \
|
||||||
: "+&r" (__mstatus), "=&r" (val) \
|
: "+&r" (__mstatus), "=&r" (val) \
|
||||||
: "m" (*addr), "r" (MSTATUS_MPRV), "r" (__mepc)); \
|
: "m" (*addr), "r" (MSTATUS_MPRV), "r" (__mepc)); \
|
||||||
return val; \
|
return val; \
|
||||||
@@ -33,9 +33,9 @@ static inline void store_##type(type *addr, type val, ulong mepc) \
|
|||||||
{ \
|
{ \
|
||||||
register ulong __mepc asm ("a2") = mepc; \
|
register ulong __mepc asm ("a2") = mepc; \
|
||||||
register ulong __mstatus asm ("a3"); \
|
register ulong __mstatus asm ("a3"); \
|
||||||
asm volatile ("csrrs %0, mstatus, %3\n" \
|
asm volatile ("csrrs %0, "STR(CSR_MSTATUS)", %3\n" \
|
||||||
#insn " %1, %2\n" \
|
#insn " %1, %2\n" \
|
||||||
"csrw mstatus, %0" \
|
"csrw "STR(CSR_MSTATUS)", %0" \
|
||||||
: "+&r" (__mstatus) \
|
: "+&r" (__mstatus) \
|
||||||
: "r" (val), "m" (*addr), "r" (MSTATUS_MPRV), "r" (__mepc)); \
|
: "r" (val), "m" (*addr), "r" (MSTATUS_MPRV), "r" (__mepc)); \
|
||||||
}
|
}
|
||||||
@@ -76,17 +76,25 @@ static inline ulong get_insn(ulong mepc, ulong *mstatus)
|
|||||||
register ulong __mstatus asm ("a3");
|
register ulong __mstatus asm ("a3");
|
||||||
ulong val;
|
ulong val;
|
||||||
#ifndef __riscv_compressed
|
#ifndef __riscv_compressed
|
||||||
asm ("csrrs %[mstatus], mstatus, %[mprv]\n"
|
asm ("csrrs %[mstatus], "STR(CSR_MSTATUS)", %[mprv]\n"
|
||||||
|
#if __riscv_xlen == 64
|
||||||
STR(LWU) " %[insn], (%[addr])\n"
|
STR(LWU) " %[insn], (%[addr])\n"
|
||||||
"csrw mstatus, %[mstatus]"
|
#else
|
||||||
|
STR(LW) " %[insn], (%[addr])\n"
|
||||||
|
#endif
|
||||||
|
"csrw "STR(CSR_MSTATUS)", %[mstatus]"
|
||||||
: [mstatus] "+&r" (__mstatus), [insn] "=&r" (val)
|
: [mstatus] "+&r" (__mstatus), [insn] "=&r" (val)
|
||||||
: [mprv] "r" (MSTATUS_MPRV | MSTATUS_MXR), [addr] "r" (__mepc));
|
: [mprv] "r" (MSTATUS_MPRV | MSTATUS_MXR), [addr] "r" (__mepc));
|
||||||
#else
|
#else
|
||||||
ulong rvc_mask = 3, tmp;
|
ulong rvc_mask = 3, tmp;
|
||||||
asm ("csrrs %[mstatus], mstatus, %[mprv]\n"
|
asm ("csrrs %[mstatus], "STR(CSR_MSTATUS)", %[mprv]\n"
|
||||||
"and %[tmp], %[addr], 2\n"
|
"and %[tmp], %[addr], 2\n"
|
||||||
"bnez %[tmp], 1f\n"
|
"bnez %[tmp], 1f\n"
|
||||||
|
#if __riscv_xlen == 64
|
||||||
STR(LWU) " %[insn], (%[addr])\n"
|
STR(LWU) " %[insn], (%[addr])\n"
|
||||||
|
#else
|
||||||
|
STR(LW) " %[insn], (%[addr])\n"
|
||||||
|
#endif
|
||||||
"and %[tmp], %[insn], %[rvc_mask]\n"
|
"and %[tmp], %[insn], %[rvc_mask]\n"
|
||||||
"beq %[tmp], %[rvc_mask], 2f\n"
|
"beq %[tmp], %[rvc_mask], 2f\n"
|
||||||
"sll %[insn], %[insn], %[xlen_minus_16]\n"
|
"sll %[insn], %[insn], %[xlen_minus_16]\n"
|
||||||
@@ -99,7 +107,7 @@ static inline ulong get_insn(ulong mepc, ulong *mstatus)
|
|||||||
"lhu %[tmp], 2(%[addr])\n"
|
"lhu %[tmp], 2(%[addr])\n"
|
||||||
"sll %[tmp], %[tmp], 16\n"
|
"sll %[tmp], %[tmp], 16\n"
|
||||||
"add %[insn], %[insn], %[tmp]\n"
|
"add %[insn], %[insn], %[tmp]\n"
|
||||||
"2: csrw mstatus, %[mstatus]"
|
"2: csrw "STR(CSR_MSTATUS)", %[mstatus]"
|
||||||
: [mstatus] "+&r" (__mstatus), [insn] "=&r" (val), [tmp] "=&r" (tmp)
|
: [mstatus] "+&r" (__mstatus), [insn] "=&r" (val), [tmp] "=&r" (tmp)
|
||||||
: [mprv] "r" (MSTATUS_MPRV | MSTATUS_MXR), [addr] "r" (__mepc),
|
: [mprv] "r" (MSTATUS_MPRV | MSTATUS_MXR), [addr] "r" (__mepc),
|
||||||
[rvc_mask] "r" (rvc_mask), [xlen_minus_16] "i" (__riscv_xlen - 16));
|
[rvc_mask] "r" (rvc_mask), [xlen_minus_16] "i" (__riscv_xlen - 16));
|
||||||
|
@@ -11,6 +11,6 @@
|
|||||||
#define __SBI_VERSION_H__
|
#define __SBI_VERSION_H__
|
||||||
|
|
||||||
#define OPENSBI_VERSION_MAJOR 0
|
#define OPENSBI_VERSION_MAJOR 0
|
||||||
#define OPENSBI_VERSION_MINOR 1
|
#define OPENSBI_VERSION_MINOR 2
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -39,7 +39,7 @@ int sbi_ecall_handler(u32 hartid, ulong mcause,
|
|||||||
case SBI_ECALL_SET_TIMER:
|
case SBI_ECALL_SET_TIMER:
|
||||||
#if __riscv_xlen == 32
|
#if __riscv_xlen == 32
|
||||||
sbi_timer_event_start(scratch,
|
sbi_timer_event_start(scratch,
|
||||||
(((u64)regs->a1 << 32) || (u64)regs->a0));
|
(((u64)regs->a1 << 32) | (u64)regs->a0));
|
||||||
#else
|
#else
|
||||||
sbi_timer_event_start(scratch, (u64)regs->a0);
|
sbi_timer_event_start(scratch, (u64)regs->a0);
|
||||||
#endif
|
#endif
|
||||||
|
@@ -23,13 +23,13 @@ int sbi_emulate_csr_read(int csr_num,
|
|||||||
ulong cen = -1UL;
|
ulong cen = -1UL;
|
||||||
|
|
||||||
if (EXTRACT_FIELD(mstatus, MSTATUS_MPP) == PRV_U)
|
if (EXTRACT_FIELD(mstatus, MSTATUS_MPP) == PRV_U)
|
||||||
cen = csr_read(scounteren);
|
cen = csr_read(CSR_SCOUNTEREN);
|
||||||
|
|
||||||
switch (csr_num) {
|
switch (csr_num) {
|
||||||
case CSR_CYCLE:
|
case CSR_CYCLE:
|
||||||
if (!((cen >> (CSR_CYCLE - CSR_CYCLE)) & 1))
|
if (!((cen >> (CSR_CYCLE - CSR_CYCLE)) & 1))
|
||||||
return -1;
|
return -1;
|
||||||
*csr_val = csr_read(mcycle);
|
*csr_val = csr_read(CSR_MCYCLE);
|
||||||
break;
|
break;
|
||||||
case CSR_TIME:
|
case CSR_TIME:
|
||||||
if (!((cen >> (CSR_TIME - CSR_CYCLE)) & 1))
|
if (!((cen >> (CSR_TIME - CSR_CYCLE)) & 1))
|
||||||
@@ -39,51 +39,50 @@ int sbi_emulate_csr_read(int csr_num,
|
|||||||
case CSR_INSTRET:
|
case CSR_INSTRET:
|
||||||
if (!((cen >> (CSR_INSTRET - CSR_CYCLE)) & 1))
|
if (!((cen >> (CSR_INSTRET - CSR_CYCLE)) & 1))
|
||||||
return -1;
|
return -1;
|
||||||
*csr_val = csr_read(minstret);
|
*csr_val = csr_read(CSR_MINSTRET);
|
||||||
break;
|
break;
|
||||||
case CSR_MHPMCOUNTER3:
|
case CSR_MHPMCOUNTER3:
|
||||||
if (!((cen >> (3 + CSR_MHPMCOUNTER3 - CSR_MHPMCOUNTER3)) & 1))
|
if (!((cen >> (3 + CSR_MHPMCOUNTER3 - CSR_MHPMCOUNTER3)) & 1))
|
||||||
return -1;
|
return -1;
|
||||||
*csr_val = csr_read(mhpmcounter3);
|
*csr_val = csr_read(CSR_MHPMCOUNTER3);
|
||||||
break;
|
break;
|
||||||
case CSR_MHPMCOUNTER4:
|
case CSR_MHPMCOUNTER4:
|
||||||
if (!((cen >> (3 + CSR_MHPMCOUNTER4 - CSR_MHPMCOUNTER3)) & 1))
|
if (!((cen >> (3 + CSR_MHPMCOUNTER4 - CSR_MHPMCOUNTER3)) & 1))
|
||||||
return -1;
|
return -1;
|
||||||
*csr_val = csr_read(mhpmcounter4);
|
*csr_val = csr_read(CSR_MHPMCOUNTER4);
|
||||||
break;
|
break;
|
||||||
#if __riscv_xlen == 32
|
#if __riscv_xlen == 32
|
||||||
case CSR_CYCLEH:
|
case CSR_CYCLEH:
|
||||||
if (!((cen >> (CSR_CYCLE - CSR_CYCLE)) & 1))
|
if (!((cen >> (CSR_CYCLE - CSR_CYCLE)) & 1))
|
||||||
return -1;
|
return -1;
|
||||||
*csr_val = csr_read(mcycleh);
|
*csr_val = csr_read(CSR_MCYCLEH);
|
||||||
break;
|
break;
|
||||||
case CSR_TIMEH:
|
case CSR_TIMEH:
|
||||||
if (!((cen >> (CSR_TIME - CSR_CYCLE)) & 1))
|
if (!((cen >> (CSR_TIME - CSR_CYCLE)) & 1))
|
||||||
return -1;
|
return -1;
|
||||||
*csr_val = sbi_timer_value(scratch);
|
*csr_val = sbi_timer_value(scratch) >> 32;
|
||||||
*csr_val = *csr_val >> 32;
|
|
||||||
break;
|
break;
|
||||||
case CSR_INSTRETH:
|
case CSR_INSTRETH:
|
||||||
if (!((cen >> (CSR_INSTRET - CSR_CYCLE)) & 1))
|
if (!((cen >> (CSR_INSTRET - CSR_CYCLE)) & 1))
|
||||||
return -1;
|
return -1;
|
||||||
*csr_val = csr_read(minstreth);
|
*csr_val = csr_read(CSR_MINSTRETH);
|
||||||
break;
|
break;
|
||||||
case CSR_MHPMCOUNTER3H:
|
case CSR_MHPMCOUNTER3H:
|
||||||
if (!((cen >> (3 + CSR_MHPMCOUNTER3 - CSR_MHPMCOUNTER3)) & 1))
|
if (!((cen >> (3 + CSR_MHPMCOUNTER3 - CSR_MHPMCOUNTER3)) & 1))
|
||||||
return -1;
|
return -1;
|
||||||
*csr_val = csr_read(mhpmcounter3h);
|
*csr_val = csr_read(CSR_MHPMCOUNTER3H);
|
||||||
break;
|
break;
|
||||||
case CSR_MHPMCOUNTER4H:
|
case CSR_MHPMCOUNTER4H:
|
||||||
if (!((cen >> (3 + CSR_MHPMCOUNTER4 - CSR_MHPMCOUNTER3)) & 1))
|
if (!((cen >> (3 + CSR_MHPMCOUNTER4 - CSR_MHPMCOUNTER3)) & 1))
|
||||||
return -1;
|
return -1;
|
||||||
*csr_val = csr_read(mhpmcounter4h);
|
*csr_val = csr_read(CSR_MHPMCOUNTER4H);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case CSR_MHPMEVENT3:
|
case CSR_MHPMEVENT3:
|
||||||
*csr_val = csr_read(mhpmevent3);
|
*csr_val = csr_read(CSR_MHPMEVENT3);
|
||||||
break;
|
break;
|
||||||
case CSR_MHPMEVENT4:
|
case CSR_MHPMEVENT4:
|
||||||
*csr_val = csr_read(mhpmevent4);
|
*csr_val = csr_read(CSR_MHPMEVENT4);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sbi_printf("%s: hartid%d: invalid csr_num=0x%x\n",
|
sbi_printf("%s: hartid%d: invalid csr_num=0x%x\n",
|
||||||
@@ -101,36 +100,36 @@ int sbi_emulate_csr_write(int csr_num,
|
|||||||
{
|
{
|
||||||
switch (csr_num) {
|
switch (csr_num) {
|
||||||
case CSR_CYCLE:
|
case CSR_CYCLE:
|
||||||
csr_write(mcycle, csr_val);
|
csr_write(CSR_MCYCLE, csr_val);
|
||||||
break;
|
break;
|
||||||
case CSR_INSTRET:
|
case CSR_INSTRET:
|
||||||
csr_write(minstret, csr_val);
|
csr_write(CSR_MINSTRET, csr_val);
|
||||||
break;
|
break;
|
||||||
case CSR_MHPMCOUNTER3:
|
case CSR_MHPMCOUNTER3:
|
||||||
csr_write(mhpmcounter3, csr_val);
|
csr_write(CSR_MHPMCOUNTER3, csr_val);
|
||||||
break;
|
break;
|
||||||
case CSR_MHPMCOUNTER4:
|
case CSR_MHPMCOUNTER4:
|
||||||
csr_write(mhpmcounter4, csr_val);
|
csr_write(CSR_MHPMCOUNTER4, csr_val);
|
||||||
break;
|
break;
|
||||||
#if __riscv_xlen == 32
|
#if __riscv_xlen == 32
|
||||||
case CSR_CYCLEH:
|
case CSR_CYCLEH:
|
||||||
csr_write(mcycleh, csr_val);
|
csr_write(CSR_MCYCLEH, csr_val);
|
||||||
break;
|
break;
|
||||||
case CSR_INSTRETH:
|
case CSR_INSTRETH:
|
||||||
csr_write(minstreth, csr_val);
|
csr_write(CSR_MINSTRETH, csr_val);
|
||||||
break;
|
break;
|
||||||
case CSR_MHPMCOUNTER3H:
|
case CSR_MHPMCOUNTER3H:
|
||||||
csr_write(mhpmcounter3h, csr_val);
|
csr_write(CSR_MHPMCOUNTER3H, csr_val);
|
||||||
break;
|
break;
|
||||||
case CSR_MHPMCOUNTER4H:
|
case CSR_MHPMCOUNTER4H:
|
||||||
csr_write(mhpmcounter4h, csr_val);
|
csr_write(CSR_MHPMCOUNTER4H, csr_val);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case CSR_MHPMEVENT3:
|
case CSR_MHPMEVENT3:
|
||||||
csr_write(mhpmevent3, csr_val);
|
csr_write(CSR_MHPMEVENT3, csr_val);
|
||||||
break;
|
break;
|
||||||
case CSR_MHPMEVENT4:
|
case CSR_MHPMEVENT4:
|
||||||
csr_write(mhpmevent4, csr_val);
|
csr_write(CSR_MHPMEVENT4, csr_val);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sbi_printf("%s: hartid%d: invalid csr_num=0x%x\n",
|
sbi_printf("%s: hartid%d: invalid csr_num=0x%x\n",
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
unsigned int sbi_current_hartid()
|
unsigned int sbi_current_hartid()
|
||||||
{
|
{
|
||||||
return (u32)csr_read(mhartid);
|
return (u32)csr_read(CSR_MHARTID);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mstatus_init(struct sbi_scratch *scratch, u32 hartid)
|
static void mstatus_init(struct sbi_scratch *scratch, u32 hartid)
|
||||||
@@ -32,21 +32,21 @@ static void mstatus_init(struct sbi_scratch *scratch, u32 hartid)
|
|||||||
|
|
||||||
/* Enable FPU */
|
/* Enable FPU */
|
||||||
if (misa_extension('D') || misa_extension('F'))
|
if (misa_extension('D') || misa_extension('F'))
|
||||||
csr_write(mstatus, MSTATUS_FS);
|
csr_write(CSR_MSTATUS, MSTATUS_FS);
|
||||||
|
|
||||||
/* Enable user/supervisor use of perf counters */
|
/* Enable user/supervisor use of perf counters */
|
||||||
if (misa_extension('S') &&
|
if (misa_extension('S') &&
|
||||||
sbi_platform_has_scounteren(plat))
|
sbi_platform_has_scounteren(plat))
|
||||||
csr_write(scounteren, -1);
|
csr_write(CSR_SCOUNTEREN, -1);
|
||||||
if (sbi_platform_has_mcounteren(plat))
|
if (sbi_platform_has_mcounteren(plat))
|
||||||
csr_write(mcounteren, -1);
|
csr_write(CSR_MCOUNTEREN, -1);
|
||||||
|
|
||||||
/* Disable all interrupts */
|
/* Disable all interrupts */
|
||||||
csr_write(mie, 0);
|
csr_write(CSR_MIE, 0);
|
||||||
|
|
||||||
/* Disable S-mode paging */
|
/* Disable S-mode paging */
|
||||||
if (misa_extension('S'))
|
if (misa_extension('S'))
|
||||||
csr_write(sptbr, 0);
|
csr_write(CSR_SATP, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fp_init(u32 hartid)
|
static int fp_init(u32 hartid)
|
||||||
@@ -60,17 +60,17 @@ static int fp_init(u32 hartid)
|
|||||||
if (!misa_extension('D') && !misa_extension('F'))
|
if (!misa_extension('D') && !misa_extension('F'))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!(csr_read(mstatus) & MSTATUS_FS))
|
if (!(csr_read(CSR_MSTATUS) & MSTATUS_FS))
|
||||||
return SBI_EINVAL;
|
return SBI_EINVAL;
|
||||||
|
|
||||||
#ifdef __riscv_flen
|
#ifdef __riscv_flen
|
||||||
for (i = 0; i < 32; i++)
|
for (i = 0; i < 32; i++)
|
||||||
init_fp_reg(i);
|
init_fp_reg(i);
|
||||||
csr_write(fcsr, 0);
|
csr_write(CSR_FCSR, 0);
|
||||||
#else
|
#else
|
||||||
fd_mask = (1 << ('F' - 'A')) | (1 << ('D' - 'A'));
|
fd_mask = (1 << ('F' - 'A')) | (1 << ('D' - 'A'));
|
||||||
csr_clear(misa, fd_mask);
|
csr_clear(CSR_MISA, fd_mask);
|
||||||
if (csr_read(misa) & fd_mask)
|
if (csr_read(CSR_MISA) & fd_mask)
|
||||||
return SBI_ENOTSUPP;
|
return SBI_ENOTSUPP;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -96,12 +96,12 @@ static int delegate_traps(struct sbi_scratch *scratch, u32 hartid)
|
|||||||
(1U << CAUSE_LOAD_PAGE_FAULT) |
|
(1U << CAUSE_LOAD_PAGE_FAULT) |
|
||||||
(1U << CAUSE_STORE_PAGE_FAULT);
|
(1U << CAUSE_STORE_PAGE_FAULT);
|
||||||
|
|
||||||
csr_write(mideleg, interrupts);
|
csr_write(CSR_MIDELEG, interrupts);
|
||||||
csr_write(medeleg, exceptions);
|
csr_write(CSR_MEDELEG, exceptions);
|
||||||
|
|
||||||
if (csr_read(mideleg) != interrupts)
|
if (csr_read(CSR_MIDELEG) != interrupts)
|
||||||
return SBI_EFAIL;
|
return SBI_EFAIL;
|
||||||
if (csr_read(medeleg) != exceptions)
|
if (csr_read(CSR_MEDELEG) != exceptions)
|
||||||
return SBI_EFAIL;
|
return SBI_EFAIL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -230,22 +230,22 @@ void __attribute__((noreturn)) sbi_hart_switch_mode(unsigned long arg0,
|
|||||||
sbi_hart_hang();
|
sbi_hart_hang();
|
||||||
}
|
}
|
||||||
|
|
||||||
val = csr_read(mstatus);
|
val = csr_read(CSR_MSTATUS);
|
||||||
val = INSERT_FIELD(val, MSTATUS_MPP, next_mode);
|
val = INSERT_FIELD(val, MSTATUS_MPP, next_mode);
|
||||||
val = INSERT_FIELD(val, MSTATUS_MPIE, 0);
|
val = INSERT_FIELD(val, MSTATUS_MPIE, 0);
|
||||||
|
|
||||||
csr_write(mstatus, val);
|
csr_write(CSR_MSTATUS, val);
|
||||||
csr_write(mepc, next_addr);
|
csr_write(CSR_MEPC, next_addr);
|
||||||
|
|
||||||
if (next_mode == PRV_S) {
|
if (next_mode == PRV_S) {
|
||||||
csr_write(stvec, next_addr);
|
csr_write(CSR_STVEC, next_addr);
|
||||||
csr_write(sscratch, 0);
|
csr_write(CSR_SSCRATCH, 0);
|
||||||
csr_write(sie, 0);
|
csr_write(CSR_SIE, 0);
|
||||||
csr_write(satp, 0);
|
csr_write(CSR_SATP, 0);
|
||||||
} else if (next_mode == PRV_U) {
|
} else if (next_mode == PRV_U) {
|
||||||
csr_write(utvec, next_addr);
|
csr_write(CSR_UTVEC, next_addr);
|
||||||
csr_write(uscratch, 0);
|
csr_write(CSR_USCRATCH, 0);
|
||||||
csr_write(uie, 0);
|
csr_write(CSR_UIE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
register unsigned long a0 asm ("a0") = arg0;
|
register unsigned long a0 asm ("a0") = arg0;
|
||||||
@@ -304,7 +304,7 @@ void sbi_hart_wait_for_coldboot(struct sbi_scratch *scratch, u32 hartid)
|
|||||||
sbi_hart_hang();
|
sbi_hart_hang();
|
||||||
|
|
||||||
/* Set MSIE bit to receive IPI */
|
/* Set MSIE bit to receive IPI */
|
||||||
csr_set(mie, MIP_MSIP);
|
csr_set(CSR_MIE, MIP_MSIP);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
spin_lock(&coldboot_wait_bitmap_lock);
|
spin_lock(&coldboot_wait_bitmap_lock);
|
||||||
@@ -312,14 +312,14 @@ void sbi_hart_wait_for_coldboot(struct sbi_scratch *scratch, u32 hartid)
|
|||||||
spin_unlock(&coldboot_wait_bitmap_lock);
|
spin_unlock(&coldboot_wait_bitmap_lock);
|
||||||
|
|
||||||
wfi();
|
wfi();
|
||||||
mipval = csr_read(mip);
|
mipval = csr_read(CSR_MIP);
|
||||||
|
|
||||||
spin_lock(&coldboot_wait_bitmap_lock);
|
spin_lock(&coldboot_wait_bitmap_lock);
|
||||||
coldboot_wait_bitmap &= ~(1UL << hartid);
|
coldboot_wait_bitmap &= ~(1UL << hartid);
|
||||||
spin_unlock(&coldboot_wait_bitmap_lock);
|
spin_unlock(&coldboot_wait_bitmap_lock);
|
||||||
} while (!(mipval && MIP_MSIP));
|
} while (!(mipval && MIP_MSIP));
|
||||||
|
|
||||||
csr_clear(mip, MIP_MSIP);
|
csr_clear(CSR_MIP, MIP_MSIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sbi_hart_wake_coldboot_harts(struct sbi_scratch *scratch, u32 hartid)
|
void sbi_hart_wake_coldboot_harts(struct sbi_scratch *scratch, u32 hartid)
|
||||||
|
@@ -127,7 +127,7 @@ int sbi_illegal_insn_handler(u32 hartid, ulong mcause,
|
|||||||
|
|
||||||
if (unlikely((insn & 3) != 3)) {
|
if (unlikely((insn & 3) != 3)) {
|
||||||
if (insn == 0) {
|
if (insn == 0) {
|
||||||
mstatus = csr_read(mstatus);
|
mstatus = csr_read(CSR_MSTATUS);
|
||||||
insn = get_insn(regs->mepc, &mstatus);
|
insn = get_insn(regs->mepc, &mstatus);
|
||||||
}
|
}
|
||||||
if ((insn & 3) != 3)
|
if ((insn & 3) != 3)
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Anup Patel <anup.patel@wdc.com>
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
* Nick Kossifidis <mick@ics.forth.gr>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sbi/riscv_asm.h>
|
#include <sbi/riscv_asm.h>
|
||||||
@@ -18,35 +19,55 @@
|
|||||||
#include <sbi/sbi_timer.h>
|
#include <sbi/sbi_timer.h>
|
||||||
#include <sbi/sbi_unpriv.h>
|
#include <sbi/sbi_unpriv.h>
|
||||||
|
|
||||||
|
static int sbi_ipi_send(struct sbi_scratch *scratch, u32 hartid, u32 event)
|
||||||
|
{
|
||||||
|
struct sbi_scratch *remote_scratch = NULL;
|
||||||
|
struct sbi_platform *plat = sbi_platform_ptr(scratch);
|
||||||
|
|
||||||
|
if (sbi_platform_hart_disabled(plat, hartid))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Set IPI type on remote hart's scratch area and
|
||||||
|
* trigger the interrupt
|
||||||
|
*/
|
||||||
|
remote_scratch = sbi_hart_id_to_scratch(scratch, hartid);
|
||||||
|
atomic_raw_set_bit(event, &remote_scratch->ipi_type);
|
||||||
|
mb();
|
||||||
|
sbi_platform_ipi_send(plat, hartid);
|
||||||
|
if (event != SBI_IPI_EVENT_SOFT)
|
||||||
|
sbi_platform_ipi_sync(plat, hartid);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int sbi_ipi_send_many(struct sbi_scratch *scratch,
|
int sbi_ipi_send_many(struct sbi_scratch *scratch,
|
||||||
ulong *pmask, u32 event)
|
ulong *pmask, u32 event)
|
||||||
{
|
{
|
||||||
ulong i, m;
|
ulong i, m;
|
||||||
struct sbi_scratch *oth;
|
|
||||||
ulong mask = sbi_hart_available_mask();
|
ulong mask = sbi_hart_available_mask();
|
||||||
struct sbi_platform *plat = sbi_platform_ptr(scratch);
|
u32 hartid = sbi_current_hartid();
|
||||||
|
|
||||||
if (pmask)
|
if (pmask)
|
||||||
mask &= load_ulong(pmask, csr_read(mepc));
|
mask &= load_ulong(pmask, csr_read(CSR_MEPC));
|
||||||
|
|
||||||
|
/* send IPIs to every other hart on the set */
|
||||||
|
for (i = 0, m = mask; m; i++, m >>= 1)
|
||||||
|
if ((m & 1UL) && (i != hartid))
|
||||||
|
sbi_ipi_send(scratch, i, event);
|
||||||
|
|
||||||
|
/* If the current hart is on the set, send an IPI
|
||||||
|
* to it as well
|
||||||
|
*/
|
||||||
|
if (mask & (1UL << hartid))
|
||||||
|
sbi_ipi_send(scratch, hartid, event);
|
||||||
|
|
||||||
/* send IPIs to everyone */
|
|
||||||
for (i = 0, m = mask; m; i++, m >>= 1) {
|
|
||||||
if ((m & 1) && !sbi_platform_hart_disabled(plat, i)) {
|
|
||||||
oth = sbi_hart_id_to_scratch(scratch, i);
|
|
||||||
atomic_raw_set_bit(event, &oth->ipi_type);
|
|
||||||
mb();
|
|
||||||
sbi_platform_ipi_send(plat, i);
|
|
||||||
if (event != SBI_IPI_EVENT_SOFT)
|
|
||||||
sbi_platform_ipi_sync(plat, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sbi_ipi_clear_smode(struct sbi_scratch *scratch)
|
void sbi_ipi_clear_smode(struct sbi_scratch *scratch)
|
||||||
{
|
{
|
||||||
csr_clear(mip, MIP_SSIP);
|
csr_clear(CSR_MIP, MIP_SSIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sbi_ipi_process(struct sbi_scratch *scratch)
|
void sbi_ipi_process(struct sbi_scratch *scratch)
|
||||||
@@ -64,7 +85,7 @@ void sbi_ipi_process(struct sbi_scratch *scratch)
|
|||||||
ipi_event = __ffs(ipi_type);
|
ipi_event = __ffs(ipi_type);
|
||||||
switch (ipi_event) {
|
switch (ipi_event) {
|
||||||
case SBI_IPI_EVENT_SOFT:
|
case SBI_IPI_EVENT_SOFT:
|
||||||
csr_set(mip, MIP_SSIP);
|
csr_set(CSR_MIP, MIP_SSIP);
|
||||||
break;
|
break;
|
||||||
case SBI_IPI_EVENT_FENCE_I:
|
case SBI_IPI_EVENT_FENCE_I:
|
||||||
__asm__ __volatile("fence.i");
|
__asm__ __volatile("fence.i");
|
||||||
@@ -83,7 +104,7 @@ void sbi_ipi_process(struct sbi_scratch *scratch)
|
|||||||
int sbi_ipi_init(struct sbi_scratch *scratch, bool cold_boot)
|
int sbi_ipi_init(struct sbi_scratch *scratch, bool cold_boot)
|
||||||
{
|
{
|
||||||
/* Enable software interrupts */
|
/* Enable software interrupts */
|
||||||
csr_set(mie, MIP_MSIP);
|
csr_set(CSR_MIE, MIP_MSIP);
|
||||||
|
|
||||||
return sbi_platform_ipi_init(sbi_platform_ptr(scratch),
|
return sbi_platform_ipi_init(sbi_platform_ptr(scratch),
|
||||||
cold_boot);
|
cold_boot);
|
||||||
|
@@ -26,9 +26,9 @@ int sbi_misaligned_load_handler(u32 hartid, ulong mcause,
|
|||||||
struct sbi_scratch *scratch)
|
struct sbi_scratch *scratch)
|
||||||
{
|
{
|
||||||
union reg_data val;
|
union reg_data val;
|
||||||
ulong mstatus = csr_read(mstatus);
|
ulong mstatus = csr_read(CSR_MSTATUS);
|
||||||
ulong insn = get_insn(regs->mepc, &mstatus);
|
ulong insn = get_insn(regs->mepc, &mstatus);
|
||||||
ulong addr = csr_read(mtval);
|
ulong addr = csr_read(CSR_MTVAL);
|
||||||
int i, fp = 0, shift = 0, len = 0;
|
int i, fp = 0, shift = 0, len = 0;
|
||||||
|
|
||||||
if ((insn & INSN_MASK_LW) == INSN_MATCH_LW) {
|
if ((insn & INSN_MASK_LW) == INSN_MATCH_LW) {
|
||||||
@@ -112,9 +112,9 @@ int sbi_misaligned_store_handler(u32 hartid, ulong mcause,
|
|||||||
struct sbi_scratch *scratch)
|
struct sbi_scratch *scratch)
|
||||||
{
|
{
|
||||||
union reg_data val;
|
union reg_data val;
|
||||||
ulong mstatus = csr_read(mstatus);
|
ulong mstatus = csr_read(CSR_MSTATUS);
|
||||||
ulong insn = get_insn(regs->mepc, &mstatus);
|
ulong insn = get_insn(regs->mepc, &mstatus);
|
||||||
ulong addr = csr_read(mtval);
|
ulong addr = csr_read(CSR_MTVAL);
|
||||||
int i, len = 0;
|
int i, len = 0;
|
||||||
|
|
||||||
val.data_ulong = GET_RS2(insn, regs);
|
val.data_ulong = GET_RS2(insn, regs);
|
||||||
|
@@ -5,11 +5,13 @@
|
|||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Anup Patel <anup.patel@wdc.com>
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
* Nick Kossifidis <mick@ics.forth.gr>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sbi/sbi_hart.h>
|
#include <sbi/sbi_hart.h>
|
||||||
#include <sbi/sbi_platform.h>
|
#include <sbi/sbi_platform.h>
|
||||||
#include <sbi/sbi_system.h>
|
#include <sbi/sbi_system.h>
|
||||||
|
#include <sbi/sbi_ipi.h>
|
||||||
|
|
||||||
int sbi_system_early_init(struct sbi_scratch *scratch, bool cold_boot)
|
int sbi_system_early_init(struct sbi_scratch *scratch, bool cold_boot)
|
||||||
{
|
{
|
||||||
@@ -34,6 +36,12 @@ void __attribute__((noreturn)) sbi_system_reboot(struct sbi_scratch *scratch,
|
|||||||
void __attribute__((noreturn)) sbi_system_shutdown(struct sbi_scratch *scratch,
|
void __attribute__((noreturn)) sbi_system_shutdown(struct sbi_scratch *scratch,
|
||||||
u32 type)
|
u32 type)
|
||||||
{
|
{
|
||||||
|
/* First try the platform-specific method */
|
||||||
sbi_platform_system_shutdown(sbi_platform_ptr(scratch), type);
|
sbi_platform_system_shutdown(sbi_platform_ptr(scratch), type);
|
||||||
|
|
||||||
|
/* If that fails (or is not implemented) send an IPI on every
|
||||||
|
* hart to hang and then hang the current hart */
|
||||||
|
sbi_ipi_send_many(scratch, NULL, SBI_IPI_EVENT_HALT);
|
||||||
|
|
||||||
sbi_hart_hang();
|
sbi_hart_hang();
|
||||||
}
|
}
|
||||||
|
@@ -56,14 +56,14 @@ void sbi_timer_event_start(struct sbi_scratch *scratch, u64 next_event)
|
|||||||
{
|
{
|
||||||
sbi_platform_timer_event_start(sbi_platform_ptr(scratch),
|
sbi_platform_timer_event_start(sbi_platform_ptr(scratch),
|
||||||
next_event);
|
next_event);
|
||||||
csr_clear(mip, MIP_STIP);
|
csr_clear(CSR_MIP, MIP_STIP);
|
||||||
csr_set(mie, MIP_MTIP);
|
csr_set(CSR_MIE, MIP_MTIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sbi_timer_process(struct sbi_scratch *scratch)
|
void sbi_timer_process(struct sbi_scratch *scratch)
|
||||||
{
|
{
|
||||||
csr_clear(mie, MIP_MTIP);
|
csr_clear(CSR_MIE, MIP_MTIP);
|
||||||
csr_set(mip, MIP_STIP);
|
csr_set(CSR_MIP, MIP_STIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sbi_timer_init(struct sbi_scratch *scratch, bool cold_boot)
|
int sbi_timer_init(struct sbi_scratch *scratch, bool cold_boot)
|
||||||
|
@@ -26,41 +26,41 @@ static void __noreturn sbi_trap_error(const char *msg,
|
|||||||
{
|
{
|
||||||
sbi_printf("%s: hart%d: %s (error %d)\n",
|
sbi_printf("%s: hart%d: %s (error %d)\n",
|
||||||
__func__, hartid, msg, rc);
|
__func__, hartid, msg, rc);
|
||||||
sbi_printf("%s: hart%d: mcause=0x%lx mtval=0x%lx\n",
|
sbi_printf("%s: hart%d: mcause=0x%"PRILX" mtval=0x%"PRILX"\n",
|
||||||
__func__, hartid, mcause, mtval);
|
__func__, hartid, mcause, mtval);
|
||||||
sbi_printf("%s: hart%d: mepc=0x%lx mstatus=0x%lx\n",
|
sbi_printf("%s: hart%d: mepc=0x%"PRILX" mstatus=0x%"PRILX"\n",
|
||||||
__func__, hartid, regs->mepc, regs->mstatus);
|
__func__, hartid, regs->mepc, regs->mstatus);
|
||||||
sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
|
sbi_printf("%s: hart%d: %s=0x%"PRILX" %s=0x%"PRILX"\n",
|
||||||
__func__, hartid, "ra", regs->ra, "sp", regs->sp);
|
__func__, hartid, "ra", regs->ra, "sp", regs->sp);
|
||||||
sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
|
sbi_printf("%s: hart%d: %s=0x%"PRILX" %s=0x%"PRILX"\n",
|
||||||
__func__, hartid, "gp", regs->gp, "tp", regs->tp);
|
__func__, hartid, "gp", regs->gp, "tp", regs->tp);
|
||||||
sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
|
sbi_printf("%s: hart%d: %s=0x%"PRILX" %s=0x%"PRILX"\n",
|
||||||
__func__, hartid, "s0", regs->s0, "s1", regs->s1);
|
__func__, hartid, "s0", regs->s0, "s1", regs->s1);
|
||||||
sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
|
sbi_printf("%s: hart%d: %s=0x%"PRILX" %s=0x%"PRILX"\n",
|
||||||
__func__, hartid, "a0", regs->a0, "a1", regs->a1);
|
__func__, hartid, "a0", regs->a0, "a1", regs->a1);
|
||||||
sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
|
sbi_printf("%s: hart%d: %s=0x%"PRILX" %s=0x%"PRILX"\n",
|
||||||
__func__, hartid, "a2", regs->a2, "a3", regs->a3);
|
__func__, hartid, "a2", regs->a2, "a3", regs->a3);
|
||||||
sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
|
sbi_printf("%s: hart%d: %s=0x%"PRILX" %s=0x%"PRILX"\n",
|
||||||
__func__, hartid, "a4", regs->a4, "a5", regs->a5);
|
__func__, hartid, "a4", regs->a4, "a5", regs->a5);
|
||||||
sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
|
sbi_printf("%s: hart%d: %s=0x%"PRILX" %s=0x%"PRILX"\n",
|
||||||
__func__, hartid, "a6", regs->a6, "a7", regs->a7);
|
__func__, hartid, "a6", regs->a6, "a7", regs->a7);
|
||||||
sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
|
sbi_printf("%s: hart%d: %s=0x%"PRILX" %s=0x%"PRILX"\n",
|
||||||
__func__, hartid, "s2", regs->s2, "s3", regs->s3);
|
__func__, hartid, "s2", regs->s2, "s3", regs->s3);
|
||||||
sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
|
sbi_printf("%s: hart%d: %s=0x%"PRILX" %s=0x%"PRILX"\n",
|
||||||
__func__, hartid, "s4", regs->s4, "s5", regs->s5);
|
__func__, hartid, "s4", regs->s4, "s5", regs->s5);
|
||||||
sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
|
sbi_printf("%s: hart%d: %s=0x%"PRILX" %s=0x%"PRILX"\n",
|
||||||
__func__, hartid, "s6", regs->s6, "s7", regs->s7);
|
__func__, hartid, "s6", regs->s6, "s7", regs->s7);
|
||||||
sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
|
sbi_printf("%s: hart%d: %s=0x%"PRILX" %s=0x%"PRILX"\n",
|
||||||
__func__, hartid, "s8", regs->s8, "s9", regs->s9);
|
__func__, hartid, "s8", regs->s8, "s9", regs->s9);
|
||||||
sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
|
sbi_printf("%s: hart%d: %s=0x%"PRILX" %s=0x%"PRILX"\n",
|
||||||
__func__, hartid, "s10", regs->s10, "s11", regs->s11);
|
__func__, hartid, "s10", regs->s10, "s11", regs->s11);
|
||||||
sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
|
sbi_printf("%s: hart%d: %s=0x%"PRILX" %s=0x%"PRILX"\n",
|
||||||
__func__, hartid, "t0", regs->t0, "t1", regs->t1);
|
__func__, hartid, "t0", regs->t0, "t1", regs->t1);
|
||||||
sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
|
sbi_printf("%s: hart%d: %s=0x%"PRILX" %s=0x%"PRILX"\n",
|
||||||
__func__, hartid, "t2", regs->t2, "t3", regs->t3);
|
__func__, hartid, "t2", regs->t2, "t3", regs->t3);
|
||||||
sbi_printf("%s: hart%d: %s=0x%lx %s=0x%lx\n",
|
sbi_printf("%s: hart%d: %s=0x%"PRILX" %s=0x%"PRILX"\n",
|
||||||
__func__, hartid, "t4", regs->t4, "t5", regs->t5);
|
__func__, hartid, "t4", regs->t4, "t5", regs->t5);
|
||||||
sbi_printf("%s: hart%d: %s=0x%lx\n",
|
sbi_printf("%s: hart%d: %s=0x%"PRILX"\n",
|
||||||
__func__, hartid, "t6", regs->t6);
|
__func__, hartid, "t6", regs->t6);
|
||||||
|
|
||||||
sbi_hart_hang();
|
sbi_hart_hang();
|
||||||
@@ -89,12 +89,12 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs,
|
|||||||
return SBI_ENOTSUPP;
|
return SBI_ENOTSUPP;
|
||||||
|
|
||||||
/* Update S-mode exception info */
|
/* Update S-mode exception info */
|
||||||
csr_write(stval, tval);
|
csr_write(CSR_STVAL, tval);
|
||||||
csr_write(sepc, epc);
|
csr_write(CSR_SEPC, epc);
|
||||||
csr_write(scause, cause);
|
csr_write(CSR_SCAUSE, cause);
|
||||||
|
|
||||||
/* Set MEPC to S-mode exception vector base */
|
/* Set MEPC to S-mode exception vector base */
|
||||||
regs->mepc = csr_read(stvec);
|
regs->mepc = csr_read(CSR_STVEC);
|
||||||
|
|
||||||
/* Initial value of new MSTATUS */
|
/* Initial value of new MSTATUS */
|
||||||
new_mstatus = regs->mstatus;
|
new_mstatus = regs->mstatus;
|
||||||
@@ -141,7 +141,7 @@ void sbi_trap_handler(struct sbi_trap_regs *regs,
|
|||||||
int rc = SBI_ENOTSUPP;
|
int rc = SBI_ENOTSUPP;
|
||||||
const char *msg = "trap handler failed";
|
const char *msg = "trap handler failed";
|
||||||
u32 hartid = sbi_current_hartid();
|
u32 hartid = sbi_current_hartid();
|
||||||
ulong mcause = csr_read(mcause);
|
ulong mcause = csr_read(CSR_MCAUSE);
|
||||||
|
|
||||||
if (mcause & (1UL << (__riscv_xlen - 1))) {
|
if (mcause & (1UL << (__riscv_xlen - 1))) {
|
||||||
mcause &= ~(1UL << (__riscv_xlen - 1));
|
mcause &= ~(1UL << (__riscv_xlen - 1));
|
||||||
@@ -183,6 +183,6 @@ void sbi_trap_handler(struct sbi_trap_regs *regs,
|
|||||||
|
|
||||||
trap_error:
|
trap_error:
|
||||||
if (rc) {
|
if (rc) {
|
||||||
sbi_trap_error(msg, rc, hartid, mcause, csr_read(mtval), regs);
|
sbi_trap_error(msg, rc, hartid, mcause, csr_read(CSR_MTVAL), regs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -87,7 +87,15 @@ static volatile u64 *clint_time_cmp;
|
|||||||
|
|
||||||
u64 clint_timer_value(void)
|
u64 clint_timer_value(void)
|
||||||
{
|
{
|
||||||
|
#if __riscv_xlen == 64
|
||||||
return readq_relaxed(clint_time_val);
|
return readq_relaxed(clint_time_val);
|
||||||
|
#else
|
||||||
|
u64 tmp;
|
||||||
|
tmp = readl_relaxed((void *)clint_time_val + 0x04);
|
||||||
|
tmp <<= 32;
|
||||||
|
tmp |= readl_relaxed(clint_time_val);
|
||||||
|
return tmp;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void clint_timer_event_stop(void)
|
void clint_timer_event_stop(void)
|
||||||
@@ -98,7 +106,12 @@ void clint_timer_event_stop(void)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Clear CLINT Time Compare */
|
/* Clear CLINT Time Compare */
|
||||||
|
#if __riscv_xlen == 64
|
||||||
writeq_relaxed(-1ULL, &clint_time_cmp[target_hart]);
|
writeq_relaxed(-1ULL, &clint_time_cmp[target_hart]);
|
||||||
|
#else
|
||||||
|
writel_relaxed(-1UL, &clint_time_cmp[target_hart]);
|
||||||
|
writel_relaxed(-1UL, (void *)(&clint_time_cmp[target_hart]) + 0x04);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void clint_timer_event_start(u64 next_event)
|
void clint_timer_event_start(u64 next_event)
|
||||||
@@ -109,7 +122,13 @@ void clint_timer_event_start(u64 next_event)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Program CLINT Time Compare */
|
/* Program CLINT Time Compare */
|
||||||
|
#if __riscv_xlen == 64
|
||||||
writeq_relaxed(next_event, &clint_time_cmp[target_hart]);
|
writeq_relaxed(next_event, &clint_time_cmp[target_hart]);
|
||||||
|
#else
|
||||||
|
u32 mask = -1UL;
|
||||||
|
writel_relaxed(next_event & mask, &clint_time_cmp[target_hart]);
|
||||||
|
writel_relaxed(next_event >> 32, (void *)(&clint_time_cmp[target_hart]) + 0x04);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int clint_warm_timer_init(void)
|
int clint_warm_timer_init(void)
|
||||||
@@ -121,7 +140,12 @@ int clint_warm_timer_init(void)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Clear CLINT Time Compare */
|
/* Clear CLINT Time Compare */
|
||||||
|
#if __riscv_xlen == 64
|
||||||
writeq_relaxed(-1ULL, &clint_time_cmp[target_hart]);
|
writeq_relaxed(-1ULL, &clint_time_cmp[target_hart]);
|
||||||
|
#else
|
||||||
|
writel_relaxed(-1UL, &clint_time_cmp[target_hart]);
|
||||||
|
writel_relaxed(-1UL, (void *)(&clint_time_cmp[target_hart]) + 0x04);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
# Compiler flags
|
# Compiler flags
|
||||||
platform-cppflags-y =
|
platform-cppflags-y =
|
||||||
platform-cflags-y =-mabi=lp64 -march=rv64imafdc -mcmodel=medany
|
platform-cflags-y =
|
||||||
platform-asflags-y =-mabi=lp64 -march=rv64imafdc -mcmodel=medany
|
platform-asflags-y =
|
||||||
platform-ldflags-y =
|
platform-ldflags-y =
|
||||||
|
|
||||||
# Common drivers to enable
|
# Common drivers to enable
|
||||||
|
@@ -88,7 +88,7 @@
|
|||||||
#define SPI1_BASE_ADDR (0x53000000U)
|
#define SPI1_BASE_ADDR (0x53000000U)
|
||||||
#define SPI3_BASE_ADDR (0x54000000U)
|
#define SPI3_BASE_ADDR (0x54000000U)
|
||||||
|
|
||||||
#define read_cycle() csr_read(mcycle)
|
#define read_cycle() csr_read(CSR_MCYCLE)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PLIC External Interrupt Numbers
|
* PLIC External Interrupt Numbers
|
||||||
|
@@ -9,10 +9,14 @@
|
|||||||
|
|
||||||
# Compiler flags
|
# Compiler flags
|
||||||
platform-cppflags-y =
|
platform-cppflags-y =
|
||||||
platform-cflags-y =-mabi=lp64 -march=rv64imafdc -mcmodel=medany
|
platform-cflags-y =
|
||||||
platform-asflags-y =-mabi=lp64 -march=rv64imafdc -mcmodel=medany
|
platform-asflags-y =
|
||||||
platform-ldflags-y =
|
platform-ldflags-y =
|
||||||
|
|
||||||
|
# Command for platform specific "make run"
|
||||||
|
platform-runcmd = qemu-system-riscv$(PLATFORM_RISCV_XLEN) -M sifive_u -m 256M \
|
||||||
|
-nographic -kernel $(build_dir)/platform/qemu/sifive_u/firmware/fw_payload.elf
|
||||||
|
|
||||||
# Common drivers to enable
|
# Common drivers to enable
|
||||||
PLATFORM_IRQCHIP_PLIC=y
|
PLATFORM_IRQCHIP_PLIC=y
|
||||||
PLATFORM_SERIAL_SIFIVE_UART=y
|
PLATFORM_SERIAL_SIFIVE_UART=y
|
||||||
@@ -21,10 +25,22 @@ PLATFORM_SYS_CLINT=y
|
|||||||
# Blobs to build
|
# Blobs to build
|
||||||
FW_TEXT_START=0x80000000
|
FW_TEXT_START=0x80000000
|
||||||
FW_JUMP=y
|
FW_JUMP=y
|
||||||
FW_JUMP_ADDR=0x80200000
|
ifeq ($(PLATFORM_RISCV_XLEN), 32)
|
||||||
|
# This needs to be 4MB alligned for 32-bit system
|
||||||
|
FW_JUMP_ADDR=0x80400000
|
||||||
|
else
|
||||||
|
# This needs to be 2MB alligned for 64-bit system
|
||||||
|
FW_JUMP_ADDR=0x80200000
|
||||||
|
endif
|
||||||
FW_JUMP_FDT_ADDR=0x82200000
|
FW_JUMP_FDT_ADDR=0x82200000
|
||||||
FW_PAYLOAD=y
|
FW_PAYLOAD=y
|
||||||
FW_PAYLOAD_OFFSET=0x200000
|
ifeq ($(PLATFORM_RISCV_XLEN), 32)
|
||||||
|
# This needs to be 4MB alligned for 32-bit system
|
||||||
|
FW_PAYLOAD_OFFSET=0x400000
|
||||||
|
else
|
||||||
|
# This needs to be 2MB alligned for 64-bit system
|
||||||
|
FW_PAYLOAD_OFFSET=0x200000
|
||||||
|
endif
|
||||||
FW_PAYLOAD_FDT_ADDR=0x82200000
|
FW_PAYLOAD_FDT_ADDR=0x82200000
|
||||||
|
|
||||||
# External Libraries to include
|
# External Libraries to include
|
||||||
|
@@ -9,10 +9,14 @@
|
|||||||
|
|
||||||
# Compiler flags
|
# Compiler flags
|
||||||
platform-cppflags-y =
|
platform-cppflags-y =
|
||||||
platform-cflags-y =-mabi=lp64 -march=rv64imafdc -mcmodel=medany
|
platform-cflags-y =
|
||||||
platform-asflags-y =-mabi=lp64 -march=rv64imafdc -mcmodel=medany
|
platform-asflags-y =
|
||||||
platform-ldflags-y =
|
platform-ldflags-y =
|
||||||
|
|
||||||
|
# Command for platform specific "make run"
|
||||||
|
platform-runcmd = qemu-system-riscv$(PLATFORM_RISCV_XLEN) -M virt -m 256M \
|
||||||
|
-nographic -kernel $(build_dir)/platform/qemu/virt/firmware/fw_payload.elf
|
||||||
|
|
||||||
# Common drivers to enable
|
# Common drivers to enable
|
||||||
PLATFORM_IRQCHIP_PLIC=y
|
PLATFORM_IRQCHIP_PLIC=y
|
||||||
PLATFORM_SERIAL_UART8250=y
|
PLATFORM_SERIAL_UART8250=y
|
||||||
@@ -21,10 +25,22 @@ PLATFORM_SYS_CLINT=y
|
|||||||
# Blobs to build
|
# Blobs to build
|
||||||
FW_TEXT_START=0x80000000
|
FW_TEXT_START=0x80000000
|
||||||
FW_JUMP=y
|
FW_JUMP=y
|
||||||
FW_JUMP_ADDR=0x80200000
|
ifeq ($(PLATFORM_RISCV_XLEN), 32)
|
||||||
|
# This needs to be 4MB alligned for 32-bit system
|
||||||
|
FW_JUMP_ADDR=0x80400000
|
||||||
|
else
|
||||||
|
# This needs to be 2MB alligned for 64-bit system
|
||||||
|
FW_JUMP_ADDR=0x80200000
|
||||||
|
endif
|
||||||
FW_JUMP_FDT_ADDR=0x82200000
|
FW_JUMP_FDT_ADDR=0x82200000
|
||||||
FW_PAYLOAD=y
|
FW_PAYLOAD=y
|
||||||
FW_PAYLOAD_OFFSET=0x200000
|
ifeq ($(PLATFORM_RISCV_XLEN), 32)
|
||||||
|
# This needs to be 4MB alligned for 32-bit system
|
||||||
|
FW_PAYLOAD_OFFSET=0x400000
|
||||||
|
else
|
||||||
|
# This needs to be 2MB alligned for 64-bit system
|
||||||
|
FW_PAYLOAD_OFFSET=0x200000
|
||||||
|
endif
|
||||||
FW_PAYLOAD_FDT_ADDR=0x82200000
|
FW_PAYLOAD_FDT_ADDR=0x82200000
|
||||||
|
|
||||||
# External Libraries to include
|
# External Libraries to include
|
||||||
|
@@ -5,9 +5,11 @@
|
|||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Anup Patel <anup.patel@wdc.com>
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
* Nick Kossifidis <mick@ics.forth.gr>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sbi/riscv_encoding.h>
|
#include <sbi/riscv_encoding.h>
|
||||||
|
#include <sbi/riscv_io.h>
|
||||||
#include <sbi/sbi_const.h>
|
#include <sbi/sbi_const.h>
|
||||||
#include <sbi/sbi_hart.h>
|
#include <sbi/sbi_hart.h>
|
||||||
#include <sbi/sbi_platform.h>
|
#include <sbi/sbi_platform.h>
|
||||||
@@ -19,6 +21,8 @@
|
|||||||
#define VIRT_HART_STACK_SIZE 8192
|
#define VIRT_HART_STACK_SIZE 8192
|
||||||
|
|
||||||
#define VIRT_TEST_ADDR 0x100000
|
#define VIRT_TEST_ADDR 0x100000
|
||||||
|
#define VIRT_TEST_FINISHER_FAIL 0x3333
|
||||||
|
#define VIRT_TEST_FINISHER_PASS 0x5555
|
||||||
|
|
||||||
#define VIRT_CLINT_ADDR 0x2000000
|
#define VIRT_CLINT_ADDR 0x2000000
|
||||||
|
|
||||||
@@ -122,7 +126,11 @@ static int virt_timer_init(bool cold_boot)
|
|||||||
|
|
||||||
static int virt_system_down(u32 type)
|
static int virt_system_down(u32 type)
|
||||||
{
|
{
|
||||||
/* For now nothing to do. */
|
/* Tell the "finisher" that the simulation
|
||||||
|
* was successful so that QEMU exits
|
||||||
|
*/
|
||||||
|
writew(VIRT_TEST_FINISHER_PASS, (void *)VIRT_TEST_ADDR);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
588
platform/sifive/fu540/HiFiveUnleashed-MicroSemi-Expansion.dts
Normal file
588
platform/sifive/fu540/HiFiveUnleashed-MicroSemi-Expansion.dts
Normal file
@@ -0,0 +1,588 @@
|
|||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
#address-cells = <0x2>;
|
||||||
|
#size-cells = <0x2>;
|
||||||
|
compatible = "sifive,fu540g", "sifive,fu500";
|
||||||
|
model = "sifive,hifive-unleashed-a00";
|
||||||
|
|
||||||
|
aliases {
|
||||||
|
serial0 = "/soc/serial@10010000";
|
||||||
|
serial1 = "/soc/serial@10011000";
|
||||||
|
};
|
||||||
|
|
||||||
|
chosen {
|
||||||
|
stdout-path = "/soc/serial@10010000:115200";
|
||||||
|
};
|
||||||
|
|
||||||
|
firmware {
|
||||||
|
sifive,fsbl = "2018-03-20";
|
||||||
|
};
|
||||||
|
|
||||||
|
cpus {
|
||||||
|
#address-cells = <0x1>;
|
||||||
|
#size-cells = <0x0>;
|
||||||
|
timebase-frequency = <0xf4240>;
|
||||||
|
|
||||||
|
cpu@0 {
|
||||||
|
clock-frequency = <0x0>;
|
||||||
|
compatible = "sifive,rocket0", "riscv";
|
||||||
|
device_type = "cpu";
|
||||||
|
i-cache-block-size = <0x40>;
|
||||||
|
i-cache-sets = <0x80>;
|
||||||
|
i-cache-size = <0x4000>;
|
||||||
|
next-level-cache = <0x1 0x2>;
|
||||||
|
reg = <0x0>;
|
||||||
|
riscv,isa = "rv64imac";
|
||||||
|
sifive,dtim = <0x3>;
|
||||||
|
sifive,itim = <0x4>;
|
||||||
|
status = "masked";
|
||||||
|
|
||||||
|
interrupt-controller {
|
||||||
|
#interrupt-cells = <0x1>;
|
||||||
|
compatible = "riscv,cpu-intc";
|
||||||
|
interrupt-controller;
|
||||||
|
linux,phandle = <0xf>;
|
||||||
|
phandle = <0xf>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cpu@1 {
|
||||||
|
clock-frequency = <0x0>;
|
||||||
|
compatible = "sifive,rocket0", "riscv";
|
||||||
|
d-cache-block-size = <0x40>;
|
||||||
|
d-cache-sets = <0x40>;
|
||||||
|
d-cache-size = <0x8000>;
|
||||||
|
d-tlb-sets = <0x1>;
|
||||||
|
d-tlb-size = <0x20>;
|
||||||
|
device_type = "cpu";
|
||||||
|
i-cache-block-size = <0x40>;
|
||||||
|
i-cache-sets = <0x40>;
|
||||||
|
i-cache-size = <0x8000>;
|
||||||
|
i-tlb-sets = <0x1>;
|
||||||
|
i-tlb-size = <0x20>;
|
||||||
|
mmu-type = "riscv,sv39";
|
||||||
|
next-level-cache = <0x1 0x2>;
|
||||||
|
reg = <0x1>;
|
||||||
|
riscv,isa = "rv64imafdc";
|
||||||
|
sifive,itim = <0x5>;
|
||||||
|
status = "okay";
|
||||||
|
tlb-split;
|
||||||
|
|
||||||
|
interrupt-controller {
|
||||||
|
#interrupt-cells = <0x1>;
|
||||||
|
compatible = "riscv,cpu-intc";
|
||||||
|
interrupt-controller;
|
||||||
|
linux,phandle = <0x10>;
|
||||||
|
phandle = <0x10>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cpu@2 {
|
||||||
|
clock-frequency = <0x0>;
|
||||||
|
compatible = "sifive,rocket0", "riscv";
|
||||||
|
d-cache-block-size = <0x40>;
|
||||||
|
d-cache-sets = <0x40>;
|
||||||
|
d-cache-size = <0x8000>;
|
||||||
|
d-tlb-sets = <0x1>;
|
||||||
|
d-tlb-size = <0x20>;
|
||||||
|
device_type = "cpu";
|
||||||
|
i-cache-block-size = <0x40>;
|
||||||
|
i-cache-sets = <0x40>;
|
||||||
|
i-cache-size = <0x8000>;
|
||||||
|
i-tlb-sets = <0x1>;
|
||||||
|
i-tlb-size = <0x20>;
|
||||||
|
mmu-type = "riscv,sv39";
|
||||||
|
next-level-cache = <0x1 0x2>;
|
||||||
|
reg = <0x2>;
|
||||||
|
riscv,isa = "rv64imafdc";
|
||||||
|
sifive,itim = <0x6>;
|
||||||
|
status = "okay";
|
||||||
|
tlb-split;
|
||||||
|
|
||||||
|
interrupt-controller {
|
||||||
|
#interrupt-cells = <0x1>;
|
||||||
|
compatible = "riscv,cpu-intc";
|
||||||
|
interrupt-controller;
|
||||||
|
linux,phandle = <0x11>;
|
||||||
|
phandle = <0x11>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cpu@3 {
|
||||||
|
clock-frequency = <0x0>;
|
||||||
|
compatible = "sifive,rocket0", "riscv";
|
||||||
|
d-cache-block-size = <0x40>;
|
||||||
|
d-cache-sets = <0x40>;
|
||||||
|
d-cache-size = <0x8000>;
|
||||||
|
d-tlb-sets = <0x1>;
|
||||||
|
d-tlb-size = <0x20>;
|
||||||
|
device_type = "cpu";
|
||||||
|
i-cache-block-size = <0x40>;
|
||||||
|
i-cache-sets = <0x40>;
|
||||||
|
i-cache-size = <0x8000>;
|
||||||
|
i-tlb-sets = <0x1>;
|
||||||
|
i-tlb-size = <0x20>;
|
||||||
|
mmu-type = "riscv,sv39";
|
||||||
|
next-level-cache = <0x1 0x2>;
|
||||||
|
reg = <0x3>;
|
||||||
|
riscv,isa = "rv64imafdc";
|
||||||
|
sifive,itim = <0x7>;
|
||||||
|
status = "okay";
|
||||||
|
tlb-split;
|
||||||
|
|
||||||
|
interrupt-controller {
|
||||||
|
#interrupt-cells = <0x1>;
|
||||||
|
compatible = "riscv,cpu-intc";
|
||||||
|
interrupt-controller;
|
||||||
|
linux,phandle = <0x12>;
|
||||||
|
phandle = <0x12>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cpu@4 {
|
||||||
|
clock-frequency = <0x0>;
|
||||||
|
compatible = "sifive,rocket0", "riscv";
|
||||||
|
d-cache-block-size = <0x40>;
|
||||||
|
d-cache-sets = <0x40>;
|
||||||
|
d-cache-size = <0x8000>;
|
||||||
|
d-tlb-sets = <0x1>;
|
||||||
|
d-tlb-size = <0x20>;
|
||||||
|
device_type = "cpu";
|
||||||
|
i-cache-block-size = <0x40>;
|
||||||
|
i-cache-sets = <0x40>;
|
||||||
|
i-cache-size = <0x8000>;
|
||||||
|
i-tlb-sets = <0x1>;
|
||||||
|
i-tlb-size = <0x20>;
|
||||||
|
mmu-type = "riscv,sv39";
|
||||||
|
next-level-cache = <0x1 0x2>;
|
||||||
|
reg = <0x4>;
|
||||||
|
riscv,isa = "rv64imafdc";
|
||||||
|
sifive,itim = <0x8>;
|
||||||
|
status = "okay";
|
||||||
|
tlb-split;
|
||||||
|
|
||||||
|
interrupt-controller {
|
||||||
|
#interrupt-cells = <0x1>;
|
||||||
|
compatible = "riscv,cpu-intc";
|
||||||
|
interrupt-controller;
|
||||||
|
linux,phandle = <0x13>;
|
||||||
|
phandle = <0x13>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
memory@80000000 {
|
||||||
|
device_type = "memory";
|
||||||
|
reg = <0x0 0x80000000 0x2 0x0>;
|
||||||
|
linux,phandle = <0xe>;
|
||||||
|
phandle = <0xe>;
|
||||||
|
};
|
||||||
|
|
||||||
|
soc {
|
||||||
|
#address-cells = <0x2>;
|
||||||
|
#size-cells = <0x2>;
|
||||||
|
compatible = "SiFive,FU540G-soc", "fu500-soc", "sifive-soc", "simple-bus";
|
||||||
|
ranges;
|
||||||
|
|
||||||
|
refclk {
|
||||||
|
#clock-cells = <0x0>;
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
clock-frequency = <0x1fca055>;
|
||||||
|
clock-output-names = "xtal";
|
||||||
|
linux,phandle = <0x9>;
|
||||||
|
phandle = <0x9>;
|
||||||
|
};
|
||||||
|
|
||||||
|
prci@10000000 {
|
||||||
|
compatible = "sifive,aloeprci0";
|
||||||
|
reg = <0x0 0x10000000 0x0 0x1000>;
|
||||||
|
reg-names = "control";
|
||||||
|
clocks = <0x9>;
|
||||||
|
#clock-cells = <0x1>;
|
||||||
|
linux,phandle = <0xa>;
|
||||||
|
phandle = <0xa>;
|
||||||
|
};
|
||||||
|
|
||||||
|
tlclk {
|
||||||
|
compatible = "fixed-factor-clock";
|
||||||
|
clocks = <0xa 0x0>;
|
||||||
|
#clock-cells = <0x0>;
|
||||||
|
clock-div = <0x2>;
|
||||||
|
clock-mult = <0x1>;
|
||||||
|
linux,phandle = <0x16>;
|
||||||
|
phandle = <0x16>;
|
||||||
|
};
|
||||||
|
|
||||||
|
cadence-gemgxl-mgmt@100a0000 {
|
||||||
|
compatible = "sifive,cadencegemgxlmgmt0";
|
||||||
|
reg = <0x0 0x100a0000 0x0 0x1000>;
|
||||||
|
reg-names = "control";
|
||||||
|
#clock-cells = <0x0>;
|
||||||
|
linux,phandle = <0x14>;
|
||||||
|
phandle = <0x14>;
|
||||||
|
};
|
||||||
|
|
||||||
|
bus-blocker@100b8000 {
|
||||||
|
compatible = "sifive,bus-blocker0";
|
||||||
|
reg = <0x0 0x100b8000 0x0 0x1000>;
|
||||||
|
reg-names = "control";
|
||||||
|
};
|
||||||
|
|
||||||
|
cache-controller@2010000 {
|
||||||
|
cache-block-size = <0x40>;
|
||||||
|
cache-level = <0x2>;
|
||||||
|
cache-sets = <0x800>;
|
||||||
|
cache-size = <0x200000>;
|
||||||
|
cache-unified;
|
||||||
|
compatible = "sifive,ccache0", "cache";
|
||||||
|
interrupt-parent = <0xb>;
|
||||||
|
interrupts = <0x1 0x2 0x3>;
|
||||||
|
next-level-cache = <0xc 0xd 0xe>;
|
||||||
|
reg = <0x0 0x2010000 0x0 0x1000 0x0 0x8000000 0x0 0x2000000>;
|
||||||
|
reg-names = "control", "sideband";
|
||||||
|
linux,phandle = <0x2>;
|
||||||
|
phandle = <0x2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
cadence-ddr-mgmt@100c0000 {
|
||||||
|
compatible = "sifive,cadenceddrmgmt0";
|
||||||
|
reg = <0x0 0x100c0000 0x0 0x1000>;
|
||||||
|
reg-names = "control";
|
||||||
|
};
|
||||||
|
|
||||||
|
chiplink@40000000 {
|
||||||
|
#address-cells = <0x2>;
|
||||||
|
#size-cells = <0x2>;
|
||||||
|
compatible = "sifive,chiplink", "simple-bus";
|
||||||
|
ranges = <0x0 0x60000000 0x0 0x60000000 0x0 0x20000000 0x30 0x0 0x30 0x0 0x10 0x0 0x0 0x40000000 0x0 0x40000000 0x0 0x20000000 0x20 0x0 0x20 0x0 0x10 0x0>;
|
||||||
|
linux,phandle = <0xd>;
|
||||||
|
phandle = <0xd>;
|
||||||
|
};
|
||||||
|
|
||||||
|
dma@3000000 {
|
||||||
|
#dma-cells = <0x1>;
|
||||||
|
compatible = "riscv,dma0";
|
||||||
|
dma-channels = <0x4>;
|
||||||
|
dma-requests = <0x0>;
|
||||||
|
interrupt-parent = <0xb>;
|
||||||
|
interrupts = <0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e>;
|
||||||
|
reg = <0x0 0x3000000 0x0 0x100000>;
|
||||||
|
reg-names = "control";
|
||||||
|
riscv,dma-pools = <0x1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
dtim@1000000 {
|
||||||
|
compatible = "sifive,dtim0";
|
||||||
|
reg = <0x0 0x1000000 0x0 0x2000>;
|
||||||
|
reg-names = "mem";
|
||||||
|
linux,phandle = <0x3>;
|
||||||
|
phandle = <0x3>;
|
||||||
|
};
|
||||||
|
|
||||||
|
ememoryotp@10070000 {
|
||||||
|
compatible = "sifive,ememoryotp0";
|
||||||
|
reg = <0x0 0x10070000 0x0 0x1000>;
|
||||||
|
reg-names = "control";
|
||||||
|
};
|
||||||
|
|
||||||
|
error-device@18000000 {
|
||||||
|
compatible = "sifive,error0";
|
||||||
|
reg = <0x0 0x18000000 0x0 0x8000000>;
|
||||||
|
reg-names = "mem";
|
||||||
|
linux,phandle = <0x1>;
|
||||||
|
phandle = <0x1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
ethernet@10090000 {
|
||||||
|
compatible = "cdns,macb";
|
||||||
|
interrupt-parent = <0xb>;
|
||||||
|
interrupts = <0x35>;
|
||||||
|
reg = <0x0 0x10090000 0x0 0x2000>;
|
||||||
|
reg-names = "control";
|
||||||
|
local-mac-address = [70 b3 d5 92 f0 1f];
|
||||||
|
phy-mode = "gmii";
|
||||||
|
clock-names = "pclk", "hclk", "tx_clk";
|
||||||
|
clocks = <0xa 0x1 0xa 0x1 0x14>;
|
||||||
|
#address-cells = <0x1>;
|
||||||
|
#size-cells = <0x0>;
|
||||||
|
|
||||||
|
ethernet-phy@0 {
|
||||||
|
reg = <0x0>;
|
||||||
|
reset-gpios = <0x15 0xc 0x1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
gpio@10060000 {
|
||||||
|
compatible = "sifive,gpio0";
|
||||||
|
interrupt-parent = <0xb>;
|
||||||
|
interrupts = <0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 0x11 0x12 0x13 0x14 0x15 0x16>;
|
||||||
|
reg = <0x0 0x10060000 0x0 0x1000>;
|
||||||
|
reg-names = "control";
|
||||||
|
gpio-controller;
|
||||||
|
#gpio-cells = <0x2>;
|
||||||
|
interrupt-controller;
|
||||||
|
#interrupt-cells = <0x2>;
|
||||||
|
linux,phandle = <0x15>;
|
||||||
|
phandle = <0x15>;
|
||||||
|
};
|
||||||
|
|
||||||
|
gpio-restart {
|
||||||
|
compatible = "gpio-restart";
|
||||||
|
gpios = <0x15 0xa 0x1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
i2c@10030000 {
|
||||||
|
compatible = "sifive,i2c0", "opencores,i2c-ocores";
|
||||||
|
reg = <0x0 0x10030000 0x0 0x1000>;
|
||||||
|
reg-names = "control";
|
||||||
|
clocks = <0x16>;
|
||||||
|
reg-shift = <0x2>;
|
||||||
|
reg-io-width = <0x1>;
|
||||||
|
#address-cells = <0x1>;
|
||||||
|
#size-cells = <0x0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
interrupt-controller@c000000 {
|
||||||
|
#interrupt-cells = <0x1>;
|
||||||
|
compatible = "riscv,plic0";
|
||||||
|
interrupt-controller;
|
||||||
|
interrupts-extended = <0xf 0xffffffff 0x10 0xffffffff 0x10 0x9 0x11 0xffffffff 0x11 0x9 0x12 0xffffffff 0x12 0x9 0x13 0xffffffff 0x13 0x9>;
|
||||||
|
reg = <0x0 0xc000000 0x0 0x4000000>;
|
||||||
|
reg-names = "control";
|
||||||
|
riscv,max-priority = <0x7>;
|
||||||
|
riscv,ndev = <0x35>;
|
||||||
|
linux,phandle = <0xb>;
|
||||||
|
phandle = <0xb>;
|
||||||
|
};
|
||||||
|
|
||||||
|
itim@1800000 {
|
||||||
|
compatible = "sifive,itim0";
|
||||||
|
reg = <0x0 0x1800000 0x0 0x4000>;
|
||||||
|
reg-names = "mem";
|
||||||
|
linux,phandle = <0x4>;
|
||||||
|
phandle = <0x4>;
|
||||||
|
};
|
||||||
|
|
||||||
|
itim@1808000 {
|
||||||
|
compatible = "sifive,itim0";
|
||||||
|
reg = <0x0 0x1808000 0x0 0x8000>;
|
||||||
|
reg-names = "mem";
|
||||||
|
linux,phandle = <0x5>;
|
||||||
|
phandle = <0x5>;
|
||||||
|
};
|
||||||
|
|
||||||
|
itim@1810000 {
|
||||||
|
compatible = "sifive,itim0";
|
||||||
|
reg = <0x0 0x1810000 0x0 0x8000>;
|
||||||
|
reg-names = "mem";
|
||||||
|
linux,phandle = <0x6>;
|
||||||
|
phandle = <0x6>;
|
||||||
|
};
|
||||||
|
|
||||||
|
itim@1818000 {
|
||||||
|
compatible = "sifive,itim0";
|
||||||
|
reg = <0x0 0x1818000 0x0 0x8000>;
|
||||||
|
reg-names = "mem";
|
||||||
|
linux,phandle = <0x7>;
|
||||||
|
phandle = <0x7>;
|
||||||
|
};
|
||||||
|
|
||||||
|
itim@1820000 {
|
||||||
|
compatible = "sifive,itim0";
|
||||||
|
reg = <0x0 0x1820000 0x0 0x8000>;
|
||||||
|
reg-names = "mem";
|
||||||
|
linux,phandle = <0x8>;
|
||||||
|
phandle = <0x8>;
|
||||||
|
};
|
||||||
|
|
||||||
|
memory-controller@100b0000 {
|
||||||
|
compatible = "sifive,aloeddr0";
|
||||||
|
interrupt-parent = <0xb>;
|
||||||
|
interrupts = <0x1f>;
|
||||||
|
reg = <0x0 0x100b0000 0x0 0x4000>;
|
||||||
|
reg-names = "control";
|
||||||
|
};
|
||||||
|
|
||||||
|
pci@2000000000 {
|
||||||
|
#address-cells = <0x3>;
|
||||||
|
#interrupt-cells = <0x1>;
|
||||||
|
#size-cells = <0x2>;
|
||||||
|
compatible = "ms-pf,axi-pcie-host";
|
||||||
|
device_type = "pci";
|
||||||
|
bus-range = <0x01 0x7f>;
|
||||||
|
interrupt-map = < 0 0 0 1 0x17 1
|
||||||
|
0 0 0 2 0x17 2
|
||||||
|
0 0 0 3 0x17 3
|
||||||
|
0 0 0 4 0x17 4>;
|
||||||
|
interrupt-map-mask = <0x0 0x0 0x0 0x7>;
|
||||||
|
interrupt-parent = <0xb>;
|
||||||
|
interrupts = <0x20>;
|
||||||
|
ranges = <0x2000000 0x0 0x40000000 0x0 0x40000000 0x0 0x20000000>;
|
||||||
|
reg = < 0x20 0x30000000 0x0 0x4000000
|
||||||
|
0x20 0x0 0x0 0x100000 >;
|
||||||
|
reg-names = "control", "apb";
|
||||||
|
|
||||||
|
ms_pcie_intc {
|
||||||
|
#address-cells = <0x0>;
|
||||||
|
#interrupt-cells = <0x1>;
|
||||||
|
interrupt-controller;
|
||||||
|
linux,phandle = <0x17>;
|
||||||
|
phandle = <0x17>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pinctrl@10080000 {
|
||||||
|
compatible = "sifive,pinctrl0";
|
||||||
|
reg = <0x0 0x10080000 0x0 0x1000>;
|
||||||
|
reg-names = "control";
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm@10020000 {
|
||||||
|
compatible = "sifive,pwm0";
|
||||||
|
interrupt-parent = <0xb>;
|
||||||
|
interrupts = <0x2a 0x2b 0x2c 0x2d>;
|
||||||
|
reg = <0x0 0x10020000 0x0 0x1000>;
|
||||||
|
reg-names = "control";
|
||||||
|
clocks = <0x16>;
|
||||||
|
sifive,approx-period = <0xf4240>;
|
||||||
|
#pwm-cells = <0x2>;
|
||||||
|
linux,phandle = <0x18>;
|
||||||
|
phandle = <0x18>;
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm@10021000 {
|
||||||
|
compatible = "sifive,pwm0";
|
||||||
|
interrupt-parent = <0xb>;
|
||||||
|
interrupts = <0x2e 0x2f 0x30 0x31>;
|
||||||
|
reg = <0x0 0x10021000 0x0 0x1000>;
|
||||||
|
reg-names = "control";
|
||||||
|
clocks = <0x16>;
|
||||||
|
sifive,approx-period = <0xf4240>;
|
||||||
|
#pwm-cells = <0x2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
pwmleds {
|
||||||
|
compatible = "pwm-leds";
|
||||||
|
|
||||||
|
heartbeat {
|
||||||
|
pwms = <0x18 0x0 0x0>;
|
||||||
|
max-brightness = <0xff>;
|
||||||
|
linux,default-trigger = "heartbeat";
|
||||||
|
};
|
||||||
|
|
||||||
|
mtd {
|
||||||
|
pwms = <0x18 0x1 0x0>;
|
||||||
|
max-brightness = <0xff>;
|
||||||
|
linux,default-trigger = "mtd";
|
||||||
|
};
|
||||||
|
|
||||||
|
netdev {
|
||||||
|
pwms = <0x18 0x2 0x0>;
|
||||||
|
max-brightness = <0xff>;
|
||||||
|
linux,default-trigger = "netdev";
|
||||||
|
};
|
||||||
|
|
||||||
|
panic {
|
||||||
|
pwms = <0x18 0x3 0x0>;
|
||||||
|
max-brightness = <0xff>;
|
||||||
|
linux,default-trigger = "panic";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
rom@1000 {
|
||||||
|
compatible = "sifive,modeselect0";
|
||||||
|
reg = <0x0 0x1000 0x0 0x1000>;
|
||||||
|
reg-names = "mem";
|
||||||
|
};
|
||||||
|
|
||||||
|
rom@10000 {
|
||||||
|
compatible = "sifive,maskrom0";
|
||||||
|
reg = <0x0 0x10000 0x0 0x8000>;
|
||||||
|
reg-names = "mem";
|
||||||
|
};
|
||||||
|
|
||||||
|
rom@a000000 {
|
||||||
|
compatible = "ucbbar,cacheable-zero0";
|
||||||
|
reg = <0x0 0xa000000 0x0 0x2000000>;
|
||||||
|
reg-names = "mem";
|
||||||
|
linux,phandle = <0xc>;
|
||||||
|
phandle = <0xc>;
|
||||||
|
};
|
||||||
|
|
||||||
|
serial@10010000 {
|
||||||
|
compatible = "sifive,uart0";
|
||||||
|
interrupt-parent = <0xb>;
|
||||||
|
interrupts = <0x4>;
|
||||||
|
reg = <0x0 0x10010000 0x0 0x1000>;
|
||||||
|
reg-names = "control";
|
||||||
|
clocks = <0x16>;
|
||||||
|
};
|
||||||
|
|
||||||
|
serial@10011000 {
|
||||||
|
compatible = "sifive,uart0";
|
||||||
|
interrupt-parent = <0xb>;
|
||||||
|
interrupts = <0x5>;
|
||||||
|
reg = <0x0 0x10011000 0x0 0x1000>;
|
||||||
|
reg-names = "control";
|
||||||
|
clocks = <0x16>;
|
||||||
|
};
|
||||||
|
|
||||||
|
spi@10040000 {
|
||||||
|
compatible = "sifive,spi0";
|
||||||
|
interrupt-parent = <0xb>;
|
||||||
|
interrupts = <0x33>;
|
||||||
|
reg = <0x0 0x10040000 0x0 0x1000 0x0 0x20000000 0x0 0x10000000>;
|
||||||
|
reg-names = "control", "mem";
|
||||||
|
clocks = <0x16>;
|
||||||
|
#address-cells = <0x1>;
|
||||||
|
#size-cells = <0x0>;
|
||||||
|
|
||||||
|
flash@0 {
|
||||||
|
compatible = "issi,is25wp256d", "jedec,spi-nor";
|
||||||
|
reg = <0x0>;
|
||||||
|
spi-max-frequency = <0x2faf080>;
|
||||||
|
m25p,fast-read;
|
||||||
|
spi-tx-bus-width = <0x4>;
|
||||||
|
spi-rx-bus-width = <0x4>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
spi@10041000 {
|
||||||
|
compatible = "sifive,spi0";
|
||||||
|
interrupt-parent = <0xb>;
|
||||||
|
interrupts = <0x34>;
|
||||||
|
reg = <0x0 0x10041000 0x0 0x1000 0x0 0x30000000 0x0 0x10000000>;
|
||||||
|
reg-names = "control", "mem";
|
||||||
|
clocks = <0x16>;
|
||||||
|
#address-cells = <0x1>;
|
||||||
|
#size-cells = <0x0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
spi@10050000 {
|
||||||
|
compatible = "sifive,spi0";
|
||||||
|
interrupt-parent = <0xb>;
|
||||||
|
interrupts = <0x6>;
|
||||||
|
reg = <0x0 0x10050000 0x0 0x1000>;
|
||||||
|
reg-names = "control";
|
||||||
|
clocks = <0x16>;
|
||||||
|
#address-cells = <0x1>;
|
||||||
|
#size-cells = <0x0>;
|
||||||
|
|
||||||
|
mmc@0 {
|
||||||
|
compatible = "mmc-spi-slot";
|
||||||
|
reg = <0x0>;
|
||||||
|
spi-max-frequency = <0x1312d00>;
|
||||||
|
voltage-ranges = <0xce4 0xce4>;
|
||||||
|
disable-wp;
|
||||||
|
gpios = <0x15 0xb 0x1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
teststatus@4000 {
|
||||||
|
compatible = "sifive,test0";
|
||||||
|
reg = <0x0 0x4000 0x0 0x1000>;
|
||||||
|
reg-names = "control";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
@@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
# Compiler flags
|
# Compiler flags
|
||||||
platform-cppflags-y =
|
platform-cppflags-y =
|
||||||
platform-cflags-y =-mabi=lp64 -march=rv64imafdc -mcmodel=medany
|
platform-cflags-y =
|
||||||
platform-asflags-y =-mabi=lp64 -march=rv64imafdc -mcmodel=medany
|
platform-asflags-y =
|
||||||
platform-ldflags-y =
|
platform-ldflags-y =
|
||||||
|
|
||||||
# Common drivers to enable
|
# Common drivers to enable
|
||||||
|
@@ -80,6 +80,7 @@ static void fu540_modify_dt(void *fdt)
|
|||||||
|
|
||||||
plic_fdt_fixup(fdt, "riscv,plic0");
|
plic_fdt_fixup(fdt, "riscv,plic0");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fu540_final_init(bool cold_boot)
|
static int fu540_final_init(bool cold_boot)
|
||||||
{
|
{
|
||||||
void *fdt;
|
void *fdt;
|
||||||
|
@@ -8,17 +8,29 @@
|
|||||||
platform-cppflags-y =
|
platform-cppflags-y =
|
||||||
|
|
||||||
# C Compiler and assembler flags.
|
# C Compiler and assembler flags.
|
||||||
# For a 64 bits platform, this will likely be:
|
platform-cflags-y =
|
||||||
# -mabi=lp64 -march=rv64imafdc -mcmodel=medany
|
platform-asflags-y =
|
||||||
# For a 32 bits platform, this will likely be:
|
|
||||||
# -mabi=lp32 -march=rv32imafdc -mcmodel=medlow
|
|
||||||
platform-cflags-y = -mabi=lp64 -march=rv64imafdc -mcmodel=medany
|
|
||||||
platform-asflags-y = -mabi=lp64 -march=rv64imafdc -mcmodel=medany
|
|
||||||
|
|
||||||
# Linker flags: additional libraries and object files that the platform
|
# Linker flags: additional libraries and object files that the platform
|
||||||
# code needs can be added here
|
# code needs can be added here
|
||||||
platform-ldflags-y =
|
platform-ldflags-y =
|
||||||
|
|
||||||
|
#
|
||||||
|
# Command for platform specific "make run"
|
||||||
|
# Useful for development and debugging on plaftform simulator (such as QEMU)
|
||||||
|
#
|
||||||
|
# platform-runcmd = your_platform_run.sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Platform RISC-V XLEN, ABI, ISA and Code Model configuration.
|
||||||
|
# These are optional parameters but platforms can optionaly provide it.
|
||||||
|
# Some of these are guessed based on GCC compiler capabilities
|
||||||
|
#
|
||||||
|
# PLATFORM_RISCV_XLEN = 64
|
||||||
|
# PLATFORM_RISCV_ABI = lp64
|
||||||
|
# PLATFORM_RISCV_ISA = rv64imafdc
|
||||||
|
# PLATFORM_RISCV_CODE_MODEL = medany
|
||||||
|
|
||||||
#
|
#
|
||||||
# OpenSBI implements generic drivers for some common generic hardware. The
|
# OpenSBI implements generic drivers for some common generic hardware. The
|
||||||
# drivers currently available are the RISC-V Platform Level Interrupt
|
# drivers currently available are the RISC-V Platform Level Interrupt
|
||||||
@@ -39,7 +51,13 @@ FW_TEXT_START=0x80000000
|
|||||||
# as needed.
|
# as needed.
|
||||||
#
|
#
|
||||||
FW_JUMP=<y|n>
|
FW_JUMP=<y|n>
|
||||||
FW_JUMP_ADDR=0x80200000
|
# This needs to be 4MB aligned for 32-bit support
|
||||||
|
# This needs to be 2MB aligned for 64-bit support
|
||||||
|
# ifeq ($(PLATFORM_RISCV_XLEN), 32)
|
||||||
|
# FW_JUMP_ADDR=0x80400000
|
||||||
|
# else
|
||||||
|
# FW_JUMP_ADDR=0x80200000
|
||||||
|
# endif
|
||||||
# FW_JUMP_FDT_ADDR=0x82200000
|
# FW_JUMP_FDT_ADDR=0x82200000
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -48,7 +66,13 @@ FW_JUMP_ADDR=0x80200000
|
|||||||
# as needed.
|
# as needed.
|
||||||
#
|
#
|
||||||
FW_PAYLOAD=<y|n>
|
FW_PAYLOAD=<y|n>
|
||||||
|
# This needs to be 4MB aligned for 32-bit support
|
||||||
|
# This needs to be 2MB aligned for 64-bit support
|
||||||
|
ifeq ($(PLATFORM_RISCV_XLEN), 32)
|
||||||
|
FW_PAYLOAD_OFFSET=0x400000
|
||||||
|
else
|
||||||
FW_PAYLOAD_OFFSET=0x200000
|
FW_PAYLOAD_OFFSET=0x200000
|
||||||
|
endif
|
||||||
# FW_PAYLOAD_ALIGN=0x1000
|
# FW_PAYLOAD_ALIGN=0x1000
|
||||||
# FW_PAYLOAD_PATH="path to next boot stage binary image file"
|
# FW_PAYLOAD_PATH="path to next boot stage binary image file"
|
||||||
# FW_PAYLOAD_FDT_PATH="path to platform flattened device tree file"
|
# FW_PAYLOAD_FDT_PATH="path to platform flattened device tree file"
|
||||||
|
@@ -27,7 +27,7 @@ static int platform_early_init(bool cold_boot)
|
|||||||
/*
|
/*
|
||||||
* Platform final initialization.
|
* Platform final initialization.
|
||||||
*/
|
*/
|
||||||
static int platform final_init(bool cold_boot);
|
static int platform_final_init(bool cold_boot)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -215,7 +215,7 @@ struct sbi_platform platform = {
|
|||||||
.hart_stack_size = 4096,
|
.hart_stack_size = 4096,
|
||||||
.disabled_hart_mask = 0,
|
.disabled_hart_mask = 0,
|
||||||
|
|
||||||
.early_init = platform_final_init,
|
.early_init = platform_early_init,
|
||||||
.final_init = platform_final_init,
|
.final_init = platform_final_init,
|
||||||
|
|
||||||
.pmp_region_count = platform_pmp_region_count,
|
.pmp_region_count = platform_pmp_region_count,
|
||||||
@@ -236,7 +236,7 @@ struct sbi_platform platform = {
|
|||||||
.timer_event_start = platform_timer_event_start,
|
.timer_event_start = platform_timer_event_start,
|
||||||
.timer_event_stop = platform_timer_event_stop,
|
.timer_event_stop = platform_timer_event_stop,
|
||||||
|
|
||||||
.system_reboot = platform_system_down,
|
.system_reboot = platform_system_reboot,
|
||||||
.system_shutdown = platform_system_down
|
.system_shutdown = platform_system_shutdown
|
||||||
};
|
};
|
||||||
|
|
||||||
|
135
scripts/create-binary-archive.sh
Executable file
135
scripts/create-binary-archive.sh
Executable file
@@ -0,0 +1,135 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
function usage()
|
||||||
|
{
|
||||||
|
echo "Usage:"
|
||||||
|
echo " $0 [options]"
|
||||||
|
echo "Options:"
|
||||||
|
echo " -h Display help or usage"
|
||||||
|
echo " -p <opensbi_source_path> OpenSBI source path"
|
||||||
|
echo " -o <build_output_path> Build output path"
|
||||||
|
echo " -d Build and install documentation"
|
||||||
|
echo " -t Build only with no archive created"
|
||||||
|
echo " -j <num_threads> Number of threads for Make (Default: 1)"
|
||||||
|
echo " -s <archive_suffix> Archive name suffix (Default: unknown)"
|
||||||
|
echo " -x <riscv_xlen> RISC-V XLEN (Default: 64)"
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Command line options
|
||||||
|
BUILD_NUM_THREADS=1
|
||||||
|
BUILD_OUTPUT_PATH="$(pwd)/build"
|
||||||
|
BUILD_OPENSBI_SOURCE_PATH="$(pwd)"
|
||||||
|
BUILD_DOCS="no"
|
||||||
|
BUILD_ONLY="no"
|
||||||
|
BUILD_ARCHIVE_SUFFIX="unknown"
|
||||||
|
BUILD_RISCV_XLEN=64
|
||||||
|
|
||||||
|
while getopts "hdtj:o:p:s:x:" o; do
|
||||||
|
case "${o}" in
|
||||||
|
h)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
d)
|
||||||
|
BUILD_DOCS="yes"
|
||||||
|
;;
|
||||||
|
t)
|
||||||
|
BUILD_ONLY="yes"
|
||||||
|
;;
|
||||||
|
j)
|
||||||
|
BUILD_NUM_THREADS=${OPTARG}
|
||||||
|
;;
|
||||||
|
o)
|
||||||
|
BUILD_OUTPUT_PATH=${OPTARG}
|
||||||
|
;;
|
||||||
|
p)
|
||||||
|
BUILD_OPENSBI_SOURCE_PATH=${OPTARG}
|
||||||
|
;;
|
||||||
|
s)
|
||||||
|
BUILD_ARCHIVE_SUFFIX=${OPTARG}
|
||||||
|
;;
|
||||||
|
x)
|
||||||
|
BUILD_RISCV_XLEN=${OPTARG}
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
shift $((OPTIND-1))
|
||||||
|
|
||||||
|
if [ -z "${BUILD_OPENSBI_SOURCE_PATH}" ]; then
|
||||||
|
echo "Must specify OpenSBI source path"
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "${BUILD_OPENSBI_SOURCE_PATH}" ]; then
|
||||||
|
echo "OpenSBI source path does not exist"
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${BUILD_ARCHIVE_SUFFIX}" ]; then
|
||||||
|
echo "Archive suffice cannot be empty"
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get version of OpenSBI
|
||||||
|
BUILD_VERSION_MAJOR=$(grep MAJOR "${BUILD_OPENSBI_SOURCE_PATH}/include/sbi/sbi_version.h" | sed 's/.*MAJOR.*\([0-9][0-9]*\)/\1/')
|
||||||
|
BUILD_VERSION_MINOR=$(grep MINOR "${BUILD_OPENSBI_SOURCE_PATH}/include/sbi/sbi_version.h" | sed 's/.*MINOR.*\([0-9][0-9]*\)/\1/')
|
||||||
|
|
||||||
|
# Setup archive name
|
||||||
|
BUILD_ARCHIVE_NAME="opensbi-${BUILD_VERSION_MAJOR}.${BUILD_VERSION_MINOR}-rv${BUILD_RISCV_XLEN}-${BUILD_ARCHIVE_SUFFIX}"
|
||||||
|
|
||||||
|
# Setup platform list
|
||||||
|
case "${BUILD_RISCV_XLEN}" in
|
||||||
|
32)
|
||||||
|
# Setup 32bit platform list
|
||||||
|
BUILD_PLATFORM_SUBDIR=("qemu/virt")
|
||||||
|
BUILD_PLATFORM_SUBDIR+=("qemu/sifive_u")
|
||||||
|
;;
|
||||||
|
64)
|
||||||
|
# Setup 64bit platform list
|
||||||
|
BUILD_PLATFORM_SUBDIR=("qemu/virt")
|
||||||
|
BUILD_PLATFORM_SUBDIR+=("qemu/sifive_u")
|
||||||
|
BUILD_PLATFORM_SUBDIR+=("sifive/fu540")
|
||||||
|
BUILD_PLATFORM_SUBDIR+=("kendryte/k210")
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Invalid RISC-V XLEN"
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Ensure output directory is present
|
||||||
|
mkdir -p "${BUILD_OUTPUT_PATH}"
|
||||||
|
|
||||||
|
# Build and install generic library
|
||||||
|
echo "Build and install generic library XLEN=${BUILD_RISCV_XLEN}"
|
||||||
|
echo ""
|
||||||
|
make -C "${BUILD_OPENSBI_SOURCE_PATH}" O="${BUILD_OUTPUT_PATH}" I="${BUILD_OUTPUT_PATH}/${BUILD_ARCHIVE_NAME}" PLATFORM_RISCV_XLEN="${BUILD_RISCV_XLEN}" install_libsbi -j "${BUILD_NUM_THREADS}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Build and install relevant platforms
|
||||||
|
for INDEX in $(seq 0 1 "$(expr ${#BUILD_PLATFORM_SUBDIR[*]} - 1)")
|
||||||
|
do
|
||||||
|
echo "Build and install PLATFORM=${BUILD_PLATFORM_SUBDIR[${INDEX}]} XLEN=${BUILD_RISCV_XLEN}"
|
||||||
|
echo ""
|
||||||
|
make -C "${BUILD_OPENSBI_SOURCE_PATH}" O="${BUILD_OUTPUT_PATH}" I="${BUILD_OUTPUT_PATH}/${BUILD_ARCHIVE_NAME}" PLATFORM="${BUILD_PLATFORM_SUBDIR[${INDEX}]}" PLATFORM_RISCV_XLEN="${BUILD_RISCV_XLEN}" install_libplatsbi install_firmwares -j "${BUILD_NUM_THREADS}"
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
# Build and install docs
|
||||||
|
if [ "${BUILD_DOCS}" == "yes" ]; then
|
||||||
|
echo "Build and install docs"
|
||||||
|
echo ""
|
||||||
|
make -C "${BUILD_OPENSBI_SOURCE_PATH}" O="${BUILD_OUTPUT_PATH}" I="${BUILD_OUTPUT_PATH}/${BUILD_ARCHIVE_NAME}" install_docs
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create archive file
|
||||||
|
if [ "${BUILD_ONLY}" == "no" ]; then
|
||||||
|
echo "Create archive ${BUILD_ARCHIVE_NAME}.tar.xz"
|
||||||
|
echo ""
|
||||||
|
tar -C "${BUILD_OUTPUT_PATH}" -cJvf "${BUILD_OUTPUT_PATH}/${BUILD_ARCHIVE_NAME}.tar.xz" "${BUILD_ARCHIVE_NAME}"
|
||||||
|
echo ""
|
||||||
|
fi
|
Reference in New Issue
Block a user