forked from Mirrors/opensbi
Compare commits
435 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
234ed8e427 | ||
![]() |
da5293f742 | ||
![]() |
1bbf36183e | ||
![]() |
386eba21bf | ||
![]() |
e884416650 | ||
![]() |
db56341dfa | ||
![]() |
0d49c3bc18 | ||
![]() |
12394a269b | ||
![]() |
b7df5e4392 | ||
![]() |
80bc5065bb | ||
![]() |
7dcb1e1753 | ||
![]() |
a029bd90c6 | ||
![]() |
6fc1986f50 | ||
![]() |
7baccfca79 | ||
![]() |
2179777364 | ||
![]() |
e7da0b4204 | ||
![]() |
4fffb53269 | ||
![]() |
ba741ea0ad | ||
![]() |
c0d2baa8c0 | ||
![]() |
9b65dcaedd | ||
![]() |
555e73778a | ||
![]() |
62ea4f4e2a | ||
![]() |
c1f6d89678 | ||
![]() |
c709d40a67 | ||
![]() |
4e370224df | ||
![]() |
3d921fad0d | ||
![]() |
8d2edc4fc9 | ||
![]() |
2677324f90 | ||
![]() |
548d03e577 | ||
![]() |
5c429ae213 | ||
![]() |
da074796df | ||
![]() |
c4acc60a46 | ||
![]() |
54a7734d86 | ||
![]() |
781cafdbee | ||
![]() |
48616b3de2 | ||
![]() |
914f81fbee | ||
![]() |
a809f406b9 | ||
![]() |
bf21632860 | ||
![]() |
74c0ea1e83 | ||
![]() |
fdf5d5c322 | ||
![]() |
c347408a39 | ||
![]() |
c10c30b485 | ||
![]() |
e856462ac2 | ||
![]() |
5fd99dbdaa | ||
![]() |
5edbb7cda1 | ||
![]() |
3e200370ee | ||
![]() |
530e95bd63 | ||
![]() |
3a30d2c34d | ||
![]() |
e73b92d862 | ||
![]() |
b1678af210 | ||
![]() |
8b650050ec | ||
![]() |
f81d6f6f43 | ||
![]() |
a126886bfa | ||
![]() |
a12d46a5e7 | ||
![]() |
dbeeacb878 | ||
![]() |
a0f2d4a10c | ||
![]() |
e9a4bfb7b5 | ||
![]() |
9c07c513aa | ||
![]() |
6ca096977d | ||
![]() |
af4b50f896 | ||
![]() |
a04c46506a | ||
![]() |
79bf80b44e | ||
![]() |
7701ea13be | ||
![]() |
aaeca7eb4e | ||
![]() |
172fa1601c | ||
![]() |
9f935a4a43 | ||
![]() |
7ccf6bf54c | ||
![]() |
6734304f8c | ||
![]() |
c1c7c3ee9e | ||
![]() |
bef63d6848 | ||
![]() |
dcb10c0056 | ||
![]() |
ebc8ebc0f8 | ||
![]() |
162d453b49 | ||
![]() |
2c341f7844 | ||
![]() |
74d1db7062 | ||
![]() |
7b0b289887 | ||
![]() |
4f3bad6e43 | ||
![]() |
e435ba0524 | ||
![]() |
d7f87d99a3 | ||
![]() |
9d56961b23 | ||
![]() |
4b18a2acc2 | ||
![]() |
937caee083 | ||
![]() |
2cfd2fc904 | ||
![]() |
2845d2d2cf | ||
![]() |
8e47649eff | ||
![]() |
ec1abf6657 | ||
![]() |
a5f9104330 | ||
![]() |
7d61a68775 | ||
![]() |
ec3e5b14d5 | ||
![]() |
78afe11ba2 | ||
![]() |
35bc810252 | ||
![]() |
a98258d0b5 | ||
![]() |
2314101989 | ||
![]() |
9bd5f8f17d | ||
![]() |
db56ef367c | ||
![]() |
637b348224 | ||
![]() |
d5725c24c6 | ||
![]() |
518e85cccb | ||
![]() |
6966ad0abe | ||
![]() |
e2c3f01af4 | ||
![]() |
32f87e5a86 | ||
![]() |
980290651f | ||
![]() |
106b888e20 | ||
![]() |
79bfd67f9a | ||
![]() |
1b8c0128f1 | ||
![]() |
51f0e4a053 | ||
![]() |
72019ee202 | ||
![]() |
4e3876d5be | ||
![]() |
c6c65ee861 | ||
![]() |
86ec5341e4 | ||
![]() |
4ce6b7a82a | ||
![]() |
64f140830d | ||
![]() |
30b60401e1 | ||
![]() |
a63f05f3de | ||
![]() |
6956e83a94 | ||
![]() |
569dd64b72 | ||
![]() |
a9a9751185 | ||
![]() |
d30bb68448 | ||
![]() |
2c685c214f | ||
![]() |
446a9c6d1e | ||
![]() |
73d6ef3b29 | ||
![]() |
89ba63493c | ||
![]() |
a38bea9341 | ||
![]() |
2966510eed | ||
![]() |
63b0f5f71a | ||
![]() |
3a8fc81357 | ||
![]() |
3aa1036f91 | ||
![]() |
49841832b8 | ||
![]() |
28b4052849 | ||
![]() |
38a4b54cdc | ||
![]() |
36833abfbb | ||
![]() |
22c4334f5c | ||
![]() |
1f235ec47f | ||
![]() |
ec0d2a7d7d | ||
![]() |
4938024420 | ||
![]() |
b2df751acf | ||
![]() |
6a053f6e6c | ||
![]() |
79d0fadb06 | ||
![]() |
13ca20d8df | ||
![]() |
aef9a60d52 | ||
![]() |
63a513edec | ||
![]() |
7be75f519f | ||
![]() |
c2286b6f04 | ||
![]() |
dfd9dd67dc | ||
![]() |
b4efa70d12 | ||
![]() |
433bac7242 | ||
![]() |
dc38929dfb | ||
![]() |
5338679ff0 | ||
![]() |
7993ca2c8e | ||
![]() |
d626037258 | ||
![]() |
65c06b026d | ||
![]() |
13717a8e53 | ||
![]() |
4f18c6e550 | ||
![]() |
2ba7087b09 | ||
![]() |
1f21b99ff0 | ||
![]() |
f1aa9e54e0 | ||
![]() |
4d063538f0 | ||
![]() |
7cc6fa4d8a | ||
![]() |
76a89403c8 | ||
![]() |
75322a634b | ||
![]() |
76f0f81407 | ||
![]() |
8ff2b94ea1 | ||
![]() |
1ac794cb61 | ||
![]() |
f0eb503db4 | ||
![]() |
44dd7be3b2 | ||
![]() |
19e966b862 | ||
![]() |
66185b3ec9 | ||
![]() |
dd33b9e0a1 | ||
![]() |
a39cd6fe4c | ||
![]() |
e3ad7c13a0 | ||
![]() |
243b0d0c0c | ||
![]() |
0a0093b0bc | ||
![]() |
01a8c8eebb | ||
![]() |
e6c1345f89 | ||
![]() |
5bdf022d07 | ||
![]() |
3a326af9be | ||
![]() |
4781545512 | ||
![]() |
6585fabbcc | ||
![]() |
a9eac67ad0 | ||
![]() |
1bb00ab3ae | ||
![]() |
9f1b72ce66 | ||
![]() |
66d018499c | ||
![]() |
615587c336 | ||
![]() |
6c7922e23b | ||
![]() |
f281de885e | ||
![]() |
e5a7f556ce | ||
![]() |
648507a867 | ||
![]() |
0a28ea54dc | ||
![]() |
ec0d80f5b4 | ||
![]() |
9e52a45f4b | ||
![]() |
54b2779cfe | ||
![]() |
dd0f21c560 | ||
![]() |
5b6957eed7 | ||
![]() |
7b211ff924 | ||
![]() |
40b221baff | ||
![]() |
7487116b41 | ||
![]() |
fe37d7da29 | ||
![]() |
5a7bd0c88d | ||
![]() |
d11c79cd97 | ||
![]() |
cb78a48231 | ||
![]() |
626467cfd9 | ||
![]() |
1de66d170e | ||
![]() |
160c88535f | ||
![]() |
550ba88db1 | ||
![]() |
4d93586bfa | ||
![]() |
4c374511fd | ||
![]() |
040e4e2ec2 | ||
![]() |
d1d6560a87 | ||
![]() |
fb84879e66 | ||
![]() |
ed265b4498 | ||
![]() |
5968894842 | ||
![]() |
9a74a64ae0 | ||
![]() |
a0c88ddb31 | ||
![]() |
315a87710f | ||
![]() |
c51f02cf14 | ||
![]() |
75eec9dd3f | ||
![]() |
814f38dc1d | ||
![]() |
db187d616c | ||
![]() |
680b09872d | ||
![]() |
c9f60fc6b7 | ||
![]() |
bd6ef02d47 | ||
![]() |
209134d8f9 | ||
![]() |
3ebfe0ec5d | ||
![]() |
19bd531a15 | ||
![]() |
e23d3ba936 | ||
![]() |
87a7ef7659 | ||
![]() |
3f8d754c2c | ||
![]() |
db6a2b5c68 | ||
![]() |
3f1c847d1f | ||
![]() |
dd9439fbac | ||
![]() |
1071f05663 | ||
![]() |
6f9bb83c1f | ||
![]() |
c9a526877c | ||
![]() |
8135520e6f | ||
![]() |
e846ce1681 | ||
![]() |
6af55769eb | ||
![]() |
666be6d62b | ||
![]() |
fcb1dedb2d | ||
![]() |
dce88467af | ||
![]() |
5fbcd625bc | ||
![]() |
327ba36211 | ||
![]() |
72a0628c7e | ||
![]() |
2343efd040 | ||
![]() |
9275ed3949 | ||
![]() |
9aabba2665 | ||
![]() |
823345ecae | ||
![]() |
16e7071f6d | ||
![]() |
eeae3d9582 | ||
![]() |
f92147c2b2 | ||
![]() |
baac7e066d | ||
![]() |
0cfe49ad63 | ||
![]() |
4b2f594b85 | ||
![]() |
ffdc858f72 | ||
![]() |
86d37bbd7d | ||
![]() |
757bb44e6e | ||
![]() |
eede1aa7c7 | ||
![]() |
9aad831e87 | ||
![]() |
466fecb957 | ||
![]() |
61f776861f | ||
![]() |
2db381fc74 | ||
![]() |
44ce5b99e9 | ||
![]() |
2b945fc180 | ||
![]() |
71d2b837c4 | ||
![]() |
d96316481d | ||
![]() |
a4a6a81b7d | ||
![]() |
d6d7e18d1d | ||
![]() |
c741abcd40 | ||
![]() |
3226bd93ce | ||
![]() |
078686d75c | ||
![]() |
650c0e525c | ||
![]() |
6e87507db6 | ||
![]() |
2abc55bb39 | ||
![]() |
678c3c3655 | ||
![]() |
4a603eb6dc | ||
![]() |
a148996a7f | ||
![]() |
00d332bbe7 | ||
![]() |
8c83fb2fc8 | ||
e1a5b737ef | |||
![]() |
82ae8e8fe2 | ||
![]() |
6704216732 | ||
![]() |
e3f69fc1e9 | ||
![]() |
5b4824082f | ||
![]() |
b677a9b8d6 | ||
![]() |
f64f4b92e4 | ||
![]() |
ac5e821d50 | ||
![]() |
f8b3bb826d | ||
![]() |
393624377a | ||
![]() |
c3b3b8f43b | ||
![]() |
3e7d666d7c | ||
![]() |
66fb729a1e | ||
![]() |
24c3082ea4 | ||
![]() |
bc874e34ce | ||
![]() |
c66543d049 | ||
![]() |
0b414532c4 | ||
![]() |
27a5c7f3c8 | ||
![]() |
f8ce996d90 | ||
![]() |
82fd42fcce | ||
![]() |
a8ef0b5d53 | ||
![]() |
44d1296018 | ||
![]() |
fdfb5332f3 | ||
![]() |
892e87998c | ||
![]() |
48b06ad16e | ||
![]() |
29bb2a6835 | ||
![]() |
c03c8a1e2c | ||
![]() |
a062200b89 | ||
![]() |
c2f23cc6ed | ||
![]() |
c2bfa2bff3 | ||
![]() |
1a8ca08cc0 | ||
![]() |
897b8fbdd9 | ||
![]() |
179eddeb9c | ||
![]() |
d6fa7f95bb | ||
![]() |
9a717ec12e | ||
![]() |
6d0b4c520d | ||
![]() |
5ff1ab0ed8 | ||
![]() |
2c2bbe7374 | ||
![]() |
d79173b4b7 | ||
![]() |
ac1c229b61 | ||
![]() |
85647a1a76 | ||
![]() |
021b9e7c76 | ||
![]() |
43ac621ecb | ||
![]() |
161b348e7e | ||
![]() |
766850222a | ||
![]() |
37923c4a66 | ||
![]() |
0a411bf717 | ||
![]() |
84cd4fc913 | ||
![]() |
817d50d0d4 | ||
![]() |
5f762d14f0 | ||
![]() |
a8b4b83b7f | ||
![]() |
da9b76b957 | ||
![]() |
3d2aaac69a | ||
![]() |
046cc16e8b | ||
![]() |
0492c5d92b | ||
![]() |
30cdf00655 | ||
![]() |
a73d45ccac | ||
![]() |
7daccaeebd | ||
![]() |
6ffe1bed09 | ||
![]() |
f95dd39ab6 | ||
![]() |
adf8b73675 | ||
![]() |
b28b8ac0d2 | ||
![]() |
e340bbf7b5 | ||
![]() |
049ad0b387 | ||
![]() |
a67fd68cbf | ||
![]() |
73c19e69f3 | ||
![]() |
15ed1e7452 | ||
![]() |
b0c9787435 | ||
![]() |
2aa43a13cd | ||
![]() |
1993182f03 | ||
![]() |
b325f6baef | ||
![]() |
6469ed101c | ||
![]() |
55e191e3b0 | ||
![]() |
c3e406f160 | ||
![]() |
e746673a79 | ||
![]() |
c0849cd731 | ||
![]() |
46a90d90e7 | ||
![]() |
fc6bd90457 | ||
![]() |
9beb57362f | ||
![]() |
c7d1b12199 | ||
![]() |
86a31f5437 | ||
![]() |
331ff6a162 | ||
![]() |
9407202532 | ||
![]() |
9777aeef41 | ||
![]() |
109266397a | ||
![]() |
aa0ed1d733 | ||
![]() |
b8732feaf7 | ||
![]() |
7219477f7b | ||
![]() |
2be424bd28 | ||
![]() |
086dbdfc92 | ||
![]() |
4370f18f34 | ||
![]() |
6590a7dab9 | ||
![]() |
bd732ae612 | ||
![]() |
dc40042322 | ||
![]() |
813f7f4c25 | ||
![]() |
ab14f94a8c | ||
![]() |
c96cc03fcc | ||
![]() |
75f903dd78 | ||
![]() |
0e1322bacb | ||
![]() |
b1d8c988bc | ||
![]() |
838657c052 | ||
![]() |
215421ca61 | ||
![]() |
7a13beb213 | ||
![]() |
18897aaf5d | ||
![]() |
f728a0be42 | ||
![]() |
98f4a20899 | ||
![]() |
dd8ef28b27 | ||
![]() |
be92da280d | ||
![]() |
30f09fbfd1 | ||
![]() |
0790be0f2c | ||
![]() |
848ed4f644 | ||
![]() |
26aec6afed | ||
![]() |
3d335bc54b | ||
![]() |
8925e3865c | ||
![]() |
e561c63036 | ||
![]() |
2c7bab76a2 | ||
![]() |
1e9f88889f | ||
![]() |
7d4420bd69 | ||
![]() |
a14e7ee82c | ||
![]() |
bbeb8e619d | ||
![]() |
1a5614e971 | ||
![]() |
0089897d41 | ||
![]() |
1ed9eb255d | ||
![]() |
0a482e2edb | ||
![]() |
190e3f4bd9 | ||
![]() |
8853758268 | ||
![]() |
98ee15ca3a | ||
![]() |
f2e82c3d79 | ||
![]() |
144acef684 | ||
![]() |
9dfe720579 | ||
![]() |
fca8c3be01 | ||
![]() |
6ed2bc154f | ||
![]() |
7b7690ed9c | ||
![]() |
6bd1512024 | ||
![]() |
2e5cc9051b | ||
![]() |
ffa6c5f457 | ||
![]() |
3cbb419def | ||
![]() |
a2a7763ac7 | ||
![]() |
75229705a0 | ||
![]() |
897a97a6af | ||
![]() |
f6e13e0dd3 | ||
![]() |
a88e424f6c | ||
![]() |
2e0f3ac758 | ||
![]() |
6c24193293 | ||
![]() |
5e4021a2f5 | ||
![]() |
6ddf71e6e9 | ||
![]() |
3f738f5897 | ||
![]() |
88c87f0af4 | ||
![]() |
dbff3e9f12 | ||
![]() |
b1318e578b | ||
![]() |
446b6f30a4 | ||
![]() |
c1b9dd3ab5 | ||
![]() |
0f18b3fe0a | ||
![]() |
85546a5477 | ||
![]() |
c90009aa20 | ||
![]() |
bf2ee7bcdc | ||
![]() |
e3f743339a | ||
![]() |
e7456399e4 |
147
Makefile
147
Makefile
@@ -12,29 +12,37 @@
|
|||||||
# o Do not print "Entering directory ...";
|
# o Do not print "Entering directory ...";
|
||||||
MAKEFLAGS += -r --no-print-directory
|
MAKEFLAGS += -r --no-print-directory
|
||||||
|
|
||||||
|
# Readlink -f requires GNU readlink
|
||||||
|
ifeq ($(shell uname -s),Darwin)
|
||||||
|
READLINK ?= greadlink
|
||||||
|
else
|
||||||
|
READLINK ?= readlink
|
||||||
|
endif
|
||||||
|
|
||||||
# Find out source, build, and install directories
|
# Find out source, build, and install directories
|
||||||
src_dir=$(CURDIR)
|
src_dir=$(CURDIR)
|
||||||
ifdef O
|
ifdef O
|
||||||
build_dir=$(shell readlink -f $(O))
|
build_dir=$(shell $(READLINK) -f $(O))
|
||||||
else
|
else
|
||||||
build_dir=$(CURDIR)/build
|
build_dir=$(CURDIR)/build
|
||||||
endif
|
endif
|
||||||
ifeq ($(build_dir),$(CURDIR))
|
ifeq ($(build_dir),$(CURDIR))
|
||||||
$(error Build directory is same as source directory.)
|
$(error Build directory is same as source directory.)
|
||||||
endif
|
endif
|
||||||
|
install_root_dir_default=$(CURDIR)/install
|
||||||
ifdef I
|
ifdef I
|
||||||
install_dir=$(shell readlink -f $(I))
|
install_root_dir=$(shell $(READLINK) -f $(I))
|
||||||
else
|
else
|
||||||
install_dir=$(CURDIR)/install
|
install_root_dir=$(install_root_dir_default)/usr
|
||||||
endif
|
endif
|
||||||
ifeq ($(install_dir),$(CURDIR))
|
ifeq ($(install_root_dir),$(CURDIR))
|
||||||
$(error Install directory is same as source directory.)
|
$(error Install root directory is same as source directory.)
|
||||||
endif
|
endif
|
||||||
ifeq ($(install_dir),$(build_dir))
|
ifeq ($(install_root_dir),$(build_dir))
|
||||||
$(error Install directory is same as build directory.)
|
$(error Install root directory is same as build directory.)
|
||||||
endif
|
endif
|
||||||
ifdef PLATFORM_DIR
|
ifdef PLATFORM_DIR
|
||||||
platform_dir_path=$(shell readlink -f $(PLATFORM_DIR))
|
platform_dir_path=$(shell $(READLINK) -f $(PLATFORM_DIR))
|
||||||
ifdef PLATFORM
|
ifdef PLATFORM
|
||||||
platform_parent_dir=$(platform_dir_path)
|
platform_parent_dir=$(platform_dir_path)
|
||||||
else
|
else
|
||||||
@@ -65,6 +73,7 @@ export firmware_dir=$(CURDIR)/firmware
|
|||||||
# Find library version
|
# Find library version
|
||||||
OPENSBI_VERSION_MAJOR=`grep "define OPENSBI_VERSION_MAJOR" $(include_dir)/sbi/sbi_version.h | sed 's/.*MAJOR.*\([0-9][0-9]*\)/\1/'`
|
OPENSBI_VERSION_MAJOR=`grep "define OPENSBI_VERSION_MAJOR" $(include_dir)/sbi/sbi_version.h | sed 's/.*MAJOR.*\([0-9][0-9]*\)/\1/'`
|
||||||
OPENSBI_VERSION_MINOR=`grep "define OPENSBI_VERSION_MINOR" $(include_dir)/sbi/sbi_version.h | sed 's/.*MINOR.*\([0-9][0-9]*\)/\1/'`
|
OPENSBI_VERSION_MINOR=`grep "define OPENSBI_VERSION_MINOR" $(include_dir)/sbi/sbi_version.h | sed 's/.*MINOR.*\([0-9][0-9]*\)/\1/'`
|
||||||
|
OPENSBI_VERSION_GIT=$(shell if [ -d $(src_dir)/.git ]; then git describe 2> /dev/null; fi)
|
||||||
|
|
||||||
# Setup compilation commands
|
# Setup compilation commands
|
||||||
ifdef CROSS_COMPILE
|
ifdef CROSS_COMPILE
|
||||||
@@ -85,6 +94,8 @@ DTC = dtc
|
|||||||
|
|
||||||
# Guess the compillers xlen
|
# Guess the compillers xlen
|
||||||
OPENSBI_CC_XLEN := $(shell TMP=`$(CC) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
|
OPENSBI_CC_XLEN := $(shell TMP=`$(CC) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
|
||||||
|
OPENSBI_CC_ABI := $(shell TMP=`$(CC) -v 2>&1 | sed -n 's/.*\(with\-abi=\([a-zA-Z0-9]*\)\).*/\2/p'`; echo $${TMP})
|
||||||
|
OPENSBI_CC_ISA := $(shell TMP=`$(CC) -v 2>&1 | sed -n 's/.*\(with\-arch=\([a-zA-Z0-9]*\)\).*/\2/p'`; echo $${TMP})
|
||||||
|
|
||||||
# Setup platform XLEN
|
# Setup platform XLEN
|
||||||
ifndef PLATFORM_RISCV_XLEN
|
ifndef PLATFORM_RISCV_XLEN
|
||||||
@@ -121,7 +132,6 @@ libsbi-objs-path-y=$(foreach obj,$(libsbi-objs-y),$(build_dir)/lib/sbi/$(obj))
|
|||||||
libsbiutils-objs-path-y=$(foreach obj,$(libsbiutils-objs-y),$(build_dir)/lib/utils/$(obj))
|
libsbiutils-objs-path-y=$(foreach obj,$(libsbiutils-objs-y),$(build_dir)/lib/utils/$(obj))
|
||||||
ifdef PLATFORM
|
ifdef PLATFORM
|
||||||
platform-objs-path-y=$(foreach obj,$(platform-objs-y),$(platform_build_dir)/$(obj))
|
platform-objs-path-y=$(foreach obj,$(platform-objs-y),$(platform_build_dir)/$(obj))
|
||||||
platform-dtb-path-y=$(foreach obj,$(platform-dtb-y),$(platform_build_dir)/$(obj))
|
|
||||||
firmware-bins-path-y=$(foreach bin,$(firmware-bins-y),$(platform_build_dir)/firmware/$(bin))
|
firmware-bins-path-y=$(foreach bin,$(firmware-bins-y),$(platform_build_dir)/firmware/$(bin))
|
||||||
endif
|
endif
|
||||||
firmware-elfs-path-y=$(firmware-bins-path-y:.bin=.elf)
|
firmware-elfs-path-y=$(firmware-bins-path-y:.bin=.elf)
|
||||||
@@ -135,27 +145,65 @@ deps-y+=$(firmware-objs-path-y:.o=.dep)
|
|||||||
|
|
||||||
# Setup platform ABI, ISA and Code Model
|
# Setup platform ABI, ISA and Code Model
|
||||||
ifndef PLATFORM_RISCV_ABI
|
ifndef PLATFORM_RISCV_ABI
|
||||||
|
ifneq ($(PLATFORM_RISCV_TOOLCHAIN_DEFAULT), 1)
|
||||||
ifeq ($(PLATFORM_RISCV_XLEN), 32)
|
ifeq ($(PLATFORM_RISCV_XLEN), 32)
|
||||||
PLATFORM_RISCV_ABI = ilp$(PLATFORM_RISCV_XLEN)
|
PLATFORM_RISCV_ABI = ilp$(PLATFORM_RISCV_XLEN)
|
||||||
else
|
else
|
||||||
PLATFORM_RISCV_ABI = lp$(PLATFORM_RISCV_XLEN)
|
PLATFORM_RISCV_ABI = lp$(PLATFORM_RISCV_XLEN)
|
||||||
endif
|
endif
|
||||||
|
else
|
||||||
|
PLATFORM_RISCV_ABI = $(OPENSBI_CC_ABI)
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
ifndef PLATFORM_RISCV_ISA
|
ifndef PLATFORM_RISCV_ISA
|
||||||
|
ifneq ($(PLATFORM_RISCV_TOOLCHAIN_DEFAULT), 1)
|
||||||
PLATFORM_RISCV_ISA = rv$(PLATFORM_RISCV_XLEN)imafdc
|
PLATFORM_RISCV_ISA = rv$(PLATFORM_RISCV_XLEN)imafdc
|
||||||
|
else
|
||||||
|
PLATFORM_RISCV_ISA = $(OPENSBI_CC_ISA)
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
ifndef PLATFORM_RISCV_CODE_MODEL
|
ifndef PLATFORM_RISCV_CODE_MODEL
|
||||||
PLATFORM_RISCV_CODE_MODEL = medany
|
PLATFORM_RISCV_CODE_MODEL = medany
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Setup install directories
|
||||||
|
ifdef INSTALL_INCLUDE_PATH
|
||||||
|
install_include_path=$(INSTALL_INCLUDE_PATH)
|
||||||
|
else
|
||||||
|
install_include_path=include
|
||||||
|
endif
|
||||||
|
ifdef INSTALL_LIB_PATH
|
||||||
|
install_lib_path=$(INSTALL_LIB_PATH)
|
||||||
|
else
|
||||||
|
ifneq ($(origin INSTALL_LIB_SUBDIR), undefined)
|
||||||
|
install_lib_subdir=$(INSTALL_LIB_SUBDIR)
|
||||||
|
else
|
||||||
|
install_lib_subdir=$(PLATFORM_RISCV_ABI)
|
||||||
|
endif
|
||||||
|
install_lib_path=lib$(subst 32,,$(PLATFORM_RISCV_XLEN))/$(install_lib_subdir)
|
||||||
|
endif
|
||||||
|
ifdef INSTALL_FIRMWARE_PATH
|
||||||
|
install_firmware_path=$(INSTALL_FIRMWARE_PATH)
|
||||||
|
else
|
||||||
|
install_firmware_path=share/opensbi/$(PLATFORM_RISCV_ABI)
|
||||||
|
endif
|
||||||
|
ifdef INSTALL_DOCS_PATH
|
||||||
|
install_docs_path=$(INSTALL_DOCS_PATH)
|
||||||
|
else
|
||||||
|
install_docs_path=share/opensbi/docs
|
||||||
|
endif
|
||||||
|
|
||||||
# Setup compilation commands flags
|
# Setup compilation commands flags
|
||||||
GENFLAGS = -I$(platform_src_dir)/include
|
GENFLAGS = -I$(platform_src_dir)/include
|
||||||
GENFLAGS += -I$(include_dir)
|
GENFLAGS += -I$(include_dir)
|
||||||
|
ifneq ($(OPENSBI_VERSION_GIT),)
|
||||||
|
GENFLAGS += -DOPENSBI_VERSION_GIT="\"$(OPENSBI_VERSION_GIT)\""
|
||||||
|
endif
|
||||||
GENFLAGS += $(libsbiutils-genflags-y)
|
GENFLAGS += $(libsbiutils-genflags-y)
|
||||||
GENFLAGS += $(platform-genflags-y)
|
GENFLAGS += $(platform-genflags-y)
|
||||||
GENFLAGS += $(firmware-genflags-y)
|
GENFLAGS += $(firmware-genflags-y)
|
||||||
|
|
||||||
CFLAGS = -g -Wall -Werror -nostdlib -fno-strict-aliasing -O2
|
CFLAGS = -g -Wall -Werror -ffreestanding -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 += -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
|
||||||
@@ -188,7 +236,7 @@ MERGEFLAGS += -r
|
|||||||
MERGEFLAGS += -b elf$(PLATFORM_RISCV_XLEN)-littleriscv
|
MERGEFLAGS += -b elf$(PLATFORM_RISCV_XLEN)-littleriscv
|
||||||
MERGEFLAGS += -m elf$(PLATFORM_RISCV_XLEN)lriscv
|
MERGEFLAGS += -m elf$(PLATFORM_RISCV_XLEN)lriscv
|
||||||
|
|
||||||
DTCFLAGS = -O dtb
|
DTSCPPFLAGS = $(CPPFLAGS) -nostdinc -nostdlib -fno-builtin -D__DTS__ -x assembler-with-cpp
|
||||||
|
|
||||||
# Setup functions for compilation
|
# Setup functions for compilation
|
||||||
define dynamic_flags
|
define dynamic_flags
|
||||||
@@ -204,12 +252,12 @@ copy_file = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
|||||||
echo " COPY $(subst $(build_dir)/,,$(1))"; \
|
echo " COPY $(subst $(build_dir)/,,$(1))"; \
|
||||||
cp -f $(2) $(1)
|
cp -f $(2) $(1)
|
||||||
inst_file = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
inst_file = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||||
echo " INSTALL $(subst $(install_dir)/,,$(1))"; \
|
echo " INSTALL $(subst $(install_root_dir)/,,$(1))"; \
|
||||||
cp -f $(2) $(1)
|
cp -f $(2) $(1)
|
||||||
inst_file_list = $(CMD_PREFIX)if [ ! -z "$(4)" ]; then \
|
inst_file_list = $(CMD_PREFIX)if [ ! -z "$(4)" ]; then \
|
||||||
mkdir -p $(1)/$(3); \
|
mkdir -p $(1)/$(3); \
|
||||||
for file in $(4) ; do \
|
for file in $(4) ; do \
|
||||||
rel_file=`echo $$file | sed -e 's@$(2)/$(3)/@@'`; \
|
rel_file=`echo $$file | sed -e 's@$(2)/$(subst $(install_firmware_path),platform,$(3))@@'`; \
|
||||||
dest_file=$(1)"/"$(3)"/"`echo $$rel_file`; \
|
dest_file=$(1)"/"$(3)"/"`echo $$rel_file`; \
|
||||||
dest_dir=`dirname $$dest_file`; \
|
dest_dir=`dirname $$dest_file`; \
|
||||||
echo " INSTALL "$(3)"/"`echo $$rel_file`; \
|
echo " INSTALL "$(3)"/"`echo $$rel_file`; \
|
||||||
@@ -218,7 +266,7 @@ inst_file_list = $(CMD_PREFIX)if [ ! -z "$(4)" ]; then \
|
|||||||
done \
|
done \
|
||||||
fi
|
fi
|
||||||
inst_header_dir = $(CMD_PREFIX)mkdir -p $(1); \
|
inst_header_dir = $(CMD_PREFIX)mkdir -p $(1); \
|
||||||
echo " INSTALL $(subst $(install_dir)/,,$(1))"; \
|
echo " INSTALL $(subst $(install_root_dir)/,,$(1))"; \
|
||||||
cp -rf $(2) $(1)
|
cp -rf $(2) $(1)
|
||||||
compile_cpp = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
compile_cpp = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||||
echo " CPP $(subst $(build_dir)/,,$(1))"; \
|
echo " CPP $(subst $(build_dir)/,,$(1))"; \
|
||||||
@@ -250,13 +298,21 @@ compile_objcopy = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
|||||||
$(OBJCOPY) -S -O binary $(2) $(1)
|
$(OBJCOPY) -S -O binary $(2) $(1)
|
||||||
compile_dts = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
compile_dts = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||||
echo " DTC $(subst $(build_dir)/,,$(1))"; \
|
echo " DTC $(subst $(build_dir)/,,$(1))"; \
|
||||||
$(DTC) $(DTCFLAGS) -o $(1) $(2)
|
$(CPP) $(DTSCPPFLAGS) $(2) | $(DTC) -O dtb -i `dirname $(2)` -o $(1)
|
||||||
|
compile_d2c = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||||
|
echo " D2C $(subst $(build_dir)/,,$(1))"; \
|
||||||
|
$(if $($(2)-varalign-$(3)),$(eval D2C_ALIGN_BYTES := $($(2)-varalign-$(3))),$(eval D2C_ALIGN_BYTES := $(4))) \
|
||||||
|
$(if $($(2)-varprefix-$(3)),$(eval D2C_NAME_PREFIX := $($(2)-varprefix-$(3))),$(eval D2C_NAME_PREFIX := $(5))) \
|
||||||
|
$(if $($(2)-padding-$(3)),$(eval D2C_PADDING_BYTES := $($(2)-padding-$(3))),$(eval D2C_PADDING_BYTES := 0)) \
|
||||||
|
$(src_dir)/scripts/d2c.sh -i $(6) -a $(D2C_ALIGN_BYTES) -p $(D2C_NAME_PREFIX) -t $(D2C_PADDING_BYTES) > $(1)
|
||||||
|
compile_gen_dep = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \
|
||||||
|
echo " GEN-DEP $(subst $(build_dir)/,,$(1))"; \
|
||||||
|
echo "$(1:.dep=$(2)): $(3)" >> $(1)
|
||||||
|
|
||||||
targets-y = $(build_dir)/lib/libsbi.a
|
targets-y = $(build_dir)/lib/libsbi.a
|
||||||
targets-y += $(build_dir)/lib/libsbiutils.a
|
targets-y += $(build_dir)/lib/libsbiutils.a
|
||||||
ifdef PLATFORM
|
ifdef PLATFORM
|
||||||
targets-y += $(platform_build_dir)/lib/libplatsbi.a
|
targets-y += $(platform_build_dir)/lib/libplatsbi.a
|
||||||
targets-y += $(platform-dtb-path-y)
|
|
||||||
endif
|
endif
|
||||||
targets-y += $(firmware-bins-path-y)
|
targets-y += $(firmware-bins-path-y)
|
||||||
|
|
||||||
@@ -267,15 +323,6 @@ all: $(targets-y)
|
|||||||
# Preserve all intermediate files
|
# Preserve all intermediate files
|
||||||
.SECONDARY:
|
.SECONDARY:
|
||||||
|
|
||||||
$(build_dir)/%.bin: $(build_dir)/%.elf
|
|
||||||
$(call compile_objcopy,$@,$<)
|
|
||||||
|
|
||||||
$(build_dir)/%.elf: $(build_dir)/%.o $(build_dir)/%.elf.ld $(platform_build_dir)/lib/libplatsbi.a
|
|
||||||
$(call compile_elf,$@,$@.ld,$< $(platform_build_dir)/lib/libplatsbi.a)
|
|
||||||
|
|
||||||
$(platform_build_dir)/%.ld: $(src_dir)/%.ldS
|
|
||||||
$(call compile_cpp,$@,$<)
|
|
||||||
|
|
||||||
$(build_dir)/lib/libsbi.a: $(libsbi-objs-path-y)
|
$(build_dir)/lib/libsbi.a: $(libsbi-objs-path-y)
|
||||||
$(call compile_ar,$@,$^)
|
$(call compile_ar,$@,$^)
|
||||||
|
|
||||||
@@ -297,18 +344,41 @@ $(build_dir)/%.dep: $(src_dir)/%.S
|
|||||||
$(build_dir)/%.o: $(src_dir)/%.S
|
$(build_dir)/%.o: $(src_dir)/%.S
|
||||||
$(call compile_as,$@,$<)
|
$(call compile_as,$@,$<)
|
||||||
|
|
||||||
|
$(platform_build_dir)/%.bin: $(platform_build_dir)/%.elf
|
||||||
|
$(call compile_objcopy,$@,$<)
|
||||||
|
|
||||||
|
$(platform_build_dir)/%.elf: $(platform_build_dir)/%.o $(platform_build_dir)/%.elf.ld $(platform_build_dir)/lib/libplatsbi.a
|
||||||
|
$(call compile_elf,$@,$@.ld,$< $(platform_build_dir)/lib/libplatsbi.a)
|
||||||
|
|
||||||
|
$(platform_build_dir)/%.ld: $(src_dir)/%.ldS
|
||||||
|
$(call compile_cpp,$@,$<)
|
||||||
|
|
||||||
$(platform_build_dir)/%.dep: $(platform_src_dir)/%.c
|
$(platform_build_dir)/%.dep: $(platform_src_dir)/%.c
|
||||||
$(call compile_cc_dep,$@,$<)
|
$(call compile_cc_dep,$@,$<)
|
||||||
|
|
||||||
$(platform_build_dir)/%.o: $(platform_src_dir)/%.c
|
$(platform_build_dir)/%.o: $(platform_src_dir)/%.c
|
||||||
$(call compile_cc,$@,$<)
|
$(call compile_cc,$@,$<)
|
||||||
|
|
||||||
|
$(platform_build_dir)/%.o: $(platform_build_dir)/%.c
|
||||||
|
$(call compile_cc,$@,$<)
|
||||||
|
|
||||||
$(platform_build_dir)/%.dep: $(platform_src_dir)/%.S
|
$(platform_build_dir)/%.dep: $(platform_src_dir)/%.S
|
||||||
$(call compile_as_dep,$@,$<)
|
$(call compile_as_dep,$@,$<)
|
||||||
|
|
||||||
$(platform_build_dir)/%.o: $(platform_src_dir)/%.S
|
$(platform_build_dir)/%.o: $(platform_src_dir)/%.S
|
||||||
$(call compile_as,$@,$<)
|
$(call compile_as,$@,$<)
|
||||||
|
|
||||||
|
$(platform_build_dir)/%.dep: $(platform_src_dir)/%.dts
|
||||||
|
$(call compile_gen_dep,$@,.dtb,$<)
|
||||||
|
$(call compile_gen_dep,$@,.c,$(@:.dep=.dtb))
|
||||||
|
$(call compile_gen_dep,$@,.o,$(@:.dep=.c))
|
||||||
|
|
||||||
|
$(platform_build_dir)/%.c: $(platform_build_dir)/%.dtb
|
||||||
|
$(call compile_d2c,$@,platform,$(subst .dtb,.o,$(subst /,-,$(subst $(platform_build_dir)/,,$<))),16,dt,$<)
|
||||||
|
|
||||||
|
$(platform_build_dir)/%.dtb: $(platform_src_dir)/%.dts
|
||||||
|
$(call compile_dts,$@,$<)
|
||||||
|
|
||||||
$(platform_build_dir)/%.dep: $(src_dir)/%.c
|
$(platform_build_dir)/%.dep: $(src_dir)/%.c
|
||||||
$(call compile_cc_dep,$@,$<)
|
$(call compile_cc_dep,$@,$<)
|
||||||
|
|
||||||
@@ -321,9 +391,6 @@ $(platform_build_dir)/%.dep: $(src_dir)/%.S
|
|||||||
$(platform_build_dir)/%.o: $(src_dir)/%.S
|
$(platform_build_dir)/%.o: $(src_dir)/%.S
|
||||||
$(call compile_as,$@,$<)
|
$(call compile_as,$@,$<)
|
||||||
|
|
||||||
$(build_dir)/%.dtb: $(src_dir)/%.dts
|
|
||||||
$(call compile_dts,$@,$<)
|
|
||||||
|
|
||||||
# Rule for "make docs"
|
# Rule for "make docs"
|
||||||
$(build_dir)/docs/latex/refman.pdf: $(build_dir)/docs/latex/refman.tex
|
$(build_dir)/docs/latex/refman.pdf: $(build_dir)/docs/latex/refman.tex
|
||||||
$(CMD_PREFIX)mkdir -p $(build_dir)/docs
|
$(CMD_PREFIX)mkdir -p $(build_dir)/docs
|
||||||
@@ -374,26 +441,26 @@ install: $(install_targets-y)
|
|||||||
|
|
||||||
.PHONY: install_libsbi
|
.PHONY: install_libsbi
|
||||||
install_libsbi: $(build_dir)/lib/libsbi.a
|
install_libsbi: $(build_dir)/lib/libsbi.a
|
||||||
$(call inst_header_dir,$(install_dir)/include,$(include_dir)/sbi)
|
$(call inst_header_dir,$(install_root_dir)/$(install_include_path),$(include_dir)/sbi)
|
||||||
$(call inst_file,$(install_dir)/lib/libsbi.a,$(build_dir)/lib/libsbi.a)
|
$(call inst_file,$(install_root_dir)/$(install_lib_path)/libsbi.a,$(build_dir)/lib/libsbi.a)
|
||||||
|
|
||||||
.PHONY: install_libsbiutils
|
.PHONY: install_libsbiutils
|
||||||
install_libsbiutils: $(build_dir)/lib/libsbiutils.a
|
install_libsbiutils: $(build_dir)/lib/libsbiutils.a
|
||||||
$(call inst_header_dir,$(install_dir)/include,$(include_dir)/sbi_utils)
|
$(call inst_header_dir,$(install_root_dir)/$(install_include_path),$(include_dir)/sbi_utils)
|
||||||
$(call inst_file,$(install_dir)/lib/libsbiutils.a,$(build_dir)/lib/libsbiutils.a)
|
$(call inst_file,$(install_root_dir)/$(install_lib_path)/libsbiutils.a,$(build_dir)/lib/libsbiutils.a)
|
||||||
|
|
||||||
.PHONY: install_libplatsbi
|
.PHONY: install_libplatsbi
|
||||||
install_libplatsbi: $(platform_build_dir)/lib/libplatsbi.a $(build_dir)/lib/libsbi.a $(build_dir)/lib/libsbiutils.a
|
install_libplatsbi: $(platform_build_dir)/lib/libplatsbi.a $(build_dir)/lib/libsbi.a $(build_dir)/lib/libsbiutils.a
|
||||||
$(call inst_file,$(install_dir)/platform/$(platform_subdir)/lib/libplatsbi.a,$(platform_build_dir)/lib/libplatsbi.a)
|
$(call inst_file,$(install_root_dir)/$(install_lib_path)/opensbi/$(platform_subdir)/lib/libplatsbi.a,$(platform_build_dir)/lib/libplatsbi.a)
|
||||||
|
|
||||||
.PHONY: install_firmwares
|
.PHONY: install_firmwares
|
||||||
install_firmwares: $(platform_build_dir)/lib/libplatsbi.a $(build_dir)/lib/libsbi.a $(build_dir)/lib/libsbiutils.a $(firmware-bins-path-y)
|
install_firmwares: $(platform_build_dir)/lib/libplatsbi.a $(build_dir)/lib/libsbi.a $(build_dir)/lib/libsbiutils.a $(firmware-bins-path-y)
|
||||||
$(call inst_file_list,$(install_dir),$(build_dir),platform/$(platform_subdir)/firmware,$(firmware-elfs-path-y))
|
$(call inst_file_list,$(install_root_dir),$(build_dir),$(install_firmware_path)/$(platform_subdir)/firmware,$(firmware-elfs-path-y))
|
||||||
$(call inst_file_list,$(install_dir),$(build_dir),platform/$(platform_subdir)/firmware,$(firmware-bins-path-y))
|
$(call inst_file_list,$(install_root_dir),$(build_dir),$(install_firmware_path)/$(platform_subdir)/firmware,$(firmware-bins-path-y))
|
||||||
|
|
||||||
.PHONY: install_docs
|
.PHONY: install_docs
|
||||||
install_docs: $(build_dir)/docs/latex/refman.pdf
|
install_docs: $(build_dir)/docs/latex/refman.pdf
|
||||||
$(call inst_file,$(install_dir)/docs/refman.pdf,$(build_dir)/docs/latex/refman.pdf)
|
$(call inst_file,$(install_root_dir)/$(install_docs_path)/refman.pdf,$(build_dir)/docs/latex/refman.pdf)
|
||||||
|
|
||||||
# Rule for "make clean"
|
# Rule for "make clean"
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
@@ -407,6 +474,8 @@ clean:
|
|||||||
$(CMD_PREFIX)find $(build_dir) -type f -name "*.elf" -exec rm -rf {} +
|
$(CMD_PREFIX)find $(build_dir) -type f -name "*.elf" -exec rm -rf {} +
|
||||||
$(if $(V), @echo " RM $(build_dir)/*.bin")
|
$(if $(V), @echo " RM $(build_dir)/*.bin")
|
||||||
$(CMD_PREFIX)find $(build_dir) -type f -name "*.bin" -exec rm -rf {} +
|
$(CMD_PREFIX)find $(build_dir) -type f -name "*.bin" -exec rm -rf {} +
|
||||||
|
$(if $(V), @echo " RM $(build_dir)/*.dtb")
|
||||||
|
$(CMD_PREFIX)find $(build_dir) -type f -name "*.dtb" -exec rm -rf {} +
|
||||||
|
|
||||||
# Rule for "make distclean"
|
# Rule for "make distclean"
|
||||||
.PHONY: distclean
|
.PHONY: distclean
|
||||||
@@ -418,7 +487,7 @@ ifeq ($(build_dir),$(CURDIR)/build)
|
|||||||
$(if $(V), @echo " RM $(build_dir)")
|
$(if $(V), @echo " RM $(build_dir)")
|
||||||
$(CMD_PREFIX)rm -rf $(build_dir)
|
$(CMD_PREFIX)rm -rf $(build_dir)
|
||||||
endif
|
endif
|
||||||
ifeq ($(install_dir),$(CURDIR)/install)
|
ifeq ($(install_root_dir),$(install_root_dir_default)/usr)
|
||||||
$(if $(V), @echo " RM $(install_dir)")
|
$(if $(V), @echo " RM $(install_root_dir_default)")
|
||||||
$(CMD_PREFIX)rm -rf $(install_dir)
|
$(CMD_PREFIX)rm -rf $(install_root_dir_default)
|
||||||
endif
|
endif
|
||||||
|
116
README.md
116
README.md
@@ -1,9 +1,41 @@
|
|||||||
Copyright (c) 2019 Western Digital Corporation or its affiliates
|
|
||||||
and other contributors.
|
|
||||||
|
|
||||||
RISC-V Open Source Supervisor Binary Interface (OpenSBI)
|
RISC-V Open Source Supervisor Binary Interface (OpenSBI)
|
||||||
========================================================
|
========================================================
|
||||||
|
|
||||||
|
Copyright and License
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The OpenSBI project is copyright (c) 2019 Western Digital Corporation
|
||||||
|
or its affiliates and other contributors.
|
||||||
|
|
||||||
|
It is distributed under the terms of the BSD 2-clause license
|
||||||
|
("Simplified BSD License" or "FreeBSD License", SPDX: *BSD-2-Clause*).
|
||||||
|
A copy of this license with OpenSBI copyright can be found in the file
|
||||||
|
[COPYING.BSD].
|
||||||
|
|
||||||
|
All source files in OpenSBI contain the 2-Clause BSD license SPDX short
|
||||||
|
identifier in place of the full license text.
|
||||||
|
|
||||||
|
```
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
```
|
||||||
|
|
||||||
|
This enables machine processing of license information based on the SPDX
|
||||||
|
License Identifiers that are available on the [SPDX] web site.
|
||||||
|
|
||||||
|
OpenSBI source code also contains code reused from other projects as listed
|
||||||
|
below. The original license text of these projects is included in the source
|
||||||
|
files where the reused code is present.
|
||||||
|
|
||||||
|
* The libfdt source code is disjunctively dual licensed
|
||||||
|
(GPL-2.0+ OR BSD-2-Clause). Some of this project code is used in OpenSBI
|
||||||
|
under the terms of the BSD 2-Clause license. Any contributions to this
|
||||||
|
code must be made under the terms of both licenses.
|
||||||
|
|
||||||
|
See also the [third party notices] file for more information.
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
The **RISC-V Supervisor Binary Interface (SBI)** is the recommended interface
|
The **RISC-V Supervisor Binary Interface (SBI)** is the recommended interface
|
||||||
between:
|
between:
|
||||||
|
|
||||||
@@ -13,7 +45,7 @@ between:
|
|||||||
executing 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 on [Github] (https://github.com/riscv/riscv-sbi-doc).
|
RISC-V Foundation on [Github].
|
||||||
|
|
||||||
The goal of the OpenSBI project is to provide an open-source reference
|
The goal of the OpenSBI project is to provide an open-source reference
|
||||||
implementation of the RISC-V SBI specifications for platform-specific firmwares
|
implementation of the RISC-V SBI specifications for platform-specific firmwares
|
||||||
@@ -37,17 +69,37 @@ platform-dependent hardware manipulation functions. For all supported platforms,
|
|||||||
OpenSBI also provides several runtime firmware examples built using the platform
|
OpenSBI also provides several runtime firmware examples built using the platform
|
||||||
*libplatsbi.a*. These example firmwares can be used to replace the legacy
|
*libplatsbi.a*. These example firmwares can be used to replace the legacy
|
||||||
*riscv-pk* bootloader (aka BBL) and enable the use of well-known bootloaders
|
*riscv-pk* bootloader (aka BBL) and enable the use of well-known bootloaders
|
||||||
such as [U-Boot] (https://git.denx.de/u-boot.git).
|
such as [U-Boot].
|
||||||
|
|
||||||
|
Supported SBI version
|
||||||
|
---------------------
|
||||||
|
Currently, OpenSBI fully supports SBI specification *v0.2*. OpenSBI also
|
||||||
|
supports Hart State Management (HSM) SBI extension starting from OpenSBI v0.7.
|
||||||
|
HSM extension allows S-mode software to boot all the harts a defined order
|
||||||
|
rather than legacy method of random booting of harts. As a result, many
|
||||||
|
required features such as CPU hotplug, kexec/kdump can also be supported easily
|
||||||
|
in S-mode. HSM extension in OpenSBI is implemented in a non-backward compatible
|
||||||
|
manner to reduce the maintenance burden and avoid confusion. That's why, any
|
||||||
|
S-mode software using OpenSBI will not be able to boot more than 1 hart if HSM
|
||||||
|
extension is not supported in S-mode.
|
||||||
|
|
||||||
|
Linux kernel already supports SBI v0.2 and HSM SBI extension starting from
|
||||||
|
**v5.7-rc1**. If you are using an Linux kernel older than **5.7-rc1** or any
|
||||||
|
other S-mode software without HSM SBI extension, you should stick to OpenSBI
|
||||||
|
v0.6 to boot all the harts. For a UMP systems, it doesn't matter.
|
||||||
|
|
||||||
|
N.B. Any S-mode boot loader (i.e. U-Boot) doesn't need to support HSM extension,
|
||||||
|
as it doesn't need to boot all the harts. The operating system should be
|
||||||
|
capable enough to bring up all other non-booting harts using HSM extension.
|
||||||
|
|
||||||
Required Toolchain
|
Required Toolchain
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
OpenSBI can be compiled natively or cross-compiled on a x86 host. For
|
OpenSBI can be compiled natively or cross-compiled on a x86 host. For
|
||||||
cross-compilation, you can build your own toolchain or just download
|
cross-compilation, you can build your own toolchain or just download
|
||||||
a prebuilt one from the
|
a prebuilt one from the [Bootlin toolchain repository].
|
||||||
[Bootlin toolchain repository] (https://toolchains.bootlin.com/).
|
|
||||||
|
|
||||||
Please note that only a 64bit version of the toolchain is available in
|
Please note that only a 64-bit version of the toolchain is available in
|
||||||
the Bootlin toolchain repository for now.
|
the Bootlin toolchain repository for now.
|
||||||
|
|
||||||
Building and Installing the OpenSBI Platform-Independent Library
|
Building and Installing the OpenSBI Platform-Independent Library
|
||||||
@@ -94,7 +146,7 @@ line, the platform-specific static library *libplatsbi.a* and firmware examples
|
|||||||
are built for the platform *<platform_subdir>* present in the directory
|
are built for the platform *<platform_subdir>* present in the directory
|
||||||
*platform* in the OpenSBI top directory. For example, to compile the platform
|
*platform* in the OpenSBI top directory. For example, to compile the platform
|
||||||
library and the firmware examples for the QEMU RISC-V *virt* machine,
|
library and the firmware examples for the QEMU RISC-V *virt* machine,
|
||||||
*<platform_subdir>* should be *qemu/virt*.
|
*<platform_subdir>* should be *generic*.
|
||||||
|
|
||||||
To build *libsbi.a*, *libplatsbi.a* and the firmware for one of the supported
|
To build *libsbi.a*, *libplatsbi.a* and the firmware for one of the supported
|
||||||
platforms, run:
|
platforms, run:
|
||||||
@@ -131,38 +183,24 @@ top-level make command line. These options, such as *PLATFORM_<xyz>* or
|
|||||||
*docs/platform/<platform_name>.md* files and
|
*docs/platform/<platform_name>.md* files and
|
||||||
*docs/firmware/<firmware_name>.md* files.
|
*docs/firmware/<firmware_name>.md* files.
|
||||||
|
|
||||||
License
|
Building 32-bit / 64-bit OpenSBI Images
|
||||||
-------
|
---------------------------------------
|
||||||
|
By default, building OpenSBI generates 32-bit or 64-bit images based on the
|
||||||
|
supplied RISC-V cross-compile toolchain. For example if *CROSS_COMPILE* is set
|
||||||
|
to *riscv64-unknown-elf-*, 64-bit OpenSBI images will be generated. If building
|
||||||
|
32-bit OpenSBI images, *CROSS_COMPILE* should be set to a toolchain that is
|
||||||
|
pre-configured to generate 32-bit RISC-V codes, like *riscv32-unknown-elf-*.
|
||||||
|
|
||||||
OpenSBI is distributed under the terms of the BSD 2-clause license
|
However it's possible to explicitly specify the image bits we want to build with
|
||||||
("Simplified BSD License" or "FreeBSD License", SPDX: *BSD-2-Clause*).
|
a given RISC-V toolchain. This can be done by setting the environment variable
|
||||||
A copy of this license with OpenSBI copyright can be found in the file
|
*PLATFORM_RISCV_XLEN* to the desired width, for example:
|
||||||
[COPYING.BSD].
|
|
||||||
|
|
||||||
All source files in OpenSBI contain the 2-Clause BSD license SPDX short
|
|
||||||
identifier in place of the full license text.
|
|
||||||
|
|
||||||
```
|
```
|
||||||
SPDX-License-Identifier: BSD-2-Clause
|
export CROSS_COMPILE=riscv64-unknown-elf-
|
||||||
|
export PLATFORM_RISCV_XLEN=32
|
||||||
```
|
```
|
||||||
|
|
||||||
This enables machine processing of license information based on the SPDX
|
will generate 32-bit OpenSBI images. And vice vesa.
|
||||||
License Identifiers that are available on the [SPDX] web site.
|
|
||||||
|
|
||||||
OpenSBI source code also contains code reused from other projects as listed
|
|
||||||
below. The original license text of these projects is included in the source
|
|
||||||
files where the reused code is present.
|
|
||||||
|
|
||||||
1. The libfdt source code is disjunctively dual licensed
|
|
||||||
(GPL-2.0+ OR BSD-2-Clause). Some of this project code is used in OpenSBI
|
|
||||||
under the terms of the BSD 2-Clause license. Any contributions to this
|
|
||||||
code must be made under the terms of both licenses.
|
|
||||||
2. Some source file for the Kendryte/k210 platform code are based on code from
|
|
||||||
the [Kendryte standalone SDK] available on github. These files retain the
|
|
||||||
original copyright and license of the Kendryte standalone SDK project and
|
|
||||||
are licensed under the terms of the Apache License, Version 2.0.
|
|
||||||
|
|
||||||
See also the [third party notices] file for more information.
|
|
||||||
|
|
||||||
Contributing to OpenSBI
|
Contributing to OpenSBI
|
||||||
-----------------------
|
-----------------------
|
||||||
@@ -182,10 +220,13 @@ Detailed documentation of various aspects of OpenSBI can be found under the
|
|||||||
|
|
||||||
* [Contribution Guideline]: Guideline for contributing code to OpenSBI project
|
* [Contribution Guideline]: Guideline for contributing code to OpenSBI project
|
||||||
* [Library Usage]: API documentation of OpenSBI static library *libsbi.a*
|
* [Library Usage]: API documentation of OpenSBI static library *libsbi.a*
|
||||||
|
* [Platform Requirements]: Requirements for using OpenSBI on a platform
|
||||||
* [Platform Support Guide]: Guideline for implementing support for new platforms
|
* [Platform 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
|
||||||
examples build supported by OpenSBI.
|
examples build supported by OpenSBI.
|
||||||
|
* [Domain Support]: Documentation for the OpenSBI domain support which helps
|
||||||
|
users achieve system-level partitioning using OpenSBI.
|
||||||
|
|
||||||
OpenSBI source code is also well documented. For source level documentation,
|
OpenSBI source code is also well documented. For source level documentation,
|
||||||
doxygen style is used. Please refer to the [Doxygen manual] for details on this
|
doxygen style is used. Please refer to the [Doxygen manual] for details on this
|
||||||
@@ -229,14 +270,17 @@ make I=<install_directory> install_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
|
[U-Boot]: https://www.denx.de/wiki/U-Boot/SourceCode
|
||||||
|
[Bootlin toolchain repository]: https://toolchains.bootlin.com/
|
||||||
[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
|
||||||
[Contributors List]: CONTRIBUTORS.md
|
[Contributors List]: CONTRIBUTORS.md
|
||||||
[Library Usage]: docs/library_usage.md
|
[Library Usage]: docs/library_usage.md
|
||||||
|
[Platform Requirements]: docs/platform_requirements.md
|
||||||
[Platform Support Guide]: docs/platform_guide.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
|
||||||
|
[Domain Support]: docs/domain_support.md
|
||||||
[Doxygen manual]: http://www.doxygen.nl/manual/index.html
|
[Doxygen manual]: http://www.doxygen.nl/manual/index.html
|
||||||
[Kendryte standalone SDK]: https://github.com/kendryte/kendryte-standalone-sdk
|
[Kendryte standalone SDK]: https://github.com/kendryte/kendryte-standalone-sdk
|
||||||
[third party notices]: ThirdPartyNotices.md
|
[third party notices]: ThirdPartyNotices.md
|
||||||
|
@@ -16,192 +16,3 @@ The libfdt source code is disjunctively dual licensed (GPL-2.0+ or
|
|||||||
BSD-2-Clause). Some of this project code is used in OpenSBI under the terms of
|
BSD-2-Clause). Some of this project code is used in OpenSBI under the terms of
|
||||||
the BSD 2-Clause license. The full text of this license can be found in the
|
the BSD 2-Clause license. The full text of this license can be found in the
|
||||||
file [COPYING.BSD](COPYING.BSD).
|
file [COPYING.BSD](COPYING.BSD).
|
||||||
|
|
||||||
Kendryte Standalone SDK
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
Copyright 2018 Canaan Inc.
|
|
||||||
|
|
||||||
The Kendryte K210 platform code reuses some code from Kendryte standalone SDK
|
|
||||||
licensed under the terms of the Apache License, Version 2.0. The full text of
|
|
||||||
this license is available at http://www.apache.org/licenses/LICENSE-2.0 and
|
|
||||||
included below.
|
|
||||||
|
|
||||||
```
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
```
|
|
||||||
|
314
docs/domain_support.md
Normal file
314
docs/domain_support.md
Normal file
@@ -0,0 +1,314 @@
|
|||||||
|
OpenSBI Domain Support
|
||||||
|
======================
|
||||||
|
|
||||||
|
An OpenSBI domain is a system-level partition (subset) of underlying hardware
|
||||||
|
having it's own memory regions (RAM and MMIO devices) and HARTs. The OpenSBI
|
||||||
|
will try to achieve secure isolation between domains using RISC-V platform
|
||||||
|
features such as PMP, ePMP, IOPMP, SiFive Shield, etc.
|
||||||
|
|
||||||
|
Important entities which help implement OpenSBI domain support are:
|
||||||
|
|
||||||
|
* **struct sbi_domain_memregion** - Representation of a domain memory region
|
||||||
|
* **struct sbi_hartmask** - Representation of domain HART set
|
||||||
|
* **struct sbi_domain** - Representation of a domain instance
|
||||||
|
|
||||||
|
Each HART of a RISC-V platform must have an OpenSBI domain assigned to it.
|
||||||
|
The OpenSBI platform support is responsible for populating domains and
|
||||||
|
providing HART id to domain mapping. The OpenSBI domain support will by
|
||||||
|
default assign **the ROOT domain** to all HARTs of a RISC-V platform so
|
||||||
|
it is not mandatory for the OpenSBI platform support to populate domains.
|
||||||
|
|
||||||
|
Domain Memory Region
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
A domain memory region is represented by **struct sbi_domain_memregion** in
|
||||||
|
OpenSBI and has following details:
|
||||||
|
|
||||||
|
* **order** - The size of a memory region is **2 ^ order** where **order**
|
||||||
|
must be **3 <= order <= __riscv_xlen**
|
||||||
|
* **base** - The base address of a memory region is **2 ^ order**
|
||||||
|
aligned start address
|
||||||
|
* **flags** - The flags of a memory region represent memory type (i.e.
|
||||||
|
RAM or MMIO) and allowed accesses (i.e. READ, WRITE, EXECUTE, etc)
|
||||||
|
|
||||||
|
Domain Instance
|
||||||
|
---------------
|
||||||
|
|
||||||
|
A domain instance is represented by **struct sbi_domain** in OpenSBI and
|
||||||
|
has following details:
|
||||||
|
|
||||||
|
* **index** - Logical index of this domain
|
||||||
|
* **name** - Name of this domain
|
||||||
|
* **assigned_harts** - HARTs assigned to this domain
|
||||||
|
* **possible_harts** - HARTs possible in this domain
|
||||||
|
* **regions** - Array of memory regions terminated by a memory region
|
||||||
|
with order zero
|
||||||
|
* **boot_hartid** - HART id of the HART booting this domain. The domain
|
||||||
|
boot HART will be started at boot-time if boot HART is possible and
|
||||||
|
assigned for this domain.
|
||||||
|
* **next_addr** - Address of the next booting stage for this domain
|
||||||
|
* **next_arg1** - Arg1 (or 'a1' register) of the next booting stage for
|
||||||
|
this domain
|
||||||
|
* **next_mode** - Privilege mode of the next booting stage for this
|
||||||
|
domain. This can be either S-mode or U-mode.
|
||||||
|
* **system_reset_allowed** - Is domain allowed to reset the system?
|
||||||
|
|
||||||
|
The memory regions represented by **regions** in **struct sbi_domain** have
|
||||||
|
following additional constraints to align with RISC-V PMP requirements:
|
||||||
|
|
||||||
|
* A memory region to protect OpenSBI firmware from S-mode and U-mode
|
||||||
|
should always be present
|
||||||
|
* For two overlapping memory regions, one should be sub-region of another
|
||||||
|
* Two overlapping memory regions should not be of same size
|
||||||
|
* Two overlapping memory regions cannot have same flags
|
||||||
|
* Memory access checks on overlapping address should prefer smallest
|
||||||
|
overlapping memory region flags.
|
||||||
|
|
||||||
|
ROOT Domain
|
||||||
|
-----------
|
||||||
|
|
||||||
|
**The ROOT domain** is the default OpenSBI domain which is assigned by
|
||||||
|
default to all HARTs of a RISC-V platform. The OpenSBI domain support
|
||||||
|
will hand-craft **the ROOT domain** very early at boot-time in the
|
||||||
|
following manner:
|
||||||
|
|
||||||
|
* **index** - Logical index of the ROOT domain is always zero
|
||||||
|
* **name** - Name of the ROOT domain is "root"
|
||||||
|
* **assigned_harts** - At boot-time all valid HARTs of a RISC-V platform
|
||||||
|
are assigned the ROOT domain which changes later based on OpenSBI
|
||||||
|
platform support
|
||||||
|
* **possible_harts** - All valid HARTs of a RISC-V platform are possible
|
||||||
|
HARTs of the ROOT domain
|
||||||
|
* **regions** - Two memory regions available to the ROOT domain:
|
||||||
|
**A)** A memory region to protect OpenSBI firmware from S-mode and U-mode
|
||||||
|
**B)** A memory region of **order=__riscv_xlen** allowing S-mode and
|
||||||
|
U-mode access to full memory address space
|
||||||
|
* **boot_hartid** - Coldboot HART is the HART booting the ROOT domain
|
||||||
|
* **next_addr** - Next booting stage address in coldboot HART scratch
|
||||||
|
space is the next address for the ROOT domain
|
||||||
|
* **next_arg1** - Next booting stage arg1 in coldboot HART scratch space
|
||||||
|
is the next arg1 for the ROOT domain
|
||||||
|
* **next_mode** - Next booting stage mode in coldboot HART scratch space
|
||||||
|
is the next mode for the ROOT domain
|
||||||
|
* **system_reset_allowed** - The ROOT domain is allowed to reset the system
|
||||||
|
|
||||||
|
Domain Effects
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Few noteworthy effects of a system partitioned into domains are as follows:
|
||||||
|
|
||||||
|
* At any point in time, a HART is running in exactly one OpenSBI domain context
|
||||||
|
* The SBI IPI and RFENCE calls from HART A are restricted to the HARTs in
|
||||||
|
domain assigned to HART A
|
||||||
|
* The SBI HSM calls which try to change/read state of HART B from HART A will
|
||||||
|
only work if both HART A and HART B are assigned same domain
|
||||||
|
* A HART running in S-mode or U-mode can only access memory based on the
|
||||||
|
memory regions of the domain assigned to the HART
|
||||||
|
|
||||||
|
Domain Device Tree Bindings
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
The OpenSBI domains can be described in the **device tree (DT) blob** (or
|
||||||
|
flattened device tree) passed to the OpenSBI firmwares by the previous
|
||||||
|
booting stage. This allows OpenSBI platform support to parse and populate
|
||||||
|
OpenSBI domains from the device tree blob (or flattened device tree).
|
||||||
|
|
||||||
|
### Domain Configuration Node
|
||||||
|
|
||||||
|
All OpenSBI domain description related DT nodes should be under the domain
|
||||||
|
configuration DT node. The **/chosen** DT node is the preferred parent of
|
||||||
|
the domain configuration DT node.
|
||||||
|
|
||||||
|
The DT properties of a domain configuration DT node are as follows:
|
||||||
|
|
||||||
|
* **compatible** (Mandatory) - The compatible string of the domain
|
||||||
|
configuration. This DT property should have value *"opensbi,domain,config"*
|
||||||
|
|
||||||
|
### Domain Memory Region Node
|
||||||
|
|
||||||
|
The domain memory region DT node describes details of a memory region and
|
||||||
|
can be pointed by multiple domain instance DT nodes. The access permissions
|
||||||
|
of the memory region are specified separately in domain instance node.
|
||||||
|
|
||||||
|
The DT properties of a domain memory region DT node are as follows:
|
||||||
|
|
||||||
|
* **compatible** (Mandatory) - The compatible string of the domain memory
|
||||||
|
region. This DT property should have value *"opensbi,domain,memregion"*
|
||||||
|
* **base** (Mandatory) - The base address of the domain memory region. This
|
||||||
|
DT property should have a **2 ^ order** aligned 64 bit address (i.e. two
|
||||||
|
DT cells).
|
||||||
|
* **order** (Mandatory) - The order of the domain memory region. This DT
|
||||||
|
property should have a 32 bit value (i.e. one DT cell) in the range
|
||||||
|
**3 <= order <= __riscv_xlen**.
|
||||||
|
* **mmio** (Optional) - A boolean flag representing whether the domain
|
||||||
|
memory region is a memory-mapped I/O (MMIO) region.
|
||||||
|
* **devices** (Optional) - The list of device DT node phandles for devices
|
||||||
|
which fall under this domain memory region.
|
||||||
|
|
||||||
|
### Domain Instance Node
|
||||||
|
|
||||||
|
The domain instance DT node describes set of possible HARTs, set of memory
|
||||||
|
regions, and other details of a domain instance.
|
||||||
|
|
||||||
|
The DT properties of a domain instance DT node are as follows:
|
||||||
|
|
||||||
|
* **compatible** (Mandatory) - The compatible string of the domain instance.
|
||||||
|
This DT property should have value *"opensbi,domain,instance"*
|
||||||
|
* **possible-harts** (Optional) - The list of CPU DT node phandles for the
|
||||||
|
the domain instance. This list represents the possible HARTs of the
|
||||||
|
domain instance.
|
||||||
|
* **regions** (Optional) - The list of domain memory region DT node phandle
|
||||||
|
and access permissions for the domain instance. Each list entry is a pair
|
||||||
|
of DT node phandle and access permissions. The access permissions are
|
||||||
|
represented as a 32bit bitmask having bits: **readable** (BIT[0]),
|
||||||
|
**writeable** (BIT[1]), **executable** (BIT[2]), and **m-mode** (BIT[3]).
|
||||||
|
* **boot-hart** (Optional) - The DT node phandle of the HART booting the
|
||||||
|
domain instance. If coldboot HART is assigned to the domain instance then
|
||||||
|
this DT property is ignored and the coldboot HART is assumed to be the
|
||||||
|
boot HART of the domain instance.
|
||||||
|
* **next-arg1** (Optional) - The 64 bit next booting stage arg1 for the
|
||||||
|
domain instance. If this DT property is not available and coldboot HART
|
||||||
|
is not assigned to the domain instance then **0x0** is used as default
|
||||||
|
value. If this DT property is not available and coldboot HART is assigned
|
||||||
|
to the domain instance then **next booting stage arg1 of coldboot HART**
|
||||||
|
is used as default value.
|
||||||
|
* **next-addr** (Optional) - The 64 bit next booting stage address for the
|
||||||
|
domain instance. If this DT property is not available and coldboot HART
|
||||||
|
is not assigned to the domain instance then **0x0** is used as default
|
||||||
|
value. If this DT property is not available and coldboot HART is assigned
|
||||||
|
to the domain instance then **next booting stage address of coldboot HART**
|
||||||
|
is used as default value.
|
||||||
|
* **next-mode** (Optional) - The 32 bit next booting stage mode for the
|
||||||
|
domain instance. The possible values of this DT property are: **0x1**
|
||||||
|
(s-mode), and **0x0** (u-mode). If this DT property is not available
|
||||||
|
and coldboot HART is not assigned to the domain instance then **0x1**
|
||||||
|
is used as default value. If this DT property is not available and
|
||||||
|
coldboot HART is assigned to the domain instance then **next booting
|
||||||
|
stage mode of coldboot HART** is used as default value.
|
||||||
|
* **system-reset-allowed** (Optional) - A boolean flag representing
|
||||||
|
whether the domain instance is allowed to do system reset.
|
||||||
|
|
||||||
|
### Assigning HART To Domain Instance
|
||||||
|
|
||||||
|
By default, all HARTs are assigned to **the ROOT domain**. The OpenSBI
|
||||||
|
platform support can provide the HART to domain instance assignment using
|
||||||
|
platform specific callback.
|
||||||
|
|
||||||
|
The HART to domain instance assignment can be parsed from the device tree
|
||||||
|
using optional DT property **opensbi,domain** in each CPU DT node. The
|
||||||
|
value of DT property **opensbi,domain** is the DT phandle of the domain
|
||||||
|
instance DT node. If **opensbi,domain** DT property is not specified then
|
||||||
|
corresponding HART is assigned to **the ROOT domain**.
|
||||||
|
|
||||||
|
### Domain Configuration Only Accessible to OpenSBI
|
||||||
|
|
||||||
|
The software running inside a domain instance should only be aware of
|
||||||
|
devices and hardware resources accessible to itself.
|
||||||
|
|
||||||
|
To hide domain configuration from domain instances, the following should
|
||||||
|
be done:
|
||||||
|
|
||||||
|
* The previous booting stage should preferably provide a separate device
|
||||||
|
tree for each domain instance and mention location of device tree in
|
||||||
|
respective domain instance DT nodes using **next-arg1** DT property.
|
||||||
|
* If domain assigned to a HART does not have separate device tree then
|
||||||
|
OpenSBI platform support should remove all domain configuration details
|
||||||
|
from the device tree passed by previous booting stage before passing it
|
||||||
|
to the next booting stage.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```
|
||||||
|
chosen {
|
||||||
|
opensbi-domains {
|
||||||
|
compatible = "opensbi,domain,config";
|
||||||
|
|
||||||
|
tmem: tmem {
|
||||||
|
compatible = "opensbi,domain,memregion";
|
||||||
|
base = <0x0 0x80100000>;
|
||||||
|
order = <20>;
|
||||||
|
};
|
||||||
|
|
||||||
|
tuart: tuart {
|
||||||
|
compatible = "opensbi,domain,memregion";
|
||||||
|
base = <0x0 0x10011000>;
|
||||||
|
order = <12>;
|
||||||
|
mmio;
|
||||||
|
devices = <&uart1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
allmem: allmem {
|
||||||
|
compatible = "opensbi,domain,memregion";
|
||||||
|
base = <0x0 0x0>;
|
||||||
|
order = <64>;
|
||||||
|
};
|
||||||
|
|
||||||
|
tdomain: trusted-domain {
|
||||||
|
compatible = "opensbi,domain,instance";
|
||||||
|
possible-harts = <&cpu0>;
|
||||||
|
regions = <&tmem 0x7>, <&tuart 0x7>;
|
||||||
|
boot-hart = <&cpu0>;
|
||||||
|
next-arg1 = <0x0 0x0>;
|
||||||
|
next-addr = <0x0 0x80100000>;
|
||||||
|
next-mode = <0x0>;
|
||||||
|
system-reset-allowed;
|
||||||
|
};
|
||||||
|
|
||||||
|
udomain: untrusted-domain {
|
||||||
|
compatible = "opensbi,domain,instance";
|
||||||
|
possible-harts = <&cpu1 &cpu2 &cpu3 &cpu4>;
|
||||||
|
regions = <&tmem 0x0>, <&tuart 0x0>, <&allmem 0x7>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cpus {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
timebase-frequency = <10000000>;
|
||||||
|
|
||||||
|
cpu0: cpu@0 {
|
||||||
|
device_type = "cpu";
|
||||||
|
reg = <0x00>;
|
||||||
|
compatible = "riscv";
|
||||||
|
opensbi-domain = <&tdomain>;
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
|
cpu1: cpu@1 {
|
||||||
|
device_type = "cpu";
|
||||||
|
reg = <0x01>;
|
||||||
|
compatible = "riscv";
|
||||||
|
opensbi-domain = <&udomain>;
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
|
cpu2: cpu@2 {
|
||||||
|
device_type = "cpu";
|
||||||
|
reg = <0x02>;
|
||||||
|
compatible = "riscv";
|
||||||
|
opensbi-domain = <&udomain>;
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
|
cpu3: cpu@3 {
|
||||||
|
device_type = "cpu";
|
||||||
|
reg = <0x03>;
|
||||||
|
compatible = "riscv";
|
||||||
|
opensbi-domain = <&udomain>;
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
|
cpu4: cpu@4 {
|
||||||
|
device_type = "cpu";
|
||||||
|
reg = <0x04>;
|
||||||
|
compatible = "riscv";
|
||||||
|
opensbi-domain = <&udomain>;
|
||||||
|
...
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
uart1: serial@10011000 {
|
||||||
|
...
|
||||||
|
};
|
||||||
|
```
|
@@ -793,7 +793,9 @@ WARN_LOGFILE =
|
|||||||
INPUT = @@SRC_DIR@@/README.md \
|
INPUT = @@SRC_DIR@@/README.md \
|
||||||
@@SRC_DIR@@/docs/contributing.md \
|
@@SRC_DIR@@/docs/contributing.md \
|
||||||
@@SRC_DIR@@/docs/platform_guide.md \
|
@@SRC_DIR@@/docs/platform_guide.md \
|
||||||
|
@@SRC_DIR@@/docs/platform_requirements.md \
|
||||||
@@SRC_DIR@@/docs/library_usage.md \
|
@@SRC_DIR@@/docs/library_usage.md \
|
||||||
|
@@SRC_DIR@@/docs/domain_support.md \
|
||||||
@@SRC_DIR@@/docs/firmware \
|
@@SRC_DIR@@/docs/firmware \
|
||||||
@@SRC_DIR@@/docs/platform \
|
@@SRC_DIR@@/docs/platform \
|
||||||
@@SRC_DIR@@/include \
|
@@SRC_DIR@@/include \
|
||||||
@@ -948,7 +950,7 @@ FILTER_SOURCE_PATTERNS =
|
|||||||
# (index.html). This can be useful if you have a project on for instance GitHub
|
# (index.html). This can be useful if you have a project on for instance GitHub
|
||||||
# and want to reuse the introduction page also for the doxygen output.
|
# and want to reuse the introduction page also for the doxygen output.
|
||||||
|
|
||||||
USE_MDFILE_AS_MAINPAGE =
|
USE_MDFILE_AS_MAINPAGE = README.md
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options related to source browsing
|
# Configuration options related to source browsing
|
||||||
@@ -1444,7 +1446,7 @@ DISABLE_INDEX = NO
|
|||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
GENERATE_TREEVIEW = NO
|
GENERATE_TREEVIEW = YES
|
||||||
|
|
||||||
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
|
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
|
||||||
# doxygen will group on one line in the generated HTML documentation.
|
# doxygen will group on one line in the generated HTML documentation.
|
||||||
|
14
docs/external/coreboot.md
vendored
14
docs/external/coreboot.md
vendored
@@ -1,7 +1,10 @@
|
|||||||
OpenSBI as coreboot payload
|
OpenSBI as coreboot payload
|
||||||
==============================
|
===========================
|
||||||
|
|
||||||
[coreboot](https://www.coreboot.org/) is a free/libre and open source firmware platform support multiple hardware architectures( x86, ARMv7, arm64, PowerPC64, MIPS and RISC-V) and diverse hardware models. In RISC-V world, coreboot currently support HiFive Unleashed with OpenSBI as a payload to boot GNU/Linux:
|
[coreboot] is a free/libre and open source firmware platform support multiple
|
||||||
|
hardware architectures(x86, ARMv7, arm64, PowerPC64, MIPS and RISC-V) and
|
||||||
|
diverse hardware models. In RISC-V world, coreboot currently support HiFive
|
||||||
|
Unleashed with OpenSBI as a payload to boot GNU/Linux:
|
||||||
|
|
||||||
```
|
```
|
||||||
SiFive HiFive unleashed's original firmware boot process:
|
SiFive HiFive unleashed's original firmware boot process:
|
||||||
@@ -21,4 +24,9 @@ coreboot boot process:
|
|||||||
+---------------------------------------------+-------------+-------+-+
|
+---------------------------------------------+-------------+-------+-+
|
||||||
```
|
```
|
||||||
|
|
||||||
The upstreaming work is still in progress. There's a [documentation](https://github.com/hardenedlinux/embedded-iot_profile/blob/master/docs/riscv/hifiveunleashed_coreboot_notes-en.md) about how to build [out-of-tree code](https://github.com/hardenedlinux/coreboot-HiFiveUnleashed) to load OpenSBI.
|
The upstreaming work is still in progress. There's a [documentation] about how
|
||||||
|
to build [out-of-tree code] to load OpenSBI.
|
||||||
|
|
||||||
|
[coreboot]: https://www.coreboot.org/
|
||||||
|
[documentation]: https://github.com/hardenedlinux/embedded-iot_profile/blob/master/docs/riscv/hifiveunleashed_coreboot_notes-en.md
|
||||||
|
[out-of-tree code]: https://github.com/hardenedlinux/coreboot-HiFiveUnleashed
|
||||||
|
@@ -51,11 +51,17 @@ case, a *FW_PAYLOAD* firmware allows embedding a flattened device tree in the
|
|||||||
Firmware Configuration and Compilation
|
Firmware Configuration and Compilation
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
All firmware types mandate the definition of the following compile time
|
All firmware types support the following common compile time configuration
|
||||||
configuration parameter.
|
parameters:
|
||||||
|
|
||||||
* **FW_TEXT_ADDR** - Defines the address at which the previous booting stage
|
* **FW_TEXT_ADDR** - Defines the execution address of the OpenSBI firmware.
|
||||||
loads OpenSBI firmware.
|
This configuration parameter is mandatory.
|
||||||
|
* **FW_FDT_PATH** - Path to an external flattened device tree binary file to
|
||||||
|
be embedded in the *.rodata* section of the final firmware. If this option
|
||||||
|
is not provided then the firmware will expect the FDT to be passed as an
|
||||||
|
argument by the prior booting stage.
|
||||||
|
* **FW_FDT_PADDING** - Optional zero bytes padding to the embedded flattened
|
||||||
|
device tree binary file specified by **FW_FDT_PATH** option.
|
||||||
|
|
||||||
Additionally, each firmware type as a set of type specific configuration
|
Additionally, each firmware type as a set of type specific configuration
|
||||||
parameters. Detailed information for each firmware type can be found in the
|
parameters. Detailed information for each firmware type can be found in the
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
OpenSBI Firmware with Dynamic Information *FW_DYNAMIC*
|
OpenSBI Firmware with Dynamic Information (FW_DYNAMIC)
|
||||||
======================================================
|
======================================================
|
||||||
|
|
||||||
OpenSBI **firmware with dynamic info (FW_DYNAMIC)** is a firmware which gets
|
OpenSBI **firmware with dynamic info (FW_DYNAMIC)** is a firmware which gets
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
OpenSBI Firmware with Jump Address *FW_JUMP*
|
OpenSBI Firmware with Jump Address (FW_JUMP)
|
||||||
============================================
|
============================================
|
||||||
|
|
||||||
OpenSBI **firmware with Jump Address (FW_JUMP)** is a firmware which only
|
OpenSBI **firmware with Jump Address (FW_JUMP)** is a firmware which only
|
||||||
@@ -38,15 +38,14 @@ follows:
|
|||||||
* **FW_JUMP_FDT_ADDR** - Address where the *flattened device tree (FDT file)*
|
* **FW_JUMP_FDT_ADDR** - Address where the *flattened device tree (FDT file)*
|
||||||
passed by the prior booting stage will be placed in memory before executing
|
passed by the prior booting stage will be placed in memory before executing
|
||||||
the booting stage following the OpenSBI firmware. If this option is not
|
the booting stage following the OpenSBI firmware. If this option is not
|
||||||
provided, then the OpenSBI firmware will pass zero as the FDT address to the
|
provided, then the OpenSBI firmware will pass the FDT address passed by the
|
||||||
following booting stage.
|
previous booting stage to the next booting stage.
|
||||||
|
|
||||||
*FW_JUMP* Example
|
*FW_JUMP* Example
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
The *[qemu/virt]* and *[qemu/sifive_u]* platforms illustrate how to configure
|
The *[qemu/virt]* platform illustrates how to configure and use a *FW_JUMP*
|
||||||
and use a *FW_JUMP* firmware. Detailed information regarding these platforms
|
firmware. Detailed information regarding these platforms can be found in the
|
||||||
can be found in the platform documentation files.
|
platform documentation files.
|
||||||
|
|
||||||
[qemu/virt]: ../platform/qemu_virt.md
|
[qemu/virt]: ../platform/qemu_virt.md
|
||||||
[qemu/sifive_u]: ../platform/qemu_sifive_u.md
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
OpenSBI Firmware with Payload *FW_PAYLOAD*
|
OpenSBI Firmware with Payload (FW_PAYLOAD)
|
||||||
==========================================
|
==========================================
|
||||||
|
|
||||||
OpenSBI **firmware with Payload (FW_PAYLOAD)** is a firmware which directly
|
OpenSBI **firmware with Payload (FW_PAYLOAD)** is a firmware which directly
|
||||||
@@ -55,35 +55,18 @@ file. The parameters currently defined are as follows:
|
|||||||
automatically generated and used as a payload. This test payload executes
|
automatically generated and used as a payload. This test payload executes
|
||||||
an infinite `while (1)` loop after printing a message on the platform console.
|
an infinite `while (1)` loop after printing a message on the platform console.
|
||||||
|
|
||||||
* **FW_PAYLOAD_FDT_PATH** - Path to an external flattened device tree binary
|
|
||||||
file to be embedded in the *.text* section of the final firmware. If this
|
|
||||||
option is not provided and no internal device tree file is specified by the
|
|
||||||
platform (c.f. *FW_PAYLOAD_FDT*), then the firmware will expect the FDT to
|
|
||||||
be passed as an argument by the prior booting stage.
|
|
||||||
|
|
||||||
* **FW_PAYLOAD_FDT** - Path to an internal flattened device tree binary file
|
|
||||||
defined by the platform code. The file name must match the DTB file name
|
|
||||||
specified in the platform *objects.mk* file with the *platform-dtb-y* entry.
|
|
||||||
This option results in *FW_PAYLOAD_FDT_PATH* to be automatically set.
|
|
||||||
Specifying *FW_PAYLOAD_FDT_PATH* on the `make` command line disables
|
|
||||||
*FW_PAYLOAD_FDT* and the command line specified device tree binary file is
|
|
||||||
used for building the final firmware.
|
|
||||||
|
|
||||||
* **FW_PAYLOAD_FDT_ADDR** - Address where the FDT passed by the prior booting
|
* **FW_PAYLOAD_FDT_ADDR** - Address where the FDT passed by the prior booting
|
||||||
stage or specified by the *FW_PAYLOAD_FDT_PATH* parameter and embedded in
|
stage or specified by the *FW_FDT_PATH* parameter and embedded in the
|
||||||
the *.text* section will be placed before executing the next booting stage,
|
*.rodata* section will be placed before executing the next booting stage,
|
||||||
that is, the payload firmware. If this option is not provided, then the
|
that is, the payload firmware. If this option is not provided, then the
|
||||||
firmware will pass zero as the FDT address to the next booting stage.
|
firmware will pass the FDT address passed by the previous booting stage
|
||||||
|
to the next booting stage.
|
||||||
|
|
||||||
*FW_PAYLOAD* Example
|
*FW_PAYLOAD* Example
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
The *[qemu/virt]* and *[qemu/sifive_u]* platforms illustrate how to configure
|
The *[qemu/virt]* platforms illustrate how to configure and use a *FW_PAYLOAD*
|
||||||
and use a *FW_PAYLOAD* firmware. Detailed information regarding these platforms
|
firmware. Detailed information regarding these platforms can be found in the
|
||||||
can be found in the platform documentation files.
|
platform documentation files.
|
||||||
|
|
||||||
The *kendryte/k210* platform also enables a build of a *FW_PAYLOAD* using an
|
|
||||||
internally defined device tree file (*FW_PAYLOAD_FDT*).
|
|
||||||
|
|
||||||
[qemu/virt]: ../platform/qemu_virt.md
|
[qemu/virt]: ../platform/qemu_virt.md
|
||||||
[qemu/sifive_u]: ../platform/qemu_sifive_u.md
|
|
||||||
|
@@ -7,4 +7,3 @@ provided as a payload to OpenSBI.
|
|||||||
|
|
||||||
Detailed examples can be found in both the [QEMU](../platform/qemu_virt.md)
|
Detailed examples can be found in both the [QEMU](../platform/qemu_virt.md)
|
||||||
and the [HiFive Unleashed](../platform/sifive_fu540.md) platform guides.
|
and the [HiFive Unleashed](../platform/sifive_fu540.md) platform guides.
|
||||||
|
|
||||||
|
@@ -7,34 +7,9 @@ environment. In the context of OpenSBI, U-Boot can be specified as a payload to
|
|||||||
the OpenSBI firmware, becoming the boot stage following the OpenSBI firmware
|
the OpenSBI firmware, becoming the boot stage following the OpenSBI firmware
|
||||||
execution.
|
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 a Linux kernel can also only execute on 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
|
Building and Generating U-Boot images
|
||||||
=====================================
|
=====================================
|
||||||
Please refer to the U-Boot build documentation for detailed instructions on
|
Please refer to the U-Boot build documentation for detailed instructions on
|
||||||
how to build U-Boot images.
|
how to build U-Boot image and boot high level operating systems from U-Boot
|
||||||
|
prompt.
|
||||||
|
|
||||||
Once U-Boot images are built, the Linux kernel image needs to be converted
|
|
||||||
into 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.
|
|
||||||
|
@@ -66,3 +66,24 @@ bootloader to service the following interrupts and traps:
|
|||||||
|
|
||||||
**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()*.
|
||||||
|
|
||||||
|
Definitions of OpenSBI Data Types for the External Firmware
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
OpenSBI can be built as library using external firmware build system such as EDK2
|
||||||
|
code base (The open source of UEFI firmware implementation) and linked with external
|
||||||
|
firmware drivers based on the external firmware architecture.
|
||||||
|
|
||||||
|
**OPENSBI_EXTERNAL_SBI_TYPES** identifier is introduced to *sbi_types.h* for selecting
|
||||||
|
external header file during the build preprocess in order to define OpensSBI data types
|
||||||
|
based on external firmware data type binding.
|
||||||
|
For example, *bool* is declared as *int* in sbi_types.h. However in EDK2 build system,
|
||||||
|
*bool* is declared as *BOOLEAN* which is defined as *unsigned char* data type.
|
||||||
|
|
||||||
|
External firmware can define **OPENSBI_EXTERNAL_SBI_TYPES** in CFLAGS and specify it to the
|
||||||
|
header file maintained in its code tree. However, the external build system has to address
|
||||||
|
the additional include directory for the external header file based on its own build system.
|
||||||
|
For example,
|
||||||
|
*-D***OPENSBI_EXTERNAL_SBI_TYPES***=OpensbiTypes.h*
|
||||||
|
Above tells *sbi_types.h* to refer to *OpensbiTypes.h* instead of using original definitions of
|
||||||
|
data types.
|
||||||
|
30
docs/platform/andes-ae350.md
Normal file
30
docs/platform/andes-ae350.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
Andes AE350 SoC Platform
|
||||||
|
========================
|
||||||
|
The AE350 AXI/AHB-based platform N25(F)/NX25(F)/D25F/A25/AX25 CPU with level-one
|
||||||
|
memories,interrupt controller, debug module, AXI and AHB Bus Matrix Controller,
|
||||||
|
AXI-to-AHB Bridge and a collection of fundamentalAHB/APB bus IP components
|
||||||
|
pre-integrated together as a system design.The high-quality and configurable
|
||||||
|
AHB/APB IPs suites a majority embedded systems, and the verified platform serves
|
||||||
|
as a starting point to jump start SoC designs.
|
||||||
|
|
||||||
|
To build platform specific library and firmwares, provide the
|
||||||
|
*PLATFORM=andes/ae350* parameter to the top level make command.
|
||||||
|
|
||||||
|
Platform Options
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The Andes AE350 platform does not have any platform-specific options.
|
||||||
|
|
||||||
|
Building Andes AE350 Platform
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
To use Linux v5.2 should be used to build Andes AE350 OpenSBI binaries by using
|
||||||
|
the compile time option FW_FDT_PATH.
|
||||||
|
|
||||||
|
AE350's dts is included in https://github.com/andestech/linux/tree/ast-v3_2_0-release-public
|
||||||
|
|
||||||
|
**Linux Kernel Payload**
|
||||||
|
|
||||||
|
```
|
||||||
|
make PLATFORM=andes/ae350 FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image FW_FDT_PATH=<ae350.dtb path>
|
||||||
|
```
|
@@ -1,9 +1,11 @@
|
|||||||
Ariane FPGA SoC Platform
|
Ariane FPGA SoC Platform
|
||||||
==========================
|
========================
|
||||||
Ariane is a 6-stage, single issue, in-order CPU which implements the 64-bit RISC-V instruction set.
|
Ariane is a 6-stage, single issue, in-order CPU which implements the 64-bit
|
||||||
The Ariane FPGA development platform is based on FPGA FPGA SoC(which currently supports only Genesys 2 board) and is capable
|
RISC-V instruction set. The Ariane FPGA development platform is based on FPGA
|
||||||
of running Linux.
|
SoC (which currently supports only Genesys 2 board) and is capable of running
|
||||||
The FPGA SoC currently contains the following peripherals:
|
Linux.
|
||||||
|
|
||||||
|
The FPGA SoC currently contains the following peripherals:
|
||||||
- DDR3 memory controller
|
- DDR3 memory controller
|
||||||
- SPI controller to conncet to an SDCard
|
- SPI controller to conncet to an SDCard
|
||||||
- Ethernet controller
|
- Ethernet controller
|
||||||
@@ -11,27 +13,26 @@ of running Linux.
|
|||||||
- Bootrom containing zero stage bootloader and device tree.
|
- Bootrom containing zero stage bootloader and device tree.
|
||||||
|
|
||||||
To build platform specific library and firmwares, provide the
|
To build platform specific library and firmwares, provide the
|
||||||
*PLATFORM=ariane-fpga* parameter to the top level `make` command.
|
*PLATFORM=fpga/ariane* parameter to the top level `make` command.
|
||||||
|
|
||||||
Platform Options
|
Platform Options
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
The *Ariane FPGA* platform does not have any platform-specific
|
The *Ariane FPGA* platform does not have any platform-specific options.
|
||||||
options.
|
|
||||||
|
|
||||||
Building Ariane FPGA Platform
|
Building Ariane FPGA Platform
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
**Linux Kernel Payload**
|
**Linux Kernel Payload**
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
make PLATFORM=ariane-fpga FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
make PLATFORM=fpga/ariane FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
||||||
```
|
```
|
||||||
|
|
||||||
Booting Ariane FPGA Platform
|
Booting Ariane FPGA Platform
|
||||||
-----------------------------
|
----------------------------
|
||||||
|
|
||||||
**Linux Kernel Payload**
|
**Linux Kernel Payload**
|
||||||
|
|
||||||
As Linux kernel image is embedded in the OpenSBI firmware binary, Ariane will directly
|
As Linux kernel image is embedded in the OpenSBI firmware binary, Ariane will
|
||||||
boot into Linux directly after powered on.
|
directly boot into Linux directly after powered on.
|
33
docs/platform/fpga-openpiton.md
Normal file
33
docs/platform/fpga-openpiton.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
OpenPiton FPGA SoC Platform
|
||||||
|
========================
|
||||||
|
OpenPiton is the world's first open source, general purpose, multithreaded
|
||||||
|
manycore processor. It is a tiled manycore framework scalable from one to
|
||||||
|
1/2 billion cores. Currently, OpenPiton supports the 64bit Ariane RISC-V
|
||||||
|
processor from ETH Zurich. To this end, Ariane has been equipped with a
|
||||||
|
different L1 cache subsystem that follows a write-through protocol and that has
|
||||||
|
support for cache invalidations and atomics.
|
||||||
|
|
||||||
|
To build platform specific library and firmwares, provide the
|
||||||
|
*PLATFORM=fpga/openpiton* parameter to the top level `make` command.
|
||||||
|
|
||||||
|
Platform Options
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The *OpenPiton* platform does not have any platform-specific options.
|
||||||
|
|
||||||
|
Building Ariane FPGA Platform
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
**Linux Kernel Payload**
|
||||||
|
|
||||||
|
```
|
||||||
|
make PLATFORM=fpga/openpiton FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
||||||
|
```
|
||||||
|
|
||||||
|
Booting Ariane FPGA Platform
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
**Linux Kernel Payload**
|
||||||
|
|
||||||
|
As Linux kernel image is embedded in the OpenSBI firmware binary, Ariane will
|
||||||
|
directly boot into Linux directly after powered on.
|
54
docs/platform/generic.md
Normal file
54
docs/platform/generic.md
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
Generic Platform
|
||||||
|
================
|
||||||
|
|
||||||
|
The **Generic** platform is a flattened device tree (FDT) based platform
|
||||||
|
where all platform specific functionality is provided based on FDT passed
|
||||||
|
by previous booting stage. The **Generic** platform allows us to use same
|
||||||
|
OpenSBI firmware binaries on various emulators, simulators, FPGAs, and
|
||||||
|
boards.
|
||||||
|
|
||||||
|
By default, the generic FDT platform makes following assumptions:
|
||||||
|
|
||||||
|
1. platform FW_TEXT_START is 0x80000000
|
||||||
|
2. platform features are default
|
||||||
|
3. platform stack size is default
|
||||||
|
4. platform has no quirks or work-arounds
|
||||||
|
|
||||||
|
The above assumptions (except 1) can be overridden by adding special platform
|
||||||
|
callbacks which will be called based on FDT root node compatible string.
|
||||||
|
|
||||||
|
Users of the generic FDT platform will have to ensure that:
|
||||||
|
|
||||||
|
1. Various FDT based drivers under lib/utils directory are upto date
|
||||||
|
based on their platform requirements
|
||||||
|
2. The FDT passed by previous booting stage has DT compatible strings and
|
||||||
|
DT properties in sync with the FDT based drivers under lib/utils directory
|
||||||
|
3. The FDT must have "stdout-path" DT property in the "/chosen" DT node when
|
||||||
|
a platform has multiple serial ports or consoles
|
||||||
|
4. On multi-HART platform, the FDT must have a DT node for IPI device and
|
||||||
|
lib/utils/ipi directory must have corresponding FDT based IPI driver
|
||||||
|
5. The FDT must have a DT node for timer device and lib/utils/timer directory
|
||||||
|
must have corresponding FDT based timer driver
|
||||||
|
|
||||||
|
To build the platform-specific library and firmware images, provide the
|
||||||
|
*PLATFORM=generic* parameter to the top level `make` command.
|
||||||
|
|
||||||
|
For custom FW_TEXT_START, we can build the platform-specific library and
|
||||||
|
firmware images by passing *PLATFORM=generic FW_TEXT_START=<custom_text_start>*
|
||||||
|
parameter to the top level `make` command.
|
||||||
|
|
||||||
|
Platform Options
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The *Generic* platform does not have any platform-specific options.
|
||||||
|
|
||||||
|
RISC-V Platforms Using Generic Platform
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
* **QEMU RISC-V Virt Machine** (*[qemu_virt.md]*)
|
||||||
|
* **Spike** (*[spike.md]*)
|
||||||
|
* **Shakti C-class SoC Platform** (*[shakti_cclass.md]*)
|
||||||
|
|
||||||
|
[qemu_virt.md]: qemu_virt.md
|
||||||
|
[spike.md]: spike.md
|
||||||
|
[shakti_cclass.md]: shakti_cclass.md
|
22
docs/platform/nuclei_ux600.md
Normal file
22
docs/platform/nuclei_ux600.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
Nuclei UX600 Platform
|
||||||
|
=====================
|
||||||
|
|
||||||
|
The **Nuclei UX600** is a 64-bit RISC-V Core which is capable of running Linux.
|
||||||
|
|
||||||
|
> Nuclei UX600: single core, pipeline as single-issue and 6~9 variable stages, in-order dispatch and out-of-order write-back, running up to >1.2GHz
|
||||||
|
|
||||||
|
To build the platform-specific library and firmware images, provide the
|
||||||
|
*PLATFORM=nuclei/ux600* parameter to the top level `make` command.
|
||||||
|
|
||||||
|
Platform Options
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The *Nuclei UX600* platform does not have any platform-specific options.
|
||||||
|
|
||||||
|
Building Nuclei UX600 Platform
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
```
|
||||||
|
make PLATFORM=nuclei/ux600 clean all
|
||||||
|
```
|
@@ -3,26 +3,44 @@ OpenSBI Supported Platforms
|
|||||||
|
|
||||||
OpenSBI currently supports the following virtual and hardware platforms:
|
OpenSBI currently supports the following virtual and hardware platforms:
|
||||||
|
|
||||||
|
* **Generic**: Flattened device tree (FDT) based platform where platform
|
||||||
|
specific functionality is provided based on the FDT passed by previous
|
||||||
|
booting stage. More details on this platform can be found in the file
|
||||||
|
*[generic.md]*.
|
||||||
|
|
||||||
* **QEMU RISC-V Virt Machine**: Platform support for the QEMU *virt* virtual
|
* **QEMU RISC-V Virt Machine**: Platform support for the QEMU *virt* virtual
|
||||||
RISC-V machine. This virtual machine is intended for RISC-V software
|
RISC-V machine. This virtual machine is intended for RISC-V software
|
||||||
development and tests. More details on this platform can be found in the
|
development and tests. More details on this platform can be found in the
|
||||||
file *[qemu_virt.md]*.
|
file *[qemu_virt.md]*.
|
||||||
|
|
||||||
* **QEMU SiFive Unleashed Machine**: Platform support for the *sifive_u* QEMU
|
|
||||||
virtual RISC-V machine. This is an emulation machine of the HiFive Unleashed
|
|
||||||
board by SiFive. More details on this platform can be found in the file
|
|
||||||
*[qemu_sifive_u.md]*.
|
|
||||||
|
|
||||||
* **SiFive FU540 SoC**: Platform support for SiFive FU540 SoC used on the
|
* **SiFive FU540 SoC**: Platform support for SiFive FU540 SoC used on the
|
||||||
HiFive Unleashed board. This platform is very similar to the *QEMU sifive_u*
|
HiFive Unleashed board, as well as the *sifive_u* QEMU virtual RISC-V
|
||||||
platform. More details on this platform can be found in the file
|
machine. More details on this platform can be found in the file
|
||||||
*[sifive_fu540.md]*.
|
*[sifive_fu540.md]*.
|
||||||
|
|
||||||
* **Kendryte K210 SoC**: Platform support for the Kendryte K210 SoC used on
|
* **Kendryte K210 SoC**: Platform support for the Kendryte K210 SoC used on
|
||||||
boards such as the Kendryte KD233 or the Sipeed MAIX Dock.
|
boards such as the Kendryte KD233 or the Sipeed MAIX Dock.
|
||||||
|
|
||||||
* **Ariane FPGA SoC**: Platform support for the Ariane FPGA SoC used on
|
* **Ariane FPGA SoC**: Platform support for the Ariane FPGA SoC used on
|
||||||
Genesys 2 board.
|
Genesys 2 board. More details on this platform can be found in the file
|
||||||
|
*[fpga-ariane.md]*.
|
||||||
|
|
||||||
|
* **Andes AE350 SoC**: Platform support for the Andes's SoC (AE350). More
|
||||||
|
details on this platform can be found in the file *[andes-ae350.md]*.
|
||||||
|
|
||||||
|
* **T-HEAD C910**: Platform support for the T-HEAD C910 Processor. More
|
||||||
|
details on this platform can be found in the file *[thead-c910.md]*.
|
||||||
|
|
||||||
|
* **Spike**: Platform support for the Spike emulator. More
|
||||||
|
details on this platform can be found in the file *[spike.md]*.
|
||||||
|
|
||||||
|
* **OpenPiton FPGA SoC**: Platform support OpenPiton research platform based
|
||||||
|
on ariane core. More details on this platform can be found in the file
|
||||||
|
*[fpga_openpiton.md]*.
|
||||||
|
|
||||||
|
* **Shakti C-class SoC Platform**: Platform support for Shakti C-class
|
||||||
|
processor based SOCs. More details on this platform can be found in the
|
||||||
|
file *[shakti_cclass.md]*.
|
||||||
|
|
||||||
The code for these supported platforms can be used as example to implement
|
The code for these supported platforms can be used as example to implement
|
||||||
support for other platforms. The *platform/template* directory also provides
|
support for other platforms. The *platform/template* directory also provides
|
||||||
@@ -30,7 +48,12 @@ template files for implementing support for a new platform. The *object.mk*,
|
|||||||
*config.mk* and *platform.c* template files provides enough comments to
|
*config.mk* and *platform.c* template files provides enough comments to
|
||||||
facilitate the implementation.
|
facilitate the implementation.
|
||||||
|
|
||||||
|
[generic.md]: generic.md
|
||||||
[qemu_virt.md]: qemu_virt.md
|
[qemu_virt.md]: qemu_virt.md
|
||||||
[qemu_sifive_u.md]: qemu_sifive_u.md
|
|
||||||
[sifive_fu540.md]: sifive_fu540.md
|
[sifive_fu540.md]: sifive_fu540.md
|
||||||
[ariane-fpga.md]: ariane-fpga.md
|
[fpga-ariane.md]: fpga-ariane.md
|
||||||
|
[andes-ae350.md]: andes-ae350.md
|
||||||
|
[thead-c910.md]: thead-c910.md
|
||||||
|
[spike.md]: spike.md
|
||||||
|
[fpga_openpiton.md]: fpga_openpiton.md
|
||||||
|
[shakti_cclass.md]: shakti_cclass.md
|
||||||
|
@@ -1,52 +0,0 @@
|
|||||||
QEMU SiFive Unleashed Machine Platform
|
|
||||||
======================================
|
|
||||||
|
|
||||||
The **QEMU SiFive Unleashed Machine** is an emulation of the SiFive Unleashed
|
|
||||||
platform.
|
|
||||||
|
|
||||||
To build this platform specific library and firmwares, provide the
|
|
||||||
*PLATFORM=qemu/sifive_u* parameter to the top level `make` command line.
|
|
||||||
|
|
||||||
Platform Options
|
|
||||||
----------------
|
|
||||||
|
|
||||||
The *QEMU SiFive Unleashed Machine* platform does not have any platform specific
|
|
||||||
options.
|
|
||||||
|
|
||||||
Executing on QEMU RISC-V 64bit
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
**No Payload Case**
|
|
||||||
|
|
||||||
Build:
|
|
||||||
```
|
|
||||||
make PLATFORM=qemu/sifive_u
|
|
||||||
```
|
|
||||||
|
|
||||||
Run:
|
|
||||||
```
|
|
||||||
qemu-system-riscv64 -M sifive_u -m 256M -display none -serial stdio \
|
|
||||||
-kernel build/platform/qemu/sifive_u/firmware/fw_payload.elf
|
|
||||||
```
|
|
||||||
|
|
||||||
**U-Boot as a Payload**
|
|
||||||
|
|
||||||
Note: the command line examples here assume that U-Boot was compiled using
|
|
||||||
the `sifive_fu540_defconfig` configuration.
|
|
||||||
|
|
||||||
Build:
|
|
||||||
```
|
|
||||||
make PLATFORM=qemu/sifive_u FW_PAYLOAD_PATH=<uboot_build_directory>/u-boot.bin
|
|
||||||
```
|
|
||||||
|
|
||||||
Run:
|
|
||||||
```
|
|
||||||
qemu-system-riscv64 -M sifive_u -m 256M -display none -serial stdio \
|
|
||||||
-kernel build/platform/qemu/sifive_u/firmware/fw_payload.elf
|
|
||||||
```
|
|
||||||
or
|
|
||||||
```
|
|
||||||
qemu-system-riscv64 -M sifive_u -m 256M -display none -serial stdio \
|
|
||||||
-kernel build/platform/qemu/sifive_u/firmware/fw_jump.elf \
|
|
||||||
-device loader,file=<uboot_build_directory>/u-boot.bin,addr=0x80200000
|
|
||||||
```
|
|
@@ -7,7 +7,7 @@ software development and testing. It is also referred to as
|
|||||||
storage, and other types of IO.
|
storage, and other types of IO.
|
||||||
|
|
||||||
To build the platform-specific library and firmware images, provide the
|
To build the platform-specific library and firmware images, provide the
|
||||||
*PLATFORM=qemu/virt* parameter to the top level `make` command.
|
*PLATFORM=generic* parameter to the top level `make` command.
|
||||||
|
|
||||||
Platform Options
|
Platform Options
|
||||||
----------------
|
----------------
|
||||||
@@ -15,20 +15,20 @@ Platform Options
|
|||||||
The *QEMU RISC-V Virt Machine* platform does not have any platform-specific
|
The *QEMU RISC-V Virt Machine* platform does not have any platform-specific
|
||||||
options.
|
options.
|
||||||
|
|
||||||
Execution on QEMU RISC-V 64bit
|
Execution on QEMU RISC-V 64-bit
|
||||||
------------------------------
|
-------------------------------
|
||||||
|
|
||||||
**No Payload Case**
|
**No Payload Case**
|
||||||
|
|
||||||
Build:
|
Build:
|
||||||
```
|
```
|
||||||
make PLATFORM=qemu/virt
|
make PLATFORM=generic
|
||||||
```
|
```
|
||||||
|
|
||||||
Run:
|
Run:
|
||||||
```
|
```
|
||||||
qemu-system-riscv64 -M virt -m 256M -nographic \
|
qemu-system-riscv64 -M virt -m 256M -nographic \
|
||||||
-kernel build/platform/qemu/virt/firmware/fw_payload.elf
|
-bios build/platform/generic/firmware/fw_payload.bin
|
||||||
```
|
```
|
||||||
|
|
||||||
**U-Boot Payload**
|
**U-Boot Payload**
|
||||||
@@ -38,19 +38,19 @@ the `qemu-riscv64_smode_defconfig` configuration.
|
|||||||
|
|
||||||
Build:
|
Build:
|
||||||
```
|
```
|
||||||
make PLATFORM=qemu/virt FW_PAYLOAD_PATH=<uboot_build_directory>/u-boot.bin
|
make PLATFORM=generic FW_PAYLOAD_PATH=<uboot_build_directory>/u-boot.bin
|
||||||
```
|
```
|
||||||
|
|
||||||
Run:
|
Run:
|
||||||
```
|
```
|
||||||
qemu-system-riscv64 -M virt -m 256M -nographic \
|
qemu-system-riscv64 -M virt -m 256M -nographic \
|
||||||
-kernel build/platform/qemu/virt/firmware/fw_payload.elf
|
-bios build/platform/generic/firmware/fw_payload.elf
|
||||||
```
|
```
|
||||||
or
|
or
|
||||||
```
|
```
|
||||||
qemu-system-riscv64 -M virt -m 256M -nographic \
|
qemu-system-riscv64 -M virt -m 256M -nographic \
|
||||||
-kernel build/platform/qemu/virt/firmware/fw_jump.elf \
|
-bios build/platform/generic/firmware/fw_jump.bin \
|
||||||
-device loader,file=<uboot_build_directory>/u-boot.bin,addr=0x80200000
|
-kernel <uboot_build_directory>/u-boot.bin
|
||||||
```
|
```
|
||||||
|
|
||||||
**Linux Kernel Payload**
|
**Linux Kernel Payload**
|
||||||
@@ -60,13 +60,13 @@ Note: We assume that the Linux kernel is compiled using
|
|||||||
|
|
||||||
Build:
|
Build:
|
||||||
```
|
```
|
||||||
make PLATFORM=qemu/virt FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
make PLATFORM=generic FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
||||||
```
|
```
|
||||||
|
|
||||||
Run:
|
Run:
|
||||||
```
|
```
|
||||||
qemu-system-riscv64 -M virt -m 256M -nographic \
|
qemu-system-riscv64 -M virt -m 256M -nographic \
|
||||||
-kernel build/platform/qemu/virt/firmware/fw_payload.elf \
|
-bios build/platform/generic/firmware/fw_payload.elf \
|
||||||
-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"
|
||||||
@@ -74,28 +74,28 @@ qemu-system-riscv64 -M virt -m 256M -nographic \
|
|||||||
or
|
or
|
||||||
```
|
```
|
||||||
qemu-system-riscv64 -M virt -m 256M -nographic \
|
qemu-system-riscv64 -M virt -m 256M -nographic \
|
||||||
-kernel build/platform/qemu/virt/firmware/fw_jump.elf \
|
-bios build/platform/generic/firmware/fw_jump.bin \
|
||||||
-device loader,file=<linux_build_directory>/arch/riscv/boot/Image,addr=0x80200000 \
|
-kernel <linux_build_directory>/arch/riscv/boot/Image \
|
||||||
-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"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Execution on QEMU RISC-V 32bit
|
Execution on QEMU RISC-V 32-bit
|
||||||
------------------------------
|
-------------------------------
|
||||||
|
|
||||||
**No Payload Case**
|
**No Payload Case**
|
||||||
|
|
||||||
Build:
|
Build:
|
||||||
```
|
```
|
||||||
make PLATFORM=qemu/virt
|
make PLATFORM=generic PLATFORM_RISCV_XLEN=32
|
||||||
```
|
```
|
||||||
|
|
||||||
Run:
|
Run:
|
||||||
```
|
```
|
||||||
qemu-system-riscv32 -M virt -m 256M -nographic \
|
qemu-system-riscv32 -M virt -m 256M -nographic \
|
||||||
-kernel build/platform/qemu/virt/firmware/fw_payload.elf
|
-bios build/platform/generic/firmware/fw_payload.bin
|
||||||
```
|
```
|
||||||
|
|
||||||
**U-Boot Payload**
|
**U-Boot Payload**
|
||||||
@@ -105,37 +105,35 @@ the `qemu-riscv32_smode_defconfig` configuration.
|
|||||||
|
|
||||||
Build:
|
Build:
|
||||||
```
|
```
|
||||||
make PLATFORM=qemu/virt FW_PAYLOAD_PATH=<uboot_build_directory>/u-boot.bin
|
make PLATFORM=generic PLATFORM_RISCV_XLEN=32 FW_PAYLOAD_PATH=<uboot_build_directory>/u-boot.bin
|
||||||
```
|
```
|
||||||
|
|
||||||
Run:
|
Run:
|
||||||
```
|
```
|
||||||
qemu-system-riscv32 -M virt -m 256M -nographic \
|
qemu-system-riscv32 -M virt -m 256M -nographic \
|
||||||
-kernel build/platform/qemu/virt/firmware/fw_payload.elf
|
-bios build/platform/generic/firmware/fw_payload.elf
|
||||||
```
|
```
|
||||||
or
|
or
|
||||||
```
|
```
|
||||||
qemu-system-riscv32 -M virt -m 256M -nographic \
|
qemu-system-riscv32 -M virt -m 256M -nographic \
|
||||||
-kernel build/platform/qemu/virt/firmware/fw_jump.elf \
|
-bios build/platform/generic/firmware/fw_jump.bin \
|
||||||
-device loader,file=<uboot_build_directory>/u-boot.bin,addr=0x80400000
|
-kernel <uboot_build_directory>/u-boot.bin
|
||||||
```
|
```
|
||||||
|
|
||||||
**Linux Kernel Payload**
|
**Linux Kernel Payload**
|
||||||
|
|
||||||
Note: We assume that the Linux kernel is compiled using
|
Note: We assume that the Linux kernel is compiled using
|
||||||
*arch/riscv/configs/rv32_defconfig* (kernel 5.1 and newer)
|
*arch/riscv/configs/rv32_defconfig*.
|
||||||
respectively using *arch/riscv/configs/defconfig* plus setting
|
|
||||||
CONFIG_ARCH_RV32I=y (kernel 5.0 and older).
|
|
||||||
|
|
||||||
Build:
|
Build:
|
||||||
```
|
```
|
||||||
make PLATFORM=qemu/virt FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
make PLATFORM=generic PLATFORM_RISCV_XLEN=32 FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
||||||
```
|
```
|
||||||
|
|
||||||
Run:
|
Run:
|
||||||
```
|
```
|
||||||
qemu-system-riscv32 -M virt -m 256M -nographic \
|
qemu-system-riscv32 -M virt -m 256M -nographic \
|
||||||
-kernel build/platform/qemu/virt/firmware/fw_payload.elf \
|
-bios build/platform/generic/firmware/fw_payload.elf \
|
||||||
-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"
|
||||||
@@ -143,10 +141,9 @@ qemu-system-riscv32 -M virt -m 256M -nographic \
|
|||||||
or
|
or
|
||||||
```
|
```
|
||||||
qemu-system-riscv32 -M virt -m 256M -nographic \
|
qemu-system-riscv32 -M virt -m 256M -nographic \
|
||||||
-kernel build/platform/qemu/virt/firmware/fw_jump.elf \
|
-bios build/platform/generic/firmware/fw_jump.bin \
|
||||||
-device loader,file=<linux_build_directory>/arch/riscv/boot/Image,addr=0x80400000 \
|
-kernel <linux_build_directory>/arch/riscv/boot/Image \
|
||||||
-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"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
33
docs/platform/shakti_cclass.md
Normal file
33
docs/platform/shakti_cclass.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
Shakti C-class SoC Platform
|
||||||
|
===========================
|
||||||
|
C-Class is a member of the SHAKTI family of processors from
|
||||||
|
Indian Institute of Technology - Madras (IIT-M).
|
||||||
|
|
||||||
|
It is an extremely configurable and commercial-grade 5-stage
|
||||||
|
in-order core supporting the standard RV64GCSUN ISA extensions.
|
||||||
|
|
||||||
|
For more details, refer:
|
||||||
|
* https://gitlab.com/shaktiproject/cores/c-class/blob/master/README.md
|
||||||
|
* https://c-class.readthedocs.io/en/latest
|
||||||
|
* https://shakti.org.in
|
||||||
|
|
||||||
|
Platform Options
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The *Shakti C-class SoC* platform does not have any platform-specific
|
||||||
|
options.
|
||||||
|
|
||||||
|
Building Shakti C-class Platform
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
**Linux Kernel Payload**
|
||||||
|
|
||||||
|
```
|
||||||
|
make PLATFORM=generic FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image FW_FDT_PATH=<shakti.dtb path>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Test Payload**
|
||||||
|
|
||||||
|
```
|
||||||
|
make PLATFORM=generic FW_FDT_PATH=<shakti.dtb path>
|
||||||
|
```
|
@@ -1,108 +1,60 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
With QEMU v4.2 or above release, the 'sifive_u' machine can be used to test
|
||||||
|
OpenSBI image built for the real hardware as well.
|
||||||
|
|
||||||
To build platform specific library and firmwares, provide the
|
To build platform specific library and firmwares, provide the
|
||||||
*PLATFORM=sifive/fu540* parameter to the top level `make` command.
|
*PLATFORM=sifive/fu540* parameter to the top level `make` command.
|
||||||
|
|
||||||
Platform Options
|
Platform Options
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
As hart0 in the FU540 doesn't have an MMU, only harts 1-4 boot by default.
|
The *SiFive FU540 SoC* platform does not have any platform-specific
|
||||||
A hart mask i.e. *FU540_ENABLED_HART_MASK* compile time option is provided
|
options.
|
||||||
to select any other hart for booting. Please keep in mind that this is not
|
|
||||||
a generic option and it can only be specified for FU540 platform in the
|
|
||||||
following way:
|
|
||||||
|
|
||||||
```
|
|
||||||
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=Image FU540_ENABLED_HART_MASK=0x02
|
|
||||||
```
|
|
||||||
This will let the board boot only hart1 instead of default 1-4.
|
|
||||||
|
|
||||||
Building SiFive Fu540 Platform
|
Building SiFive Fu540 Platform
|
||||||
-----------------------------
|
------------------------------
|
||||||
|
|
||||||
In order to boot SMP Linux in U-Boot, Linux v5.1 (or higher) and latest
|
In order to boot SMP Linux in U-Boot, Linux v5.1 (or higher) and latest
|
||||||
U-Boot v2019.04 (or higher) should be used.
|
U-Boot v2020.01 (or higher) should be used.
|
||||||
|
|
||||||
**Linux Kernel Payload**
|
**Linux Kernel Payload**
|
||||||
|
|
||||||
The HiFive Unleashed device tree(DT) is merged in Linux v5.2 release. This
|
The HiFive Unleashed device tree(DT) is merged in Linux v5.2 release. This
|
||||||
DT (device tree) is not backward compatible with the DT passed from FSBL.
|
DT (device tree) is not backward compatible with the DT passed from FSBL.
|
||||||
|
|
||||||
To use Linux v5.2 (or higher, the pre-built DTB (DT binary) from Linux v5.2
|
To use Linux v5.2 (or higher), the pre-built DTB (DT binary) from Linux v5.2
|
||||||
(or higher) should be used to build SiFive FU540 OpenSBI binaries by using
|
(or higher) should be used to build SiFive FU540 OpenSBI binaries by using
|
||||||
the compile time option *FW_PAYLOAD_FDT_PATH*.
|
the compile time option *FW_FDT_PATH*.
|
||||||
|
|
||||||
```
|
```
|
||||||
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
|
||||||
or
|
or
|
||||||
(For Linux v5.2 or higher)
|
(For Linux v5.2 or higher)
|
||||||
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image FW_PAYLOAD_FDT_PATH=<hifive-unleashed-a00.dtb path from Linux kernel>
|
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image FW_FDT_PATH=<hifive-unleashed-a00.dtb path from Linux kernel>
|
||||||
```
|
```
|
||||||
|
|
||||||
**U-Boot Payload**
|
**U-Boot Payload**
|
||||||
|
|
||||||
The command-line example here assumes that U-Boot was compiled using the
|
The command-line example here assumes that U-Boot was compiled using the
|
||||||
sifive_fu540_defconfig configuration and with U-Boot v2019.04 (or higher)
|
sifive_fu540_defconfig configuration and with U-Boot v2020.01, and up to
|
||||||
having SMP support.
|
v2020.07-rc3.
|
||||||
|
|
||||||
To use U-Boot which follows Linux v5.2 (or higher) DT bindings, we will
|
|
||||||
need custom U-Boot with required driver changes which can be found in
|
|
||||||
riscv_unleashed_mmc_spi_v2 branch of https://github.com/avpatel/u-boot.git
|
|
||||||
|
|
||||||
```
|
```
|
||||||
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<u-boot_build_dir>/u-boot.bin
|
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<u-boot_build_dir>/u-boot-dtb.bin
|
||||||
or
|
|
||||||
(For U-Boot which follows Linux v5.2 (or higher) DT bindings)
|
|
||||||
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<u-boot_build_dir>/u-boot.bin FW_PAYLOAD_FDT_PATH=<hifive-unleashed-a00.dtb path from Linux kernel>
|
|
||||||
```
|
|
||||||
|
|
||||||
Generate the uImage from Linux Image.
|
|
||||||
```
|
|
||||||
mkimage -A riscv -O linux -T kernel -C none -a 0x80200000 -e 0x80200000 -n Linux -d \
|
|
||||||
<linux_build_directory>/arch/riscv/boot/Image \
|
|
||||||
<linux_build_directory>/arch/riscv/boot/uImage
|
|
||||||
```
|
|
||||||
|
|
||||||
**U-Boot & Linux Kernel as a single payload**
|
|
||||||
|
|
||||||
A single monolithic image containing both U-Boot & Linux can also be used if
|
|
||||||
network boot setup is not available.
|
|
||||||
|
|
||||||
1. Generate the uImage from Linux Image.
|
|
||||||
```
|
|
||||||
mkimage -A riscv -O linux -T kernel -C none -a 0x80200000 -e 0x80200000 -n Linux -d \
|
|
||||||
<linux_build_directory>/arch/riscv/boot/Image \
|
|
||||||
<linux_build_directory>/arch/riscv/boot/uImage
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Create a temporary image with u-boot.bin as the first payload. The
|
|
||||||
command-line example here assumes that U-Boot was compiled using
|
|
||||||
sifive_fu540_defconfig configuration.
|
|
||||||
```
|
|
||||||
dd if=~/workspace/u-boot-riscv/u-boot.bin of=/tmp/temp.bin bs=1M
|
|
||||||
```
|
|
||||||
3. Append the Linux Kernel image generated in step 1.
|
|
||||||
```
|
|
||||||
dd if=<linux_build_directory>/arch/riscv/boot/uImage of=/tmp/temp.bin bs=1M seek=4
|
|
||||||
```
|
|
||||||
4. Compile OpenSBI with temp.bin (generated in step 3) as payload.
|
|
||||||
```
|
|
||||||
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=/tmp/temp.bin
|
|
||||||
or
|
|
||||||
(For U-Boot which follows Linux v5.2 (or higher) DT bindings)
|
|
||||||
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=/tmp/temp.bin FW_PAYLOAD_FDT_PATH=<hifive-unleashed-a00.dtb path from Linux kernel>
|
|
||||||
```
|
```
|
||||||
|
For U-Boot v2020.07-rc4 or later releases, SPL support was added in U-Boot.
|
||||||
|
Please refer to the detailed U-Boot booting guide available at [U-Boot].
|
||||||
|
|
||||||
Flashing the OpenSBI firmware binary to storage media:
|
Flashing the OpenSBI firmware binary to storage media:
|
||||||
-----------------------------------------------------
|
------------------------------------------------------
|
||||||
The first stage boot loader([FSBL](https://github.com/sifive/freedom-u540-c000-bootloader))
|
The first stage boot loader ([FSBL]) expects the storage media to have a GPT
|
||||||
expects the storage media to have a GPT partition table. It tries to look for
|
partition table. It tries to look for a partition with following GUID to load
|
||||||
a partition with following GUID to load the next stage boot loader (OpenSBI
|
the next stage boot loader (OpenSBI in this case).
|
||||||
in this case).
|
|
||||||
|
|
||||||
```
|
```
|
||||||
2E54B353-1271-4842-806F-E436D6AF6985
|
2E54B353-1271-4842-806F-E436D6AF6985
|
||||||
@@ -142,39 +94,32 @@ 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. U-Boot tftp boot method can be used to load kernel image in U-Boot
|
||||||
prompt. Here are the steps do a tftpboot.
|
prompt. Here are the steps do a tftpboot.
|
||||||
|
|
||||||
1. Set the mac address of the board.
|
1. Set the ip address of the board.
|
||||||
```
|
|
||||||
setenv ethaddr <mac address of the board>
|
|
||||||
```
|
|
||||||
(Note: This step is optional)
|
|
||||||
|
|
||||||
2. Set the ip address of the board.
|
|
||||||
```
|
```
|
||||||
setenv ipaddr <ipaddr of the board>
|
setenv ipaddr <ipaddr of the board>
|
||||||
```
|
```
|
||||||
|
2. Set the tftpboot server IP.
|
||||||
3. Set the tftpboot server IP.
|
|
||||||
```
|
```
|
||||||
setenv serverip <ipaddr of the tftp server>
|
setenv serverip <ipaddr of the tftp server>
|
||||||
```
|
```
|
||||||
|
3. Set the network gateway address.
|
||||||
4. Set the network gateway address.
|
|
||||||
```
|
```
|
||||||
setenv gatewayip <ipaddress of the network gateway>
|
setenv gatewayip <ipaddress of the network gateway>
|
||||||
```
|
```
|
||||||
|
4. Load the Linux kernel image from the tftp server.
|
||||||
5. Load the Linux kernel image from the tftp server.
|
|
||||||
```
|
```
|
||||||
tftpboot ${kernel_addr_r} <uImage path in tftpboot directory>
|
tftpboot ${kernel_addr_r} <Image path in tftpboot directory>
|
||||||
```
|
```
|
||||||
|
5. Load the ramdisk image from the tftp server. This is only required if
|
||||||
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
|
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.
|
already part of the kernel or loaded from an external storage by kernel.
|
||||||
```
|
```
|
||||||
tftpboot ${ramdisk_addr_r} <ramdisk path in tftpboot directory>
|
tftpboot ${ramdisk_addr_r} <ramdisk path in tftpboot directory>
|
||||||
```
|
```
|
||||||
|
6. Load the pre-compiled device tree via tftpboot.
|
||||||
|
```
|
||||||
|
tftpboot ${fdt_addr_r} <hifive-unleashed-a00.dtb path in tftpboot directory>
|
||||||
|
```
|
||||||
7. Set the boot command-line arguments.
|
7. Set the boot command-line arguments.
|
||||||
```
|
```
|
||||||
setenv bootargs "root=<root partition> rw console=ttySIF0 earlycon=sbi"
|
setenv bootargs "root=<root partition> rw console=ttySIF0 earlycon=sbi"
|
||||||
@@ -183,13 +128,12 @@ setenv bootargs "root=<root partition> rw console=ttySIF0 earlycon=sbi"
|
|||||||
** /dev/ram ** - If a ramdisk is used
|
** /dev/ram ** - If a ramdisk is used
|
||||||
** root=/dev/mmcblk0pX ** - If a rootfs is already on some other partition
|
** root=/dev/mmcblk0pX ** - If a rootfs is already on some other partition
|
||||||
of sdcard)
|
of sdcard)
|
||||||
|
|
||||||
8. Now boot into Linux.
|
8. Now boot into Linux.
|
||||||
```
|
```
|
||||||
bootm ${kernel_addr_r} ${ramdisk_addr_r} ${fdtcontroladdr}
|
booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}
|
||||||
or
|
or
|
||||||
(If ramdisk is not loaded from network)
|
(If ramdisk is not loaded from network)
|
||||||
bootm ${kernel_addr_r} - ${fdtcontroladdr}
|
booti ${kernel_addr_r} - ${fdt_addr_r}
|
||||||
```
|
```
|
||||||
|
|
||||||
**U-Boot & Linux Kernel as a single payload**
|
**U-Boot & Linux Kernel as a single payload**
|
||||||
@@ -197,5 +141,55 @@ bootm ${kernel_addr_r} - ${fdtcontroladdr}
|
|||||||
At U-Boot prompt execute the following boot command to boot Linux.
|
At U-Boot prompt execute the following boot command to boot Linux.
|
||||||
|
|
||||||
```
|
```
|
||||||
bootm ${kernel_addr_r} - ${fdtcontroladdr}
|
booti ${kernel_addr_r} - ${fdt_addr_r}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
QEMU Specific Instructions
|
||||||
|
--------------------------
|
||||||
|
If you want to test OpenSBI with QEMU 'sifive_u' machine, please follow the
|
||||||
|
same instructions above, with the exception of not passing FW_FDT_PATH.
|
||||||
|
|
||||||
|
This is because QEMU generates a device tree blob on the fly based on the
|
||||||
|
command line parameters and it's compatible with the one used in the upstream
|
||||||
|
Linux kernel.
|
||||||
|
|
||||||
|
When U-Boot v2020.01 (or higher) is used as the payload, as the SiFive FU540
|
||||||
|
DTB for the real hardware is embedded in U-Boot binary itself, due to the same
|
||||||
|
reason above, we need to switch the U-Boot sifive_fu540_defconfig configuration
|
||||||
|
from **CONFIG_OF_SEPARATE** to **CONFIG_OF_PRIOR_STAGE** so that U-Boot uses the
|
||||||
|
DTB generated by QEMU, and u-boot.bin should be used as the payload image, like:
|
||||||
|
|
||||||
|
```
|
||||||
|
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<u-boot_build_dir>/u-boot.bin
|
||||||
|
```
|
||||||
|
|
||||||
|
U-Boot v2020.07 release added SPL support to SiFive HiFive Unleashed board,
|
||||||
|
hence a build error will be seen after you switch to **CONFIG_OF_PRIOR_STAGE**.
|
||||||
|
|
||||||
|
```
|
||||||
|
./tools/mkimage: Can't open arch/riscv/dts/hifive-unleashed-a00.dtb: No such file or directory
|
||||||
|
./tools/mkimage: failed to build FIT
|
||||||
|
Makefile:1402: recipe for target 'u-boot.img' failed
|
||||||
|
make: *** [u-boot.img] Error 1
|
||||||
|
```
|
||||||
|
|
||||||
|
The above errors can be safely ignored as we don't run U-Boot SPL under QEMU.
|
||||||
|
|
||||||
|
Run:
|
||||||
|
```
|
||||||
|
qemu-system-riscv64 -M sifive_u -m 256M -nographic \
|
||||||
|
-bios build/platform/sifive/fu540/firmware/fw_payload.bin
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```
|
||||||
|
qemu-system-riscv64 -M sifive_u -m 256M -nographic \
|
||||||
|
-bios build/platform/sifive/fu540/firmware/fw_jump.bin \
|
||||||
|
-kernel <uboot_build_dir>/u-boot.bin
|
||||||
|
```
|
||||||
|
|
||||||
|
While the real hardware operates at the 64-bit mode, it's possible for QEMU to
|
||||||
|
test the 32-bit OpenSBI firmware. This can be helpful for testing 32-bit SiFive
|
||||||
|
specific drivers.
|
||||||
|
|
||||||
|
[U-Boot]: https://gitlab.denx.de/u-boot/u-boot/blob/master/doc/board/sifive/fu540.rst
|
||||||
|
[FSBL]: https://github.com/sifive/freedom-u540-c000-bootloader
|
||||||
|
89
docs/platform/spike.md
Normal file
89
docs/platform/spike.md
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
Spike Simulator Platform
|
||||||
|
========================
|
||||||
|
|
||||||
|
The **Spike** is a RISC-V ISA simulator which implements a functional model
|
||||||
|
of one or more RISC-V harts. The **Spike** compatible virtual platform is
|
||||||
|
also available on QEMU. In fact, we can use same OpenSBI firmware binaries
|
||||||
|
on **Spike** simulator and QEMU Spike machine.
|
||||||
|
|
||||||
|
For more details, refer [Spike on GitHub](https://github.com/riscv/riscv-isa-sim)
|
||||||
|
|
||||||
|
To build the platform-specific library and firmware images, provide the
|
||||||
|
*PLATFORM=generic* parameter to the top level `make` command.
|
||||||
|
|
||||||
|
Platform Options
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The *Spike* platform does not have any platform-specific options.
|
||||||
|
|
||||||
|
Execution on Spike Simulator
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
**No Payload Case**
|
||||||
|
|
||||||
|
Build:
|
||||||
|
```
|
||||||
|
make PLATFORM=generic
|
||||||
|
```
|
||||||
|
|
||||||
|
Run:
|
||||||
|
```
|
||||||
|
spike build/platform/generic/firmware/fw_payload.elf
|
||||||
|
```
|
||||||
|
|
||||||
|
**Linux Kernel Payload**
|
||||||
|
|
||||||
|
Note: We assume that the Linux kernel is compiled using
|
||||||
|
*arch/riscv/configs/defconfig*.
|
||||||
|
|
||||||
|
Build:
|
||||||
|
```
|
||||||
|
make PLATFORM=generic FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
||||||
|
```
|
||||||
|
|
||||||
|
Run:
|
||||||
|
```
|
||||||
|
spike --initrd <path_to_cpio_ramdisk> build/platform/generic/firmware/fw_payload.elf
|
||||||
|
```
|
||||||
|
|
||||||
|
Execution on QEMU RISC-V 64-bit
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
**No Payload Case**
|
||||||
|
|
||||||
|
Build:
|
||||||
|
```
|
||||||
|
make PLATFORM=generic
|
||||||
|
```
|
||||||
|
|
||||||
|
Run:
|
||||||
|
```
|
||||||
|
qemu-system-riscv64 -M spike -m 256M -nographic \
|
||||||
|
-bios build/platform/generic/firmware/fw_payload.elf
|
||||||
|
```
|
||||||
|
|
||||||
|
**Linux Kernel Payload**
|
||||||
|
|
||||||
|
Note: We assume that the Linux kernel is compiled using
|
||||||
|
*arch/riscv/configs/defconfig*.
|
||||||
|
|
||||||
|
Build:
|
||||||
|
```
|
||||||
|
make PLATFORM=generic FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image
|
||||||
|
```
|
||||||
|
|
||||||
|
Run:
|
||||||
|
```
|
||||||
|
qemu-system-riscv64 -M spike -m 256M -nographic \
|
||||||
|
-bios build/platform/generic/firmware/fw_payload.elf \
|
||||||
|
-initrd <path_to_cpio_ramdisk> \
|
||||||
|
-append "root=/dev/ram rw console=hvc0 earlycon=sbi"
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```
|
||||||
|
qemu-system-riscv64 -M spike -m 256M -nographic \
|
||||||
|
-bios build/platform/generic/firmware/fw_jump.elf \
|
||||||
|
-kernel <linux_build_directory>/arch/riscv/boot/Image \
|
||||||
|
-initrd <path_to_cpio_ramdisk> \
|
||||||
|
-append "root=/dev/ram rw console=hvc0 earlycon=sbi"
|
||||||
|
```
|
34
docs/platform/thead-c910.md
Normal file
34
docs/platform/thead-c910.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
T-HEAD C910 Processor
|
||||||
|
=====================
|
||||||
|
C910 is a 12-stage, 3 issues, 8 executions, out-of-order 64-bit RISC-V CPU which
|
||||||
|
supports 16 cores, runs with 2.5GHz, and is capable of running Linux.
|
||||||
|
|
||||||
|
To build platform specific library and firmwares, provide the
|
||||||
|
*PLATFORM=thead/c910* parameter to the top level make command.
|
||||||
|
|
||||||
|
Platform Options
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The *T-HEAD C910* platform does not have any platform-specific options.
|
||||||
|
|
||||||
|
Building T-HEAD C910 Platform
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
```
|
||||||
|
make PLATFORM=thead/c910
|
||||||
|
```
|
||||||
|
|
||||||
|
Booting T-HEAD C910 Platform
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
**No Payload**
|
||||||
|
|
||||||
|
As there's no payload, you may download vmlinux or u-boot to FW_JUMP_ADDR which
|
||||||
|
specified in config.mk or compile commands with GDB. And the execution flow will
|
||||||
|
turn to vmlinux or u-boot when opensbi ends.
|
||||||
|
|
||||||
|
**Linux Kernel Payload**
|
||||||
|
|
||||||
|
You can also choose to use Linux kernel as payload by enabling FW_PAYLOAD=y
|
||||||
|
along with specifying FW_PAYLOAD_OFFSET. The kernel image will be embedded in
|
||||||
|
the OPENSBI firmware binary, T-head will directly boot into Linux after OpenSBI.
|
44
docs/platform_requirements.md
Normal file
44
docs/platform_requirements.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
OpenSBI Platform Requirements
|
||||||
|
=============================
|
||||||
|
|
||||||
|
The RISC-V platform requirements for OpenSBI can change over time
|
||||||
|
with advances in RISC-V specifications and ecosystem.
|
||||||
|
|
||||||
|
To handle this, we have two types of RISC-V platform requirements:
|
||||||
|
|
||||||
|
1. **Base platform requirements** which apply to all OpenSBI releases
|
||||||
|
2. **Release specific platform requirements** which apply to a OpenSBI
|
||||||
|
release and later releases
|
||||||
|
|
||||||
|
Currently, we don't have any **Release specific platform requirements**
|
||||||
|
but such platform requirements will be added in future.
|
||||||
|
|
||||||
|
Base Platform Requirements
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
The base RISC-V platform requirements for OpenSBI are as follows:
|
||||||
|
|
||||||
|
1. At least rv32ima or rv64ima required on all HARTs
|
||||||
|
2. At least one HART should have S-mode support because:
|
||||||
|
|
||||||
|
* SBI calls are meant for RISC-V S-mode (Supervisor mode)
|
||||||
|
* OpenSBI implements SBI calls for S-mode software
|
||||||
|
|
||||||
|
3. The MTVEC CSR on all HARTs must support direct mode
|
||||||
|
4. The PMP CSRs are optional. If PMP CSRs are not implemented then
|
||||||
|
OpenSBI cannot protect M-mode firmware and secured memory regions
|
||||||
|
5. The TIME CSR is optional. If TIME CSR is not implemented in
|
||||||
|
hardware then a 64-bit MMIO counter is required to track time
|
||||||
|
and emulate TIME CSR
|
||||||
|
6. Hardware support for injecting M-mode software interrupts on
|
||||||
|
a multi-HART platform
|
||||||
|
|
||||||
|
The RISC-V extensions not covered by rv32ima or rv64ima are optional
|
||||||
|
for OpenSBI. Although, OpenSBI will detect and handle some of these
|
||||||
|
optional RISC-V extensions at runtime.
|
||||||
|
|
||||||
|
The optional RISC-V extensions handled by OpenSBI at runtime are:
|
||||||
|
|
||||||
|
* D-extension: Double precision floating point
|
||||||
|
* F-extension: Single precision floating point
|
||||||
|
* H-extension: Hypervisor
|
@@ -7,5 +7,8 @@
|
|||||||
# Anup Patel <anup.patel@wdc.com>
|
# Anup Patel <anup.patel@wdc.com>
|
||||||
#
|
#
|
||||||
|
|
||||||
|
$(platform_build_dir)/firmware/fw_dynamic.o: $(FW_FDT_PATH)
|
||||||
|
$(platform_build_dir)/firmware/fw_jump.o: $(FW_FDT_PATH)
|
||||||
|
$(platform_build_dir)/firmware/fw_payload.o: $(FW_FDT_PATH)
|
||||||
|
|
||||||
$(platform_build_dir)/firmware/fw_payload.o: $(FW_PAYLOAD_PATH_FINAL)
|
$(platform_build_dir)/firmware/fw_payload.o: $(FW_PAYLOAD_PATH_FINAL)
|
||||||
$(platform_build_dir)/firmware/fw_payload.o: $(FW_PAYLOAD_FDT_PATH)
|
|
||||||
|
@@ -13,6 +13,9 @@
|
|||||||
#include <sbi/sbi_scratch.h>
|
#include <sbi/sbi_scratch.h>
|
||||||
#include <sbi/sbi_trap.h>
|
#include <sbi/sbi_trap.h>
|
||||||
|
|
||||||
|
#define BOOT_STATUS_RELOCATE_DONE 1
|
||||||
|
#define BOOT_STATUS_BOOT_HART_DONE 2
|
||||||
|
|
||||||
.macro MOV_3R __d0, __s0, __d1, __s1, __d2, __s2
|
.macro MOV_3R __d0, __s0, __d1, __s1, __d2, __s2
|
||||||
add \__d0, \__s0, zero
|
add \__d0, \__s0, zero
|
||||||
add \__d1, \__s1, zero
|
add \__d1, \__s1, zero
|
||||||
@@ -38,17 +41,26 @@
|
|||||||
999:
|
999:
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.globl _start
|
.globl _start
|
||||||
.globl _start_warm
|
.globl _start_warm
|
||||||
_start:
|
_start:
|
||||||
/*
|
/* Find preferred boot HART id */
|
||||||
* Jump to warm-boot if this is not the first core booting,
|
MOV_3R s0, a0, s1, a1, s2, a2
|
||||||
* that is, for mhartid != 0
|
call fw_boot_hart
|
||||||
*/
|
add a6, a0, zero
|
||||||
csrr a6, CSR_MHARTID
|
MOV_3R a0, s0, a1, s1, a2, s2
|
||||||
blt zero, a6, _wait_relocate_copy_done
|
li a7, -1
|
||||||
|
beq a6, a7, _try_lottery
|
||||||
|
/* Jump to relocation wait loop if we are not boot hart */
|
||||||
|
bne a0, a6, _wait_relocate_copy_done
|
||||||
|
_try_lottery:
|
||||||
|
/* Jump to relocation wait loop if we don't get relocation lottery */
|
||||||
|
la a6, _relocate_lottery
|
||||||
|
li a7, 1
|
||||||
|
amoadd.w a6, a7, (a6)
|
||||||
|
bnez a6, _wait_relocate_copy_done
|
||||||
|
|
||||||
/* Save load address */
|
/* Save load address */
|
||||||
la t0, _load_start
|
la t0, _load_start
|
||||||
@@ -72,6 +84,8 @@ _relocate:
|
|||||||
blt t2, t0, _relocate_copy_to_upper
|
blt t2, t0, _relocate_copy_to_upper
|
||||||
_relocate_copy_to_lower:
|
_relocate_copy_to_lower:
|
||||||
ble t1, t2, _relocate_copy_to_lower_loop
|
ble t1, t2, _relocate_copy_to_lower_loop
|
||||||
|
la t3, _relocate_lottery
|
||||||
|
BRANGE t2, t1, t3, _start_hang
|
||||||
la t3, _boot_status
|
la t3, _boot_status
|
||||||
BRANGE t2, t1, t3, _start_hang
|
BRANGE t2, t1, t3, _start_hang
|
||||||
la t3, _relocate
|
la t3, _relocate
|
||||||
@@ -88,6 +102,8 @@ _relocate_copy_to_lower_loop:
|
|||||||
jr t4
|
jr t4
|
||||||
_relocate_copy_to_upper:
|
_relocate_copy_to_upper:
|
||||||
ble t3, t0, _relocate_copy_to_upper_loop
|
ble t3, t0, _relocate_copy_to_upper_loop
|
||||||
|
la t2, _relocate_lottery
|
||||||
|
BRANGE t0, t3, t2, _start_hang
|
||||||
la t2, _boot_status
|
la t2, _boot_status
|
||||||
BRANGE t0, t3, t2, _start_hang
|
BRANGE t0, t3, t2, _start_hang
|
||||||
la t2, _relocate
|
la t2, _relocate
|
||||||
@@ -108,26 +124,33 @@ _wait_relocate_copy_done:
|
|||||||
REG_L t1, 0(t1)
|
REG_L t1, 0(t1)
|
||||||
beq t0, t1, _wait_for_boot_hart
|
beq t0, t1, _wait_for_boot_hart
|
||||||
la t2, _boot_status
|
la t2, _boot_status
|
||||||
sub t2, t2, t0
|
|
||||||
add t2, t2, t1
|
|
||||||
la t3, _wait_for_boot_hart
|
la t3, _wait_for_boot_hart
|
||||||
sub t3, t3, t0
|
sub t3, t3, t0
|
||||||
add t3, t3, t1
|
add t3, t3, t1
|
||||||
1:
|
1:
|
||||||
/* waitting for relocate copy done (_boot_status == 1) */
|
/* waitting for relocate copy done (_boot_status == 1) */
|
||||||
li t4, 1
|
li t4, BOOT_STATUS_RELOCATE_DONE
|
||||||
REG_L t5, 0(t2)
|
REG_L t5, 0(t2)
|
||||||
/* Reduce the bus traffic so that boot hart may proceed faster */
|
/* Reduce the bus traffic so that boot hart may proceed faster */
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
bne t4, t5, 1b
|
bgt t4, t5, 1b
|
||||||
jr t3
|
jr t3
|
||||||
_relocate_done:
|
_relocate_done:
|
||||||
|
|
||||||
/* mark relocate copy done */
|
/*
|
||||||
|
* Mark relocate copy done
|
||||||
|
* Use _boot_status copy relative to the load address
|
||||||
|
*/
|
||||||
la t0, _boot_status
|
la t0, _boot_status
|
||||||
li t1, 1
|
la t1, _link_start
|
||||||
|
REG_L t1, 0(t1)
|
||||||
|
la t2, _load_start
|
||||||
|
REG_L t2, 0(t2)
|
||||||
|
sub t0, t0, t1
|
||||||
|
add t0, t0, t2
|
||||||
|
li t1, BOOT_STATUS_RELOCATE_DONE
|
||||||
REG_S t1, 0(t0)
|
REG_S t1, 0(t0)
|
||||||
fence rw, rw
|
fence rw, rw
|
||||||
|
|
||||||
@@ -137,11 +160,44 @@ _relocate_done:
|
|||||||
li ra, 0
|
li ra, 0
|
||||||
call _reset_regs
|
call _reset_regs
|
||||||
|
|
||||||
|
/* Zero-out BSS */
|
||||||
|
la s4, _bss_start
|
||||||
|
la s5, _bss_end
|
||||||
|
_bss_zero:
|
||||||
|
REG_S zero, (s4)
|
||||||
|
add s4, s4, __SIZEOF_POINTER__
|
||||||
|
blt s4, s5, _bss_zero
|
||||||
|
|
||||||
|
/* Setup temporary trap handler */
|
||||||
|
la s4, _start_hang
|
||||||
|
csrw CSR_MTVEC, s4
|
||||||
|
|
||||||
|
/* Setup temporary stack */
|
||||||
|
la s4, _fw_end
|
||||||
|
li s5, (SBI_SCRATCH_SIZE * 2)
|
||||||
|
add sp, s4, s5
|
||||||
|
|
||||||
/* Allow main firmware to save info */
|
/* Allow main firmware to save info */
|
||||||
MOV_5R s0, a0, s1, a1, s2, a2, s3, a3, s4, a4
|
MOV_5R s0, a0, s1, a1, s2, a2, s3, a3, s4, a4
|
||||||
call fw_save_info
|
call fw_save_info
|
||||||
MOV_5R a0, s0, a1, s1, a2, s2, a3, s3, a4, s4
|
MOV_5R a0, s0, a1, s1, a2, s2, a3, s3, a4, s4
|
||||||
|
|
||||||
|
#ifdef FW_FDT_PATH
|
||||||
|
/* Override previous arg1 */
|
||||||
|
la a1, fw_fdt_bin
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize platform
|
||||||
|
* Note: The a0 to a4 registers passed to the
|
||||||
|
* firmware are parameters to this function.
|
||||||
|
*/
|
||||||
|
MOV_5R s0, a0, s1, a1, s2, a2, s3, a3, s4, a4
|
||||||
|
call fw_platform_init
|
||||||
|
add t0, a0, zero
|
||||||
|
MOV_5R a0, s0, a1, s1, a2, s2, a3, s3, a4, s4
|
||||||
|
add a1, t0, zero
|
||||||
|
|
||||||
/* Preload HART details
|
/* Preload HART details
|
||||||
* s7 -> HART Count
|
* s7 -> HART Count
|
||||||
* s8 -> HART Stack Size
|
* s8 -> HART Stack Size
|
||||||
@@ -205,40 +261,24 @@ _scratch_init:
|
|||||||
/* Store hartid-to-scratch function address in scratch space */
|
/* Store hartid-to-scratch function address in scratch space */
|
||||||
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)
|
||||||
|
/* Store trap-exit function address in scratch space */
|
||||||
|
la a4, _trap_exit
|
||||||
|
REG_S a4, SBI_SCRATCH_TRAP_EXIT_OFFSET(tp)
|
||||||
/* Clear tmp0 in scratch space */
|
/* Clear tmp0 in scratch space */
|
||||||
REG_S zero, SBI_SCRATCH_TMP0_OFFSET(tp)
|
REG_S zero, SBI_SCRATCH_TMP0_OFFSET(tp)
|
||||||
/* Store firmware options in scratch space */
|
/* Store firmware options in scratch space */
|
||||||
MOV_3R s0, a0, s1, a1, s2, a2
|
MOV_3R s0, a0, s1, a1, s2, a2
|
||||||
#ifdef FW_OPTIONS
|
#ifdef FW_OPTIONS
|
||||||
li a4, FW_OPTIONS
|
li a0, FW_OPTIONS
|
||||||
#else
|
#else
|
||||||
add a4, zero, zero
|
|
||||||
#endif
|
|
||||||
call fw_options
|
call fw_options
|
||||||
or a4, a4, a0
|
#endif
|
||||||
REG_S a4, SBI_SCRATCH_OPTIONS_OFFSET(tp)
|
REG_S a0, SBI_SCRATCH_OPTIONS_OFFSET(tp)
|
||||||
MOV_3R a0, s0, a1, s1, a2, s2
|
MOV_3R a0, s0, a1, s1, a2, s2
|
||||||
/* Move to next scratch space */
|
/* Move to next scratch space */
|
||||||
add t1, t1, t2
|
add t1, t1, t2
|
||||||
blt t1, s7, _scratch_init
|
blt t1, s7, _scratch_init
|
||||||
|
|
||||||
/* Zero-out BSS */
|
|
||||||
la a4, _bss_start
|
|
||||||
la a5, _bss_end
|
|
||||||
_bss_zero:
|
|
||||||
REG_S zero, (a4)
|
|
||||||
add a4, a4, __SIZEOF_POINTER__
|
|
||||||
blt a4, a5, _bss_zero
|
|
||||||
|
|
||||||
/* Override pervious arg1 */
|
|
||||||
MOV_3R s0, a0, s1, a1, s2, a2
|
|
||||||
call fw_prev_arg1
|
|
||||||
add t1, a0, zero
|
|
||||||
MOV_3R a0, s0, a1, s1, a2, s2
|
|
||||||
beqz t1, _prev_arg1_override_done
|
|
||||||
add a1, t1, zero
|
|
||||||
_prev_arg1_override_done:
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Relocate Flatened Device Tree (FDT)
|
* Relocate Flatened Device Tree (FDT)
|
||||||
* source FDT address = previous arg1
|
* source FDT address = previous arg1
|
||||||
@@ -302,15 +342,15 @@ _fdt_reloc_again:
|
|||||||
_fdt_reloc_done:
|
_fdt_reloc_done:
|
||||||
|
|
||||||
/* mark boot hart done */
|
/* mark boot hart done */
|
||||||
li t0, 2
|
li t0, BOOT_STATUS_BOOT_HART_DONE
|
||||||
la t1, _boot_status
|
la t1, _boot_status
|
||||||
REG_S t0, 0(t1)
|
REG_S t0, 0(t1)
|
||||||
fence rw, rw
|
fence rw, rw
|
||||||
j _start_warm
|
j _start_warm
|
||||||
|
|
||||||
/* waitting for boot hart done (_boot_status == 2) */
|
/* waiting for boot hart to be done (_boot_status == 2) */
|
||||||
_wait_for_boot_hart:
|
_wait_for_boot_hart:
|
||||||
li t0, 2
|
li t0, BOOT_STATUS_BOOT_HART_DONE
|
||||||
la t1, _boot_status
|
la t1, _boot_status
|
||||||
REG_L t1, 0(t1)
|
REG_L t1, 0(t1)
|
||||||
/* Reduce the bus traffic so that boot hart may proceed faster */
|
/* Reduce the bus traffic so that boot hart may proceed faster */
|
||||||
@@ -328,6 +368,7 @@ _start_warm:
|
|||||||
csrw CSR_MIE, zero
|
csrw CSR_MIE, zero
|
||||||
csrw CSR_MIP, zero
|
csrw CSR_MIP, zero
|
||||||
|
|
||||||
|
/* Find HART count and HART stack size */
|
||||||
la a4, platform
|
la a4, platform
|
||||||
#if __riscv_xlen == 64
|
#if __riscv_xlen == 64
|
||||||
lwu s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
|
lwu s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
|
||||||
@@ -336,12 +377,29 @@ _start_warm:
|
|||||||
lw s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
|
lw s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
|
||||||
lw s8, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(a4)
|
lw s8, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(a4)
|
||||||
#endif
|
#endif
|
||||||
|
REG_L s9, SBI_PLATFORM_HART_INDEX2ID_OFFSET(a4)
|
||||||
|
|
||||||
/* HART ID should be within expected limit */
|
/* Find HART id */
|
||||||
csrr s6, CSR_MHARTID
|
csrr s6, CSR_MHARTID
|
||||||
bge s6, s7, _start_hang
|
|
||||||
|
|
||||||
/* find the scratch space for this hart */
|
/* Find HART index */
|
||||||
|
beqz s9, 3f
|
||||||
|
li a4, 0
|
||||||
|
1:
|
||||||
|
#if __riscv_xlen == 64
|
||||||
|
lwu a5, (s9)
|
||||||
|
#else
|
||||||
|
lw a5, (s9)
|
||||||
|
#endif
|
||||||
|
beq a5, s6, 2f
|
||||||
|
add s9, s9, 4
|
||||||
|
add a4, a4, 1
|
||||||
|
blt a4, s7, 1b
|
||||||
|
li a4, -1
|
||||||
|
2: add s6, a4, zero
|
||||||
|
3: bge s6, s7, _start_hang
|
||||||
|
|
||||||
|
/* Find the scratch space based on HART index */
|
||||||
la tp, _fw_end
|
la tp, _fw_end
|
||||||
mul a5, s7, s8
|
mul a5, s7, s8
|
||||||
add tp, tp, a5
|
add tp, tp, a5
|
||||||
@@ -358,10 +416,27 @@ _start_warm:
|
|||||||
|
|
||||||
/* Setup trap handler */
|
/* Setup trap handler */
|
||||||
la a4, _trap_handler
|
la a4, _trap_handler
|
||||||
|
#if __riscv_xlen == 32
|
||||||
|
csrr a5, CSR_MISA
|
||||||
|
srli a5, a5, ('H' - 'A')
|
||||||
|
andi a5, a5, 0x1
|
||||||
|
beq a5, zero, _skip_trap_handler_rv32_hyp
|
||||||
|
la a4, _trap_handler_rv32_hyp
|
||||||
|
_skip_trap_handler_rv32_hyp:
|
||||||
|
#endif
|
||||||
csrw CSR_MTVEC, a4
|
csrw CSR_MTVEC, a4
|
||||||
/* Make sure that mtvec is updated */
|
|
||||||
1: csrr a5, CSR_MTVEC
|
#if __riscv_xlen == 32
|
||||||
bne a4, a5, 1b
|
/* Override trap exit for H-extension */
|
||||||
|
csrr a5, CSR_MISA
|
||||||
|
srli a5, a5, ('H' - 'A')
|
||||||
|
andi a5, a5, 0x1
|
||||||
|
beq a5, zero, _skip_trap_exit_rv32_hyp
|
||||||
|
la a4, _trap_exit_rv32_hyp
|
||||||
|
csrr a5, CSR_MSCRATCH
|
||||||
|
REG_S a4, SBI_SCRATCH_TRAP_EXIT_OFFSET(a5)
|
||||||
|
_skip_trap_exit_rv32_hyp:
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Initialize SBI runtime */
|
/* Initialize SBI runtime */
|
||||||
csrr a0, CSR_MSCRATCH
|
csrr a0, CSR_MSCRATCH
|
||||||
@@ -371,6 +446,8 @@ _start_warm:
|
|||||||
j _start_hang
|
j _start_hang
|
||||||
|
|
||||||
.align 3
|
.align 3
|
||||||
|
_relocate_lottery:
|
||||||
|
RISCV_PTR 0
|
||||||
_boot_status:
|
_boot_status:
|
||||||
RISCV_PTR 0
|
RISCV_PTR 0
|
||||||
_load_start:
|
_load_start:
|
||||||
@@ -380,87 +457,79 @@ _link_start:
|
|||||||
_link_end:
|
_link_end:
|
||||||
RISCV_PTR _fw_reloc_end
|
RISCV_PTR _fw_reloc_end
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.globl _hartid_to_scratch
|
.globl _hartid_to_scratch
|
||||||
_hartid_to_scratch:
|
_hartid_to_scratch:
|
||||||
add sp, sp, -(3 * __SIZEOF_POINTER__)
|
|
||||||
REG_S s0, (sp)
|
|
||||||
REG_S s1, (__SIZEOF_POINTER__)(sp)
|
|
||||||
REG_S s2, (__SIZEOF_POINTER__ * 2)(sp)
|
|
||||||
/*
|
/*
|
||||||
* a0 -> HART ID (passed by caller)
|
* a0 -> HART ID (passed by caller)
|
||||||
* s0 -> HART Stack Size
|
* a1 -> HART Index (passed by caller)
|
||||||
* s1 -> HART Stack End
|
* t0 -> HART Stack Size
|
||||||
* s2 -> Temporary
|
* t1 -> HART Stack End
|
||||||
|
* t2 -> Temporary
|
||||||
*/
|
*/
|
||||||
la s2, platform
|
la t2, platform
|
||||||
#if __riscv_xlen == 64
|
#if __riscv_xlen == 64
|
||||||
lwu s0, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(s2)
|
lwu t0, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(t2)
|
||||||
lwu s2, SBI_PLATFORM_HART_COUNT_OFFSET(s2)
|
lwu t2, SBI_PLATFORM_HART_COUNT_OFFSET(t2)
|
||||||
#else
|
#else
|
||||||
lw s0, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(s2)
|
lw t0, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(t2)
|
||||||
lw s2, SBI_PLATFORM_HART_COUNT_OFFSET(s2)
|
lw t2, SBI_PLATFORM_HART_COUNT_OFFSET(t2)
|
||||||
#endif
|
#endif
|
||||||
mul s2, s2, s0
|
sub t2, t2, a1
|
||||||
la s1, _fw_end
|
mul t2, t2, t0
|
||||||
add s1, s1, s2
|
la t1, _fw_end
|
||||||
mul s2, s0, a0
|
add t1, t1, t2
|
||||||
sub s1, s1, s2
|
li t2, SBI_SCRATCH_SIZE
|
||||||
li s2, SBI_SCRATCH_SIZE
|
sub a0, t1, t2
|
||||||
sub a0, s1, s2
|
|
||||||
REG_L s0, (sp)
|
|
||||||
REG_L s1, (__SIZEOF_POINTER__)(sp)
|
|
||||||
REG_L s2, (__SIZEOF_POINTER__ * 2)(sp)
|
|
||||||
add sp, sp, (3 * __SIZEOF_POINTER__)
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.globl _start_hang
|
.globl _start_hang
|
||||||
_start_hang:
|
_start_hang:
|
||||||
wfi
|
wfi
|
||||||
j _start_hang
|
j _start_hang
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
.globl _trap_handler
|
.align 3
|
||||||
_trap_handler:
|
.globl fw_platform_init
|
||||||
|
.weak fw_platform_init
|
||||||
|
fw_platform_init:
|
||||||
|
add a0, a1, zero
|
||||||
|
ret
|
||||||
|
|
||||||
|
.macro TRAP_SAVE_AND_SETUP_SP_T0
|
||||||
/* Swap TP and MSCRATCH */
|
/* Swap TP and MSCRATCH */
|
||||||
csrrw tp, CSR_MSCRATCH, tp
|
csrrw tp, CSR_MSCRATCH, tp
|
||||||
|
|
||||||
/* Save T0 in scratch space */
|
/* Save T0 in scratch space */
|
||||||
REG_S t0, SBI_SCRATCH_TMP0_OFFSET(tp)
|
REG_S t0, SBI_SCRATCH_TMP0_OFFSET(tp)
|
||||||
|
|
||||||
/* Check which mode we came from */
|
/*
|
||||||
|
* Set T0 to appropriate exception stack
|
||||||
|
*
|
||||||
|
* Came_From_M_Mode = ((MSTATUS.MPP < PRV_M) ? 1 : 0) - 1;
|
||||||
|
* Exception_Stack = TP ^ (Came_From_M_Mode & (SP ^ TP))
|
||||||
|
*
|
||||||
|
* Came_From_M_Mode = 0 ==> Exception_Stack = TP
|
||||||
|
* Came_From_M_Mode = -1 ==> Exception_Stack = SP
|
||||||
|
*/
|
||||||
csrr t0, CSR_MSTATUS
|
csrr t0, CSR_MSTATUS
|
||||||
srl t0, t0, MSTATUS_MPP_SHIFT
|
srl t0, t0, MSTATUS_MPP_SHIFT
|
||||||
and t0, t0, PRV_M
|
and t0, t0, PRV_M
|
||||||
xori t0, t0, PRV_M
|
slti t0, t0, PRV_M
|
||||||
beq t0, zero, _trap_handler_m_mode
|
add t0, t0, -1
|
||||||
|
xor sp, sp, tp
|
||||||
|
and t0, t0, sp
|
||||||
|
xor sp, sp, tp
|
||||||
|
xor t0, tp, t0
|
||||||
|
|
||||||
/* We came from S-mode or U-mode */
|
/* Save original SP on exception stack */
|
||||||
_trap_handler_s_mode:
|
REG_S sp, (SBI_TRAP_REGS_OFFSET(sp) - SBI_TRAP_REGS_SIZE)(t0)
|
||||||
/* Set T0 to original SP */
|
|
||||||
add t0, sp, zero
|
|
||||||
|
|
||||||
/* Setup exception stack */
|
/* Set SP to exception stack and make room for trap registers */
|
||||||
add sp, tp, -(SBI_TRAP_REGS_SIZE)
|
add sp, t0, -(SBI_TRAP_REGS_SIZE)
|
||||||
|
|
||||||
/* Jump to code common for all modes */
|
|
||||||
j _trap_handler_all_mode
|
|
||||||
|
|
||||||
/* We came from M-mode */
|
|
||||||
_trap_handler_m_mode:
|
|
||||||
/* Set T0 to original SP */
|
|
||||||
add t0, sp, zero
|
|
||||||
|
|
||||||
/* Re-use current SP as exception stack */
|
|
||||||
add sp, sp, -(SBI_TRAP_REGS_SIZE)
|
|
||||||
|
|
||||||
_trap_handler_all_mode:
|
|
||||||
/* Save original SP (from T0) on stack */
|
|
||||||
REG_S t0, SBI_TRAP_REGS_OFFSET(sp)(sp)
|
|
||||||
|
|
||||||
/* Restore T0 from scratch space */
|
/* Restore T0 from scratch space */
|
||||||
REG_L t0, SBI_SCRATCH_TMP0_OFFSET(tp)
|
REG_L t0, SBI_SCRATCH_TMP0_OFFSET(tp)
|
||||||
@@ -470,13 +539,23 @@ _trap_handler_all_mode:
|
|||||||
|
|
||||||
/* Swap TP and MSCRATCH */
|
/* Swap TP and MSCRATCH */
|
||||||
csrrw tp, CSR_MSCRATCH, tp
|
csrrw tp, CSR_MSCRATCH, tp
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro TRAP_SAVE_MEPC_MSTATUS have_mstatush
|
||||||
/* Save MEPC and MSTATUS CSRs */
|
/* Save MEPC and MSTATUS CSRs */
|
||||||
csrr t0, CSR_MEPC
|
csrr t0, CSR_MEPC
|
||||||
REG_S t0, SBI_TRAP_REGS_OFFSET(mepc)(sp)
|
REG_S t0, SBI_TRAP_REGS_OFFSET(mepc)(sp)
|
||||||
csrr t0, CSR_MSTATUS
|
csrr t0, CSR_MSTATUS
|
||||||
REG_S t0, SBI_TRAP_REGS_OFFSET(mstatus)(sp)
|
REG_S t0, SBI_TRAP_REGS_OFFSET(mstatus)(sp)
|
||||||
|
.if \have_mstatush
|
||||||
|
csrr t0, CSR_MSTATUSH
|
||||||
|
REG_S t0, SBI_TRAP_REGS_OFFSET(mstatusH)(sp)
|
||||||
|
.else
|
||||||
|
REG_S zero, SBI_TRAP_REGS_OFFSET(mstatusH)(sp)
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro TRAP_SAVE_GENERAL_REGS_EXCEPT_SP_T0
|
||||||
/* Save all general regisers except SP and T0 */
|
/* 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 ra, SBI_TRAP_REGS_OFFSET(ra)(sp)
|
||||||
@@ -508,12 +587,15 @@ _trap_handler_all_mode:
|
|||||||
REG_S t4, SBI_TRAP_REGS_OFFSET(t4)(sp)
|
REG_S t4, SBI_TRAP_REGS_OFFSET(t4)(sp)
|
||||||
REG_S t5, SBI_TRAP_REGS_OFFSET(t5)(sp)
|
REG_S t5, SBI_TRAP_REGS_OFFSET(t5)(sp)
|
||||||
REG_S t6, SBI_TRAP_REGS_OFFSET(t6)(sp)
|
REG_S t6, SBI_TRAP_REGS_OFFSET(t6)(sp)
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro TRAP_CALL_C_ROUTINE
|
||||||
/* Call C routine */
|
/* Call C routine */
|
||||||
add a0, sp, zero
|
add a0, sp, zero
|
||||||
csrr a1, CSR_MSCRATCH
|
|
||||||
call sbi_trap_handler
|
call sbi_trap_handler
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro TRAP_RESTORE_GENERAL_REGS_EXCEPT_SP_T0
|
||||||
/* Restore all general regisers except SP and T0 */
|
/* Restore all general regisers except SP and T0 */
|
||||||
REG_L ra, SBI_TRAP_REGS_OFFSET(ra)(sp)
|
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)
|
||||||
@@ -544,23 +626,100 @@ _trap_handler_all_mode:
|
|||||||
REG_L t4, SBI_TRAP_REGS_OFFSET(t4)(sp)
|
REG_L t4, SBI_TRAP_REGS_OFFSET(t4)(sp)
|
||||||
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)
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro TRAP_RESTORE_MEPC_MSTATUS have_mstatush
|
||||||
/* Restore MEPC and MSTATUS CSRs */
|
/* Restore MEPC and MSTATUS CSRs */
|
||||||
REG_L t0, SBI_TRAP_REGS_OFFSET(mepc)(sp)
|
REG_L t0, SBI_TRAP_REGS_OFFSET(mepc)(sp)
|
||||||
csrw CSR_MEPC, t0
|
csrw CSR_MEPC, t0
|
||||||
REG_L t0, SBI_TRAP_REGS_OFFSET(mstatus)(sp)
|
REG_L t0, SBI_TRAP_REGS_OFFSET(mstatus)(sp)
|
||||||
csrw CSR_MSTATUS, t0
|
csrw CSR_MSTATUS, t0
|
||||||
|
.if \have_mstatush
|
||||||
|
REG_L t0, SBI_TRAP_REGS_OFFSET(mstatusH)(sp)
|
||||||
|
csrw CSR_MSTATUSH, t0
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro TRAP_RESTORE_SP_T0
|
||||||
/* Restore T0 */
|
/* Restore T0 */
|
||||||
REG_L t0, SBI_TRAP_REGS_OFFSET(t0)(sp)
|
REG_L t0, SBI_TRAP_REGS_OFFSET(t0)(sp)
|
||||||
|
|
||||||
/* Restore SP */
|
/* Restore SP */
|
||||||
REG_L sp, SBI_TRAP_REGS_OFFSET(sp)(sp)
|
REG_L sp, SBI_TRAP_REGS_OFFSET(sp)(sp)
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
|
.globl _trap_handler
|
||||||
|
_trap_handler:
|
||||||
|
TRAP_SAVE_AND_SETUP_SP_T0
|
||||||
|
|
||||||
|
TRAP_SAVE_MEPC_MSTATUS 0
|
||||||
|
|
||||||
|
TRAP_SAVE_GENERAL_REGS_EXCEPT_SP_T0
|
||||||
|
|
||||||
|
TRAP_CALL_C_ROUTINE
|
||||||
|
|
||||||
|
TRAP_RESTORE_GENERAL_REGS_EXCEPT_SP_T0
|
||||||
|
|
||||||
|
TRAP_RESTORE_MEPC_MSTATUS 0
|
||||||
|
|
||||||
|
TRAP_RESTORE_SP_T0
|
||||||
|
|
||||||
mret
|
mret
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
|
.globl _trap_exit
|
||||||
|
_trap_exit:
|
||||||
|
add sp, a0, zero
|
||||||
|
|
||||||
|
TRAP_RESTORE_GENERAL_REGS_EXCEPT_SP_T0
|
||||||
|
|
||||||
|
TRAP_RESTORE_MEPC_MSTATUS 0
|
||||||
|
|
||||||
|
TRAP_RESTORE_SP_T0
|
||||||
|
|
||||||
|
mret
|
||||||
|
|
||||||
|
#if __riscv_xlen == 32
|
||||||
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
|
.globl _trap_handler_rv32_hyp
|
||||||
|
_trap_handler_rv32_hyp:
|
||||||
|
TRAP_SAVE_AND_SETUP_SP_T0
|
||||||
|
|
||||||
|
TRAP_SAVE_MEPC_MSTATUS 1
|
||||||
|
|
||||||
|
TRAP_SAVE_GENERAL_REGS_EXCEPT_SP_T0
|
||||||
|
|
||||||
|
TRAP_CALL_C_ROUTINE
|
||||||
|
|
||||||
|
TRAP_RESTORE_GENERAL_REGS_EXCEPT_SP_T0
|
||||||
|
|
||||||
|
TRAP_RESTORE_MEPC_MSTATUS 1
|
||||||
|
|
||||||
|
TRAP_RESTORE_SP_T0
|
||||||
|
|
||||||
|
mret
|
||||||
|
|
||||||
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
|
.globl _trap_exit_rv32_hyp
|
||||||
|
_trap_exit_rv32_hyp:
|
||||||
|
add sp, a0, zero
|
||||||
|
|
||||||
|
TRAP_RESTORE_GENERAL_REGS_EXCEPT_SP_T0
|
||||||
|
|
||||||
|
TRAP_RESTORE_MEPC_MSTATUS 1
|
||||||
|
|
||||||
|
TRAP_RESTORE_SP_T0
|
||||||
|
|
||||||
|
mret
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.globl _reset_regs
|
.globl _reset_regs
|
||||||
_reset_regs:
|
_reset_regs:
|
||||||
|
|
||||||
@@ -597,3 +756,14 @@ _reset_regs:
|
|||||||
csrw CSR_MSCRATCH, 0
|
csrw CSR_MSCRATCH, 0
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
#ifdef FW_FDT_PATH
|
||||||
|
.section .rodata
|
||||||
|
.align 4
|
||||||
|
.globl fw_fdt_bin
|
||||||
|
fw_fdt_bin:
|
||||||
|
.incbin FW_FDT_PATH
|
||||||
|
#ifdef FW_FDT_PADDING
|
||||||
|
.fill FW_FDT_PADDING, 1, 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
@@ -11,14 +11,40 @@
|
|||||||
|
|
||||||
#include "fw_base.S"
|
#include "fw_base.S"
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
_bad_dynamic_info:
|
_bad_dynamic_info:
|
||||||
wfi
|
wfi
|
||||||
j _bad_dynamic_info
|
j _bad_dynamic_info
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
|
.global fw_boot_hart
|
||||||
|
/*
|
||||||
|
* This function is called very early even before
|
||||||
|
* fw_save_info() is called.
|
||||||
|
* We can only use a0, a1, and a2 registers here.
|
||||||
|
* The boot HART id should be returned in 'a0'.
|
||||||
|
*/
|
||||||
|
fw_boot_hart:
|
||||||
|
/* Sanity checks */
|
||||||
|
li a1, FW_DYNAMIC_INFO_MAGIC_VALUE
|
||||||
|
REG_L a0, FW_DYNAMIC_INFO_MAGIC_OFFSET(a2)
|
||||||
|
bne a0, a1, _bad_dynamic_info
|
||||||
|
li a1, FW_DYNAMIC_INFO_VERSION_MAX
|
||||||
|
REG_L a0, FW_DYNAMIC_INFO_VERSION_OFFSET(a2)
|
||||||
|
bgt a0, a1, _bad_dynamic_info
|
||||||
|
|
||||||
|
/* Read boot HART id */
|
||||||
|
li a1, 0x2
|
||||||
|
blt a0, a1, 2f
|
||||||
|
REG_L a0, FW_DYNAMIC_INFO_BOOT_HART_OFFSET(a2)
|
||||||
|
ret
|
||||||
|
2: li a0, -1
|
||||||
|
ret
|
||||||
|
|
||||||
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.global fw_save_info
|
.global fw_save_info
|
||||||
/*
|
/*
|
||||||
* We can only use a0, a1, a2, a3, and a4 registers here.
|
* We can only use a0, a1, a2, a3, and a4 registers here.
|
||||||
@@ -27,14 +53,19 @@ _bad_dynamic_info:
|
|||||||
* Nothing to be returned here.
|
* Nothing to be returned here.
|
||||||
*/
|
*/
|
||||||
fw_save_info:
|
fw_save_info:
|
||||||
|
/* Save next arg1 in 'a1' */
|
||||||
la a4, _dynamic_next_arg1
|
la a4, _dynamic_next_arg1
|
||||||
REG_S a1, (a4)
|
REG_S a1, (a4)
|
||||||
|
|
||||||
|
/* Sanity checks */
|
||||||
li a4, FW_DYNAMIC_INFO_MAGIC_VALUE
|
li a4, FW_DYNAMIC_INFO_MAGIC_VALUE
|
||||||
REG_L a3, FW_DYNAMIC_INFO_MAGIC_OFFSET(a2)
|
REG_L a3, FW_DYNAMIC_INFO_MAGIC_OFFSET(a2)
|
||||||
bne a3, a4, _bad_dynamic_info
|
bne a3, a4, _bad_dynamic_info
|
||||||
li a4, FW_DYNAMIC_INFO_VERSION_MAX
|
li a4, FW_DYNAMIC_INFO_VERSION_MAX
|
||||||
REG_L a3, FW_DYNAMIC_INFO_VERSION_OFFSET(a2)
|
REG_L a3, FW_DYNAMIC_INFO_VERSION_OFFSET(a2)
|
||||||
bgt a3, a4, _bad_dynamic_info
|
bgt a3, a4, _bad_dynamic_info
|
||||||
|
|
||||||
|
/* Save version == 0x1 fields */
|
||||||
la a4, _dynamic_next_addr
|
la a4, _dynamic_next_addr
|
||||||
REG_L a3, FW_DYNAMIC_INFO_NEXT_ADDR_OFFSET(a2)
|
REG_L a3, FW_DYNAMIC_INFO_NEXT_ADDR_OFFSET(a2)
|
||||||
REG_S a3, (a4)
|
REG_S a3, (a4)
|
||||||
@@ -44,24 +75,24 @@ fw_save_info:
|
|||||||
la a4, _dynamic_options
|
la a4, _dynamic_options
|
||||||
REG_L a3, FW_DYNAMIC_INFO_OPTIONS_OFFSET(a2)
|
REG_L a3, FW_DYNAMIC_INFO_OPTIONS_OFFSET(a2)
|
||||||
REG_S a3, (a4)
|
REG_S a3, (a4)
|
||||||
|
|
||||||
|
/* Save version == 0x2 fields */
|
||||||
|
li a4, 0x2
|
||||||
|
REG_L a3, FW_DYNAMIC_INFO_VERSION_OFFSET(a2)
|
||||||
|
blt a3, a4, 2f
|
||||||
|
la a4, _dynamic_boot_hart
|
||||||
|
REG_L a3, FW_DYNAMIC_INFO_BOOT_HART_OFFSET(a2)
|
||||||
|
REG_S a3, (a4)
|
||||||
|
2:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
.global fw_prev_arg1
|
|
||||||
/*
|
|
||||||
* We can only use a0, a1, and a2 registers here.
|
|
||||||
* The previous arg1 should be returned in 'a0'.
|
|
||||||
*/
|
|
||||||
fw_prev_arg1:
|
|
||||||
add a0, zero, zero
|
|
||||||
ret
|
|
||||||
|
|
||||||
.align 3
|
.align 3
|
||||||
.section .entry, "ax", %progbits
|
|
||||||
.global fw_next_arg1
|
.global fw_next_arg1
|
||||||
/*
|
/*
|
||||||
* We can only use a0, a1, and a2 registers here.
|
* We can only use a0, a1, and a2 registers here.
|
||||||
|
* The a0, a1, and a2 registers will be same as passed by
|
||||||
|
* previous booting stage.
|
||||||
* The next arg1 should be returned in 'a0'.
|
* The next arg1 should be returned in 'a0'.
|
||||||
*/
|
*/
|
||||||
fw_next_arg1:
|
fw_next_arg1:
|
||||||
@@ -69,8 +100,8 @@ fw_next_arg1:
|
|||||||
REG_L a0, (a0)
|
REG_L a0, (a0)
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.global fw_next_addr
|
.global fw_next_addr
|
||||||
/*
|
/*
|
||||||
* We can only use a0, a1, and a2 registers here.
|
* We can only use a0, a1, and a2 registers here.
|
||||||
@@ -81,8 +112,8 @@ fw_next_addr:
|
|||||||
REG_L a0, (a0)
|
REG_L a0, (a0)
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.global fw_next_mode
|
.global fw_next_mode
|
||||||
/*
|
/*
|
||||||
* We can only use a0, a1, and a2 registers here.
|
* We can only use a0, a1, and a2 registers here.
|
||||||
@@ -93,8 +124,8 @@ fw_next_mode:
|
|||||||
REG_L a0, (a0)
|
REG_L a0, (a0)
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.global fw_options
|
.global fw_options
|
||||||
/*
|
/*
|
||||||
* We can only use a0, a1, and a2 registers here.
|
* We can only use a0, a1, and a2 registers here.
|
||||||
@@ -106,8 +137,8 @@ fw_options:
|
|||||||
REG_L a0, (a0)
|
REG_L a0, (a0)
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
_dynamic_next_arg1:
|
_dynamic_next_arg1:
|
||||||
RISCV_PTR 0x0
|
RISCV_PTR 0x0
|
||||||
_dynamic_next_addr:
|
_dynamic_next_addr:
|
||||||
@@ -116,3 +147,5 @@ _dynamic_next_mode:
|
|||||||
RISCV_PTR PRV_S
|
RISCV_PTR PRV_S
|
||||||
_dynamic_options:
|
_dynamic_options:
|
||||||
RISCV_PTR 0x0
|
RISCV_PTR 0x0
|
||||||
|
_dynamic_boot_hart:
|
||||||
|
RISCV_PTR -1
|
||||||
|
@@ -9,8 +9,21 @@
|
|||||||
|
|
||||||
#include "fw_base.S"
|
#include "fw_base.S"
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
|
.global fw_boot_hart
|
||||||
|
/*
|
||||||
|
* This function is called very early even before
|
||||||
|
* fw_save_info() is called.
|
||||||
|
* We can only use a0, a1, and a2 registers here.
|
||||||
|
* The boot HART id should be returned in 'a0'.
|
||||||
|
*/
|
||||||
|
fw_boot_hart:
|
||||||
|
li a0, -1
|
||||||
|
ret
|
||||||
|
|
||||||
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.global fw_save_info
|
.global fw_save_info
|
||||||
/*
|
/*
|
||||||
* We can only use a0, a1, a2, a3, and a4 registers here.
|
* We can only use a0, a1, a2, a3, and a4 registers here.
|
||||||
@@ -21,34 +34,25 @@
|
|||||||
fw_save_info:
|
fw_save_info:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
.global fw_prev_arg1
|
|
||||||
/*
|
|
||||||
* We can only use a0, a1, and a2 registers here.
|
|
||||||
* The previous arg1 should be returned in 'a0'.
|
|
||||||
*/
|
|
||||||
fw_prev_arg1:
|
|
||||||
add a0, zero, zero
|
|
||||||
ret
|
|
||||||
|
|
||||||
.align 3
|
.align 3
|
||||||
.section .entry, "ax", %progbits
|
|
||||||
.global fw_next_arg1
|
.global fw_next_arg1
|
||||||
/*
|
/*
|
||||||
* We can only use a0, a1, and a2 registers here.
|
* We can only use a0, a1, and a2 registers here.
|
||||||
|
* The a0, a1, and a2 registers will be same as passed by
|
||||||
|
* previous booting stage.
|
||||||
* The next arg1 should be returned in 'a0'.
|
* The next arg1 should be returned in 'a0'.
|
||||||
*/
|
*/
|
||||||
fw_next_arg1:
|
fw_next_arg1:
|
||||||
#ifdef FW_JUMP_FDT_ADDR
|
#ifdef FW_JUMP_FDT_ADDR
|
||||||
li a0, FW_JUMP_FDT_ADDR
|
li a0, FW_JUMP_FDT_ADDR
|
||||||
#else
|
#else
|
||||||
add a0, zero, zero
|
add a0, a1, zero
|
||||||
#endif
|
#endif
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.global fw_next_addr
|
.global fw_next_addr
|
||||||
/*
|
/*
|
||||||
* We can only use a0, a1, and a2 registers here.
|
* We can only use a0, a1, and a2 registers here.
|
||||||
@@ -59,8 +63,8 @@ fw_next_addr:
|
|||||||
REG_L a0, (a0)
|
REG_L a0, (a0)
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.global fw_next_mode
|
.global fw_next_mode
|
||||||
/*
|
/*
|
||||||
* We can only use a0, a1, and a2 registers here.
|
* We can only use a0, a1, and a2 registers here.
|
||||||
@@ -70,8 +74,8 @@ fw_next_mode:
|
|||||||
li a0, PRV_S
|
li a0, PRV_S
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.global fw_options
|
.global fw_options
|
||||||
/*
|
/*
|
||||||
* We can only use a0, a1, and a2 registers here.
|
* We can only use a0, a1, and a2 registers here.
|
||||||
@@ -86,7 +90,7 @@ fw_options:
|
|||||||
#error "Must define FW_JUMP_ADDR"
|
#error "Must define FW_JUMP_ADDR"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
_jump_addr:
|
_jump_addr:
|
||||||
RISCV_PTR FW_JUMP_ADDR
|
RISCV_PTR FW_JUMP_ADDR
|
||||||
|
@@ -9,8 +9,21 @@
|
|||||||
|
|
||||||
#include "fw_base.S"
|
#include "fw_base.S"
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
|
.global fw_boot_hart
|
||||||
|
/*
|
||||||
|
* This function is called very early even before
|
||||||
|
* fw_save_info() is called.
|
||||||
|
* We can only use a0, a1, and a2 registers here.
|
||||||
|
* The boot HART id should be returned in 'a0'.
|
||||||
|
*/
|
||||||
|
fw_boot_hart:
|
||||||
|
li a0, -1
|
||||||
|
ret
|
||||||
|
|
||||||
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.global fw_save_info
|
.global fw_save_info
|
||||||
/*
|
/*
|
||||||
* We can only use a0, a1, a2, a3, and a4 registers here.
|
* We can only use a0, a1, a2, a3, and a4 registers here.
|
||||||
@@ -21,38 +34,25 @@
|
|||||||
fw_save_info:
|
fw_save_info:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
.global fw_prev_arg1
|
|
||||||
/*
|
|
||||||
* We can only use a0, a1, and a2 registers here.
|
|
||||||
* The previous arg1 should be returned in 'a0'.
|
|
||||||
*/
|
|
||||||
fw_prev_arg1:
|
|
||||||
#ifdef FW_PAYLOAD_FDT_PATH
|
|
||||||
la a0, fdt_bin
|
|
||||||
#else
|
|
||||||
add a0, zero, zero
|
|
||||||
#endif
|
|
||||||
ret
|
|
||||||
|
|
||||||
.align 3
|
.align 3
|
||||||
.section .entry, "ax", %progbits
|
|
||||||
.global fw_next_arg1
|
.global fw_next_arg1
|
||||||
/*
|
/*
|
||||||
* We can only use a0, a1, and a2 registers here.
|
* We can only use a0, a1, and a2 registers here.
|
||||||
|
* The a0, a1, and a2 registers will be same as passed by
|
||||||
|
* previous booting stage.
|
||||||
* The next arg1 should be returned in 'a0'.
|
* The next arg1 should be returned in 'a0'.
|
||||||
*/
|
*/
|
||||||
fw_next_arg1:
|
fw_next_arg1:
|
||||||
#ifdef FW_PAYLOAD_FDT_ADDR
|
#ifdef FW_PAYLOAD_FDT_ADDR
|
||||||
li a0, FW_PAYLOAD_FDT_ADDR
|
li a0, FW_PAYLOAD_FDT_ADDR
|
||||||
#else
|
#else
|
||||||
add a0, zero, zero
|
add a0, a1, zero
|
||||||
#endif
|
#endif
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.global fw_next_addr
|
.global fw_next_addr
|
||||||
/*
|
/*
|
||||||
* We can only use a0, a1, and a2 registers here.
|
* We can only use a0, a1, and a2 registers here.
|
||||||
@@ -62,8 +62,8 @@ fw_next_addr:
|
|||||||
la a0, payload_bin
|
la a0, payload_bin
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.global fw_next_mode
|
.global fw_next_mode
|
||||||
/*
|
/*
|
||||||
* We can only use a0, a1, and a2 registers here.
|
* We can only use a0, a1, and a2 registers here.
|
||||||
@@ -73,8 +73,8 @@ fw_next_mode:
|
|||||||
li a0, PRV_S
|
li a0, PRV_S
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.global fw_options
|
.global fw_options
|
||||||
/*
|
/*
|
||||||
* We can only use a0, a1, and a2 registers here.
|
* We can only use a0, a1, and a2 registers here.
|
||||||
@@ -85,16 +85,8 @@ fw_options:
|
|||||||
add a0, zero, zero
|
add a0, zero, zero
|
||||||
ret
|
ret
|
||||||
|
|
||||||
#ifdef FW_PAYLOAD_FDT_PATH
|
|
||||||
.align 4
|
|
||||||
.section .text, "ax", %progbits
|
|
||||||
.globl fdt_bin
|
|
||||||
fdt_bin:
|
|
||||||
.incbin FW_PAYLOAD_FDT_PATH
|
|
||||||
#endif
|
|
||||||
|
|
||||||
.align 4
|
|
||||||
.section .payload, "ax", %progbits
|
.section .payload, "ax", %progbits
|
||||||
|
.align 4
|
||||||
.globl payload_bin
|
.globl payload_bin
|
||||||
payload_bin:
|
payload_bin:
|
||||||
#ifndef FW_PAYLOAD_PATH
|
#ifndef FW_PAYLOAD_PATH
|
||||||
|
@@ -17,6 +17,13 @@ ifdef FW_TEXT_START
|
|||||||
firmware-genflags-y += -DFW_TEXT_START=$(FW_TEXT_START)
|
firmware-genflags-y += -DFW_TEXT_START=$(FW_TEXT_START)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef FW_FDT_PATH
|
||||||
|
firmware-genflags-y += -DFW_FDT_PATH=\"$(FW_FDT_PATH)\"
|
||||||
|
ifdef FW_FDT_PADDING
|
||||||
|
firmware-genflags-y += -DFW_FDT_PADDING=$(FW_FDT_PADDING)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
firmware-bins-$(FW_DYNAMIC) += fw_dynamic.bin
|
firmware-bins-$(FW_DYNAMIC) += fw_dynamic.bin
|
||||||
|
|
||||||
firmware-bins-$(FW_JUMP) += fw_jump.bin
|
firmware-bins-$(FW_JUMP) += fw_jump.bin
|
||||||
@@ -41,14 +48,6 @@ ifdef FW_PAYLOAD_ALIGN
|
|||||||
firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_ALIGN=$(FW_PAYLOAD_ALIGN)
|
firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_ALIGN=$(FW_PAYLOAD_ALIGN)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifndef FW_PAYLOAD_FDT_PATH
|
|
||||||
ifdef FW_PAYLOAD_FDT
|
|
||||||
FW_PAYLOAD_FDT_PATH=$(platform_build_dir)/$(FW_PAYLOAD_FDT)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
ifdef FW_PAYLOAD_FDT_PATH
|
|
||||||
firmware-genflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_PATH=\"$(FW_PAYLOAD_FDT_PATH)\"
|
|
||||||
endif
|
|
||||||
ifdef FW_PAYLOAD_FDT_ADDR
|
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)
|
||||||
endif
|
endif
|
||||||
|
@@ -23,8 +23,8 @@
|
|||||||
#define REG_L __REG_SEL(ld, lw)
|
#define REG_L __REG_SEL(ld, lw)
|
||||||
#define REG_S __REG_SEL(sd, sw)
|
#define REG_S __REG_SEL(sd, sw)
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.globl _start
|
.globl _start
|
||||||
_start:
|
_start:
|
||||||
/* Pick one hart to run the main boot sequence */
|
/* Pick one hart to run the main boot sequence */
|
||||||
@@ -71,15 +71,15 @@ _start_warm:
|
|||||||
/* 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
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
.globl _start_hang
|
.globl _start_hang
|
||||||
_start_hang:
|
_start_hang:
|
||||||
wfi
|
wfi
|
||||||
j _start_hang
|
j _start_hang
|
||||||
|
|
||||||
.align 3
|
|
||||||
.section .entry, "ax", %progbits
|
.section .entry, "ax", %progbits
|
||||||
|
.align 3
|
||||||
_hart_lottery:
|
_hart_lottery:
|
||||||
RISCV_PTR 0
|
RISCV_PTR 0
|
||||||
_boot_a0:
|
_boot_a0:
|
||||||
|
@@ -9,6 +9,31 @@
|
|||||||
|
|
||||||
#include <sbi/sbi_ecall_interface.h>
|
#include <sbi/sbi_ecall_interface.h>
|
||||||
|
|
||||||
|
#define SBI_ECALL(__num, __a0, __a1, __a2) \
|
||||||
|
({ \
|
||||||
|
register unsigned long a0 asm("a0") = (unsigned long)(__a0); \
|
||||||
|
register unsigned long a1 asm("a1") = (unsigned long)(__a1); \
|
||||||
|
register unsigned long a2 asm("a2") = (unsigned long)(__a2); \
|
||||||
|
register unsigned long a7 asm("a7") = (unsigned long)(__num); \
|
||||||
|
asm volatile("ecall" \
|
||||||
|
: "+r"(a0) \
|
||||||
|
: "r"(a1), "r"(a2), "r"(a7) \
|
||||||
|
: "memory"); \
|
||||||
|
a0; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define SBI_ECALL_0(__num) SBI_ECALL(__num, 0, 0, 0)
|
||||||
|
#define SBI_ECALL_1(__num, __a0) SBI_ECALL(__num, __a0, 0, 0)
|
||||||
|
#define SBI_ECALL_2(__num, __a0, __a1) SBI_ECALL(__num, __a0, __a1, 0)
|
||||||
|
|
||||||
|
#define sbi_ecall_console_putc(c) SBI_ECALL_1(SBI_EXT_0_1_CONSOLE_PUTCHAR, (c))
|
||||||
|
|
||||||
|
static inline void sbi_ecall_console_puts(const char *str)
|
||||||
|
{
|
||||||
|
while (str && *str)
|
||||||
|
sbi_ecall_console_putc(*str++);
|
||||||
|
}
|
||||||
|
|
||||||
#define wfi() \
|
#define wfi() \
|
||||||
do { \
|
do { \
|
||||||
__asm__ __volatile__("wfi" ::: "memory"); \
|
__asm__ __volatile__("wfi" ::: "memory"); \
|
||||||
|
@@ -18,18 +18,20 @@
|
|||||||
#define FW_DYNAMIC_INFO_MAGIC_OFFSET (0 * __SIZEOF_POINTER__)
|
#define FW_DYNAMIC_INFO_MAGIC_OFFSET (0 * __SIZEOF_POINTER__)
|
||||||
/** Offset of version member in fw_dynamic_info */
|
/** Offset of version member in fw_dynamic_info */
|
||||||
#define FW_DYNAMIC_INFO_VERSION_OFFSET (1 * __SIZEOF_POINTER__)
|
#define FW_DYNAMIC_INFO_VERSION_OFFSET (1 * __SIZEOF_POINTER__)
|
||||||
/** Offset of next_addr member in fw_dynamic_info */
|
/** Offset of next_addr member in fw_dynamic_info (version >= 1) */
|
||||||
#define FW_DYNAMIC_INFO_NEXT_ADDR_OFFSET (2 * __SIZEOF_POINTER__)
|
#define FW_DYNAMIC_INFO_NEXT_ADDR_OFFSET (2 * __SIZEOF_POINTER__)
|
||||||
/** Offset of next_mode member in fw_dynamic_info */
|
/** Offset of next_mode member in fw_dynamic_info (version >= 1) */
|
||||||
#define FW_DYNAMIC_INFO_NEXT_MODE_OFFSET (3 * __SIZEOF_POINTER__)
|
#define FW_DYNAMIC_INFO_NEXT_MODE_OFFSET (3 * __SIZEOF_POINTER__)
|
||||||
/** Offset of options member in fw_dynamic_info */
|
/** Offset of options member in fw_dynamic_info (version >= 1) */
|
||||||
#define FW_DYNAMIC_INFO_OPTIONS_OFFSET (4 * __SIZEOF_POINTER__)
|
#define FW_DYNAMIC_INFO_OPTIONS_OFFSET (4 * __SIZEOF_POINTER__)
|
||||||
|
/** Offset of boot_hart member in fw_dynamic_info (version >= 2) */
|
||||||
|
#define FW_DYNAMIC_INFO_BOOT_HART_OFFSET (5 * __SIZEOF_POINTER__)
|
||||||
|
|
||||||
/** Expected value of info magic ('OSBI' ascii string in hex) */
|
/** Expected value of info magic ('OSBI' ascii string in hex) */
|
||||||
#define FW_DYNAMIC_INFO_MAGIC_VALUE 0x4942534f
|
#define FW_DYNAMIC_INFO_MAGIC_VALUE 0x4942534f
|
||||||
|
|
||||||
/** Maximum supported info version */
|
/** Maximum supported info version */
|
||||||
#define FW_DYNAMIC_INFO_VERSION_MAX 0x1
|
#define FW_DYNAMIC_INFO_VERSION_MAX 0x2
|
||||||
|
|
||||||
/** Possible next mode values */
|
/** Possible next mode values */
|
||||||
#define FW_DYNAMIC_INFO_NEXT_MODE_U 0x0
|
#define FW_DYNAMIC_INFO_NEXT_MODE_U 0x0
|
||||||
@@ -54,6 +56,22 @@ struct fw_dynamic_info {
|
|||||||
unsigned long next_mode;
|
unsigned long next_mode;
|
||||||
/** Options for OpenSBI library */
|
/** Options for OpenSBI library */
|
||||||
unsigned long options;
|
unsigned long options;
|
||||||
|
/**
|
||||||
|
* Preferred boot HART id
|
||||||
|
*
|
||||||
|
* It is possible that the previous booting stage uses same link
|
||||||
|
* address as the FW_DYNAMIC firmware. In this case, the relocation
|
||||||
|
* lottery mechanism can potentially overwrite the previous booting
|
||||||
|
* stage while other HARTs are still running in the previous booting
|
||||||
|
* stage leading to boot-time crash. To avoid this boot-time crash,
|
||||||
|
* the previous booting stage can specify last HART that will jump
|
||||||
|
* to the FW_DYNAMIC firmware as the preferred boot HART.
|
||||||
|
*
|
||||||
|
* To avoid specifying a preferred boot HART, the previous booting
|
||||||
|
* stage can set it to -1UL which will force the FW_DYNAMIC firmware
|
||||||
|
* to use the relocation lottery mechanism.
|
||||||
|
*/
|
||||||
|
unsigned long boot_hart;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -38,7 +38,6 @@
|
|||||||
#define LGREG __REG_SEL(3, 2)
|
#define LGREG __REG_SEL(3, 2)
|
||||||
|
|
||||||
#if __SIZEOF_POINTER__ == 8
|
#if __SIZEOF_POINTER__ == 8
|
||||||
#define BITS_PER_LONG 64
|
|
||||||
#ifdef __ASSEMBLY__
|
#ifdef __ASSEMBLY__
|
||||||
#define RISCV_PTR .dword
|
#define RISCV_PTR .dword
|
||||||
#define RISCV_SZPTR 8
|
#define RISCV_SZPTR 8
|
||||||
@@ -49,7 +48,6 @@
|
|||||||
#define RISCV_LGPTR "3"
|
#define RISCV_LGPTR "3"
|
||||||
#endif
|
#endif
|
||||||
#elif __SIZEOF_POINTER__ == 4
|
#elif __SIZEOF_POINTER__ == 4
|
||||||
#define BITS_PER_LONG 32
|
|
||||||
#ifdef __ASSEMBLY__
|
#ifdef __ASSEMBLY__
|
||||||
#define RISCV_PTR .word
|
#define RISCV_PTR .word
|
||||||
#define RISCV_SZPTR 4
|
#define RISCV_SZPTR 4
|
||||||
@@ -159,35 +157,30 @@ void csr_write_num(int csr_num, unsigned long val);
|
|||||||
__asm__ __volatile__("wfi" ::: "memory"); \
|
__asm__ __volatile__("wfi" ::: "memory"); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static inline int misa_extension(char ext)
|
/* Get current HART id */
|
||||||
{
|
#define current_hartid() ((unsigned int)csr_read(CSR_MHARTID))
|
||||||
return csr_read(CSR_MISA) & (1 << (ext - 'A'));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int misa_xlen(void)
|
/* determine CPU extension, return non-zero support */
|
||||||
{
|
int misa_extension_imp(char ext);
|
||||||
return ((long)csr_read(CSR_MISA) < 0) ? 64 : 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void misa_string(char *out, unsigned int out_sz)
|
#define misa_extension(c)\
|
||||||
{
|
({\
|
||||||
unsigned long i, val = csr_read(CSR_MISA);
|
_Static_assert(((c >= 'A') && (c <= 'Z')),\
|
||||||
|
"The parameter of misa_extension must be [A-Z]");\
|
||||||
|
misa_extension_imp(c);\
|
||||||
|
})
|
||||||
|
|
||||||
for (i = 0; i < 26; i++) {
|
/* Get MXL field of misa, return -1 on error */
|
||||||
if (val & (1 << i)) {
|
int misa_xlen(void);
|
||||||
*out = 'A' + i;
|
|
||||||
out++;
|
/* Get RISC-V ISA string representation */
|
||||||
}
|
void misa_string(int xlen, char *out, unsigned int out_sz);
|
||||||
}
|
|
||||||
*out = '\0';
|
|
||||||
out++;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
|
int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
|
||||||
unsigned long log2len);
|
unsigned long log2len);
|
||||||
|
|
||||||
int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
|
int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
|
||||||
unsigned long *log2len_out);
|
unsigned long *log2len);
|
||||||
|
|
||||||
#endif /* !__ASSEMBLY__ */
|
#endif /* !__ASSEMBLY__ */
|
||||||
|
|
||||||
|
@@ -29,12 +29,15 @@ long atomic_add_return(atomic_t *atom, long value);
|
|||||||
|
|
||||||
long atomic_sub_return(atomic_t *atom, long value);
|
long atomic_sub_return(atomic_t *atom, long value);
|
||||||
|
|
||||||
long arch_atomic_cmpxchg(atomic_t *atom, long oldval, long newval);
|
long atomic_cmpxchg(atomic_t *atom, long oldval, long newval);
|
||||||
|
|
||||||
long arch_atomic_xchg(atomic_t *atom, long newval);
|
long atomic_xchg(atomic_t *atom, long newval);
|
||||||
|
|
||||||
unsigned int atomic_raw_xchg_uint(volatile unsigned int *ptr,
|
unsigned int atomic_raw_xchg_uint(volatile unsigned int *ptr,
|
||||||
unsigned int newval);
|
unsigned int newval);
|
||||||
|
|
||||||
|
unsigned long atomic_raw_xchg_ulong(volatile unsigned long *ptr,
|
||||||
|
unsigned long newval);
|
||||||
/**
|
/**
|
||||||
* Set a bit in an atomic variable and return the new value.
|
* Set a bit in an atomic variable and return the new value.
|
||||||
* @nr : Bit to set.
|
* @nr : Bit to set.
|
||||||
|
@@ -12,202 +12,186 @@
|
|||||||
|
|
||||||
#include <sbi/sbi_const.h>
|
#include <sbi/sbi_const.h>
|
||||||
|
|
||||||
/* TODO: Make constants usable in assembly with _AC() macro */
|
|
||||||
|
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
#define MSTATUS_UIE 0x00000001
|
#define MSTATUS_SIE _UL(0x00000002)
|
||||||
#define MSTATUS_SIE 0x00000002
|
#define MSTATUS_MIE _UL(0x00000008)
|
||||||
#define MSTATUS_HIE 0x00000004
|
|
||||||
#define MSTATUS_MIE 0x00000008
|
|
||||||
#define MSTATUS_UPIE 0x00000010
|
|
||||||
#define MSTATUS_SPIE_SHIFT 5
|
#define MSTATUS_SPIE_SHIFT 5
|
||||||
#define MSTATUS_SPIE (1UL << MSTATUS_SPIE_SHIFT)
|
#define MSTATUS_SPIE (_UL(1) << MSTATUS_SPIE_SHIFT)
|
||||||
#define MSTATUS_HPIE 0x00000040
|
#define MSTATUS_UBE _UL(0x00000040)
|
||||||
#define MSTATUS_MPIE 0x00000080
|
#define MSTATUS_MPIE _UL(0x00000080)
|
||||||
#define MSTATUS_SPP_SHIFT 8
|
#define MSTATUS_SPP_SHIFT 8
|
||||||
#define MSTATUS_SPP (1UL << MSTATUS_SPP_SHIFT)
|
#define MSTATUS_SPP (_UL(1) << MSTATUS_SPP_SHIFT)
|
||||||
#define MSTATUS_HPP 0x00000600
|
|
||||||
#define MSTATUS_MPP_SHIFT 11
|
#define MSTATUS_MPP_SHIFT 11
|
||||||
#define MSTATUS_MPP (3UL << MSTATUS_MPP_SHIFT)
|
#define MSTATUS_MPP (_UL(3) << MSTATUS_MPP_SHIFT)
|
||||||
#define MSTATUS_FS 0x00006000
|
#define MSTATUS_FS _UL(0x00006000)
|
||||||
#define MSTATUS_XS 0x00018000
|
#define MSTATUS_XS _UL(0x00018000)
|
||||||
#define MSTATUS_MPRV 0x00020000
|
#define MSTATUS_VS _UL(0x01800000)
|
||||||
#define MSTATUS_SUM 0x00040000
|
#define MSTATUS_MPRV _UL(0x00020000)
|
||||||
#define MSTATUS_MXR 0x00080000
|
#define MSTATUS_SUM _UL(0x00040000)
|
||||||
#define MSTATUS_TVM 0x00100000
|
#define MSTATUS_MXR _UL(0x00080000)
|
||||||
#define MSTATUS_TW 0x00200000
|
#define MSTATUS_TVM _UL(0x00100000)
|
||||||
#define MSTATUS_TSR 0x00400000
|
#define MSTATUS_TW _UL(0x00200000)
|
||||||
#define MSTATUS32_SD 0x80000000
|
#define MSTATUS_TSR _UL(0x00400000)
|
||||||
#define MSTATUS_UXL 0x0000000300000000
|
#define MSTATUS32_SD _UL(0x80000000)
|
||||||
#define MSTATUS_SXL 0x0000000C00000000
|
#if __riscv_xlen == 64
|
||||||
#define MSTATUS64_SD 0x8000000000000000
|
#define MSTATUS_UXL _ULL(0x0000000300000000)
|
||||||
|
#define MSTATUS_SXL _ULL(0x0000000C00000000)
|
||||||
|
#define MSTATUS_SBE _ULL(0x0000001000000000)
|
||||||
|
#define MSTATUS_MBE _ULL(0x0000002000000000)
|
||||||
|
#define MSTATUS_MPV _ULL(0x0000008000000000)
|
||||||
|
#else
|
||||||
|
#define MSTATUSH_SBE _UL(0x00000010)
|
||||||
|
#define MSTATUSH_MBE _UL(0x00000020)
|
||||||
|
#define MSTATUSH_MPV _UL(0x00000080)
|
||||||
|
#endif
|
||||||
|
#define MSTATUS32_SD _UL(0x80000000)
|
||||||
|
#define MSTATUS64_SD _ULL(0x8000000000000000)
|
||||||
|
|
||||||
#define SSTATUS_UIE 0x00000001
|
#define SSTATUS_SIE MSTATUS_SIE
|
||||||
#define SSTATUS_SIE 0x00000002
|
#define SSTATUS_SPIE_SHIFT MSTATUS_SPIE_SHIFT
|
||||||
#define SSTATUS_UPIE 0x00000010
|
#define SSTATUS_SPIE MSTATUS_SPIE
|
||||||
#define SSTATUS_SPIE 0x00000020
|
#define SSTATUS_SPP_SHIFT MSTATUS_SPP_SHIFT
|
||||||
#define SSTATUS_SPP 0x00000100
|
#define SSTATUS_SPP MSTATUS_SPP
|
||||||
#define SSTATUS_FS 0x00006000
|
#define SSTATUS_FS MSTATUS_FS
|
||||||
#define SSTATUS_XS 0x00018000
|
#define SSTATUS_XS MSTATUS_XS
|
||||||
#define SSTATUS_SUM 0x00040000
|
#define SSTATUS_VS MSTATUS_VS
|
||||||
#define SSTATUS_MXR 0x00080000
|
#define SSTATUS_SUM MSTATUS_SUM
|
||||||
#define SSTATUS32_SD 0x80000000
|
#define SSTATUS_MXR MSTATUS_MXR
|
||||||
#define SSTATUS_UXL 0x0000000300000000
|
#define SSTATUS32_SD MSTATUS32_SD
|
||||||
#define SSTATUS64_SD 0x8000000000000000
|
#define SSTATUS64_UXL MSTATUS_UXL
|
||||||
|
#define SSTATUS64_SD MSTATUS64_SD
|
||||||
|
|
||||||
#define DCSR_XDEBUGVER (3U<<30)
|
#if __riscv_xlen == 64
|
||||||
#define DCSR_NDRESET (1<<29)
|
#define HSTATUS_VSXL _UL(0x300000000)
|
||||||
#define DCSR_FULLRESET (1<<28)
|
#define HSTATUS_VSXL_SHIFT 32
|
||||||
#define DCSR_EBREAKM (1<<15)
|
#endif
|
||||||
#define DCSR_EBREAKH (1<<14)
|
#define HSTATUS_VTSR _UL(0x00400000)
|
||||||
#define DCSR_EBREAKS (1<<13)
|
#define HSTATUS_VTW _UL(0x00200000)
|
||||||
#define DCSR_EBREAKU (1<<12)
|
#define HSTATUS_VTVM _UL(0x00100000)
|
||||||
#define DCSR_STOPCYCLE (1<<10)
|
#define HSTATUS_VGEIN _UL(0x0003f000)
|
||||||
#define DCSR_STOPTIME (1<<9)
|
#define HSTATUS_VGEIN_SHIFT 12
|
||||||
#define DCSR_CAUSE (7<<6)
|
#define HSTATUS_HU _UL(0x00000200)
|
||||||
#define DCSR_DEBUGINT (1<<5)
|
#define HSTATUS_SPVP _UL(0x00000100)
|
||||||
#define DCSR_HALT (1<<3)
|
#define HSTATUS_SPV _UL(0x00000080)
|
||||||
#define DCSR_STEP (1<<2)
|
#define HSTATUS_GVA _UL(0x00000040)
|
||||||
#define DCSR_PRV (3<<0)
|
#define HSTATUS_VSBE _UL(0x00000020)
|
||||||
|
|
||||||
#define DCSR_CAUSE_NONE 0
|
|
||||||
#define DCSR_CAUSE_SWBP 1
|
|
||||||
#define DCSR_CAUSE_HWBP 2
|
|
||||||
#define DCSR_CAUSE_DEBUGINT 3
|
|
||||||
#define DCSR_CAUSE_STEP 4
|
|
||||||
#define DCSR_CAUSE_HALT 5
|
|
||||||
|
|
||||||
#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4))
|
|
||||||
#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5))
|
|
||||||
#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11))
|
|
||||||
|
|
||||||
#define MCONTROL_SELECT (1<<19)
|
|
||||||
#define MCONTROL_TIMING (1<<18)
|
|
||||||
#define MCONTROL_ACTION (0x3f<<12)
|
|
||||||
#define MCONTROL_CHAIN (1<<11)
|
|
||||||
#define MCONTROL_MATCH (0xf<<7)
|
|
||||||
#define MCONTROL_M (1<<6)
|
|
||||||
#define MCONTROL_H (1<<5)
|
|
||||||
#define MCONTROL_S (1<<4)
|
|
||||||
#define MCONTROL_U (1<<3)
|
|
||||||
#define MCONTROL_EXECUTE (1<<2)
|
|
||||||
#define MCONTROL_STORE (1<<1)
|
|
||||||
#define MCONTROL_LOAD (1<<0)
|
|
||||||
|
|
||||||
#define MCONTROL_TYPE_NONE 0
|
|
||||||
#define MCONTROL_TYPE_MATCH 2
|
|
||||||
|
|
||||||
#define MCONTROL_ACTION_DEBUG_EXCEPTION 0
|
|
||||||
#define MCONTROL_ACTION_DEBUG_MODE 1
|
|
||||||
#define MCONTROL_ACTION_TRACE_START 2
|
|
||||||
#define MCONTROL_ACTION_TRACE_STOP 3
|
|
||||||
#define MCONTROL_ACTION_TRACE_EMIT 4
|
|
||||||
|
|
||||||
#define MCONTROL_MATCH_EQUAL 0
|
|
||||||
#define MCONTROL_MATCH_NAPOT 1
|
|
||||||
#define MCONTROL_MATCH_GE 2
|
|
||||||
#define MCONTROL_MATCH_LT 3
|
|
||||||
#define MCONTROL_MATCH_MASK_LOW 4
|
|
||||||
#define MCONTROL_MATCH_MASK_HIGH 5
|
|
||||||
|
|
||||||
#define IRQ_S_SOFT 1
|
#define IRQ_S_SOFT 1
|
||||||
#define IRQ_H_SOFT 2
|
#define IRQ_VS_SOFT 2
|
||||||
#define IRQ_M_SOFT 3
|
#define IRQ_M_SOFT 3
|
||||||
#define IRQ_S_TIMER 5
|
#define IRQ_S_TIMER 5
|
||||||
#define IRQ_H_TIMER 6
|
#define IRQ_VS_TIMER 6
|
||||||
#define IRQ_M_TIMER 7
|
#define IRQ_M_TIMER 7
|
||||||
#define IRQ_S_EXT 9
|
#define IRQ_S_EXT 9
|
||||||
#define IRQ_H_EXT 10
|
#define IRQ_VS_EXT 10
|
||||||
#define IRQ_M_EXT 11
|
#define IRQ_M_EXT 11
|
||||||
#define IRQ_COP 12
|
#define IRQ_S_GEXT 12
|
||||||
#define IRQ_HOST 13
|
|
||||||
|
|
||||||
#define MIP_SSIP (1 << IRQ_S_SOFT)
|
#define MIP_SSIP (_UL(1) << IRQ_S_SOFT)
|
||||||
#define MIP_HSIP (1 << IRQ_H_SOFT)
|
#define MIP_VSSIP (_UL(1) << IRQ_VS_SOFT)
|
||||||
#define MIP_MSIP (1 << IRQ_M_SOFT)
|
#define MIP_MSIP (_UL(1) << IRQ_M_SOFT)
|
||||||
#define MIP_STIP (1 << IRQ_S_TIMER)
|
#define MIP_STIP (_UL(1) << IRQ_S_TIMER)
|
||||||
#define MIP_HTIP (1 << IRQ_H_TIMER)
|
#define MIP_VSTIP (_UL(1) << IRQ_VS_TIMER)
|
||||||
#define MIP_MTIP (1 << IRQ_M_TIMER)
|
#define MIP_MTIP (_UL(1) << IRQ_M_TIMER)
|
||||||
#define MIP_SEIP (1 << IRQ_S_EXT)
|
#define MIP_SEIP (_UL(1) << IRQ_S_EXT)
|
||||||
#define MIP_HEIP (1 << IRQ_H_EXT)
|
#define MIP_VSEIP (_UL(1) << IRQ_VS_EXT)
|
||||||
#define MIP_MEIP (1 << IRQ_M_EXT)
|
#define MIP_MEIP (_UL(1) << IRQ_M_EXT)
|
||||||
|
#define MIP_SGEIP (_UL(1) << IRQ_S_GEXT)
|
||||||
|
|
||||||
#define SIP_SSIP MIP_SSIP
|
#define SIP_SSIP MIP_SSIP
|
||||||
#define SIP_STIP MIP_STIP
|
#define SIP_STIP MIP_STIP
|
||||||
|
|
||||||
#define PRV_U 0
|
#define PRV_U _UL(0)
|
||||||
#define PRV_S 1
|
#define PRV_S _UL(1)
|
||||||
#define PRV_H 2
|
#define PRV_M _UL(3)
|
||||||
#define PRV_M 3
|
|
||||||
|
|
||||||
#define SATP32_MODE 0x80000000
|
#define SATP32_MODE _UL(0x80000000)
|
||||||
#define SATP32_ASID 0x7FC00000
|
#define SATP32_ASID _UL(0x7FC00000)
|
||||||
#define SATP32_PPN 0x003FFFFF
|
#define SATP32_PPN _UL(0x003FFFFF)
|
||||||
#define SATP64_MODE 0xF000000000000000
|
#define SATP64_MODE _ULL(0xF000000000000000)
|
||||||
#define SATP64_ASID 0x0FFFF00000000000
|
#define SATP64_ASID _ULL(0x0FFFF00000000000)
|
||||||
#define SATP64_PPN 0x00000FFFFFFFFFFF
|
#define SATP64_PPN _ULL(0x00000FFFFFFFFFFF)
|
||||||
|
|
||||||
#define SATP_MODE_OFF 0
|
#define SATP_MODE_OFF _UL(0)
|
||||||
#define SATP_MODE_SV32 1
|
#define SATP_MODE_SV32 _UL(1)
|
||||||
#define SATP_MODE_SV39 8
|
#define SATP_MODE_SV39 _UL(8)
|
||||||
#define SATP_MODE_SV48 9
|
#define SATP_MODE_SV48 _UL(9)
|
||||||
#define SATP_MODE_SV57 10
|
#define SATP_MODE_SV57 _UL(10)
|
||||||
#define SATP_MODE_SV64 11
|
#define SATP_MODE_SV64 _UL(11)
|
||||||
|
|
||||||
#define PMP_R 0x01
|
#define HGATP_MODE_OFF _UL(0)
|
||||||
#define PMP_W 0x02
|
#define HGATP_MODE_SV32X4 _UL(1)
|
||||||
#define PMP_X 0x04
|
#define HGATP_MODE_SV39X4 _UL(8)
|
||||||
#define PMP_A 0x18
|
#define HGATP_MODE_SV48X4 _UL(9)
|
||||||
#define PMP_A_TOR 0x08
|
|
||||||
#define PMP_A_NA4 0x10
|
#define HGATP32_MODE_SHIFT 31
|
||||||
#define PMP_A_NAPOT 0x18
|
#define HGATP32_VMID_SHIFT 22
|
||||||
#define PMP_L 0x80
|
#define HGATP32_VMID_MASK _UL(0x1FC00000)
|
||||||
|
#define HGATP32_PPN _UL(0x003FFFFF)
|
||||||
|
|
||||||
|
#define HGATP64_MODE_SHIFT 60
|
||||||
|
#define HGATP64_VMID_SHIFT 44
|
||||||
|
#define HGATP64_VMID_MASK _ULL(0x03FFF00000000000)
|
||||||
|
#define HGATP64_PPN _ULL(0x00000FFFFFFFFFFF)
|
||||||
|
|
||||||
|
#define PMP_R _UL(0x01)
|
||||||
|
#define PMP_W _UL(0x02)
|
||||||
|
#define PMP_X _UL(0x04)
|
||||||
|
#define PMP_A _UL(0x18)
|
||||||
|
#define PMP_A_TOR _UL(0x08)
|
||||||
|
#define PMP_A_NA4 _UL(0x10)
|
||||||
|
#define PMP_A_NAPOT _UL(0x18)
|
||||||
|
#define PMP_L _UL(0x80)
|
||||||
|
|
||||||
#define PMP_SHIFT 2
|
#define PMP_SHIFT 2
|
||||||
#define PMP_COUNT 16
|
#define PMP_COUNT 64
|
||||||
|
#if __riscv_xlen == 64
|
||||||
/* page table entry (PTE) fields */
|
#define PMP_ADDR_MASK ((_ULL(0x1) << 54) - 1)
|
||||||
#define PTE_V 0x001 /* Valid */
|
#else
|
||||||
#define PTE_R 0x002 /* Read */
|
#define PMP_ADDR_MASK _UL(0xFFFFFFFF)
|
||||||
#define PTE_W 0x004 /* Write */
|
#endif
|
||||||
#define PTE_X 0x008 /* Execute */
|
|
||||||
#define PTE_U 0x010 /* User */
|
|
||||||
#define PTE_G 0x020 /* Global */
|
|
||||||
#define PTE_A 0x040 /* Accessed */
|
|
||||||
#define PTE_D 0x080 /* Dirty */
|
|
||||||
#define PTE_SOFT 0x300 /* Reserved for Software */
|
|
||||||
|
|
||||||
#define PTE_PPN_SHIFT 10
|
|
||||||
|
|
||||||
#define PTE_TABLE(PTE) \
|
|
||||||
(((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V)
|
|
||||||
|
|
||||||
#if __riscv_xlen == 64
|
#if __riscv_xlen == 64
|
||||||
#define MSTATUS_SD MSTATUS64_SD
|
#define MSTATUS_SD MSTATUS64_SD
|
||||||
#define SSTATUS_SD SSTATUS64_SD
|
#define SSTATUS_SD SSTATUS64_SD
|
||||||
#define RISCV_PGLEVEL_BITS 9
|
|
||||||
#define SATP_MODE SATP64_MODE
|
#define SATP_MODE SATP64_MODE
|
||||||
|
|
||||||
|
#define HGATP_PPN HGATP64_PPN
|
||||||
|
#define HGATP_VMID_SHIFT HGATP64_VMID_SHIFT
|
||||||
|
#define HGATP_VMID_MASK HGATP64_VMID_MASK
|
||||||
|
#define HGATP_MODE_SHIFT HGATP64_MODE_SHIFT
|
||||||
#else
|
#else
|
||||||
#define MSTATUS_SD MSTATUS32_SD
|
#define MSTATUS_SD MSTATUS32_SD
|
||||||
#define SSTATUS_SD SSTATUS32_SD
|
#define SSTATUS_SD SSTATUS32_SD
|
||||||
#define RISCV_PGLEVEL_BITS 10
|
|
||||||
#define SATP_MODE SATP32_MODE
|
#define SATP_MODE SATP32_MODE
|
||||||
#endif
|
|
||||||
#define RISCV_PGSHIFT 12
|
|
||||||
#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)
|
|
||||||
|
|
||||||
#define CSR_USTATUS 0x0
|
#define HGATP_PPN HGATP32_PPN
|
||||||
#define CSR_FFLAGS 0x1
|
#define HGATP_VMID_SHIFT HGATP32_VMID_SHIFT
|
||||||
#define CSR_FRM 0x2
|
#define HGATP_VMID_MASK HGATP32_VMID_MASK
|
||||||
#define CSR_FCSR 0x3
|
#define HGATP_MODE_SHIFT HGATP32_MODE_SHIFT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ===== User-level CSRs ===== */
|
||||||
|
|
||||||
|
/* User Trap Setup (N-extension) */
|
||||||
|
#define CSR_USTATUS 0x000
|
||||||
|
#define CSR_UIE 0x004
|
||||||
|
#define CSR_UTVEC 0x005
|
||||||
|
|
||||||
|
/* User Trap Handling (N-extension) */
|
||||||
|
#define CSR_USCRATCH 0x040
|
||||||
|
#define CSR_UEPC 0x041
|
||||||
|
#define CSR_UCAUSE 0x042
|
||||||
|
#define CSR_UTVAL 0x043
|
||||||
|
#define CSR_UIP 0x044
|
||||||
|
|
||||||
|
/* User Floating-point CSRs */
|
||||||
|
#define CSR_FFLAGS 0x001
|
||||||
|
#define CSR_FRM 0x002
|
||||||
|
#define CSR_FCSR 0x003
|
||||||
|
|
||||||
|
/* User Counters/Timers */
|
||||||
#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
|
||||||
@@ -239,119 +223,6 @@
|
|||||||
#define CSR_HPMCOUNTER29 0xc1d
|
#define CSR_HPMCOUNTER29 0xc1d
|
||||||
#define CSR_HPMCOUNTER30 0xc1e
|
#define CSR_HPMCOUNTER30 0xc1e
|
||||||
#define CSR_HPMCOUNTER31 0xc1f
|
#define CSR_HPMCOUNTER31 0xc1f
|
||||||
#define CSR_SSTATUS 0x100
|
|
||||||
#define CSR_SIE 0x104
|
|
||||||
#define CSR_STVEC 0x105
|
|
||||||
#define CSR_SCOUNTEREN 0x106
|
|
||||||
#define CSR_SSCRATCH 0x140
|
|
||||||
#define CSR_SEPC 0x141
|
|
||||||
#define CSR_SCAUSE 0x142
|
|
||||||
#define CSR_STVAL 0x143
|
|
||||||
#define CSR_SIP 0x144
|
|
||||||
#define CSR_SATP 0x180
|
|
||||||
#define CSR_MSTATUS 0x300
|
|
||||||
#define CSR_MISA 0x301
|
|
||||||
#define CSR_MEDELEG 0x302
|
|
||||||
#define CSR_MIDELEG 0x303
|
|
||||||
#define CSR_MIE 0x304
|
|
||||||
#define CSR_MTVEC 0x305
|
|
||||||
#define CSR_MCOUNTEREN 0x306
|
|
||||||
#define CSR_MSCRATCH 0x340
|
|
||||||
#define CSR_MEPC 0x341
|
|
||||||
#define CSR_MCAUSE 0x342
|
|
||||||
#define CSR_MTVAL 0x343
|
|
||||||
#define CSR_MIP 0x344
|
|
||||||
#define CSR_PMPCFG0 0x3a0
|
|
||||||
#define CSR_PMPCFG1 0x3a1
|
|
||||||
#define CSR_PMPCFG2 0x3a2
|
|
||||||
#define CSR_PMPCFG3 0x3a3
|
|
||||||
#define CSR_PMPADDR0 0x3b0
|
|
||||||
#define CSR_PMPADDR1 0x3b1
|
|
||||||
#define CSR_PMPADDR2 0x3b2
|
|
||||||
#define CSR_PMPADDR3 0x3b3
|
|
||||||
#define CSR_PMPADDR4 0x3b4
|
|
||||||
#define CSR_PMPADDR5 0x3b5
|
|
||||||
#define CSR_PMPADDR6 0x3b6
|
|
||||||
#define CSR_PMPADDR7 0x3b7
|
|
||||||
#define CSR_PMPADDR8 0x3b8
|
|
||||||
#define CSR_PMPADDR9 0x3b9
|
|
||||||
#define CSR_PMPADDR10 0x3ba
|
|
||||||
#define CSR_PMPADDR11 0x3bb
|
|
||||||
#define CSR_PMPADDR12 0x3bc
|
|
||||||
#define CSR_PMPADDR13 0x3bd
|
|
||||||
#define CSR_PMPADDR14 0x3be
|
|
||||||
#define CSR_PMPADDR15 0x3bf
|
|
||||||
#define CSR_TSELECT 0x7a0
|
|
||||||
#define CSR_TDATA1 0x7a1
|
|
||||||
#define CSR_TDATA2 0x7a2
|
|
||||||
#define CSR_TDATA3 0x7a3
|
|
||||||
#define CSR_DCSR 0x7b0
|
|
||||||
#define CSR_DPC 0x7b1
|
|
||||||
#define CSR_DSCRATCH 0x7b2
|
|
||||||
#define CSR_MCYCLE 0xb00
|
|
||||||
#define CSR_MINSTRET 0xb02
|
|
||||||
#define CSR_MHPMCOUNTER3 0xb03
|
|
||||||
#define CSR_MHPMCOUNTER4 0xb04
|
|
||||||
#define CSR_MHPMCOUNTER5 0xb05
|
|
||||||
#define CSR_MHPMCOUNTER6 0xb06
|
|
||||||
#define CSR_MHPMCOUNTER7 0xb07
|
|
||||||
#define CSR_MHPMCOUNTER8 0xb08
|
|
||||||
#define CSR_MHPMCOUNTER9 0xb09
|
|
||||||
#define CSR_MHPMCOUNTER10 0xb0a
|
|
||||||
#define CSR_MHPMCOUNTER11 0xb0b
|
|
||||||
#define CSR_MHPMCOUNTER12 0xb0c
|
|
||||||
#define CSR_MHPMCOUNTER13 0xb0d
|
|
||||||
#define CSR_MHPMCOUNTER14 0xb0e
|
|
||||||
#define CSR_MHPMCOUNTER15 0xb0f
|
|
||||||
#define CSR_MHPMCOUNTER16 0xb10
|
|
||||||
#define CSR_MHPMCOUNTER17 0xb11
|
|
||||||
#define CSR_MHPMCOUNTER18 0xb12
|
|
||||||
#define CSR_MHPMCOUNTER19 0xb13
|
|
||||||
#define CSR_MHPMCOUNTER20 0xb14
|
|
||||||
#define CSR_MHPMCOUNTER21 0xb15
|
|
||||||
#define CSR_MHPMCOUNTER22 0xb16
|
|
||||||
#define CSR_MHPMCOUNTER23 0xb17
|
|
||||||
#define CSR_MHPMCOUNTER24 0xb18
|
|
||||||
#define CSR_MHPMCOUNTER25 0xb19
|
|
||||||
#define CSR_MHPMCOUNTER26 0xb1a
|
|
||||||
#define CSR_MHPMCOUNTER27 0xb1b
|
|
||||||
#define CSR_MHPMCOUNTER28 0xb1c
|
|
||||||
#define CSR_MHPMCOUNTER29 0xb1d
|
|
||||||
#define CSR_MHPMCOUNTER30 0xb1e
|
|
||||||
#define CSR_MHPMCOUNTER31 0xb1f
|
|
||||||
#define CSR_MHPMEVENT3 0x323
|
|
||||||
#define CSR_MHPMEVENT4 0x324
|
|
||||||
#define CSR_MHPMEVENT5 0x325
|
|
||||||
#define CSR_MHPMEVENT6 0x326
|
|
||||||
#define CSR_MHPMEVENT7 0x327
|
|
||||||
#define CSR_MHPMEVENT8 0x328
|
|
||||||
#define CSR_MHPMEVENT9 0x329
|
|
||||||
#define CSR_MHPMEVENT10 0x32a
|
|
||||||
#define CSR_MHPMEVENT11 0x32b
|
|
||||||
#define CSR_MHPMEVENT12 0x32c
|
|
||||||
#define CSR_MHPMEVENT13 0x32d
|
|
||||||
#define CSR_MHPMEVENT14 0x32e
|
|
||||||
#define CSR_MHPMEVENT15 0x32f
|
|
||||||
#define CSR_MHPMEVENT16 0x330
|
|
||||||
#define CSR_MHPMEVENT17 0x331
|
|
||||||
#define CSR_MHPMEVENT18 0x332
|
|
||||||
#define CSR_MHPMEVENT19 0x333
|
|
||||||
#define CSR_MHPMEVENT20 0x334
|
|
||||||
#define CSR_MHPMEVENT21 0x335
|
|
||||||
#define CSR_MHPMEVENT22 0x336
|
|
||||||
#define CSR_MHPMEVENT23 0x337
|
|
||||||
#define CSR_MHPMEVENT24 0x338
|
|
||||||
#define CSR_MHPMEVENT25 0x339
|
|
||||||
#define CSR_MHPMEVENT26 0x33a
|
|
||||||
#define CSR_MHPMEVENT27 0x33b
|
|
||||||
#define CSR_MHPMEVENT28 0x33c
|
|
||||||
#define CSR_MHPMEVENT29 0x33d
|
|
||||||
#define CSR_MHPMEVENT30 0x33e
|
|
||||||
#define CSR_MHPMEVENT31 0x33f
|
|
||||||
#define CSR_MVENDORID 0xf11
|
|
||||||
#define CSR_MARCHID 0xf12
|
|
||||||
#define CSR_MIMPID 0xf13
|
|
||||||
#define CSR_MHARTID 0xf14
|
|
||||||
#define CSR_CYCLEH 0xc80
|
#define CSR_CYCLEH 0xc80
|
||||||
#define CSR_TIMEH 0xc81
|
#define CSR_TIMEH 0xc81
|
||||||
#define CSR_INSTRETH 0xc82
|
#define CSR_INSTRETH 0xc82
|
||||||
@@ -384,6 +255,203 @@
|
|||||||
#define CSR_HPMCOUNTER29H 0xc9d
|
#define CSR_HPMCOUNTER29H 0xc9d
|
||||||
#define CSR_HPMCOUNTER30H 0xc9e
|
#define CSR_HPMCOUNTER30H 0xc9e
|
||||||
#define CSR_HPMCOUNTER31H 0xc9f
|
#define CSR_HPMCOUNTER31H 0xc9f
|
||||||
|
|
||||||
|
/* ===== Supervisor-level CSRs ===== */
|
||||||
|
|
||||||
|
/* Supervisor Trap Setup */
|
||||||
|
#define CSR_SSTATUS 0x100
|
||||||
|
#define CSR_SEDELEG 0x102
|
||||||
|
#define CSR_SIDELEG 0x103
|
||||||
|
#define CSR_SIE 0x104
|
||||||
|
#define CSR_STVEC 0x105
|
||||||
|
#define CSR_SCOUNTEREN 0x106
|
||||||
|
|
||||||
|
/* Supervisor Trap Handling */
|
||||||
|
#define CSR_SSCRATCH 0x140
|
||||||
|
#define CSR_SEPC 0x141
|
||||||
|
#define CSR_SCAUSE 0x142
|
||||||
|
#define CSR_STVAL 0x143
|
||||||
|
#define CSR_SIP 0x144
|
||||||
|
|
||||||
|
/* Supervisor Protection and Translation */
|
||||||
|
#define CSR_SATP 0x180
|
||||||
|
|
||||||
|
/* ===== Hypervisor-level CSRs ===== */
|
||||||
|
|
||||||
|
/* Hypervisor Trap Setup (H-extension) */
|
||||||
|
#define CSR_HSTATUS 0x600
|
||||||
|
#define CSR_HEDELEG 0x602
|
||||||
|
#define CSR_HIDELEG 0x603
|
||||||
|
#define CSR_HIE 0x604
|
||||||
|
#define CSR_HCOUNTEREN 0x606
|
||||||
|
#define CSR_HGEIE 0x607
|
||||||
|
|
||||||
|
/* Hypervisor Trap Handling (H-extension) */
|
||||||
|
#define CSR_HTVAL 0x643
|
||||||
|
#define CSR_HIP 0x644
|
||||||
|
#define CSR_HVIP 0x645
|
||||||
|
#define CSR_HTINST 0x64a
|
||||||
|
#define CSR_HGEIP 0xe12
|
||||||
|
|
||||||
|
/* Hypervisor Protection and Translation (H-extension) */
|
||||||
|
#define CSR_HGATP 0x680
|
||||||
|
|
||||||
|
/* Hypervisor Counter/Timer Virtualization Registers (H-extension) */
|
||||||
|
#define CSR_HTIMEDELTA 0x605
|
||||||
|
#define CSR_HTIMEDELTAH 0x615
|
||||||
|
|
||||||
|
/* Virtual Supervisor Registers (H-extension) */
|
||||||
|
#define CSR_VSSTATUS 0x200
|
||||||
|
#define CSR_VSIE 0x204
|
||||||
|
#define CSR_VSTVEC 0x205
|
||||||
|
#define CSR_VSSCRATCH 0x240
|
||||||
|
#define CSR_VSEPC 0x241
|
||||||
|
#define CSR_VSCAUSE 0x242
|
||||||
|
#define CSR_VSTVAL 0x243
|
||||||
|
#define CSR_VSIP 0x244
|
||||||
|
#define CSR_VSATP 0x280
|
||||||
|
|
||||||
|
/* ===== Machine-level CSRs ===== */
|
||||||
|
|
||||||
|
/* Machine Information Registers */
|
||||||
|
#define CSR_MVENDORID 0xf11
|
||||||
|
#define CSR_MARCHID 0xf12
|
||||||
|
#define CSR_MIMPID 0xf13
|
||||||
|
#define CSR_MHARTID 0xf14
|
||||||
|
|
||||||
|
/* Machine Trap Setup */
|
||||||
|
#define CSR_MSTATUS 0x300
|
||||||
|
#define CSR_MISA 0x301
|
||||||
|
#define CSR_MEDELEG 0x302
|
||||||
|
#define CSR_MIDELEG 0x303
|
||||||
|
#define CSR_MIE 0x304
|
||||||
|
#define CSR_MTVEC 0x305
|
||||||
|
#define CSR_MCOUNTEREN 0x306
|
||||||
|
#define CSR_MSTATUSH 0x310
|
||||||
|
|
||||||
|
/* Machine Trap Handling */
|
||||||
|
#define CSR_MSCRATCH 0x340
|
||||||
|
#define CSR_MEPC 0x341
|
||||||
|
#define CSR_MCAUSE 0x342
|
||||||
|
#define CSR_MTVAL 0x343
|
||||||
|
#define CSR_MIP 0x344
|
||||||
|
#define CSR_MTINST 0x34a
|
||||||
|
#define CSR_MTVAL2 0x34b
|
||||||
|
|
||||||
|
/* Machine Memory Protection */
|
||||||
|
#define CSR_PMPCFG0 0x3a0
|
||||||
|
#define CSR_PMPCFG1 0x3a1
|
||||||
|
#define CSR_PMPCFG2 0x3a2
|
||||||
|
#define CSR_PMPCFG3 0x3a3
|
||||||
|
#define CSR_PMPCFG4 0x3a4
|
||||||
|
#define CSR_PMPCFG5 0x3a5
|
||||||
|
#define CSR_PMPCFG6 0x3a6
|
||||||
|
#define CSR_PMPCFG7 0x3a7
|
||||||
|
#define CSR_PMPCFG8 0x3a8
|
||||||
|
#define CSR_PMPCFG9 0x3a9
|
||||||
|
#define CSR_PMPCFG10 0x3aa
|
||||||
|
#define CSR_PMPCFG11 0x3ab
|
||||||
|
#define CSR_PMPCFG12 0x3ac
|
||||||
|
#define CSR_PMPCFG13 0x3ad
|
||||||
|
#define CSR_PMPCFG14 0x3ae
|
||||||
|
#define CSR_PMPCFG15 0x3af
|
||||||
|
#define CSR_PMPADDR0 0x3b0
|
||||||
|
#define CSR_PMPADDR1 0x3b1
|
||||||
|
#define CSR_PMPADDR2 0x3b2
|
||||||
|
#define CSR_PMPADDR3 0x3b3
|
||||||
|
#define CSR_PMPADDR4 0x3b4
|
||||||
|
#define CSR_PMPADDR5 0x3b5
|
||||||
|
#define CSR_PMPADDR6 0x3b6
|
||||||
|
#define CSR_PMPADDR7 0x3b7
|
||||||
|
#define CSR_PMPADDR8 0x3b8
|
||||||
|
#define CSR_PMPADDR9 0x3b9
|
||||||
|
#define CSR_PMPADDR10 0x3ba
|
||||||
|
#define CSR_PMPADDR11 0x3bb
|
||||||
|
#define CSR_PMPADDR12 0x3bc
|
||||||
|
#define CSR_PMPADDR13 0x3bd
|
||||||
|
#define CSR_PMPADDR14 0x3be
|
||||||
|
#define CSR_PMPADDR15 0x3bf
|
||||||
|
#define CSR_PMPADDR16 0x3c0
|
||||||
|
#define CSR_PMPADDR17 0x3c1
|
||||||
|
#define CSR_PMPADDR18 0x3c2
|
||||||
|
#define CSR_PMPADDR19 0x3c3
|
||||||
|
#define CSR_PMPADDR20 0x3c4
|
||||||
|
#define CSR_PMPADDR21 0x3c5
|
||||||
|
#define CSR_PMPADDR22 0x3c6
|
||||||
|
#define CSR_PMPADDR23 0x3c7
|
||||||
|
#define CSR_PMPADDR24 0x3c8
|
||||||
|
#define CSR_PMPADDR25 0x3c9
|
||||||
|
#define CSR_PMPADDR26 0x3ca
|
||||||
|
#define CSR_PMPADDR27 0x3cb
|
||||||
|
#define CSR_PMPADDR28 0x3cc
|
||||||
|
#define CSR_PMPADDR29 0x3cd
|
||||||
|
#define CSR_PMPADDR30 0x3ce
|
||||||
|
#define CSR_PMPADDR31 0x3cf
|
||||||
|
#define CSR_PMPADDR32 0x3d0
|
||||||
|
#define CSR_PMPADDR33 0x3d1
|
||||||
|
#define CSR_PMPADDR34 0x3d2
|
||||||
|
#define CSR_PMPADDR35 0x3d3
|
||||||
|
#define CSR_PMPADDR36 0x3d4
|
||||||
|
#define CSR_PMPADDR37 0x3d5
|
||||||
|
#define CSR_PMPADDR38 0x3d6
|
||||||
|
#define CSR_PMPADDR39 0x3d7
|
||||||
|
#define CSR_PMPADDR40 0x3d8
|
||||||
|
#define CSR_PMPADDR41 0x3d9
|
||||||
|
#define CSR_PMPADDR42 0x3da
|
||||||
|
#define CSR_PMPADDR43 0x3db
|
||||||
|
#define CSR_PMPADDR44 0x3dc
|
||||||
|
#define CSR_PMPADDR45 0x3dd
|
||||||
|
#define CSR_PMPADDR46 0x3de
|
||||||
|
#define CSR_PMPADDR47 0x3df
|
||||||
|
#define CSR_PMPADDR48 0x3e0
|
||||||
|
#define CSR_PMPADDR49 0x3e1
|
||||||
|
#define CSR_PMPADDR50 0x3e2
|
||||||
|
#define CSR_PMPADDR51 0x3e3
|
||||||
|
#define CSR_PMPADDR52 0x3e4
|
||||||
|
#define CSR_PMPADDR53 0x3e5
|
||||||
|
#define CSR_PMPADDR54 0x3e6
|
||||||
|
#define CSR_PMPADDR55 0x3e7
|
||||||
|
#define CSR_PMPADDR56 0x3e8
|
||||||
|
#define CSR_PMPADDR57 0x3e9
|
||||||
|
#define CSR_PMPADDR58 0x3ea
|
||||||
|
#define CSR_PMPADDR59 0x3eb
|
||||||
|
#define CSR_PMPADDR60 0x3ec
|
||||||
|
#define CSR_PMPADDR61 0x3ed
|
||||||
|
#define CSR_PMPADDR62 0x3ee
|
||||||
|
#define CSR_PMPADDR63 0x3ef
|
||||||
|
|
||||||
|
/* Machine Counters/Timers */
|
||||||
|
#define CSR_MCYCLE 0xb00
|
||||||
|
#define CSR_MINSTRET 0xb02
|
||||||
|
#define CSR_MHPMCOUNTER3 0xb03
|
||||||
|
#define CSR_MHPMCOUNTER4 0xb04
|
||||||
|
#define CSR_MHPMCOUNTER5 0xb05
|
||||||
|
#define CSR_MHPMCOUNTER6 0xb06
|
||||||
|
#define CSR_MHPMCOUNTER7 0xb07
|
||||||
|
#define CSR_MHPMCOUNTER8 0xb08
|
||||||
|
#define CSR_MHPMCOUNTER9 0xb09
|
||||||
|
#define CSR_MHPMCOUNTER10 0xb0a
|
||||||
|
#define CSR_MHPMCOUNTER11 0xb0b
|
||||||
|
#define CSR_MHPMCOUNTER12 0xb0c
|
||||||
|
#define CSR_MHPMCOUNTER13 0xb0d
|
||||||
|
#define CSR_MHPMCOUNTER14 0xb0e
|
||||||
|
#define CSR_MHPMCOUNTER15 0xb0f
|
||||||
|
#define CSR_MHPMCOUNTER16 0xb10
|
||||||
|
#define CSR_MHPMCOUNTER17 0xb11
|
||||||
|
#define CSR_MHPMCOUNTER18 0xb12
|
||||||
|
#define CSR_MHPMCOUNTER19 0xb13
|
||||||
|
#define CSR_MHPMCOUNTER20 0xb14
|
||||||
|
#define CSR_MHPMCOUNTER21 0xb15
|
||||||
|
#define CSR_MHPMCOUNTER22 0xb16
|
||||||
|
#define CSR_MHPMCOUNTER23 0xb17
|
||||||
|
#define CSR_MHPMCOUNTER24 0xb18
|
||||||
|
#define CSR_MHPMCOUNTER25 0xb19
|
||||||
|
#define CSR_MHPMCOUNTER26 0xb1a
|
||||||
|
#define CSR_MHPMCOUNTER27 0xb1b
|
||||||
|
#define CSR_MHPMCOUNTER28 0xb1c
|
||||||
|
#define CSR_MHPMCOUNTER29 0xb1d
|
||||||
|
#define CSR_MHPMCOUNTER30 0xb1e
|
||||||
|
#define CSR_MHPMCOUNTER31 0xb1f
|
||||||
#define CSR_MCYCLEH 0xb80
|
#define CSR_MCYCLEH 0xb80
|
||||||
#define CSR_MINSTRETH 0xb82
|
#define CSR_MINSTRETH 0xb82
|
||||||
#define CSR_MHPMCOUNTER3H 0xb83
|
#define CSR_MHPMCOUNTER3H 0xb83
|
||||||
@@ -416,6 +484,52 @@
|
|||||||
#define CSR_MHPMCOUNTER30H 0xb9e
|
#define CSR_MHPMCOUNTER30H 0xb9e
|
||||||
#define CSR_MHPMCOUNTER31H 0xb9f
|
#define CSR_MHPMCOUNTER31H 0xb9f
|
||||||
|
|
||||||
|
/* Machine Counter Setup */
|
||||||
|
#define CSR_MCOUNTINHIBIT 0x320
|
||||||
|
#define CSR_MHPMEVENT3 0x323
|
||||||
|
#define CSR_MHPMEVENT4 0x324
|
||||||
|
#define CSR_MHPMEVENT5 0x325
|
||||||
|
#define CSR_MHPMEVENT6 0x326
|
||||||
|
#define CSR_MHPMEVENT7 0x327
|
||||||
|
#define CSR_MHPMEVENT8 0x328
|
||||||
|
#define CSR_MHPMEVENT9 0x329
|
||||||
|
#define CSR_MHPMEVENT10 0x32a
|
||||||
|
#define CSR_MHPMEVENT11 0x32b
|
||||||
|
#define CSR_MHPMEVENT12 0x32c
|
||||||
|
#define CSR_MHPMEVENT13 0x32d
|
||||||
|
#define CSR_MHPMEVENT14 0x32e
|
||||||
|
#define CSR_MHPMEVENT15 0x32f
|
||||||
|
#define CSR_MHPMEVENT16 0x330
|
||||||
|
#define CSR_MHPMEVENT17 0x331
|
||||||
|
#define CSR_MHPMEVENT18 0x332
|
||||||
|
#define CSR_MHPMEVENT19 0x333
|
||||||
|
#define CSR_MHPMEVENT20 0x334
|
||||||
|
#define CSR_MHPMEVENT21 0x335
|
||||||
|
#define CSR_MHPMEVENT22 0x336
|
||||||
|
#define CSR_MHPMEVENT23 0x337
|
||||||
|
#define CSR_MHPMEVENT24 0x338
|
||||||
|
#define CSR_MHPMEVENT25 0x339
|
||||||
|
#define CSR_MHPMEVENT26 0x33a
|
||||||
|
#define CSR_MHPMEVENT27 0x33b
|
||||||
|
#define CSR_MHPMEVENT28 0x33c
|
||||||
|
#define CSR_MHPMEVENT29 0x33d
|
||||||
|
#define CSR_MHPMEVENT30 0x33e
|
||||||
|
#define CSR_MHPMEVENT31 0x33f
|
||||||
|
|
||||||
|
/* Debug/Trace Registers */
|
||||||
|
#define CSR_TSELECT 0x7a0
|
||||||
|
#define CSR_TDATA1 0x7a1
|
||||||
|
#define CSR_TDATA2 0x7a2
|
||||||
|
#define CSR_TDATA3 0x7a3
|
||||||
|
|
||||||
|
/* Debug Mode Registers */
|
||||||
|
#define CSR_DCSR 0x7b0
|
||||||
|
#define CSR_DPC 0x7b1
|
||||||
|
#define CSR_DSCRATCH0 0x7b2
|
||||||
|
#define CSR_DSCRATCH1 0x7b3
|
||||||
|
|
||||||
|
/* ===== Trap/Exception Causes ===== */
|
||||||
|
|
||||||
#define CAUSE_MISALIGNED_FETCH 0x0
|
#define CAUSE_MISALIGNED_FETCH 0x0
|
||||||
#define CAUSE_FETCH_ACCESS 0x1
|
#define CAUSE_FETCH_ACCESS 0x1
|
||||||
#define CAUSE_ILLEGAL_INSTRUCTION 0x2
|
#define CAUSE_ILLEGAL_INSTRUCTION 0x2
|
||||||
@@ -425,12 +539,18 @@
|
|||||||
#define CAUSE_MISALIGNED_STORE 0x6
|
#define CAUSE_MISALIGNED_STORE 0x6
|
||||||
#define CAUSE_STORE_ACCESS 0x7
|
#define CAUSE_STORE_ACCESS 0x7
|
||||||
#define CAUSE_USER_ECALL 0x8
|
#define CAUSE_USER_ECALL 0x8
|
||||||
#define CAUSE_HYPERVISOR_ECALL 0x9
|
#define CAUSE_SUPERVISOR_ECALL 0x9
|
||||||
#define CAUSE_SUPERVISOR_ECALL 0xa
|
#define CAUSE_VIRTUAL_SUPERVISOR_ECALL 0xa
|
||||||
#define CAUSE_MACHINE_ECALL 0xb
|
#define CAUSE_MACHINE_ECALL 0xb
|
||||||
#define CAUSE_FETCH_PAGE_FAULT 0xc
|
#define CAUSE_FETCH_PAGE_FAULT 0xc
|
||||||
#define CAUSE_LOAD_PAGE_FAULT 0xd
|
#define CAUSE_LOAD_PAGE_FAULT 0xd
|
||||||
#define CAUSE_STORE_PAGE_FAULT 0xf
|
#define CAUSE_STORE_PAGE_FAULT 0xf
|
||||||
|
#define CAUSE_FETCH_GUEST_PAGE_FAULT 0x14
|
||||||
|
#define CAUSE_LOAD_GUEST_PAGE_FAULT 0x15
|
||||||
|
#define CAUSE_VIRTUAL_INST_FAULT 0x16
|
||||||
|
#define CAUSE_STORE_GUEST_PAGE_FAULT 0x17
|
||||||
|
|
||||||
|
/* ===== Instruction Encodings ===== */
|
||||||
|
|
||||||
#define INSN_MATCH_LB 0x3
|
#define INSN_MATCH_LB 0x3
|
||||||
#define INSN_MASK_LB 0x707f
|
#define INSN_MASK_LB 0x707f
|
||||||
@@ -502,7 +622,19 @@
|
|||||||
#define INSN_MATCH_C_FSWSP 0xe002
|
#define INSN_MATCH_C_FSWSP 0xe002
|
||||||
#define INSN_MASK_C_FSWSP 0xe003
|
#define INSN_MASK_C_FSWSP 0xe003
|
||||||
|
|
||||||
#define INSN_LEN(insn) ((((insn) & 0x3) < 0x3) ? 2 : 4)
|
#define INSN_MASK_WFI 0xffffff00
|
||||||
|
#define INSN_MATCH_WFI 0x10500000
|
||||||
|
|
||||||
|
#define INSN_16BIT_MASK 0x3
|
||||||
|
#define INSN_32BIT_MASK 0x1c
|
||||||
|
|
||||||
|
#define INSN_IS_16BIT(insn) \
|
||||||
|
(((insn) & INSN_16BIT_MASK) != INSN_16BIT_MASK)
|
||||||
|
#define INSN_IS_32BIT(insn) \
|
||||||
|
(((insn) & INSN_16BIT_MASK) == INSN_16BIT_MASK && \
|
||||||
|
((insn) & INSN_32BIT_MASK) != INSN_32BIT_MASK)
|
||||||
|
|
||||||
|
#define INSN_LEN(insn) (INSN_IS_16BIT(insn) ? 2 : 4)
|
||||||
|
|
||||||
#if __riscv_xlen == 64
|
#if __riscv_xlen == 64
|
||||||
#define LOG_REGBYTES 3
|
#define LOG_REGBYTES 3
|
||||||
|
@@ -73,10 +73,6 @@
|
|||||||
|
|
||||||
#define SET_FS_DIRTY() ((void)0)
|
#define SET_FS_DIRTY() ((void)0)
|
||||||
|
|
||||||
#else
|
|
||||||
#error "Floating point emulation not supported.\n"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GET_F32_RS1(insn, regs) (GET_F32_REG(insn, 15, regs))
|
#define GET_F32_RS1(insn, regs) (GET_F32_REG(insn, 15, regs))
|
||||||
#define GET_F32_RS2(insn, regs) (GET_F32_REG(insn, 20, regs))
|
#define GET_F32_RS2(insn, regs) (GET_F32_REG(insn, 20, regs))
|
||||||
#define GET_F32_RS3(insn, regs) (GET_F32_REG(insn, 27, regs))
|
#define GET_F32_RS3(insn, regs) (GET_F32_REG(insn, 27, regs))
|
||||||
@@ -94,3 +90,5 @@
|
|||||||
#define GET_F64_RS2S(insn, regs) (GET_F64_REG(RVC_RS2S(insn), 0, regs))
|
#define GET_F64_RS2S(insn, regs) (GET_F64_REG(RVC_RS2S(insn), 0, regs))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
128
include/sbi/sbi_bitmap.h
Normal file
128
include/sbi/sbi_bitmap.h
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SBI_BITMAP_H__
|
||||||
|
#define __SBI_BITMAP_H__
|
||||||
|
|
||||||
|
#include <sbi/sbi_bitops.h>
|
||||||
|
|
||||||
|
#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
|
||||||
|
#define BITMAP_LAST_WORD_MASK(nbits) \
|
||||||
|
( \
|
||||||
|
((nbits) % BITS_PER_LONG) ? \
|
||||||
|
((1UL << ((nbits) % BITS_PER_LONG)) - 1) : ~0UL \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define small_const_nbits(nbits) \
|
||||||
|
(__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG)
|
||||||
|
|
||||||
|
#define DECLARE_BITMAP(name, nbits) unsigned long name[BITS_TO_LONGS(nbits)]
|
||||||
|
#define DEFINE_BITMAP(name) extern unsigned long name[]
|
||||||
|
|
||||||
|
static inline unsigned long bitmap_estimate_size(int nbits)
|
||||||
|
{
|
||||||
|
return (BITS_TO_LONGS(nbits) * sizeof(unsigned long));
|
||||||
|
}
|
||||||
|
|
||||||
|
void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
|
||||||
|
const unsigned long *bitmap2, int bits);
|
||||||
|
void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
|
||||||
|
const unsigned long *bitmap2, int bits);
|
||||||
|
void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
|
||||||
|
const unsigned long *bitmap2, int bits);
|
||||||
|
|
||||||
|
static inline void bitmap_set(unsigned long *bmap, int start, int len)
|
||||||
|
{
|
||||||
|
int bit;
|
||||||
|
for (bit = start; bit < (start + len); bit++)
|
||||||
|
bmap[BIT_WORD(bit)] |= (0x1UL << BIT_WORD_OFFSET(bit));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bitmap_clear(unsigned long *bmap, int start, int len)
|
||||||
|
{
|
||||||
|
int bit;
|
||||||
|
for (bit = start; bit < (start + len); bit++)
|
||||||
|
bmap[BIT_WORD(bit)] &= ~(0x1UL << BIT_WORD_OFFSET(bit));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bitmap_zero(unsigned long *dst, int nbits)
|
||||||
|
{
|
||||||
|
if (small_const_nbits(nbits))
|
||||||
|
*dst = 0UL;
|
||||||
|
else {
|
||||||
|
size_t i, len = BITS_TO_LONGS(nbits);
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
dst[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bitmap_zero_except(unsigned long *dst,
|
||||||
|
int exception, int nbits)
|
||||||
|
{
|
||||||
|
if (small_const_nbits(nbits))
|
||||||
|
*dst = 0UL;
|
||||||
|
else {
|
||||||
|
size_t i, len = BITS_TO_LONGS(nbits);
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
dst[i] = 0;
|
||||||
|
}
|
||||||
|
if (exception < nbits)
|
||||||
|
__set_bit(exception, dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bitmap_fill(unsigned long *dst, int nbits)
|
||||||
|
{
|
||||||
|
size_t i, nlongs = BITS_TO_LONGS(nbits);
|
||||||
|
if (!small_const_nbits(nbits)) {
|
||||||
|
for (i = 0; i < (nlongs - 1); i++)
|
||||||
|
dst[i] = -1UL;
|
||||||
|
}
|
||||||
|
dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bitmap_copy(unsigned long *dst,
|
||||||
|
const unsigned long *src, int nbits)
|
||||||
|
{
|
||||||
|
if (small_const_nbits(nbits))
|
||||||
|
*dst = *src;
|
||||||
|
else {
|
||||||
|
size_t i, len = BITS_TO_LONGS(nbits);
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
dst[i] = src[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bitmap_and(unsigned long *dst, const unsigned long *src1,
|
||||||
|
const unsigned long *src2, int nbits)
|
||||||
|
{
|
||||||
|
if (small_const_nbits(nbits))
|
||||||
|
*dst = *src1 & *src2;
|
||||||
|
else
|
||||||
|
__bitmap_and(dst, src1, src2, nbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
|
||||||
|
const unsigned long *src2, int nbits)
|
||||||
|
{
|
||||||
|
if (small_const_nbits(nbits))
|
||||||
|
*dst = *src1 | *src2;
|
||||||
|
else
|
||||||
|
__bitmap_or(dst, src1, src2, nbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1,
|
||||||
|
const unsigned long *src2, int nbits)
|
||||||
|
{
|
||||||
|
if (small_const_nbits(nbits))
|
||||||
|
*dst = *src1 ^ *src2;
|
||||||
|
else
|
||||||
|
__bitmap_xor(dst, src1, src2, nbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@@ -4,14 +4,37 @@
|
|||||||
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Atish Patra<atish.patra@wdc.com>
|
* Atish Patra <atish.patra@wdc.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __SBI_BITOPS_H__
|
#ifndef __SBI_BITOPS_H__
|
||||||
#define __SBI_BITOPS_H__
|
#define __SBI_BITOPS_H__
|
||||||
|
|
||||||
#include <sbi/sbi_bits.h>
|
#include <sbi/sbi_types.h>
|
||||||
#include <sbi/riscv_asm.h>
|
|
||||||
|
#if __SIZEOF_POINTER__ == 8
|
||||||
|
#define BITS_PER_LONG 64
|
||||||
|
#elif __SIZEOF_POINTER__ == 4
|
||||||
|
#define BITS_PER_LONG 32
|
||||||
|
#else
|
||||||
|
#error "Unexpected __SIZEOF_POINTER__"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define EXTRACT_FIELD(val, which) \
|
||||||
|
(((val) & (which)) / ((which) & ~((which)-1)))
|
||||||
|
#define INSERT_FIELD(val, which, fieldval) \
|
||||||
|
(((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1))))
|
||||||
|
|
||||||
|
#define BITS_TO_LONGS(nbits) (((nbits) + BITS_PER_LONG - 1) / \
|
||||||
|
BITS_PER_LONG)
|
||||||
|
|
||||||
|
#define BIT(nr) (1UL << (nr))
|
||||||
|
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
||||||
|
#define BIT_WORD(bit) ((bit) / BITS_PER_LONG)
|
||||||
|
#define BIT_WORD_OFFSET(bit) ((bit) & (BITS_PER_LONG - 1))
|
||||||
|
|
||||||
|
#define GENMASK(h, l) \
|
||||||
|
(((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ffs - Find first bit set
|
* ffs - Find first bit set
|
||||||
@@ -43,10 +66,8 @@ static inline int ffs(int x)
|
|||||||
x >>= 2;
|
x >>= 2;
|
||||||
r += 2;
|
r += 2;
|
||||||
}
|
}
|
||||||
if (!(x & 1)) {
|
if (!(x & 1))
|
||||||
x >>= 1;
|
|
||||||
r += 1;
|
r += 1;
|
||||||
}
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,4 +116,205 @@ static inline int __ffs(unsigned long word)
|
|||||||
*/
|
*/
|
||||||
#define ffz(x) __ffs(~(x))
|
#define ffz(x) __ffs(~(x))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fls - find last (most-significant) bit set
|
||||||
|
* @x: the word to search
|
||||||
|
*
|
||||||
|
* This is defined the same way as ffs.
|
||||||
|
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline int fls(int x)
|
||||||
|
{
|
||||||
|
int r = 32;
|
||||||
|
|
||||||
|
if (!x)
|
||||||
|
return 0;
|
||||||
|
if (!(x & 0xffff0000u)) {
|
||||||
|
x <<= 16;
|
||||||
|
r -= 16;
|
||||||
|
}
|
||||||
|
if (!(x & 0xff000000u)) {
|
||||||
|
x <<= 8;
|
||||||
|
r -= 8;
|
||||||
|
}
|
||||||
|
if (!(x & 0xf0000000u)) {
|
||||||
|
x <<= 4;
|
||||||
|
r -= 4;
|
||||||
|
}
|
||||||
|
if (!(x & 0xc0000000u)) {
|
||||||
|
x <<= 2;
|
||||||
|
r -= 2;
|
||||||
|
}
|
||||||
|
if (!(x & 0x80000000u))
|
||||||
|
r -= 1;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __fls - find last (most-significant) set bit in a long word
|
||||||
|
* @word: the word to search
|
||||||
|
*
|
||||||
|
* Undefined if no set bit exists, so code should check against 0 first.
|
||||||
|
*/
|
||||||
|
static inline unsigned long __fls(unsigned long word)
|
||||||
|
{
|
||||||
|
int num = BITS_PER_LONG - 1;
|
||||||
|
|
||||||
|
#if BITS_PER_LONG == 64
|
||||||
|
if (!(word & (~0ul << 32))) {
|
||||||
|
num -= 32;
|
||||||
|
word <<= 32;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!(word & (~0ul << (BITS_PER_LONG-16)))) {
|
||||||
|
num -= 16;
|
||||||
|
word <<= 16;
|
||||||
|
}
|
||||||
|
if (!(word & (~0ul << (BITS_PER_LONG-8)))) {
|
||||||
|
num -= 8;
|
||||||
|
word <<= 8;
|
||||||
|
}
|
||||||
|
if (!(word & (~0ul << (BITS_PER_LONG-4)))) {
|
||||||
|
num -= 4;
|
||||||
|
word <<= 4;
|
||||||
|
}
|
||||||
|
if (!(word & (~0ul << (BITS_PER_LONG-2)))) {
|
||||||
|
num -= 2;
|
||||||
|
word <<= 2;
|
||||||
|
}
|
||||||
|
if (!(word & (~0ul << (BITS_PER_LONG-1))))
|
||||||
|
num -= 1;
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define for_each_set_bit(bit, addr, size) \
|
||||||
|
for ((bit) = find_first_bit((addr), (size)); \
|
||||||
|
(bit) < (size); \
|
||||||
|
(bit) = find_next_bit((addr), (size), (bit) + 1))
|
||||||
|
|
||||||
|
/* same as for_each_set_bit() but use bit as value to start with */
|
||||||
|
#define for_each_set_bit_from(bit, addr, size) \
|
||||||
|
for ((bit) = find_next_bit((addr), (size), (bit)); \
|
||||||
|
(bit) < (size); \
|
||||||
|
(bit) = find_next_bit((addr), (size), (bit) + 1))
|
||||||
|
|
||||||
|
#define for_each_clear_bit(bit, addr, size) \
|
||||||
|
for ((bit) = find_first_zero_bit((addr), (size)); \
|
||||||
|
(bit) < (size); \
|
||||||
|
(bit) = find_next_zero_bit((addr), (size), (bit) + 1))
|
||||||
|
|
||||||
|
/* same as for_each_clear_bit() but use bit as value to start with */
|
||||||
|
#define for_each_clear_bit_from(bit, addr, size) \
|
||||||
|
for ((bit) = find_next_zero_bit((addr), (size), (bit)); \
|
||||||
|
(bit) < (size); \
|
||||||
|
(bit) = find_next_zero_bit((addr), (size), (bit) + 1))
|
||||||
|
|
||||||
|
unsigned long find_first_bit(const unsigned long *addr,
|
||||||
|
unsigned long size);
|
||||||
|
|
||||||
|
unsigned long find_first_zero_bit(const unsigned long *addr,
|
||||||
|
unsigned long size);
|
||||||
|
|
||||||
|
unsigned long find_last_bit(const unsigned long *addr,
|
||||||
|
unsigned long size);
|
||||||
|
|
||||||
|
unsigned long find_next_bit(const unsigned long *addr,
|
||||||
|
unsigned long size, unsigned long offset);
|
||||||
|
|
||||||
|
unsigned long find_next_zero_bit(const unsigned long *addr,
|
||||||
|
unsigned long size,
|
||||||
|
unsigned long offset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __set_bit - Set a bit in memory
|
||||||
|
* @nr: the bit to set
|
||||||
|
* @addr: the address to start counting from
|
||||||
|
*
|
||||||
|
* This function is non-atomic and may be reordered.
|
||||||
|
*/
|
||||||
|
static inline void __set_bit(int nr, volatile unsigned long *addr)
|
||||||
|
{
|
||||||
|
unsigned long mask = BIT_MASK(nr);
|
||||||
|
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||||
|
|
||||||
|
*p |= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __clear_bit - Clear a bit in memory
|
||||||
|
* @nr: the bit to clear
|
||||||
|
* @addr: the address to start counting from
|
||||||
|
*
|
||||||
|
* This function is non-atomic and may be reordered.
|
||||||
|
*/
|
||||||
|
static inline void __clear_bit(int nr, volatile unsigned long *addr)
|
||||||
|
{
|
||||||
|
unsigned long mask = BIT_MASK(nr);
|
||||||
|
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||||
|
|
||||||
|
*p &= ~mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __change_bit - Toggle a bit in memory
|
||||||
|
* @nr: the bit to change
|
||||||
|
* @addr: the address to start counting from
|
||||||
|
*
|
||||||
|
* This function is non-atomic and may be reordered.
|
||||||
|
*/
|
||||||
|
static inline void __change_bit(int nr, volatile unsigned long *addr)
|
||||||
|
{
|
||||||
|
unsigned long mask = BIT_MASK(nr);
|
||||||
|
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||||
|
|
||||||
|
*p ^= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __test_and_set_bit - Set a bit and return its old value
|
||||||
|
* @nr: Bit to set
|
||||||
|
* @addr: Address to count from
|
||||||
|
*
|
||||||
|
* This operation is non-atomic and can be reordered.
|
||||||
|
*/
|
||||||
|
static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
|
||||||
|
{
|
||||||
|
unsigned long mask = BIT_MASK(nr);
|
||||||
|
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||||
|
unsigned long old = *p;
|
||||||
|
|
||||||
|
*p = old | mask;
|
||||||
|
return (old & mask) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __test_and_clear_bit - Clear a bit and return its old value
|
||||||
|
* @nr: Bit to clear
|
||||||
|
* @addr: Address to count from
|
||||||
|
*
|
||||||
|
* This operation is non-atomic and can be reordered.
|
||||||
|
*/
|
||||||
|
static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
|
||||||
|
{
|
||||||
|
unsigned long mask = BIT_MASK(nr);
|
||||||
|
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||||
|
unsigned long old = *p;
|
||||||
|
|
||||||
|
*p = old & ~mask;
|
||||||
|
return (old & mask) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __test_bit - Determine whether a bit is set
|
||||||
|
* @nr: bit number to test
|
||||||
|
* @addr: Address to start counting from
|
||||||
|
*
|
||||||
|
* This operation is non-atomic and can be reordered.
|
||||||
|
*/
|
||||||
|
static inline int __test_bit(int nr, const volatile unsigned long *addr)
|
||||||
|
{
|
||||||
|
return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*
|
|
||||||
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Anup Patel <anup.patel@wdc.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __SBI_BITS_H__
|
|
||||||
#define __SBI_BITS_H__
|
|
||||||
|
|
||||||
#define likely(x) __builtin_expect((x), 1)
|
|
||||||
#define unlikely(x) __builtin_expect((x), 0)
|
|
||||||
|
|
||||||
#define ROUNDUP(a, b) ((((a)-1) / (b) + 1) * (b))
|
|
||||||
#define ROUNDDOWN(a, b) ((a) / (b) * (b))
|
|
||||||
|
|
||||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
|
||||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
||||||
#define CLAMP(a, lo, hi) MIN(MAX(a, lo), hi)
|
|
||||||
|
|
||||||
#define EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1)))
|
|
||||||
#define INSERT_FIELD(val, which, fieldval) \
|
|
||||||
(((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1))))
|
|
||||||
|
|
||||||
#define STR(x) XSTR(x)
|
|
||||||
#define XSTR(x) #x
|
|
||||||
|
|
||||||
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
|
||||||
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
|
||||||
#endif
|
|
@@ -30,7 +30,10 @@ int __printf(3, 4) sbi_snprintf(char *out, u32 out_sz, const char *format, ...);
|
|||||||
|
|
||||||
int __printf(1, 2) sbi_printf(const char *format, ...);
|
int __printf(1, 2) sbi_printf(const char *format, ...);
|
||||||
|
|
||||||
|
int __printf(1, 2) sbi_dprintf(const char *format, ...);
|
||||||
|
|
||||||
struct sbi_scratch;
|
struct sbi_scratch;
|
||||||
|
|
||||||
int sbi_console_init(struct sbi_scratch *scratch);
|
int sbi_console_init(struct sbi_scratch *scratch);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -10,7 +10,8 @@
|
|||||||
#ifndef __SBI_CONST_H__
|
#ifndef __SBI_CONST_H__
|
||||||
#define __SBI_CONST_H__
|
#define __SBI_CONST_H__
|
||||||
|
|
||||||
/* Some constant macros are used in both assembler and
|
/*
|
||||||
|
* Some constant macros are used in both assembler and
|
||||||
* C code. Therefore we cannot annotate them always with
|
* C code. Therefore we cannot annotate them always with
|
||||||
* 'UL' and other type specifiers unilaterally. We
|
* 'UL' and other type specifiers unilaterally. We
|
||||||
* use the following macros to deal with this.
|
* use the following macros to deal with this.
|
||||||
|
50
include/sbi/sbi_csr_detect.h
Normal file
50
include/sbi/sbi_csr_detect.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Atish Patra <atish.patra@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SBI_CSR_DETECT__H
|
||||||
|
#define __SBI_CSR_DETECT__H
|
||||||
|
|
||||||
|
#include <sbi/riscv_encoding.h>
|
||||||
|
#include <sbi/sbi_hart.h>
|
||||||
|
|
||||||
|
#define csr_read_allowed(csr_num, trap) \
|
||||||
|
({ \
|
||||||
|
register ulong tinfo asm("a3") = (ulong)trap; \
|
||||||
|
register ulong ttmp asm("a4"); \
|
||||||
|
register ulong mtvec = sbi_hart_expected_trap_addr(); \
|
||||||
|
register ulong ret = 0; \
|
||||||
|
asm volatile( \
|
||||||
|
"add %[ttmp], %[tinfo], zero\n" \
|
||||||
|
"csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n" \
|
||||||
|
"csrr %[ret], %[csr]\n" \
|
||||||
|
"csrw " STR(CSR_MTVEC) ", %[mtvec]" \
|
||||||
|
: [mtvec] "+&r"(mtvec), [tinfo] "+&r"(tinfo), \
|
||||||
|
[ttmp] "+&r"(ttmp), [ret] "=&r" (ret) \
|
||||||
|
: [csr] "i" (csr_num) \
|
||||||
|
: "memory"); \
|
||||||
|
ret; \
|
||||||
|
}) \
|
||||||
|
|
||||||
|
#define csr_write_allowed(csr_num, trap, value) \
|
||||||
|
({ \
|
||||||
|
register ulong tinfo asm("a3") = (ulong)trap; \
|
||||||
|
register ulong ttmp asm("a4"); \
|
||||||
|
register ulong mtvec = sbi_hart_expected_trap_addr(); \
|
||||||
|
asm volatile( \
|
||||||
|
"add %[ttmp], %[tinfo], zero\n" \
|
||||||
|
"csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n" \
|
||||||
|
"csrw %[csr], %[val]\n" \
|
||||||
|
"csrw " STR(CSR_MTVEC) ", %[mtvec]" \
|
||||||
|
: [mtvec] "+&r"(mtvec), \
|
||||||
|
[tinfo] "+&r"(tinfo), [ttmp] "+&r"(ttmp) \
|
||||||
|
: [csr] "i" (csr_num), [val] "r" (value) \
|
||||||
|
: "memory"); \
|
||||||
|
}) \
|
||||||
|
|
||||||
|
#endif
|
165
include/sbi/sbi_domain.h
Normal file
165
include/sbi/sbi_domain.h
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SBI_DOMAIN_H__
|
||||||
|
#define __SBI_DOMAIN_H__
|
||||||
|
|
||||||
|
#include <sbi/sbi_types.h>
|
||||||
|
#include <sbi/sbi_hartmask.h>
|
||||||
|
|
||||||
|
struct sbi_scratch;
|
||||||
|
|
||||||
|
/** Domain access types */
|
||||||
|
enum sbi_domain_access {
|
||||||
|
SBI_DOMAIN_READ = (1UL << 0),
|
||||||
|
SBI_DOMAIN_WRITE = (1UL << 1),
|
||||||
|
SBI_DOMAIN_EXECUTE = (1UL << 2),
|
||||||
|
SBI_DOMAIN_MMIO = (1UL << 3)
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Representation of OpenSBI domain memory region */
|
||||||
|
struct sbi_domain_memregion {
|
||||||
|
/**
|
||||||
|
* Size of memory region as power of 2
|
||||||
|
* It has to be minimum 3 and maximum __riscv_xlen
|
||||||
|
*/
|
||||||
|
unsigned long order;
|
||||||
|
/**
|
||||||
|
* Base address of memory region
|
||||||
|
* It must be 2^order aligned address
|
||||||
|
*/
|
||||||
|
unsigned long base;
|
||||||
|
/** Flags representing memory region attributes */
|
||||||
|
#define SBI_DOMAIN_MEMREGION_READABLE (1UL << 0)
|
||||||
|
#define SBI_DOMAIN_MEMREGION_WRITEABLE (1UL << 1)
|
||||||
|
#define SBI_DOMAIN_MEMREGION_EXECUTABLE (1UL << 2)
|
||||||
|
#define SBI_DOMAIN_MEMREGION_MMODE (1UL << 3)
|
||||||
|
#define SBI_DOMAIN_MEMREGION_ACCESS_MASK (0xfUL)
|
||||||
|
|
||||||
|
#define SBI_DOMAIN_MEMREGION_MMIO (1UL << 31)
|
||||||
|
unsigned long flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Maximum number of domains */
|
||||||
|
#define SBI_DOMAIN_MAX_INDEX 32
|
||||||
|
|
||||||
|
/** Representation of OpenSBI domain */
|
||||||
|
struct sbi_domain {
|
||||||
|
/**
|
||||||
|
* Logical index of this domain
|
||||||
|
* Note: This set by sbi_domain_finalize() in the coldboot path
|
||||||
|
*/
|
||||||
|
u32 index;
|
||||||
|
/**
|
||||||
|
* HARTs assigned to this domain
|
||||||
|
* Note: This set by sbi_domain_init() and sbi_domain_finalize()
|
||||||
|
* in the coldboot path
|
||||||
|
*/
|
||||||
|
struct sbi_hartmask assigned_harts;
|
||||||
|
/** Name of this domain */
|
||||||
|
char name[64];
|
||||||
|
/** Possible HARTs in this domain */
|
||||||
|
const struct sbi_hartmask *possible_harts;
|
||||||
|
/** Array of memory regions terminated by a region with order zero */
|
||||||
|
struct sbi_domain_memregion *regions;
|
||||||
|
/** HART id of the HART booting this domain */
|
||||||
|
u32 boot_hartid;
|
||||||
|
/** Arg1 (or 'a1' register) of next booting stage for this domain */
|
||||||
|
unsigned long next_arg1;
|
||||||
|
/** Address of next booting stage for this domain */
|
||||||
|
unsigned long next_addr;
|
||||||
|
/** Privilege mode of next booting stage for this domain */
|
||||||
|
unsigned long next_mode;
|
||||||
|
/** Is domain allowed to reset the system */
|
||||||
|
bool system_reset_allowed;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** HART id to domain table */
|
||||||
|
extern struct sbi_domain *hartid_to_domain_table[];
|
||||||
|
|
||||||
|
/** Get pointer to sbi_domain from HART id */
|
||||||
|
#define sbi_hartid_to_domain(__hartid) \
|
||||||
|
hartid_to_domain_table[__hartid]
|
||||||
|
|
||||||
|
/** Get pointer to sbi_domain for current HART */
|
||||||
|
#define sbi_domain_thishart_ptr() \
|
||||||
|
sbi_hartid_to_domain(current_hartid())
|
||||||
|
|
||||||
|
/** Index to domain table */
|
||||||
|
extern struct sbi_domain *domidx_to_domain_table[];
|
||||||
|
|
||||||
|
/** Get pointer to sbi_domain from index */
|
||||||
|
#define sbi_index_to_domain(__index) \
|
||||||
|
domidx_to_domain_table[__index]
|
||||||
|
|
||||||
|
/** Iterate over each domain */
|
||||||
|
#define sbi_domain_for_each(__i, __d) \
|
||||||
|
for ((__i) = 0; ((__d) = sbi_index_to_domain(__i)); (__i)++)
|
||||||
|
|
||||||
|
/** Iterate over each memory region of a domain */
|
||||||
|
#define sbi_domain_for_each_memregion(__d, __r) \
|
||||||
|
for ((__r) = (__d)->regions; (__r)->order; (__r)++)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether given HART is assigned to specified domain
|
||||||
|
* @param dom pointer to domain
|
||||||
|
* @param hartid the HART ID
|
||||||
|
* @return TRUE if HART is assigned to domain otherwise FALSE
|
||||||
|
*/
|
||||||
|
bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get ulong assigned HART mask for given domain and HART base ID
|
||||||
|
* @param dom pointer to domain
|
||||||
|
* @param hbase the HART base ID
|
||||||
|
* @return ulong possible HART mask
|
||||||
|
* Note: the return ulong mask will be set to zero on failure.
|
||||||
|
*/
|
||||||
|
ulong sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom,
|
||||||
|
ulong hbase);
|
||||||
|
|
||||||
|
/** Initialize a domain memory region as firmware region */
|
||||||
|
void sbi_domain_memregion_initfw(struct sbi_domain_memregion *reg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether we can access specified address for given mode and
|
||||||
|
* memory region flags under a domain
|
||||||
|
* @param dom pointer to domain
|
||||||
|
* @param addr the address to be checked
|
||||||
|
* @param mode the privilege mode of access
|
||||||
|
* @param access_flags bitmask of domain access types (enum sbi_domain_access)
|
||||||
|
* @return TRUE if access allowed otherwise FALSE
|
||||||
|
*/
|
||||||
|
bool sbi_domain_check_addr(const struct sbi_domain *dom,
|
||||||
|
unsigned long addr, unsigned long mode,
|
||||||
|
unsigned long access_flags);
|
||||||
|
|
||||||
|
/** Dump domain details on the console */
|
||||||
|
void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix);
|
||||||
|
|
||||||
|
/** Dump all domain details on the console */
|
||||||
|
void sbi_domain_dump_all(const char *suffix);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new domain
|
||||||
|
* @param dom pointer to domain
|
||||||
|
* @param assign_mask pointer to HART mask of HARTs assigned to the domain
|
||||||
|
*
|
||||||
|
* @return 0 on success and negative error code on failure
|
||||||
|
*/
|
||||||
|
int sbi_domain_register(struct sbi_domain *dom,
|
||||||
|
const struct sbi_hartmask *assign_mask);
|
||||||
|
|
||||||
|
/** Finalize domain tables and startup non-root domains */
|
||||||
|
int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid);
|
||||||
|
|
||||||
|
/** Initialize domains */
|
||||||
|
int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid);
|
||||||
|
|
||||||
|
#endif
|
@@ -11,15 +11,51 @@
|
|||||||
#define __SBI_ECALL_H__
|
#define __SBI_ECALL_H__
|
||||||
|
|
||||||
#include <sbi/sbi_types.h>
|
#include <sbi/sbi_types.h>
|
||||||
|
#include <sbi/sbi_list.h>
|
||||||
|
|
||||||
|
#define SBI_ECALL_VERSION_MAJOR 0
|
||||||
|
#define SBI_ECALL_VERSION_MINOR 2
|
||||||
|
#define SBI_OPENSBI_IMPID 1
|
||||||
|
|
||||||
struct sbi_trap_regs;
|
struct sbi_trap_regs;
|
||||||
struct sbi_scratch;
|
struct sbi_trap_info;
|
||||||
|
|
||||||
|
struct sbi_ecall_extension {
|
||||||
|
struct sbi_dlist head;
|
||||||
|
unsigned long extid_start;
|
||||||
|
unsigned long extid_end;
|
||||||
|
int (* probe)(unsigned long extid, unsigned long *out_val);
|
||||||
|
int (* handle)(unsigned long extid, unsigned long funcid,
|
||||||
|
const struct sbi_trap_regs *regs,
|
||||||
|
unsigned long *out_val,
|
||||||
|
struct sbi_trap_info *out_trap);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct sbi_ecall_extension ecall_base;
|
||||||
|
extern struct sbi_ecall_extension ecall_legacy;
|
||||||
|
extern struct sbi_ecall_extension ecall_time;
|
||||||
|
extern struct sbi_ecall_extension ecall_rfence;
|
||||||
|
extern struct sbi_ecall_extension ecall_ipi;
|
||||||
|
extern struct sbi_ecall_extension ecall_vendor;
|
||||||
|
extern struct sbi_ecall_extension ecall_hsm;
|
||||||
|
extern struct sbi_ecall_extension ecall_srst;
|
||||||
|
|
||||||
u16 sbi_ecall_version_major(void);
|
u16 sbi_ecall_version_major(void);
|
||||||
|
|
||||||
u16 sbi_ecall_version_minor(void);
|
u16 sbi_ecall_version_minor(void);
|
||||||
|
|
||||||
int sbi_ecall_handler(u32 hartid, ulong mcause, struct sbi_trap_regs *regs,
|
unsigned long sbi_ecall_get_impid(void);
|
||||||
struct sbi_scratch *scratch);
|
|
||||||
|
void sbi_ecall_set_impid(unsigned long impid);
|
||||||
|
|
||||||
|
struct sbi_ecall_extension *sbi_ecall_find_extension(unsigned long extid);
|
||||||
|
|
||||||
|
int sbi_ecall_register_extension(struct sbi_ecall_extension *ext);
|
||||||
|
|
||||||
|
void sbi_ecall_unregister_extension(struct sbi_ecall_extension *ext);
|
||||||
|
|
||||||
|
int sbi_ecall_handler(struct sbi_trap_regs *regs);
|
||||||
|
|
||||||
|
int sbi_ecall_init(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -12,41 +12,87 @@
|
|||||||
|
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
|
||||||
#define SBI_ECALL_SET_TIMER 0
|
/* SBI Extension IDs */
|
||||||
#define SBI_ECALL_CONSOLE_PUTCHAR 1
|
#define SBI_EXT_0_1_SET_TIMER 0x0
|
||||||
#define SBI_ECALL_CONSOLE_GETCHAR 2
|
#define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1
|
||||||
#define SBI_ECALL_CLEAR_IPI 3
|
#define SBI_EXT_0_1_CONSOLE_GETCHAR 0x2
|
||||||
#define SBI_ECALL_SEND_IPI 4
|
#define SBI_EXT_0_1_CLEAR_IPI 0x3
|
||||||
#define SBI_ECALL_REMOTE_FENCE_I 5
|
#define SBI_EXT_0_1_SEND_IPI 0x4
|
||||||
#define SBI_ECALL_REMOTE_SFENCE_VMA 6
|
#define SBI_EXT_0_1_REMOTE_FENCE_I 0x5
|
||||||
#define SBI_ECALL_REMOTE_SFENCE_VMA_ASID 7
|
#define SBI_EXT_0_1_REMOTE_SFENCE_VMA 0x6
|
||||||
#define SBI_ECALL_SHUTDOWN 8
|
#define SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID 0x7
|
||||||
|
#define SBI_EXT_0_1_SHUTDOWN 0x8
|
||||||
|
#define SBI_EXT_BASE 0x10
|
||||||
|
#define SBI_EXT_TIME 0x54494D45
|
||||||
|
#define SBI_EXT_IPI 0x735049
|
||||||
|
#define SBI_EXT_RFENCE 0x52464E43
|
||||||
|
#define SBI_EXT_HSM 0x48534D
|
||||||
|
#define SBI_EXT_SRST 0x53525354
|
||||||
|
|
||||||
|
/* SBI function IDs for BASE extension*/
|
||||||
|
#define SBI_EXT_BASE_GET_SPEC_VERSION 0x0
|
||||||
|
#define SBI_EXT_BASE_GET_IMP_ID 0x1
|
||||||
|
#define SBI_EXT_BASE_GET_IMP_VERSION 0x2
|
||||||
|
#define SBI_EXT_BASE_PROBE_EXT 0x3
|
||||||
|
#define SBI_EXT_BASE_GET_MVENDORID 0x4
|
||||||
|
#define SBI_EXT_BASE_GET_MARCHID 0x5
|
||||||
|
#define SBI_EXT_BASE_GET_MIMPID 0x6
|
||||||
|
|
||||||
|
/* SBI function IDs for TIME extension*/
|
||||||
|
#define SBI_EXT_TIME_SET_TIMER 0x0
|
||||||
|
|
||||||
|
/* SBI function IDs for IPI extension*/
|
||||||
|
#define SBI_EXT_IPI_SEND_IPI 0x0
|
||||||
|
|
||||||
|
/* SBI function IDs for RFENCE extension*/
|
||||||
|
#define SBI_EXT_RFENCE_REMOTE_FENCE_I 0x0
|
||||||
|
#define SBI_EXT_RFENCE_REMOTE_SFENCE_VMA 0x1
|
||||||
|
#define SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID 0x2
|
||||||
|
#define SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA 0x3
|
||||||
|
#define SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID 0x4
|
||||||
|
#define SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA 0x5
|
||||||
|
#define SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID 0x6
|
||||||
|
|
||||||
|
/* SBI function IDs for HSM extension */
|
||||||
|
#define SBI_EXT_HSM_HART_START 0x0
|
||||||
|
#define SBI_EXT_HSM_HART_STOP 0x1
|
||||||
|
#define SBI_EXT_HSM_HART_GET_STATUS 0x2
|
||||||
|
|
||||||
|
#define SBI_HSM_HART_STATUS_STARTED 0x0
|
||||||
|
#define SBI_HSM_HART_STATUS_STOPPED 0x1
|
||||||
|
#define SBI_HSM_HART_STATUS_START_PENDING 0x2
|
||||||
|
#define SBI_HSM_HART_STATUS_STOP_PENDING 0x3
|
||||||
|
|
||||||
|
/* SBI function IDs for SRST extension */
|
||||||
|
#define SBI_EXT_SRST_RESET 0x0
|
||||||
|
|
||||||
|
#define SBI_SRST_RESET_TYPE_SHUTDOWN 0x0
|
||||||
|
#define SBI_SRST_RESET_TYPE_COLD_REBOOT 0x1
|
||||||
|
#define SBI_SRST_RESET_TYPE_WARM_REBOOT 0x2
|
||||||
|
#define SBI_SRST_RESET_TYPE_LAST SBI_SRST_RESET_TYPE_WARM_REBOOT
|
||||||
|
|
||||||
|
#define SBI_SRST_RESET_REASON_NONE 0x0
|
||||||
|
#define SBI_SRST_RESET_REASON_SYSFAIL 0x1
|
||||||
|
|
||||||
|
#define SBI_SPEC_VERSION_MAJOR_OFFSET 24
|
||||||
|
#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f
|
||||||
|
#define SBI_SPEC_VERSION_MINOR_MASK 0xffffff
|
||||||
|
#define SBI_EXT_VENDOR_START 0x09000000
|
||||||
|
#define SBI_EXT_VENDOR_END 0x09FFFFFF
|
||||||
|
#define SBI_EXT_FIRMWARE_START 0x0A000000
|
||||||
|
#define SBI_EXT_FIRMWARE_END 0x0AFFFFFF
|
||||||
|
|
||||||
|
/* SBI return error codes */
|
||||||
|
#define SBI_SUCCESS 0
|
||||||
|
#define SBI_ERR_FAILED -1
|
||||||
|
#define SBI_ERR_NOT_SUPPORTED -2
|
||||||
|
#define SBI_ERR_INVALID_PARAM -3
|
||||||
|
#define SBI_ERR_DENIED -4
|
||||||
|
#define SBI_ERR_INVALID_ADDRESS -5
|
||||||
|
#define SBI_ERR_ALREADY_AVAILABLE -6
|
||||||
|
|
||||||
|
#define SBI_LAST_ERR SBI_ERR_ALREADY_AVAILABLE
|
||||||
|
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
#define SBI_ECALL(__num, __a0, __a1, __a2) \
|
|
||||||
({ \
|
|
||||||
register unsigned long a0 asm("a0") = (unsigned long)(__a0); \
|
|
||||||
register unsigned long a1 asm("a1") = (unsigned long)(__a1); \
|
|
||||||
register unsigned long a2 asm("a2") = (unsigned long)(__a2); \
|
|
||||||
register unsigned long a7 asm("a7") = (unsigned long)(__num); \
|
|
||||||
asm volatile("ecall" \
|
|
||||||
: "+r"(a0) \
|
|
||||||
: "r"(a1), "r"(a2), "r"(a7) \
|
|
||||||
: "memory"); \
|
|
||||||
a0; \
|
|
||||||
})
|
|
||||||
|
|
||||||
#define SBI_ECALL_0(__num) SBI_ECALL(__num, 0, 0, 0)
|
|
||||||
#define SBI_ECALL_1(__num, __a0) SBI_ECALL(__num, __a0, 0, 0)
|
|
||||||
#define SBI_ECALL_2(__num, __a0, __a1) SBI_ECALL(__num, __a0, __a1, 0)
|
|
||||||
|
|
||||||
#define sbi_ecall_console_putc(c) SBI_ECALL_1(SBI_ECALL_CONSOLE_PUTCHAR, (c));
|
|
||||||
|
|
||||||
static inline void sbi_ecall_console_puts(const char *str)
|
|
||||||
{
|
|
||||||
while (str && *str)
|
|
||||||
sbi_ecall_console_putc(*str++);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -12,12 +12,12 @@
|
|||||||
|
|
||||||
#include <sbi/sbi_types.h>
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
struct sbi_scratch;
|
struct sbi_trap_regs;
|
||||||
|
|
||||||
int sbi_emulate_csr_read(int csr_num, u32 hartid, ulong mstatus,
|
int sbi_emulate_csr_read(int csr_num, struct sbi_trap_regs *regs,
|
||||||
struct sbi_scratch *scratch, ulong *csr_val);
|
ulong *csr_val);
|
||||||
|
|
||||||
int sbi_emulate_csr_write(int csr_num, u32 hartid, ulong mstatus,
|
int sbi_emulate_csr_write(int csr_num, struct sbi_trap_regs *regs,
|
||||||
struct sbi_scratch *scratch, ulong csr_val);
|
ulong csr_val);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -10,22 +10,28 @@
|
|||||||
#ifndef __SBI_ERROR_H__
|
#ifndef __SBI_ERROR_H__
|
||||||
#define __SBI_ERROR_H__
|
#define __SBI_ERROR_H__
|
||||||
|
|
||||||
|
#include <sbi/sbi_ecall_interface.h>
|
||||||
|
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
|
||||||
#define SBI_OK 0
|
#define SBI_OK 0
|
||||||
#define SBI_EUNKNOWN -1
|
#define SBI_EFAIL SBI_ERR_FAILED
|
||||||
#define SBI_EFAIL -2
|
#define SBI_ENOTSUPP SBI_ERR_NOT_SUPPORTED
|
||||||
#define SBI_EINVAL -3
|
#define SBI_EINVAL SBI_ERR_INVALID_PARAM
|
||||||
#define SBI_ENOENT -4
|
#define SBI_EDENIED SBI_ERR_DENIED
|
||||||
#define SBI_ENOTSUPP -5
|
#define SBI_EINVALID_ADDR SBI_ERR_INVALID_ADDRESS
|
||||||
#define SBI_ENODEV -6
|
#define SBI_EALREADY SBI_ERR_ALREADY_AVAILABLE
|
||||||
#define SBI_ENOSYS -7
|
|
||||||
#define SBI_ETIMEDOUT -8
|
#define SBI_ENODEV -1000
|
||||||
#define SBI_EIO -9
|
#define SBI_ENOSYS -1001
|
||||||
#define SBI_EILL -10
|
#define SBI_ETIMEDOUT -1002
|
||||||
#define SBI_ENOSPC -11
|
#define SBI_EIO -1003
|
||||||
#define SBI_ENOMEM -12
|
#define SBI_EILL -1004
|
||||||
#define SBI_ETRAP -13
|
#define SBI_ENOSPC -1005
|
||||||
|
#define SBI_ENOMEM -1006
|
||||||
|
#define SBI_ETRAP -1007
|
||||||
|
#define SBI_EUNKNOWN -1008
|
||||||
|
#define SBI_ENOENT -1009
|
||||||
|
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
|
@@ -26,7 +26,6 @@ struct sbi_fifo {
|
|||||||
enum sbi_fifo_inplace_update_types {
|
enum sbi_fifo_inplace_update_types {
|
||||||
SBI_FIFO_SKIP,
|
SBI_FIFO_SKIP,
|
||||||
SBI_FIFO_UPDATED,
|
SBI_FIFO_UPDATED,
|
||||||
SBI_FIFO_RESET,
|
|
||||||
SBI_FIFO_UNCHANGED,
|
SBI_FIFO_UNCHANGED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -12,35 +12,45 @@
|
|||||||
|
|
||||||
#include <sbi/sbi_types.h>
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
|
/** Possible feature flags of a hart */
|
||||||
|
enum sbi_hart_features {
|
||||||
|
/** Hart has S-mode counter enable */
|
||||||
|
SBI_HART_HAS_SCOUNTEREN = (1 << 0),
|
||||||
|
/** Hart has M-mode counter enable */
|
||||||
|
SBI_HART_HAS_MCOUNTEREN = (1 << 1),
|
||||||
|
/** HART has timer csr implementation in hardware */
|
||||||
|
SBI_HART_HAS_TIME = (1 << 2),
|
||||||
|
|
||||||
|
/** Last index of Hart features*/
|
||||||
|
SBI_HART_HAS_LAST_FEATURE = SBI_HART_HAS_TIME,
|
||||||
|
};
|
||||||
|
|
||||||
struct sbi_scratch;
|
struct sbi_scratch;
|
||||||
|
|
||||||
int sbi_hart_init(struct sbi_scratch *scratch, u32 hartid, bool cold_boot);
|
int sbi_hart_init(struct sbi_scratch *scratch, bool cold_boot);
|
||||||
|
|
||||||
void *sbi_hart_get_trap_info(struct sbi_scratch *scratch);
|
extern void (*sbi_hart_expected_trap)(void);
|
||||||
|
static inline ulong sbi_hart_expected_trap_addr(void)
|
||||||
|
{
|
||||||
|
return (ulong)sbi_hart_expected_trap;
|
||||||
|
}
|
||||||
|
|
||||||
void sbi_hart_set_trap_info(struct sbi_scratch *scratch, void *data);
|
unsigned int sbi_hart_mhpm_count(struct sbi_scratch *scratch);
|
||||||
|
void sbi_hart_delegation_dump(struct sbi_scratch *scratch,
|
||||||
void sbi_hart_pmp_dump(struct sbi_scratch *scratch);
|
const char *prefix, const char *suffix);
|
||||||
|
unsigned int sbi_hart_pmp_count(struct sbi_scratch *scratch);
|
||||||
|
unsigned long sbi_hart_pmp_granularity(struct sbi_scratch *scratch);
|
||||||
|
unsigned int sbi_hart_pmp_addrbits(struct sbi_scratch *scratch);
|
||||||
|
int sbi_hart_pmp_configure(struct sbi_scratch *scratch);
|
||||||
|
bool sbi_hart_has_feature(struct sbi_scratch *scratch, unsigned long feature);
|
||||||
|
void sbi_hart_get_features_str(struct sbi_scratch *scratch,
|
||||||
|
char *features_str, int nfstr);
|
||||||
|
|
||||||
void __attribute__((noreturn)) sbi_hart_hang(void);
|
void __attribute__((noreturn)) sbi_hart_hang(void);
|
||||||
|
|
||||||
void __attribute__((noreturn))
|
void __attribute__((noreturn))
|
||||||
sbi_hart_switch_mode(unsigned long arg0, unsigned long arg1,
|
sbi_hart_switch_mode(unsigned long arg0, unsigned long arg1,
|
||||||
unsigned long next_addr, unsigned long next_mode);
|
unsigned long next_addr, unsigned long next_mode,
|
||||||
|
bool next_virt);
|
||||||
void sbi_hart_mark_available(u32 hartid);
|
|
||||||
|
|
||||||
ulong sbi_hart_available_mask(void);
|
|
||||||
|
|
||||||
void sbi_hart_unmark_available(u32 hartid);
|
|
||||||
|
|
||||||
struct sbi_scratch *sbi_hart_id_to_scratch(struct sbi_scratch *scratch,
|
|
||||||
u32 hartid);
|
|
||||||
|
|
||||||
void sbi_hart_wait_for_coldboot(struct sbi_scratch *scratch, u32 hartid);
|
|
||||||
|
|
||||||
void sbi_hart_wake_coldboot_harts(struct sbi_scratch *scratch, u32 hartid);
|
|
||||||
|
|
||||||
u32 sbi_current_hartid(void);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
141
include/sbi/sbi_hartmask.h
Normal file
141
include/sbi/sbi_hartmask.h
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SBI_HARTMASK_H__
|
||||||
|
#define __SBI_HARTMASK_H__
|
||||||
|
|
||||||
|
#include <sbi/sbi_bitmap.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of bits in a hartmask
|
||||||
|
*
|
||||||
|
* The hartmask is indexed using physical HART id so this define
|
||||||
|
* also represents the maximum number of HART ids generic OpenSBI
|
||||||
|
* can handle.
|
||||||
|
*/
|
||||||
|
#define SBI_HARTMASK_MAX_BITS 128
|
||||||
|
|
||||||
|
/** Representation of hartmask */
|
||||||
|
struct sbi_hartmask {
|
||||||
|
DECLARE_BITMAP(bits, SBI_HARTMASK_MAX_BITS);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Initialize hartmask to zero */
|
||||||
|
#define SBI_HARTMASK_INIT(__m) \
|
||||||
|
bitmap_zero(((__m)->bits), SBI_HARTMASK_MAX_BITS)
|
||||||
|
|
||||||
|
/** Initialize hartmask to zero except a particular HART id */
|
||||||
|
#define SBI_HARTMASK_INIT_EXCEPT(__m, __h) \
|
||||||
|
bitmap_zero_except(((__m)->bits), (__h), SBI_HARTMASK_MAX_BITS)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get underlying bitmap of hartmask
|
||||||
|
* @param m the hartmask pointer
|
||||||
|
*/
|
||||||
|
#define sbi_hartmask_bits(__m) ((__m)->bits)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a HART in hartmask
|
||||||
|
* @param h HART id to set
|
||||||
|
* @param m the hartmask pointer
|
||||||
|
*/
|
||||||
|
static inline void sbi_hartmask_set_hart(u32 h, struct sbi_hartmask *m)
|
||||||
|
{
|
||||||
|
if (h < SBI_HARTMASK_MAX_BITS)
|
||||||
|
__set_bit(h, m->bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear a HART in hartmask
|
||||||
|
* @param h HART id to clear
|
||||||
|
* @param m the hartmask pointer
|
||||||
|
*/
|
||||||
|
static inline void sbi_hartmask_clear_hart(u32 h, struct sbi_hartmask *m)
|
||||||
|
{
|
||||||
|
if (h < SBI_HARTMASK_MAX_BITS)
|
||||||
|
__clear_bit(h, m->bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test a HART in hartmask
|
||||||
|
* @param h HART id to test
|
||||||
|
* @param m the hartmask pointer
|
||||||
|
*/
|
||||||
|
static inline int sbi_hartmask_test_hart(u32 h, const struct sbi_hartmask *m)
|
||||||
|
{
|
||||||
|
if (h < SBI_HARTMASK_MAX_BITS)
|
||||||
|
return __test_bit(h, m->bits);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set all HARTs in a hartmask
|
||||||
|
* @param dstp the hartmask pointer
|
||||||
|
*/
|
||||||
|
static inline void sbi_hartmask_set_all(struct sbi_hartmask *dstp)
|
||||||
|
{
|
||||||
|
bitmap_fill(sbi_hartmask_bits(dstp), SBI_HARTMASK_MAX_BITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all HARTs in a hartmask
|
||||||
|
* @param dstp the hartmask pointer
|
||||||
|
*/
|
||||||
|
static inline void sbi_hartmask_clear_all(struct sbi_hartmask *dstp)
|
||||||
|
{
|
||||||
|
bitmap_zero(sbi_hartmask_bits(dstp), SBI_HARTMASK_MAX_BITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* *dstp = *src1p & *src2p
|
||||||
|
* @param dstp the hartmask result
|
||||||
|
* @param src1p the first input
|
||||||
|
* @param src2p the second input
|
||||||
|
*/
|
||||||
|
static inline void sbi_hartmask_and(struct sbi_hartmask *dstp,
|
||||||
|
const struct sbi_hartmask *src1p,
|
||||||
|
const struct sbi_hartmask *src2p)
|
||||||
|
{
|
||||||
|
bitmap_and(sbi_hartmask_bits(dstp), sbi_hartmask_bits(src1p),
|
||||||
|
sbi_hartmask_bits(src2p), SBI_HARTMASK_MAX_BITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* *dstp = *src1p | *src2p
|
||||||
|
* @param dstp the hartmask result
|
||||||
|
* @param src1p the first input
|
||||||
|
* @param src2p the second input
|
||||||
|
*/
|
||||||
|
static inline void sbi_hartmask_or(struct sbi_hartmask *dstp,
|
||||||
|
const struct sbi_hartmask *src1p,
|
||||||
|
const struct sbi_hartmask *src2p)
|
||||||
|
{
|
||||||
|
bitmap_or(sbi_hartmask_bits(dstp), sbi_hartmask_bits(src1p),
|
||||||
|
sbi_hartmask_bits(src2p), SBI_HARTMASK_MAX_BITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* *dstp = *src1p ^ *src2p
|
||||||
|
* @param dstp the hartmask result
|
||||||
|
* @param src1p the first input
|
||||||
|
* @param src2p the second input
|
||||||
|
*/
|
||||||
|
static inline void sbi_hartmask_xor(struct sbi_hartmask *dstp,
|
||||||
|
const struct sbi_hartmask *src1p,
|
||||||
|
const struct sbi_hartmask *src2p)
|
||||||
|
{
|
||||||
|
bitmap_xor(sbi_hartmask_bits(dstp), sbi_hartmask_bits(src1p),
|
||||||
|
sbi_hartmask_bits(src2p), SBI_HARTMASK_MAX_BITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Iterate over each HART in hartmask */
|
||||||
|
#define sbi_hartmask_for_each_hart(__h, __m) \
|
||||||
|
for_each_set_bit(__h, (__m)->bits, SBI_HARTMASK_MAX_BITS)
|
||||||
|
|
||||||
|
#endif
|
38
include/sbi/sbi_hfence.h
Normal file
38
include/sbi/sbi_hfence.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Atish Patra <atish.patra@wdc.com>
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SBI_FENCE_H__
|
||||||
|
#define __SBI_FENCE_H__
|
||||||
|
|
||||||
|
/** Invalidate Stage2 TLBs for given VMID and guest physical address */
|
||||||
|
void __sbi_hfence_gvma_vmid_gpa(unsigned long gpa, unsigned long vmid);
|
||||||
|
|
||||||
|
/** Invalidate Stage2 TLBs for given VMID */
|
||||||
|
void __sbi_hfence_gvma_vmid(unsigned long vmid);
|
||||||
|
|
||||||
|
/** Invalidate Stage2 TLBs for given guest physical address */
|
||||||
|
void __sbi_hfence_gvma_gpa(unsigned long gpa);
|
||||||
|
|
||||||
|
/** Invalidate all possible Stage2 TLBs */
|
||||||
|
void __sbi_hfence_gvma_all(void);
|
||||||
|
|
||||||
|
/** Invalidate unified TLB entries for given asid and guest virtual address */
|
||||||
|
void __sbi_hfence_vvma_asid_va(unsigned long va, unsigned long asid);
|
||||||
|
|
||||||
|
/** Invalidate unified TLB entries for given ASID for a guest*/
|
||||||
|
void __sbi_hfence_vvma_asid(unsigned long asid);
|
||||||
|
|
||||||
|
/** Invalidate unified TLB entries for a given guest virtual address */
|
||||||
|
void __sbi_hfence_vvma_va(unsigned long va);
|
||||||
|
|
||||||
|
/** Invalidate all possible Stage2 TLBs */
|
||||||
|
void __sbi_hfence_vvma_all(void);
|
||||||
|
|
||||||
|
#endif
|
38
include/sbi/sbi_hsm.h
Normal file
38
include/sbi/sbi_hsm.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Atish Patra <atish.patra@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SBI_HSM_H__
|
||||||
|
#define __SBI_HSM_H__
|
||||||
|
|
||||||
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
|
/** Hart state values **/
|
||||||
|
#define SBI_HART_STOPPED 0
|
||||||
|
#define SBI_HART_STOPPING 1
|
||||||
|
#define SBI_HART_STARTING 2
|
||||||
|
#define SBI_HART_STARTED 3
|
||||||
|
#define SBI_HART_UNKNOWN 4
|
||||||
|
|
||||||
|
struct sbi_domain;
|
||||||
|
struct sbi_scratch;
|
||||||
|
|
||||||
|
int sbi_hsm_init(struct sbi_scratch *scratch, u32 hartid, bool cold_boot);
|
||||||
|
void __noreturn sbi_hsm_exit(struct sbi_scratch *scratch);
|
||||||
|
|
||||||
|
int sbi_hsm_hart_start(struct sbi_scratch *scratch,
|
||||||
|
const struct sbi_domain *dom,
|
||||||
|
u32 hartid, ulong saddr, ulong smode, ulong priv);
|
||||||
|
int sbi_hsm_hart_stop(struct sbi_scratch *scratch, bool exitnow);
|
||||||
|
int sbi_hsm_hart_get_state(const struct sbi_domain *dom, u32 hartid);
|
||||||
|
int sbi_hsm_hart_state_to_status(int state);
|
||||||
|
int sbi_hsm_hart_started_mask(const struct sbi_domain *dom,
|
||||||
|
ulong hbase, ulong *out_hmask);
|
||||||
|
void sbi_hsm_prepare_next_jump(struct sbi_scratch *scratch, u32 hartid);
|
||||||
|
|
||||||
|
#endif
|
@@ -13,10 +13,7 @@
|
|||||||
#include <sbi/sbi_types.h>
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
struct sbi_trap_regs;
|
struct sbi_trap_regs;
|
||||||
struct sbi_scratch;
|
|
||||||
|
|
||||||
int sbi_illegal_insn_handler(u32 hartid, ulong mcause,
|
int sbi_illegal_insn_handler(ulong insn, struct sbi_trap_regs *regs);
|
||||||
struct sbi_trap_regs *regs,
|
|
||||||
struct sbi_scratch *scratch);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -16,4 +16,8 @@ struct sbi_scratch;
|
|||||||
|
|
||||||
void __noreturn sbi_init(struct sbi_scratch *scratch);
|
void __noreturn sbi_init(struct sbi_scratch *scratch);
|
||||||
|
|
||||||
|
unsigned long sbi_init_count(u32 hartid);
|
||||||
|
|
||||||
|
void __noreturn sbi_exit(struct sbi_scratch *scratch);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -10,32 +10,61 @@
|
|||||||
#ifndef __SBI_IPI_H__
|
#ifndef __SBI_IPI_H__
|
||||||
#define __SBI_IPI_H__
|
#define __SBI_IPI_H__
|
||||||
|
|
||||||
#include <sbi/riscv_unpriv.h>
|
|
||||||
#include <sbi/sbi_types.h>
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
|
||||||
#define SBI_IPI_EVENT_SOFT 0x1
|
#define SBI_IPI_EVENT_MAX __riscv_xlen
|
||||||
#define SBI_IPI_EVENT_FENCE_I 0x2
|
|
||||||
#define SBI_IPI_EVENT_SFENCE_VMA 0x4
|
|
||||||
#define SBI_IPI_EVENT_SFENCE_VMA_ASID 0x8
|
|
||||||
#define SBI_IPI_EVENT_HALT 0x10
|
|
||||||
|
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
struct sbi_scratch;
|
struct sbi_scratch;
|
||||||
|
|
||||||
struct sbi_ipi_data {
|
/** IPI event operations or callbacks */
|
||||||
unsigned long ipi_type;
|
struct sbi_ipi_event_ops {
|
||||||
|
/** Name of the IPI event operations */
|
||||||
|
char name[32];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update callback to save/enqueue data for remote HART
|
||||||
|
* Note: This is an optional callback and it is called just before
|
||||||
|
* triggering IPI to remote HART.
|
||||||
|
*/
|
||||||
|
int (* update)(struct sbi_scratch *scratch,
|
||||||
|
struct sbi_scratch *remote_scratch,
|
||||||
|
u32 remote_hartid, void *data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sync callback to wait for remote HART
|
||||||
|
* Note: This is an optional callback and it is called just after
|
||||||
|
* triggering IPI to remote HART.
|
||||||
|
*/
|
||||||
|
void (* sync)(struct sbi_scratch *scratch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process callback to handle IPI event
|
||||||
|
* Note: This is a mandatory callback and it is called on the
|
||||||
|
* remote HART after IPI is triggered.
|
||||||
|
*/
|
||||||
|
void (* process)(struct sbi_scratch *scratch);
|
||||||
};
|
};
|
||||||
|
|
||||||
int sbi_ipi_send_many(struct sbi_scratch *scratch, struct unpriv_trap *uptrap,
|
int sbi_ipi_send_many(ulong hmask, ulong hbase, u32 event, void *data);
|
||||||
ulong *pmask, u32 event, void *data);
|
|
||||||
|
|
||||||
void sbi_ipi_clear_smode(struct sbi_scratch *scratch);
|
int sbi_ipi_event_create(const struct sbi_ipi_event_ops *ops);
|
||||||
|
|
||||||
void sbi_ipi_process(struct sbi_scratch *scratch);
|
void sbi_ipi_event_destroy(u32 event);
|
||||||
|
|
||||||
|
int sbi_ipi_send_smode(ulong hmask, ulong hbase);
|
||||||
|
|
||||||
|
void sbi_ipi_clear_smode(void);
|
||||||
|
|
||||||
|
int sbi_ipi_send_halt(ulong hmask, ulong hbase);
|
||||||
|
|
||||||
|
void sbi_ipi_process(void);
|
||||||
|
|
||||||
int sbi_ipi_init(struct sbi_scratch *scratch, bool cold_boot);
|
int sbi_ipi_init(struct sbi_scratch *scratch, bool cold_boot);
|
||||||
|
|
||||||
|
void sbi_ipi_exit(struct sbi_scratch *scratch);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
152
include/sbi/sbi_list.h
Normal file
152
include/sbi/sbi_list.h
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Simple doubly-linked list library.
|
||||||
|
*
|
||||||
|
* Adapted from Xvisor source file libs/include/libs/list.h
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SBI_LIST_H__
|
||||||
|
#define __SBI_LIST_H__
|
||||||
|
|
||||||
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
|
#define SBI_LIST_POISON_PREV 0xDEADBEEF
|
||||||
|
#define SBI_LIST_POISON_NEXT 0xFADEBABE
|
||||||
|
|
||||||
|
struct sbi_dlist {
|
||||||
|
struct sbi_dlist *next, *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SBI_LIST_HEAD_INIT(__lname) { &(__lname), &(__lname) }
|
||||||
|
|
||||||
|
#define SBI_LIST_HEAD(_lname) \
|
||||||
|
struct sbi_dlist _lname = SBI_LIST_HEAD_INIT(_lname)
|
||||||
|
|
||||||
|
#define SBI_INIT_LIST_HEAD(ptr) \
|
||||||
|
do { \
|
||||||
|
(ptr)->next = ptr; (ptr)->prev = ptr; \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
static inline void __sbi_list_add(struct sbi_dlist *new,
|
||||||
|
struct sbi_dlist *prev,
|
||||||
|
struct sbi_dlist *next)
|
||||||
|
{
|
||||||
|
new->prev = prev;
|
||||||
|
new->next = next;
|
||||||
|
prev->next = new;
|
||||||
|
next->prev = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the new node after the given head.
|
||||||
|
* @param new New node that needs to be added to list.
|
||||||
|
* @param head List head after which the "new" node should be added.
|
||||||
|
* Note: the new node is added after the head.
|
||||||
|
*/
|
||||||
|
static inline void sbi_list_add(struct sbi_dlist *new, struct sbi_dlist *head)
|
||||||
|
{
|
||||||
|
__sbi_list_add(new, head, head->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a node at the tail where tnode points to tail node.
|
||||||
|
* @param new The new node to be added before tail.
|
||||||
|
* @param tnode The current tail node.
|
||||||
|
* Note: the new node is added before tail node.
|
||||||
|
*/
|
||||||
|
static inline void sbi_list_add_tail(struct sbi_dlist *new,
|
||||||
|
struct sbi_dlist *tnode)
|
||||||
|
{
|
||||||
|
__sbi_list_add(new, tnode->prev, tnode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __sbi_list_del(struct sbi_dlist *prev,
|
||||||
|
struct sbi_dlist *next)
|
||||||
|
{
|
||||||
|
prev->next = next;
|
||||||
|
next->prev = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __sbi_list_del_entry(struct sbi_dlist *entry)
|
||||||
|
{
|
||||||
|
__sbi_list_del(entry->prev, entry->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a given entry from list.
|
||||||
|
* @param node Node to be deleted.
|
||||||
|
*/
|
||||||
|
static inline void sbi_list_del(struct sbi_dlist *entry)
|
||||||
|
{
|
||||||
|
__sbi_list_del(entry->prev, entry->next);
|
||||||
|
entry->next = (void *)SBI_LIST_POISON_NEXT;
|
||||||
|
entry->prev = (void *)SBI_LIST_POISON_PREV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes entry from list and reinitialize it.
|
||||||
|
* @param entry the element to delete from the list.
|
||||||
|
*/
|
||||||
|
static inline void sbi_list_del_init(struct sbi_dlist *entry)
|
||||||
|
{
|
||||||
|
__sbi_list_del_entry(entry);
|
||||||
|
SBI_INIT_LIST_HEAD(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the struct for this entry
|
||||||
|
* @param ptr the &struct list_head pointer.
|
||||||
|
* @param type the type of the struct this is embedded in.
|
||||||
|
* @param member the name of the list_struct within the struct.
|
||||||
|
*/
|
||||||
|
#define sbi_list_entry(ptr, type, member) \
|
||||||
|
container_of(ptr, type, member)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the first element from a list
|
||||||
|
* @param ptr the list head to take the element from.
|
||||||
|
* @param type the type of the struct this is embedded in.
|
||||||
|
* @param member the name of the list_struct within the struct.
|
||||||
|
*
|
||||||
|
* Note: that list is expected to be not empty.
|
||||||
|
*/
|
||||||
|
#define sbi_list_first_entry(ptr, type, member) \
|
||||||
|
sbi_list_entry((ptr)->next, type, member)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the last element from a list
|
||||||
|
* @param ptr the list head to take the element from.
|
||||||
|
* @param type the type of the struct this is embedded in.
|
||||||
|
* @param member the name of the list_head within the struct.
|
||||||
|
*
|
||||||
|
* Note: that list is expected to be not empty.
|
||||||
|
*/
|
||||||
|
#define sbi_list_last_entry(ptr, type, member) \
|
||||||
|
sbi_list_entry((ptr)->prev, type, member)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate over a list
|
||||||
|
* @param pos the &struct list_head to use as a loop cursor.
|
||||||
|
* @param head the head for your list.
|
||||||
|
*/
|
||||||
|
#define sbi_list_for_each(pos, head) \
|
||||||
|
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate over list of given type
|
||||||
|
* @param pos the type * to use as a loop cursor.
|
||||||
|
* @param head the head for your list.
|
||||||
|
* @param member the name of the list_struct within the struct.
|
||||||
|
*/
|
||||||
|
#define sbi_list_for_each_entry(pos, head, member) \
|
||||||
|
for (pos = sbi_list_entry((head)->next, typeof(*pos), member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = sbi_list_entry(pos->member.next, typeof(*pos), member))
|
||||||
|
|
||||||
|
#endif
|
15
include/sbi/sbi_math.h
Normal file
15
include/sbi/sbi_math.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Atish Patra <atish.patra@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SBI_MATH_H__
|
||||||
|
#define __SBI_MATH_H__
|
||||||
|
|
||||||
|
unsigned long log2roundup(unsigned long x);
|
||||||
|
|
||||||
|
#endif
|
@@ -13,14 +13,11 @@
|
|||||||
#include <sbi/sbi_types.h>
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
struct sbi_trap_regs;
|
struct sbi_trap_regs;
|
||||||
struct sbi_scratch;
|
|
||||||
|
|
||||||
int sbi_misaligned_load_handler(u32 hartid, ulong mcause,
|
int sbi_misaligned_load_handler(ulong addr, ulong tval2, ulong tinst,
|
||||||
struct sbi_trap_regs *regs,
|
struct sbi_trap_regs *regs);
|
||||||
struct sbi_scratch *scratch);
|
|
||||||
|
|
||||||
int sbi_misaligned_store_handler(u32 hartid, ulong mcause,
|
int sbi_misaligned_store_handler(ulong addr, ulong tval2, ulong tinst,
|
||||||
struct sbi_trap_regs *regs,
|
struct sbi_trap_regs *regs);
|
||||||
struct sbi_scratch *scratch);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -10,7 +10,8 @@
|
|||||||
#ifndef __SBI_PLATFORM_H__
|
#ifndef __SBI_PLATFORM_H__
|
||||||
#define __SBI_PLATFORM_H__
|
#define __SBI_PLATFORM_H__
|
||||||
|
|
||||||
/** OpenSBI 32-bit platform version with:
|
/**
|
||||||
|
* OpenSBI 32-bit platform version with:
|
||||||
* 1. upper 16-bits as major number
|
* 1. upper 16-bits as major number
|
||||||
* 2. lower 16-bits as minor number
|
* 2. lower 16-bits as minor number
|
||||||
*/
|
*/
|
||||||
@@ -28,17 +29,25 @@
|
|||||||
#define SBI_PLATFORM_HART_COUNT_OFFSET (0x50)
|
#define SBI_PLATFORM_HART_COUNT_OFFSET (0x50)
|
||||||
/** Offset of hart_stack_size in struct sbi_platform */
|
/** Offset of hart_stack_size in struct sbi_platform */
|
||||||
#define SBI_PLATFORM_HART_STACK_SIZE_OFFSET (0x54)
|
#define SBI_PLATFORM_HART_STACK_SIZE_OFFSET (0x54)
|
||||||
/** Offset of disabled_hart_mask in struct sbi_platform */
|
|
||||||
#define SBI_PLATFORM_DISABLED_HART_OFFSET (0x58)
|
|
||||||
/** Offset of platform_ops_addr in struct sbi_platform */
|
/** Offset of platform_ops_addr in struct sbi_platform */
|
||||||
#define SBI_PLATFORM_OPS_OFFSET (0x60)
|
#define SBI_PLATFORM_OPS_OFFSET (0x58)
|
||||||
/** Offset of firmware_context in struct sbi_platform */
|
/** Offset of firmware_context in struct sbi_platform */
|
||||||
#define SBI_PLATFORM_FIRMWARE_CONTEXT_OFFSET (0x60 + __SIZEOF_POINTER__)
|
#define SBI_PLATFORM_FIRMWARE_CONTEXT_OFFSET (0x58 + __SIZEOF_POINTER__)
|
||||||
|
/** Offset of hart_index2id in struct sbi_platform */
|
||||||
|
#define SBI_PLATFORM_HART_INDEX2ID_OFFSET (0x58 + (__SIZEOF_POINTER__ * 2))
|
||||||
|
|
||||||
|
#define SBI_PLATFORM_TLB_RANGE_FLUSH_LIMIT_DEFAULT (1UL << 12)
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#include <sbi/sbi_version.h>
|
#include <sbi/sbi_ecall_interface.h>
|
||||||
|
#include <sbi/sbi_error.h>
|
||||||
#include <sbi/sbi_scratch.h>
|
#include <sbi/sbi_scratch.h>
|
||||||
|
#include <sbi/sbi_version.h>
|
||||||
|
|
||||||
|
struct sbi_domain_memregion;
|
||||||
|
struct sbi_trap_info;
|
||||||
|
struct sbi_trap_regs;
|
||||||
|
|
||||||
/** Possible feature flags of a platform */
|
/** Possible feature flags of a platform */
|
||||||
enum sbi_platform_features {
|
enum sbi_platform_features {
|
||||||
@@ -46,21 +55,18 @@ enum sbi_platform_features {
|
|||||||
SBI_PLATFORM_HAS_TIMER_VALUE = (1 << 0),
|
SBI_PLATFORM_HAS_TIMER_VALUE = (1 << 0),
|
||||||
/** Platform has HART hotplug support */
|
/** Platform has HART hotplug support */
|
||||||
SBI_PLATFORM_HAS_HART_HOTPLUG = (1 << 1),
|
SBI_PLATFORM_HAS_HART_HOTPLUG = (1 << 1),
|
||||||
/** Platform has PMP support */
|
|
||||||
SBI_PLATFORM_HAS_PMP = (1 << 2),
|
|
||||||
/** Platform has S-mode counter enable */
|
|
||||||
SBI_PLATFORM_HAS_SCOUNTEREN = (1 << 3),
|
|
||||||
/** Platform has M-mode counter enable */
|
|
||||||
SBI_PLATFORM_HAS_MCOUNTEREN = (1 << 4),
|
|
||||||
/** Platform has fault delegation support */
|
/** Platform has fault delegation support */
|
||||||
SBI_PLATFORM_HAS_MFAULTS_DELEGATION = (1 << 5),
|
SBI_PLATFORM_HAS_MFAULTS_DELEGATION = (1 << 2),
|
||||||
|
/** Platform has custom secondary hart booting support */
|
||||||
|
SBI_PLATFORM_HAS_HART_SECONDARY_BOOT = (1 << 3),
|
||||||
|
|
||||||
|
/** Last index of Platform features*/
|
||||||
|
SBI_PLATFORM_HAS_LAST_FEATURE = SBI_PLATFORM_HAS_HART_SECONDARY_BOOT,
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Default feature set for a platform */
|
/** Default feature set for a platform */
|
||||||
#define SBI_PLATFORM_DEFAULT_FEATURES \
|
#define SBI_PLATFORM_DEFAULT_FEATURES \
|
||||||
(SBI_PLATFORM_HAS_TIMER_VALUE | SBI_PLATFORM_HAS_PMP | \
|
(SBI_PLATFORM_HAS_TIMER_VALUE | SBI_PLATFORM_HAS_MFAULTS_DELEGATION)
|
||||||
SBI_PLATFORM_HAS_SCOUNTEREN | SBI_PLATFORM_HAS_MCOUNTEREN | \
|
|
||||||
SBI_PLATFORM_HAS_MFAULTS_DELEGATION)
|
|
||||||
|
|
||||||
/** Platform functions */
|
/** Platform functions */
|
||||||
struct sbi_platform_operations {
|
struct sbi_platform_operations {
|
||||||
@@ -69,14 +75,27 @@ struct sbi_platform_operations {
|
|||||||
/** Platform final initialization */
|
/** Platform final initialization */
|
||||||
int (*final_init)(bool cold_boot);
|
int (*final_init)(bool cold_boot);
|
||||||
|
|
||||||
/** Get number of PMP regions for given HART */
|
/** Platform early exit */
|
||||||
u32 (*pmp_region_count)(u32 hartid);
|
void (*early_exit)(void);
|
||||||
|
/** Platform final exit */
|
||||||
|
void (*final_exit)(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get PMP regions details (namely: protection, base address,
|
* For platforms that do not implement misa, non-standard
|
||||||
* and size) for given HART
|
* methods are needed to determine cpu extension.
|
||||||
*/
|
*/
|
||||||
int (*pmp_region_info)(u32 hartid, u32 index, ulong *prot, ulong *addr,
|
int (*misa_check_extension)(char ext);
|
||||||
ulong *log2size);
|
|
||||||
|
/**
|
||||||
|
* For platforms that do not implement misa, non-standard
|
||||||
|
* methods are needed to get MXL field of misa.
|
||||||
|
*/
|
||||||
|
int (*misa_get_xlen)(void);
|
||||||
|
|
||||||
|
/** Get platform specific root domain memory regions */
|
||||||
|
struct sbi_domain_memregion *(*domains_root_regions)(void);
|
||||||
|
/** Initialize (or populate) domains for the platform */
|
||||||
|
int (*domains_init)(void);
|
||||||
|
|
||||||
/** Write a character to the platform console output */
|
/** Write a character to the platform console output */
|
||||||
void (*console_putc)(char ch);
|
void (*console_putc)(char ch);
|
||||||
@@ -87,15 +106,20 @@ struct sbi_platform_operations {
|
|||||||
|
|
||||||
/** Initialize the platform interrupt controller for current HART */
|
/** Initialize the platform interrupt controller for current HART */
|
||||||
int (*irqchip_init)(bool cold_boot);
|
int (*irqchip_init)(bool cold_boot);
|
||||||
|
/** Exit the platform interrupt controller for current HART */
|
||||||
|
void (*irqchip_exit)(void);
|
||||||
|
|
||||||
/** Send IPI to a target HART */
|
/** Send IPI to a target HART */
|
||||||
void (*ipi_send)(u32 target_hart);
|
void (*ipi_send)(u32 target_hart);
|
||||||
/** Wait for target HART to acknowledge IPI */
|
|
||||||
void (*ipi_sync)(u32 target_hart);
|
|
||||||
/** Clear IPI for a target HART */
|
/** Clear IPI for a target HART */
|
||||||
void (*ipi_clear)(u32 target_hart);
|
void (*ipi_clear)(u32 target_hart);
|
||||||
/** Initialize IPI for current HART */
|
/** Initialize IPI for current HART */
|
||||||
int (*ipi_init)(bool cold_boot);
|
int (*ipi_init)(bool cold_boot);
|
||||||
|
/** Exit IPI for current HART */
|
||||||
|
void (*ipi_exit)(void);
|
||||||
|
|
||||||
|
/** Get tlb flush limit value **/
|
||||||
|
u64 (*get_tlbr_flush_limit)(void);
|
||||||
|
|
||||||
/** Get platform timer value */
|
/** Get platform timer value */
|
||||||
u64 (*timer_value)(void);
|
u64 (*timer_value)(void);
|
||||||
@@ -105,12 +129,33 @@ struct sbi_platform_operations {
|
|||||||
void (*timer_event_stop)(void);
|
void (*timer_event_stop)(void);
|
||||||
/** Initialize platform timer for current HART */
|
/** Initialize platform timer for current HART */
|
||||||
int (*timer_init)(bool cold_boot);
|
int (*timer_init)(bool cold_boot);
|
||||||
|
/** Exit platform timer for current HART */
|
||||||
|
void (*timer_exit)(void);
|
||||||
|
|
||||||
/** Reboot the platform */
|
/** Bringup the given hart */
|
||||||
int (*system_reboot)(u32 type);
|
int (*hart_start)(u32 hartid, ulong saddr);
|
||||||
/** Shutdown or poweroff the platform */
|
/**
|
||||||
int (*system_shutdown)(u32 type);
|
* Stop the current hart from running. This call doesn't expect to
|
||||||
} __packed;
|
* return if success.
|
||||||
|
*/
|
||||||
|
int (*hart_stop)(void);
|
||||||
|
|
||||||
|
/* Check whether reset type and reason supported by the platform */
|
||||||
|
int (*system_reset_check)(u32 reset_type, u32 reset_reason);
|
||||||
|
/** Reset the platform */
|
||||||
|
void (*system_reset)(u32 reset_type, u32 reset_reason);
|
||||||
|
|
||||||
|
/** platform specific SBI extension implementation probe function */
|
||||||
|
int (*vendor_ext_check)(long extid);
|
||||||
|
/** platform specific SBI extension implementation provider */
|
||||||
|
int (*vendor_ext_provider)(long extid, long funcid,
|
||||||
|
const struct sbi_trap_regs *regs,
|
||||||
|
unsigned long *out_value,
|
||||||
|
struct sbi_trap_info *out_trap);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Platform default per-HART stack size for exception/interrupt handling */
|
||||||
|
#define SBI_PLATFORM_DEFAULT_HART_STACK_SIZE 8192
|
||||||
|
|
||||||
/** Representation of a platform */
|
/** Representation of a platform */
|
||||||
struct sbi_platform {
|
struct sbi_platform {
|
||||||
@@ -134,13 +179,27 @@ struct sbi_platform {
|
|||||||
u32 hart_count;
|
u32 hart_count;
|
||||||
/** Per-HART stack size for exception/interrupt handling */
|
/** Per-HART stack size for exception/interrupt handling */
|
||||||
u32 hart_stack_size;
|
u32 hart_stack_size;
|
||||||
/** Mask representing the set of disabled HARTs */
|
|
||||||
u64 disabled_hart_mask;
|
|
||||||
/** Pointer to sbi platform operations */
|
/** Pointer to sbi platform operations */
|
||||||
unsigned long platform_ops_addr;
|
unsigned long platform_ops_addr;
|
||||||
/** Pointer to system firmware specific context */
|
/** Pointer to system firmware specific context */
|
||||||
unsigned long firmware_context;
|
unsigned long firmware_context;
|
||||||
} __packed;
|
/**
|
||||||
|
* HART index to HART id table
|
||||||
|
*
|
||||||
|
* For used HART index <abc>:
|
||||||
|
* hart_index2id[<abc>] = some HART id
|
||||||
|
* For unused HART index <abc>:
|
||||||
|
* hart_index2id[<abc>] = -1U
|
||||||
|
*
|
||||||
|
* If hart_index2id == NULL then we assume identity mapping
|
||||||
|
* hart_index2id[<abc>] = <abc>
|
||||||
|
*
|
||||||
|
* We have only two restrictions:
|
||||||
|
* 1. HART index < sbi_platform hart_count
|
||||||
|
* 2. HART id < SBI_HARTMASK_MAX_BITS
|
||||||
|
*/
|
||||||
|
const u32 *hart_index2id;
|
||||||
|
};
|
||||||
|
|
||||||
/** Get pointer to sbi_platform for sbi_scratch pointer */
|
/** Get pointer to sbi_platform for sbi_scratch pointer */
|
||||||
#define sbi_platform_ptr(__s) \
|
#define sbi_platform_ptr(__s) \
|
||||||
@@ -158,46 +217,78 @@ struct sbi_platform {
|
|||||||
/** Check whether the platform supports HART hotplug */
|
/** Check whether the platform supports HART hotplug */
|
||||||
#define sbi_platform_has_hart_hotplug(__p) \
|
#define sbi_platform_has_hart_hotplug(__p) \
|
||||||
((__p)->features & SBI_PLATFORM_HAS_HART_HOTPLUG)
|
((__p)->features & SBI_PLATFORM_HAS_HART_HOTPLUG)
|
||||||
/** Check whether the platform has PMP support */
|
|
||||||
#define sbi_platform_has_pmp(__p) ((__p)->features & SBI_PLATFORM_HAS_PMP)
|
|
||||||
/** Check whether the platform supports scounteren CSR */
|
|
||||||
#define sbi_platform_has_scounteren(__p) \
|
|
||||||
((__p)->features & SBI_PLATFORM_HAS_SCOUNTEREN)
|
|
||||||
/** Check whether the platform supports mcounteren CSR */
|
|
||||||
#define sbi_platform_has_mcounteren(__p) \
|
|
||||||
((__p)->features & SBI_PLATFORM_HAS_MCOUNTEREN)
|
|
||||||
/** Check whether the platform supports fault delegation */
|
/** Check whether the platform supports fault delegation */
|
||||||
#define sbi_platform_has_mfaults_delegation(__p) \
|
#define sbi_platform_has_mfaults_delegation(__p) \
|
||||||
((__p)->features & SBI_PLATFORM_HAS_MFAULTS_DELEGATION)
|
((__p)->features & SBI_PLATFORM_HAS_MFAULTS_DELEGATION)
|
||||||
|
/** Check whether the platform supports custom secondary hart booting support */
|
||||||
|
#define sbi_platform_has_hart_secondary_boot(__p) \
|
||||||
|
((__p)->features & SBI_PLATFORM_HAS_HART_SECONDARY_BOOT)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get HART index for the given HART
|
||||||
|
*
|
||||||
|
* @param plat pointer to struct sbi_platform
|
||||||
|
* @param hartid HART ID
|
||||||
|
*
|
||||||
|
* @return 0 <= value < hart_count for valid HART otherwise -1U
|
||||||
|
*/
|
||||||
|
u32 sbi_platform_hart_index(const struct sbi_platform *plat, u32 hartid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the platform features in string format
|
||||||
|
*
|
||||||
|
* @param plat pointer to struct sbi_platform
|
||||||
|
* @param features_str pointer to a char array where the features string will be
|
||||||
|
* updated
|
||||||
|
* @param nfstr length of the features_str. The feature string will be truncated
|
||||||
|
* if nfstr is not long enough.
|
||||||
|
*/
|
||||||
|
void sbi_platform_get_features_str(const struct sbi_platform *plat,
|
||||||
|
char *features_str, int nfstr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get name of the platform
|
* Get name of the platform
|
||||||
*
|
*
|
||||||
* @param plat pointer to struct sbi_platform
|
* @param plat pointer to struct sbi_platform
|
||||||
*
|
*
|
||||||
* @return pointer to platform name on success and NULL on failure
|
* @return pointer to platform name on success and "Unknown" on failure
|
||||||
*/
|
*/
|
||||||
static inline const char *sbi_platform_name(const struct sbi_platform *plat)
|
static inline const char *sbi_platform_name(const struct sbi_platform *plat)
|
||||||
{
|
{
|
||||||
if (plat)
|
if (plat)
|
||||||
return plat->name;
|
return plat->name;
|
||||||
return NULL;
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the given HART is disabled
|
* Get the platform features
|
||||||
*
|
*
|
||||||
* @param plat pointer to struct sbi_platform
|
* @param plat pointer to struct sbi_platform
|
||||||
* @param hartid HART ID
|
|
||||||
*
|
*
|
||||||
* @return TRUE if HART is disabled and FALSE otherwise
|
* @return the features value currently set for the given platform
|
||||||
*/
|
*/
|
||||||
static inline bool sbi_platform_hart_disabled(const struct sbi_platform *plat,
|
static inline unsigned long sbi_platform_get_features(
|
||||||
u32 hartid)
|
const struct sbi_platform *plat)
|
||||||
{
|
{
|
||||||
if (plat && (plat->disabled_hart_mask & (1 << hartid)))
|
if (plat)
|
||||||
return TRUE;
|
return plat->features;
|
||||||
return FALSE;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get platform specific tlb range flush maximum value. Any request with size
|
||||||
|
* higher than this is upgraded to a full flush.
|
||||||
|
*
|
||||||
|
* @param plat pointer to struct sbi_platform
|
||||||
|
*
|
||||||
|
* @return tlb range flush limit value. Returns a default (page size) if not
|
||||||
|
* defined by platform.
|
||||||
|
*/
|
||||||
|
static inline u64 sbi_platform_tlbr_flush_limit(const struct sbi_platform *plat)
|
||||||
|
{
|
||||||
|
if (plat && sbi_platform_ops(plat)->get_tlbr_flush_limit)
|
||||||
|
return sbi_platform_ops(plat)->get_tlbr_flush_limit();
|
||||||
|
return SBI_PLATFORM_TLB_RANGE_FLUSH_LIMIT_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -228,6 +319,57 @@ static inline u32 sbi_platform_hart_stack_size(const struct sbi_platform *plat)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether given HART is invalid
|
||||||
|
*
|
||||||
|
* @param plat pointer to struct sbi_platform
|
||||||
|
* @param hartid HART ID
|
||||||
|
*
|
||||||
|
* @return TRUE if HART is invalid and FALSE otherwise
|
||||||
|
*/
|
||||||
|
static inline bool sbi_platform_hart_invalid(const struct sbi_platform *plat,
|
||||||
|
u32 hartid)
|
||||||
|
{
|
||||||
|
if (!plat)
|
||||||
|
return TRUE;
|
||||||
|
if (plat->hart_count <= sbi_platform_hart_index(plat, hartid))
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bringup a given hart from previous stage. Platform should implement this
|
||||||
|
* operation if they support a custom mechanism to start a hart. Otherwise,
|
||||||
|
* a generic WFI based approach will be used to start/stop a hart in OpenSBI.
|
||||||
|
*
|
||||||
|
* @param plat pointer to struct sbi_platform
|
||||||
|
* @param hartid HART id
|
||||||
|
* @param saddr M-mode start physical address for the HART
|
||||||
|
*
|
||||||
|
* @return 0 if sucessful and negative error code on failure
|
||||||
|
*/
|
||||||
|
static inline int sbi_platform_hart_start(const struct sbi_platform *plat,
|
||||||
|
u32 hartid, ulong saddr)
|
||||||
|
{
|
||||||
|
if (plat && sbi_platform_ops(plat)->hart_start)
|
||||||
|
return sbi_platform_ops(plat)->hart_start(hartid, saddr);
|
||||||
|
return SBI_ENOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the current hart in OpenSBI.
|
||||||
|
*
|
||||||
|
* @param plat pointer to struct sbi_platform
|
||||||
|
*
|
||||||
|
* @return Negative error code on failure. It doesn't return on success.
|
||||||
|
*/
|
||||||
|
static inline int sbi_platform_hart_stop(const struct sbi_platform *plat)
|
||||||
|
{
|
||||||
|
if (plat && sbi_platform_ops(plat)->hart_stop)
|
||||||
|
return sbi_platform_ops(plat)->hart_stop();
|
||||||
|
return SBI_ENOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Early initialization for current HART
|
* Early initialization for current HART
|
||||||
*
|
*
|
||||||
@@ -261,42 +403,84 @@ static inline int sbi_platform_final_init(const struct sbi_platform *plat,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of PMP regions of a HART
|
* Early exit for current HART
|
||||||
*
|
*
|
||||||
* @param plat pointer to struct sbi_platform
|
* @param plat pointer to struct sbi_platform
|
||||||
* @param hartid HART ID
|
|
||||||
*
|
|
||||||
* @return number of PMP regions
|
|
||||||
*/
|
*/
|
||||||
static inline u32 sbi_platform_pmp_region_count(const struct sbi_platform *plat,
|
static inline void sbi_platform_early_exit(const struct sbi_platform *plat)
|
||||||
u32 hartid)
|
|
||||||
{
|
{
|
||||||
if (plat && sbi_platform_ops(plat)->pmp_region_count)
|
if (plat && sbi_platform_ops(plat)->early_exit)
|
||||||
return sbi_platform_ops(plat)->pmp_region_count(hartid);
|
sbi_platform_ops(plat)->early_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Final exit for current HART
|
||||||
|
*
|
||||||
|
* @param plat pointer to struct sbi_platform
|
||||||
|
*/
|
||||||
|
static inline void sbi_platform_final_exit(const struct sbi_platform *plat)
|
||||||
|
{
|
||||||
|
if (plat && sbi_platform_ops(plat)->final_exit)
|
||||||
|
sbi_platform_ops(plat)->final_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check CPU extension in MISA
|
||||||
|
*
|
||||||
|
* @param plat pointer to struct sbi_platform
|
||||||
|
* @param ext shorthand letter for CPU extensions
|
||||||
|
*
|
||||||
|
* @return zero for not-supported and non-zero for supported
|
||||||
|
*/
|
||||||
|
static inline int sbi_platform_misa_extension(const struct sbi_platform *plat,
|
||||||
|
char ext)
|
||||||
|
{
|
||||||
|
if (plat && sbi_platform_ops(plat)->misa_check_extension)
|
||||||
|
return sbi_platform_ops(plat)->misa_check_extension(ext);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get PMP regions details (namely: protection, base address,
|
* Get MXL field of MISA
|
||||||
* and size) of a HART
|
*
|
||||||
|
* @param plat pointer to struct sbi_platform
|
||||||
|
*
|
||||||
|
* @return 1/2/3 on success and error code on failure
|
||||||
|
*/
|
||||||
|
static inline int sbi_platform_misa_xlen(const struct sbi_platform *plat)
|
||||||
|
{
|
||||||
|
if (plat && sbi_platform_ops(plat)->misa_get_xlen)
|
||||||
|
return sbi_platform_ops(plat)->misa_get_xlen();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get platform specific root domain memory regions
|
||||||
|
*
|
||||||
|
* @param plat pointer to struct sbi_platform
|
||||||
|
*
|
||||||
|
* @return an array of memory regions terminated by a region with order zero
|
||||||
|
* or NULL for no memory regions
|
||||||
|
*/
|
||||||
|
static inline struct sbi_domain_memregion *
|
||||||
|
sbi_platform_domains_root_regions(const struct sbi_platform *plat)
|
||||||
|
{
|
||||||
|
if (plat && sbi_platform_ops(plat)->domains_root_regions)
|
||||||
|
return sbi_platform_ops(plat)->domains_root_regions();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize (or populate) domains for the platform
|
||||||
*
|
*
|
||||||
* @param plat pointer to struct sbi_platform
|
* @param plat pointer to struct sbi_platform
|
||||||
* @param hartid HART ID
|
|
||||||
* @param index index of PMP region for which we want details
|
|
||||||
* @param prot output pointer for PMP region protection
|
|
||||||
* @param addr output pointer for PMP region base address
|
|
||||||
* @param log2size output pointer for log-of-2 PMP region size
|
|
||||||
*
|
*
|
||||||
* @return 0 on success and negative error code on failure
|
* @return 0 on success and negative error code on failure
|
||||||
*/
|
*/
|
||||||
static inline int sbi_platform_pmp_region_info(const struct sbi_platform *plat,
|
static inline int sbi_platform_domains_init(const struct sbi_platform *plat)
|
||||||
u32 hartid, u32 index,
|
|
||||||
ulong *prot, ulong *addr,
|
|
||||||
ulong *log2size)
|
|
||||||
{
|
{
|
||||||
if (plat && sbi_platform_ops(plat)->pmp_region_info)
|
if (plat && sbi_platform_ops(plat)->domains_init)
|
||||||
return sbi_platform_ops(plat)->pmp_region_info(hartid, index, prot, addr,
|
return sbi_platform_ops(plat)->domains_init();
|
||||||
log2size);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,6 +541,17 @@ static inline int sbi_platform_irqchip_init(const struct sbi_platform *plat,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exit the platform interrupt controller for current HART
|
||||||
|
*
|
||||||
|
* @param plat pointer to struct sbi_platform
|
||||||
|
*/
|
||||||
|
static inline void sbi_platform_irqchip_exit(const struct sbi_platform *plat)
|
||||||
|
{
|
||||||
|
if (plat && sbi_platform_ops(plat)->irqchip_exit)
|
||||||
|
sbi_platform_ops(plat)->irqchip_exit();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send IPI to a target HART
|
* Send IPI to a target HART
|
||||||
*
|
*
|
||||||
@@ -370,19 +565,6 @@ static inline void sbi_platform_ipi_send(const struct sbi_platform *plat,
|
|||||||
sbi_platform_ops(plat)->ipi_send(target_hart);
|
sbi_platform_ops(plat)->ipi_send(target_hart);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for target HART to acknowledge IPI
|
|
||||||
*
|
|
||||||
* @param plat pointer to struct sbi_platform
|
|
||||||
* @param target_hart HART ID of IPI target
|
|
||||||
*/
|
|
||||||
static inline void sbi_platform_ipi_sync(const struct sbi_platform *plat,
|
|
||||||
u32 target_hart)
|
|
||||||
{
|
|
||||||
if (plat && sbi_platform_ops(plat)->ipi_sync)
|
|
||||||
sbi_platform_ops(plat)->ipi_sync(target_hart);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear IPI for a target HART
|
* Clear IPI for a target HART
|
||||||
*
|
*
|
||||||
@@ -412,12 +594,23 @@ static inline int sbi_platform_ipi_init(const struct sbi_platform *plat,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exit the platform IPI support for current HART
|
||||||
|
*
|
||||||
|
* @param plat pointer to struct sbi_platform
|
||||||
|
*/
|
||||||
|
static inline void sbi_platform_ipi_exit(const struct sbi_platform *plat)
|
||||||
|
{
|
||||||
|
if (plat && sbi_platform_ops(plat)->ipi_exit)
|
||||||
|
sbi_platform_ops(plat)->ipi_exit();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get platform timer value
|
* Get platform timer value
|
||||||
*
|
*
|
||||||
* @param plat pointer to struct sbi_platform
|
* @param plat pointer to struct sbi_platform
|
||||||
*
|
*
|
||||||
* @return 64bit timer value
|
* @return 64-bit timer value
|
||||||
*/
|
*/
|
||||||
static inline u64 sbi_platform_timer_value(const struct sbi_platform *plat)
|
static inline u64 sbi_platform_timer_value(const struct sbi_platform *plat)
|
||||||
{
|
{
|
||||||
@@ -468,35 +661,95 @@ static inline int sbi_platform_timer_init(const struct sbi_platform *plat,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reboot the platform
|
* Exit the platform timer for current HART
|
||||||
*
|
*
|
||||||
* @param plat pointer to struct sbi_platform
|
* @param plat pointer to struct sbi_platform
|
||||||
* @param type type of reboot
|
|
||||||
*
|
|
||||||
* @return 0 on success and negative error code on failure
|
|
||||||
*/
|
*/
|
||||||
static inline int sbi_platform_system_reboot(const struct sbi_platform *plat,
|
static inline void sbi_platform_timer_exit(const struct sbi_platform *plat)
|
||||||
u32 type)
|
|
||||||
{
|
{
|
||||||
if (plat && sbi_platform_ops(plat)->system_reboot)
|
if (plat && sbi_platform_ops(plat)->timer_exit)
|
||||||
return sbi_platform_ops(plat)->system_reboot(type);
|
sbi_platform_ops(plat)->timer_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether reset type and reason supported by the platform
|
||||||
|
*
|
||||||
|
* @param plat pointer to struct sbi_platform
|
||||||
|
* @param reset_type type of reset
|
||||||
|
* @param reset_reason reason for reset
|
||||||
|
*
|
||||||
|
* @return 0 if reset type and reason not supported and 1 if supported
|
||||||
|
*/
|
||||||
|
static inline int sbi_platform_system_reset_check(
|
||||||
|
const struct sbi_platform *plat,
|
||||||
|
u32 reset_type, u32 reset_reason)
|
||||||
|
{
|
||||||
|
if (plat && sbi_platform_ops(plat)->system_reset_check)
|
||||||
|
return sbi_platform_ops(plat)->system_reset_check(reset_type,
|
||||||
|
reset_reason);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shutdown or poweroff the platform
|
* Reset the platform
|
||||||
|
*
|
||||||
|
* This function will not return for supported reset type and reset reason
|
||||||
*
|
*
|
||||||
* @param plat pointer to struct sbi_platform
|
* @param plat pointer to struct sbi_platform
|
||||||
* @param type type of shutdown or poweroff
|
* @param reset_type type of reset
|
||||||
|
* @param reset_reason reason for reset
|
||||||
|
*/
|
||||||
|
static inline void sbi_platform_system_reset(const struct sbi_platform *plat,
|
||||||
|
u32 reset_type, u32 reset_reason)
|
||||||
|
{
|
||||||
|
if (plat && sbi_platform_ops(plat)->system_reset)
|
||||||
|
sbi_platform_ops(plat)->system_reset(reset_type, reset_reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a vendor extension is implemented or not.
|
||||||
|
*
|
||||||
|
* @param plat pointer to struct sbi_platform
|
||||||
|
* @param extid vendor SBI extension id
|
||||||
|
*
|
||||||
|
* @return 0 if extid is not implemented and 1 if implemented
|
||||||
|
*/
|
||||||
|
static inline int sbi_platform_vendor_ext_check(const struct sbi_platform *plat,
|
||||||
|
long extid)
|
||||||
|
{
|
||||||
|
if (plat && sbi_platform_ops(plat)->vendor_ext_check)
|
||||||
|
return sbi_platform_ops(plat)->vendor_ext_check(extid);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke platform specific vendor SBI extension implementation.
|
||||||
|
*
|
||||||
|
* @param plat pointer to struct sbi_platform
|
||||||
|
* @param extid vendor SBI extension id
|
||||||
|
* @param funcid SBI function id within the extension id
|
||||||
|
* @param regs pointer to trap registers passed by the caller
|
||||||
|
* @param out_value output value that can be filled by the callee
|
||||||
|
* @param out_trap trap info that can be filled by the callee
|
||||||
*
|
*
|
||||||
* @return 0 on success and negative error code on failure
|
* @return 0 on success and negative error code on failure
|
||||||
*/
|
*/
|
||||||
static inline int sbi_platform_system_shutdown(const struct sbi_platform *plat,
|
static inline int sbi_platform_vendor_ext_provider(
|
||||||
u32 type)
|
const struct sbi_platform *plat,
|
||||||
|
long extid, long funcid,
|
||||||
|
const struct sbi_trap_regs *regs,
|
||||||
|
unsigned long *out_value,
|
||||||
|
struct sbi_trap_info *out_trap)
|
||||||
{
|
{
|
||||||
if (plat && sbi_platform_ops(plat)->system_shutdown)
|
if (plat && sbi_platform_ops(plat)->vendor_ext_provider) {
|
||||||
return sbi_platform_ops(plat)->system_shutdown(type);
|
return sbi_platform_ops(plat)->vendor_ext_provider(extid,
|
||||||
return 0;
|
funcid, regs,
|
||||||
|
out_value,
|
||||||
|
out_trap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SBI_ENOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -30,21 +30,22 @@
|
|||||||
#define SBI_SCRATCH_PLATFORM_ADDR_OFFSET (6 * __SIZEOF_POINTER__)
|
#define SBI_SCRATCH_PLATFORM_ADDR_OFFSET (6 * __SIZEOF_POINTER__)
|
||||||
/** Offset of hartid_to_scratch member in sbi_scratch */
|
/** Offset of hartid_to_scratch member in sbi_scratch */
|
||||||
#define SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET (7 * __SIZEOF_POINTER__)
|
#define SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET (7 * __SIZEOF_POINTER__)
|
||||||
|
/** Offset of trap_exit member in sbi_scratch */
|
||||||
|
#define SBI_SCRATCH_TRAP_EXIT_OFFSET (8 * __SIZEOF_POINTER__)
|
||||||
/** Offset of tmp0 member in sbi_scratch */
|
/** Offset of tmp0 member in sbi_scratch */
|
||||||
#define SBI_SCRATCH_TMP0_OFFSET (8 * __SIZEOF_POINTER__)
|
#define SBI_SCRATCH_TMP0_OFFSET (9 * __SIZEOF_POINTER__)
|
||||||
/** Offset of options member in sbi_scratch */
|
/** Offset of options member in sbi_scratch */
|
||||||
#define SBI_SCRATCH_OPTIONS_OFFSET (9 * __SIZEOF_POINTER__)
|
#define SBI_SCRATCH_OPTIONS_OFFSET (10 * __SIZEOF_POINTER__)
|
||||||
/** Offset of extra space in sbi_scratch */
|
/** Offset of extra space in sbi_scratch */
|
||||||
#define SBI_SCRATCH_EXTRA_SPACE_OFFSET (10 * __SIZEOF_POINTER__)
|
#define SBI_SCRATCH_EXTRA_SPACE_OFFSET (11 * __SIZEOF_POINTER__)
|
||||||
/** Maximum size of sbi_scratch and sbi_ipi_data */
|
/** Maximum size of sbi_scratch (4KB) */
|
||||||
#define SBI_SCRATCH_SIZE (64 * __SIZEOF_POINTER__)
|
#define SBI_SCRATCH_SIZE (0x1000)
|
||||||
|
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#include <sbi/sbi_types.h>
|
#include <sbi/sbi_types.h>
|
||||||
#include <sbi/sbi_ipi.h>
|
|
||||||
|
|
||||||
/** Representation of per-HART scratch space */
|
/** Representation of per-HART scratch space */
|
||||||
struct sbi_scratch {
|
struct sbi_scratch {
|
||||||
@@ -64,16 +65,20 @@ struct sbi_scratch {
|
|||||||
unsigned long platform_addr;
|
unsigned long platform_addr;
|
||||||
/** Address of HART ID to sbi_scratch conversion function */
|
/** Address of HART ID to sbi_scratch conversion function */
|
||||||
unsigned long hartid_to_scratch;
|
unsigned long hartid_to_scratch;
|
||||||
|
/** Address of trap exit function */
|
||||||
|
unsigned long trap_exit;
|
||||||
/** Temporary storage */
|
/** Temporary storage */
|
||||||
unsigned long tmp0;
|
unsigned long tmp0;
|
||||||
/** Options for OpenSBI library */
|
/** Options for OpenSBI library */
|
||||||
unsigned long options;
|
unsigned long options;
|
||||||
} __packed;
|
};
|
||||||
|
|
||||||
/** Possible options for OpenSBI library */
|
/** Possible options for OpenSBI library */
|
||||||
enum sbi_scratch_options {
|
enum sbi_scratch_options {
|
||||||
/** Disable prints during boot */
|
/** Disable prints during boot */
|
||||||
SBI_SCRATCH_NO_BOOT_PRINTS = (1 << 0),
|
SBI_SCRATCH_NO_BOOT_PRINTS = (1 << 0),
|
||||||
|
/** Enable runtime debug prints */
|
||||||
|
SBI_SCRATCH_DEBUG_PRINTS = (1 << 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Get pointer to sbi_scratch for current HART */
|
/** Get pointer to sbi_scratch for current HART */
|
||||||
@@ -84,7 +89,11 @@ enum sbi_scratch_options {
|
|||||||
#define sbi_scratch_thishart_arg1_ptr() \
|
#define sbi_scratch_thishart_arg1_ptr() \
|
||||||
((void *)(sbi_scratch_thishart_ptr()->next_arg1))
|
((void *)(sbi_scratch_thishart_ptr()->next_arg1))
|
||||||
|
|
||||||
/** Allocate from extra space in sbi_scratch
|
/** Initialize scratch table and allocator */
|
||||||
|
int sbi_scratch_init(struct sbi_scratch *scratch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate from extra space in sbi_scratch
|
||||||
*
|
*
|
||||||
* @return zero on failure and non-zero (>= SBI_SCRATCH_EXTRA_SPACE_OFFSET)
|
* @return zero on failure and non-zero (>= SBI_SCRATCH_EXTRA_SPACE_OFFSET)
|
||||||
* on success
|
* on success
|
||||||
@@ -101,6 +110,19 @@ void sbi_scratch_free_offset(unsigned long offset);
|
|||||||
#define sbi_scratch_thishart_offset_ptr(offset) \
|
#define sbi_scratch_thishart_offset_ptr(offset) \
|
||||||
((void *)sbi_scratch_thishart_ptr() + (offset))
|
((void *)sbi_scratch_thishart_ptr() + (offset))
|
||||||
|
|
||||||
|
/** HART id to scratch table */
|
||||||
|
extern struct sbi_scratch *hartid_to_scratch_table[];
|
||||||
|
|
||||||
|
/** Get sbi_scratch from HART id */
|
||||||
|
#define sbi_hartid_to_scratch(__hartid) \
|
||||||
|
hartid_to_scratch_table[__hartid]
|
||||||
|
|
||||||
|
/** Last HART id having a sbi_scratch pointer */
|
||||||
|
extern u32 last_hartid_having_scratch;
|
||||||
|
|
||||||
|
/** Get last HART id having a sbi_scratch pointer */
|
||||||
|
#define sbi_scratch_last_hartid() last_hartid_having_scratch
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -12,8 +12,15 @@
|
|||||||
|
|
||||||
#include <sbi/sbi_types.h>
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Provides sbi_strcmp for the completeness of supporting string functions.
|
||||||
|
it is not recommended to use sbi_strcmp() but use sbi_strncmp instead.
|
||||||
|
*/
|
||||||
|
|
||||||
int sbi_strcmp(const char *a, const char *b);
|
int sbi_strcmp(const char *a, const char *b);
|
||||||
|
|
||||||
|
int sbi_strncmp(const char *a, const char *b, size_t count);
|
||||||
|
|
||||||
size_t sbi_strlen(const char *str);
|
size_t sbi_strlen(const char *str);
|
||||||
|
|
||||||
size_t sbi_strnlen(const char *str, size_t count);
|
size_t sbi_strnlen(const char *str, size_t count);
|
||||||
|
@@ -12,16 +12,8 @@
|
|||||||
|
|
||||||
#include <sbi/sbi_types.h>
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
struct sbi_scratch;
|
bool sbi_system_reset_supported(u32 reset_type, u32 reset_reason);
|
||||||
|
|
||||||
int sbi_system_early_init(struct sbi_scratch *scratch, bool cold_boot);
|
void __noreturn sbi_system_reset(u32 reset_type, u32 reset_reason);
|
||||||
|
|
||||||
int sbi_system_final_init(struct sbi_scratch *scratch, bool cold_boot);
|
|
||||||
|
|
||||||
void __attribute__((noreturn))
|
|
||||||
sbi_system_reboot(struct sbi_scratch *scratch, u32 type);
|
|
||||||
|
|
||||||
void __attribute__((noreturn))
|
|
||||||
sbi_system_shutdown(struct sbi_scratch *scratch, u32 type);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -14,14 +14,31 @@
|
|||||||
|
|
||||||
struct sbi_scratch;
|
struct sbi_scratch;
|
||||||
|
|
||||||
u64 sbi_timer_value(struct sbi_scratch *scratch);
|
/** Get timer value for current HART */
|
||||||
|
u64 sbi_timer_value(void);
|
||||||
|
|
||||||
void sbi_timer_event_stop(struct sbi_scratch *scratch);
|
/** Get virtualized timer value for current HART */
|
||||||
|
u64 sbi_timer_virt_value(void);
|
||||||
|
|
||||||
void sbi_timer_event_start(struct sbi_scratch *scratch, u64 next_event);
|
/** Get timer delta value for current HART */
|
||||||
|
u64 sbi_timer_get_delta(void);
|
||||||
|
|
||||||
void sbi_timer_process(struct sbi_scratch *scratch);
|
/** Set timer delta value for current HART */
|
||||||
|
void sbi_timer_set_delta(ulong delta);
|
||||||
|
|
||||||
|
/** Set upper 32-bits of timer delta value for current HART */
|
||||||
|
void sbi_timer_set_delta_upper(ulong delta_upper);
|
||||||
|
|
||||||
|
/** Start timer event for current HART */
|
||||||
|
void sbi_timer_event_start(u64 next_event);
|
||||||
|
|
||||||
|
/** Process timer event for current HART */
|
||||||
|
void sbi_timer_process(void);
|
||||||
|
|
||||||
|
/* Initialize timer */
|
||||||
int sbi_timer_init(struct sbi_scratch *scratch, bool cold_boot);
|
int sbi_timer_init(struct sbi_scratch *scratch, bool cold_boot);
|
||||||
|
|
||||||
|
/* Exit timer */
|
||||||
|
void sbi_timer_exit(struct sbi_scratch *scratch);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -12,21 +12,15 @@
|
|||||||
#define __SBI_TLB_H__
|
#define __SBI_TLB_H__
|
||||||
|
|
||||||
#include <sbi/sbi_types.h>
|
#include <sbi/sbi_types.h>
|
||||||
|
#include <sbi/sbi_hartmask.h>
|
||||||
|
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
|
||||||
#define SBI_TLB_FLUSH_ALL ((unsigned long)-1)
|
#define SBI_TLB_FLUSH_ALL ((unsigned long)-1)
|
||||||
#define SBI_TLB_FLUSH_MAX_SIZE (1UL << 30)
|
|
||||||
|
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
#define SBI_TLB_FIFO_NUM_ENTRIES 4
|
#define SBI_TLB_FIFO_NUM_ENTRIES 8
|
||||||
|
|
||||||
enum sbi_tlb_info_types {
|
|
||||||
SBI_TLB_FLUSH_VMA,
|
|
||||||
SBI_TLB_FLUSH_VMA_ASID,
|
|
||||||
SBI_TLB_FLUSH_VMA_VMID
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sbi_scratch;
|
struct sbi_scratch;
|
||||||
|
|
||||||
@@ -34,15 +28,33 @@ struct sbi_tlb_info {
|
|||||||
unsigned long start;
|
unsigned long start;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
unsigned long asid;
|
unsigned long asid;
|
||||||
unsigned long type;
|
unsigned long vmid;
|
||||||
|
void (*local_fn)(struct sbi_tlb_info *tinfo);
|
||||||
|
struct sbi_hartmask smask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void sbi_tlb_local_hfence_vvma(struct sbi_tlb_info *tinfo);
|
||||||
|
void sbi_tlb_local_hfence_gvma(struct sbi_tlb_info *tinfo);
|
||||||
|
void sbi_tlb_local_sfence_vma(struct sbi_tlb_info *tinfo);
|
||||||
|
void sbi_tlb_local_hfence_vvma_asid(struct sbi_tlb_info *tinfo);
|
||||||
|
void sbi_tlb_local_hfence_gvma_vmid(struct sbi_tlb_info *tinfo);
|
||||||
|
void sbi_tlb_local_sfence_vma_asid(struct sbi_tlb_info *tinfo);
|
||||||
|
void sbi_tlb_local_fence_i(struct sbi_tlb_info *tinfo);
|
||||||
|
|
||||||
|
#define SBI_TLB_INFO_INIT(__p, __start, __size, __asid, __vmid, __lfn, __src) \
|
||||||
|
do { \
|
||||||
|
(__p)->start = (__start); \
|
||||||
|
(__p)->size = (__size); \
|
||||||
|
(__p)->asid = (__asid); \
|
||||||
|
(__p)->vmid = (__vmid); \
|
||||||
|
(__p)->local_fn = (__lfn); \
|
||||||
|
SBI_HARTMASK_INIT_EXCEPT(&(__p)->smask, (__src)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define SBI_TLB_INFO_SIZE sizeof(struct sbi_tlb_info)
|
#define SBI_TLB_INFO_SIZE sizeof(struct sbi_tlb_info)
|
||||||
|
|
||||||
int sbi_tlb_fifo_update(struct sbi_scratch *scratch, u32 event, void *data);
|
int sbi_tlb_request(ulong hmask, ulong hbase, struct sbi_tlb_info *tinfo);
|
||||||
|
|
||||||
void sbi_tlb_fifo_process(struct sbi_scratch *scratch, u32 event);
|
int sbi_tlb_init(struct sbi_scratch *scratch, bool cold_boot);
|
||||||
|
|
||||||
int sbi_tlb_fifo_init(struct sbi_scratch *scratch, bool cold_boot);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -80,8 +80,23 @@
|
|||||||
#define SBI_TRAP_REGS_mepc 32
|
#define SBI_TRAP_REGS_mepc 32
|
||||||
/** Index of mstatus member in sbi_trap_regs */
|
/** Index of mstatus member in sbi_trap_regs */
|
||||||
#define SBI_TRAP_REGS_mstatus 33
|
#define SBI_TRAP_REGS_mstatus 33
|
||||||
|
/** Index of mstatusH member in sbi_trap_regs */
|
||||||
|
#define SBI_TRAP_REGS_mstatusH 34
|
||||||
/** Last member index in sbi_trap_regs */
|
/** Last member index in sbi_trap_regs */
|
||||||
#define SBI_TRAP_REGS_last 34
|
#define SBI_TRAP_REGS_last 35
|
||||||
|
|
||||||
|
/** Index of epc member in sbi_trap_info */
|
||||||
|
#define SBI_TRAP_INFO_epc 0
|
||||||
|
/** Index of cause member in sbi_trap_info */
|
||||||
|
#define SBI_TRAP_INFO_cause 1
|
||||||
|
/** Index of tval member in sbi_trap_info */
|
||||||
|
#define SBI_TRAP_INFO_tval 2
|
||||||
|
/** Index of tval2 member in sbi_trap_info */
|
||||||
|
#define SBI_TRAP_INFO_tval2 3
|
||||||
|
/** Index of tinst member in sbi_trap_info */
|
||||||
|
#define SBI_TRAP_INFO_tinst 4
|
||||||
|
/** Last member index in sbi_trap_info */
|
||||||
|
#define SBI_TRAP_INFO_last 5
|
||||||
|
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
@@ -90,6 +105,11 @@
|
|||||||
/** Size (in bytes) of sbi_trap_regs */
|
/** Size (in bytes) of sbi_trap_regs */
|
||||||
#define SBI_TRAP_REGS_SIZE SBI_TRAP_REGS_OFFSET(last)
|
#define SBI_TRAP_REGS_SIZE SBI_TRAP_REGS_OFFSET(last)
|
||||||
|
|
||||||
|
/** Get offset of member with name 'x' in sbi_trap_info */
|
||||||
|
#define SBI_TRAP_INFO_OFFSET(x) ((SBI_TRAP_INFO_##x) * __SIZEOF_POINTER__)
|
||||||
|
/** Size (in bytes) of sbi_trap_info */
|
||||||
|
#define SBI_TRAP_INFO_SIZE SBI_TRAP_INFO_OFFSET(last)
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#include <sbi/sbi_types.h>
|
#include <sbi/sbi_types.h>
|
||||||
@@ -164,14 +184,30 @@ struct sbi_trap_regs {
|
|||||||
unsigned long mepc;
|
unsigned long mepc;
|
||||||
/** mstatus register state */
|
/** mstatus register state */
|
||||||
unsigned long mstatus;
|
unsigned long mstatus;
|
||||||
} __packed;
|
/** mstatusH register state (only for 32-bit) */
|
||||||
|
unsigned long mstatusH;
|
||||||
|
};
|
||||||
|
|
||||||
struct sbi_scratch;
|
/** Representation of trap details */
|
||||||
|
struct sbi_trap_info {
|
||||||
|
/** epc Trap program counter */
|
||||||
|
unsigned long epc;
|
||||||
|
/** cause Trap exception cause */
|
||||||
|
unsigned long cause;
|
||||||
|
/** tval Trap value */
|
||||||
|
unsigned long tval;
|
||||||
|
/** tval2 Trap value 2 */
|
||||||
|
unsigned long tval2;
|
||||||
|
/** tinst Trap instruction */
|
||||||
|
unsigned long tinst;
|
||||||
|
};
|
||||||
|
|
||||||
int sbi_trap_redirect(struct sbi_trap_regs *regs, struct sbi_scratch *scratch,
|
int sbi_trap_redirect(struct sbi_trap_regs *regs,
|
||||||
ulong epc, ulong cause, ulong tval);
|
struct sbi_trap_info *trap);
|
||||||
|
|
||||||
void sbi_trap_handler(struct sbi_trap_regs *regs, struct sbi_scratch *scratch);
|
void sbi_trap_handler(struct sbi_trap_regs *regs);
|
||||||
|
|
||||||
|
void __noreturn sbi_trap_exit(const struct sbi_trap_regs *regs);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -10,6 +10,8 @@
|
|||||||
#ifndef __SBI_TYPES_H__
|
#ifndef __SBI_TYPES_H__
|
||||||
#define __SBI_TYPES_H__
|
#define __SBI_TYPES_H__
|
||||||
|
|
||||||
|
#ifndef OPENSBI_EXTERNAL_SBI_TYPES
|
||||||
|
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
|
||||||
typedef char s8;
|
typedef char s8;
|
||||||
@@ -54,12 +56,54 @@ typedef unsigned long physical_size_t;
|
|||||||
|
|
||||||
#define TRUE 1
|
#define TRUE 1
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
|
#define true TRUE
|
||||||
|
#define false FALSE
|
||||||
|
|
||||||
#define NULL ((void *)0)
|
#define NULL ((void *)0)
|
||||||
|
|
||||||
#define __packed __attribute__((packed))
|
#define __packed __attribute__((packed))
|
||||||
#define __noreturn __attribute__((noreturn))
|
#define __noreturn __attribute__((noreturn))
|
||||||
|
|
||||||
|
#define likely(x) __builtin_expect((x), 1)
|
||||||
|
#define unlikely(x) __builtin_expect((x), 0)
|
||||||
|
|
||||||
|
#undef offsetof
|
||||||
|
#ifdef __compiler_offsetof
|
||||||
|
#define offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE,MEMBER)
|
||||||
|
#else
|
||||||
|
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define container_of(ptr, type, member) ({ \
|
||||||
|
const typeof(((type *)0)->member) * __mptr = (ptr); \
|
||||||
|
(type *)((char *)__mptr - offsetof(type, member)); })
|
||||||
|
|
||||||
|
#define array_size(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
|
||||||
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
#define CLAMP(a, lo, hi) MIN(MAX(a, lo), hi)
|
||||||
|
|
||||||
|
#define STR(x) XSTR(x)
|
||||||
|
#define XSTR(x) #x
|
||||||
|
|
||||||
|
#define ROUNDUP(a, b) ((((a)-1) / (b) + 1) * (b))
|
||||||
|
#define ROUNDDOWN(a, b) ((a) / (b) * (b))
|
||||||
|
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* OPENSBI_EXTERNAL_SBI_TYPES could be defined in CFLAGS for using the
|
||||||
|
* external definitions of data types and common macros.
|
||||||
|
* OPENSBI_EXTERNAL_SBI_TYPES is the file name to external header file,
|
||||||
|
* the external build system should address the additional include
|
||||||
|
* directory ccordingly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define XSTR(x) #x
|
||||||
|
#define STR(x) XSTR(x)
|
||||||
|
#include STR(OPENSBI_EXTERNAL_SBI_TYPES)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -7,28 +7,21 @@
|
|||||||
* Anup Patel <anup.patel@wdc.com>
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __RISCV_UNPRIV_H__
|
#ifndef __SBI_UNPRIV_H__
|
||||||
#define __RISCV_UNPRIV_H__
|
#define __SBI_UNPRIV_H__
|
||||||
|
|
||||||
#include <sbi/sbi_types.h>
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
struct sbi_scratch;
|
struct sbi_scratch;
|
||||||
|
struct sbi_trap_info;
|
||||||
struct unpriv_trap {
|
|
||||||
unsigned long ilen;
|
|
||||||
unsigned long cause;
|
|
||||||
unsigned long tval;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DECLARE_UNPRIVILEGED_LOAD_FUNCTION(type) \
|
#define DECLARE_UNPRIVILEGED_LOAD_FUNCTION(type) \
|
||||||
type load_##type(const type *addr, \
|
type sbi_load_##type(const type *addr, \
|
||||||
struct sbi_scratch *scratch, \
|
struct sbi_trap_info *trap);
|
||||||
struct unpriv_trap *trap);
|
|
||||||
|
|
||||||
#define DECLARE_UNPRIVILEGED_STORE_FUNCTION(type) \
|
#define DECLARE_UNPRIVILEGED_STORE_FUNCTION(type) \
|
||||||
void store_##type(type *addr, type val, \
|
void sbi_store_##type(type *addr, type val, \
|
||||||
struct sbi_scratch *scratch, \
|
struct sbi_trap_info *trap);
|
||||||
struct unpriv_trap *trap);
|
|
||||||
|
|
||||||
DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u8)
|
DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u8)
|
||||||
DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u16)
|
DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u16)
|
||||||
@@ -43,6 +36,6 @@ DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u64)
|
|||||||
DECLARE_UNPRIVILEGED_STORE_FUNCTION(u64)
|
DECLARE_UNPRIVILEGED_STORE_FUNCTION(u64)
|
||||||
DECLARE_UNPRIVILEGED_LOAD_FUNCTION(ulong)
|
DECLARE_UNPRIVILEGED_LOAD_FUNCTION(ulong)
|
||||||
|
|
||||||
ulong get_insn(ulong mepc, ulong *mstatus);
|
ulong sbi_get_insn(ulong mepc, struct sbi_trap_info *trap);
|
||||||
|
|
||||||
#endif
|
#endif
|
@@ -11,7 +11,7 @@
|
|||||||
#define __SBI_VERSION_H__
|
#define __SBI_VERSION_H__
|
||||||
|
|
||||||
#define OPENSBI_VERSION_MAJOR 0
|
#define OPENSBI_VERSION_MAJOR 0
|
||||||
#define OPENSBI_VERSION_MINOR 4
|
#define OPENSBI_VERSION_MINOR 9
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OpenSBI 32-bit version with:
|
* OpenSBI 32-bit version with:
|
||||||
|
73
include/sbi_utils/fdt/fdt_domain.h
Normal file
73
include/sbi_utils/fdt/fdt_domain.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
// SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
/*
|
||||||
|
* fdt_domain.c - Flat Device Tree Domain helper routines
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FDT_DOMAIN_H__
|
||||||
|
#define __FDT_DOMAIN_H__
|
||||||
|
|
||||||
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
|
struct sbi_domain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate over each domains in device tree
|
||||||
|
*
|
||||||
|
* @param fdt device tree blob
|
||||||
|
* @param opaque private pointer for each iteration
|
||||||
|
* @param fn callback function for each iteration
|
||||||
|
*
|
||||||
|
* @return 0 on success and negative error code on failure
|
||||||
|
*/
|
||||||
|
int fdt_iterate_each_domain(void *fdt, void *opaque,
|
||||||
|
int (*fn)(void *fdt, int domain_offset,
|
||||||
|
void *opaque));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate over each memregion of a domain in device tree
|
||||||
|
*
|
||||||
|
* @param fdt device tree blob
|
||||||
|
* @param domain_offset domain DT node offset
|
||||||
|
* @param opaque private pointer for each iteration
|
||||||
|
* @param fn callback function for each iteration
|
||||||
|
*
|
||||||
|
* @return 0 on success and negative error code on failure
|
||||||
|
*/
|
||||||
|
int fdt_iterate_each_memregion(void *fdt, int domain_offset, void *opaque,
|
||||||
|
int (*fn)(void *fdt, int domain_offset,
|
||||||
|
int region_offset, u32 region_access,
|
||||||
|
void *opaque));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fix up the domain configuration in the device tree
|
||||||
|
*
|
||||||
|
* This routine:
|
||||||
|
* 1. Disables MMIO devices not accessible to the coldboot HART domain
|
||||||
|
* 2. Removes "opensbi-domain" DT property from CPU DT nodes
|
||||||
|
* 3. Removes domain configuration DT node under /chosen DT node
|
||||||
|
*
|
||||||
|
* It is recommended that platform support call this function in
|
||||||
|
* their final_init() platform operation.
|
||||||
|
*
|
||||||
|
* @param fdt device tree blob
|
||||||
|
*/
|
||||||
|
void fdt_domain_fixup(void *fdt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate domains from device tree
|
||||||
|
*
|
||||||
|
* It is recommended that platform support call this function in
|
||||||
|
* their domains_init() platform operation.
|
||||||
|
*
|
||||||
|
* @param fdt device tree blob
|
||||||
|
*
|
||||||
|
* @return 0 on success and negative error code on failure
|
||||||
|
*/
|
||||||
|
int fdt_domains_populate(void *fdt);
|
||||||
|
|
||||||
|
#endif /* __FDT_DOMAIN_H__ */
|
78
include/sbi_utils/fdt/fdt_fixup.h
Normal file
78
include/sbi_utils/fdt/fdt_fixup.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
// SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
/*
|
||||||
|
* fdt_fixup.h - Flat Device Tree manipulation helper routines
|
||||||
|
* Implement platform specific DT fixups on top of libfdt.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Bin Meng <bmeng.cn@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FDT_FIXUP_H__
|
||||||
|
#define __FDT_FIXUP_H__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fix up the CPU node in the device tree
|
||||||
|
*
|
||||||
|
* This routine updates the "status" property of a CPU node in the device tree
|
||||||
|
* to "disabled" if that hart is in disabled state in OpenSBI.
|
||||||
|
*
|
||||||
|
* It is recommended that platform codes call this helper in their final_init()
|
||||||
|
*
|
||||||
|
* @param fdt: device tree blob
|
||||||
|
*/
|
||||||
|
void fdt_cpu_fixup(void *fdt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fix up the PLIC node in the device tree
|
||||||
|
*
|
||||||
|
* This routine updates the "interrupt-extended" property of the PLIC node in
|
||||||
|
* the device tree to hide the M-mode external interrupt from CPUs.
|
||||||
|
*
|
||||||
|
* It is recommended that platform codes call this helper in their final_init()
|
||||||
|
*
|
||||||
|
* @param fdt: device tree blob
|
||||||
|
* @param compat: PLIC node compatible string
|
||||||
|
*/
|
||||||
|
void fdt_plic_fixup(void *fdt, const char *compat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fix up the reserved memory node in the device tree
|
||||||
|
*
|
||||||
|
* This routine inserts a child node of the reserved memory node in the device
|
||||||
|
* tree that describes the protected memory region done by OpenSBI via PMP.
|
||||||
|
*
|
||||||
|
* It is recommended that platform codes call this helper in their final_init()
|
||||||
|
*
|
||||||
|
* @param fdt: device tree blob
|
||||||
|
* @return zero on success and -ve on failure
|
||||||
|
*/
|
||||||
|
int fdt_reserved_memory_fixup(void *fdt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fix up the reserved memory subnodes in the device tree
|
||||||
|
*
|
||||||
|
* This routine adds the no-map property to the reserved memory subnodes so
|
||||||
|
* that the OS does not map those PMP protected memory regions.
|
||||||
|
*
|
||||||
|
* Platform codes must call this helper in their final_init() after fdt_fixups()
|
||||||
|
* if the OS should not map the PMP protected reserved regions.
|
||||||
|
*
|
||||||
|
* @param fdt: device tree blob
|
||||||
|
* @return zero on success and -ve on failure
|
||||||
|
*/
|
||||||
|
int fdt_reserved_memory_nomap_fixup(void *fdt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* General device tree fix-up
|
||||||
|
*
|
||||||
|
* This routine do all required device tree fix-ups for a typical platform.
|
||||||
|
* It fixes up the PLIC node and the reserved memory node in the device tree
|
||||||
|
* by calling the corresponding helper routines to accomplish the task.
|
||||||
|
*
|
||||||
|
* It is recommended that platform codes call this helper in their final_init()
|
||||||
|
*
|
||||||
|
* @param fdt: device tree blob
|
||||||
|
*/
|
||||||
|
void fdt_fixups(void *fdt);
|
||||||
|
|
||||||
|
#endif /* __FDT_FIXUP_H__ */
|
||||||
|
|
68
include/sbi_utils/fdt/fdt_helper.h
Normal file
68
include/sbi_utils/fdt/fdt_helper.h
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
// SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
/*
|
||||||
|
* fdt_helper.h - Flat Device Tree parsing helper routines
|
||||||
|
* Implement helper routines to parse FDT nodes on top of
|
||||||
|
* libfdt for OpenSBI usage
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Bin Meng <bmeng.cn@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FDT_HELPER_H__
|
||||||
|
#define __FDT_HELPER_H__
|
||||||
|
|
||||||
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
|
struct fdt_match {
|
||||||
|
const char *compatible;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct platform_uart_data {
|
||||||
|
unsigned long addr;
|
||||||
|
unsigned long freq;
|
||||||
|
unsigned long baud;
|
||||||
|
unsigned long reg_shift;
|
||||||
|
unsigned long reg_io_width;
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct fdt_match *fdt_match_node(void *fdt, int nodeoff,
|
||||||
|
const struct fdt_match *match_table);
|
||||||
|
|
||||||
|
int fdt_find_match(void *fdt, int startoff,
|
||||||
|
const struct fdt_match *match_table,
|
||||||
|
const struct fdt_match **out_match);
|
||||||
|
|
||||||
|
int fdt_get_node_addr_size(void *fdt, int node, unsigned long *addr,
|
||||||
|
unsigned long *size);
|
||||||
|
|
||||||
|
int fdt_parse_hart_id(void *fdt, int cpu_offset, u32 *hartid);
|
||||||
|
|
||||||
|
int fdt_parse_max_hart_id(void *fdt, u32 *max_hartid);
|
||||||
|
|
||||||
|
int fdt_parse_shakti_uart_node(void *fdt, int nodeoffset,
|
||||||
|
struct platform_uart_data *uart);
|
||||||
|
|
||||||
|
int fdt_parse_sifive_uart_node(void *fdt, int nodeoffset,
|
||||||
|
struct platform_uart_data *uart);
|
||||||
|
|
||||||
|
int fdt_parse_uart8250_node(void *fdt, int nodeoffset,
|
||||||
|
struct platform_uart_data *uart);
|
||||||
|
|
||||||
|
int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
|
||||||
|
const char *compatible);
|
||||||
|
|
||||||
|
struct plic_data;
|
||||||
|
|
||||||
|
int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic);
|
||||||
|
|
||||||
|
int fdt_parse_plic(void *fdt, struct plic_data *plic, const char *compat);
|
||||||
|
|
||||||
|
struct clint_data;
|
||||||
|
|
||||||
|
int fdt_parse_clint_node(void *fdt, int nodeoffset, bool for_timer,
|
||||||
|
struct clint_data *clint);
|
||||||
|
|
||||||
|
int fdt_parse_compat_addr(void *fdt, unsigned long *addr,
|
||||||
|
const char *compatible);
|
||||||
|
|
||||||
|
#endif /* __FDT_HELPER_H__ */
|
32
include/sbi_utils/ipi/fdt_ipi.h
Normal file
32
include/sbi_utils/ipi/fdt_ipi.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FDT_IPI_H__
|
||||||
|
#define __FDT_IPI_H__
|
||||||
|
|
||||||
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
|
struct fdt_ipi {
|
||||||
|
const struct fdt_match *match_table;
|
||||||
|
int (*cold_init)(void *fdt, int nodeoff, const struct fdt_match *match);
|
||||||
|
int (*warm_init)(void);
|
||||||
|
void (*exit)(void);
|
||||||
|
void (*send)(u32 target_hart);
|
||||||
|
void (*clear)(u32 target_hart);
|
||||||
|
};
|
||||||
|
|
||||||
|
void fdt_ipi_send(u32 target_hart);
|
||||||
|
|
||||||
|
void fdt_ipi_clear(u32 target_hart);
|
||||||
|
|
||||||
|
void fdt_ipi_exit(void);
|
||||||
|
|
||||||
|
int fdt_ipi_init(bool cold_boot);
|
||||||
|
|
||||||
|
#endif
|
26
include/sbi_utils/irqchip/fdt_irqchip.h
Normal file
26
include/sbi_utils/irqchip/fdt_irqchip.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FDT_IRQCHIP_H__
|
||||||
|
#define __FDT_IRQCHIP_H__
|
||||||
|
|
||||||
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
|
struct fdt_irqchip {
|
||||||
|
const struct fdt_match *match_table;
|
||||||
|
int (*cold_init)(void *fdt, int nodeoff, const struct fdt_match *match);
|
||||||
|
int (*warm_init)(void);
|
||||||
|
void (*exit)(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
void fdt_irqchip_exit(void);
|
||||||
|
|
||||||
|
int fdt_irqchip_init(bool cold_boot);
|
||||||
|
|
||||||
|
#endif
|
@@ -12,14 +12,18 @@
|
|||||||
|
|
||||||
#include <sbi/sbi_types.h>
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
void plic_fdt_fixup(void *fdt, const char *compat);
|
struct plic_data {
|
||||||
|
unsigned long addr;
|
||||||
|
unsigned long num_src;
|
||||||
|
};
|
||||||
|
|
||||||
int plic_warm_irqchip_init(u32 target_hart, int m_cntx_id, int s_cntx_id);
|
int plic_warm_irqchip_init(struct plic_data *plic,
|
||||||
|
int m_cntx_id, int s_cntx_id);
|
||||||
|
|
||||||
int plic_cold_irqchip_init(unsigned long base, u32 num_sources, u32 hart_count);
|
int plic_cold_irqchip_init(struct plic_data *plic);
|
||||||
|
|
||||||
void plic_set_thresh(u32 cntxid, u32 val);
|
void plic_set_thresh(struct plic_data *plic, u32 cntxid, u32 val);
|
||||||
|
|
||||||
void plic_set_ie(u32 cntxid, u32 word_index, u32 val);
|
void plic_set_ie(struct plic_data *plic, u32 cntxid, u32 word_index, u32 val);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
28
include/sbi_utils/reset/fdt_reset.h
Normal file
28
include/sbi_utils/reset/fdt_reset.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FDT_RESET_H__
|
||||||
|
#define __FDT_RESET_H__
|
||||||
|
|
||||||
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
|
struct fdt_reset {
|
||||||
|
const struct fdt_match *match_table;
|
||||||
|
int (*init)(void *fdt, int nodeoff, const struct fdt_match *match);
|
||||||
|
int (*system_reset_check)(u32 reset_type, u32 reset_reason);
|
||||||
|
void (*system_reset)(u32 reset_type, u32 reset_reason);
|
||||||
|
};
|
||||||
|
|
||||||
|
int fdt_system_reset_check(u32 reset_type, u32 reset_reason);
|
||||||
|
|
||||||
|
void fdt_system_reset(u32 reset_type, u32 reset_reason);
|
||||||
|
|
||||||
|
int fdt_reset_init(void);
|
||||||
|
|
||||||
|
#endif
|
28
include/sbi_utils/serial/fdt_serial.h
Normal file
28
include/sbi_utils/serial/fdt_serial.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FDT_SERIAL_H__
|
||||||
|
#define __FDT_SERIAL_H__
|
||||||
|
|
||||||
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
|
struct fdt_serial {
|
||||||
|
const struct fdt_match *match_table;
|
||||||
|
int (*init)(void *fdt, int nodeoff, const struct fdt_match *match);
|
||||||
|
void (*putc)(char ch);
|
||||||
|
int (*getc)(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
void fdt_serial_putc(char ch);
|
||||||
|
|
||||||
|
int fdt_serial_getc(void);
|
||||||
|
|
||||||
|
int fdt_serial_init(void);
|
||||||
|
|
||||||
|
#endif
|
18
include/sbi_utils/serial/shakti-uart.h
Normal file
18
include/sbi_utils/serial/shakti-uart.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Vijai Kumar K <vijai@behindbytes.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SERIAL_SHAKTI_UART_H__
|
||||||
|
#define __SERIAL_SHAKTI_UART_H__
|
||||||
|
|
||||||
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
|
void shakti_uart_putc(char ch);
|
||||||
|
|
||||||
|
int shakti_uart_getc(void);
|
||||||
|
|
||||||
|
int shakti_uart_init(unsigned long base, u32 in_freq, u32 baudrate);
|
||||||
|
|
||||||
|
#endif
|
@@ -12,15 +12,30 @@
|
|||||||
|
|
||||||
#include <sbi/sbi_types.h>
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
void clint_ipi_send(u32 target_hart);
|
struct clint_data {
|
||||||
|
/* Public details */
|
||||||
|
unsigned long addr;
|
||||||
|
u32 first_hartid;
|
||||||
|
u32 hart_count;
|
||||||
|
bool has_64bit_mmio;
|
||||||
|
/* Private details (initialized and used by CLINT library)*/
|
||||||
|
u32 *ipi;
|
||||||
|
struct clint_data *time_delta_reference;
|
||||||
|
unsigned long time_delta_computed;
|
||||||
|
u64 time_delta;
|
||||||
|
u64 *time_val;
|
||||||
|
u64 *time_cmp;
|
||||||
|
u64 (*time_rd)(volatile u64 *addr);
|
||||||
|
void (*time_wr)(u64 value, volatile u64 *addr);
|
||||||
|
};
|
||||||
|
|
||||||
void clint_ipi_sync(u32 target_hart);
|
void clint_ipi_send(u32 target_hart);
|
||||||
|
|
||||||
void clint_ipi_clear(u32 target_hart);
|
void clint_ipi_clear(u32 target_hart);
|
||||||
|
|
||||||
int clint_warm_ipi_init(void);
|
int clint_warm_ipi_init(void);
|
||||||
|
|
||||||
int clint_cold_ipi_init(unsigned long base, u32 hart_count);
|
int clint_cold_ipi_init(struct clint_data *clint);
|
||||||
|
|
||||||
u64 clint_timer_value(void);
|
u64 clint_timer_value(void);
|
||||||
|
|
||||||
@@ -30,6 +45,7 @@ void clint_timer_event_start(u64 next_event);
|
|||||||
|
|
||||||
int clint_warm_timer_init(void);
|
int clint_warm_timer_init(void);
|
||||||
|
|
||||||
int clint_cold_timer_init(unsigned long base, u32 hart_count);
|
int clint_cold_timer_init(struct clint_data *clint,
|
||||||
|
struct clint_data *reference);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
21
include/sbi_utils/sys/htif.h
Normal file
21
include/sbi_utils/sys/htif.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2020, The Regents of the University of California
|
||||||
|
* (Regents). All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SYS_HTIF_H__
|
||||||
|
#define __SYS_HTIF_H__
|
||||||
|
|
||||||
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
|
void htif_putc(char ch);
|
||||||
|
|
||||||
|
int htif_getc(void);
|
||||||
|
|
||||||
|
int htif_system_reset_check(u32 type, u32 reason);
|
||||||
|
|
||||||
|
void htif_system_reset(u32 type, u32 reason);
|
||||||
|
|
||||||
|
#endif
|
21
include/sbi_utils/sys/sifive_test.h
Normal file
21
include/sbi_utils/sys/sifive_test.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SYS_SIFIVE_TEST_H__
|
||||||
|
#define __SYS_SIFIVE_TEST_H__
|
||||||
|
|
||||||
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
|
int sifive_test_system_reset_check(u32 type, u32 reason);
|
||||||
|
|
||||||
|
void sifive_test_system_reset(u32 type, u32 reason);
|
||||||
|
|
||||||
|
int sifive_test_init(unsigned long base);
|
||||||
|
|
||||||
|
#endif
|
35
include/sbi_utils/timer/fdt_timer.h
Normal file
35
include/sbi_utils/timer/fdt_timer.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FDT_TIMER_H__
|
||||||
|
#define __FDT_TIMER_H__
|
||||||
|
|
||||||
|
#include <sbi/sbi_types.h>
|
||||||
|
|
||||||
|
struct fdt_timer {
|
||||||
|
const struct fdt_match *match_table;
|
||||||
|
int (*cold_init)(void *fdt, int nodeoff, const struct fdt_match *match);
|
||||||
|
int (*warm_init)(void);
|
||||||
|
void (*exit)(void);
|
||||||
|
u64 (*value)(void);
|
||||||
|
void (*event_stop)(void);
|
||||||
|
void (*event_start)(u64 next_event);
|
||||||
|
};
|
||||||
|
|
||||||
|
u64 fdt_timer_value(void);
|
||||||
|
|
||||||
|
void fdt_timer_event_stop(void);
|
||||||
|
|
||||||
|
void fdt_timer_event_start(u64 next_event);
|
||||||
|
|
||||||
|
void fdt_timer_exit(void);
|
||||||
|
|
||||||
|
int fdt_timer_init(bool cold_boot);
|
||||||
|
|
||||||
|
#endif
|
@@ -11,20 +11,33 @@ libsbi-objs-y += riscv_asm.o
|
|||||||
libsbi-objs-y += riscv_atomic.o
|
libsbi-objs-y += riscv_atomic.o
|
||||||
libsbi-objs-y += riscv_hardfp.o
|
libsbi-objs-y += riscv_hardfp.o
|
||||||
libsbi-objs-y += riscv_locks.o
|
libsbi-objs-y += riscv_locks.o
|
||||||
libsbi-objs-y += riscv_unpriv.o
|
|
||||||
|
|
||||||
|
libsbi-objs-y += sbi_bitmap.o
|
||||||
|
libsbi-objs-y += sbi_bitops.o
|
||||||
libsbi-objs-y += sbi_console.o
|
libsbi-objs-y += sbi_console.o
|
||||||
|
libsbi-objs-y += sbi_domain.o
|
||||||
libsbi-objs-y += sbi_ecall.o
|
libsbi-objs-y += sbi_ecall.o
|
||||||
|
libsbi-objs-y += sbi_ecall_base.o
|
||||||
|
libsbi-objs-y += sbi_ecall_hsm.o
|
||||||
|
libsbi-objs-y += sbi_ecall_legacy.o
|
||||||
|
libsbi-objs-y += sbi_ecall_replace.o
|
||||||
|
libsbi-objs-y += sbi_ecall_vendor.o
|
||||||
libsbi-objs-y += sbi_emulate_csr.o
|
libsbi-objs-y += sbi_emulate_csr.o
|
||||||
libsbi-objs-y += sbi_fifo.o
|
libsbi-objs-y += sbi_fifo.o
|
||||||
libsbi-objs-y += sbi_hart.o
|
libsbi-objs-y += sbi_hart.o
|
||||||
|
libsbi-objs-y += sbi_math.o
|
||||||
|
libsbi-objs-y += sbi_hfence.o
|
||||||
|
libsbi-objs-y += sbi_hsm.o
|
||||||
libsbi-objs-y += sbi_illegal_insn.o
|
libsbi-objs-y += sbi_illegal_insn.o
|
||||||
libsbi-objs-y += sbi_init.o
|
libsbi-objs-y += sbi_init.o
|
||||||
libsbi-objs-y += sbi_ipi.o
|
libsbi-objs-y += sbi_ipi.o
|
||||||
libsbi-objs-y += sbi_misaligned_ldst.o
|
libsbi-objs-y += sbi_misaligned_ldst.o
|
||||||
|
libsbi-objs-y += sbi_platform.o
|
||||||
libsbi-objs-y += sbi_scratch.o
|
libsbi-objs-y += sbi_scratch.o
|
||||||
|
libsbi-objs-y += sbi_string.o
|
||||||
libsbi-objs-y += sbi_system.o
|
libsbi-objs-y += sbi_system.o
|
||||||
libsbi-objs-y += sbi_timer.o
|
libsbi-objs-y += sbi_timer.o
|
||||||
libsbi-objs-y += sbi_tlb.o
|
libsbi-objs-y += sbi_tlb.o
|
||||||
libsbi-objs-y += sbi_trap.o
|
libsbi-objs-y += sbi_trap.o
|
||||||
libsbi-objs-y += sbi_string.o
|
libsbi-objs-y += sbi_unpriv.o
|
||||||
|
libsbi-objs-y += sbi_expected_trap.o
|
||||||
|
@@ -10,145 +10,168 @@
|
|||||||
#include <sbi/riscv_asm.h>
|
#include <sbi/riscv_asm.h>
|
||||||
#include <sbi/riscv_encoding.h>
|
#include <sbi/riscv_encoding.h>
|
||||||
#include <sbi/sbi_error.h>
|
#include <sbi/sbi_error.h>
|
||||||
|
#include <sbi/sbi_platform.h>
|
||||||
|
|
||||||
|
/* determine CPU extension, return non-zero support */
|
||||||
|
int misa_extension_imp(char ext)
|
||||||
|
{
|
||||||
|
unsigned long misa = csr_read(CSR_MISA);
|
||||||
|
|
||||||
|
if (misa) {
|
||||||
|
if ('A' <= ext && ext <= 'Z')
|
||||||
|
return misa & (1 << (ext - 'A'));
|
||||||
|
if ('a' <= ext && ext <= 'z')
|
||||||
|
return misa & (1 << (ext - 'a'));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sbi_platform_misa_extension(sbi_platform_thishart_ptr(), ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
int misa_xlen(void)
|
||||||
|
{
|
||||||
|
long r;
|
||||||
|
|
||||||
|
if (csr_read(CSR_MISA) == 0)
|
||||||
|
return sbi_platform_misa_xlen(sbi_platform_thishart_ptr());
|
||||||
|
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"csrr t0, misa\n\t"
|
||||||
|
"slti t1, t0, 0\n\t"
|
||||||
|
"slli t1, t1, 1\n\t"
|
||||||
|
"slli t0, t0, 1\n\t"
|
||||||
|
"slti t0, t0, 0\n\t"
|
||||||
|
"add %0, t0, t1"
|
||||||
|
: "=r"(r)
|
||||||
|
:
|
||||||
|
: "t0", "t1");
|
||||||
|
|
||||||
|
return r ? r : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void misa_string(int xlen, char *out, unsigned int out_sz)
|
||||||
|
{
|
||||||
|
unsigned int i, pos = 0;
|
||||||
|
const char valid_isa_order[] = "iemafdqclbjtpvnsuhkorwxyzg";
|
||||||
|
|
||||||
|
if (!out)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (5 <= (out_sz - pos)) {
|
||||||
|
out[pos++] = 'r';
|
||||||
|
out[pos++] = 'v';
|
||||||
|
switch (xlen) {
|
||||||
|
case 1:
|
||||||
|
out[pos++] = '3';
|
||||||
|
out[pos++] = '2';
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
out[pos++] = '6';
|
||||||
|
out[pos++] = '4';
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
out[pos++] = '1';
|
||||||
|
out[pos++] = '2';
|
||||||
|
out[pos++] = '8';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < array_size(valid_isa_order) && (pos < out_sz); i++) {
|
||||||
|
if (misa_extension_imp(valid_isa_order[i]))
|
||||||
|
out[pos++] = valid_isa_order[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos < out_sz)
|
||||||
|
out[pos++] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long csr_read_num(int csr_num)
|
unsigned long csr_read_num(int csr_num)
|
||||||
{
|
{
|
||||||
|
#define switchcase_csr_read(__csr_num, __val) \
|
||||||
|
case __csr_num: \
|
||||||
|
__val = csr_read(__csr_num); \
|
||||||
|
break;
|
||||||
|
#define switchcase_csr_read_2(__csr_num, __val) \
|
||||||
|
switchcase_csr_read(__csr_num + 0, __val) \
|
||||||
|
switchcase_csr_read(__csr_num + 1, __val)
|
||||||
|
#define switchcase_csr_read_4(__csr_num, __val) \
|
||||||
|
switchcase_csr_read_2(__csr_num + 0, __val) \
|
||||||
|
switchcase_csr_read_2(__csr_num + 2, __val)
|
||||||
|
#define switchcase_csr_read_8(__csr_num, __val) \
|
||||||
|
switchcase_csr_read_4(__csr_num + 0, __val) \
|
||||||
|
switchcase_csr_read_4(__csr_num + 4, __val)
|
||||||
|
#define switchcase_csr_read_16(__csr_num, __val) \
|
||||||
|
switchcase_csr_read_8(__csr_num + 0, __val) \
|
||||||
|
switchcase_csr_read_8(__csr_num + 8, __val)
|
||||||
|
#define switchcase_csr_read_32(__csr_num, __val) \
|
||||||
|
switchcase_csr_read_16(__csr_num + 0, __val) \
|
||||||
|
switchcase_csr_read_16(__csr_num + 16, __val)
|
||||||
|
#define switchcase_csr_read_64(__csr_num, __val) \
|
||||||
|
switchcase_csr_read_32(__csr_num + 0, __val) \
|
||||||
|
switchcase_csr_read_32(__csr_num + 32, __val)
|
||||||
|
|
||||||
unsigned long ret = 0;
|
unsigned long ret = 0;
|
||||||
|
|
||||||
switch (csr_num) {
|
switch (csr_num) {
|
||||||
case CSR_PMPCFG0:
|
switchcase_csr_read_16(CSR_PMPCFG0, ret)
|
||||||
ret = csr_read(CSR_PMPCFG0);
|
switchcase_csr_read_64(CSR_PMPADDR0, ret)
|
||||||
break;
|
|
||||||
case CSR_PMPCFG1:
|
|
||||||
ret = csr_read(CSR_PMPCFG1);
|
|
||||||
break;
|
|
||||||
case CSR_PMPCFG2:
|
|
||||||
ret = csr_read(CSR_PMPCFG2);
|
|
||||||
break;
|
|
||||||
case CSR_PMPCFG3:
|
|
||||||
ret = csr_read(CSR_PMPCFG3);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR0:
|
|
||||||
ret = csr_read(CSR_PMPADDR0);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR1:
|
|
||||||
ret = csr_read(CSR_PMPADDR1);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR2:
|
|
||||||
ret = csr_read(CSR_PMPADDR2);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR3:
|
|
||||||
ret = csr_read(CSR_PMPADDR3);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR4:
|
|
||||||
ret = csr_read(CSR_PMPADDR4);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR5:
|
|
||||||
ret = csr_read(CSR_PMPADDR5);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR6:
|
|
||||||
ret = csr_read(CSR_PMPADDR6);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR7:
|
|
||||||
ret = csr_read(CSR_PMPADDR7);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR8:
|
|
||||||
ret = csr_read(CSR_PMPADDR8);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR9:
|
|
||||||
ret = csr_read(CSR_PMPADDR9);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR10:
|
|
||||||
ret = csr_read(CSR_PMPADDR10);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR11:
|
|
||||||
ret = csr_read(CSR_PMPADDR11);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR12:
|
|
||||||
ret = csr_read(CSR_PMPADDR12);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR13:
|
|
||||||
ret = csr_read(CSR_PMPADDR13);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR14:
|
|
||||||
ret = csr_read(CSR_PMPADDR14);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR15:
|
|
||||||
ret = csr_read(CSR_PMPADDR15);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
#undef switchcase_csr_read_64
|
||||||
|
#undef switchcase_csr_read_32
|
||||||
|
#undef switchcase_csr_read_16
|
||||||
|
#undef switchcase_csr_read_8
|
||||||
|
#undef switchcase_csr_read_4
|
||||||
|
#undef switchcase_csr_read_2
|
||||||
|
#undef switchcase_csr_read
|
||||||
}
|
}
|
||||||
|
|
||||||
void csr_write_num(int csr_num, unsigned long val)
|
void csr_write_num(int csr_num, unsigned long val)
|
||||||
{
|
{
|
||||||
|
#define switchcase_csr_write(__csr_num, __val) \
|
||||||
|
case __csr_num: \
|
||||||
|
csr_write(__csr_num, __val); \
|
||||||
|
break;
|
||||||
|
#define switchcase_csr_write_2(__csr_num, __val) \
|
||||||
|
switchcase_csr_write(__csr_num + 0, __val) \
|
||||||
|
switchcase_csr_write(__csr_num + 1, __val)
|
||||||
|
#define switchcase_csr_write_4(__csr_num, __val) \
|
||||||
|
switchcase_csr_write_2(__csr_num + 0, __val) \
|
||||||
|
switchcase_csr_write_2(__csr_num + 2, __val)
|
||||||
|
#define switchcase_csr_write_8(__csr_num, __val) \
|
||||||
|
switchcase_csr_write_4(__csr_num + 0, __val) \
|
||||||
|
switchcase_csr_write_4(__csr_num + 4, __val)
|
||||||
|
#define switchcase_csr_write_16(__csr_num, __val) \
|
||||||
|
switchcase_csr_write_8(__csr_num + 0, __val) \
|
||||||
|
switchcase_csr_write_8(__csr_num + 8, __val)
|
||||||
|
#define switchcase_csr_write_32(__csr_num, __val) \
|
||||||
|
switchcase_csr_write_16(__csr_num + 0, __val) \
|
||||||
|
switchcase_csr_write_16(__csr_num + 16, __val)
|
||||||
|
#define switchcase_csr_write_64(__csr_num, __val) \
|
||||||
|
switchcase_csr_write_32(__csr_num + 0, __val) \
|
||||||
|
switchcase_csr_write_32(__csr_num + 32, __val)
|
||||||
|
|
||||||
switch (csr_num) {
|
switch (csr_num) {
|
||||||
case CSR_PMPCFG0:
|
switchcase_csr_write_16(CSR_PMPCFG0, val)
|
||||||
csr_write(CSR_PMPCFG0, val);
|
switchcase_csr_write_64(CSR_PMPADDR0, val)
|
||||||
break;
|
|
||||||
case CSR_PMPCFG1:
|
|
||||||
csr_write(CSR_PMPCFG1, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPCFG2:
|
|
||||||
csr_write(CSR_PMPCFG2, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPCFG3:
|
|
||||||
csr_write(CSR_PMPCFG3, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR0:
|
|
||||||
csr_write(CSR_PMPADDR0, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR1:
|
|
||||||
csr_write(CSR_PMPADDR1, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR2:
|
|
||||||
csr_write(CSR_PMPADDR2, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR3:
|
|
||||||
csr_write(CSR_PMPADDR3, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR4:
|
|
||||||
csr_write(CSR_PMPADDR4, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR5:
|
|
||||||
csr_write(CSR_PMPADDR5, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR6:
|
|
||||||
csr_write(CSR_PMPADDR6, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR7:
|
|
||||||
csr_write(CSR_PMPADDR7, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR8:
|
|
||||||
csr_write(CSR_PMPADDR8, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR9:
|
|
||||||
csr_write(CSR_PMPADDR9, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR10:
|
|
||||||
csr_write(CSR_PMPADDR10, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR11:
|
|
||||||
csr_write(CSR_PMPADDR11, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR12:
|
|
||||||
csr_write(CSR_PMPADDR12, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR13:
|
|
||||||
csr_write(CSR_PMPADDR13, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR14:
|
|
||||||
csr_write(CSR_PMPADDR14, val);
|
|
||||||
break;
|
|
||||||
case CSR_PMPADDR15:
|
|
||||||
csr_write(CSR_PMPADDR15, val);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#undef switchcase_csr_write_64
|
||||||
|
#undef switchcase_csr_write_32
|
||||||
|
#undef switchcase_csr_write_16
|
||||||
|
#undef switchcase_csr_write_8
|
||||||
|
#undef switchcase_csr_write_4
|
||||||
|
#undef switchcase_csr_write_2
|
||||||
|
#undef switchcase_csr_write
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long ctz(unsigned long x)
|
static unsigned long ctz(unsigned long x)
|
||||||
@@ -191,7 +214,7 @@ int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
|
|||||||
|
|
||||||
/* encode PMP config */
|
/* encode PMP config */
|
||||||
prot |= (log2len == PMP_SHIFT) ? PMP_A_NA4 : PMP_A_NAPOT;
|
prot |= (log2len == PMP_SHIFT) ? PMP_A_NA4 : PMP_A_NAPOT;
|
||||||
cfgmask = ~(0xff << pmpcfg_shift);
|
cfgmask = ~(0xffUL << pmpcfg_shift);
|
||||||
pmpcfg = (csr_read_num(pmpcfg_csr) & cfgmask);
|
pmpcfg = (csr_read_num(pmpcfg_csr) & cfgmask);
|
||||||
pmpcfg |= ((prot << pmpcfg_shift) & ~cfgmask);
|
pmpcfg |= ((prot << pmpcfg_shift) & ~cfgmask);
|
||||||
|
|
||||||
@@ -216,16 +239,16 @@ int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
|
int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
|
||||||
unsigned long *log2len_out)
|
unsigned long *log2len)
|
||||||
{
|
{
|
||||||
int pmpcfg_csr, pmpcfg_shift, pmpaddr_csr;
|
int pmpcfg_csr, pmpcfg_shift, pmpaddr_csr;
|
||||||
unsigned long cfgmask, pmpcfg, prot;
|
unsigned long cfgmask, pmpcfg, prot;
|
||||||
unsigned long t1, addr, log2len;
|
unsigned long t1, addr, len;
|
||||||
|
|
||||||
/* check parameters */
|
/* check parameters */
|
||||||
if (n >= PMP_COUNT || !prot_out || !addr_out || !log2len_out)
|
if (n >= PMP_COUNT || !prot_out || !addr_out || !log2len)
|
||||||
return SBI_EINVAL;
|
return SBI_EINVAL;
|
||||||
*prot_out = *addr_out = *log2len_out = 0;
|
*prot_out = *addr_out = *log2len = 0;
|
||||||
|
|
||||||
/* calculate PMP register and offset */
|
/* calculate PMP register and offset */
|
||||||
#if __riscv_xlen == 32
|
#if __riscv_xlen == 32
|
||||||
@@ -243,7 +266,7 @@ int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
|
|||||||
return SBI_ENOTSUPP;
|
return SBI_ENOTSUPP;
|
||||||
|
|
||||||
/* decode PMP config */
|
/* decode PMP config */
|
||||||
cfgmask = (0xff << pmpcfg_shift);
|
cfgmask = (0xffUL << pmpcfg_shift);
|
||||||
pmpcfg = csr_read_num(pmpcfg_csr) & cfgmask;
|
pmpcfg = csr_read_num(pmpcfg_csr) & cfgmask;
|
||||||
prot = pmpcfg >> pmpcfg_shift;
|
prot = pmpcfg >> pmpcfg_shift;
|
||||||
|
|
||||||
@@ -252,21 +275,21 @@ int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
|
|||||||
addr = csr_read_num(pmpaddr_csr);
|
addr = csr_read_num(pmpaddr_csr);
|
||||||
if (addr == -1UL) {
|
if (addr == -1UL) {
|
||||||
addr = 0;
|
addr = 0;
|
||||||
log2len = __riscv_xlen;
|
len = __riscv_xlen;
|
||||||
} else {
|
} else {
|
||||||
t1 = ctz(~addr);
|
t1 = ctz(~addr);
|
||||||
addr = (addr & ~((1UL << t1) - 1)) << PMP_SHIFT;
|
addr = (addr & ~((1UL << t1) - 1)) << PMP_SHIFT;
|
||||||
log2len = (t1 + PMP_SHIFT + 1);
|
len = (t1 + PMP_SHIFT + 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
addr = csr_read_num(pmpaddr_csr) << PMP_SHIFT;
|
addr = csr_read_num(pmpaddr_csr) << PMP_SHIFT;
|
||||||
log2len = PMP_SHIFT;
|
len = PMP_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return details */
|
/* return details */
|
||||||
*prot_out = prot;
|
*prot_out = prot;
|
||||||
*addr_out = addr;
|
*addr_out = addr;
|
||||||
*log2len_out = log2len;
|
*log2len = len;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -7,11 +7,10 @@
|
|||||||
* Anup Patel <anup.patel@wdc.com>
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sbi/sbi_types.h>
|
#include <sbi/sbi_bitops.h>
|
||||||
#include <sbi/riscv_asm.h>
|
#include <sbi/riscv_asm.h>
|
||||||
#include <sbi/riscv_atomic.h>
|
#include <sbi/riscv_atomic.h>
|
||||||
#include <sbi/riscv_barrier.h>
|
#include <sbi/riscv_barrier.h>
|
||||||
#include <sbi/sbi_bits.h>
|
|
||||||
|
|
||||||
long atomic_read(atomic_t *atom)
|
long atomic_read(atomic_t *atom)
|
||||||
{
|
{
|
||||||
@@ -50,6 +49,39 @@ long atomic_sub_return(atomic_t *atom, long value)
|
|||||||
return ret - value;
|
return ret - value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define __axchg(ptr, new, size) \
|
||||||
|
({ \
|
||||||
|
__typeof__(ptr) __ptr = (ptr); \
|
||||||
|
__typeof__(new) __new = (new); \
|
||||||
|
__typeof__(*(ptr)) __ret; \
|
||||||
|
switch (size) { \
|
||||||
|
case 4: \
|
||||||
|
__asm__ __volatile__ ( \
|
||||||
|
" amoswap.w.aqrl %0, %2, %1\n" \
|
||||||
|
: "=r" (__ret), "+A" (*__ptr) \
|
||||||
|
: "r" (__new) \
|
||||||
|
: "memory"); \
|
||||||
|
break; \
|
||||||
|
case 8: \
|
||||||
|
__asm__ __volatile__ ( \
|
||||||
|
" amoswap.d.aqrl %0, %2, %1\n" \
|
||||||
|
: "=r" (__ret), "+A" (*__ptr) \
|
||||||
|
: "r" (__new) \
|
||||||
|
: "memory"); \
|
||||||
|
break; \
|
||||||
|
default: \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
__ret; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define axchg(ptr, x) \
|
||||||
|
({ \
|
||||||
|
__typeof__(*(ptr)) _x_ = (x); \
|
||||||
|
(__typeof__(*(ptr))) __axchg((ptr), _x_, sizeof(*(ptr))); \
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
#define __xchg(ptr, new, size) \
|
#define __xchg(ptr, new, size) \
|
||||||
({ \
|
({ \
|
||||||
__typeof__(ptr) __ptr = (ptr); \
|
__typeof__(ptr) __ptr = (ptr); \
|
||||||
@@ -135,7 +167,7 @@ long atomic_sub_return(atomic_t *atom, long value)
|
|||||||
__cmpxchg((ptr), _o_, _n_, sizeof(*(ptr))); \
|
__cmpxchg((ptr), _o_, _n_, sizeof(*(ptr))); \
|
||||||
})
|
})
|
||||||
|
|
||||||
long arch_atomic_cmpxchg(atomic_t *atom, long oldval, long newval)
|
long atomic_cmpxchg(atomic_t *atom, long oldval, long newval)
|
||||||
{
|
{
|
||||||
#ifdef __riscv_atomic
|
#ifdef __riscv_atomic
|
||||||
return __sync_val_compare_and_swap(&atom->counter, oldval, newval);
|
return __sync_val_compare_and_swap(&atom->counter, oldval, newval);
|
||||||
@@ -144,16 +176,11 @@ long arch_atomic_cmpxchg(atomic_t *atom, long oldval, long newval)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
long arch_atomic_xchg(atomic_t *atom, long newval)
|
long atomic_xchg(atomic_t *atom, long newval)
|
||||||
{
|
{
|
||||||
/* Atomically set new value and return old value. */
|
/* Atomically set new value and return old value. */
|
||||||
#ifdef __riscv_atomic
|
#ifdef __riscv_atomic
|
||||||
/*
|
return axchg(&atom->counter, newval);
|
||||||
* The name of GCC built-in macro __sync_lock_test_and_set()
|
|
||||||
* is misleading. A more appropriate name for GCC built-in
|
|
||||||
* macro would be __sync_val_exchange().
|
|
||||||
*/
|
|
||||||
return __sync_lock_test_and_set(&atom->counter, newval);
|
|
||||||
#else
|
#else
|
||||||
return xchg(&atom->counter, newval);
|
return xchg(&atom->counter, newval);
|
||||||
#endif
|
#endif
|
||||||
@@ -164,23 +191,29 @@ unsigned int atomic_raw_xchg_uint(volatile unsigned int *ptr,
|
|||||||
{
|
{
|
||||||
/* Atomically set new value and return old value. */
|
/* Atomically set new value and return old value. */
|
||||||
#ifdef __riscv_atomic
|
#ifdef __riscv_atomic
|
||||||
/*
|
return axchg(ptr, newval);
|
||||||
* The name of GCC built-in macro __sync_lock_test_and_set()
|
|
||||||
* is misleading. A more appropriate name for GCC built-in
|
|
||||||
* macro would be __sync_val_exchange().
|
|
||||||
*/
|
|
||||||
return __sync_lock_test_and_set(ptr, newval);
|
|
||||||
#else
|
#else
|
||||||
return xchg(ptr, newval);
|
return xchg(ptr, newval);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (BITS_PER_LONG == 64)
|
unsigned long atomic_raw_xchg_ulong(volatile unsigned long *ptr,
|
||||||
|
unsigned long newval)
|
||||||
|
{
|
||||||
|
/* Atomically set new value and return old value. */
|
||||||
|
#ifdef __riscv_atomic
|
||||||
|
return axchg(ptr, newval);
|
||||||
|
#else
|
||||||
|
return xchg(ptr, newval);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (__SIZEOF_POINTER__ == 8)
|
||||||
#define __AMO(op) "amo" #op ".d"
|
#define __AMO(op) "amo" #op ".d"
|
||||||
#elif (BITS_PER_LONG == 32)
|
#elif (__SIZEOF_POINTER__ == 4)
|
||||||
#define __AMO(op) "amo" #op ".w"
|
#define __AMO(op) "amo" #op ".w"
|
||||||
#else
|
#else
|
||||||
#error "Unexpected BITS_PER_LONG"
|
#error "Unexpected __SIZEOF_POINTER__"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define __atomic_op_bit_ord(op, mod, nr, addr, ord) \
|
#define __atomic_op_bit_ord(op, mod, nr, addr, ord) \
|
||||||
|
@@ -1,145 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*
|
|
||||||
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Anup Patel <anup.patel@wdc.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sbi/riscv_encoding.h>
|
|
||||||
#include <sbi/riscv_unpriv.h>
|
|
||||||
#include <sbi/sbi_bits.h>
|
|
||||||
#include <sbi/sbi_hart.h>
|
|
||||||
#include <sbi/sbi_scratch.h>
|
|
||||||
|
|
||||||
#define DEFINE_UNPRIVILEGED_LOAD_FUNCTION(type, insn, insnlen) \
|
|
||||||
type load_##type(const type *addr, \
|
|
||||||
struct sbi_scratch *scratch, \
|
|
||||||
struct unpriv_trap *trap) \
|
|
||||||
{ \
|
|
||||||
register ulong __mstatus asm("a2"); \
|
|
||||||
type val = 0; \
|
|
||||||
trap->ilen = insnlen; \
|
|
||||||
trap->cause = 0; \
|
|
||||||
trap->tval = 0; \
|
|
||||||
sbi_hart_set_trap_info(scratch, trap); \
|
|
||||||
asm volatile( \
|
|
||||||
"csrrs %0, " STR(CSR_MSTATUS) ", %3\n" \
|
|
||||||
#insn " %1, %2\n" \
|
|
||||||
"csrw " STR(CSR_MSTATUS) ", %0" \
|
|
||||||
: "+&r"(__mstatus), "=&r"(val) \
|
|
||||||
: "m"(*addr), "r"(MSTATUS_MPRV)); \
|
|
||||||
sbi_hart_set_trap_info(scratch, NULL); \
|
|
||||||
return val; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEFINE_UNPRIVILEGED_STORE_FUNCTION(type, insn, insnlen) \
|
|
||||||
void store_##type(type *addr, type val, \
|
|
||||||
struct sbi_scratch *scratch, \
|
|
||||||
struct unpriv_trap *trap) \
|
|
||||||
{ \
|
|
||||||
register ulong __mstatus asm("a3"); \
|
|
||||||
trap->ilen = insnlen; \
|
|
||||||
trap->cause = 0; \
|
|
||||||
trap->tval = 0; \
|
|
||||||
sbi_hart_set_trap_info(scratch, trap); \
|
|
||||||
asm volatile( \
|
|
||||||
"csrrs %0, " STR(CSR_MSTATUS) ", %3\n" \
|
|
||||||
#insn " %1, %2\n" \
|
|
||||||
"csrw " STR(CSR_MSTATUS) ", %0" \
|
|
||||||
: "+&r"(__mstatus) \
|
|
||||||
: "r"(val), "m"(*addr), "r"(MSTATUS_MPRV)); \
|
|
||||||
sbi_hart_set_trap_info(scratch, NULL); \
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_UNPRIVILEGED_LOAD_FUNCTION(u8, lbu, 4)
|
|
||||||
DEFINE_UNPRIVILEGED_LOAD_FUNCTION(u16, lhu, 4)
|
|
||||||
DEFINE_UNPRIVILEGED_LOAD_FUNCTION(s8, lb, 4)
|
|
||||||
DEFINE_UNPRIVILEGED_LOAD_FUNCTION(s16, lh, 4)
|
|
||||||
DEFINE_UNPRIVILEGED_LOAD_FUNCTION(s32, lw, 2)
|
|
||||||
DEFINE_UNPRIVILEGED_STORE_FUNCTION(u8, sb, 4)
|
|
||||||
DEFINE_UNPRIVILEGED_STORE_FUNCTION(u16, sh, 4)
|
|
||||||
DEFINE_UNPRIVILEGED_STORE_FUNCTION(u32, sw, 2)
|
|
||||||
#if __riscv_xlen == 64
|
|
||||||
DEFINE_UNPRIVILEGED_LOAD_FUNCTION(u32, lwu, 4)
|
|
||||||
DEFINE_UNPRIVILEGED_LOAD_FUNCTION(u64, ld, 2)
|
|
||||||
DEFINE_UNPRIVILEGED_STORE_FUNCTION(u64, sd, 2)
|
|
||||||
DEFINE_UNPRIVILEGED_LOAD_FUNCTION(ulong, ld, 2)
|
|
||||||
#else
|
|
||||||
DEFINE_UNPRIVILEGED_LOAD_FUNCTION(u32, lw, 2)
|
|
||||||
DEFINE_UNPRIVILEGED_LOAD_FUNCTION(ulong, lw, 2)
|
|
||||||
|
|
||||||
u64 load_u64(const u64 *addr,
|
|
||||||
struct sbi_scratch *scratch, struct unpriv_trap *trap)
|
|
||||||
{
|
|
||||||
u64 ret = load_u32((u32 *)addr, scratch, trap);
|
|
||||||
|
|
||||||
if (trap->cause)
|
|
||||||
return 0;
|
|
||||||
ret |= ((u64)load_u32((u32 *)addr + 1, scratch, trap) << 32);
|
|
||||||
if (trap->cause)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void store_u64(u64 *addr, u64 val,
|
|
||||||
struct sbi_scratch *scratch, struct unpriv_trap *trap)
|
|
||||||
{
|
|
||||||
store_u32((u32 *)addr, val, scratch, trap);
|
|
||||||
if (trap->cause)
|
|
||||||
return;
|
|
||||||
|
|
||||||
store_u32((u32 *)addr + 1, val >> 32, scratch, trap);
|
|
||||||
if (trap->cause)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ulong get_insn(ulong mepc, ulong *mstatus)
|
|
||||||
{
|
|
||||||
register ulong __mepc asm("a2") = mepc;
|
|
||||||
register ulong __mstatus asm("a3");
|
|
||||||
ulong val;
|
|
||||||
#ifndef __riscv_compressed
|
|
||||||
asm("csrrs %[mstatus], " STR(CSR_MSTATUS) ", %[mprv]\n"
|
|
||||||
#if __riscv_xlen == 64
|
|
||||||
STR(LWU) " %[insn], (%[addr])\n"
|
|
||||||
#else
|
|
||||||
STR(LW) " %[insn], (%[addr])\n"
|
|
||||||
#endif
|
|
||||||
"csrw " STR(CSR_MSTATUS) ", %[mstatus]"
|
|
||||||
: [mstatus] "+&r"(__mstatus), [insn] "=&r"(val)
|
|
||||||
: [mprv] "r"(MSTATUS_MPRV | MSTATUS_MXR), [addr] "r"(__mepc));
|
|
||||||
#else
|
|
||||||
ulong rvc_mask = 3, tmp;
|
|
||||||
asm("csrrs %[mstatus], " STR(CSR_MSTATUS) ", %[mprv]\n"
|
|
||||||
"and %[tmp], %[addr], 2\n"
|
|
||||||
"bnez %[tmp], 1f\n"
|
|
||||||
#if __riscv_xlen == 64
|
|
||||||
STR(LWU) " %[insn], (%[addr])\n"
|
|
||||||
#else
|
|
||||||
STR(LW) " %[insn], (%[addr])\n"
|
|
||||||
#endif
|
|
||||||
"and %[tmp], %[insn], %[rvc_mask]\n"
|
|
||||||
"beq %[tmp], %[rvc_mask], 2f\n"
|
|
||||||
"sll %[insn], %[insn], %[xlen_minus_16]\n"
|
|
||||||
"srl %[insn], %[insn], %[xlen_minus_16]\n"
|
|
||||||
"j 2f\n"
|
|
||||||
"1:\n"
|
|
||||||
"lhu %[insn], (%[addr])\n"
|
|
||||||
"and %[tmp], %[insn], %[rvc_mask]\n"
|
|
||||||
"bne %[tmp], %[rvc_mask], 2f\n"
|
|
||||||
"lhu %[tmp], 2(%[addr])\n"
|
|
||||||
"sll %[tmp], %[tmp], 16\n"
|
|
||||||
"add %[insn], %[insn], %[tmp]\n"
|
|
||||||
"2: csrw " STR(CSR_MSTATUS) ", %[mstatus]"
|
|
||||||
: [mstatus] "+&r"(__mstatus), [insn] "=&r"(val), [tmp] "=&r"(tmp)
|
|
||||||
: [mprv] "r"(MSTATUS_MPRV | MSTATUS_MXR), [addr] "r"(__mepc),
|
|
||||||
[rvc_mask] "r"(rvc_mask), [xlen_minus_16] "i"(__riscv_xlen - 16));
|
|
||||||
#endif
|
|
||||||
if (mstatus)
|
|
||||||
*mstatus = __mstatus;
|
|
||||||
return val;
|
|
||||||
}
|
|
40
lib/sbi/sbi_bitmap.c
Normal file
40
lib/sbi/sbi_bitmap.c
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sbi/sbi_bitmap.h>
|
||||||
|
|
||||||
|
void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
|
||||||
|
const unsigned long *bitmap2, int bits)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
int nr = BITS_TO_LONGS(bits);
|
||||||
|
|
||||||
|
for (k = 0; k < nr; k++)
|
||||||
|
dst[k] = bitmap1[k] & bitmap2[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
|
||||||
|
const unsigned long *bitmap2, int bits)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
int nr = BITS_TO_LONGS(bits);
|
||||||
|
|
||||||
|
for (k = 0; k < nr; k++)
|
||||||
|
dst[k] = bitmap1[k] | bitmap2[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
|
||||||
|
const unsigned long *bitmap2, int bits)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
int nr = BITS_TO_LONGS(bits);
|
||||||
|
|
||||||
|
for (k = 0; k < nr; k++)
|
||||||
|
dst[k] = bitmap1[k] ^ bitmap2[k];
|
||||||
|
}
|
200
lib/sbi/sbi_bitops.c
Normal file
200
lib/sbi/sbi_bitops.c
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Atish Patra <atish.patra@wdc.com>
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sbi/sbi_bitops.h>
|
||||||
|
|
||||||
|
#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find_first_bit - find the first set bit in a memory region
|
||||||
|
* @addr: The address to start the search at
|
||||||
|
* @size: The maximum size to search
|
||||||
|
*
|
||||||
|
* Returns the bit number of the first set bit.
|
||||||
|
*/
|
||||||
|
unsigned long find_first_bit(const unsigned long *addr,
|
||||||
|
unsigned long size)
|
||||||
|
{
|
||||||
|
const unsigned long *p = addr;
|
||||||
|
unsigned long result = 0;
|
||||||
|
unsigned long tmp;
|
||||||
|
|
||||||
|
while (size & ~(BITS_PER_LONG-1)) {
|
||||||
|
if ((tmp = *(p++)))
|
||||||
|
goto found;
|
||||||
|
result += BITS_PER_LONG;
|
||||||
|
size -= BITS_PER_LONG;
|
||||||
|
}
|
||||||
|
if (!size)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
|
||||||
|
if (tmp == 0UL) /* Are any bits set? */
|
||||||
|
return result + size; /* Nope. */
|
||||||
|
found:
|
||||||
|
return result + __ffs(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find_first_zero_bit - find the first cleared bit in a memory region
|
||||||
|
* @addr: The address to start the search at
|
||||||
|
* @size: The maximum size to search
|
||||||
|
*
|
||||||
|
* Returns the bit number of the first cleared bit.
|
||||||
|
*/
|
||||||
|
unsigned long find_first_zero_bit(const unsigned long *addr,
|
||||||
|
unsigned long size)
|
||||||
|
{
|
||||||
|
const unsigned long *p = addr;
|
||||||
|
unsigned long result = 0;
|
||||||
|
unsigned long tmp;
|
||||||
|
|
||||||
|
while (size & ~(BITS_PER_LONG-1)) {
|
||||||
|
if (~(tmp = *(p++)))
|
||||||
|
goto found;
|
||||||
|
result += BITS_PER_LONG;
|
||||||
|
size -= BITS_PER_LONG;
|
||||||
|
}
|
||||||
|
if (!size)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
tmp = (*p) | (~0UL << size);
|
||||||
|
if (tmp == ~0UL) /* Are any bits zero? */
|
||||||
|
return result + size; /* Nope. */
|
||||||
|
found:
|
||||||
|
return result + ffz(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find_last_bit - find the last set bit in a memory region
|
||||||
|
* @addr: The address to start the search at
|
||||||
|
* @size: The maximum size to search
|
||||||
|
*
|
||||||
|
* Returns the bit number of the first set bit, or size.
|
||||||
|
*/
|
||||||
|
unsigned long find_last_bit(const unsigned long *addr,
|
||||||
|
unsigned long size)
|
||||||
|
{
|
||||||
|
unsigned long words;
|
||||||
|
unsigned long tmp;
|
||||||
|
|
||||||
|
/* Start at final word. */
|
||||||
|
words = size / BITS_PER_LONG;
|
||||||
|
|
||||||
|
/* Partial final word? */
|
||||||
|
if (size & (BITS_PER_LONG-1)) {
|
||||||
|
tmp = (addr[words] & (~0UL >> (BITS_PER_LONG
|
||||||
|
- (size & (BITS_PER_LONG-1)))));
|
||||||
|
if (tmp)
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (words) {
|
||||||
|
tmp = addr[--words];
|
||||||
|
if (tmp) {
|
||||||
|
found:
|
||||||
|
return words * BITS_PER_LONG + __fls(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not found */
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find_next_bit - find the next set bit in a memory region
|
||||||
|
* @addr: The address to base the search on
|
||||||
|
* @offset: The bitnumber to start searching at
|
||||||
|
* @size: The bitmap size in bits
|
||||||
|
*/
|
||||||
|
unsigned long find_next_bit(const unsigned long *addr,
|
||||||
|
unsigned long size, unsigned long offset)
|
||||||
|
{
|
||||||
|
const unsigned long *p = addr + BITOP_WORD(offset);
|
||||||
|
unsigned long result = offset & ~(BITS_PER_LONG-1);
|
||||||
|
unsigned long tmp;
|
||||||
|
|
||||||
|
if (offset >= size)
|
||||||
|
return size;
|
||||||
|
size -= result;
|
||||||
|
offset %= BITS_PER_LONG;
|
||||||
|
if (offset) {
|
||||||
|
tmp = *(p++);
|
||||||
|
tmp &= (~0UL << offset);
|
||||||
|
if (size < BITS_PER_LONG)
|
||||||
|
goto found_first;
|
||||||
|
if (tmp)
|
||||||
|
goto found_middle;
|
||||||
|
size -= BITS_PER_LONG;
|
||||||
|
result += BITS_PER_LONG;
|
||||||
|
}
|
||||||
|
while (size & ~(BITS_PER_LONG-1)) {
|
||||||
|
if ((tmp = *(p++)))
|
||||||
|
goto found_middle;
|
||||||
|
result += BITS_PER_LONG;
|
||||||
|
size -= BITS_PER_LONG;
|
||||||
|
}
|
||||||
|
if (!size)
|
||||||
|
return result;
|
||||||
|
tmp = *p;
|
||||||
|
|
||||||
|
found_first:
|
||||||
|
tmp &= (~0UL >> (BITS_PER_LONG - size));
|
||||||
|
if (tmp == 0UL) /* Are any bits set? */
|
||||||
|
return result + size; /* Nope. */
|
||||||
|
found_middle:
|
||||||
|
return result + __ffs(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find_next_zero_bit - find the next cleared bit in a memory region
|
||||||
|
* @addr: The address to base the search on
|
||||||
|
* @offset: The bitnumber to start searching at
|
||||||
|
* @size: The bitmap size in bits
|
||||||
|
*/
|
||||||
|
unsigned long find_next_zero_bit(const unsigned long *addr,
|
||||||
|
unsigned long size,
|
||||||
|
unsigned long offset)
|
||||||
|
{
|
||||||
|
const unsigned long *p = addr + BITOP_WORD(offset);
|
||||||
|
unsigned long result = offset & ~(BITS_PER_LONG-1);
|
||||||
|
unsigned long tmp;
|
||||||
|
|
||||||
|
if (offset >= size)
|
||||||
|
return size;
|
||||||
|
size -= result;
|
||||||
|
offset %= BITS_PER_LONG;
|
||||||
|
if (offset) {
|
||||||
|
tmp = *(p++);
|
||||||
|
tmp |= ~0UL >> (BITS_PER_LONG - offset);
|
||||||
|
if (size < BITS_PER_LONG)
|
||||||
|
goto found_first;
|
||||||
|
if (~tmp)
|
||||||
|
goto found_middle;
|
||||||
|
size -= BITS_PER_LONG;
|
||||||
|
result += BITS_PER_LONG;
|
||||||
|
}
|
||||||
|
while (size & ~(BITS_PER_LONG-1)) {
|
||||||
|
if (~(tmp = *(p++)))
|
||||||
|
goto found_middle;
|
||||||
|
result += BITS_PER_LONG;
|
||||||
|
size -= BITS_PER_LONG;
|
||||||
|
}
|
||||||
|
if (!size)
|
||||||
|
return result;
|
||||||
|
tmp = *p;
|
||||||
|
|
||||||
|
found_first:
|
||||||
|
tmp |= ~0UL << size;
|
||||||
|
if (tmp == ~0UL) /* Are any bits zero? */
|
||||||
|
return result + size; /* Nope. */
|
||||||
|
found_middle:
|
||||||
|
return result + ffz(tmp);
|
||||||
|
}
|
@@ -7,9 +7,10 @@
|
|||||||
* Anup Patel <anup.patel@wdc.com>
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sbi/sbi_platform.h>
|
|
||||||
#include <sbi/sbi_console.h>
|
|
||||||
#include <sbi/riscv_locks.h>
|
#include <sbi/riscv_locks.h>
|
||||||
|
#include <sbi/sbi_console.h>
|
||||||
|
#include <sbi/sbi_platform.h>
|
||||||
|
#include <sbi/sbi_scratch.h>
|
||||||
|
|
||||||
static const struct sbi_platform *console_plat = NULL;
|
static const struct sbi_platform *console_plat = NULL;
|
||||||
static spinlock_t console_out_lock = SPIN_LOCK_INITIALIZER;
|
static spinlock_t console_out_lock = SPIN_LOCK_INITIALIZER;
|
||||||
@@ -375,6 +376,20 @@ int sbi_printf(const char *format, ...)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sbi_dprintf(const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
int retval = 0;
|
||||||
|
struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
if (scratch->options & SBI_SCRATCH_DEBUG_PRINTS)
|
||||||
|
retval = print(NULL, NULL, format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
int sbi_console_init(struct sbi_scratch *scratch)
|
int sbi_console_init(struct sbi_scratch *scratch)
|
||||||
{
|
{
|
||||||
console_plat = sbi_platform_ptr(scratch);
|
console_plat = sbi_platform_ptr(scratch);
|
||||||
|
539
lib/sbi/sbi_domain.c
Normal file
539
lib/sbi/sbi_domain.c
Normal file
@@ -0,0 +1,539 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sbi/riscv_asm.h>
|
||||||
|
#include <sbi/sbi_console.h>
|
||||||
|
#include <sbi/sbi_domain.h>
|
||||||
|
#include <sbi/sbi_hartmask.h>
|
||||||
|
#include <sbi/sbi_hsm.h>
|
||||||
|
#include <sbi/sbi_math.h>
|
||||||
|
#include <sbi/sbi_platform.h>
|
||||||
|
#include <sbi/sbi_scratch.h>
|
||||||
|
#include <sbi/sbi_string.h>
|
||||||
|
|
||||||
|
struct sbi_domain *hartid_to_domain_table[SBI_HARTMASK_MAX_BITS] = { 0 };
|
||||||
|
struct sbi_domain *domidx_to_domain_table[SBI_DOMAIN_MAX_INDEX] = { 0 };
|
||||||
|
|
||||||
|
static u32 domain_count = 0;
|
||||||
|
|
||||||
|
static struct sbi_hartmask root_hmask = { 0 };
|
||||||
|
|
||||||
|
#define ROOT_FW_REGION 0
|
||||||
|
#define ROOT_ALL_REGION 1
|
||||||
|
#define ROOT_END_REGION 2
|
||||||
|
static struct sbi_domain_memregion root_memregs[ROOT_END_REGION + 1] = { 0 };
|
||||||
|
|
||||||
|
static struct sbi_domain root = {
|
||||||
|
.name = "root",
|
||||||
|
.possible_harts = &root_hmask,
|
||||||
|
.regions = root_memregs,
|
||||||
|
.system_reset_allowed = TRUE,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartid)
|
||||||
|
{
|
||||||
|
if (dom)
|
||||||
|
return sbi_hartmask_test_hart(hartid, &dom->assigned_harts);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom,
|
||||||
|
ulong hbase)
|
||||||
|
{
|
||||||
|
ulong ret, bword, boff;
|
||||||
|
|
||||||
|
if (!dom)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
bword = BIT_WORD(hbase);
|
||||||
|
boff = BIT_WORD_OFFSET(hbase);
|
||||||
|
|
||||||
|
ret = sbi_hartmask_bits(&dom->assigned_harts)[bword++] >> boff;
|
||||||
|
if (boff && bword < BIT_WORD(SBI_HARTMASK_MAX_BITS)) {
|
||||||
|
ret |= (sbi_hartmask_bits(&dom->assigned_harts)[bword] &
|
||||||
|
(BIT(boff) - 1UL)) << (BITS_PER_LONG - boff);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sbi_domain_memregion_initfw(struct sbi_domain_memregion *reg)
|
||||||
|
{
|
||||||
|
if (!reg)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sbi_memcpy(reg, &root_memregs[ROOT_FW_REGION], sizeof(*reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sbi_domain_check_addr(const struct sbi_domain *dom,
|
||||||
|
unsigned long addr, unsigned long mode,
|
||||||
|
unsigned long access_flags)
|
||||||
|
{
|
||||||
|
bool mmio = FALSE;
|
||||||
|
struct sbi_domain_memregion *reg;
|
||||||
|
unsigned long rstart, rend, rflags, rwx = 0;
|
||||||
|
|
||||||
|
if (!dom)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (access_flags & SBI_DOMAIN_READ)
|
||||||
|
rwx |= SBI_DOMAIN_MEMREGION_READABLE;
|
||||||
|
if (access_flags & SBI_DOMAIN_WRITE)
|
||||||
|
rwx |= SBI_DOMAIN_MEMREGION_WRITEABLE;
|
||||||
|
if (access_flags & SBI_DOMAIN_EXECUTE)
|
||||||
|
rwx |= SBI_DOMAIN_MEMREGION_EXECUTABLE;
|
||||||
|
if (access_flags & SBI_DOMAIN_MMIO)
|
||||||
|
mmio = TRUE;
|
||||||
|
|
||||||
|
sbi_domain_for_each_memregion(dom, reg) {
|
||||||
|
rflags = reg->flags;
|
||||||
|
if (mode == PRV_M && !(rflags & SBI_DOMAIN_MEMREGION_MMODE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rstart = reg->base;
|
||||||
|
rend = (reg->order < __riscv_xlen) ?
|
||||||
|
rstart + ((1UL << reg->order) - 1) : -1UL;
|
||||||
|
if (rstart <= addr && addr <= rend) {
|
||||||
|
if ((mmio && !(rflags & SBI_DOMAIN_MEMREGION_MMIO)) ||
|
||||||
|
(!mmio && (rflags & SBI_DOMAIN_MEMREGION_MMIO)))
|
||||||
|
return FALSE;
|
||||||
|
return ((rflags & rwx) == rwx) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (mode == PRV_M) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if region complies with constraints */
|
||||||
|
static bool is_region_valid(const struct sbi_domain_memregion *reg)
|
||||||
|
{
|
||||||
|
if (reg->order < 3 || __riscv_xlen < reg->order)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (reg->base & (BIT(reg->order) - 1))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check if regionA is sub-region of regionB */
|
||||||
|
static bool is_region_subset(const struct sbi_domain_memregion *regA,
|
||||||
|
const struct sbi_domain_memregion *regB)
|
||||||
|
{
|
||||||
|
ulong regA_start = regA->base;
|
||||||
|
ulong regA_end = regA->base + (BIT(regA->order) - 1);
|
||||||
|
ulong regB_start = regB->base;
|
||||||
|
ulong regB_end = regB->base + (BIT(regA->order) - 1);
|
||||||
|
|
||||||
|
if ((regB_start <= regA_start) &&
|
||||||
|
(regA_start < regB_end) &&
|
||||||
|
(regB_start < regA_end) &&
|
||||||
|
(regA_end <= regB_end))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check if regionA conflicts regionB */
|
||||||
|
static bool is_region_conflict(const struct sbi_domain_memregion *regA,
|
||||||
|
const struct sbi_domain_memregion *regB)
|
||||||
|
{
|
||||||
|
if ((is_region_subset(regA, regB) || is_region_subset(regB, regA)) &&
|
||||||
|
regA->flags == regB->flags)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check if regionA should be placed before regionB */
|
||||||
|
static bool is_region_before(const struct sbi_domain_memregion *regA,
|
||||||
|
const struct sbi_domain_memregion *regB)
|
||||||
|
{
|
||||||
|
if (regA->order < regB->order)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if ((regA->order == regB->order) &&
|
||||||
|
(regA->base < regB->base))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sanitize_domain(const struct sbi_platform *plat,
|
||||||
|
struct sbi_domain *dom)
|
||||||
|
{
|
||||||
|
u32 i, j, count;
|
||||||
|
bool have_fw_reg;
|
||||||
|
struct sbi_domain_memregion treg, *reg, *reg1;
|
||||||
|
|
||||||
|
/* Check possible HARTs */
|
||||||
|
if (!dom->possible_harts) {
|
||||||
|
sbi_printf("%s: %s possible HART mask is NULL\n",
|
||||||
|
__func__, dom->name);
|
||||||
|
return SBI_EINVAL;
|
||||||
|
}
|
||||||
|
sbi_hartmask_for_each_hart(i, dom->possible_harts) {
|
||||||
|
if (sbi_platform_hart_invalid(plat, i)) {
|
||||||
|
sbi_printf("%s: %s possible HART mask has invalid "
|
||||||
|
"hart %d\n", __func__, dom->name, i);
|
||||||
|
return SBI_EINVAL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Check memory regions */
|
||||||
|
if (!dom->regions) {
|
||||||
|
sbi_printf("%s: %s regions is NULL\n",
|
||||||
|
__func__, dom->name);
|
||||||
|
return SBI_EINVAL;
|
||||||
|
}
|
||||||
|
sbi_domain_for_each_memregion(dom, reg) {
|
||||||
|
if (!is_region_valid(reg)) {
|
||||||
|
sbi_printf("%s: %s has invalid region base=0x%lx "
|
||||||
|
"order=%lu flags=0x%lx\n", __func__,
|
||||||
|
dom->name, reg->base, reg->order,
|
||||||
|
reg->flags);
|
||||||
|
return SBI_EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Count memory regions and check presence of firmware region */
|
||||||
|
count = 0;
|
||||||
|
have_fw_reg = FALSE;
|
||||||
|
sbi_domain_for_each_memregion(dom, reg) {
|
||||||
|
if (reg->order == root_memregs[ROOT_FW_REGION].order &&
|
||||||
|
reg->base == root_memregs[ROOT_FW_REGION].base &&
|
||||||
|
reg->flags == root_memregs[ROOT_FW_REGION].flags)
|
||||||
|
have_fw_reg = TRUE;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (!have_fw_reg) {
|
||||||
|
sbi_printf("%s: %s does not have firmware region\n",
|
||||||
|
__func__, dom->name);
|
||||||
|
return SBI_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sort the memory regions */
|
||||||
|
for (i = 0; i < (count - 1); i++) {
|
||||||
|
reg = &dom->regions[i];
|
||||||
|
for (j = i + 1; j < count; j++) {
|
||||||
|
reg1 = &dom->regions[j];
|
||||||
|
|
||||||
|
if (is_region_conflict(reg1, reg)) {
|
||||||
|
sbi_printf("%s: %s conflict between regions "
|
||||||
|
"(base=0x%lx order=%lu flags=0x%lx) and "
|
||||||
|
"(base=0x%lx order=%lu flags=0x%lx)\n",
|
||||||
|
__func__, dom->name,
|
||||||
|
reg->base, reg->order, reg->flags,
|
||||||
|
reg1->base, reg1->order, reg1->flags);
|
||||||
|
return SBI_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_region_before(reg1, reg))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sbi_memcpy(&treg, reg1, sizeof(treg));
|
||||||
|
sbi_memcpy(reg1, reg, sizeof(treg));
|
||||||
|
sbi_memcpy(reg, &treg, sizeof(treg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We don't need to check boot HART id of domain because if boot
|
||||||
|
* HART id is not possible/assigned to this domain then it won't
|
||||||
|
* be started at boot-time by sbi_domain_finalize().
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check next mode
|
||||||
|
*
|
||||||
|
* We only allow next mode to be S-mode or U-mode.so that we can
|
||||||
|
* protect M-mode context and enforce checks on memory accesses.
|
||||||
|
*/
|
||||||
|
if (dom->next_mode != PRV_S &&
|
||||||
|
dom->next_mode != PRV_U) {
|
||||||
|
sbi_printf("%s: %s invalid next booting stage mode 0x%lx\n",
|
||||||
|
__func__, dom->name, dom->next_mode);
|
||||||
|
return SBI_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check next address and next mode*/
|
||||||
|
if (!sbi_domain_check_addr(dom, dom->next_addr, dom->next_mode,
|
||||||
|
SBI_DOMAIN_EXECUTE)) {
|
||||||
|
sbi_printf("%s: %s next booting stage addres 0x%lx can't "
|
||||||
|
"execute\n", __func__, dom->name, dom->next_addr);
|
||||||
|
return SBI_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix)
|
||||||
|
{
|
||||||
|
u32 i, k;
|
||||||
|
unsigned long rstart, rend;
|
||||||
|
struct sbi_domain_memregion *reg;
|
||||||
|
|
||||||
|
sbi_printf("Domain%d Name %s: %s\n",
|
||||||
|
dom->index, suffix, dom->name);
|
||||||
|
|
||||||
|
sbi_printf("Domain%d Boot HART %s: %d\n",
|
||||||
|
dom->index, suffix, dom->boot_hartid);
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
sbi_printf("Domain%d HARTs %s: ", dom->index, suffix);
|
||||||
|
sbi_hartmask_for_each_hart(i, dom->possible_harts)
|
||||||
|
sbi_printf("%s%d%s", (k++) ? "," : "",
|
||||||
|
i, sbi_domain_is_assigned_hart(dom, i) ? "*" : "");
|
||||||
|
sbi_printf("\n");
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
sbi_domain_for_each_memregion(dom, reg) {
|
||||||
|
rstart = reg->base;
|
||||||
|
rend = (reg->order < __riscv_xlen) ?
|
||||||
|
rstart + ((1UL << reg->order) - 1) : -1UL;
|
||||||
|
|
||||||
|
#if __riscv_xlen == 32
|
||||||
|
sbi_printf("Domain%d Region%02d %s: 0x%08lx-0x%08lx ",
|
||||||
|
#else
|
||||||
|
sbi_printf("Domain%d Region%02d %s: 0x%016lx-0x%016lx ",
|
||||||
|
#endif
|
||||||
|
dom->index, i, suffix, rstart, rend);
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
if (reg->flags & SBI_DOMAIN_MEMREGION_MMODE)
|
||||||
|
sbi_printf("%cM", (k++) ? ',' : '(');
|
||||||
|
if (reg->flags & SBI_DOMAIN_MEMREGION_MMIO)
|
||||||
|
sbi_printf("%cI", (k++) ? ',' : '(');
|
||||||
|
if (reg->flags & SBI_DOMAIN_MEMREGION_READABLE)
|
||||||
|
sbi_printf("%cR", (k++) ? ',' : '(');
|
||||||
|
if (reg->flags & SBI_DOMAIN_MEMREGION_WRITEABLE)
|
||||||
|
sbi_printf("%cW", (k++) ? ',' : '(');
|
||||||
|
if (reg->flags & SBI_DOMAIN_MEMREGION_EXECUTABLE)
|
||||||
|
sbi_printf("%cX", (k++) ? ',' : '(');
|
||||||
|
sbi_printf("%s\n", (k++) ? ")" : "()");
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __riscv_xlen == 32
|
||||||
|
sbi_printf("Domain%d Next Address%s: 0x%08lx\n",
|
||||||
|
#else
|
||||||
|
sbi_printf("Domain%d Next Address%s: 0x%016lx\n",
|
||||||
|
#endif
|
||||||
|
dom->index, suffix, dom->next_addr);
|
||||||
|
|
||||||
|
#if __riscv_xlen == 32
|
||||||
|
sbi_printf("Domain%d Next Arg1 %s: 0x%08lx\n",
|
||||||
|
#else
|
||||||
|
sbi_printf("Domain%d Next Arg1 %s: 0x%016lx\n",
|
||||||
|
#endif
|
||||||
|
dom->index, suffix, dom->next_arg1);
|
||||||
|
|
||||||
|
sbi_printf("Domain%d Next Mode %s: ", dom->index, suffix);
|
||||||
|
switch (dom->next_mode) {
|
||||||
|
case PRV_M:
|
||||||
|
sbi_printf("M-mode\n");
|
||||||
|
break;
|
||||||
|
case PRV_S:
|
||||||
|
sbi_printf("S-mode\n");
|
||||||
|
break;
|
||||||
|
case PRV_U:
|
||||||
|
sbi_printf("U-mode\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sbi_printf("Unknown\n");
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
sbi_printf("Domain%d SysReset %s: %s\n",
|
||||||
|
dom->index, suffix, (dom->system_reset_allowed) ? "yes" : "no");
|
||||||
|
}
|
||||||
|
|
||||||
|
void sbi_domain_dump_all(const char *suffix)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
const struct sbi_domain *dom;
|
||||||
|
|
||||||
|
sbi_domain_for_each(i, dom) {
|
||||||
|
sbi_domain_dump(dom, suffix);
|
||||||
|
sbi_printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int sbi_domain_register(struct sbi_domain *dom,
|
||||||
|
const struct sbi_hartmask *assign_mask)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
int rc;
|
||||||
|
struct sbi_domain *tdom;
|
||||||
|
u32 cold_hartid = current_hartid();
|
||||||
|
const struct sbi_platform *plat = sbi_platform_thishart_ptr();
|
||||||
|
|
||||||
|
if (!dom || !assign_mask)
|
||||||
|
return SBI_EINVAL;
|
||||||
|
|
||||||
|
/* Check if domain already discovered */
|
||||||
|
sbi_domain_for_each(i, tdom) {
|
||||||
|
if (tdom == dom)
|
||||||
|
return SBI_EALREADY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure that we have room for Domain Index to
|
||||||
|
* HART ID mapping
|
||||||
|
*/
|
||||||
|
if (SBI_DOMAIN_MAX_INDEX <= domain_count) {
|
||||||
|
sbi_printf("%s: No room for %s\n",
|
||||||
|
__func__, dom->name);
|
||||||
|
return SBI_ENOSPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sanitize discovered domain */
|
||||||
|
rc = sanitize_domain(plat, dom);
|
||||||
|
if (rc) {
|
||||||
|
sbi_printf("%s: sanity checks failed for"
|
||||||
|
" %s (error %d)\n", __func__,
|
||||||
|
dom->name, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assign index to domain */
|
||||||
|
dom->index = domain_count++;
|
||||||
|
domidx_to_domain_table[dom->index] = dom;
|
||||||
|
|
||||||
|
/* Clear assigned HARTs of domain */
|
||||||
|
sbi_hartmask_clear_all(&dom->assigned_harts);
|
||||||
|
|
||||||
|
/* Assign domain to HART if HART is a possible HART */
|
||||||
|
sbi_hartmask_for_each_hart(i, assign_mask) {
|
||||||
|
if (!sbi_hartmask_test_hart(i, dom->possible_harts))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
tdom = hartid_to_domain_table[i];
|
||||||
|
if (tdom)
|
||||||
|
sbi_hartmask_clear_hart(i,
|
||||||
|
&tdom->assigned_harts);
|
||||||
|
hartid_to_domain_table[i] = dom;
|
||||||
|
sbi_hartmask_set_hart(i, &dom->assigned_harts);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If cold boot HART is assigned to this domain then
|
||||||
|
* override boot HART of this domain.
|
||||||
|
*/
|
||||||
|
if (i == cold_hartid &&
|
||||||
|
dom->boot_hartid != cold_hartid) {
|
||||||
|
sbi_printf("Domain%d Boot HARTID forced to"
|
||||||
|
" %d\n", dom->index, cold_hartid);
|
||||||
|
dom->boot_hartid = cold_hartid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
u32 i, dhart;
|
||||||
|
struct sbi_domain *dom;
|
||||||
|
const struct sbi_platform *plat = sbi_platform_ptr(scratch);
|
||||||
|
|
||||||
|
/* Initialize and populate domains for the platform */
|
||||||
|
rc = sbi_platform_domains_init(plat);
|
||||||
|
if (rc) {
|
||||||
|
sbi_printf("%s: platform domains_init() failed (error %d)\n",
|
||||||
|
__func__, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Startup boot HART of domains */
|
||||||
|
sbi_domain_for_each(i, dom) {
|
||||||
|
/* Domain boot HART */
|
||||||
|
dhart = dom->boot_hartid;
|
||||||
|
|
||||||
|
/* Ignore of boot HART is off limits */
|
||||||
|
if (SBI_HARTMASK_MAX_BITS <= dhart)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Ignore if boot HART not possible for this domain */
|
||||||
|
if (!sbi_hartmask_test_hart(dhart, dom->possible_harts))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Ignore if boot HART assigned different domain */
|
||||||
|
if (sbi_hartid_to_domain(dhart) != dom ||
|
||||||
|
!sbi_hartmask_test_hart(dhart, &dom->assigned_harts))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Startup boot HART of domain */
|
||||||
|
if (dhart == cold_hartid) {
|
||||||
|
scratch->next_addr = dom->next_addr;
|
||||||
|
scratch->next_mode = dom->next_mode;
|
||||||
|
scratch->next_arg1 = dom->next_arg1;
|
||||||
|
} else {
|
||||||
|
rc = sbi_hsm_hart_start(scratch, NULL, dhart,
|
||||||
|
dom->next_addr,
|
||||||
|
dom->next_mode,
|
||||||
|
dom->next_arg1);
|
||||||
|
if (rc) {
|
||||||
|
sbi_printf("%s: failed to start boot HART %d"
|
||||||
|
" for %s (error %d)\n", __func__,
|
||||||
|
dhart, dom->name, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
struct sbi_domain_memregion *memregs;
|
||||||
|
const struct sbi_platform *plat = sbi_platform_ptr(scratch);
|
||||||
|
|
||||||
|
/* Root domain firmware memory region */
|
||||||
|
root_memregs[ROOT_FW_REGION].order = log2roundup(scratch->fw_size);
|
||||||
|
root_memregs[ROOT_FW_REGION].base = scratch->fw_start &
|
||||||
|
~((1UL << root_memregs[0].order) - 1UL);
|
||||||
|
root_memregs[ROOT_FW_REGION].flags = 0;
|
||||||
|
|
||||||
|
/* Root domain allow everything memory region */
|
||||||
|
root_memregs[ROOT_ALL_REGION].order = __riscv_xlen;
|
||||||
|
root_memregs[ROOT_ALL_REGION].base = 0;
|
||||||
|
root_memregs[ROOT_ALL_REGION].flags = (SBI_DOMAIN_MEMREGION_READABLE |
|
||||||
|
SBI_DOMAIN_MEMREGION_WRITEABLE |
|
||||||
|
SBI_DOMAIN_MEMREGION_EXECUTABLE);
|
||||||
|
|
||||||
|
/* Root domain memory region end */
|
||||||
|
root_memregs[ROOT_END_REGION].order = 0;
|
||||||
|
|
||||||
|
/* Use platform specific root memory regions when available */
|
||||||
|
memregs = sbi_platform_domains_root_regions(plat);
|
||||||
|
if (memregs)
|
||||||
|
root.regions = memregs;
|
||||||
|
|
||||||
|
/* Root domain boot HART id is same as coldboot HART id */
|
||||||
|
root.boot_hartid = cold_hartid;
|
||||||
|
|
||||||
|
/* Root domain next booting stage details */
|
||||||
|
root.next_arg1 = scratch->next_arg1;
|
||||||
|
root.next_addr = scratch->next_addr;
|
||||||
|
root.next_mode = scratch->next_mode;
|
||||||
|
|
||||||
|
/* Root domain possible and assigned HARTs */
|
||||||
|
for (i = 0; i < SBI_HARTMASK_MAX_BITS; i++) {
|
||||||
|
if (sbi_platform_hart_invalid(plat, i))
|
||||||
|
continue;
|
||||||
|
sbi_hartmask_set_hart(i, &root_hmask);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sbi_domain_register(&root, &root_hmask);
|
||||||
|
}
|
@@ -11,15 +11,8 @@
|
|||||||
#include <sbi/sbi_ecall.h>
|
#include <sbi/sbi_ecall.h>
|
||||||
#include <sbi/sbi_ecall_interface.h>
|
#include <sbi/sbi_ecall_interface.h>
|
||||||
#include <sbi/sbi_error.h>
|
#include <sbi/sbi_error.h>
|
||||||
#include <sbi/sbi_ipi.h>
|
|
||||||
#include <sbi/sbi_system.h>
|
|
||||||
#include <sbi/sbi_timer.h>
|
|
||||||
#include <sbi/sbi_tlb.h>
|
|
||||||
#include <sbi/sbi_trap.h>
|
#include <sbi/sbi_trap.h>
|
||||||
|
|
||||||
#define SBI_ECALL_VERSION_MAJOR 0
|
|
||||||
#define SBI_ECALL_VERSION_MINOR 1
|
|
||||||
|
|
||||||
u16 sbi_ecall_version_major(void)
|
u16 sbi_ecall_version_major(void)
|
||||||
{
|
{
|
||||||
return SBI_ECALL_VERSION_MAJOR;
|
return SBI_ECALL_VERSION_MAJOR;
|
||||||
@@ -30,78 +23,153 @@ u16 sbi_ecall_version_minor(void)
|
|||||||
return SBI_ECALL_VERSION_MINOR;
|
return SBI_ECALL_VERSION_MINOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sbi_ecall_handler(u32 hartid, ulong mcause, struct sbi_trap_regs *regs,
|
static unsigned long ecall_impid = SBI_OPENSBI_IMPID;
|
||||||
struct sbi_scratch *scratch)
|
|
||||||
|
unsigned long sbi_ecall_get_impid(void)
|
||||||
{
|
{
|
||||||
int ret = SBI_ENOTSUPP;
|
return ecall_impid;
|
||||||
struct unpriv_trap uptrap;
|
}
|
||||||
struct sbi_tlb_info tlb_info;
|
|
||||||
|
|
||||||
switch (regs->a7) {
|
void sbi_ecall_set_impid(unsigned long impid)
|
||||||
case SBI_ECALL_SET_TIMER:
|
{
|
||||||
#if __riscv_xlen == 32
|
ecall_impid = impid;
|
||||||
sbi_timer_event_start(scratch,
|
}
|
||||||
(((u64)regs->a1 << 32) | (u64)regs->a0));
|
|
||||||
#else
|
|
||||||
sbi_timer_event_start(scratch, (u64)regs->a0);
|
|
||||||
#endif
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
case SBI_ECALL_CONSOLE_PUTCHAR:
|
|
||||||
sbi_putc(regs->a0);
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
case SBI_ECALL_CONSOLE_GETCHAR:
|
|
||||||
regs->a0 = sbi_getc();
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
case SBI_ECALL_CLEAR_IPI:
|
|
||||||
sbi_ipi_clear_smode(scratch);
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
case SBI_ECALL_SEND_IPI:
|
|
||||||
ret = sbi_ipi_send_many(scratch, &uptrap, (ulong *)regs->a0,
|
|
||||||
SBI_IPI_EVENT_SOFT, NULL);
|
|
||||||
break;
|
|
||||||
case SBI_ECALL_REMOTE_FENCE_I:
|
|
||||||
ret = sbi_ipi_send_many(scratch, &uptrap, (ulong *)regs->a0,
|
|
||||||
SBI_IPI_EVENT_FENCE_I, NULL);
|
|
||||||
break;
|
|
||||||
case SBI_ECALL_REMOTE_SFENCE_VMA:
|
|
||||||
tlb_info.start = (unsigned long)regs->a1;
|
|
||||||
tlb_info.size = (unsigned long)regs->a2;
|
|
||||||
tlb_info.type = SBI_TLB_FLUSH_VMA;
|
|
||||||
|
|
||||||
ret = sbi_ipi_send_many(scratch, &uptrap, (ulong *)regs->a0,
|
static SBI_LIST_HEAD(ecall_exts_list);
|
||||||
SBI_IPI_EVENT_SFENCE_VMA, &tlb_info);
|
|
||||||
break;
|
|
||||||
case SBI_ECALL_REMOTE_SFENCE_VMA_ASID:
|
|
||||||
tlb_info.start = (unsigned long)regs->a1;
|
|
||||||
tlb_info.size = (unsigned long)regs->a2;
|
|
||||||
tlb_info.asid = (unsigned long)regs->a3;
|
|
||||||
tlb_info.type = SBI_TLB_FLUSH_VMA_ASID;
|
|
||||||
|
|
||||||
ret = sbi_ipi_send_many(scratch, &uptrap, (ulong *)regs->a0,
|
struct sbi_ecall_extension *sbi_ecall_find_extension(unsigned long extid)
|
||||||
SBI_IPI_EVENT_SFENCE_VMA_ASID,
|
{
|
||||||
&tlb_info);
|
struct sbi_ecall_extension *t, *ret = NULL;
|
||||||
break;
|
|
||||||
case SBI_ECALL_SHUTDOWN:
|
|
||||||
sbi_system_shutdown(scratch, 0);
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
regs->a0 = SBI_ENOTSUPP;
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!ret) {
|
sbi_list_for_each_entry(t, &ecall_exts_list, head) {
|
||||||
regs->mepc += 4;
|
if (t->extid_start <= extid && extid <= t->extid_end) {
|
||||||
} else if (ret == SBI_ETRAP) {
|
ret = t;
|
||||||
ret = 0;
|
break;
|
||||||
sbi_trap_redirect(regs, scratch, regs->mepc,
|
}
|
||||||
uptrap.cause, uptrap.tval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sbi_ecall_register_extension(struct sbi_ecall_extension *ext)
|
||||||
|
{
|
||||||
|
struct sbi_ecall_extension *t;
|
||||||
|
|
||||||
|
if (!ext || (ext->extid_end < ext->extid_start) || !ext->handle)
|
||||||
|
return SBI_EINVAL;
|
||||||
|
|
||||||
|
sbi_list_for_each_entry(t, &ecall_exts_list, head) {
|
||||||
|
unsigned long start = t->extid_start;
|
||||||
|
unsigned long end = t->extid_end;
|
||||||
|
if (end < ext->extid_start || ext->extid_end < start)
|
||||||
|
/* no overlap */;
|
||||||
|
else
|
||||||
|
return SBI_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SBI_INIT_LIST_HEAD(&ext->head);
|
||||||
|
sbi_list_add_tail(&ext->head, &ecall_exts_list);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sbi_ecall_unregister_extension(struct sbi_ecall_extension *ext)
|
||||||
|
{
|
||||||
|
bool found = FALSE;
|
||||||
|
struct sbi_ecall_extension *t;
|
||||||
|
|
||||||
|
if (!ext)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sbi_list_for_each_entry(t, &ecall_exts_list, head) {
|
||||||
|
if (t == ext) {
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
sbi_list_del_init(&ext->head);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sbi_ecall_handler(struct sbi_trap_regs *regs)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct sbi_ecall_extension *ext;
|
||||||
|
unsigned long extension_id = regs->a7;
|
||||||
|
unsigned long func_id = regs->a6;
|
||||||
|
struct sbi_trap_info trap = {0};
|
||||||
|
unsigned long out_val = 0;
|
||||||
|
bool is_0_1_spec = 0;
|
||||||
|
|
||||||
|
ext = sbi_ecall_find_extension(extension_id);
|
||||||
|
if (ext && ext->handle) {
|
||||||
|
ret = ext->handle(extension_id, func_id,
|
||||||
|
regs, &out_val, &trap);
|
||||||
|
if (extension_id >= SBI_EXT_0_1_SET_TIMER &&
|
||||||
|
extension_id <= SBI_EXT_0_1_SHUTDOWN)
|
||||||
|
is_0_1_spec = 1;
|
||||||
|
} else {
|
||||||
|
ret = SBI_ENOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == SBI_ETRAP) {
|
||||||
|
trap.epc = regs->mepc;
|
||||||
|
sbi_trap_redirect(regs, &trap);
|
||||||
|
} else {
|
||||||
|
if (ret < SBI_LAST_ERR) {
|
||||||
|
sbi_printf("%s: Invalid error %d for ext=0x%lx "
|
||||||
|
"func=0x%lx\n", __func__, ret,
|
||||||
|
extension_id, func_id);
|
||||||
|
ret = SBI_ERR_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function should return non-zero value only in case of
|
||||||
|
* fatal error. However, there is no good way to distinguish
|
||||||
|
* between a fatal and non-fatal errors yet. That's why we treat
|
||||||
|
* every return value except ETRAP as non-fatal and just return
|
||||||
|
* accordingly for now. Once fatal errors are defined, that
|
||||||
|
* case should be handled differently.
|
||||||
|
*/
|
||||||
|
regs->mepc += 4;
|
||||||
|
regs->a0 = ret;
|
||||||
|
if (!is_0_1_spec)
|
||||||
|
regs->a1 = out_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sbi_ecall_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* The order of below registrations is performance optimized */
|
||||||
|
ret = sbi_ecall_register_extension(&ecall_time);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
ret = sbi_ecall_register_extension(&ecall_rfence);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
ret = sbi_ecall_register_extension(&ecall_ipi);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
ret = sbi_ecall_register_extension(&ecall_base);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
ret = sbi_ecall_register_extension(&ecall_hsm);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
ret = sbi_ecall_register_extension(&ecall_srst);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
ret = sbi_ecall_register_extension(&ecall_legacy);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
ret = sbi_ecall_register_extension(&ecall_vendor);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
79
lib/sbi/sbi_ecall_base.c
Normal file
79
lib/sbi/sbi_ecall_base.c
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
* Atish Patra <atish.patra@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sbi/sbi_ecall.h>
|
||||||
|
#include <sbi/sbi_ecall_interface.h>
|
||||||
|
#include <sbi/sbi_error.h>
|
||||||
|
#include <sbi/sbi_trap.h>
|
||||||
|
#include <sbi/sbi_version.h>
|
||||||
|
#include <sbi/riscv_asm.h>
|
||||||
|
|
||||||
|
static int sbi_ecall_base_probe(unsigned long extid, unsigned long *out_val)
|
||||||
|
{
|
||||||
|
struct sbi_ecall_extension *ext;
|
||||||
|
|
||||||
|
ext = sbi_ecall_find_extension(extid);
|
||||||
|
if (!ext) {
|
||||||
|
*out_val = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ext->probe)
|
||||||
|
return ext->probe(extid, out_val);
|
||||||
|
|
||||||
|
*out_val = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sbi_ecall_base_handler(unsigned long extid, unsigned long funcid,
|
||||||
|
const struct sbi_trap_regs *regs,
|
||||||
|
unsigned long *out_val,
|
||||||
|
struct sbi_trap_info *out_trap)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
switch (funcid) {
|
||||||
|
case SBI_EXT_BASE_GET_SPEC_VERSION:
|
||||||
|
*out_val = (SBI_ECALL_VERSION_MAJOR <<
|
||||||
|
SBI_SPEC_VERSION_MAJOR_OFFSET) &
|
||||||
|
(SBI_SPEC_VERSION_MAJOR_MASK <<
|
||||||
|
SBI_SPEC_VERSION_MAJOR_OFFSET);
|
||||||
|
*out_val = *out_val | SBI_ECALL_VERSION_MINOR;
|
||||||
|
break;
|
||||||
|
case SBI_EXT_BASE_GET_IMP_ID:
|
||||||
|
*out_val = sbi_ecall_get_impid();
|
||||||
|
break;
|
||||||
|
case SBI_EXT_BASE_GET_IMP_VERSION:
|
||||||
|
*out_val = OPENSBI_VERSION;
|
||||||
|
break;
|
||||||
|
case SBI_EXT_BASE_GET_MVENDORID:
|
||||||
|
*out_val = csr_read(CSR_MVENDORID);
|
||||||
|
break;
|
||||||
|
case SBI_EXT_BASE_GET_MARCHID:
|
||||||
|
*out_val = csr_read(CSR_MARCHID);
|
||||||
|
break;
|
||||||
|
case SBI_EXT_BASE_GET_MIMPID:
|
||||||
|
*out_val = csr_read(CSR_MIMPID);
|
||||||
|
break;
|
||||||
|
case SBI_EXT_BASE_PROBE_EXT:
|
||||||
|
ret = sbi_ecall_base_probe(regs->a0, out_val);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = SBI_ENOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sbi_ecall_extension ecall_base = {
|
||||||
|
.extid_start = SBI_EXT_BASE,
|
||||||
|
.extid_end = SBI_EXT_BASE,
|
||||||
|
.handle = sbi_ecall_base_handler,
|
||||||
|
};
|
59
lib/sbi/sbi_ecall_hsm.c
Normal file
59
lib/sbi/sbi_ecall_hsm.c
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Atish Patra <atish.patra@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sbi/sbi_domain.h>
|
||||||
|
#include <sbi/sbi_ecall.h>
|
||||||
|
#include <sbi/sbi_ecall_interface.h>
|
||||||
|
#include <sbi/sbi_error.h>
|
||||||
|
#include <sbi/sbi_trap.h>
|
||||||
|
#include <sbi/sbi_version.h>
|
||||||
|
#include <sbi/sbi_hsm.h>
|
||||||
|
#include <sbi/sbi_scratch.h>
|
||||||
|
#include <sbi/riscv_asm.h>
|
||||||
|
|
||||||
|
static int sbi_ecall_hsm_handler(unsigned long extid, unsigned long funcid,
|
||||||
|
const struct sbi_trap_regs *regs,
|
||||||
|
unsigned long *out_val,
|
||||||
|
struct sbi_trap_info *out_trap)
|
||||||
|
{
|
||||||
|
ulong smode;
|
||||||
|
int ret = 0, hstate;
|
||||||
|
struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
|
||||||
|
|
||||||
|
switch (funcid) {
|
||||||
|
case SBI_EXT_HSM_HART_START:
|
||||||
|
smode = csr_read(CSR_MSTATUS);
|
||||||
|
smode = (smode & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT;
|
||||||
|
ret = sbi_hsm_hart_start(scratch, sbi_domain_thishart_ptr(),
|
||||||
|
regs->a0, regs->a1, smode, regs->a2);
|
||||||
|
break;
|
||||||
|
case SBI_EXT_HSM_HART_STOP:
|
||||||
|
ret = sbi_hsm_hart_stop(scratch, TRUE);
|
||||||
|
break;
|
||||||
|
case SBI_EXT_HSM_HART_GET_STATUS:
|
||||||
|
hstate = sbi_hsm_hart_get_state(sbi_domain_thishart_ptr(),
|
||||||
|
regs->a0);
|
||||||
|
ret = sbi_hsm_hart_state_to_status(hstate);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = SBI_ENOTSUPP;
|
||||||
|
};
|
||||||
|
if (ret >= 0) {
|
||||||
|
*out_val = ret;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sbi_ecall_extension ecall_hsm = {
|
||||||
|
.extid_start = SBI_EXT_HSM,
|
||||||
|
.extid_end = SBI_EXT_HSM,
|
||||||
|
.handle = sbi_ecall_hsm_handler,
|
||||||
|
};
|
124
lib/sbi/sbi_ecall_legacy.c
Normal file
124
lib/sbi/sbi_ecall_legacy.c
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
* Atish Patra <atish.patra@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sbi/riscv_asm.h>
|
||||||
|
#include <sbi/sbi_console.h>
|
||||||
|
#include <sbi/sbi_domain.h>
|
||||||
|
#include <sbi/sbi_ecall.h>
|
||||||
|
#include <sbi/sbi_ecall_interface.h>
|
||||||
|
#include <sbi/sbi_error.h>
|
||||||
|
#include <sbi/sbi_hsm.h>
|
||||||
|
#include <sbi/sbi_ipi.h>
|
||||||
|
#include <sbi/sbi_platform.h>
|
||||||
|
#include <sbi/sbi_system.h>
|
||||||
|
#include <sbi/sbi_timer.h>
|
||||||
|
#include <sbi/sbi_tlb.h>
|
||||||
|
#include <sbi/sbi_trap.h>
|
||||||
|
#include <sbi/sbi_unpriv.h>
|
||||||
|
#include <sbi/sbi_hart.h>
|
||||||
|
|
||||||
|
static int sbi_load_hart_mask_unpriv(ulong *pmask, ulong *hmask,
|
||||||
|
struct sbi_trap_info *uptrap)
|
||||||
|
{
|
||||||
|
ulong mask = 0;
|
||||||
|
|
||||||
|
if (pmask) {
|
||||||
|
mask = sbi_load_ulong(pmask, uptrap);
|
||||||
|
if (uptrap->cause)
|
||||||
|
return SBI_ETRAP;
|
||||||
|
} else {
|
||||||
|
sbi_hsm_hart_started_mask(sbi_domain_thishart_ptr(),
|
||||||
|
0, &mask);
|
||||||
|
}
|
||||||
|
*hmask = mask;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sbi_ecall_legacy_handler(unsigned long extid, unsigned long funcid,
|
||||||
|
const struct sbi_trap_regs *regs,
|
||||||
|
unsigned long *out_val,
|
||||||
|
struct sbi_trap_info *out_trap)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct sbi_tlb_info tlb_info;
|
||||||
|
u32 source_hart = current_hartid();
|
||||||
|
ulong hmask = 0;
|
||||||
|
|
||||||
|
switch (extid) {
|
||||||
|
case SBI_EXT_0_1_SET_TIMER:
|
||||||
|
#if __riscv_xlen == 32
|
||||||
|
sbi_timer_event_start((((u64)regs->a1 << 32) | (u64)regs->a0));
|
||||||
|
#else
|
||||||
|
sbi_timer_event_start((u64)regs->a0);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case SBI_EXT_0_1_CONSOLE_PUTCHAR:
|
||||||
|
sbi_putc(regs->a0);
|
||||||
|
break;
|
||||||
|
case SBI_EXT_0_1_CONSOLE_GETCHAR:
|
||||||
|
ret = sbi_getc();
|
||||||
|
break;
|
||||||
|
case SBI_EXT_0_1_CLEAR_IPI:
|
||||||
|
sbi_ipi_clear_smode();
|
||||||
|
break;
|
||||||
|
case SBI_EXT_0_1_SEND_IPI:
|
||||||
|
ret = sbi_load_hart_mask_unpriv((ulong *)regs->a0,
|
||||||
|
&hmask, out_trap);
|
||||||
|
if (ret != SBI_ETRAP)
|
||||||
|
ret = sbi_ipi_send_smode(hmask, 0);
|
||||||
|
break;
|
||||||
|
case SBI_EXT_0_1_REMOTE_FENCE_I:
|
||||||
|
ret = sbi_load_hart_mask_unpriv((ulong *)regs->a0,
|
||||||
|
&hmask, out_trap);
|
||||||
|
if (ret != SBI_ETRAP) {
|
||||||
|
SBI_TLB_INFO_INIT(&tlb_info, 0, 0, 0, 0,
|
||||||
|
sbi_tlb_local_fence_i,
|
||||||
|
source_hart);
|
||||||
|
ret = sbi_tlb_request(hmask, 0, &tlb_info);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SBI_EXT_0_1_REMOTE_SFENCE_VMA:
|
||||||
|
ret = sbi_load_hart_mask_unpriv((ulong *)regs->a0,
|
||||||
|
&hmask, out_trap);
|
||||||
|
if (ret != SBI_ETRAP) {
|
||||||
|
SBI_TLB_INFO_INIT(&tlb_info, regs->a1, regs->a2, 0, 0,
|
||||||
|
sbi_tlb_local_sfence_vma,
|
||||||
|
source_hart);
|
||||||
|
ret = sbi_tlb_request(hmask, 0, &tlb_info);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID:
|
||||||
|
ret = sbi_load_hart_mask_unpriv((ulong *)regs->a0,
|
||||||
|
&hmask, out_trap);
|
||||||
|
if (ret != SBI_ETRAP) {
|
||||||
|
SBI_TLB_INFO_INIT(&tlb_info, regs->a1,
|
||||||
|
regs->a2, regs->a3, 0,
|
||||||
|
sbi_tlb_local_sfence_vma_asid,
|
||||||
|
source_hart);
|
||||||
|
ret = sbi_tlb_request(hmask, 0, &tlb_info);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SBI_EXT_0_1_SHUTDOWN:
|
||||||
|
sbi_system_reset(SBI_SRST_RESET_TYPE_SHUTDOWN,
|
||||||
|
SBI_SRST_RESET_REASON_NONE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = SBI_ENOTSUPP;
|
||||||
|
};
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sbi_ecall_extension ecall_legacy = {
|
||||||
|
.extid_start = SBI_EXT_0_1_SET_TIMER,
|
||||||
|
.extid_end = SBI_EXT_0_1_SHUTDOWN,
|
||||||
|
.handle = sbi_ecall_legacy_handler,
|
||||||
|
};
|
196
lib/sbi/sbi_ecall_replace.c
Normal file
196
lib/sbi/sbi_ecall_replace.c
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
* Atish Patra <atish.patra@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sbi/riscv_asm.h>
|
||||||
|
#include <sbi/sbi_ecall.h>
|
||||||
|
#include <sbi/sbi_ecall_interface.h>
|
||||||
|
#include <sbi/sbi_error.h>
|
||||||
|
#include <sbi/sbi_hart.h>
|
||||||
|
#include <sbi/sbi_ipi.h>
|
||||||
|
#include <sbi/sbi_system.h>
|
||||||
|
#include <sbi/sbi_timer.h>
|
||||||
|
#include <sbi/sbi_tlb.h>
|
||||||
|
#include <sbi/sbi_trap.h>
|
||||||
|
|
||||||
|
static int sbi_ecall_time_handler(unsigned long extid, unsigned long funcid,
|
||||||
|
const struct sbi_trap_regs *regs,
|
||||||
|
unsigned long *out_val,
|
||||||
|
struct sbi_trap_info *out_trap)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (funcid == SBI_EXT_TIME_SET_TIMER) {
|
||||||
|
#if __riscv_xlen == 32
|
||||||
|
sbi_timer_event_start((((u64)regs->a1 << 32) | (u64)regs->a0));
|
||||||
|
#else
|
||||||
|
sbi_timer_event_start((u64)regs->a0);
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
ret = SBI_ENOTSUPP;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sbi_ecall_extension ecall_time = {
|
||||||
|
.extid_start = SBI_EXT_TIME,
|
||||||
|
.extid_end = SBI_EXT_TIME,
|
||||||
|
.handle = sbi_ecall_time_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int sbi_ecall_rfence_handler(unsigned long extid, unsigned long funcid,
|
||||||
|
const struct sbi_trap_regs *regs,
|
||||||
|
unsigned long *out_val,
|
||||||
|
struct sbi_trap_info *out_trap)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
unsigned long vmid;
|
||||||
|
struct sbi_tlb_info tlb_info;
|
||||||
|
u32 source_hart = current_hartid();
|
||||||
|
|
||||||
|
if (funcid >= SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA &&
|
||||||
|
funcid <= SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID)
|
||||||
|
if (!misa_extension('H'))
|
||||||
|
return SBI_ENOTSUPP;
|
||||||
|
|
||||||
|
switch (funcid) {
|
||||||
|
case SBI_EXT_RFENCE_REMOTE_FENCE_I:
|
||||||
|
SBI_TLB_INFO_INIT(&tlb_info, 0, 0, 0, 0,
|
||||||
|
sbi_tlb_local_fence_i, source_hart);
|
||||||
|
ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info);
|
||||||
|
break;
|
||||||
|
case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA:
|
||||||
|
SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, 0, 0,
|
||||||
|
sbi_tlb_local_hfence_gvma, source_hart);
|
||||||
|
ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info);
|
||||||
|
break;
|
||||||
|
case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID:
|
||||||
|
SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, 0, regs->a4,
|
||||||
|
sbi_tlb_local_hfence_gvma_vmid,
|
||||||
|
source_hart);
|
||||||
|
ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info);
|
||||||
|
break;
|
||||||
|
case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA:
|
||||||
|
vmid = (csr_read(CSR_HGATP) & HGATP_VMID_MASK);
|
||||||
|
vmid = vmid >> HGATP_VMID_SHIFT;
|
||||||
|
SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, 0, vmid,
|
||||||
|
sbi_tlb_local_hfence_vvma, source_hart);
|
||||||
|
ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info);
|
||||||
|
break;
|
||||||
|
case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID:
|
||||||
|
vmid = (csr_read(CSR_HGATP) & HGATP_VMID_MASK);
|
||||||
|
vmid = vmid >> HGATP_VMID_SHIFT;
|
||||||
|
SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, regs->a4,
|
||||||
|
vmid, sbi_tlb_local_hfence_vvma_asid,
|
||||||
|
source_hart);
|
||||||
|
ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info);
|
||||||
|
break;
|
||||||
|
case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA:
|
||||||
|
SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, 0, 0,
|
||||||
|
sbi_tlb_local_sfence_vma, source_hart);
|
||||||
|
ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info);
|
||||||
|
break;
|
||||||
|
case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
|
||||||
|
SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, regs->a4, 0,
|
||||||
|
sbi_tlb_local_sfence_vma_asid, source_hart);
|
||||||
|
ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = SBI_ENOTSUPP;
|
||||||
|
};
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sbi_ecall_extension ecall_rfence = {
|
||||||
|
.extid_start = SBI_EXT_RFENCE,
|
||||||
|
.extid_end = SBI_EXT_RFENCE,
|
||||||
|
.handle = sbi_ecall_rfence_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int sbi_ecall_ipi_handler(unsigned long extid, unsigned long funcid,
|
||||||
|
const struct sbi_trap_regs *regs,
|
||||||
|
unsigned long *out_val,
|
||||||
|
struct sbi_trap_info *out_trap)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (funcid == SBI_EXT_IPI_SEND_IPI)
|
||||||
|
ret = sbi_ipi_send_smode(regs->a0, regs->a1);
|
||||||
|
else
|
||||||
|
ret = SBI_ENOTSUPP;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sbi_ecall_extension ecall_ipi = {
|
||||||
|
.extid_start = SBI_EXT_IPI,
|
||||||
|
.extid_end = SBI_EXT_IPI,
|
||||||
|
.handle = sbi_ecall_ipi_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int sbi_ecall_srst_handler(unsigned long extid, unsigned long funcid,
|
||||||
|
const struct sbi_trap_regs *regs,
|
||||||
|
unsigned long *out_val,
|
||||||
|
struct sbi_trap_info *out_trap)
|
||||||
|
{
|
||||||
|
if (funcid == SBI_EXT_SRST_RESET) {
|
||||||
|
if ((((u32)-1U) <= ((u64)regs->a0)) ||
|
||||||
|
(((u32)-1U) <= ((u64)regs->a1)))
|
||||||
|
return SBI_EINVAL;
|
||||||
|
|
||||||
|
switch (regs->a0) {
|
||||||
|
case SBI_SRST_RESET_TYPE_SHUTDOWN:
|
||||||
|
case SBI_SRST_RESET_TYPE_COLD_REBOOT:
|
||||||
|
case SBI_SRST_RESET_TYPE_WARM_REBOOT:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SBI_ENOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (regs->a1) {
|
||||||
|
case SBI_SRST_RESET_REASON_NONE:
|
||||||
|
case SBI_SRST_RESET_REASON_SYSFAIL:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SBI_ENOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sbi_system_reset_supported(regs->a0, regs->a1))
|
||||||
|
sbi_system_reset(regs->a0, regs->a1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SBI_ENOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sbi_ecall_srst_probe(unsigned long extid, unsigned long *out_val)
|
||||||
|
{
|
||||||
|
u32 type, count = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At least one standard reset types should be supported by
|
||||||
|
* the platform for SBI SRST extension to be usable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (type = 0; type <= SBI_SRST_RESET_TYPE_LAST; type++) {
|
||||||
|
if (sbi_system_reset_supported(type,
|
||||||
|
SBI_SRST_RESET_REASON_NONE))
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_val = (count) ? 1 : 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sbi_ecall_extension ecall_srst = {
|
||||||
|
.extid_start = SBI_EXT_SRST,
|
||||||
|
.extid_end = SBI_EXT_SRST,
|
||||||
|
.handle = sbi_ecall_srst_handler,
|
||||||
|
.probe = sbi_ecall_srst_probe,
|
||||||
|
};
|
40
lib/sbi/sbi_ecall_vendor.c
Normal file
40
lib/sbi/sbi_ecall_vendor.c
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
* Atish Patra <atish.patra@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sbi/sbi_ecall.h>
|
||||||
|
#include <sbi/sbi_ecall_interface.h>
|
||||||
|
#include <sbi/sbi_error.h>
|
||||||
|
#include <sbi/sbi_platform.h>
|
||||||
|
#include <sbi/sbi_trap.h>
|
||||||
|
|
||||||
|
static int sbi_ecall_vendor_probe(unsigned long extid,
|
||||||
|
unsigned long *out_val)
|
||||||
|
{
|
||||||
|
*out_val = sbi_platform_vendor_ext_check(sbi_platform_thishart_ptr(),
|
||||||
|
extid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sbi_ecall_vendor_handler(unsigned long extid, unsigned long funcid,
|
||||||
|
const struct sbi_trap_regs *regs,
|
||||||
|
unsigned long *out_val,
|
||||||
|
struct sbi_trap_info *out_trap)
|
||||||
|
{
|
||||||
|
return sbi_platform_vendor_ext_provider(sbi_platform_thishart_ptr(),
|
||||||
|
extid, funcid, regs,
|
||||||
|
out_val, out_trap);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sbi_ecall_extension ecall_vendor = {
|
||||||
|
.extid_start = SBI_EXT_VENDOR_START,
|
||||||
|
.extid_end = SBI_EXT_VENDOR_END,
|
||||||
|
.probe = sbi_ecall_vendor_probe,
|
||||||
|
.handle = sbi_ecall_vendor_handler,
|
||||||
|
};
|
@@ -9,129 +9,180 @@
|
|||||||
|
|
||||||
#include <sbi/riscv_asm.h>
|
#include <sbi/riscv_asm.h>
|
||||||
#include <sbi/riscv_encoding.h>
|
#include <sbi/riscv_encoding.h>
|
||||||
#include <sbi/sbi_bits.h>
|
#include <sbi/sbi_bitops.h>
|
||||||
#include <sbi/sbi_console.h>
|
#include <sbi/sbi_console.h>
|
||||||
#include <sbi/sbi_emulate_csr.h>
|
#include <sbi/sbi_emulate_csr.h>
|
||||||
#include <sbi/sbi_error.h>
|
#include <sbi/sbi_error.h>
|
||||||
|
#include <sbi/sbi_hart.h>
|
||||||
|
#include <sbi/sbi_scratch.h>
|
||||||
#include <sbi/sbi_timer.h>
|
#include <sbi/sbi_timer.h>
|
||||||
|
#include <sbi/sbi_trap.h>
|
||||||
|
|
||||||
int sbi_emulate_csr_read(int csr_num, u32 hartid, ulong mstatus,
|
static bool hpm_allowed(int hpm_num, ulong prev_mode, bool virt)
|
||||||
struct sbi_scratch *scratch, ulong *csr_val)
|
|
||||||
{
|
{
|
||||||
ulong cen = -1UL;
|
ulong cen = -1UL;
|
||||||
|
|
||||||
if (EXTRACT_FIELD(mstatus, MSTATUS_MPP) == PRV_U)
|
if (prev_mode <= PRV_S) {
|
||||||
cen = csr_read(CSR_SCOUNTEREN);
|
cen &= csr_read(CSR_MCOUNTEREN);
|
||||||
|
if (virt)
|
||||||
|
cen &= csr_read(CSR_HCOUNTEREN);
|
||||||
|
}
|
||||||
|
if (prev_mode == PRV_U)
|
||||||
|
cen &= csr_read(CSR_SCOUNTEREN);
|
||||||
|
|
||||||
|
return ((cen >> hpm_num) & 1) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sbi_emulate_csr_read(int csr_num, struct sbi_trap_regs *regs,
|
||||||
|
ulong *csr_val)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
|
||||||
|
ulong prev_mode = (regs->mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT;
|
||||||
|
#if __riscv_xlen == 32
|
||||||
|
bool virt = (regs->mstatusH & MSTATUSH_MPV) ? TRUE : FALSE;
|
||||||
|
#else
|
||||||
|
bool virt = (regs->mstatus & MSTATUS_MPV) ? TRUE : FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (csr_num) {
|
switch (csr_num) {
|
||||||
|
case CSR_HTIMEDELTA:
|
||||||
|
if (prev_mode == PRV_S && !virt)
|
||||||
|
*csr_val = sbi_timer_get_delta();
|
||||||
|
else
|
||||||
|
ret = SBI_ENOTSUPP;
|
||||||
|
break;
|
||||||
case CSR_CYCLE:
|
case CSR_CYCLE:
|
||||||
if (!((cen >> (CSR_CYCLE - CSR_CYCLE)) & 1))
|
if (!hpm_allowed(csr_num - CSR_CYCLE, prev_mode, virt))
|
||||||
return -1;
|
return SBI_ENOTSUPP;
|
||||||
*csr_val = csr_read(CSR_MCYCLE);
|
*csr_val = csr_read(CSR_MCYCLE);
|
||||||
break;
|
break;
|
||||||
case CSR_TIME:
|
case CSR_TIME:
|
||||||
if (!((cen >> (CSR_TIME - CSR_CYCLE)) & 1))
|
/*
|
||||||
return -1;
|
* We emulate TIME CSR for both Host (HS/U-mode) and
|
||||||
*csr_val = sbi_timer_value(scratch);
|
* Guest (VS/VU-mode).
|
||||||
|
*
|
||||||
|
* Faster TIME CSR reads are critical for good performance
|
||||||
|
* in S-mode software so we don't check CSR permissions.
|
||||||
|
*/
|
||||||
|
*csr_val = (virt) ? sbi_timer_virt_value():
|
||||||
|
sbi_timer_value();
|
||||||
break;
|
break;
|
||||||
case CSR_INSTRET:
|
case CSR_INSTRET:
|
||||||
if (!((cen >> (CSR_INSTRET - CSR_CYCLE)) & 1))
|
if (!hpm_allowed(csr_num - CSR_CYCLE, prev_mode, virt))
|
||||||
return -1;
|
return SBI_ENOTSUPP;
|
||||||
*csr_val = csr_read(CSR_MINSTRET);
|
*csr_val = csr_read(CSR_MINSTRET);
|
||||||
break;
|
break;
|
||||||
case CSR_MHPMCOUNTER3:
|
|
||||||
if (!((cen >> (3 + CSR_MHPMCOUNTER3 - CSR_MHPMCOUNTER3)) & 1))
|
|
||||||
return -1;
|
|
||||||
*csr_val = csr_read(CSR_MHPMCOUNTER3);
|
|
||||||
break;
|
|
||||||
case CSR_MHPMCOUNTER4:
|
|
||||||
if (!((cen >> (3 + CSR_MHPMCOUNTER4 - CSR_MHPMCOUNTER3)) & 1))
|
|
||||||
return -1;
|
|
||||||
*csr_val = csr_read(CSR_MHPMCOUNTER4);
|
|
||||||
break;
|
|
||||||
#if __riscv_xlen == 32
|
#if __riscv_xlen == 32
|
||||||
|
case CSR_HTIMEDELTAH:
|
||||||
|
if (prev_mode == PRV_S && !virt)
|
||||||
|
*csr_val = sbi_timer_get_delta() >> 32;
|
||||||
|
else
|
||||||
|
ret = SBI_ENOTSUPP;
|
||||||
|
break;
|
||||||
case CSR_CYCLEH:
|
case CSR_CYCLEH:
|
||||||
if (!((cen >> (CSR_CYCLE - CSR_CYCLE)) & 1))
|
if (!hpm_allowed(csr_num - CSR_CYCLEH, prev_mode, virt))
|
||||||
return -1;
|
return SBI_ENOTSUPP;
|
||||||
*csr_val = csr_read(CSR_MCYCLEH);
|
*csr_val = csr_read(CSR_MCYCLEH);
|
||||||
break;
|
break;
|
||||||
case CSR_TIMEH:
|
case CSR_TIMEH:
|
||||||
if (!((cen >> (CSR_TIME - CSR_CYCLE)) & 1))
|
/* Refer comments on TIME CSR above. */
|
||||||
return -1;
|
*csr_val = (virt) ? sbi_timer_virt_value() >> 32:
|
||||||
*csr_val = sbi_timer_value(scratch) >> 32;
|
sbi_timer_value() >> 32;
|
||||||
break;
|
break;
|
||||||
case CSR_INSTRETH:
|
case CSR_INSTRETH:
|
||||||
if (!((cen >> (CSR_INSTRET - CSR_CYCLE)) & 1))
|
if (!hpm_allowed(csr_num - CSR_CYCLEH, prev_mode, virt))
|
||||||
return -1;
|
return SBI_ENOTSUPP;
|
||||||
*csr_val = csr_read(CSR_MINSTRETH);
|
*csr_val = csr_read(CSR_MINSTRETH);
|
||||||
break;
|
break;
|
||||||
case CSR_MHPMCOUNTER3H:
|
|
||||||
if (!((cen >> (3 + CSR_MHPMCOUNTER3 - CSR_MHPMCOUNTER3)) & 1))
|
|
||||||
return -1;
|
|
||||||
*csr_val = csr_read(CSR_MHPMCOUNTER3H);
|
|
||||||
break;
|
|
||||||
case CSR_MHPMCOUNTER4H:
|
|
||||||
if (!((cen >> (3 + CSR_MHPMCOUNTER4 - CSR_MHPMCOUNTER3)) & 1))
|
|
||||||
return -1;
|
|
||||||
*csr_val = csr_read(CSR_MHPMCOUNTER4H);
|
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
case CSR_MHPMEVENT3:
|
|
||||||
*csr_val = csr_read(CSR_MHPMEVENT3);
|
#define switchcase_hpm(__uref, __mref, __csr) \
|
||||||
break;
|
case __csr: \
|
||||||
case CSR_MHPMEVENT4:
|
if ((sbi_hart_mhpm_count(scratch) + 3) <= (__csr - __uref))\
|
||||||
*csr_val = csr_read(CSR_MHPMEVENT4);
|
return SBI_ENOTSUPP; \
|
||||||
|
if (!hpm_allowed(__csr - __uref, prev_mode, virt)) \
|
||||||
|
return SBI_ENOTSUPP; \
|
||||||
|
*csr_val = csr_read(__mref + __csr - __uref); \
|
||||||
break;
|
break;
|
||||||
|
#define switchcase_hpm_2(__uref, __mref, __csr) \
|
||||||
|
switchcase_hpm(__uref, __mref, __csr + 0) \
|
||||||
|
switchcase_hpm(__uref, __mref, __csr + 1)
|
||||||
|
#define switchcase_hpm_4(__uref, __mref, __csr) \
|
||||||
|
switchcase_hpm_2(__uref, __mref, __csr + 0) \
|
||||||
|
switchcase_hpm_2(__uref, __mref, __csr + 2)
|
||||||
|
#define switchcase_hpm_8(__uref, __mref, __csr) \
|
||||||
|
switchcase_hpm_4(__uref, __mref, __csr + 0) \
|
||||||
|
switchcase_hpm_4(__uref, __mref, __csr + 4)
|
||||||
|
#define switchcase_hpm_16(__uref, __mref, __csr) \
|
||||||
|
switchcase_hpm_8(__uref, __mref, __csr + 0) \
|
||||||
|
switchcase_hpm_8(__uref, __mref, __csr + 8)
|
||||||
|
|
||||||
|
switchcase_hpm(CSR_CYCLE, CSR_MCYCLE, CSR_HPMCOUNTER3)
|
||||||
|
switchcase_hpm_4(CSR_CYCLE, CSR_MCYCLE, CSR_HPMCOUNTER4)
|
||||||
|
switchcase_hpm_8(CSR_CYCLE, CSR_MCYCLE, CSR_HPMCOUNTER8)
|
||||||
|
switchcase_hpm_16(CSR_CYCLE, CSR_MCYCLE, CSR_HPMCOUNTER16)
|
||||||
|
|
||||||
|
#if __riscv_xlen == 32
|
||||||
|
switchcase_hpm(CSR_CYCLEH, CSR_MCYCLEH, CSR_HPMCOUNTER3H)
|
||||||
|
switchcase_hpm_4(CSR_CYCLEH, CSR_MCYCLEH, CSR_HPMCOUNTER4H)
|
||||||
|
switchcase_hpm_8(CSR_CYCLEH, CSR_MCYCLEH, CSR_HPMCOUNTER8H)
|
||||||
|
switchcase_hpm_16(CSR_CYCLEH, CSR_MCYCLEH, CSR_HPMCOUNTER16H)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef switchcase_hpm_16
|
||||||
|
#undef switchcase_hpm_8
|
||||||
|
#undef switchcase_hpm_4
|
||||||
|
#undef switchcase_hpm_2
|
||||||
|
#undef switchcase_hpm
|
||||||
|
|
||||||
default:
|
default:
|
||||||
sbi_printf("%s: hartid%d: invalid csr_num=0x%x\n", __func__,
|
ret = SBI_ENOTSUPP;
|
||||||
hartid, csr_num);
|
break;
|
||||||
return SBI_ENOTSUPP;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return 0;
|
if (ret)
|
||||||
|
sbi_dprintf("%s: hartid%d: invalid csr_num=0x%x\n",
|
||||||
|
__func__, current_hartid(), csr_num);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sbi_emulate_csr_write(int csr_num, u32 hartid, ulong mstatus,
|
int sbi_emulate_csr_write(int csr_num, struct sbi_trap_regs *regs,
|
||||||
struct sbi_scratch *scratch, ulong csr_val)
|
ulong csr_val)
|
||||||
{
|
{
|
||||||
|
int ret = 0;
|
||||||
|
ulong prev_mode = (regs->mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT;
|
||||||
|
#if __riscv_xlen == 32
|
||||||
|
bool virt = (regs->mstatusH & MSTATUSH_MPV) ? TRUE : FALSE;
|
||||||
|
#else
|
||||||
|
bool virt = (regs->mstatus & MSTATUS_MPV) ? TRUE : FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (csr_num) {
|
switch (csr_num) {
|
||||||
case CSR_CYCLE:
|
case CSR_HTIMEDELTA:
|
||||||
csr_write(CSR_MCYCLE, csr_val);
|
if (prev_mode == PRV_S && !virt)
|
||||||
break;
|
sbi_timer_set_delta(csr_val);
|
||||||
case CSR_INSTRET:
|
else
|
||||||
csr_write(CSR_MINSTRET, csr_val);
|
ret = SBI_ENOTSUPP;
|
||||||
break;
|
|
||||||
case CSR_MHPMCOUNTER3:
|
|
||||||
csr_write(CSR_MHPMCOUNTER3, csr_val);
|
|
||||||
break;
|
|
||||||
case CSR_MHPMCOUNTER4:
|
|
||||||
csr_write(CSR_MHPMCOUNTER4, csr_val);
|
|
||||||
break;
|
break;
|
||||||
#if __riscv_xlen == 32
|
#if __riscv_xlen == 32
|
||||||
case CSR_CYCLEH:
|
case CSR_HTIMEDELTAH:
|
||||||
csr_write(CSR_MCYCLEH, csr_val);
|
if (prev_mode == PRV_S && !virt)
|
||||||
break;
|
sbi_timer_set_delta_upper(csr_val);
|
||||||
case CSR_INSTRETH:
|
else
|
||||||
csr_write(CSR_MINSTRETH, csr_val);
|
ret = SBI_ENOTSUPP;
|
||||||
break;
|
|
||||||
case CSR_MHPMCOUNTER3H:
|
|
||||||
csr_write(CSR_MHPMCOUNTER3H, csr_val);
|
|
||||||
break;
|
|
||||||
case CSR_MHPMCOUNTER4H:
|
|
||||||
csr_write(CSR_MHPMCOUNTER4H, csr_val);
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case CSR_MHPMEVENT3:
|
|
||||||
csr_write(CSR_MHPMEVENT3, csr_val);
|
|
||||||
break;
|
|
||||||
case CSR_MHPMEVENT4:
|
|
||||||
csr_write(CSR_MHPMEVENT4, csr_val);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
sbi_printf("%s: hartid%d: invalid csr_num=0x%x\n", __func__,
|
ret = SBI_ENOTSUPP;
|
||||||
hartid, csr_num);
|
break;
|
||||||
return SBI_ENOTSUPP;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return 0;
|
if (ret)
|
||||||
|
sbi_dprintf("%s: hartid%d: invalid csr_num=0x%x\n",
|
||||||
|
__func__, current_hartid(), csr_num);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
56
lib/sbi/sbi_expected_trap.S
Normal file
56
lib/sbi/sbi_expected_trap.S
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sbi/riscv_asm.h>
|
||||||
|
#include <sbi/sbi_trap.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We assume that faulting instruction is is 4-byte long and blindly
|
||||||
|
* increment SEPC by 4.
|
||||||
|
*
|
||||||
|
* The trap info will be saved as follows:
|
||||||
|
* A3 <- pointer struct sbi_trap_info
|
||||||
|
* A4 <- temporary
|
||||||
|
*/
|
||||||
|
|
||||||
|
.align 3
|
||||||
|
.global __sbi_expected_trap
|
||||||
|
__sbi_expected_trap:
|
||||||
|
/* Without H-extension so, MTVAL2 and MTINST CSRs not available */
|
||||||
|
csrr a4, CSR_MEPC
|
||||||
|
REG_S a4, SBI_TRAP_INFO_OFFSET(epc)(a3)
|
||||||
|
csrr a4, CSR_MCAUSE
|
||||||
|
REG_S a4, SBI_TRAP_INFO_OFFSET(cause)(a3)
|
||||||
|
csrr a4, CSR_MTVAL
|
||||||
|
REG_S a4, SBI_TRAP_INFO_OFFSET(tval)(a3)
|
||||||
|
REG_S zero, SBI_TRAP_INFO_OFFSET(tval2)(a3)
|
||||||
|
REG_S zero, SBI_TRAP_INFO_OFFSET(tinst)(a3)
|
||||||
|
csrr a4, CSR_MEPC
|
||||||
|
addi a4, a4, 4
|
||||||
|
csrw CSR_MEPC, a4
|
||||||
|
mret
|
||||||
|
|
||||||
|
.align 3
|
||||||
|
.global __sbi_expected_trap_hext
|
||||||
|
__sbi_expected_trap_hext:
|
||||||
|
/* With H-extension so, MTVAL2 and MTINST CSRs available */
|
||||||
|
csrr a4, CSR_MEPC
|
||||||
|
REG_S a4, SBI_TRAP_INFO_OFFSET(epc)(a3)
|
||||||
|
csrr a4, CSR_MCAUSE
|
||||||
|
REG_S a4, SBI_TRAP_INFO_OFFSET(cause)(a3)
|
||||||
|
csrr a4, CSR_MTVAL
|
||||||
|
REG_S a4, SBI_TRAP_INFO_OFFSET(tval)(a3)
|
||||||
|
csrr a4, CSR_MTVAL2
|
||||||
|
REG_S a4, SBI_TRAP_INFO_OFFSET(tval2)(a3)
|
||||||
|
csrr a4, CSR_MTINST
|
||||||
|
REG_S a4, SBI_TRAP_INFO_OFFSET(tinst)(a3)
|
||||||
|
csrr a4, CSR_MEPC
|
||||||
|
addi a4, a4, 4
|
||||||
|
csrw CSR_MEPC, a4
|
||||||
|
mret
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user