mirror of
https://github.com/mmueller41/genode.git
synced 2026-01-22 04:52:56 +01:00
Compare commits
272 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2034180d87 | ||
|
|
88cae5e82e | ||
|
|
bdfe634fdf | ||
|
|
f2d38443f7 | ||
|
|
7138b2740a | ||
|
|
a42a5995cf | ||
|
|
4673eb9578 | ||
|
|
2c61392237 | ||
|
|
2c3a0bbe1b | ||
|
|
973d710101 | ||
|
|
8ef8e8ede9 | ||
|
|
615830e107 | ||
|
|
acf00c29c3 | ||
|
|
24f97f9593 | ||
|
|
53316bfd55 | ||
|
|
7740da3197 | ||
|
|
9e443c78db | ||
|
|
db89c85954 | ||
|
|
078883fda3 | ||
|
|
b28a551538 | ||
|
|
e777165090 | ||
|
|
aaf0454956 | ||
|
|
a9e95e24fe | ||
|
|
c04ddbf6d8 | ||
|
|
0a0f0031a4 | ||
|
|
ea79c0e2e9 | ||
|
|
33f64343e1 | ||
|
|
15e231d733 | ||
|
|
039e333d2b | ||
|
|
927af36c58 | ||
|
|
afbe3d8674 | ||
|
|
6a1c11393e | ||
|
|
b718a94b47 | ||
|
|
05a460c11f | ||
|
|
aff92004d1 | ||
|
|
de4335b443 | ||
|
|
5cdfb0a3a5 | ||
|
|
313202fb65 | ||
|
|
d1e10e939d | ||
|
|
abcb0f62d7 | ||
|
|
6adbb9e438 | ||
|
|
e17f271ba6 | ||
|
|
7d4f8fa746 | ||
|
|
35cf48cdc8 | ||
|
|
85a2ebc1c4 | ||
|
|
bcbb0dabf5 | ||
|
|
de65c3f7cc | ||
|
|
3de1423a6a | ||
|
|
a128b40f03 | ||
|
|
ba291bcc57 | ||
|
|
9f43aa4363 | ||
|
|
f1aa137c9d | ||
|
|
776d7f947f | ||
|
|
d4bf55a308 | ||
|
|
99245aceb2 | ||
|
|
fe5c31b774 | ||
|
|
b2f78cc475 | ||
|
|
ca971bbfd8 | ||
|
|
1f9890d635 | ||
|
|
42cce8668b | ||
|
|
6553e9d79f | ||
|
|
8c5f350e0e | ||
|
|
de0a771fae | ||
|
|
8366d07082 | ||
|
|
8da1c77908 | ||
|
|
bab5bb67e7 | ||
|
|
ed2d54ed87 | ||
|
|
73eb7a8d4b | ||
|
|
34b18e9da2 | ||
|
|
b888a26d57 | ||
|
|
0ddc69d370 | ||
|
|
4782fd34f6 | ||
|
|
512c29c486 | ||
|
|
37dc5c2c78 | ||
|
|
8824ce8962 | ||
|
|
b9cf2eade8 | ||
|
|
13cc423050 | ||
|
|
fb673fe4fd | ||
|
|
3e4eb0d135 | ||
|
|
34dd7f982c | ||
|
|
5de17d4223 | ||
|
|
0b04f9de25 | ||
|
|
9fd6034e94 | ||
|
|
a9fc5304c0 | ||
|
|
60d9c90921 | ||
|
|
c7f1b85652 | ||
|
|
8876dd057d | ||
|
|
d65872a815 | ||
|
|
fd66252ca4 | ||
|
|
16378745bf | ||
|
|
7750a399cc | ||
|
|
a011c76d85 | ||
|
|
dd9b606182 | ||
|
|
8e74fdc585 | ||
|
|
959b26fee0 | ||
|
|
83a03df6a4 | ||
|
|
c3c6a82d13 | ||
|
|
d7d62c53a6 | ||
|
|
2b5f4b0aaf | ||
|
|
b43a5f1255 | ||
|
|
a96f912f73 | ||
|
|
797a6c7422 | ||
|
|
3bb7d4e67b | ||
|
|
28a5404281 | ||
|
|
d83e076f11 | ||
|
|
b1a6db090f | ||
|
|
4dd2db7634 | ||
|
|
58c4f1585b | ||
|
|
0e208c3d3d | ||
|
|
5d23e5903e | ||
|
|
b53601d01b | ||
|
|
3d274366ab | ||
|
|
2c7c814e19 | ||
|
|
a7bc8bac9a | ||
|
|
9ae441e469 | ||
|
|
bfa3053e62 | ||
|
|
ecaf09a41b | ||
|
|
617d5ee3e6 | ||
|
|
69bc875ac7 | ||
|
|
0eef45e63f | ||
|
|
0c08334b2c | ||
|
|
03ce614c23 | ||
|
|
5169de72c4 | ||
|
|
73f71322f0 | ||
|
|
93f06dd11a | ||
|
|
b5fe1d752b | ||
|
|
a9521853bd | ||
|
|
3f14defd9d | ||
|
|
5a1fc6da60 | ||
|
|
b7e806d5eb | ||
|
|
fabea7fba1 | ||
|
|
f8c2596259 | ||
|
|
d67a26ea4c | ||
|
|
7836d92b22 | ||
|
|
9f95784f02 | ||
|
|
e856158824 | ||
|
|
b34ce7d2b0 | ||
|
|
f0ec8b27c1 | ||
|
|
b55646e1b0 | ||
|
|
8d1e40eb5b | ||
|
|
ebfd6a55b3 | ||
|
|
8f9d4737a6 | ||
|
|
7ffcc74d72 | ||
|
|
02c16e7106 | ||
|
|
c72f91fefb | ||
|
|
6974abcf41 | ||
|
|
99db9e5246 | ||
|
|
7bbabcf817 | ||
|
|
f8b4541e2b | ||
|
|
4f19d4869f | ||
|
|
ea156e18ec | ||
|
|
dbad6f7061 | ||
|
|
9e089e7e75 | ||
|
|
fba4f54571 | ||
|
|
abd55fda9a | ||
|
|
5e940da040 | ||
|
|
055b7c57b6 | ||
|
|
d5b38b674e | ||
|
|
06ea6cd462 | ||
|
|
1eeba3ed73 | ||
|
|
873c3f3984 | ||
|
|
a64372647d | ||
|
|
5112df9792 | ||
|
|
e2268c09a0 | ||
|
|
f0ac145471 | ||
|
|
00708b6696 | ||
|
|
d30edd4841 | ||
|
|
9affbf33ec | ||
|
|
ff28a89000 | ||
|
|
a34227cdda | ||
|
|
7fc26d496a | ||
|
|
47b1db6f0a | ||
|
|
819e54f860 | ||
|
|
0918c6006b | ||
|
|
7f2b99e2a8 | ||
|
|
1eb3f13484 | ||
|
|
7d232cafb0 | ||
|
|
34a33e7301 | ||
|
|
a604ea6851 | ||
|
|
cd0d378142 | ||
|
|
2f3b67c9e0 | ||
|
|
2262eb8347 | ||
|
|
e6c7596af5 | ||
|
|
869fbc92b1 | ||
|
|
ced0f71f13 | ||
|
|
7e35b84054 | ||
|
|
2e5cb2ea82 | ||
|
|
c7d2d3a231 | ||
|
|
a951a9f72f | ||
|
|
e285d806b3 | ||
|
|
ba4045889b | ||
|
|
b8e6124594 | ||
|
|
0dece91973 | ||
|
|
36bfb56e49 | ||
|
|
9a9d093e01 | ||
|
|
6476cb3bbd | ||
|
|
76668f0774 | ||
|
|
db8957562f | ||
|
|
358b2ef0c7 | ||
|
|
8de324245c | ||
|
|
83cc8da588 | ||
|
|
da9e764c47 | ||
|
|
0b7ea4abab | ||
|
|
f988c254df | ||
|
|
8ce197d7fa | ||
|
|
18cee192e2 | ||
|
|
852785324f | ||
|
|
8818d810a1 | ||
|
|
17f17df74b | ||
|
|
010e00ae7a | ||
|
|
a8d071b372 | ||
|
|
044a109c3a | ||
|
|
a99a33e93e | ||
|
|
3f9b098b70 | ||
|
|
c3b161e814 | ||
|
|
65dac52574 | ||
|
|
330b0a731c | ||
|
|
45b4d6b187 | ||
|
|
e7f3e99aab | ||
|
|
f5be746894 | ||
|
|
6525ec5951 | ||
|
|
a61e278cec | ||
|
|
b9041d601d | ||
|
|
aeb9213e73 | ||
|
|
d605681ce4 | ||
|
|
6e21ab42d2 | ||
|
|
56e4588e91 | ||
|
|
395e955756 | ||
|
|
a586828844 | ||
|
|
49bf33e404 | ||
|
|
f545fa0e36 | ||
|
|
e38060d81e | ||
|
|
52addb591b | ||
|
|
ed9c4f4427 | ||
|
|
5f0843082a | ||
|
|
f02e9001e8 | ||
|
|
6c1d1363ff | ||
|
|
194b6b64c1 | ||
|
|
d2fd00a828 | ||
|
|
7bdb8c9007 | ||
|
|
effeb765b9 | ||
|
|
5d444a12dc | ||
|
|
108b29d33d | ||
|
|
f9ea52db9a | ||
|
|
2a503d3599 | ||
|
|
e3c262579d | ||
|
|
1335b7b550 | ||
|
|
3a4f7128fd | ||
|
|
ce9e43ae51 | ||
|
|
7cea03f695 | ||
|
|
6a3368ee27 | ||
|
|
e83849cf99 | ||
|
|
1e7c0c2066 | ||
|
|
722154f0a8 | ||
|
|
c288973bf2 | ||
|
|
f0c54a7ca3 | ||
|
|
1730e10469 | ||
|
|
be7a119deb | ||
|
|
6fcdbf5e9e | ||
|
|
864189762c | ||
|
|
1914f5ae2e | ||
|
|
ff70ca6427 | ||
|
|
e142d0d2e8 | ||
|
|
2ed22595ff | ||
|
|
47179201a5 | ||
|
|
4c5c9fd7a9 | ||
|
|
28bb1f8fd7 | ||
|
|
83266db30b | ||
|
|
caad308a21 | ||
|
|
b6a28795dd | ||
|
|
4092cd1f6e | ||
|
|
bea9feb362 |
206
.gitignore
vendored
206
.gitignore
vendored
@@ -3,165 +3,49 @@
|
||||
*.swp
|
||||
*.rej
|
||||
|
||||
/base-codezero/contrib
|
||||
/base-fiasco/contrib
|
||||
/base-fiasco/download
|
||||
/base-foc/contrib
|
||||
/base-nova/contrib
|
||||
/base-nova/download
|
||||
/base-okl4/contrib
|
||||
/base-okl4/download
|
||||
/base-pistachio/contrib
|
||||
/dde_ipxe/contrib
|
||||
/dde_linux/contrib
|
||||
/dde_linux/download
|
||||
/dde_oss/contrib
|
||||
/dde_oss/download
|
||||
/dde_rump/contrib
|
||||
/dde_rump/include/rump
|
||||
/libports/contrib
|
||||
/libports/download
|
||||
/libports/include/curl/
|
||||
/libports/include/EGL/egl.h
|
||||
/libports/include/EGL/eglext.h
|
||||
/libports/include/GL
|
||||
/libports/include/KHR
|
||||
/libports/include/SDL
|
||||
/libports/include/exfat
|
||||
/libports/include/ffat
|
||||
/libports/include/fribidi
|
||||
/libports/include/freetype
|
||||
/libports/include/ft2build.h
|
||||
/libports/include/fuse-ext2
|
||||
/libports/include/iconv/
|
||||
/libports/include/icu/
|
||||
/libports/include/jbig2dec
|
||||
/libports/include/libc-amd64/
|
||||
/libports/include/libc-arm/
|
||||
/libports/include/libc-i386/
|
||||
/libports/include/libc/
|
||||
/libports/include/libpng
|
||||
/libports/include/libssh/
|
||||
/libports/include/lua
|
||||
/libports/include/lwip/lwip
|
||||
/libports/include/lwip/netif
|
||||
/libports/include/mupdf
|
||||
/libports/include/ncurses/MKterm.h.awk
|
||||
/libports/include/ncurses/capdefaults.c
|
||||
/libports/include/ncurses/curses.h
|
||||
/libports/include/ncurses/ncurses.h
|
||||
/libports/include/ncurses/hashed_db.h
|
||||
/libports/include/ncurses/hashsize.h
|
||||
/libports/include/ncurses/init_keytry.h
|
||||
/libports/include/ncurses/keys.list
|
||||
/libports/include/ncurses/nc_alloc.h
|
||||
/libports/include/ncurses/nc_panel.h
|
||||
/libports/include/ncurses/nc_tparm.h
|
||||
/libports/include/ncurses/ncurses_def.h
|
||||
/libports/include/ncurses/ncurses_dll.h
|
||||
/libports/include/ncurses/parametrized.h
|
||||
/libports/include/ncurses/term.h
|
||||
/libports/include/ncurses/term_entry.h
|
||||
/libports/include/ncurses/termcap.h
|
||||
/libports/include/ncurses/tic.h
|
||||
/libports/include/ncurses/unctrl.h
|
||||
/libports/include/openjpeg
|
||||
/libports/include/openssl
|
||||
/libports/src/lib/openssl/x86_32/aes_enc.s
|
||||
/libports/src/lib/openssl/x86_32/cpuid.s
|
||||
/libports/src/lib/openssl/x86_64/aes_enc.s
|
||||
/libports/src/lib/openssl/x86_64/cpuid.s
|
||||
/libports/src/lib/openssl/x86_64/modexp512.s
|
||||
/libports/src/lib/openssl/x86_64/rc4_md5.s
|
||||
/libports/include/pcre
|
||||
/libports/include/python2.6
|
||||
/libports/include/qoost
|
||||
/libports/include/readline/keymaps.h
|
||||
/libports/include/readline/rlstdc.h
|
||||
/libports/include/readline/rltypedefs.h
|
||||
/libports/include/readline/tilde.h
|
||||
/libports/include/stdcxx
|
||||
/libports/include/zlib
|
||||
/libports/include/gmp/gmp-impl.h
|
||||
/libports/include/gmp/arm/gmp-mparam.h
|
||||
/libports/include/gmp/x86_32/gmp-mparam.h
|
||||
/libports/include/gmp/x86_64/gmp-mparam.h
|
||||
/libports/include/mpc/
|
||||
/libports/include/mpfr/
|
||||
/libports/include/stdcxx-genode/bits/atomic_lockfree_defines.h
|
||||
/libports/include/stdcxx-genode/bits/atomic_word.h
|
||||
/libports/include/stdcxx-genode/bits/basic_file.h
|
||||
/libports/include/stdcxx-genode/bits/c++allocator.h
|
||||
/libports/include/stdcxx-genode/bits/c++io.h
|
||||
/libports/include/stdcxx-genode/bits/c++locale.h
|
||||
/libports/include/stdcxx-genode/bits/cpu_defines.h
|
||||
/libports/include/stdcxx-genode/bits/cxxabi_tweaks.h
|
||||
/libports/include/stdcxx-genode/bits/ctype_base.h
|
||||
/libports/include/stdcxx-genode/bits/ctype_inline.h
|
||||
/libports/include/stdcxx-genode/bits/cxxabi_forced.h
|
||||
/libports/include/stdcxx-genode/bits/error_constants.h
|
||||
/libports/include/stdcxx-genode/bits/exception_defines.h
|
||||
/libports/include/stdcxx-genode/bits/hash_bytes.h
|
||||
/libports/include/stdcxx-genode/bits/messages_members.h
|
||||
/libports/include/stdcxx-genode/bits/os_defines.h
|
||||
/libports/include/stdcxx-genode/bits/time_members.h
|
||||
/libports/include/stdcxx-genode/bits/exception_ptr.h
|
||||
/libports/include/stdcxx-genode/bits/nested_exception.h
|
||||
/libports/include/stdcxx-genode/exception
|
||||
/libports/include/stdcxx-genode/new
|
||||
/libports/include/stdcxx-genode/typeinfo
|
||||
/libports/include/stdcxx-genode/initializer_list
|
||||
/libports/include/x86emu/stdint.h
|
||||
/libports/include/x86emu/stdio.h
|
||||
/libports/include/x86emu/stdlib.h
|
||||
/libports/include/x86emu/string.h
|
||||
/libports/include/x86emu/x86emu.h
|
||||
/libports/include/x86emu/x86emu/
|
||||
/libports/src/lib/gmp/mpn/asm-defs.m4
|
||||
/libports/src/lib/gmp/mpn/arm/hamdist.c
|
||||
/libports/src/lib/gmp/mpn/arm/popcount.c
|
||||
/libports/src/lib/gmp/mpn/x86_32/add_n.asm
|
||||
/libports/src/lib/gmp/mpn/x86_32/sub_n.asm
|
||||
/libports/src/lib/gmp/mpn/x86_64/add_n.asm
|
||||
/libports/src/lib/gmp/mpn/x86_64/hamdist.asm
|
||||
/libports/src/lib/gmp/mpn/x86_64/popcount.asm
|
||||
/libports/src/lib/gmp/mpn/x86_64/sub_n.asm
|
||||
/libports/src/lib/ncurses/codes.c
|
||||
/libports/src/lib/ncurses/comp_captab.c
|
||||
/libports/src/lib/ncurses/fallback.c
|
||||
/libports/src/lib/ncurses/make_hash
|
||||
/libports/src/lib/ncurses/make_keys
|
||||
/libports/src/lib/ncurses/names.c
|
||||
/libports/src/lib/ncurses/unctrl.c
|
||||
/libports/src/lib/qt5/qtjsbackend
|
||||
/libports/src/lib/qt5/qtwebkit/Source/JavaScriptCore
|
||||
/libports/src/lib/qt5/qtwebkit/Source/WebCore/generated
|
||||
/libports/tool/mesa/glsl
|
||||
/libports/tool/mupdf
|
||||
/libports/tool/qt5/bootstrap
|
||||
/libports/tool/qt5/misc/var
|
||||
/libports/tool/qt5/moc
|
||||
/libports/tool/qt5/qmake/*.d
|
||||
/libports/tool/qt5/qmake/*.o
|
||||
/libports/tool/qt5/qmake/qmake
|
||||
/libports/tool/qt5/rcc
|
||||
/libports/tool/qt5/uic
|
||||
/ports-foc/contrib
|
||||
/ports-okl4/contrib
|
||||
/ports-okl4/download
|
||||
/ports/contrib
|
||||
/ports/download
|
||||
/ports/src/app/arora/html
|
||||
/ports/src/lib/gdbserver_platform/generated
|
||||
/qt4/contrib
|
||||
/qt4/download
|
||||
/qt4/tool/bootstrap
|
||||
/qt4/tool/misc/var
|
||||
/qt4/tool/moc
|
||||
/qt4/tool/qmake/*.d
|
||||
/qt4/tool/qmake/*.o
|
||||
/qt4/tool/qmake/qmake
|
||||
/qt4/tool/rcc
|
||||
/qt4/tool/uic
|
||||
/linux_drivers
|
||||
/build
|
||||
/contrib
|
||||
/repos/base-codezero/contrib
|
||||
/repos/base-fiasco/contrib
|
||||
/repos/base-fiasco/download
|
||||
/repos/base-foc/contrib
|
||||
/repos/base-pistachio/contrib
|
||||
/repos/dde_ipxe/contrib
|
||||
/repos/dde_linux/contrib
|
||||
/repos/dde_linux/download
|
||||
/repos/dde_oss/contrib
|
||||
/repos/dde_oss/download
|
||||
/repos/dde_rump/contrib
|
||||
/repos/dde_rump/include/rump
|
||||
/repos/libports/contrib
|
||||
/repos/libports/download
|
||||
/repos/libports/src/lib/qt5/qtjsbackend
|
||||
/repos/libports/src/lib/qt5/qtwebkit/Source/JavaScriptCore
|
||||
/repos/libports/src/lib/qt5/qtwebkit/Source/WebCore/generated
|
||||
/repos/libports/tool/qt5/bootstrap
|
||||
/repos/libports/tool/qt5/misc/var
|
||||
/repos/libports/tool/qt5/moc
|
||||
/repos/libports/tool/qt5/qmake/*.d
|
||||
/repos/libports/tool/qt5/qmake/*.o
|
||||
/repos/libports/tool/qt5/qmake/qmake
|
||||
/repos/libports/tool/qt5/rcc
|
||||
/repos/libports/tool/qt5/uic
|
||||
/repos/ports-foc/contrib
|
||||
/repos/ports-okl4/contrib
|
||||
/repos/ports-okl4/download
|
||||
/repos/ports/contrib
|
||||
/repos/ports/download
|
||||
/repos/ports/src/app/arora/html
|
||||
/repos/ports/src/lib/gdbserver_platform/generated
|
||||
/repos/qt4/contrib
|
||||
/repos/qt4/download
|
||||
/repos/qt4/tool/bootstrap
|
||||
/repos/qt4/tool/misc/var
|
||||
/repos/qt4/tool/moc
|
||||
/repos/qt4/tool/qmake/*.d
|
||||
/repos/qt4/tool/qmake/*.o
|
||||
/repos/qt4/tool/qmake/qmake
|
||||
/repos/qt4/tool/rcc
|
||||
/repos/qt4/tool/uic
|
||||
/repos/linux_drivers
|
||||
|
||||
|
||||
138
README
138
README
@@ -36,7 +36,7 @@ usage scenario.
|
||||
Directory overview
|
||||
##################
|
||||
|
||||
The Genode source tree is composed of the following subdirectories:
|
||||
The source tree is composed of the following subdirectories:
|
||||
|
||||
:'doc':
|
||||
|
||||
@@ -50,145 +50,17 @@ The Genode source tree is composed of the following subdirectories:
|
||||
|
||||
! doc/components.txt
|
||||
|
||||
:'base':
|
||||
:'repos':
|
||||
|
||||
This directory contains the source-code repository of the fundamental
|
||||
frameworks and interfaces of Genode. Furthermore, it contains the generic
|
||||
parts of core.
|
||||
|
||||
:'os':
|
||||
|
||||
This directory contains the non-base OS components such as the init process,
|
||||
device drivers, and basic system services.
|
||||
|
||||
:'demo':
|
||||
|
||||
This directory contains the source-code repository of various services and
|
||||
applications that we use for demonstration purposes. For example, a graphical
|
||||
application launcher called Launchpad and the Scout tutorial browser.
|
||||
|
||||
:'base-<platform>':
|
||||
These directories contain platform-specific source-code repositories
|
||||
complementing the 'base' repository. The following platforms are supported:
|
||||
|
||||
:'linux':
|
||||
Linux kernel (both x86_32 and x86_64)
|
||||
|
||||
:'nova':
|
||||
NOVA hypervisor developed at University of Technology Dresden
|
||||
See [http://genode.org/documentation/platforms/nova]
|
||||
|
||||
:'foc':
|
||||
Fiasco.OC is a modernized version of the Fiasco microkernel with a
|
||||
completely revised kernel interface fostering capability-based
|
||||
security. It is not compatible with L4/Fiasco.
|
||||
See [http://genode.org/documentation/platforms/foc]
|
||||
|
||||
:'hw':
|
||||
The hw platform allows the execution of Genode on bare ARM hardware
|
||||
without the need for a separate kernel. The kernel functionality is
|
||||
included in core.
|
||||
See [http://genode.org/documentation/platforms/hw]
|
||||
|
||||
:'okl4':
|
||||
OKL4 kernel (x86_32 and ARM) developed at Open-Kernel-Labs.
|
||||
See [http://genode.org/documentation/platforms/okl4]
|
||||
|
||||
:'pistachio':
|
||||
L4ka::Pistachio kernel developed at University of Karlsruhe.
|
||||
See [http://genode.org/documentation/platforms/pistachio]
|
||||
|
||||
:'fiasco':
|
||||
L4/Fiasco kernel developed at University of Technology Dresden.
|
||||
See [http://genode.org/documentation/platforms/fiasco]
|
||||
|
||||
:'codezero':
|
||||
Codezero microkernel developed by B-Labs
|
||||
See [http://genode.org/documentation/platforms/codezero]
|
||||
|
||||
:'host':
|
||||
Pseudo platform documenting the interface between the generic and
|
||||
platform-specific parts of the base framework. This is not a functional
|
||||
base platform.
|
||||
This directory contains the so-called source-code repositories of Genode.
|
||||
Please refer to the README file in the 'repos' directory to learn more
|
||||
about the roles of the individual repositories.
|
||||
|
||||
:'tool':
|
||||
|
||||
Source-code management tools and scripts. Please refer to the README file
|
||||
contained in the directory.
|
||||
|
||||
:'hello_tutorial':
|
||||
|
||||
Tutorial for creating a simple client-server scenario with Genode. This
|
||||
repository includes documentation and the complete source code.
|
||||
|
||||
:'libports':
|
||||
|
||||
This source-code repository contains ports of popular open-source libraries
|
||||
to Genode, most importantly the C library. The repository contains no
|
||||
upstream source code but means to download the code and adapt it to Genode.
|
||||
For instructions about how to use this mechanism, please consult the README
|
||||
file at the top level of the repository. Among the 3rd-party libraries
|
||||
are Qt5, libSDL, freetype, Python, ncurses, Mesa, and libav.
|
||||
|
||||
:'dde_linux':
|
||||
|
||||
This source-code repository contains the device driver environment for
|
||||
executing Linux device drivers natively on Genode. Currently, this
|
||||
repository hosts the USB stack.
|
||||
|
||||
:'linux_drivers':
|
||||
|
||||
Deprecated version of the Linux device driver environment featuring audio
|
||||
drivers and the Intel GEM driver. This repository is in a transitionary
|
||||
phase. Its functionality will be incorporated into 'dde_linux'.
|
||||
|
||||
:'dde_ipxe':
|
||||
|
||||
This source-code repository contains the device-driver environment for
|
||||
executing drivers of the iPXE project.
|
||||
|
||||
:'dde_oss':
|
||||
|
||||
This source-code repository contains the device-driver environment for the
|
||||
audio drivers of the Open Sound System (OSS).
|
||||
|
||||
:'dde_rump':
|
||||
|
||||
This source-code repository contains the port of rump kernels, which are
|
||||
used to execute subsystems of the NetBSD kernel as user level processes.
|
||||
The repository contains a server that uses a rump kernel to provide
|
||||
various NetBSD file systems to Genode.
|
||||
|
||||
:'qt4':
|
||||
|
||||
This source-code repository contains the Genode version of Qt4 framework.
|
||||
Please find more information about using Qt4 with Genode in the repository's
|
||||
'README' file. Please note that the Qt4 support is deprecated. Use Qt5
|
||||
as contained in 'libports' instead.
|
||||
|
||||
:'ports':
|
||||
|
||||
This source-code repository hosts ports of 3rd-party applications to
|
||||
Genode. The repository does not contain upstream source code but provides
|
||||
a mechanism for downloading the official source distributions and adapt
|
||||
them to the Genode environment. The used mechanism is roughly the same
|
||||
as used for the 'libports' repository. Please consult 'libports/README'
|
||||
for further information.
|
||||
|
||||
:'ports-<platform>':
|
||||
|
||||
These platform-specific source-code repositories contain software that
|
||||
capitalizes special features of the respective kernel platform.
|
||||
For the Fiasco.OC platform, 'ports-foc' hosts a port of the L4Linux
|
||||
kernel. For further information, please refer to the README file at the
|
||||
top level of the respective repository.
|
||||
|
||||
:'gems':
|
||||
|
||||
This source-code repository contains Genode applications that use
|
||||
both native Genode interfaces as well as features of other high-level
|
||||
repositories, in particular shared libraries provided by 'libports'.
|
||||
|
||||
|
||||
Contact
|
||||
#######
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
#
|
||||
# \brief Download, and unpack Fiasco and addtional needed tools (sigma0, bootstrap)
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2011-07-18
|
||||
#
|
||||
|
||||
VERBOSE ?= @
|
||||
ECHO = @echo
|
||||
DOWNLOAD_DIR = download
|
||||
CONTRIB_DIR = contrib
|
||||
FIASCO_ARCHIVE = 3rd_fiasco.tar.bz2
|
||||
FIASCO_URI = http://downloads.sourceforge.net/project/genode/3rd/$(FIASCO_ARCHIVE)
|
||||
PATCHES = $(shell find patches -name *.patch)
|
||||
|
||||
#
|
||||
# Utility to check if a tool is installed
|
||||
#
|
||||
check_tool = $(if $(shell which $(1)),,$(error Need to have '$(1)' installed.))
|
||||
|
||||
$(call check_tool,wget)
|
||||
$(call check_tool,patch)
|
||||
$(call check_tool,tar)
|
||||
$(call check_tool,byacc)
|
||||
|
||||
#
|
||||
# Print help information by default
|
||||
#
|
||||
help:
|
||||
$(ECHO)
|
||||
$(ECHO) "Prepare the Fiasco base repository"
|
||||
$(ECHO)
|
||||
$(ECHO) "--- available commands ---"
|
||||
$(ECHO) "prepare - download and extract the Fiasco source code"
|
||||
$(ECHO) "clean - clean everything except downloaded archives"
|
||||
$(ECHO) "cleanall - clean everything including downloaded archives"
|
||||
$(ECHO)
|
||||
|
||||
$(DOWNLOAD_DIR)/$(FIASCO_ARCHIVE):
|
||||
$(ECHO) "downloading source code to '$(DOWNLOAD_DIR)/'"
|
||||
$(VERBOSE)mkdir -p $(DOWNLOAD_DIR)
|
||||
$(VERBOSE)wget -c $(FIASCO_URI) -O $@
|
||||
|
||||
$(CONTRIB_DIR): $(DOWNLOAD_DIR)/$(FIASCO_ARCHIVE)
|
||||
$(ECHO) "unpacking source code to '$(CONTRIB_DIR)/'"
|
||||
$(VERBOSE)tar xjf $<
|
||||
$(VERBOSE)mv 3rd $@
|
||||
$(ECHO) "applying patches to '$@/'"
|
||||
$(VERBOSE)for i in $(PATCHES); do patch -d $@ -p0 < $$i; done
|
||||
$(VERBOSE)touch $@
|
||||
|
||||
prepare: $(CONTRIB_DIR)
|
||||
|
||||
clean:
|
||||
$(VERBOSE)rm -rf $(CONTRIB_DIR)
|
||||
|
||||
cleanall: clean
|
||||
$(VERBOSE)rm -rf $(DOWNLOAD_DIR)
|
||||
@@ -1,15 +0,0 @@
|
||||
--- fiasco/snapshot/kernel/fiasco/src/kern/kernel_uart.cpp 2008-07-30 13:19:01.000000000 +0200
|
||||
+++ fiasco/snapshot/kernel/fiasco/src/kern/kernel_uart.cpp 2013-06-10 14:21:54.183996620 +0200
|
||||
@@ -72,6 +72,12 @@
|
||||
if ( (s = strstr(cmdline, " -comport "))
|
||||
||(s = strstr(cmdline, " -comport=")))
|
||||
p = strtoul(s + 10, 0, 0);
|
||||
+ else
|
||||
+ {
|
||||
+ unsigned short bda_comports = (*((unsigned short *)0x410) >> 9) & 0x7;
|
||||
+ if (bda_comports)
|
||||
+ p = *((unsigned short *)0x400);
|
||||
+ }
|
||||
|
||||
if ((s = strstr(cmdline, " -comirq=")))
|
||||
i = strtoul(s + 9, 0, 0);
|
||||
@@ -1,90 +0,0 @@
|
||||
#
|
||||
# \brief Checkout Fiasco.OC and addtional needed tools (sigma0, bootstrap)
|
||||
# \author Stefan Kalkowski
|
||||
# \author Sebastian Sumpf
|
||||
# \date 2011-03-31
|
||||
#
|
||||
|
||||
VERBOSE ?= @
|
||||
ECHO = @echo
|
||||
SVN_URI = http://svn.tudos.org/repos/oc/tudos/trunk
|
||||
GIT_URI = http://github.com/ssumpf/foc.git
|
||||
GIT_BRANCH = r56
|
||||
CONTRIB_DIR = contrib
|
||||
GNU_FIND ?= find
|
||||
|
||||
SVN_TARGETS = tools/preprocess \
|
||||
kernel/fiasco \
|
||||
l4/conf \
|
||||
l4/doc \
|
||||
l4/mk \
|
||||
l4/tool \
|
||||
l4/pkg/bootstrap \
|
||||
l4/pkg/cxx \
|
||||
l4/pkg/drivers-frst \
|
||||
l4/pkg/l4sys \
|
||||
l4/pkg/l4util \
|
||||
l4/pkg/ldscripts \
|
||||
l4/pkg/libgcc-pure \
|
||||
l4/pkg/libgcc \
|
||||
l4/pkg/libsigma0 \
|
||||
l4/pkg/sigma0 \
|
||||
l4/pkg/uclibc-headers \
|
||||
l4/pkg/uclibc-minimal \
|
||||
l4/pkg/uclibc \
|
||||
l4/pkg/libvcpu
|
||||
|
||||
#
|
||||
# Utility to check if a tool is installed
|
||||
#
|
||||
check_tool = $(if $(shell which $(1)),,$(error Need to have '$(1)' installed.))
|
||||
|
||||
$(call check_tool,git)
|
||||
$(call check_tool,svn)
|
||||
$(call check_tool,$(GNU_FIND))
|
||||
|
||||
#
|
||||
# Print help information by default
|
||||
#
|
||||
help::
|
||||
|
||||
$(CONTRIB_DIR)/.git:
|
||||
$(VERBOSE)git clone $(GIT_URI) $(CONTRIB_DIR)
|
||||
|
||||
prepare: $(CONTRIB_DIR)/.git
|
||||
$(VERBOSE)cd $(CONTRIB_DIR); git fetch origin
|
||||
$(VERBOSE)cd $(CONTRIB_DIR); git checkout $(GIT_BRANCH)
|
||||
$(VERBOSE)cd $(CONTRIB_DIR); git rebase origin/$(GIT_BRANCH)
|
||||
|
||||
$(SVN_REV)/%:
|
||||
$(VERBOSE)svn co -r $(SVN_REV) $(SVN_URI)/$* $@
|
||||
|
||||
checkout_base:
|
||||
ifeq ($(SVN_REV),)
|
||||
$(error Syntax 'make checkout SVN_REV=<revision>')
|
||||
endif
|
||||
$(VERBOSE)svn export -r $(SVN_REV) $(SVN_URI)/l4/COPYING-GPL-2 $(SVN_REV)
|
||||
$(VERBOSE)svn co -r $(SVN_REV) --depth immediates $(SVN_URI) $(SVN_REV)
|
||||
$(VERBOSE)svn co -r $(SVN_REV) --depth files $(SVN_URI)/l4 $(SVN_REV)/l4
|
||||
$(VERBOSE)svn co -r $(SVN_REV) --depth files $(SVN_URI)/l4/pkg $(SVN_REV)/l4/pkg
|
||||
|
||||
checkout: checkout_base $(addprefix $(SVN_REV)/,$(SVN_TARGETS))
|
||||
$(VERBOSE)$(GNU_FIND) $(SVN_REV) -depth -name .svn -type d -exec rm -r {} ";"
|
||||
|
||||
help::
|
||||
$(ECHO)
|
||||
$(ECHO) "Check out upstream source code of Fiasco.OC"
|
||||
$(ECHO)
|
||||
$(ECHO) "The source code will be located at the '$(CONTRIB_DIR)/' directory."
|
||||
$(ECHO)
|
||||
$(ECHO) "--- available commands ---"
|
||||
$(ECHO) "prepare - checkout upstream source codes"
|
||||
$(ECHO) "checkout SVN_REV=<rev> - checkout out <rev> revision of Fiasco.OC/L4RE from the official repositiry"
|
||||
$(ECHO) " and store in directory <rev>"
|
||||
$(ECHO) "clean - remove upstream source codes"
|
||||
$(ECHO)
|
||||
|
||||
clean::
|
||||
$(VERBOSE)rm -rf $(CONTRIB_DIR)
|
||||
|
||||
.NOTPARALLEL:
|
||||
@@ -1,5 +0,0 @@
|
||||
REQUIRES = platform_arndale
|
||||
FIASCO_DIR = $(REP_DIR)/contrib/kernel/fiasco
|
||||
KERNEL_CONFIG = $(REP_DIR)/config/arndale.kernel
|
||||
|
||||
-include $(PRG_DIR)/../target.inc
|
||||
@@ -1,5 +0,0 @@
|
||||
REQUIRES = platform_panda
|
||||
FIASCO_DIR = $(REP_DIR)/contrib/kernel/fiasco
|
||||
KERNEL_CONFIG = $(REP_DIR)/config/panda.kernel
|
||||
|
||||
-include $(PRG_DIR)/../target.inc
|
||||
@@ -1,620 +0,0 @@
|
||||
/*
|
||||
* \brief Interface between kernel and userland
|
||||
* \author Martin stein
|
||||
* \date 2011-11-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _KERNEL__INTERFACE_H_
|
||||
#define _KERNEL__INTERFACE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <kernel/interface_support.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
class Native_utcb;
|
||||
class Platform_pd;
|
||||
class Tlb;
|
||||
}
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
typedef Genode::Tlb Tlb;
|
||||
typedef Genode::addr_t addr_t;
|
||||
typedef Genode::size_t size_t;
|
||||
typedef Genode::Platform_pd Platform_pd;
|
||||
typedef Genode::Native_utcb Native_utcb;
|
||||
|
||||
/**
|
||||
* Kernel names of all kernel calls
|
||||
*/
|
||||
struct Call_id
|
||||
{
|
||||
enum {
|
||||
NEW_THREAD = 0,
|
||||
BIN_THREAD = 1,
|
||||
START_THREAD = 2,
|
||||
PAUSE_THREAD = 3,
|
||||
RESUME_THREAD = 4,
|
||||
YIELD_THREAD = 5,
|
||||
ACCESS_THREAD_REGS = 6,
|
||||
ROUTE_THREAD_EVENT = 7,
|
||||
UPDATE_PD = 8,
|
||||
UPDATE_REGION = 9,
|
||||
NEW_PD = 10,
|
||||
BIN_PD = 11,
|
||||
SEND_REQUEST_MSG = 12,
|
||||
SEND_REPLY_MSG = 13,
|
||||
AWAIT_REQUEST_MSG = 14,
|
||||
NEW_SIGNAL_RECEIVER = 15,
|
||||
NEW_SIGNAL_CONTEXT = 16,
|
||||
KILL_SIGNAL_CONTEXT = 17,
|
||||
BIN_SIGNAL_CONTEXT = 18,
|
||||
BIN_SIGNAL_RECEIVER = 19,
|
||||
SUBMIT_SIGNAL = 20,
|
||||
AWAIT_SIGNAL = 21,
|
||||
SIGNAL_PENDING = 22,
|
||||
ACK_SIGNAL = 23,
|
||||
NEW_VM = 24,
|
||||
RUN_VM = 25,
|
||||
PAUSE_VM = 26,
|
||||
PRINT_CHAR = 27,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
** Kernel call with 1 to 6 arguments **
|
||||
** **
|
||||
** These functions must not be inline to ensure that objects, **
|
||||
** wich are referenced by arguments, are tagged as "used" even **
|
||||
** though only the pointer gets handled in here. **
|
||||
*****************************************************************/
|
||||
|
||||
Call_ret call(Call_arg arg_0);
|
||||
|
||||
Call_ret call(Call_arg arg_0,
|
||||
Call_arg arg_1);
|
||||
|
||||
Call_ret call(Call_arg arg_0,
|
||||
Call_arg arg_1,
|
||||
Call_arg arg_2);
|
||||
|
||||
Call_ret call(Call_arg arg_0,
|
||||
Call_arg arg_1,
|
||||
Call_arg arg_2,
|
||||
Call_arg arg_3);
|
||||
|
||||
Call_ret call(Call_arg arg_0,
|
||||
Call_arg arg_1,
|
||||
Call_arg arg_2,
|
||||
Call_arg arg_3,
|
||||
Call_arg arg_4);
|
||||
|
||||
Call_ret call(Call_arg arg_0,
|
||||
Call_arg arg_1,
|
||||
Call_arg arg_2,
|
||||
Call_arg arg_3,
|
||||
Call_arg arg_4,
|
||||
Call_arg arg_5);
|
||||
|
||||
/**
|
||||
* Virtual range of the mode transition region in every PD
|
||||
*/
|
||||
addr_t mode_transition_virt_base();
|
||||
size_t mode_transition_size();
|
||||
|
||||
/**
|
||||
* Get sizes of the kernel objects
|
||||
*/
|
||||
size_t thread_size();
|
||||
size_t pd_size();
|
||||
size_t signal_context_size();
|
||||
size_t signal_receiver_size();
|
||||
size_t vm_size();
|
||||
|
||||
/**
|
||||
* Get alignment constraints of the kernel objects
|
||||
*/
|
||||
unsigned kernel_pd_alignm_log2();
|
||||
|
||||
|
||||
/**
|
||||
* Create a protection domain
|
||||
*
|
||||
* \param p appropriate memory donation for the kernel object
|
||||
* \param pd core local Platform_pd object
|
||||
*
|
||||
* \retval >0 kernel name of the new protection domain
|
||||
* \retval 0 failed
|
||||
*
|
||||
* Restricted to core threads. Regaining of the supplied memory is not
|
||||
* supported by now.
|
||||
*/
|
||||
inline unsigned new_pd(void * const dst, Platform_pd * const pd)
|
||||
{
|
||||
return call(Call_id::NEW_PD, (Call_arg)dst, (Call_arg)pd);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destruct a protection domain
|
||||
*
|
||||
* \param pd_id kernel name of the targeted protection domain
|
||||
*
|
||||
* \retval 0 succeeded
|
||||
* \retval -1 failed
|
||||
*/
|
||||
inline int bin_pd(unsigned const pd_id)
|
||||
{
|
||||
return call(Call_id::BIN_PD, pd_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Propagate changes in PD configuration
|
||||
*
|
||||
* \param pd_id ID of the PD that has been configured
|
||||
*
|
||||
* It might be, that the kernel and/or the hardware caches parts of PD
|
||||
* configurations such as virtual address translations. This function
|
||||
* ensures that the current configuration of the targeted PD gets fully
|
||||
* applied from the moment it returns to the userland. This function is
|
||||
* inappropriate in case that a PD wants to change its own configuration.
|
||||
* There's no need for this function after a configuration change that
|
||||
* can't affect the kernel- and/or hardware-caches.
|
||||
*
|
||||
* Restricted to core threads.
|
||||
*/
|
||||
inline void update_pd(unsigned const pd_id)
|
||||
{
|
||||
call(Call_id::UPDATE_PD, pd_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Propagate memory-updates within a given virtual region
|
||||
*
|
||||
* \param base virtual base of the region
|
||||
* \param size size of the region
|
||||
*
|
||||
* If one updates a memory region and must ensure that the update
|
||||
* gets visible directly to other address spaces, this function does
|
||||
* the job.
|
||||
*
|
||||
* Restricted to core threads.
|
||||
*/
|
||||
inline void update_region(addr_t const base, size_t const size)
|
||||
{
|
||||
call(Call_id::UPDATE_REGION, (Call_arg)base, (Call_arg)size);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create kernel object that acts as thread that isn't executed initially
|
||||
*
|
||||
* \param p memory donation for the new kernel thread object
|
||||
* \param priority scheduling priority of the new thread
|
||||
* \param label debugging label of the new thread
|
||||
*
|
||||
* \retval >0 kernel name of the new thread
|
||||
* \retval 0 failed
|
||||
*
|
||||
* Restricted to core threads.
|
||||
*/
|
||||
inline int new_thread(void * const p, unsigned const priority,
|
||||
char const * const label)
|
||||
{
|
||||
return call((Call_arg)Call_id::NEW_THREAD, (Call_arg)p, (Call_arg)priority,
|
||||
(Call_arg)label);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destruct kernel thread-object
|
||||
*
|
||||
* \param thread_id kernel name of the targeted thread
|
||||
*
|
||||
* Restricted to core threads.
|
||||
*/
|
||||
inline void bin_thread(unsigned const thread_id)
|
||||
{
|
||||
call(Call_id::BIN_THREAD, thread_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start executing a thread
|
||||
*
|
||||
* \param thread_id kernel name of targeted thread
|
||||
* \param cpu_id kernel name of targeted processor
|
||||
* \param pd_id kernel name of targeted protection domain
|
||||
* \param utcb core local pointer to userland thread-context
|
||||
*
|
||||
* Restricted to core threads.
|
||||
*/
|
||||
inline Tlb * start_thread(unsigned const thread_id, unsigned const cpu_id,
|
||||
unsigned const pd_id, Native_utcb * const utcb)
|
||||
{
|
||||
return (Tlb *)call(Call_id::START_THREAD, thread_id, cpu_id, pd_id,
|
||||
(Call_arg)utcb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prevent thread from participating in CPU scheduling
|
||||
*
|
||||
* \param thread_id kernel name of the targeted thread or 0
|
||||
*
|
||||
* \retval 0 succeeded
|
||||
* \retval -1 the targeted thread does not exist or is still active
|
||||
*
|
||||
* If thread_id is set to 0 the caller targets itself. If the caller
|
||||
* doesn't target itself, the call is restricted to core threads.
|
||||
*/
|
||||
inline int pause_thread(unsigned const thread_id)
|
||||
{
|
||||
return call(Call_id::PAUSE_THREAD, thread_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Let an already started thread participate in CPU scheduling
|
||||
*
|
||||
* \param thread_id kernel name of the targeted thread
|
||||
*
|
||||
* \retval 0 succeeded and thread was paused beforehand
|
||||
* \retval 1 succeeded and thread was active beforehand
|
||||
* \retval -1 failed
|
||||
*
|
||||
* If the targeted thread blocks for any event except a 'start_thread'
|
||||
* call this call cancels the blocking.
|
||||
*/
|
||||
inline int resume_thread(unsigned const thread_id)
|
||||
{
|
||||
return call(Call_id::RESUME_THREAD, thread_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Let the current thread give up its remaining timeslice
|
||||
*
|
||||
* \param thread_id kernel name of the benefited thread
|
||||
*
|
||||
* If thread_id is valid the call will resume the targeted thread
|
||||
* additionally.
|
||||
*/
|
||||
inline void yield_thread(unsigned const thread_id)
|
||||
{
|
||||
call(Call_id::YIELD_THREAD, thread_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set or unset the handler of an event a kernel thread-object triggers
|
||||
*
|
||||
* \param thread_id kernel name of the targeted thread
|
||||
* \param event_id kernel name of the targeted thread event
|
||||
* \param signal_context_id kernel name of the handlers signal context
|
||||
*
|
||||
* Restricted to core threads.
|
||||
*/
|
||||
inline int route_thread_event(unsigned const thread_id,
|
||||
unsigned const event_id,
|
||||
unsigned const signal_context_id)
|
||||
{
|
||||
return call(Call_id::ROUTE_THREAD_EVENT, thread_id,
|
||||
event_id, signal_context_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send request message and await receipt of corresponding reply message
|
||||
*
|
||||
* \param thread_id kernel name of targeted thread
|
||||
*
|
||||
* \retval 0 succeeded
|
||||
* \retval -1 failed
|
||||
*
|
||||
* If the call returns successful, the received message is located at the
|
||||
* base of the callers userland thread-context.
|
||||
*/
|
||||
inline int send_request_msg(unsigned const thread_id)
|
||||
{
|
||||
return call(Call_id::SEND_REQUEST_MSG, thread_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Await receipt of request message
|
||||
*
|
||||
* \retval 0 succeeded
|
||||
* \retval -1 failed
|
||||
*
|
||||
* If the call returns successful, the received message is located at the
|
||||
* base of the callers userland thread-context.
|
||||
*/
|
||||
inline int await_request_msg()
|
||||
{
|
||||
return call(Call_id::AWAIT_REQUEST_MSG);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reply to lastly received request message
|
||||
*
|
||||
* \param await_request_msg wether the call shall await a request message
|
||||
*
|
||||
* \retval 0 await_request_msg == 0 or request-message receipt succeeded
|
||||
* \retval -1 await_request_msg == 1 and request-message receipt failed
|
||||
*
|
||||
* If the call returns successful and await_request_msg == 1, the received
|
||||
* message is located at the base of the callers userland thread-context.
|
||||
*/
|
||||
inline int send_reply_msg(bool const await_request_msg)
|
||||
{
|
||||
return call(Call_id::SEND_REPLY_MSG, await_request_msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Print a char c to the kernels serial ouput
|
||||
*
|
||||
* If c is set to 0 the kernel prints a table of all threads and their
|
||||
* current activities to the serial output.
|
||||
*/
|
||||
inline void print_char(char const c)
|
||||
{
|
||||
call(Call_id::PRINT_CHAR, c);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Access plain member variables of a kernel thread-object
|
||||
*
|
||||
* \param thread_id kernel name of the targeted thread
|
||||
* \param reads amount of read operations
|
||||
* \param writes amount of write operations
|
||||
* \param read_values base of value buffer for read operations
|
||||
* \param write_values base of value buffer for write operations
|
||||
*
|
||||
* \retval 0 all operations done
|
||||
* \retval >0 amount of undone operations
|
||||
* \retval -1 failed to start processing operations
|
||||
*
|
||||
* Restricted to core threads. Operations are processed in order of the
|
||||
* appearance of the register names in the callers UTCB. If reads = 0,
|
||||
* read_values is of no relevance. If writes = 0, write_values is of no
|
||||
* relevance.
|
||||
*
|
||||
* Expected structure at the callers UTCB base:
|
||||
*
|
||||
* 0 * sizeof(addr_t): read register name #1
|
||||
* ... ...
|
||||
* (reads - 1) * sizeof(addr_t): read register name #reads
|
||||
* (reads - 0) * sizeof(addr_t): write register name #1
|
||||
* ... ...
|
||||
* (reads + writes - 1) * sizeof(addr_t): write register name #writes
|
||||
*
|
||||
* Expected structure at write_values:
|
||||
*
|
||||
* 0 * sizeof(addr_t): write value #1
|
||||
* ... ...
|
||||
* (writes - 1) * sizeof(addr_t): write value #writes
|
||||
*/
|
||||
inline int access_thread_regs(unsigned const thread_id,
|
||||
unsigned const reads,
|
||||
unsigned const writes,
|
||||
addr_t * const read_values,
|
||||
addr_t * const write_values)
|
||||
{
|
||||
return call(Call_id::ACCESS_THREAD_REGS, thread_id, reads, writes,
|
||||
(Call_arg)read_values, (Call_arg)write_values);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a kernel object that acts as a signal receiver
|
||||
*
|
||||
* \param p memory donation for the kernel signal-receiver object
|
||||
*
|
||||
* \retval >0 kernel name of the new signal receiver
|
||||
* \retval 0 failed
|
||||
*
|
||||
* Restricted to core threads.
|
||||
*/
|
||||
inline unsigned new_signal_receiver(addr_t const p)
|
||||
{
|
||||
return call(Call_id::NEW_SIGNAL_RECEIVER, p);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create kernel object that acts as a signal context and assign it
|
||||
*
|
||||
* \param p memory donation for the kernel signal-context object
|
||||
* \param receiver kernel name of targeted signal receiver
|
||||
* \param imprint user label of the signal context
|
||||
*
|
||||
* \retval >0 kernel name of the new signal context
|
||||
* \retval 0 failed
|
||||
*
|
||||
* Restricted to core threads.
|
||||
*/
|
||||
inline unsigned new_signal_context(addr_t const p,
|
||||
unsigned const receiver,
|
||||
unsigned const imprint)
|
||||
{
|
||||
return call(Call_id::NEW_SIGNAL_CONTEXT, p, receiver, imprint);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Await any context of a receiver and optionally ack a context before
|
||||
*
|
||||
* \param receiver_id kernel name of the targeted signal receiver
|
||||
* \param context_id kernel name of a context that shall be acknowledged
|
||||
*
|
||||
* \retval 0 suceeded
|
||||
* \retval -1 failed
|
||||
*
|
||||
* If context is set to 0, the call doesn't acknowledge any context.
|
||||
* If this call returns 0, an instance of 'Signal::Data' is located at the
|
||||
* base of the callers UTCB. Every occurence of a signal is provided
|
||||
* through this function until it gets delivered through this function or
|
||||
* context respectively receiver get destructed. If multiple threads
|
||||
* listen at the same receiver, and/or multiple contexts of the receiver
|
||||
* trigger simultanously, there is no assertion about wich thread
|
||||
* receives, and from wich context. A context that delivered once doesn't
|
||||
* deliver again unless its last delivery has been acknowledged via
|
||||
* ack_signal.
|
||||
*/
|
||||
inline int await_signal(unsigned const receiver_id,
|
||||
unsigned const context_id)
|
||||
{
|
||||
return call(Call_id::AWAIT_SIGNAL, receiver_id, context_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return wether any context of a receiver is pending
|
||||
*
|
||||
* \param receiver kernel name of the targeted signal receiver
|
||||
*
|
||||
* \retval 0 none of the contexts is pending or the receiver doesn't exist
|
||||
* \retval 1 a context of the signal receiver is pending
|
||||
*/
|
||||
inline bool signal_pending(unsigned const receiver)
|
||||
{
|
||||
return call(Call_id::SIGNAL_PENDING, receiver);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Trigger a specific signal context
|
||||
*
|
||||
* \param context kernel name of the targeted signal context
|
||||
* \param num how often the context shall be triggered by this call
|
||||
*
|
||||
* \retval 0 suceeded
|
||||
* \retval -1 failed
|
||||
*/
|
||||
inline int submit_signal(unsigned const context, unsigned const num)
|
||||
{
|
||||
return call(Call_id::SUBMIT_SIGNAL, context, num);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Acknowledge the processing of the last delivery of a signal context
|
||||
*
|
||||
* \param context kernel name of the targeted signal context
|
||||
*/
|
||||
inline void ack_signal(unsigned const context)
|
||||
{
|
||||
call(Call_id::ACK_SIGNAL, context);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Halt processing of a signal context synchronously
|
||||
*
|
||||
* \param context kernel name of the targeted signal context
|
||||
*
|
||||
* \retval 0 suceeded
|
||||
* \retval -1 failed
|
||||
*/
|
||||
inline int kill_signal_context(unsigned const context)
|
||||
{
|
||||
return call(Call_id::KILL_SIGNAL_CONTEXT, context);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destruct a signal context
|
||||
*
|
||||
* \param context kernel name of the targeted signal context
|
||||
*
|
||||
* \retval 0 suceeded
|
||||
* \retval -1 failed
|
||||
*
|
||||
* Restricted to core threads.
|
||||
*/
|
||||
inline int bin_signal_context(unsigned const context)
|
||||
{
|
||||
return call(Call_id::BIN_SIGNAL_CONTEXT, context);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destruct a signal receiver
|
||||
*
|
||||
* \param receiver kernel name of the targeted signal receiver
|
||||
*
|
||||
* \retval 0 suceeded
|
||||
* \retval -1 failed
|
||||
*
|
||||
* Restricted to core threads.
|
||||
*/
|
||||
inline int bin_signal_receiver(unsigned const receiver)
|
||||
{
|
||||
return call(Call_id::BIN_SIGNAL_RECEIVER, receiver);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a virtual machine that is stopped initially
|
||||
*
|
||||
* \param dst memory donation for the kernel VM-object
|
||||
* \param state location of the CPU state of the VM
|
||||
* \param signal_context_id kernel name of the signal context for VM events
|
||||
*
|
||||
* \retval >0 kernel name of the new VM
|
||||
* \retval 0 failed
|
||||
*
|
||||
* Restricted to core threads. Regaining of the supplied memory is not
|
||||
* supported by now.
|
||||
*/
|
||||
inline int new_vm(void * const dst, void * const state,
|
||||
unsigned const signal_context_id)
|
||||
{
|
||||
return call(Call_id::NEW_VM, (Call_arg)dst, (Call_arg)state,
|
||||
signal_context_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute a virtual-machine (again)
|
||||
*
|
||||
* \param vm_id kernel name of the targeted VM
|
||||
*
|
||||
* Restricted to core threads.
|
||||
*/
|
||||
inline void run_vm(unsigned const vm_id)
|
||||
{
|
||||
call(Call_id::RUN_VM, vm_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stop execution of a virtual-machine
|
||||
*
|
||||
* \param vm_id kernel name of the targeted VM
|
||||
*
|
||||
* Restricted to core threads.
|
||||
*/
|
||||
inline void pause_vm(unsigned const vm_id)
|
||||
{
|
||||
call(Call_id::PAUSE_VM, vm_id);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _KERNEL__INTERFACE_H_ */
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* \brief Startup code for core on ARM
|
||||
* \author Martin Stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-10-01
|
||||
*
|
||||
* The code in this file is compliant to the general ARM instruction- and
|
||||
* register-set but the semantics are tested only on ARMv6 and ARMv7 by now.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Do no operation for 'count' cycles
|
||||
*/
|
||||
.macro _nop count
|
||||
.rept \count
|
||||
mov r8, r8
|
||||
.endr
|
||||
.endm
|
||||
|
||||
.section ".text.crt0"
|
||||
|
||||
/* ELF entry symbol */
|
||||
.global _start
|
||||
_start:
|
||||
|
||||
/* idle a little initially because 'u-boot' likes it this way */
|
||||
_nop 8
|
||||
|
||||
/* zero-fill BSS segment, BSS boundaries must be aligned to 4 */
|
||||
.extern _bss_start
|
||||
.extern _bss_end
|
||||
ldr r0, =_bss_start
|
||||
ldr r1, =_bss_end
|
||||
mov r2, #0
|
||||
1:
|
||||
cmp r1, r0
|
||||
ble 2f
|
||||
str r2, [r0]
|
||||
add r0, r0, #4
|
||||
b 1b
|
||||
2:
|
||||
|
||||
/* enable C++ to prepare the first kernel run */
|
||||
ldr sp, =_kernel_stack_high
|
||||
bl init_phys_kernel
|
||||
|
||||
/* call kernel routine */
|
||||
.extern kernel
|
||||
_start_kernel:
|
||||
ldr sp, =_kernel_stack_high
|
||||
bl kernel
|
||||
|
||||
/* catch erroneous kernel return */
|
||||
3: b 3b
|
||||
|
||||
.section .bss
|
||||
|
||||
/* kernel stack */
|
||||
.align 3
|
||||
.space 64*1024
|
||||
.global _kernel_stack_high
|
||||
_kernel_stack_high:
|
||||
|
||||
/* main-thread UTCB-pointer for the Genode thread-API */
|
||||
.align 3
|
||||
.global _main_thread_utcb
|
||||
_main_thread_utcb: .long 0
|
||||
|
||||
@@ -1,234 +0,0 @@
|
||||
/*
|
||||
* \brief Transition between kernel and userland
|
||||
* \author Martin stein
|
||||
* \date 2011-11-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Invalidate all entries of the branch prediction cache
|
||||
*
|
||||
* FIXME branch prediction shall not be activated for now because we have no
|
||||
* support for instruction barriers. The manual says that one should
|
||||
* implement this via 'swi 0xf00000', but when we do this in SVC mode it
|
||||
* pollutes our SP and this is not acceptable with the current mode
|
||||
* transition implementation
|
||||
*/
|
||||
.macro _flush_branch_predictor
|
||||
mcr p15, 0, sp, c7, c5, 6
|
||||
/* swi 0xf00000 */
|
||||
.endm
|
||||
|
||||
/**
|
||||
* Switch from an interrupted user context to a kernel context
|
||||
*
|
||||
* \param exception_type immediate exception type ID
|
||||
* \param pc_adjust immediate value that gets subtracted from the
|
||||
* user PC before it gets saved
|
||||
*/
|
||||
.macro _user_to_kernel_pic exception_type, pc_adjust
|
||||
|
||||
/*
|
||||
* We expect that privileged modes are never interrupted by an
|
||||
* exception. Thus we can assume that we always come from
|
||||
* user mode at this point.
|
||||
*/
|
||||
|
||||
/************************************************
|
||||
** We're still in the user protection domain, **
|
||||
** so we must avoid access to kernel memory **
|
||||
************************************************/
|
||||
|
||||
/* load kernel cidr */
|
||||
adr sp, _mt_master_context_begin
|
||||
ldr sp, [sp, #18*4]
|
||||
mcr p15, 0, sp, c13, c0, 1
|
||||
_flush_branch_predictor
|
||||
|
||||
/* load kernel section table */
|
||||
adr sp, _mt_master_context_begin
|
||||
ldr sp, [sp, #19*4]
|
||||
mcr p15, 0, sp, c2, c0, 0
|
||||
_flush_branch_predictor
|
||||
|
||||
/*******************************************
|
||||
** Now it's save to access kernel memory **
|
||||
*******************************************/
|
||||
|
||||
/* get user context pointer */
|
||||
ldr sp, _mt_client_context_ptr
|
||||
|
||||
/*
|
||||
* Save user r0 ... r12. We explicitely target user registers
|
||||
* via '^' because we might be in FIQ exception-mode where
|
||||
* some of them are banked. Doesn't affect other modes.
|
||||
*/
|
||||
stmia sp, {r0-r12}^
|
||||
|
||||
/* save user lr and sp */
|
||||
add r0, sp, #13*4
|
||||
stmia r0, {sp,lr}^
|
||||
|
||||
/* adjust and save user pc */
|
||||
.if \pc_adjust != 0
|
||||
sub lr, lr, #\pc_adjust
|
||||
.endif
|
||||
str lr, [sp, #15*4]
|
||||
|
||||
/* save user psr */
|
||||
mrs r0, spsr
|
||||
str r0, [sp, #16*4]
|
||||
|
||||
/* save type of exception that interrupted the user */
|
||||
mov r0, #\exception_type
|
||||
str r0, [sp, #17*4]
|
||||
|
||||
/*
|
||||
* Switch to supervisor mode
|
||||
*
|
||||
* FIXME This is done due to incorrect behavior when running the kernel
|
||||
* high-level-code in FIQ-exception mode. Please debug this behavior
|
||||
* and remove this switch.
|
||||
*/
|
||||
cps #19
|
||||
|
||||
/* get kernel context pointer */
|
||||
adr r0, _mt_master_context_begin
|
||||
|
||||
/* load kernel context */
|
||||
add r0, r0, #13*4
|
||||
ldmia r0, {sp, lr, pc}
|
||||
|
||||
.endm
|
||||
|
||||
|
||||
.section .text
|
||||
|
||||
/*
|
||||
* The mode transition PIC switches between a kernel context and a user
|
||||
* context and thereby between their address spaces. Due to the latter
|
||||
* it must be mapped executable to the same region in every address space.
|
||||
* To enable such switching, the kernel context must be stored within this
|
||||
* region, thus one should map it solely accessable for privileged modes.
|
||||
*/
|
||||
.p2align 12
|
||||
.global _mt_begin
|
||||
_mt_begin:
|
||||
|
||||
/*
|
||||
* On user exceptions the CPU has to jump to one of the following
|
||||
* 7 entry vectors to switch to a kernel context.
|
||||
*/
|
||||
.global _mt_kernel_entry_pic
|
||||
_mt_kernel_entry_pic:
|
||||
|
||||
b _rst_entry /* 0x00: reset */
|
||||
b _und_entry /* 0x04: undefined instruction */
|
||||
b _swi_entry /* 0x08: software interrupt */
|
||||
b _pab_entry /* 0x0c: prefetch abort */
|
||||
b _dab_entry /* 0x10: data abort */
|
||||
nop /* 0x14: reserved */
|
||||
b _irq_entry /* 0x18: interrupt request */
|
||||
b _fiq_entry /* 0x1c: fast interrupt request */
|
||||
|
||||
/* PICs that switch from an user exception to the kernel */
|
||||
_rst_entry: _user_to_kernel_pic 1, 0
|
||||
_und_entry: _user_to_kernel_pic 2, 4
|
||||
_swi_entry:
|
||||
|
||||
/*
|
||||
* FIXME fast SWI routines pollute the SVC SP but we have
|
||||
* to call them especially in SVC mode
|
||||
*/
|
||||
|
||||
/* check if SWI requests a fast service routine */
|
||||
/* ldr sp, [r14, #-0x4]
|
||||
and sp, sp, #0xffffff
|
||||
*/
|
||||
/* fast "instruction barrier" service routine */
|
||||
/* cmp sp, #0xf00000
|
||||
bne _mt_slow_swi
|
||||
movs pc, r14
|
||||
*/
|
||||
/* slow high level service routine */
|
||||
_mt_slow_swi:
|
||||
_user_to_kernel_pic 3, 0
|
||||
|
||||
_pab_entry: _user_to_kernel_pic 4, 4
|
||||
_dab_entry: _user_to_kernel_pic 5, 8
|
||||
_irq_entry: _user_to_kernel_pic 6, 4
|
||||
_fiq_entry: _user_to_kernel_pic 7, 4
|
||||
|
||||
/* kernel must jump to this point to switch to a user context */
|
||||
.p2align 2
|
||||
.global _mt_user_entry_pic
|
||||
_mt_user_entry_pic:
|
||||
|
||||
/* get user context pointer */
|
||||
ldr lr, _mt_client_context_ptr
|
||||
|
||||
/* buffer user pc */
|
||||
ldr r0, [lr, #15*4]
|
||||
adr r1, _mt_buffer
|
||||
str r0, [r1]
|
||||
|
||||
/* buffer user psr */
|
||||
ldr r0, [lr, #16*4]
|
||||
msr spsr, r0
|
||||
|
||||
/* load user r0 ... r12 */
|
||||
ldmia lr, {r0-r12}
|
||||
|
||||
/* load user sp and lr */
|
||||
add sp, lr, #13*4
|
||||
ldmia sp, {sp,lr}^
|
||||
|
||||
/* get user cidr and section table */
|
||||
ldr sp, [lr, #18*4]
|
||||
ldr lr, [lr, #19*4]
|
||||
|
||||
/********************************************************
|
||||
** From now on, until we leave kernel mode, we must **
|
||||
** avoid access to memory that is not mapped globally **
|
||||
********************************************************/
|
||||
|
||||
/* apply user contextidr and section table */
|
||||
mcr p15, 0, sp, c13, c0, 1
|
||||
mcr p15, 0, lr, c2, c0, 0
|
||||
_flush_branch_predictor
|
||||
|
||||
/* load user pc (implies application of the user psr) */
|
||||
adr lr, _mt_buffer
|
||||
ldmia lr, {pc}^
|
||||
|
||||
/* leave some space for the kernel context */
|
||||
.p2align 2
|
||||
.global _mt_master_context_begin
|
||||
_mt_master_context_begin: .space 32*4
|
||||
.global _mt_master_context_end
|
||||
_mt_master_context_end:
|
||||
|
||||
/* pointer to the context backup space */
|
||||
.p2align 2
|
||||
.global _mt_client_context_ptr
|
||||
_mt_client_context_ptr: .long 0
|
||||
|
||||
/* a local word-sized buffer */
|
||||
.p2align 2
|
||||
.global _mt_buffer
|
||||
_mt_buffer: .long 0
|
||||
|
||||
.p2align 2
|
||||
.global _mt_end
|
||||
_mt_end:
|
||||
|
||||
/* FIXME this exists only because _vm_mon_entry pollutes kernel.cc */
|
||||
.global _mt_vm_entry_pic
|
||||
_mt_vm_entry_pic:
|
||||
1: b 1b
|
||||
@@ -1,338 +0,0 @@
|
||||
/*
|
||||
* \brief Transition between kernel/userland, and secure/non-secure world
|
||||
* \author Martin stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-11-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Switch from an interrupted user context to a kernel context
|
||||
*
|
||||
* \param exception_type immediate exception type ID
|
||||
* \param pc_adjust immediate value that gets subtracted from the
|
||||
* user PC before it gets saved
|
||||
*/
|
||||
.macro _user_to_kernel_pic exception_type, pc_adjust
|
||||
|
||||
/*
|
||||
* We expect that privileged modes are never interrupted by an
|
||||
* exception. Thus we can assume that we always come from
|
||||
* user mode at this point.
|
||||
*/
|
||||
|
||||
/* when not in FIQ mode disable FIQs */
|
||||
.if \exception_type != 6
|
||||
cpsid f
|
||||
.endif
|
||||
|
||||
/************************************************
|
||||
** We're still in the user protection domain, **
|
||||
** so we must avoid access to kernel memory **
|
||||
************************************************/
|
||||
|
||||
/* load kernel cidr */
|
||||
adr sp, _mt_master_context_begin
|
||||
ldr sp, [sp, #18*4]
|
||||
mcr p15, 0, sp, c13, c0, 1
|
||||
isb
|
||||
|
||||
/* load kernel section table */
|
||||
adr sp, _mt_master_context_begin
|
||||
ldr sp, [sp, #19*4]
|
||||
orr sp, sp, #0b1000000 /* set TTBR0 flags */
|
||||
mcr p15, 0, sp, c2, c0, 0
|
||||
isb
|
||||
dsb
|
||||
|
||||
/*******************************************
|
||||
** Now it's save to access kernel memory **
|
||||
*******************************************/
|
||||
|
||||
/* get user context pointer */
|
||||
ldr sp, _mt_client_context_ptr
|
||||
|
||||
/*
|
||||
* Save user r0 ... r12. We explicitely target user registers
|
||||
* via '^' because we might be in FIQ exception-mode where
|
||||
* some of them are banked. Doesn't affect other modes.
|
||||
*/
|
||||
stmia sp, {r0-r12}^
|
||||
|
||||
/* save user lr and sp */
|
||||
add r0, sp, #13*4
|
||||
stmia r0, {sp,lr}^
|
||||
|
||||
/* adjust and save user pc */
|
||||
.if \pc_adjust != 0
|
||||
sub lr, lr, #\pc_adjust
|
||||
.endif
|
||||
str lr, [sp, #15*4]
|
||||
|
||||
/* save user psr */
|
||||
mrs r0, spsr
|
||||
str r0, [sp, #16*4]
|
||||
|
||||
/* save type of exception that interrupted the user */
|
||||
mov r0, #\exception_type
|
||||
str r0, [sp, #17*4]
|
||||
|
||||
/*
|
||||
* Switch to supervisor mode
|
||||
* FIXME This is done due to incorrect behavior when running the kernel
|
||||
* high-level-code in FIQ-exception mode. Please debug this behavior
|
||||
* and remove this switch.
|
||||
*/
|
||||
cps #19
|
||||
|
||||
/* get kernel context pointer */
|
||||
adr r0, _mt_master_context_begin
|
||||
|
||||
/* load kernel context */
|
||||
add r0, r0, #13*4
|
||||
ldmia r0, {sp, lr, pc}
|
||||
|
||||
.endm /* _user_to_kernel_pic */
|
||||
|
||||
|
||||
/**
|
||||
* Switch from kernel context to a user context
|
||||
*/
|
||||
.macro _kernel_to_user_pic
|
||||
|
||||
/* get user context pointer */
|
||||
ldr lr, _mt_client_context_ptr
|
||||
|
||||
/* buffer user pc */
|
||||
ldr r0, [lr, #15*4]
|
||||
adr r1, _mt_buffer
|
||||
str r0, [r1]
|
||||
|
||||
/* buffer user psr */
|
||||
ldr r0, [lr, #16*4]
|
||||
msr spsr, r0
|
||||
|
||||
/* load user r0 ... r12 */
|
||||
ldmia lr, {r0-r12}
|
||||
|
||||
/* load user sp and lr */
|
||||
add sp, lr, #13*4
|
||||
ldmia sp, {sp,lr}^
|
||||
|
||||
/* get user contextidr and section table */
|
||||
ldr sp, [lr, #18*4]
|
||||
ldr lr, [lr, #19*4]
|
||||
orr lr, lr, #0b1000000 /* set TTBR0 flags */
|
||||
|
||||
/********************************************************
|
||||
** From now on, until we leave kernel mode, we must **
|
||||
** avoid access to memory that is not mapped globally **
|
||||
********************************************************/
|
||||
|
||||
/* apply user contextidr and section table */
|
||||
mcr p15, 0, sp, c13, c0, 1
|
||||
mcr p15, 0, lr, c2, c0, 0
|
||||
isb
|
||||
dsb
|
||||
|
||||
/* load user pc (implies application of the user psr) */
|
||||
adr lr, _mt_buffer
|
||||
ldmia lr, {pc}^
|
||||
|
||||
.endm /* _kernel_to_user_pic */
|
||||
|
||||
|
||||
.macro _fiq_check_prior_mode
|
||||
mrs r8, spsr /* load fiq-spsr */
|
||||
and r8, #31
|
||||
cmp r8, #16 /* check whether we come from user-mode */
|
||||
beq 1f
|
||||
mrs r8, spsr /* enable fiq-ignore bit */
|
||||
orr r8, #64
|
||||
msr spsr, r8
|
||||
subs pc, lr, #4 /* resume previous exception */
|
||||
1:
|
||||
.endm /* _fiq_check_prior_mode */
|
||||
|
||||
/**
|
||||
* Save sp, lr and spsr register banks of specified exception mode
|
||||
*/
|
||||
.macro _save_bank mode
|
||||
cps #\mode /* switch to given mode */
|
||||
mrs r1, spsr /* store mode-specific spsr */
|
||||
stmia r0!, {r1,sp,lr} /* store mode-specific sp and lr */
|
||||
.endm /* _save_bank mode */
|
||||
|
||||
|
||||
/**
|
||||
* Switch from an interrupted VM to the kernel context
|
||||
*
|
||||
* \param exception_type immediate exception type ID
|
||||
* \param pc_adjust immediate value that gets subtracted from the
|
||||
* vm's PC before it gets saved
|
||||
*/
|
||||
.macro _vm_to_kernel exception_type, pc_adjust
|
||||
ldr sp, _mt_client_context_ptr /* load context pointer */
|
||||
stmia sp, {r0-lr}^ /* save user regs r0-r12,sp,lr */
|
||||
add r0, sp, #15*4
|
||||
.if \pc_adjust != 0 /* adjust pc if necessary */
|
||||
sub lr, lr, #\pc_adjust
|
||||
.endif
|
||||
stmia r0!, {lr} /* save pc */
|
||||
mrs r1, spsr /* spsr to r0 */
|
||||
mov r2, #\exception_type /* exception reason to r1 */
|
||||
stmia r0!, {r1-r2} /* save spsr, and exception reason */
|
||||
mrc p15, 0, r3, c6, c0, 0 /* move DFAR to r3 */
|
||||
mrc p15, 0, r4, c2, c0, 0 /* move TTBR0 to r4 */
|
||||
mrc p15, 0, r5, c2, c0, 1 /* move TTBR1 to r5 */
|
||||
mrc p15, 0, r6, c2, c0, 2 /* move TTBRC to r6 */
|
||||
mov r1, #0
|
||||
mcr p15, 0, r1, c1, c1, 0 /* disable non-secure bit */
|
||||
_save_bank 27 /* save undefined banks */
|
||||
_save_bank 19 /* save supervisor banks */
|
||||
_save_bank 23 /* save abort banks */
|
||||
_save_bank 18 /* save irq banks */
|
||||
_save_bank 17 /* save fiq banks */
|
||||
stmia r0!, {r8-r12} /* save fiq r8-r12 */
|
||||
stmia r0!, {r3-r6} /* save MMU registers */
|
||||
cps #19 /* switch to supervisor mode */
|
||||
adr r0, _mt_master_context_begin /* get kernel context pointer */
|
||||
add r0, r0, #13*4 /* load kernel context */
|
||||
ldmia r0, {sp,lr,pc}
|
||||
.endm /* _vm_to_kernel */
|
||||
|
||||
|
||||
/**
|
||||
* Restore sp, lr and spsr register banks of specified exception mode
|
||||
*/
|
||||
.macro _restore_bank mode
|
||||
cps #\mode /* switch to given mode */
|
||||
ldmia r0!, {r1,sp,lr} /* load mode-specific sp, lr, and spsr into r1 */
|
||||
msr spsr_cxfs, r1 /* load mode-specific spsr */
|
||||
.endm
|
||||
|
||||
|
||||
/**
|
||||
* Switch from kernel context to a VM
|
||||
*/
|
||||
.macro _kernel_to_vm
|
||||
ldr r0, _mt_client_context_ptr /* get vm context pointer */
|
||||
add r0, r0, #18*4 /* add offset of banked modes */
|
||||
_restore_bank 27 /* load undefined banks */
|
||||
_restore_bank 19 /* load supervisor banks */
|
||||
_restore_bank 23 /* load abort banks */
|
||||
_restore_bank 18 /* load irq banks */
|
||||
_restore_bank 17 /* load fiq banks */
|
||||
ldmia r0!, {r8 - r12} /* load fiq r8-r12 */
|
||||
cps #22 /* switch to monitor mode */
|
||||
ldr sp, _mt_client_context_ptr /* get vm context pointer */
|
||||
ldmia sp, {r0-lr}^ /* load user r0-r12,sp,lr */
|
||||
ldr lr, [sp, #16*4] /* load vm's cpsr to lr */
|
||||
msr spsr_cxfs, lr /* save cpsr to be load when switching */
|
||||
mov lr, #13
|
||||
mcr p15, 0, lr, c1, c1, 0 /* enable EA, FIQ, and NS bit in SCTRL */
|
||||
ldr lr, [sp, #15*4] /* load vm's ip */
|
||||
subs pc, lr, #0
|
||||
.endm /* _kernel_to_vm */
|
||||
|
||||
|
||||
.section .text
|
||||
|
||||
/*
|
||||
* The mode transition PIC switches between a kernel context and a user
|
||||
* context and thereby between their address spaces. Due to the latter
|
||||
* it must be mapped executable to the same region in every address space.
|
||||
* To enable such switching, the kernel context must be stored within this
|
||||
* region, thus one should map it solely accessable for privileged modes.
|
||||
*/
|
||||
.p2align 12 /* page-aligned */
|
||||
.global _mt_begin
|
||||
_mt_begin:
|
||||
|
||||
/*
|
||||
* On user exceptions the CPU has to jump to one of the following
|
||||
* 7 entry vectors to switch to a kernel context.
|
||||
*/
|
||||
.global _mt_kernel_entry_pic
|
||||
_mt_kernel_entry_pic:
|
||||
|
||||
b _rst_entry /* 0x00: reset */
|
||||
b _und_entry /* 0x04: undefined instruction */
|
||||
b _svc_entry /* 0x08: supervisor call */
|
||||
b _pab_entry /* 0x0c: prefetch abort */
|
||||
b _dab_entry /* 0x10: data abort */
|
||||
nop /* 0x14: reserved */
|
||||
b _irq_entry /* 0x18: interrupt request */
|
||||
_fiq_check_prior_mode /* 0x1c: fast interrupt request */
|
||||
_user_to_kernel_pic 7, 4
|
||||
|
||||
/* PICs that switch from an user exception to the kernel */
|
||||
_rst_entry: _user_to_kernel_pic 1, 0
|
||||
_und_entry: _user_to_kernel_pic 2, 4
|
||||
_svc_entry: _user_to_kernel_pic 3, 0
|
||||
_pab_entry: _user_to_kernel_pic 4, 4
|
||||
_dab_entry: _user_to_kernel_pic 5, 8
|
||||
_irq_entry: _user_to_kernel_pic 6, 4
|
||||
|
||||
/* kernel must jump to this point to switch to a user context */
|
||||
.p2align 2
|
||||
.global _mt_user_entry_pic
|
||||
_mt_user_entry_pic:
|
||||
_kernel_to_user_pic
|
||||
|
||||
/* leave some space for the kernel context */
|
||||
.p2align 2
|
||||
.global _mt_master_context_begin
|
||||
_mt_master_context_begin: .space 32*4
|
||||
.global _mt_master_context_end
|
||||
_mt_master_context_end:
|
||||
|
||||
/* pointer to the context backup space */
|
||||
.p2align 2
|
||||
.global _mt_client_context_ptr
|
||||
_mt_client_context_ptr: .long 0
|
||||
|
||||
/* a local word-sized buffer */
|
||||
.p2align 2
|
||||
.global _mt_buffer
|
||||
_mt_buffer: .long 0
|
||||
|
||||
.global _mt_end
|
||||
_mt_end:
|
||||
|
||||
/*
|
||||
* On vm exceptions the CPU has to jump to one of the following
|
||||
* 7 entry vectors to switch to a kernel context.
|
||||
*/
|
||||
.p2align 4
|
||||
.global _mon_kernel_entry
|
||||
_mon_kernel_entry:
|
||||
b _mon_rst_entry /* reset */
|
||||
b _mon_und_entry /* undefined instruction */
|
||||
b _mon_svc_entry /* supervisor call */
|
||||
b _mon_pab_entry /* prefetch abort */
|
||||
b _mon_dab_entry /* data abort */
|
||||
nop /* reserved */
|
||||
b _mon_irq_entry /* interrupt request */
|
||||
_vm_to_kernel 7, 4 /* fast interrupt request */
|
||||
|
||||
/* PICs that switch from a vm exception to the kernel */
|
||||
_mon_rst_entry: _vm_to_kernel 1, 0
|
||||
_mon_und_entry: _vm_to_kernel 2, 4
|
||||
_mon_svc_entry: _vm_to_kernel 3, 0
|
||||
_mon_pab_entry: _vm_to_kernel 4, 4
|
||||
_mon_dab_entry: _vm_to_kernel 5, 8
|
||||
_mon_irq_entry: _vm_to_kernel 6, 4
|
||||
|
||||
/* kernel must jump to this point to switch to a vm */
|
||||
.p2align 2
|
||||
.global _mt_vm_entry_pic
|
||||
_mt_vm_entry_pic:
|
||||
_kernel_to_vm
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* \brief Support code for the thread API
|
||||
* \author Martin Stein
|
||||
* \date 2013-05-07
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <rm_session/rm_session.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
/**
|
||||
* Return single instance of the context-area RM-session
|
||||
*
|
||||
* In base-hw core this object is never used because contexts
|
||||
* get allocated through the phys-mem allocator. Anyways the
|
||||
* accessor must exist because generic main-thread startup calls
|
||||
* it to ensure that common allocations do not steal context area.
|
||||
*/
|
||||
namespace Genode { Rm_session * env_context_area_rm_session() { return 0; } }
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* \brief CPU driver for core
|
||||
* \author Martin Stein
|
||||
* \date 2012-04-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _EXYNOS5__CPU_H_
|
||||
#define _EXYNOS5__CPU_H_
|
||||
|
||||
/* core includes */
|
||||
#include <cpu/cortex_a15.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* CPU driver for core
|
||||
*/
|
||||
class Cpu : public Cortex_a15::Cpu { };
|
||||
}
|
||||
|
||||
#endif /* _EXYNOS5__CPU_H_ */
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* \brief Translation lookaside buffer
|
||||
* \author Martin Stein
|
||||
* \date 2012-04-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _EXYNOS5__TLB_H_
|
||||
#define _EXYNOS5__TLB_H_
|
||||
|
||||
/* core includes */
|
||||
#include <board.h>
|
||||
#include <tlb/arm_v7.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
struct Page_flags : Arm::Page_flags { };
|
||||
|
||||
class Tlb : public Arm_v7::Section_table { };
|
||||
|
||||
/**
|
||||
* Translation lookaside buffer of core
|
||||
*/
|
||||
class Core_tlb : public Tlb
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor - ensures that core never gets a pagefault
|
||||
*/
|
||||
Core_tlb()
|
||||
{
|
||||
using namespace Genode;
|
||||
map_core_area(Board::RAM_0_BASE, Board::RAM_0_SIZE, 0);
|
||||
map_core_area(Board::MMIO_0_BASE, Board::MMIO_0_SIZE, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _EXYNOS5__TLB_H_ */
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* \brief CPU driver for core
|
||||
* \author Martin Stein
|
||||
* \date 2012-04-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _IMX31__CPU_H_
|
||||
#define _IMX31__CPU_H_
|
||||
|
||||
/* core includes */
|
||||
#include <cpu/arm_v6.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* CPU driver for core
|
||||
*/
|
||||
class Cpu : public Arm_v6::Cpu { };
|
||||
}
|
||||
|
||||
#endif /* _IMX31__CPU_H_ */
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* \brief Translation lookaside buffer
|
||||
* \author Norman Feske
|
||||
* \author Martin stein
|
||||
* \date 2012-08-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _IMX31__TLB_H_
|
||||
#define _IMX31__TLB_H_
|
||||
|
||||
/* core includes */
|
||||
#include <tlb/arm_v6.h>
|
||||
#include <board.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
struct Page_flags : Arm::Page_flags { };
|
||||
|
||||
class Tlb : public Arm_v6::Section_table { };
|
||||
|
||||
/**
|
||||
* Translation lookaside buffer of core
|
||||
*/
|
||||
class Core_tlb : public Tlb
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor - ensures that core never gets a pagefault
|
||||
*/
|
||||
Core_tlb()
|
||||
{
|
||||
map_core_area(Board::RAM_0_BASE, Board::RAM_0_SIZE, 0);
|
||||
map_core_area(Board::MMIO_0_BASE, Board::MMIO_0_SIZE, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _IMX31__TLB_H_ */
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* \brief CPU driver for core
|
||||
* \author Martin Stein
|
||||
* \date 2012-12-14
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _IMX53__CPU_H_
|
||||
#define _IMX53__CPU_H_
|
||||
|
||||
/* core includes */
|
||||
#include <cpu/cortex_a8.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* CPU driver for core
|
||||
*/
|
||||
class Cpu : public Cortex_a8::Cpu { };
|
||||
}
|
||||
|
||||
#endif /* _IMX53__CPU_H_ */
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* \brief Translation lookaside buffer
|
||||
* \author Stefan Kalkowski
|
||||
* \author Martin Stein
|
||||
* \date 2012-10-24
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _IMX53__TLB_H_
|
||||
#define _IMX53__TLB_H_
|
||||
|
||||
/* core includes */
|
||||
#include <board.h>
|
||||
#include <tlb/arm_v7.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
struct Page_flags : Arm::Page_flags { };
|
||||
|
||||
class Tlb : public Arm_v7::Section_table { };
|
||||
|
||||
/**
|
||||
* Translation lookaside buffer of core
|
||||
*/
|
||||
class Core_tlb : public Tlb
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor - ensures that core never gets a pagefault
|
||||
*/
|
||||
Core_tlb()
|
||||
{
|
||||
map_core_area(Board::RAM0_BASE, Board::RAM0_SIZE, 0);
|
||||
map_core_area(Board::RAM1_BASE, Board::RAM1_SIZE, 0);
|
||||
map_core_area(Board::MMIO_BASE, Board::MMIO_SIZE, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _IMX53__TLB_H_ */
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* \brief Translation lookaside buffer
|
||||
* \author Stefan Kalkowski
|
||||
* \author Martin Stein
|
||||
* \date 2012-10-24
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _IMX53__TLB_H_
|
||||
#define _IMX53__TLB_H_
|
||||
|
||||
#include <drivers/trustzone.h>
|
||||
|
||||
/* core includes */
|
||||
#include <board.h>
|
||||
#include <tlb/arm_v7.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
struct Page_flags : Arm::Page_flags { };
|
||||
|
||||
class Tlb : public Arm_v7::Section_table { };
|
||||
|
||||
/**
|
||||
* Translation lookaside buffer of core
|
||||
*/
|
||||
class Core_tlb : public Tlb
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor - ensures that core never gets a pagefault
|
||||
*/
|
||||
Core_tlb()
|
||||
{
|
||||
map_core_area(Trustzone::SECURE_RAM_BASE,
|
||||
Trustzone::SECURE_RAM_SIZE, 0);
|
||||
map_core_area(Board::MMIO_BASE, Board::MMIO_SIZE, 1);
|
||||
map_core_area(Trustzone::VM_STATE_BASE,
|
||||
Trustzone::VM_STATE_SIZE, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _IMX53__TLB_H_ */
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
/*
|
||||
* \brief Platform specific part of a Genode protection domain
|
||||
* \author Martin Stein
|
||||
* \date 2012-02-12
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__PLATFORM_PD_H_
|
||||
#define _CORE__INCLUDE__PLATFORM_PD_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
#include <root/root.h>
|
||||
|
||||
/* Core includes */
|
||||
#include <tlb.h>
|
||||
#include <platform.h>
|
||||
#include <platform_thread.h>
|
||||
#include <address_space.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
Genode::size_t pd_size();
|
||||
unsigned pd_alignm_log2();
|
||||
}
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Regain all administrative memory that isn't used anymore by 'tlb'
|
||||
*/
|
||||
inline void regain_ram_from_tlb(Tlb * tlb)
|
||||
{
|
||||
size_t s;
|
||||
void * base;
|
||||
while (tlb->regain_memory(base, s)) {
|
||||
platform()->ram_alloc()->free(base, s);
|
||||
}
|
||||
}
|
||||
|
||||
class Platform_thread;
|
||||
|
||||
/**
|
||||
* Platform specific part of a Genode protection domain
|
||||
*/
|
||||
class Platform_pd : public Address_space
|
||||
{
|
||||
unsigned _id;
|
||||
Native_capability _parent;
|
||||
Native_thread_id _main_thread;
|
||||
char const * const _label;
|
||||
Tlb * _tlb;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Platform_pd(char const *label) : _main_thread(0), _label(label)
|
||||
{
|
||||
/* get some aligned space for the kernel object */
|
||||
void * kernel_pd = 0;
|
||||
Range_allocator * ram = platform()->ram_alloc();
|
||||
bool kernel_pd_ok =
|
||||
ram->alloc_aligned(Kernel::pd_size(), &kernel_pd,
|
||||
Kernel::pd_alignm_log2()).is_ok();
|
||||
if (!kernel_pd_ok) {
|
||||
PERR("failed to allocate kernel object");
|
||||
throw Root::Quota_exceeded();
|
||||
}
|
||||
/* create kernel object */
|
||||
_id = Kernel::new_pd(kernel_pd, this);
|
||||
if (!_id) {
|
||||
PERR("failed to create kernel object");
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
_tlb = (Tlb *)kernel_pd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Platform_pd();
|
||||
|
||||
/**
|
||||
* Bind thread 't' to protection domain
|
||||
*
|
||||
* \return 0 on success or
|
||||
* -1 if failed
|
||||
*/
|
||||
int bind_thread(Platform_thread * t)
|
||||
{
|
||||
/* is this the first and therefore main thread in this PD? */
|
||||
if (!_main_thread)
|
||||
{
|
||||
/* annotate that we've got a main thread from now on */
|
||||
_main_thread = t->id();
|
||||
return t->join_pd(_id, 1, Address_space::weak_ptr());
|
||||
}
|
||||
return t->join_pd(_id, 0, Address_space::weak_ptr());
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign parent interface to protection domain
|
||||
*/
|
||||
int assign_parent(Native_capability parent)
|
||||
{
|
||||
if (!parent.valid()) {
|
||||
PERR("parent invalid");
|
||||
return -1;
|
||||
}
|
||||
_parent = parent;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
char const * const label() { return _label; }
|
||||
|
||||
|
||||
/*****************************
|
||||
** Address-space interface **
|
||||
*****************************/
|
||||
|
||||
void flush(addr_t, size_t) { PDBG("not implemented"); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__PLATFORM_PD_H_ */
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
/*
|
||||
* \brief Signal service on the HW-core
|
||||
* \author Martin stein
|
||||
* \date 2012-05-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__SIGNAL_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__SIGNAL_SESSION_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <signal_session/signal_session.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/slab.h>
|
||||
#include <base/allocator_guard.h>
|
||||
#include <base/object_pool.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Provides the signal service
|
||||
*/
|
||||
class Signal_session_component : public Rpc_object<Signal_session>
|
||||
{
|
||||
public:
|
||||
|
||||
enum {
|
||||
/**
|
||||
* Lastly Receiver::slab_size() was 112. Additionally we
|
||||
* have to take in account, that the backing store might add
|
||||
* its metadata and round up to next page size. So we choose
|
||||
* 35 * 112 which mostly is save to end up in one page only.
|
||||
*/
|
||||
RECEIVERS_SB_SIZE = 3920,
|
||||
|
||||
/**
|
||||
* Lastly Context::slab_size() size was 124. Additionally we
|
||||
* have to take in account, that the backing store might add
|
||||
* its metadata and round up to next page size. So we choose
|
||||
* 32 * 124 which mostly is save to end up in one page only.
|
||||
*/
|
||||
CONTEXTS_SB_SIZE = 3968,
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Maps a signal-receiver name to related core and kernel resources
|
||||
*/
|
||||
class Receiver;
|
||||
|
||||
/**
|
||||
* Maps a signal-context name to related core and kernel resources
|
||||
*/
|
||||
class Context;
|
||||
|
||||
typedef Object_pool<Receiver> Receiver_pool;
|
||||
typedef Object_pool<Context> Context_pool;
|
||||
|
||||
Allocator_guard _md_alloc;
|
||||
Slab _receivers_slab;
|
||||
Receiver_pool _receivers;
|
||||
Slab _contexts_slab;
|
||||
Context_pool _contexts;
|
||||
char _initial_receivers_sb [RECEIVERS_SB_SIZE];
|
||||
char _initial_contexts_sb [CONTEXTS_SB_SIZE];
|
||||
|
||||
/**
|
||||
* Destruct receiver 'r'
|
||||
*/
|
||||
void _destruct_receiver(Receiver * const r);
|
||||
|
||||
/**
|
||||
* Destruct context 'c'
|
||||
*/
|
||||
void _destruct_context(Context * const c);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param md Metadata allocator
|
||||
* \param ram_quota Amount of RAM quota donated to this session
|
||||
*/
|
||||
Signal_session_component(Allocator * const md,
|
||||
size_t const ram_quota);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Signal_session_component();
|
||||
|
||||
/**
|
||||
* Raise the quota of this session by 'q'
|
||||
*/
|
||||
void upgrade_ram_quota(size_t const q) { _md_alloc.upgrade(q); }
|
||||
|
||||
/******************************
|
||||
** Signal_session interface **
|
||||
******************************/
|
||||
|
||||
Signal_receiver_capability alloc_receiver();
|
||||
|
||||
Signal_context_capability
|
||||
alloc_context(Signal_receiver_capability, unsigned const);
|
||||
|
||||
void free_receiver(Signal_receiver_capability);
|
||||
|
||||
void free_context(Signal_context_capability);
|
||||
};
|
||||
}
|
||||
|
||||
class Genode::Signal_session_component::Receiver : public Receiver_pool::Entry
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Receiver(Untyped_capability cap) : Entry(cap) { }
|
||||
|
||||
/**
|
||||
* Name of signal receiver
|
||||
*/
|
||||
unsigned id() const { return Receiver_pool::Entry::cap().dst(); }
|
||||
|
||||
/**
|
||||
* Size of SLAB block occupied by resources and this resource info
|
||||
*/
|
||||
static size_t slab_size()
|
||||
{
|
||||
return sizeof(Receiver) + Kernel::signal_receiver_size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Base of region donated to the kernel
|
||||
*/
|
||||
static addr_t kernel_donation(void * const slab_addr)
|
||||
{
|
||||
return ((addr_t)slab_addr + sizeof(Receiver));
|
||||
}
|
||||
};
|
||||
|
||||
class Genode::Signal_session_component::Context : public Context_pool::Entry
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Context(Untyped_capability cap) : Entry(cap) { }
|
||||
|
||||
/**
|
||||
* Name of signal context
|
||||
*/
|
||||
unsigned id() const { return Context_pool::Entry::cap().dst(); }
|
||||
|
||||
/**
|
||||
* Size of SLAB block occupied by resources and this resource info
|
||||
*/
|
||||
static size_t slab_size()
|
||||
{
|
||||
return sizeof(Context) + Kernel::signal_context_size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Base of region donated to the kernel
|
||||
*/
|
||||
static addr_t kernel_donation(void * const slab_addr)
|
||||
{
|
||||
return ((addr_t)slab_addr + sizeof(Context));
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__CAP_SESSION_COMPONENT_H_ */
|
||||
@@ -1,287 +0,0 @@
|
||||
/*
|
||||
* \brief Singlethreaded minimalistic kernel
|
||||
* \author Martin Stein
|
||||
* \date 2011-10-20
|
||||
*
|
||||
* This kernel is the only code except the mode transition PIC, that runs in
|
||||
* privileged CPU mode. It has two tasks. First it initializes the process
|
||||
* 'core', enriches it with the whole identically mapped address range,
|
||||
* joins and applies it, assigns one thread to it with a userdefined
|
||||
* entrypoint (the core main thread) and starts this thread in userland.
|
||||
* Afterwards it is called each time an exception occurs in userland to do
|
||||
* a minimum of appropriate exception handling. Thus it holds a CPU context
|
||||
* for itself as for any other thread. But due to the fact that it never
|
||||
* relies on prior kernel runs this context only holds some constant pointers
|
||||
* such as SP and IP.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/pd.h>
|
||||
#include <kernel/vm.h>
|
||||
#include <kernel/irq.h>
|
||||
#include <platform_pd.h>
|
||||
#include <trustzone.h>
|
||||
#include <timer.h>
|
||||
#include <pic.h>
|
||||
|
||||
/* base includes */
|
||||
#include <unmanaged_singleton.h>
|
||||
|
||||
/* base-hw includes */
|
||||
#include <kernel/perf_counter.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
/* get core configuration */
|
||||
extern Genode::Native_utcb * _main_thread_utcb;
|
||||
extern Genode::Native_thread_id _main_thread_id;
|
||||
extern int _kernel_stack_high;
|
||||
extern "C" void CORE_MAIN();
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
/**
|
||||
* Return interrupt-controller singleton
|
||||
*/
|
||||
Pic * pic() { return unmanaged_singleton<Pic>(); }
|
||||
|
||||
/* import Genode types */
|
||||
typedef Genode::umword_t umword_t;
|
||||
typedef Genode::Core_tlb Core_tlb;
|
||||
typedef Genode::Core_thread_id Core_thread_id;
|
||||
|
||||
void init_platform();
|
||||
}
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
/**
|
||||
* Idle thread entry
|
||||
*/
|
||||
static void idle_main() { while (1) ; }
|
||||
|
||||
Pd_ids * pd_ids() { return unmanaged_singleton<Pd_ids>(); }
|
||||
Thread_ids * thread_ids() { return unmanaged_singleton<Thread_ids>(); }
|
||||
Signal_context_ids * signal_context_ids() { return unmanaged_singleton<Signal_context_ids>(); }
|
||||
Signal_receiver_ids * signal_receiver_ids() { return unmanaged_singleton<Signal_receiver_ids>(); }
|
||||
|
||||
Pd_pool * pd_pool() { return unmanaged_singleton<Pd_pool>(); }
|
||||
Thread_pool * thread_pool() { return unmanaged_singleton<Thread_pool>(); }
|
||||
Signal_context_pool * signal_context_pool() { return unmanaged_singleton<Signal_context_pool>(); }
|
||||
Signal_receiver_pool * signal_receiver_pool() { return unmanaged_singleton<Signal_receiver_pool>(); }
|
||||
|
||||
/**
|
||||
* Access to static kernel timer
|
||||
*/
|
||||
static Timer * timer() { static Timer _object; return &_object; }
|
||||
|
||||
|
||||
void reset_lap_time()
|
||||
{
|
||||
timer()->start_one_shot(timer()->ms_to_tics(USER_LAP_TIME_MS));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Static kernel PD that describes core
|
||||
*/
|
||||
static Pd * core()
|
||||
{
|
||||
/**
|
||||
* Core protection-domain
|
||||
*/
|
||||
class Core_pd : public Pd
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Core_pd(Tlb * const tlb, Platform_pd * const platform_pd)
|
||||
:
|
||||
Pd(tlb, platform_pd)
|
||||
{ }
|
||||
};
|
||||
constexpr int tlb_align = 1 << Core_tlb::ALIGNM_LOG2;
|
||||
Core_tlb * core_tlb = unmanaged_singleton<Core_tlb, tlb_align>();
|
||||
Core_pd * core_pd = unmanaged_singleton<Core_pd>(core_tlb, nullptr);
|
||||
return core_pd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get core attributes
|
||||
*/
|
||||
unsigned core_id() { return core()->id(); }
|
||||
}
|
||||
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
/**
|
||||
* Access to static CPU scheduler
|
||||
*/
|
||||
Cpu_scheduler * cpu_scheduler()
|
||||
{
|
||||
/* create idle thread */
|
||||
static char idle_stack[DEFAULT_STACK_SIZE]
|
||||
__attribute__((aligned(Cpu::DATA_ACCESS_ALIGNM)));
|
||||
static Thread idle(Priority::MAX, "idle");
|
||||
static bool init = 0;
|
||||
if (!init) {
|
||||
enum { STACK_SIZE = sizeof(idle_stack)/sizeof(idle_stack[0]) };
|
||||
idle.ip = (addr_t)&idle_main;;
|
||||
idle.sp = (addr_t)&idle_stack[STACK_SIZE];;
|
||||
idle.init(0, core_id(), 0, 0);
|
||||
init = 1;
|
||||
}
|
||||
/* create CPU scheduler with a permanent idle thread */
|
||||
static Cpu_scheduler cpu_sched(&idle);
|
||||
return &cpu_sched;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get attributes of the mode transition region in every PD
|
||||
*/
|
||||
addr_t mode_transition_virt_base() { return mtc()->VIRT_BASE; }
|
||||
size_t mode_transition_size() { return mtc()->SIZE; }
|
||||
|
||||
/**
|
||||
* Get attributes of the kernel objects
|
||||
*/
|
||||
size_t thread_size() { return sizeof(Thread); }
|
||||
size_t pd_size() { return sizeof(Tlb) + sizeof(Pd); }
|
||||
size_t signal_context_size() { return sizeof(Signal_context); }
|
||||
size_t signal_receiver_size() { return sizeof(Signal_receiver); }
|
||||
unsigned pd_alignm_log2() { return Tlb::ALIGNM_LOG2; }
|
||||
size_t vm_size() { return sizeof(Vm); }
|
||||
|
||||
|
||||
/**
|
||||
* Handle an interrupt request
|
||||
*/
|
||||
void handle_interrupt()
|
||||
{
|
||||
/* determine handling for specific interrupt */
|
||||
unsigned irq_id;
|
||||
if (pic()->take_request(irq_id))
|
||||
{
|
||||
switch (irq_id) {
|
||||
|
||||
case Timer::IRQ: {
|
||||
|
||||
cpu_scheduler()->yield();
|
||||
timer()->clear_interrupt();
|
||||
reset_lap_time();
|
||||
break; }
|
||||
|
||||
default: {
|
||||
|
||||
Irq::occurred(irq_id);
|
||||
break; }
|
||||
}
|
||||
}
|
||||
/* disengage interrupt controller from IRQ */
|
||||
pic()->finish_request();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the system for the first run of 'kernel'
|
||||
*/
|
||||
extern "C" void init_phys_kernel() {
|
||||
Cpu::init_phys_kernel(); }
|
||||
|
||||
/**
|
||||
* Kernel main routine
|
||||
*/
|
||||
extern "C" void kernel()
|
||||
{
|
||||
static bool initial_call = true;
|
||||
|
||||
/* an exception occurred */
|
||||
if (!initial_call)
|
||||
{
|
||||
/* handle exception that interrupted the last user */
|
||||
cpu_scheduler()->head()->handle_exception();
|
||||
|
||||
/* kernel initialization */
|
||||
} else {
|
||||
|
||||
/* enable kernel timer */
|
||||
pic()->unmask(Timer::IRQ);
|
||||
|
||||
/* TrustZone initialization code */
|
||||
trustzone_initialization(pic());
|
||||
|
||||
/* enable performance counter */
|
||||
perf_counter()->enable();
|
||||
|
||||
/* switch to core address space */
|
||||
Cpu::init_virt_kernel(core()->tlb()->base(), core_id());
|
||||
|
||||
/*
|
||||
* From this point on, it is safe to use 'cmpxchg', i.e., to create
|
||||
* singleton objects via the static-local object pattern. See
|
||||
* the comment in 'src/base/singleton.h'.
|
||||
*/
|
||||
|
||||
/* create the core main thread */
|
||||
{
|
||||
/* get stack memory that fullfills the constraints for core stacks */
|
||||
enum {
|
||||
STACK_ALIGNM = 1 << Genode::CORE_STACK_ALIGNM_LOG2,
|
||||
STACK_SIZE = DEFAULT_STACK_SIZE,
|
||||
};
|
||||
if (STACK_SIZE > STACK_ALIGNM - sizeof(Core_thread_id)) {
|
||||
PERR("stack size does not fit stack alignment of core");
|
||||
}
|
||||
static char s[STACK_SIZE] __attribute__((aligned(STACK_ALIGNM)));
|
||||
|
||||
/* provide thread ident at the aligned base of the stack */
|
||||
*(Core_thread_id *)s = 0;
|
||||
|
||||
/* start thread with stack pointer at the top of stack */
|
||||
static Native_utcb utcb;
|
||||
static Thread t(Priority::MAX, "core");
|
||||
_main_thread_id = t.id();
|
||||
_main_thread_utcb = &utcb;
|
||||
_main_thread_utcb->start_info()->init(t.id(), Genode::Native_capability());
|
||||
t.ip = (addr_t)CORE_MAIN;;
|
||||
t.sp = (addr_t)s + STACK_SIZE;
|
||||
t.init(0, core_id(), &utcb, 1);
|
||||
}
|
||||
/* kernel initialization finished */
|
||||
init_platform();
|
||||
reset_lap_time();
|
||||
initial_call = false;
|
||||
}
|
||||
/* will jump to the context related mode-switch */
|
||||
cpu_scheduler()->head()->proceed();
|
||||
}
|
||||
|
||||
Kernel::Mode_transition_control * Kernel::mtc()
|
||||
{
|
||||
/* compose CPU context for kernel entry */
|
||||
struct Kernel_context : Cpu::Context
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Kernel_context()
|
||||
{
|
||||
ip = (addr_t)kernel;
|
||||
sp = (addr_t)&_kernel_stack_high;
|
||||
core()->admit(this);
|
||||
}
|
||||
} * const k = unmanaged_singleton<Kernel_context>();
|
||||
|
||||
/* initialize mode transition page */
|
||||
return unmanaged_singleton<Mode_transition_control>(k);
|
||||
}
|
||||
@@ -1,217 +0,0 @@
|
||||
/*
|
||||
* \brief Kernel backend for protection domains
|
||||
* \author Martin Stein
|
||||
* \date 2012-11-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _KERNEL__PD_H_
|
||||
#define _KERNEL__PD_H_
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/configuration.h>
|
||||
#include <kernel/object.h>
|
||||
#include <tlb.h>
|
||||
#include <cpu.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* structure of the mode transition */
|
||||
extern int _mt_begin;
|
||||
extern int _mt_end;
|
||||
extern int _mt_user_entry_pic;
|
||||
extern int _mt_vm_entry_pic;
|
||||
extern Genode::addr_t _mt_client_context_ptr;
|
||||
extern Genode::addr_t _mt_master_context_begin;
|
||||
extern Genode::addr_t _mt_master_context_end;
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
/**
|
||||
* Controls the mode-transition page
|
||||
*
|
||||
* The mode transition page is a small memory region that is mapped by
|
||||
* every PD to the same virtual address. It contains code that acts as a
|
||||
* link between high privileged CPU mode (often called kernel) and low
|
||||
* privileged CPU mode (often called userland). The mode transition
|
||||
* control provides a simple interface to access the code from within
|
||||
* the kernel.
|
||||
*/
|
||||
struct Mode_transition_control;
|
||||
|
||||
/**
|
||||
* Return the system wide mode-transition control
|
||||
*/
|
||||
Mode_transition_control * mtc();
|
||||
|
||||
/**
|
||||
* Kernel backend of protection domains
|
||||
*/
|
||||
class Pd;
|
||||
|
||||
class Pd_ids : public Id_allocator<MAX_PDS> { };
|
||||
typedef Object_pool<Pd> Pd_pool;
|
||||
|
||||
Pd_ids * pd_ids();
|
||||
Pd_pool * pd_pool();
|
||||
}
|
||||
|
||||
class Kernel::Mode_transition_control
|
||||
{
|
||||
friend class Pd;
|
||||
|
||||
private:
|
||||
|
||||
typedef Genode::Cpu Cpu;
|
||||
typedef Genode::Cpu_state_modes Cpu_state_modes;
|
||||
typedef Genode::Page_flags Page_flags;
|
||||
|
||||
addr_t const _virt_user_entry;
|
||||
|
||||
public:
|
||||
|
||||
enum {
|
||||
SIZE_LOG2 = Tlb::MIN_PAGE_SIZE_LOG2,
|
||||
SIZE = 1 << SIZE_LOG2,
|
||||
VIRT_BASE = Cpu::EXCEPTION_ENTRY,
|
||||
VIRT_END = VIRT_BASE + SIZE,
|
||||
ALIGNM_LOG2 = SIZE_LOG2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param c CPU context for kernel mode entry
|
||||
*/
|
||||
Mode_transition_control(Cpu::Context * const c)
|
||||
:
|
||||
_virt_user_entry(VIRT_BASE + ((addr_t)&_mt_user_entry_pic -
|
||||
(addr_t)&_mt_begin))
|
||||
{
|
||||
/* check if mode transition fits into aligned region */
|
||||
addr_t const mt_begin = (addr_t)&_mt_begin;
|
||||
addr_t const mt_end = (addr_t)&_mt_end;
|
||||
size_t const mt_size = mt_end - mt_begin;
|
||||
assert(mt_size <= SIZE);
|
||||
|
||||
/* check if kernel context fits into the mode transition */
|
||||
addr_t const kc_begin = (addr_t)&_mt_master_context_begin;
|
||||
addr_t const kc_end = (addr_t)&_mt_master_context_end;
|
||||
size_t const kc_size = kc_end - kc_begin;
|
||||
assert(sizeof(Cpu::Context) <= kc_size);
|
||||
|
||||
/* fetch kernel-mode context */
|
||||
Genode::memcpy(&_mt_master_context_begin, c, sizeof(Cpu::Context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the mode transition page to a virtual address space
|
||||
*
|
||||
* \param tlb translation buffer of the address space
|
||||
* \param ram RAM donation for mapping (first try without)
|
||||
*
|
||||
* \return RAM-donation size that is needed to do the mapping
|
||||
*/
|
||||
size_t map(Tlb * tlb, addr_t ram = 0)
|
||||
{
|
||||
Page_flags::access_t const flags = Page_flags::mode_transition();
|
||||
addr_t const phys_base = (addr_t)&_mt_begin;
|
||||
return tlb->insert_translation(VIRT_BASE, phys_base, SIZE_LOG2,
|
||||
flags, (void *)ram);
|
||||
}
|
||||
|
||||
/**
|
||||
* Continue user-mode execution with CPU context 'c'
|
||||
*/
|
||||
void continue_user(Cpu::Context * const c)
|
||||
{
|
||||
_mt_client_context_ptr = (addr_t)c;
|
||||
((void(*)(void))_virt_user_entry)();
|
||||
}
|
||||
|
||||
/**
|
||||
* Continue VM execution with CPU state 's'
|
||||
*/
|
||||
void continue_vm(Cpu_state_modes * s)
|
||||
{
|
||||
_mt_client_context_ptr = (addr_t)s;
|
||||
((void(*)(void))&_mt_vm_entry_pic)();
|
||||
}
|
||||
};
|
||||
|
||||
class Kernel::Pd : public Object<Pd, MAX_PDS, Pd_ids, pd_ids, pd_pool>
|
||||
{
|
||||
private:
|
||||
|
||||
typedef Genode::Cpu Cpu;
|
||||
|
||||
Tlb * const _tlb;
|
||||
Platform_pd * const _platform_pd;
|
||||
|
||||
/* keep ready memory for size-aligned extra costs at construction */
|
||||
enum { EXTRA_RAM_SIZE = 2 * Tlb::MAX_COSTS_PER_TRANSLATION };
|
||||
char _extra_ram[EXTRA_RAM_SIZE];
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param tlb translation lookaside buffer of the PD
|
||||
* \param platform_pd core object of the PD
|
||||
*/
|
||||
Pd(Tlb * const tlb, Platform_pd * const platform_pd)
|
||||
:
|
||||
_tlb(tlb), _platform_pd(platform_pd)
|
||||
{
|
||||
/* try to add translation for mode transition region */
|
||||
unsigned const slog2 = mtc()->map(tlb);
|
||||
|
||||
/* extra ram needed to translate mode transition region */
|
||||
if (slog2)
|
||||
{
|
||||
/* get size aligned extra ram */
|
||||
addr_t const ram = (addr_t)&_extra_ram;
|
||||
addr_t const ram_end = ram + sizeof(_extra_ram);
|
||||
addr_t const aligned_ram = (ram_end - (1 << slog2)) &
|
||||
~((1 << slog2) - 1);
|
||||
addr_t const aligned_ram_end = aligned_ram + (1 << slog2);
|
||||
|
||||
/* check attributes of aligned extra ram */
|
||||
assert(aligned_ram >= ram && aligned_ram_end <= ram_end)
|
||||
|
||||
/* translate mode transition region globally */
|
||||
mtc()->map(tlb, aligned_ram);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Pd() { }
|
||||
|
||||
/**
|
||||
* Let the CPU context 'c' join the PD
|
||||
*/
|
||||
void admit(Cpu::Context * const c)
|
||||
{
|
||||
c->protection_domain(id());
|
||||
c->tlb(tlb()->base());
|
||||
}
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Tlb * tlb() const { return _tlb; }
|
||||
|
||||
Platform_pd * platform_pd() const { return _platform_pd; }
|
||||
};
|
||||
|
||||
#endif /* _KERNEL__PD_H_ */
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* \brief Transtaltion lookaside buffer
|
||||
* \author Martin Stein
|
||||
* \date 2012-04-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _PANDA__TLB_H_
|
||||
#define _PANDA__TLB_H_
|
||||
|
||||
/* core includes */
|
||||
#include <board.h>
|
||||
#include <tlb/arm_v7.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
struct Page_flags : Arm::Page_flags { };
|
||||
|
||||
class Tlb : public Arm_v7::Section_table { };
|
||||
|
||||
/**
|
||||
* Transtaltion lookaside buffer of core
|
||||
*/
|
||||
class Core_tlb : public Tlb
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* On Pandaboard the L2 cache needs to be disabled by a
|
||||
* TrustZone hypervisor call
|
||||
*/
|
||||
void _disable_outer_l2_cache()
|
||||
{
|
||||
asm volatile (
|
||||
"stmfd sp!, {r0-r12} \n"
|
||||
"mov r0, #0 \n"
|
||||
"ldr r12, =0x102 \n"
|
||||
"dsb \n"
|
||||
"smc #0 \n"
|
||||
"ldmfd sp!, {r0-r12}");
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor - ensures that core never gets a pagefault
|
||||
*/
|
||||
Core_tlb()
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/*
|
||||
* Disable L2-cache by now, or we get into deep trouble with the MMU
|
||||
* not using the L2 cache
|
||||
*/
|
||||
_disable_outer_l2_cache();
|
||||
|
||||
map_core_area(Board::RAM_0_BASE, Board::RAM_0_SIZE, 0);
|
||||
map_core_area(Board::MMIO_0_BASE, Board::MMIO_0_SIZE, 1);
|
||||
map_core_area(Board::MMIO_1_BASE, Board::MMIO_1_SIZE, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _PANDA__TLB_H_ */
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* \brief CPU driver for core
|
||||
* \author Martin Stein
|
||||
* \date 2012-04-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _PBXA9__CPU_H_
|
||||
#define _PBXA9__CPU_H_
|
||||
|
||||
/* core includes */
|
||||
#include <cpu/cortex_a9.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* CPU driver for core
|
||||
*/
|
||||
class Cpu : public Cortex_a9::Cpu { };
|
||||
}
|
||||
|
||||
#endif /* _PBXA9__CPU_H_ */
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* \brief Translation lookaside buffer
|
||||
* \author Martin Stein
|
||||
* \date 2012-04-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _PBXA9__TLB_H_
|
||||
#define _PBXA9__TLB_H_
|
||||
|
||||
/* core includes */
|
||||
#include <board.h>
|
||||
#include <tlb/arm_v7.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
struct Page_flags : Arm::Page_flags { };
|
||||
|
||||
class Tlb : public Arm_v7::Section_table { };
|
||||
|
||||
/**
|
||||
* Translation lookaside buffer of core
|
||||
*/
|
||||
class Core_tlb : public Tlb
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor - ensures that core never gets a pagefault
|
||||
*/
|
||||
Core_tlb()
|
||||
{
|
||||
using namespace Genode;
|
||||
map_core_area(Board::RAM_0_BASE, Board::RAM_0_SIZE, 0);
|
||||
map_core_area(Board::RAM_1_BASE, Board::RAM_1_SIZE, 0);
|
||||
map_core_area(Board::MMIO_0_BASE, Board::MMIO_0_SIZE, 1);
|
||||
map_core_area(Board::MMIO_1_BASE, Board::MMIO_1_SIZE, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _PBXA9__TLB_H_ */
|
||||
|
||||
@@ -1,326 +0,0 @@
|
||||
/*
|
||||
* \brief Programmable interrupt controller for core
|
||||
* \author Martin stein
|
||||
* \date 2011-10-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _PIC__ARM_GIC_H_
|
||||
#define _PIC__ARM_GIC_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/mmio.h>
|
||||
|
||||
namespace Arm_gic
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/**
|
||||
* Programmable interrupt controller for core
|
||||
*
|
||||
* ARM generic interrupt controller, Architecture version 2.0
|
||||
*/
|
||||
class Pic
|
||||
{
|
||||
public:
|
||||
|
||||
enum { MAX_INTERRUPT_ID = 1023 };
|
||||
|
||||
protected:
|
||||
|
||||
enum {
|
||||
MIN_SPI = 32,
|
||||
SPURIOUS_ID = 1023,
|
||||
};
|
||||
|
||||
/**
|
||||
* Distributor interface
|
||||
*/
|
||||
struct Distr : public Mmio
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Distr(addr_t const base) : Mmio(base) { }
|
||||
|
||||
/**
|
||||
* Control register
|
||||
*/
|
||||
struct Ctlr : Register<0x000, 32>
|
||||
{
|
||||
struct Enable : Bitfield<0,1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Controller type register
|
||||
*/
|
||||
struct Typer : Register<0x004, 32>
|
||||
{
|
||||
struct It_lines_number : Bitfield<0,5> { };
|
||||
struct Cpu_number : Bitfield<5,3> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Interrupt group register
|
||||
*/
|
||||
struct Igroupr :
|
||||
Register_array<0x80, 32, MAX_INTERRUPT_ID + 1, 1>
|
||||
{
|
||||
struct Group_status : Bitfield<0, 1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Interrupt set enable registers
|
||||
*/
|
||||
struct Isenabler :
|
||||
Register_array<0x100, 32, MAX_INTERRUPT_ID + 1, 1, true>
|
||||
{
|
||||
struct Set_enable : Bitfield<0, 1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Interrupt clear enable registers
|
||||
*/
|
||||
struct Icenabler :
|
||||
Register_array<0x180, 32, MAX_INTERRUPT_ID + 1, 1, true>
|
||||
{
|
||||
struct Clear_enable : Bitfield<0, 1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Interrupt priority level registers
|
||||
*/
|
||||
struct Ipriorityr :
|
||||
Register_array<0x400, 32, MAX_INTERRUPT_ID + 1, 8>
|
||||
{
|
||||
enum { GET_MIN = 0xff };
|
||||
|
||||
struct Priority : Bitfield<0, 8> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Interrupt processor target registers
|
||||
*/
|
||||
struct Itargetsr :
|
||||
Register_array<0x800, 32, MAX_INTERRUPT_ID + 1, 8>
|
||||
{
|
||||
enum { ALL = 0xff };
|
||||
|
||||
struct Cpu_targets : Bitfield<0, 8> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Interrupt configuration registers
|
||||
*/
|
||||
struct Icfgr :
|
||||
Register_array<0xc00, 32, MAX_INTERRUPT_ID + 1, 2>
|
||||
{
|
||||
struct Edge_triggered : Bitfield<1, 1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Minimum supported interrupt priority
|
||||
*/
|
||||
Ipriorityr::access_t min_priority()
|
||||
{
|
||||
write<Ipriorityr::Priority>(Ipriorityr::GET_MIN, 0);
|
||||
return read<Ipriorityr::Priority>(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum supported interrupt priority
|
||||
*/
|
||||
Ipriorityr::access_t max_priority() { return 0; }
|
||||
|
||||
/**
|
||||
* ID of the maximum supported interrupt
|
||||
*/
|
||||
Typer::access_t max_interrupt()
|
||||
{
|
||||
enum { LINE_WIDTH_LOG2 = 5 };
|
||||
Typer::access_t lnr = read<Typer::It_lines_number>();
|
||||
return ((lnr + 1) << LINE_WIDTH_LOG2) - 1;
|
||||
}
|
||||
|
||||
} _distr;
|
||||
|
||||
/**
|
||||
* CPU interface
|
||||
*/
|
||||
struct Cpu : public Mmio
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Cpu(addr_t const base) : Mmio(base) { }
|
||||
|
||||
/**
|
||||
* Control register
|
||||
*/
|
||||
struct Ctlr : Register<0x00, 32>
|
||||
{
|
||||
/* Without security extension */
|
||||
struct Enable : Bitfield<0,1> { };
|
||||
|
||||
/* In a secure world */
|
||||
struct Enable_grp0 : Bitfield<0,1> { };
|
||||
struct Enable_grp1 : Bitfield<1,1> { };
|
||||
struct Fiq_en : Bitfield<3,1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Priority mask register
|
||||
*/
|
||||
struct Pmr : Register<0x04, 32>
|
||||
{
|
||||
struct Priority : Bitfield<0,8> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Binary point register
|
||||
*/
|
||||
struct Bpr : Register<0x08, 32>
|
||||
{
|
||||
enum { NO_PREEMPTION = 7 };
|
||||
|
||||
struct Binary_point : Bitfield<0,3> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Interrupt acknowledge register
|
||||
*/
|
||||
struct Iar : Register<0x0c, 32, true>
|
||||
{
|
||||
struct Irq_id : Bitfield<0,10> { };
|
||||
struct Cpu_id : Bitfield<10,3> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* End of interrupt register
|
||||
*/
|
||||
struct Eoir : Register<0x10, 32, true>
|
||||
{
|
||||
struct Irq_id : Bitfield<0,10> { };
|
||||
struct Cpu_id : Bitfield<10,3> { };
|
||||
};
|
||||
} _cpu;
|
||||
|
||||
unsigned const _max_interrupt;
|
||||
unsigned _last_request;
|
||||
|
||||
/**
|
||||
* Wether the security extension is used or not
|
||||
*/
|
||||
inline static bool _use_security_ext();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor, all interrupts get masked
|
||||
*/
|
||||
Pic(addr_t const distr_base, addr_t const cpu_base) :
|
||||
_distr(distr_base), _cpu(cpu_base),
|
||||
_max_interrupt(_distr.max_interrupt()),
|
||||
_last_request(SPURIOUS_ID)
|
||||
{
|
||||
/* with security extension any board has its own init */
|
||||
if (_use_security_ext()) return;
|
||||
|
||||
/* disable device */
|
||||
_distr.write<Distr::Ctlr::Enable>(0);
|
||||
|
||||
/* supported priority range */
|
||||
unsigned const min_prio = _distr.min_priority();
|
||||
unsigned const max_prio = _distr.max_priority();
|
||||
|
||||
/* configure every shared peripheral interrupt */
|
||||
for (unsigned i=MIN_SPI; i <= _max_interrupt; i++)
|
||||
{
|
||||
_distr.write<Distr::Icfgr::Edge_triggered>(0, i);
|
||||
_distr.write<Distr::Ipriorityr::Priority>(max_prio, i);
|
||||
_distr.write<Distr::Itargetsr::Cpu_targets>(
|
||||
Distr::Itargetsr::ALL, i);
|
||||
}
|
||||
|
||||
/* disable the priority filter */
|
||||
_cpu.write<Cpu::Pmr::Priority>(min_prio);
|
||||
|
||||
/* disable preemption of interrupt handling by interrupts */
|
||||
_cpu.write<Cpu::Bpr::Binary_point>(Cpu::Bpr::NO_PREEMPTION);
|
||||
|
||||
/* enable device */
|
||||
_distr.write<Distr::Ctlr::Enable>(1);
|
||||
_cpu.write<Cpu::Ctlr::Enable>(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ID of the last interrupt request
|
||||
*
|
||||
* \return True if the request with ID 'i' is treated as accepted
|
||||
* by the CPU and awaits an subsequently 'finish_request'
|
||||
* call. Otherwise this returns false and the value of 'i'
|
||||
* remains useless.
|
||||
*/
|
||||
bool take_request(unsigned & i)
|
||||
{
|
||||
_last_request = _cpu.read<Cpu::Iar::Irq_id>();
|
||||
i = _last_request;
|
||||
return valid(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the last request that was taken via 'take_request'
|
||||
*/
|
||||
void finish_request()
|
||||
{
|
||||
if (!valid(_last_request)) return;
|
||||
_cpu.write<Cpu::Eoir>(Cpu::Eoir::Irq_id::bits(_last_request) |
|
||||
Cpu::Eoir::Cpu_id::bits(0) );
|
||||
_last_request = SPURIOUS_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if 'i' is a valid interrupt request ID at the device
|
||||
*/
|
||||
bool valid(unsigned const i) const { return i <= _max_interrupt; }
|
||||
|
||||
/**
|
||||
* Unmask all interrupts
|
||||
*/
|
||||
void unmask()
|
||||
{
|
||||
for (unsigned i=0; i <= _max_interrupt; i++)
|
||||
_distr.write<Distr::Isenabler::Set_enable>(1, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmask interrupt 'i'
|
||||
*/
|
||||
void unmask(unsigned const i) {
|
||||
_distr.write<Distr::Isenabler::Set_enable>(1, i); }
|
||||
|
||||
/**
|
||||
* Mask all interrupts
|
||||
*/
|
||||
void mask()
|
||||
{
|
||||
for (unsigned i=0; i <= _max_interrupt; i++)
|
||||
_distr.write<Distr::Icenabler::Clear_enable>(1, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mask interrupt 'i'
|
||||
*/
|
||||
void mask(unsigned const i) {
|
||||
_distr.write<Distr::Icenabler::Clear_enable>(1, i); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _PIC__ARM_GIC_H_ */
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* \brief Export RAM dataspace as shared memory object (dummy)
|
||||
* \author Martin Stein
|
||||
* \date 2012-02-12
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
|
||||
/* base-hw includes */
|
||||
#include <kernel/interface.h>
|
||||
|
||||
/* core includes */
|
||||
#include <ram_session_component.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
void Ram_session_component::_export_ram_ds(Dataspace_component *ds) { }
|
||||
|
||||
|
||||
void Ram_session_component::_revoke_ram_ds(Dataspace_component *ds) { }
|
||||
|
||||
|
||||
void Ram_session_component::_clear_ds (Dataspace_component * ds)
|
||||
{
|
||||
memset((void *)ds->phys_addr(), 0, ds->size());
|
||||
|
||||
/* make the new DS-content visible to other PDs */
|
||||
Kernel::update_region(ds->phys_addr(), ds->size());
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* \brief Board driver for core
|
||||
* \author Norman Feske
|
||||
* \date 2013-04-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _RPI__BOARD_H_
|
||||
#define _RPI__BOARD_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <drivers/board_base.h>
|
||||
|
||||
namespace Genode { struct Board; }
|
||||
|
||||
struct Genode::Board : Genode::Board_base { static void prepare_kernel() { } };
|
||||
|
||||
#endif /* _RPI__BOARD_H_ */
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* \brief Translation lookaside buffer
|
||||
* \author Norman Feske
|
||||
* \author Martin stein
|
||||
* \date 2012-08-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _RPI__TLB_H_
|
||||
#define _RPI__TLB_H_
|
||||
|
||||
/* core includes */
|
||||
#include <tlb/arm_v6.h>
|
||||
#include <board.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
struct Page_flags : Arm::Page_flags { };
|
||||
|
||||
class Tlb : public Arm_v6::Section_table { };
|
||||
|
||||
/**
|
||||
* Translation lookaside buffer of core
|
||||
*/
|
||||
class Core_tlb : public Tlb
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor - ensures that core never gets a pagefault
|
||||
*/
|
||||
Core_tlb()
|
||||
{
|
||||
map_core_area(Board::RAM_0_BASE, Board::RAM_0_SIZE, 0);
|
||||
map_core_area(Board::MMIO_0_BASE, Board::MMIO_0_SIZE, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _RPI__TLB_H_ */
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* \brief Implementation of Thread API interface for core
|
||||
* \author Martin Stein
|
||||
* \date 2012-01-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/thread.h>
|
||||
#include <base/env.h>
|
||||
#include <kernel/log.h>
|
||||
|
||||
/* core includes */
|
||||
#include <platform.h>
|
||||
#include <platform_thread.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
extern Genode::Native_utcb * _main_thread_utcb;
|
||||
|
||||
namespace Kernel { unsigned core_id(); }
|
||||
|
||||
|
||||
Native_utcb * Thread_base::utcb()
|
||||
{
|
||||
if (this) { return _tid.platform_thread->utcb_virt(); }
|
||||
return _main_thread_utcb;
|
||||
}
|
||||
|
||||
|
||||
Thread_base * Thread_base::myself()
|
||||
{
|
||||
/* get thread ident from the aligned base of the stack */
|
||||
int dummy = 0;
|
||||
addr_t sp = (addr_t)(&dummy);
|
||||
enum { SP_MASK = ~((1 << CORE_STACK_ALIGNM_LOG2) - 1) };
|
||||
Core_thread_id id = *(Core_thread_id *)((addr_t)sp & SP_MASK);
|
||||
return (Thread_base *)id;
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::_thread_start()
|
||||
{
|
||||
/* this is never called by the main thread */
|
||||
Thread_base::myself()->_thread_bootstrap();
|
||||
Thread_base::myself()->entry();
|
||||
}
|
||||
|
||||
|
||||
Thread_base::Thread_base(const char * const label, size_t const stack_size, Type)
|
||||
{
|
||||
_tid.platform_thread = new (platform()->core_mem_alloc())
|
||||
Platform_thread(stack_size, Kernel::core_id(), label);
|
||||
}
|
||||
|
||||
|
||||
Thread_base::~Thread_base()
|
||||
{
|
||||
Kernel::log() << __PRETTY_FUNCTION__ << "not implemented\n";
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::start()
|
||||
{
|
||||
/* allocate stack memory that fullfills the constraints for core stacks */
|
||||
size_t const size = _tid.platform_thread->stack_size();
|
||||
if (size > (1 << CORE_STACK_ALIGNM_LOG2) - sizeof(Core_thread_id)) {
|
||||
PERR("stack size does not fit stack alignment of core");
|
||||
return;
|
||||
}
|
||||
void * base;
|
||||
Platform * const p = static_cast<Platform *>(platform());
|
||||
Range_allocator * const alloc = p->core_mem_alloc();
|
||||
if (alloc->alloc_aligned(size, &base, CORE_STACK_ALIGNM_LOG2).is_error()) {
|
||||
PERR("failed to allocate stack memory");
|
||||
return;
|
||||
}
|
||||
/* provide thread ident at the aligned base of the stack */
|
||||
*(Core_thread_id *)base = (Core_thread_id)this;
|
||||
|
||||
/* start thread with stack pointer at the top of stack */
|
||||
void * sp = (void *)((addr_t)base + size);
|
||||
void * ip = (void *)&_thread_start;
|
||||
if (_tid.platform_thread->start(ip, sp)) {
|
||||
PERR("failed to start thread");
|
||||
alloc->free(base, size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::join()
|
||||
{
|
||||
_join_lock.lock();
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::cancel_blocking()
|
||||
{
|
||||
_tid.platform_thread->cancel_blocking();
|
||||
}
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
* \brief Timer for core
|
||||
* \author Martin stein
|
||||
* \date 2013-01-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _TIMER__EXYNOS_MCT_H_
|
||||
#define _TIMER__EXYNOS_MCT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/mmio.h>
|
||||
|
||||
namespace Exynos_mct
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/**
|
||||
* Timer for core
|
||||
*/
|
||||
class Timer : public Mmio
|
||||
{
|
||||
enum {
|
||||
PRESCALER = 1,
|
||||
DIV_MUX = 0,
|
||||
};
|
||||
|
||||
/**
|
||||
* MCT configuration
|
||||
*/
|
||||
struct Mct_cfg : Register<0x0, 32>
|
||||
{
|
||||
struct Prescaler : Bitfield<0, 8> { };
|
||||
struct Div_mux : Bitfield<8, 3> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Local timer 0 free running counter buffer
|
||||
*/
|
||||
struct L0_frcntb : Register<0x310, 32> { };
|
||||
|
||||
/**
|
||||
* Local timer 0 configuration
|
||||
*/
|
||||
struct L0_tcon : Register<0x320, 32>
|
||||
{
|
||||
struct Frc_start : Bitfield<3, 1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Local timer 0 expired status
|
||||
*/
|
||||
struct L0_int_cstat : Register<0x330, 32, true>
|
||||
{
|
||||
struct Frcnt : Bitfield<1, 1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Local timer 0 interrupt enable
|
||||
*/
|
||||
struct L0_int_enb : Register<0x334, 32>
|
||||
{
|
||||
struct Frceie : Bitfield<1, 1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Local timer 0 write status
|
||||
*/
|
||||
struct L0_wstat : Register<0x340, 32, true>
|
||||
{
|
||||
struct Frcntb : Bitfield<2, 1> { };
|
||||
struct Tcon : Bitfield<3, 1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Write to reg that replies via ack bit and clear ack bit
|
||||
*/
|
||||
template <typename DEST, typename ACK>
|
||||
void _acked_write(typename DEST::Register_base::access_t const v)
|
||||
{
|
||||
typedef typename DEST::Register_base Dest;
|
||||
typedef typename ACK::Bitfield_base Ack;
|
||||
write<Dest>(v);
|
||||
while (!read<Ack>());
|
||||
write<Ack>(1);
|
||||
}
|
||||
|
||||
float const _tics_per_ms;
|
||||
|
||||
/**
|
||||
* Start and stop counting
|
||||
*/
|
||||
void _run(bool const run)
|
||||
{
|
||||
_acked_write<L0_tcon, L0_wstat::Tcon>
|
||||
(L0_tcon::Frc_start::bits(run));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Timer(addr_t const base, unsigned const clk)
|
||||
: Mmio(base), _tics_per_ms((float)clk / (PRESCALER + 1) / (1 << DIV_MUX) / 1000)
|
||||
{
|
||||
Mct_cfg::access_t mct_cfg = 0;
|
||||
Mct_cfg::Prescaler::set(mct_cfg, PRESCALER);
|
||||
Mct_cfg::Div_mux::set(mct_cfg, DIV_MUX);
|
||||
write<Mct_cfg>(mct_cfg);
|
||||
write<L0_int_enb>(L0_int_enb::Frceie::bits(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Start one-shot run with an IRQ delay of 'tics'
|
||||
*/
|
||||
inline void start_one_shot(unsigned const tics)
|
||||
{
|
||||
_run(0);
|
||||
_acked_write<L0_frcntb, L0_wstat::Frcntb>(tics);
|
||||
_run(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate 'ms' milliseconds to a native timer value
|
||||
*/
|
||||
unsigned ms_to_tics(unsigned const ms)
|
||||
{
|
||||
return ms * _tics_per_ms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear interrupt output line
|
||||
*/
|
||||
void clear_interrupt() { write<L0_int_cstat::Frcnt>(1); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _TIMER__EXYNOS_MCT_H_ */
|
||||
@@ -1,937 +0,0 @@
|
||||
/*
|
||||
* \brief TLB driver for core
|
||||
* \author Martin Stein
|
||||
* \date 2012-02-22
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _TLB__ARM_H_
|
||||
#define _TLB__ARM_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/register.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
/* base-hw includes */
|
||||
#include <placement_new.h>
|
||||
|
||||
namespace Arm
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/**
|
||||
* Map app-specific mem attributes to a TLB-specific POD
|
||||
*/
|
||||
struct Page_flags : Register<8>
|
||||
{
|
||||
struct W : Bitfield<0, 1> { }; /* writeable */
|
||||
struct X : Bitfield<1, 1> { }; /* executable */
|
||||
struct K : Bitfield<2, 1> { }; /* privileged */
|
||||
struct G : Bitfield<3, 1> { }; /* global */
|
||||
struct D : Bitfield<4, 1> { }; /* device */
|
||||
struct C : Bitfield<5, 1> { }; /* cacheable */
|
||||
|
||||
/**
|
||||
* Create flag POD for Genode pagers
|
||||
*/
|
||||
static access_t
|
||||
apply_mapping(bool const writeable,
|
||||
bool const write_combined,
|
||||
bool const io_mem) {
|
||||
return W::bits(writeable) | X::bits(1) | K::bits(0) | G::bits(0) |
|
||||
D::bits(io_mem) | C::bits(!write_combined & !io_mem); }
|
||||
|
||||
/**
|
||||
* Create flag POD for kernel when it creates the core space
|
||||
*/
|
||||
static access_t map_core_area(bool const io_mem) {
|
||||
return W::bits(1) | X::bits(1) | K::bits(0) | G::bits(0) |
|
||||
D::bits(io_mem) | C::bits(!io_mem); }
|
||||
|
||||
/**
|
||||
* Create flag POD for the mode transition region
|
||||
*/
|
||||
static access_t mode_transition() {
|
||||
return W::bits(1) | X::bits(1) | K::bits(1) | G::bits(1) |
|
||||
D::bits(0) | C::bits(1); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if 'p' is aligned to 1 << 'alignm_log2'
|
||||
*/
|
||||
inline bool aligned(addr_t const a, size_t const alignm_log2) {
|
||||
return a == ((a >> alignm_log2) << alignm_log2); }
|
||||
|
||||
/**
|
||||
* Common access permission [1:0] bitfield values
|
||||
*/
|
||||
struct Ap_1_0_bitfield
|
||||
{
|
||||
enum {
|
||||
KERNEL_AND_USER_NO_ACCESS = 0,
|
||||
USER_NO_ACCESS = 1,
|
||||
USER_RO_ACCESS = 2,
|
||||
KERNEL_AND_USER_SAME_ACCESS = 3
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Common access permission [2] bitfield values
|
||||
*/
|
||||
struct Ap_2_bitfield
|
||||
{
|
||||
enum {
|
||||
KERNEL_RW_OR_NO_ACCESS = 0,
|
||||
KERNEL_RO_ACCESS = 1
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Permission configuration according to given access rights
|
||||
*
|
||||
* \param T targeted translation-table-descriptor type
|
||||
* \param w see 'Section_table::insert_translation'
|
||||
* \param x see 'Section_table::insert_translation'
|
||||
* \param k see 'Section_table::insert_translation'
|
||||
*
|
||||
* \return descriptor value with requested perms and the rest left zero
|
||||
*/
|
||||
template <typename T>
|
||||
static typename T::access_t
|
||||
access_permission_bits(Page_flags::access_t const flags)
|
||||
{
|
||||
/* lookup table for AP bitfield values according to 'w' and 'k' flag */
|
||||
typedef typename T::Ap_1_0 Ap_1_0;
|
||||
typedef typename T::Ap_2 Ap_2;
|
||||
|
||||
/*
|
||||
* Note: Don't make 'ap_bits' static to avoid implicit use of 'cmpxchg'
|
||||
* prior enabling the MMU.
|
||||
*
|
||||
* XXX Replace array with a simpler-to-grasp switch statement.
|
||||
*/
|
||||
typename T::access_t const ap_bits[2][2] = {{
|
||||
Ap_1_0::bits(Ap_1_0::USER_RO_ACCESS) | /* -- */
|
||||
Ap_2::bits(Ap_2::KERNEL_RW_OR_NO_ACCESS),
|
||||
|
||||
Ap_1_0::bits(Ap_1_0::USER_NO_ACCESS) | /* -k */
|
||||
Ap_2::bits(Ap_2::KERNEL_RO_ACCESS) }, {
|
||||
|
||||
Ap_1_0::bits(Ap_1_0::KERNEL_AND_USER_SAME_ACCESS) | /* w- */
|
||||
Ap_2::bits(Ap_2::KERNEL_RW_OR_NO_ACCESS),
|
||||
|
||||
Ap_1_0::bits(Ap_1_0::USER_NO_ACCESS) | /* wk */
|
||||
Ap_2::bits(Ap_2::KERNEL_RW_OR_NO_ACCESS) }
|
||||
};
|
||||
/* combine XN and AP bitfield values according to the flags */
|
||||
typedef typename T::Xn Xn;
|
||||
return Xn::bits(!Page_flags::X::get(flags)) |
|
||||
ap_bits[Page_flags::W::get(flags)][Page_flags::K::get(flags)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Memory region attributes for the translation descriptor 'T'
|
||||
*/
|
||||
template <typename T>
|
||||
static typename T::access_t
|
||||
memory_region_attr(Page_flags::access_t const flags);
|
||||
|
||||
/**
|
||||
* Second level translation table
|
||||
*
|
||||
* A table is dedicated to either secure or non-secure mode. All
|
||||
* translations done by this table apply to domain 0. They are not
|
||||
* shareable and have zero-filled memory region attributes.
|
||||
*/
|
||||
class Page_table
|
||||
{
|
||||
enum {
|
||||
_1KB_LOG2 = 10,
|
||||
_4KB_LOG2 = 12,
|
||||
_64KB_LOG2 = 16,
|
||||
_1MB_LOG2 = 20,
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
enum {
|
||||
SIZE_LOG2 = _1KB_LOG2,
|
||||
SIZE = 1 << SIZE_LOG2,
|
||||
ALIGNM_LOG2 = SIZE_LOG2,
|
||||
|
||||
VIRT_SIZE_LOG2 = _1MB_LOG2,
|
||||
VIRT_SIZE = 1 << VIRT_SIZE_LOG2,
|
||||
VIRT_BASE_MASK = ~((1 << VIRT_SIZE_LOG2) - 1),
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Common descriptor structure
|
||||
*/
|
||||
struct Descriptor : Register<32>
|
||||
{
|
||||
/**
|
||||
* Descriptor types
|
||||
*/
|
||||
enum Type { FAULT, SMALL_PAGE, LARGE_PAGE };
|
||||
|
||||
struct Type_1 : Bitfield<1, 1> { };
|
||||
struct Type_2 : Bitfield<0, 1> { };
|
||||
|
||||
/**
|
||||
* Get descriptor type of 'v'
|
||||
*/
|
||||
static Type type(access_t const v)
|
||||
{
|
||||
access_t const t1 = Type_1::get(v);
|
||||
if (t1 == 0) {
|
||||
access_t const t2 = Type_2::get(v);
|
||||
if (t2 == 0) return FAULT;
|
||||
if (t2 == 1) return LARGE_PAGE;
|
||||
}
|
||||
if (t1 == 1) return SMALL_PAGE;
|
||||
return FAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set descriptor type of 'v'
|
||||
*/
|
||||
static void type(access_t & v, Type const t)
|
||||
{
|
||||
switch (t) {
|
||||
|
||||
case FAULT: {
|
||||
|
||||
Type_1::set(v, 0);
|
||||
Type_2::set(v, 0);
|
||||
break; }
|
||||
|
||||
case SMALL_PAGE: {
|
||||
|
||||
Type_1::set(v, 1);
|
||||
break; }
|
||||
|
||||
case LARGE_PAGE: {
|
||||
|
||||
Type_1::set(v, 0);
|
||||
Type_2::set(v, 1);
|
||||
break; }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate descriptor 'v'
|
||||
*/
|
||||
static void invalidate(access_t & v) { type(v, FAULT); }
|
||||
|
||||
/**
|
||||
* Return if descriptor 'v' is valid
|
||||
*/
|
||||
static bool valid(access_t & v) { return type(v) != FAULT; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents an untranslated virtual region
|
||||
*/
|
||||
struct Fault : Descriptor
|
||||
{
|
||||
enum {
|
||||
VIRT_SIZE_LOG2 = _4KB_LOG2,
|
||||
VIRT_SIZE = 1 << VIRT_SIZE_LOG2,
|
||||
VIRT_BASE_MASK = ~((1 << VIRT_SIZE_LOG2) - 1)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Small page descriptor structure
|
||||
*/
|
||||
struct Small_page : Descriptor
|
||||
{
|
||||
enum {
|
||||
VIRT_SIZE_LOG2 = _4KB_LOG2,
|
||||
VIRT_SIZE = 1 << VIRT_SIZE_LOG2,
|
||||
VIRT_OFFSET_MASK = (1 << VIRT_SIZE_LOG2) - 1,
|
||||
VIRT_BASE_MASK = ~(VIRT_OFFSET_MASK),
|
||||
};
|
||||
|
||||
struct Xn : Bitfield<0, 1> { }; /* execute never */
|
||||
struct B : Bitfield<2, 1> { }; /* mem region attr. */
|
||||
struct C : Bitfield<3, 1> { }; /* mem region attr. */
|
||||
struct Ap_1_0 : Bitfield<4, 2>, /* access permission */
|
||||
Ap_1_0_bitfield { };
|
||||
struct Tex : Bitfield<6, 3> { }; /* mem region attr. */
|
||||
struct Ap_2 : Bitfield<9, 1>, /* access permission */
|
||||
Ap_2_bitfield { };
|
||||
struct S : Bitfield<10, 1> { }; /* shareable bit */
|
||||
struct Ng : Bitfield<11, 1> { }; /* not global bit */
|
||||
struct Pa_31_12 : Bitfield<12, 20> { }; /* physical base */
|
||||
|
||||
/**
|
||||
* Compose descriptor value
|
||||
*/
|
||||
static access_t create(Page_flags::access_t const flags,
|
||||
addr_t const pa)
|
||||
{
|
||||
access_t v = access_permission_bits<Small_page>(flags) |
|
||||
memory_region_attr<Small_page>(flags) |
|
||||
Ng::bits(!Page_flags::G::get(flags)) |
|
||||
S::bits(0) | Pa_31_12::masked(pa);
|
||||
Descriptor::type(v, Descriptor::SMALL_PAGE);
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Table payload
|
||||
*
|
||||
* Must be the only member of this class
|
||||
*/
|
||||
Descriptor::access_t _entries[SIZE/sizeof(Descriptor::access_t)];
|
||||
|
||||
enum { MAX_INDEX = sizeof(_entries) / sizeof(_entries[0]) - 1 };
|
||||
|
||||
/**
|
||||
* Get entry index by virtual offset
|
||||
*
|
||||
* \param i is overridden with the index if call returns 0
|
||||
* \param vo virtual offset relative to the virtual table base
|
||||
*
|
||||
* \retval 0 on success
|
||||
* \retval <0 translation failed
|
||||
*/
|
||||
int _index_by_vo (unsigned & i, addr_t const vo) const
|
||||
{
|
||||
if (vo > max_virt_offset()) return -1;
|
||||
i = vo >> Small_page::VIRT_SIZE_LOG2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Page_table()
|
||||
{
|
||||
/* check table alignment */
|
||||
if (!aligned((addr_t)this, ALIGNM_LOG2) ||
|
||||
(addr_t)this != (addr_t)_entries)
|
||||
{
|
||||
PDBG("Insufficient table alignment");
|
||||
while (1) ;
|
||||
}
|
||||
/* start with an empty table */
|
||||
for (unsigned i = 0; i <= MAX_INDEX; i++)
|
||||
Descriptor::invalidate(_entries[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum virtual offset that can be translated by this table
|
||||
*/
|
||||
static addr_t max_virt_offset()
|
||||
{
|
||||
return (MAX_INDEX << Small_page::VIRT_SIZE_LOG2)
|
||||
+ (Small_page::VIRT_SIZE - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert one atomic translation into this table
|
||||
*
|
||||
* \param vo offset of the virtual region represented
|
||||
* by the translation within the virtual
|
||||
* region represented by this table
|
||||
* \param pa base of the physical backing store
|
||||
* \param size_log2 log2(Size of the translated region),
|
||||
* must be supported by this table
|
||||
* \param flags mapping flags
|
||||
*
|
||||
* This method overrides an existing translation in case
|
||||
* that it spans the the same virtual range and is not
|
||||
* a link to another table level.
|
||||
*/
|
||||
void insert_translation(addr_t const vo, addr_t const pa,
|
||||
size_t const size_log2,
|
||||
Page_flags::access_t const flags)
|
||||
{
|
||||
/* validate virtual address */
|
||||
unsigned i;
|
||||
if (_index_by_vo (i, vo)) {
|
||||
PDBG("Invalid virtual offset");
|
||||
while (1) ;
|
||||
}
|
||||
/* select descriptor type by the translation size */
|
||||
if (size_log2 == Small_page::VIRT_SIZE_LOG2)
|
||||
{
|
||||
/* compose new descriptor value */
|
||||
Descriptor::access_t const entry =
|
||||
Small_page::create(flags, pa);
|
||||
|
||||
/* check if we can we write to the targeted entry */
|
||||
if (Descriptor::valid(_entries[i]))
|
||||
{
|
||||
/*
|
||||
* It's possible that multiple threads fault at the
|
||||
* same time on the same translation, thus we need
|
||||
* this check.
|
||||
*/
|
||||
if (_entries[i] == entry) return;
|
||||
|
||||
/* never modify existing translations */
|
||||
PDBG("Couldn't override entry");
|
||||
while (1) ;
|
||||
}
|
||||
/* override table entry with new descriptor value */
|
||||
_entries[i] = entry;
|
||||
return;
|
||||
}
|
||||
PDBG("Translation size not supported");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove translations that overlap with a given virtual region
|
||||
*
|
||||
* \param vo region offset within the tables virtual region
|
||||
* \param size region size
|
||||
*/
|
||||
void remove_region(addr_t vo, size_t const size)
|
||||
{
|
||||
addr_t const ve = vo + size;
|
||||
unsigned i;
|
||||
while (1)
|
||||
{
|
||||
if (vo >= ve) { return; }
|
||||
if (_index_by_vo(i, vo)) { return; }
|
||||
addr_t next_vo;
|
||||
switch (Descriptor::type(_entries[i])) {
|
||||
|
||||
case Descriptor::FAULT: {
|
||||
|
||||
vo &= Fault::VIRT_BASE_MASK;
|
||||
next_vo = vo + Fault::VIRT_SIZE;
|
||||
break; }
|
||||
|
||||
case Descriptor::SMALL_PAGE: {
|
||||
|
||||
vo &= Small_page::VIRT_BASE_MASK;
|
||||
Descriptor::invalidate(_entries[i]);
|
||||
next_vo = vo + Small_page::VIRT_SIZE;
|
||||
break; }
|
||||
|
||||
case Descriptor::LARGE_PAGE: {
|
||||
|
||||
PDBG("large pages not supported by now");
|
||||
while (1) ;
|
||||
break; }
|
||||
}
|
||||
if (next_vo < vo) { return; }
|
||||
vo = next_vo;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this table solely contain invalid entries
|
||||
*/
|
||||
bool empty()
|
||||
{
|
||||
for (unsigned i = 0; i <= MAX_INDEX; i++) {
|
||||
if (Descriptor::valid(_entries[i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next translation size log2 by area constraints
|
||||
*
|
||||
* \param vo virtual offset within this table
|
||||
* \param s area size
|
||||
*/
|
||||
static unsigned
|
||||
translation_size_l2(addr_t const vo, size_t const s)
|
||||
{
|
||||
off_t const o = vo & Small_page::VIRT_OFFSET_MASK;
|
||||
if (!o && s >= Small_page::VIRT_SIZE)
|
||||
return Small_page::VIRT_SIZE_LOG2;
|
||||
PDBG("Insufficient alignment or size");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
} __attribute__((aligned(1<<Page_table::ALIGNM_LOG2)));
|
||||
|
||||
/**
|
||||
* First level translation table
|
||||
*
|
||||
* A table is dedicated to either secure or non-secure mode. All
|
||||
* translations done by this table apply to domain 0. They are not
|
||||
* shareable and have zero-filled memory region attributes. The size
|
||||
* of this table is fixed to such a value that this table translates
|
||||
* a space wich is addressable by 32 bit.
|
||||
*/
|
||||
class Section_table
|
||||
{
|
||||
enum {
|
||||
_16KB_LOG2 = 14,
|
||||
_1MB_LOG2 = 20,
|
||||
_16MB_LOG2 = 24,
|
||||
|
||||
DOMAIN = 0,
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
enum {
|
||||
SIZE_LOG2 = _16KB_LOG2,
|
||||
SIZE = 1 << SIZE_LOG2,
|
||||
ALIGNM_LOG2 = SIZE_LOG2,
|
||||
|
||||
VIRT_SIZE_LOG2 = _1MB_LOG2,
|
||||
VIRT_SIZE = 1 << VIRT_SIZE_LOG2,
|
||||
VIRT_BASE_MASK = ~((1 << VIRT_SIZE_LOG2) - 1),
|
||||
|
||||
MAX_COSTS_PER_TRANSLATION = sizeof(Page_table),
|
||||
|
||||
MAX_PAGE_SIZE_LOG2 = 20,
|
||||
MIN_PAGE_SIZE_LOG2 = 12,
|
||||
};
|
||||
|
||||
/**
|
||||
* A first level translation descriptor
|
||||
*/
|
||||
struct Descriptor : Register<32>
|
||||
{
|
||||
/**
|
||||
* Descriptor types
|
||||
*/
|
||||
enum Type { FAULT, PAGE_TABLE, SECTION, SUPERSECTION };
|
||||
|
||||
struct Type_1 : Bitfield<0, 2> { }; /* entry type code 1 */
|
||||
struct Type_2 : Bitfield<18, 1> { }; /* entry type code 2 */
|
||||
|
||||
/**
|
||||
* Get descriptor type of 'v'
|
||||
*/
|
||||
static Type type(access_t const v)
|
||||
{
|
||||
access_t const t1 = Type_1::get(v);
|
||||
if (t1 == 0) return FAULT;
|
||||
if (t1 == 1) return PAGE_TABLE;
|
||||
if (t1 == 2) {
|
||||
access_t const t2 = Type_2::get(v);
|
||||
if (t2 == 0) return SECTION;
|
||||
if (t2 == 1) return SUPERSECTION;
|
||||
}
|
||||
return FAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set descriptor type of 'v'
|
||||
*/
|
||||
static void type(access_t & v, Type const t)
|
||||
{
|
||||
switch (t) {
|
||||
case FAULT: Type_1::set(v, 0); break;
|
||||
case PAGE_TABLE: Type_1::set(v, 1); break;
|
||||
case SECTION:
|
||||
Type_1::set(v, 2);
|
||||
Type_2::set(v, 0); break;
|
||||
case SUPERSECTION:
|
||||
Type_1::set(v, 2);
|
||||
Type_2::set(v, 1); break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate descriptor 'v'
|
||||
*/
|
||||
static void invalidate(access_t & v) { type(v, FAULT); }
|
||||
|
||||
/**
|
||||
* Return if descriptor 'v' is valid
|
||||
*/
|
||||
static bool valid(access_t & v) { return type(v) != FAULT; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents an untranslated virtual region
|
||||
*/
|
||||
struct Fault : Descriptor
|
||||
{
|
||||
enum {
|
||||
VIRT_SIZE_LOG2 = _1MB_LOG2,
|
||||
VIRT_SIZE = 1 << VIRT_SIZE_LOG2,
|
||||
VIRT_BASE_MASK = ~((1 << VIRT_SIZE_LOG2) - 1)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Link to a second level translation table
|
||||
*/
|
||||
struct Page_table_descriptor : Descriptor
|
||||
{
|
||||
struct Domain : Bitfield<5, 4> { }; /* domain */
|
||||
struct Pa_31_10 : Bitfield<10, 22> { }; /* physical base */
|
||||
|
||||
/**
|
||||
* Compose descriptor value
|
||||
*/
|
||||
static access_t create(Page_table * const pt)
|
||||
{
|
||||
access_t v = Domain::bits(DOMAIN) |
|
||||
Pa_31_10::masked((addr_t)pt);
|
||||
Descriptor::type(v, Descriptor::PAGE_TABLE);
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Section translation descriptor
|
||||
*/
|
||||
struct Section : Descriptor
|
||||
{
|
||||
enum {
|
||||
VIRT_SIZE_LOG2 = _1MB_LOG2,
|
||||
VIRT_SIZE = 1 << VIRT_SIZE_LOG2,
|
||||
VIRT_OFFSET_MASK = (1 << VIRT_SIZE_LOG2) - 1,
|
||||
VIRT_BASE_MASK = ~(VIRT_OFFSET_MASK),
|
||||
};
|
||||
|
||||
struct B : Bitfield<2, 1> { }; /* mem. region attr. */
|
||||
struct C : Bitfield<3, 1> { }; /* mem. region attr. */
|
||||
struct Xn : Bitfield<4, 1> { }; /* execute never bit */
|
||||
struct Domain : Bitfield<5, 4> { }; /* domain */
|
||||
struct Ap_1_0 : Bitfield<10, 2>, /* access permission */
|
||||
Ap_1_0_bitfield { };
|
||||
struct Tex : Bitfield<12, 3> { }; /* mem. region attr. */
|
||||
struct Ap_2 : Bitfield<15, 1>, /* access permission */
|
||||
Ap_2_bitfield { };
|
||||
struct S : Bitfield<16, 1> { }; /* shared */
|
||||
struct Ng : Bitfield<17, 1> { }; /* not global */
|
||||
struct Pa_31_20 : Bitfield<20, 12> { }; /* physical base */
|
||||
|
||||
/**
|
||||
* Compose descriptor value
|
||||
*/
|
||||
static access_t create(Page_flags::access_t const flags,
|
||||
addr_t const pa)
|
||||
{
|
||||
access_t v = access_permission_bits<Section>(flags) |
|
||||
memory_region_attr<Section>(flags) |
|
||||
Domain::bits(DOMAIN) | S::bits(0) |
|
||||
Ng::bits(!Page_flags::G::get(flags)) |
|
||||
Pa_31_20::masked(pa);
|
||||
Descriptor::type(v, Descriptor::SECTION);
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
/* table payload, must be the first member of this class */
|
||||
Descriptor::access_t _entries[SIZE/sizeof(Descriptor::access_t)];
|
||||
|
||||
enum { MAX_INDEX = sizeof(_entries) / sizeof(_entries[0]) - 1 };
|
||||
|
||||
/**
|
||||
* Get entry index by virtual offset
|
||||
*
|
||||
* \param i is overridden with the resulting index
|
||||
* \param vo offset within the virtual region represented
|
||||
* by this table
|
||||
*
|
||||
* \retval 0 on success
|
||||
* \retval <0 if virtual offset couldn't be resolved,
|
||||
* in this case 'i' reside invalid
|
||||
*/
|
||||
int _index_by_vo(unsigned & i, addr_t const vo) const
|
||||
{
|
||||
if (vo > max_virt_offset()) return -1;
|
||||
i = vo >> Section::VIRT_SIZE_LOG2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Placement new
|
||||
*/
|
||||
void * operator new (size_t, void * p) { return p; }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Section_table()
|
||||
{
|
||||
/* check for appropriate positioning of the table */
|
||||
if (!aligned((addr_t)this, ALIGNM_LOG2)
|
||||
|| (addr_t)this != (addr_t)_entries)
|
||||
{
|
||||
PDBG("Insufficient table alignment");
|
||||
while (1) ;
|
||||
}
|
||||
/* start with an empty table */
|
||||
for (unsigned i = 0; i <= MAX_INDEX; i++)
|
||||
Descriptor::invalidate(_entries[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum virtual offset that can be translated by this table
|
||||
*/
|
||||
static addr_t max_virt_offset()
|
||||
{
|
||||
return (MAX_INDEX << Section::VIRT_SIZE_LOG2)
|
||||
+ (Section::VIRT_SIZE - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert one atomic translation into this table
|
||||
*
|
||||
* \param ST platform specific section-table type
|
||||
* \param st platform specific section table
|
||||
* \param vo offset of the virtual region represented
|
||||
* by the translation within the virtual
|
||||
* region represented by this table
|
||||
* \param pa base of the physical backing store
|
||||
* \param size_log2 size log2 of the translated region
|
||||
* \param flags mapping flags
|
||||
* \param extra_space If > 0, it must point to a portion of
|
||||
* size-aligned memory space wich may be used
|
||||
* furthermore by the table for the incurring
|
||||
* administrative costs of the translation.
|
||||
* To determine the amount of additionally
|
||||
* needed memory one can instrument this
|
||||
* method with 'extra_space' set to 0.
|
||||
* The so donated memory may be regained by
|
||||
* using the method 'regain_memory'.
|
||||
*
|
||||
* \retval 0 translation successfully inserted
|
||||
* \retval >0 Translation not inserted, the return value
|
||||
* is the size log2 of additional size-aligned
|
||||
* space that is needed to do the translation.
|
||||
* This occurs solely when 'extra_space' is 0.
|
||||
*
|
||||
* This method overrides an existing translation in case that it
|
||||
* spans the the same virtual range and is not a link to another
|
||||
* table level.
|
||||
*/
|
||||
template <typename ST>
|
||||
size_t insert_translation(addr_t const vo, addr_t const pa,
|
||||
size_t const size_log2,
|
||||
Page_flags::access_t const flags,
|
||||
ST * const st,
|
||||
void * const extra_space = 0)
|
||||
{
|
||||
typedef typename ST::Section Section;
|
||||
typedef typename ST::Page_table_descriptor Page_table_descriptor;
|
||||
|
||||
/* validate virtual address */
|
||||
unsigned i;
|
||||
if (_index_by_vo (i, vo)) {
|
||||
PDBG("Invalid virtual offset");
|
||||
while (1) ;
|
||||
}
|
||||
/* select descriptor type by translation size */
|
||||
if (size_log2 < Section::VIRT_SIZE_LOG2)
|
||||
{
|
||||
/* check if an appropriate page table already exists */
|
||||
Page_table * pt;
|
||||
if (Descriptor::type(_entries[i]) == Descriptor::PAGE_TABLE) {
|
||||
pt = (Page_table *)(addr_t)
|
||||
Page_table_descriptor::Pa_31_10::masked(_entries[i]);
|
||||
}
|
||||
/* check if we have enough memory for the page table */
|
||||
else if (extra_space)
|
||||
{
|
||||
/* check if we can write to the targeted entry */
|
||||
if (Descriptor::valid(_entries[i])) {
|
||||
PDBG ("Couldn't override entry");
|
||||
while (1) ;
|
||||
}
|
||||
/* create and link page table */
|
||||
pt = new (extra_space) Page_table();
|
||||
_entries[i] = Page_table_descriptor::create(pt, st);
|
||||
}
|
||||
/* request additional memory to create a page table */
|
||||
else return Page_table::SIZE_LOG2;
|
||||
|
||||
/* insert translation */
|
||||
pt->insert_translation(vo - Section::Pa_31_20::masked(vo),
|
||||
pa, size_log2, flags);
|
||||
return 0;
|
||||
}
|
||||
if (size_log2 == Section::VIRT_SIZE_LOG2)
|
||||
{
|
||||
/* compose section descriptor */
|
||||
Descriptor::access_t const entry =
|
||||
Section::create(flags, pa, st);
|
||||
|
||||
/* check if we can we write to the targeted entry */
|
||||
if (Descriptor::valid(_entries[i]))
|
||||
{
|
||||
/*
|
||||
* It's possible that multiple threads fault at the
|
||||
* same time on the same translation, thus we need
|
||||
* this check.
|
||||
*/
|
||||
if (_entries[i] == entry) return 0;
|
||||
|
||||
/* never modify existing translations */
|
||||
PDBG("Couldn't override entry");
|
||||
while (1) ;
|
||||
}
|
||||
/* override the table entry */
|
||||
_entries[i] = entry;
|
||||
return 0;
|
||||
}
|
||||
PDBG("Translation size not supported");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove translations that overlap with a given virtual region
|
||||
*
|
||||
* \param vo region offset within the tables virtual region
|
||||
* \param size region size
|
||||
*/
|
||||
void remove_region(addr_t vo, size_t const size)
|
||||
{
|
||||
addr_t const ve = vo + size;
|
||||
unsigned i;
|
||||
while (1)
|
||||
{
|
||||
if (vo >= ve) { return; }
|
||||
if (_index_by_vo(i, vo)) { return; }
|
||||
addr_t next_vo;
|
||||
switch (Descriptor::type(_entries[i])) {
|
||||
|
||||
case Descriptor::FAULT: {
|
||||
|
||||
vo &= Fault::VIRT_BASE_MASK;
|
||||
next_vo = vo + Fault::VIRT_SIZE;
|
||||
break; }
|
||||
|
||||
case Descriptor::PAGE_TABLE: {
|
||||
|
||||
typedef Page_table_descriptor Ptd;
|
||||
typedef Page_table Pt;
|
||||
|
||||
vo &= Pt::VIRT_BASE_MASK;
|
||||
Pt * const pt = (Pt *)Ptd::Pa_31_10::masked(_entries[i]);
|
||||
addr_t const pt_vo = vo - Section::Pa_31_20::masked(vo);
|
||||
pt->remove_region(pt_vo, ve - vo);
|
||||
next_vo = vo + Pt::VIRT_SIZE;
|
||||
break; }
|
||||
|
||||
case Descriptor::SECTION: {
|
||||
|
||||
vo &= Section::VIRT_BASE_MASK;
|
||||
Descriptor::invalidate(_entries[i]);
|
||||
next_vo = vo + Section::VIRT_SIZE;
|
||||
break; }
|
||||
|
||||
case Descriptor::SUPERSECTION: {
|
||||
|
||||
PDBG("supersections not supported by now");
|
||||
while (1) { }
|
||||
break; }
|
||||
}
|
||||
if (next_vo < vo) { return; }
|
||||
vo = next_vo;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get base address for hardware table walk
|
||||
*/
|
||||
addr_t base() const { return (addr_t)_entries; }
|
||||
|
||||
/**
|
||||
* Get a portion of memory that is no longer used by this table
|
||||
*
|
||||
* \param base base of regained mem portion if method returns 1
|
||||
* \param s size of regained mem portion if method returns 1
|
||||
*
|
||||
* \retval 1 successfully regained memory
|
||||
* \retval 0 no more memory to regain
|
||||
*/
|
||||
bool regain_memory (void * & base, size_t & s)
|
||||
{
|
||||
/* walk through all entries */
|
||||
for (unsigned i = 0; i <= MAX_INDEX; i++)
|
||||
{
|
||||
if (Descriptor::type(_entries[i]) == Descriptor::PAGE_TABLE)
|
||||
{
|
||||
Page_table * const pt = (Page_table *)
|
||||
(addr_t)Page_table_descriptor::Pa_31_10::masked(_entries[i]);
|
||||
if (pt->empty())
|
||||
{
|
||||
/* we've found an useless page table */
|
||||
Descriptor::invalidate(_entries[i]);
|
||||
base = (void *)pt;
|
||||
s = sizeof(Page_table);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next translation size log2 by area constraints
|
||||
*
|
||||
* \param vo virtual offset within this table
|
||||
* \param s area size
|
||||
*/
|
||||
static unsigned
|
||||
translation_size_l2(addr_t const vo, size_t const s)
|
||||
{
|
||||
off_t const o = vo & Section::VIRT_OFFSET_MASK;
|
||||
if (!o && s >= Section::VIRT_SIZE)
|
||||
return Section::VIRT_SIZE_LOG2;
|
||||
return Page_table::translation_size_l2(o, s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert translations for given area, do not permit displacement
|
||||
*
|
||||
* \param vo virtual offset within this table
|
||||
* \param s area size
|
||||
* \param flags mapping flags
|
||||
*/
|
||||
template <typename ST>
|
||||
void map_core_area(addr_t vo, size_t s, bool io_mem, ST * st)
|
||||
{
|
||||
/* initialize parameters */
|
||||
Page_flags::access_t const flags =
|
||||
Page_flags::map_core_area(io_mem);
|
||||
unsigned tsl2 = translation_size_l2(vo, s);
|
||||
size_t ts = 1 << tsl2;
|
||||
|
||||
/* walk through the area and map all offsets */
|
||||
while (1)
|
||||
{
|
||||
/* map current offset without displacement */
|
||||
if(st->insert_translation(vo, vo, tsl2, flags)) {
|
||||
PDBG("Displacement not permitted");
|
||||
return;
|
||||
}
|
||||
/* update parameters for next round or exit */
|
||||
vo += ts;
|
||||
s = ts < s ? s - ts : 0;
|
||||
if (!s) return;
|
||||
tsl2 = translation_size_l2(vo, s);
|
||||
ts = 1 << tsl2;
|
||||
}
|
||||
}
|
||||
|
||||
} __attribute__((aligned(1<<Section_table::ALIGNM_LOG2)));
|
||||
}
|
||||
|
||||
#endif /* _TLB__ARM_H_ */
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* \brief TLB driver for core
|
||||
* \author Martin Stein
|
||||
* \date 2012-02-22
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _TLB__ARM_V6_H_
|
||||
#define _TLB__ARM_V6_H_
|
||||
|
||||
/* core includes */
|
||||
#include <tlb/arm.h>
|
||||
|
||||
namespace Arm_v6
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/**
|
||||
* First level translation table
|
||||
*/
|
||||
class Section_table : public Arm::Section_table
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Link to second level translation-table
|
||||
*/
|
||||
struct Page_table_descriptor : Arm::Section_table::Page_table_descriptor
|
||||
{
|
||||
/**
|
||||
* Compose descriptor value
|
||||
*/
|
||||
static access_t create(Arm::Page_table * const pt,
|
||||
Section_table *)
|
||||
{
|
||||
return Arm::Section_table::Page_table_descriptor::create(pt);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Section translation descriptor
|
||||
*/
|
||||
struct Section : Arm::Section_table::Section
|
||||
{
|
||||
struct P : Bitfield<9, 1> { }; /* enable ECC */
|
||||
|
||||
/**
|
||||
* Compose descriptor value
|
||||
*/
|
||||
static access_t create(Arm::Page_flags::access_t const flags,
|
||||
addr_t const pa, Section_table *)
|
||||
{
|
||||
return Arm::Section_table::Section::create(flags, pa) |
|
||||
P::bits(0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Insert one atomic translation into this table
|
||||
*
|
||||
* For details see 'Arm::Section_table::insert_translation'
|
||||
*/
|
||||
size_t
|
||||
insert_translation(addr_t const vo, addr_t const pa,
|
||||
size_t const size_log2,
|
||||
Arm::Page_flags::access_t const flags,
|
||||
void * const extra_space = 0) {
|
||||
return Arm::Section_table::
|
||||
insert_translation<Section_table>(vo, pa, size_log2, flags,
|
||||
this, extra_space); }
|
||||
|
||||
/**
|
||||
* Insert translations for given area, do not permit displacement
|
||||
*
|
||||
* \param vo virtual offset within this table
|
||||
* \param s area size
|
||||
* \param io_mem wether the area maps MMIO
|
||||
*/
|
||||
void map_core_area(addr_t vo, size_t s, bool const io_mem) {
|
||||
Arm::Section_table::map_core_area<Section_table>(vo, s, io_mem,
|
||||
this); }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
static typename T::access_t
|
||||
Arm::memory_region_attr(Arm::Page_flags::access_t const flags)
|
||||
{
|
||||
typedef typename T::Tex Tex;
|
||||
typedef typename T::C C;
|
||||
typedef typename T::B B;
|
||||
|
||||
/*
|
||||
* FIXME: upgrade to write-back & write-allocate when !d & c
|
||||
*/
|
||||
if(Arm::Page_flags::D::get(flags))
|
||||
return 0;
|
||||
|
||||
if(Arm::Page_flags::C::get(flags))
|
||||
return Tex::bits(5) | C::bits(0) | B::bits(1);
|
||||
|
||||
return Tex::bits(6) | C::bits(1) | B::bits(0);
|
||||
}
|
||||
|
||||
#endif /* _TLB__ARM_V6_H_ */
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* \brief TLB driver for core
|
||||
* \author Martin Stein
|
||||
* \date 2012-02-22
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _TLB__ARM_V7_H_
|
||||
#define _TLB__ARM_V7_H_
|
||||
|
||||
/* core includes */
|
||||
#include <tlb/arm.h>
|
||||
#include <cpu/arm_v7.h>
|
||||
|
||||
namespace Arm_v7
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/**
|
||||
* ARMv7 first level translation table
|
||||
*/
|
||||
class Section_table : public Arm::Section_table
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Link to second level translation-table
|
||||
*/
|
||||
struct Page_table_descriptor : Arm::Section_table::Page_table_descriptor
|
||||
{
|
||||
struct Ns : Bitfield<3, 1> { }; /* non-secure bit */
|
||||
|
||||
/**
|
||||
* Compose descriptor value
|
||||
*/
|
||||
static access_t create(Arm::Page_table * const pt,
|
||||
Section_table * const st)
|
||||
{
|
||||
return Arm::Section_table::Page_table_descriptor::create(pt) |
|
||||
Ns::bits(!st->secure());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Section translation descriptor
|
||||
*/
|
||||
struct Section : Arm::Section_table::Section
|
||||
{
|
||||
struct Ns : Bitfield<19, 1> { }; /* non-secure bit */
|
||||
|
||||
/**
|
||||
* Compose descriptor value
|
||||
*/
|
||||
static access_t create(Arm::Page_flags::access_t const flags,
|
||||
addr_t const pa,
|
||||
Section_table * const st)
|
||||
{
|
||||
return Arm::Section_table::Section::create(flags, pa) |
|
||||
Ns::bits(!st->secure());
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
/* if this table is dedicated to secure mode or to non-secure mode */
|
||||
bool _secure;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Section_table() : _secure(Arm_v7::Cpu::secure_mode()) { }
|
||||
|
||||
/**
|
||||
* Insert one atomic translation into this table
|
||||
*
|
||||
* For details see 'Arm::Section_table::insert_translation'
|
||||
*/
|
||||
size_t
|
||||
insert_translation(addr_t const vo, addr_t const pa,
|
||||
size_t const size_log2,
|
||||
Arm::Page_flags::access_t const flags,
|
||||
void * const extra_space = 0) {
|
||||
return Arm::Section_table::
|
||||
insert_translation<Section_table>(vo, pa, size_log2, flags,
|
||||
this, extra_space); }
|
||||
|
||||
/**
|
||||
* Insert translations for given area, do not permit displacement
|
||||
*
|
||||
* \param vo virtual offset within this table
|
||||
* \param s area size
|
||||
* \param io_mem wether the area maps MMIO
|
||||
*/
|
||||
void map_core_area(addr_t vo, size_t s, bool const io_mem) {
|
||||
Arm::Section_table::map_core_area<Section_table>(vo, s, io_mem,
|
||||
this); }
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
bool secure() { return _secure; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
static typename T::access_t
|
||||
Arm::memory_region_attr(Arm::Page_flags::access_t const flags)
|
||||
{
|
||||
typedef typename T::Tex Tex;
|
||||
typedef typename T::C C;
|
||||
typedef typename T::B B;
|
||||
|
||||
/*
|
||||
* FIXME: upgrade to write-back & write-allocate when !d & c
|
||||
*/
|
||||
if(Arm::Page_flags::D::get(flags))
|
||||
return Tex::bits(2) | C::bits(0) | B::bits(0);
|
||||
|
||||
if(Arm::Page_flags::C::get(flags))
|
||||
return Tex::bits(5) | C::bits(0) | B::bits(1);
|
||||
|
||||
return Tex::bits(6) | C::bits(1) | B::bits(0);
|
||||
}
|
||||
|
||||
#endif /* _TLB__ARM_V7_H_ */
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* \brief CPU driver for core
|
||||
* \author Martin Stein
|
||||
* \date 2012-04-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _VEA9X4__CPU_H_
|
||||
#define _VEA9X4__CPU_H_
|
||||
|
||||
/* core includes */
|
||||
#include <cpu/cortex_a9.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* CPU driver for core
|
||||
*/
|
||||
class Cpu : public Cortex_a9::Cpu { };
|
||||
}
|
||||
|
||||
#endif /* _VEA9X4__CPU_H_ */
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* \brief Translation lookaside buffer
|
||||
* \author Martin Stein
|
||||
* \date 2012-04-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _VEA9X4__TLB_H_
|
||||
#define _VEA9X4__TLB_H_
|
||||
|
||||
/* core includes */
|
||||
#include <board.h>
|
||||
#include <tlb/arm_v7.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
struct Page_flags : Arm::Page_flags { };
|
||||
|
||||
class Tlb : public Arm_v7::Section_table { };
|
||||
|
||||
/**
|
||||
* Translation lookaside buffer of core
|
||||
*/
|
||||
class Core_tlb : public Tlb
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor - ensures that core never gets a pagefault
|
||||
*/
|
||||
Core_tlb()
|
||||
{
|
||||
map_core_area(Board::RAM_0_BASE, Board::RAM_0_SIZE, 0);
|
||||
map_core_area(Board::RAM_1_BASE, Board::RAM_1_SIZE, 0);
|
||||
map_core_area(Board::RAM_2_BASE, Board::RAM_2_SIZE, 0);
|
||||
map_core_area(Board::RAM_3_BASE, Board::RAM_3_SIZE, 0);
|
||||
map_core_area(Board::MMIO_0_BASE, Board::MMIO_0_SIZE, 1);
|
||||
map_core_area(Board::MMIO_1_BASE, Board::MMIO_1_SIZE, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _VEA9X4__TLB_H_ */
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* \brief Translation lookaside buffer
|
||||
* \author Martin Stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-04-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _VEA9X4__TLB_H_
|
||||
#define _VEA9X4__TLB_H_
|
||||
|
||||
#include <drivers/trustzone.h>
|
||||
|
||||
/* core includes */
|
||||
#include <board.h>
|
||||
#include <tlb/arm_v7.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
struct Page_flags : Arm::Page_flags { };
|
||||
|
||||
class Tlb : public Arm_v7::Section_table { };
|
||||
|
||||
/**
|
||||
* Translation lookaside buffer of core
|
||||
*/
|
||||
class Core_tlb : public Tlb
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor - ensures that core never gets a pagefault
|
||||
*/
|
||||
Core_tlb()
|
||||
{
|
||||
map_core_area(Trustzone::SECURE_RAM_BASE, Trustzone::SECURE_RAM_SIZE, 0);
|
||||
map_core_area(Board::MMIO_0_BASE, Board::MMIO_0_SIZE, 1);
|
||||
map_core_area(Board::MMIO_1_BASE, Board::MMIO_1_SIZE, 1);
|
||||
map_core_area(Trustzone::VM_STATE_BASE, Trustzone::VM_STATE_SIZE, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _VEA9X4__TLB_H_ */
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
#
|
||||
# \brief Download, and unpack the NOVA hypervisor.
|
||||
# \author Stefan Kalkowski
|
||||
# \author Alexander Boettcher
|
||||
# \date 2012-06-04
|
||||
#
|
||||
|
||||
VERBOSE ?= @
|
||||
ECHO = @echo
|
||||
GIT_URL = https://github.com/alex-ab/NOVA.git
|
||||
GIT_REV = HEAD
|
||||
GIT_BRANCH = r4
|
||||
CONTRIB_DIR = contrib
|
||||
PATCHES = $(shell find patches -name '*.patch')
|
||||
|
||||
#
|
||||
# Utility to check if a tool is installed
|
||||
#
|
||||
check_tool = $(if $(shell which $(1)),,$(error Need to have '$(1)' installed.))
|
||||
|
||||
$(call check_tool,git)
|
||||
$(call check_tool,patch)
|
||||
|
||||
#
|
||||
# Print help information by default
|
||||
#
|
||||
help::
|
||||
|
||||
prepare: $(CONTRIB_DIR)
|
||||
|
||||
help::
|
||||
$(ECHO)
|
||||
$(ECHO) "Prepare the NOVA base repository"
|
||||
$(ECHO)
|
||||
$(ECHO) "--- available commands ---"
|
||||
$(ECHO) "prepare - checkout upstream source codes"
|
||||
$(ECHO) "clean - remove upstream source codes"
|
||||
$(ECHO)
|
||||
|
||||
$(CONTRIB_DIR)/.git:
|
||||
$(VERBOSE)git clone $(GIT_URL) $(CONTRIB_DIR)
|
||||
|
||||
.PHONY: $(CONTRIB_DIR)
|
||||
|
||||
$(CONTRIB_DIR): $(CONTRIB_DIR)/.git
|
||||
$(VERBOSE)cd $(CONTRIB_DIR); git pull
|
||||
$(VERBOSE)cd $(CONTRIB_DIR); git reset --hard $(GIT_REV); git checkout $(GIT_BRANCH)
|
||||
$(ECHO) "applying patches to '$(CONTRIB_DIR)/'"
|
||||
$(VERBOSE)for i in $(PATCHES); do patch -d $@ -p1 < $$i; done
|
||||
|
||||
.PHONY: $(CONTRIB_DIR)
|
||||
|
||||
clean::
|
||||
$(VERBOSE)rm -rf $(CONTRIB_DIR)
|
||||
@@ -1,116 +0,0 @@
|
||||
diff --git a/include/sc.hpp b/include/sc.hpp
|
||||
index b849a1f..b480050 100644
|
||||
--- a/include/sc.hpp
|
||||
+++ b/include/sc.hpp
|
||||
@@ -54,7 +54,7 @@ class Sc : public Kobject, public Refcount
|
||||
|
||||
static unsigned prio_top CPULOCAL;
|
||||
|
||||
- void ready_enqueue (uint64);
|
||||
+ void ready_enqueue (uint64, bool use_left = true);
|
||||
void ready_dequeue (uint64);
|
||||
|
||||
static void free (Rcu_elem * a) {
|
||||
@@ -90,7 +90,7 @@ class Sc : public Kobject, public Refcount
|
||||
static void rke_handler();
|
||||
|
||||
NORETURN
|
||||
- static void schedule (bool = false);
|
||||
+ static void schedule (bool = false, bool = true);
|
||||
|
||||
ALWAYS_INLINE
|
||||
static inline void *operator new (size_t) { return cache.alloc(); }
|
||||
diff --git a/include/syscall.hpp b/include/syscall.hpp
|
||||
index 59e4489..5d61f1e 100644
|
||||
--- a/include/syscall.hpp
|
||||
+++ b/include/syscall.hpp
|
||||
@@ -138,6 +138,9 @@ class Sys_ec_ctrl : public Sys_regs
|
||||
public:
|
||||
ALWAYS_INLINE
|
||||
inline unsigned long ec() const { return ARG_1 >> 8; }
|
||||
+
|
||||
+ ALWAYS_INLINE
|
||||
+ inline unsigned op() const { return flags() & 0x3; }
|
||||
};
|
||||
|
||||
class Sys_sc_ctrl : public Sys_regs
|
||||
diff --git a/src/sc.cpp b/src/sc.cpp
|
||||
index 53ff07b..bc4dfa2 100644
|
||||
--- a/src/sc.cpp
|
||||
+++ b/src/sc.cpp
|
||||
@@ -52,7 +52,7 @@ Sc::Sc (Pd *own, Ec *e, unsigned c, Sc *x) : Kobject (SC, static_cast<Space_obj
|
||||
trace (TRACE_SYSCALL, "SC:%p created (EC:%p CPU:%#x P:%#x Q:%#x) - xCPU", this, e, c, prio, budget / (Lapic::freq_bus / 1000));
|
||||
}
|
||||
|
||||
-void Sc::ready_enqueue (uint64 t)
|
||||
+void Sc::ready_enqueue (uint64 t, bool use_left)
|
||||
{
|
||||
assert (prio < priorities);
|
||||
assert (cpu == Cpu::id);
|
||||
@@ -68,13 +68,13 @@ void Sc::ready_enqueue (uint64 t)
|
||||
next = list[prio];
|
||||
prev = list[prio]->prev;
|
||||
next->prev = prev->next = this;
|
||||
- if (left)
|
||||
+ if (use_left && left)
|
||||
list[prio] = this;
|
||||
}
|
||||
|
||||
trace (TRACE_SCHEDULE, "ENQ:%p (%02u) PRIO:%#x TOP:%#x %s", this, left, prio, prio_top, prio > current->prio ? "reschedule" : "");
|
||||
|
||||
- if (prio > current->prio || (this != current && prio == current->prio && left))
|
||||
+ if (prio > current->prio || (this != current && prio == current->prio && (use_left && left)))
|
||||
Cpu::hazard |= HZD_SCHED;
|
||||
|
||||
if (!left)
|
||||
@@ -106,7 +106,7 @@ void Sc::ready_dequeue (uint64 t)
|
||||
tsc = t;
|
||||
}
|
||||
|
||||
-void Sc::schedule (bool suspend)
|
||||
+void Sc::schedule (bool suspend, bool use_left)
|
||||
{
|
||||
Counter::print<1,16> (++Counter::schedule, Console_vga::COLOR_LIGHT_CYAN, SPN_SCH);
|
||||
|
||||
@@ -123,7 +123,7 @@ void Sc::schedule (bool suspend)
|
||||
delete current;
|
||||
else
|
||||
if (EXPECT_TRUE (!suspend))
|
||||
- current->ready_enqueue (t);
|
||||
+ current->ready_enqueue (t, use_left);
|
||||
|
||||
Sc *sc = list[prio_top];
|
||||
assert (sc);
|
||||
diff --git a/src/syscall.cpp b/src/syscall.cpp
|
||||
index 975d4dc..6e792b0 100644
|
||||
--- a/src/syscall.cpp
|
||||
+++ b/src/syscall.cpp
|
||||
@@ -409,6 +412,9 @@ void Ec::sys_ec_ctrl()
|
||||
{
|
||||
Sys_ec_ctrl *r = static_cast<Sys_ec_ctrl *>(current->sys_regs());
|
||||
|
||||
+ switch (r->op()) {
|
||||
+ case 0:
|
||||
+{
|
||||
Capability cap = Space_obj::lookup (r->ec());
|
||||
if (EXPECT_FALSE (cap.obj()->type() != Kobject::EC || !(cap.prm() & 1UL << 0))) {
|
||||
trace (TRACE_ERROR, "%s: Bad EC CAP (%#lx)", __func__, r->ec());
|
||||
@@ -423,6 +429,18 @@ void Ec::sys_ec_ctrl()
|
||||
|
||||
if (Cpu::id != ec->cpu && Ec::remote (ec->cpu) == ec)
|
||||
Lapic::send_ipi (ec->cpu, VEC_IPI_RKE);
|
||||
+
|
||||
+ }
|
||||
+}
|
||||
+ break;
|
||||
+
|
||||
+ case 1:
|
||||
+ current->cont = sys_finish<Sys_regs::SUCCESS>;
|
||||
+ Sc::schedule (false, false);
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ sys_finish<Sys_regs::BAD_PAR>();
|
||||
}
|
||||
|
||||
sys_finish<Sys_regs::SUCCESS>();
|
||||
@@ -1,71 +0,0 @@
|
||||
#
|
||||
# \brief Download, unpack and patch OKL4 source code
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2011-05-02
|
||||
|
||||
DOWNLOAD_DIR = download
|
||||
CONTRIB_DIR = contrib/okl4
|
||||
|
||||
VERBOSE ?= @
|
||||
ECHO = @echo
|
||||
OKL4_VERSION = okl4_2.1.1-patch.9
|
||||
OKL4_ARCHIVE = $(OKL4_VERSION).tar.gz
|
||||
OKL4_URI = http://wiki.ok-labs.com/downloads/release-2.1.1-patch.9/$(OKL4_ARCHIVE)
|
||||
PATCHES = $(shell find patches -name *.patch)
|
||||
SHELL = bash
|
||||
|
||||
#
|
||||
# Utility to check if a tool is installed
|
||||
#
|
||||
check_tool = $(if $(shell which $(1)),,$(error Need to have '$(1)' installed.))
|
||||
|
||||
$(call check_tool,wget)
|
||||
$(call check_tool,patch)
|
||||
$(call check_tool,sed)
|
||||
|
||||
#
|
||||
# Determine python version to use for OKL4's elfweaver
|
||||
#
|
||||
PYTHON2 := $(notdir $(lastword $(shell which python2 python2.{4,5,6,7,8})))
|
||||
ifeq ($(PYTHON2),)
|
||||
prepare: python_not_installed
|
||||
python_not_installed:
|
||||
$(ECHO) "Error: OKL4 needs Python 2 to be installed"
|
||||
@false;
|
||||
endif
|
||||
|
||||
#
|
||||
# Print help information by default
|
||||
#
|
||||
help:
|
||||
$(ECHO)
|
||||
$(ECHO) "Prepare the OKL4 base repository"
|
||||
$(ECHO)
|
||||
$(ECHO) "--- available commands ---"
|
||||
$(ECHO) "prepare - download and extract the OKL4 source code"
|
||||
$(ECHO) "clean - clean everything except downloaded archives"
|
||||
$(ECHO) "cleanall - clean everything including downloaded archives"
|
||||
$(ECHO)
|
||||
|
||||
$(DOWNLOAD_DIR)/$(OKL4_ARCHIVE):
|
||||
$(ECHO) "downloading source code to '$(DOWNLOAD_DIR)/'"
|
||||
$(VERBOSE)mkdir -p $(DOWNLOAD_DIR)
|
||||
$(VERBOSE)wget -c $(OKL4_URI) -O $@
|
||||
|
||||
$(CONTRIB_DIR): clean
|
||||
|
||||
$(CONTRIB_DIR): $(DOWNLOAD_DIR)/$(OKL4_ARCHIVE)
|
||||
$(ECHO) "unpacking source code to '$(CONTRIB_DIR)/'"
|
||||
$(VERBOSE)tar xzf $<
|
||||
$(VERBOSE)mv $(OKL4_VERSION) $@
|
||||
$(ECHO) "applying patches to '$(CONTRIB_DIR)/'"
|
||||
$(VERBOSE)for i in $(PATCHES); do patch -d $@ -p1 < $$i; done
|
||||
$(VERBOSE)sed -i "s/env python/env $(PYTHON2)/" $(CONTRIB_DIR)/tools/pyelf/elfweaver
|
||||
|
||||
prepare: $(CONTRIB_DIR)
|
||||
|
||||
clean:
|
||||
$(VERBOSE)rm -rf $(CONTRIB_DIR)
|
||||
|
||||
cleanall: clean
|
||||
$(VERBOSE)rm -rf $(DOWNLOAD_DIR)
|
||||
@@ -1,67 +0,0 @@
|
||||
#
|
||||
# \brief Checkout Pistachio and additional needed tools (kickstart)
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2011-07-15
|
||||
#
|
||||
|
||||
VERBOSE = @
|
||||
ECHO = @echo
|
||||
GIT_URI = https://github.com/l4ka/pistachio.git
|
||||
GIT_REV = 76bac3d926dc707c6a3243b38c1505d2b5b6537b
|
||||
CONTRIB_DIR = contrib
|
||||
SHELL = bash
|
||||
PATCHES = $(shell find patches -name *.patch)
|
||||
|
||||
#
|
||||
# Utility to check if a tool is installed
|
||||
#
|
||||
check_tool = $(if $(shell which $(1)),,$(error Need to have '$(1)' installed.))
|
||||
|
||||
$(call check_tool,git)
|
||||
$(call check_tool,patch)
|
||||
$(call check_tool,sed)
|
||||
$(call check_tool,autoheader)
|
||||
$(call check_tool,autoconf)
|
||||
|
||||
#
|
||||
# Determine python version to use for CML2
|
||||
#
|
||||
PYTHON2 := $(notdir $(lastword $(shell which python2 $(addprefix python2.,4 5 6 7 8))))
|
||||
ifeq ($(PYTHON2),)
|
||||
prepare: python_not_installed
|
||||
python_not_installed:
|
||||
$(ECHO) "Error: CML2 Configuration System needs Python 2 to be installed"
|
||||
@false;
|
||||
endif
|
||||
|
||||
#
|
||||
# Print help information by default
|
||||
#
|
||||
help::
|
||||
$(ECHO)
|
||||
$(ECHO) "Check out upstream source code of Pistachio"
|
||||
$(ECHO)
|
||||
$(ECHO) "The source code will be located at the '$(CONTRIB_DIR)/' directory."
|
||||
$(ECHO)
|
||||
$(ECHO) "--- available commands ---"
|
||||
$(ECHO) "prepare - checkout upstream source codes"
|
||||
$(ECHO) "clean - remove upstream source codes"
|
||||
$(ECHO)
|
||||
|
||||
$(CONTRIB_DIR):
|
||||
$(VERBOSE)git clone $(GIT_URI) contrib
|
||||
|
||||
prepare: $(CONTRIB_DIR)
|
||||
$(VERBOSE)cd $(CONTRIB_DIR); git fetch; git reset --hard $(GIT_REV)
|
||||
$(ECHO) "applying patches to '$(CONTRIB_DIR)/'"
|
||||
$(VERBOSE)for i in $(PATCHES); do patch -d $(CONTRIB_DIR) -p1 < $$i; done
|
||||
@# use GCC front end for as linker for the pistachio user land
|
||||
$(VERBOSE)sed -i "/LD=/s/^.*$$/LD=\$$(CC)/" $(CONTRIB_DIR)/user/config.mk.in
|
||||
@# add '-Wl,' prefix to '-melf_*' linker options
|
||||
$(VERBOSE)sed -i "s/-melf_/-Wl,-melf_/" `grep -rl melf_ $(CONTRIB_DIR)/user`
|
||||
$(VERBOSE)for i in cmlcompile.py cmlconfigure.py configtrans.py; do \
|
||||
sed -i "s/env python/env $(PYTHON2)/" $(CONTRIB_DIR)/contrib/cml2/$$i; done
|
||||
$(VERBOSE)cd $(CONTRIB_DIR)/user; autoheader; autoconf;
|
||||
|
||||
clean::
|
||||
$(VERBOSE)rm -rf $(CONTRIB_DIR)
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* \brief Atomic operations for ARM
|
||||
* \author Norman Feske
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2007-04-28
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2007-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__ARM__CPU__ATOMIC_H_
|
||||
#define _INCLUDE__ARM__CPU__ATOMIC_H_
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/**
|
||||
* Atomic compare and exchange
|
||||
*
|
||||
* This function compares the value at dest with cmp_val.
|
||||
* If both values are equal, dest is set to new_val. If
|
||||
* both values are different, the value at dest remains
|
||||
* unchanged.
|
||||
*
|
||||
* \return 1 if the value was successfully changed to new_val,
|
||||
* 0 if cmp_val and the value at dest differ.
|
||||
*/
|
||||
inline int cmpxchg(volatile int *dest, int cmp_val, int new_val)
|
||||
{
|
||||
unsigned long equal, not_exclusive;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"@ cmpxchg\n"
|
||||
" 1: \n"
|
||||
" ldrex %0, [%2] \n"
|
||||
" cmp %0, %3 \n"
|
||||
" bne 2f \n"
|
||||
" strexeq %0, %4, [%2]\n"
|
||||
" teqeq %0, #0 \n"
|
||||
" bne 1b \n"
|
||||
" moveq %1, #1 \n"
|
||||
" 2: \n"
|
||||
" movne %1, #0 \n"
|
||||
: "=&r" (not_exclusive), "=&r" (equal)
|
||||
: "r" (dest), "r" (cmp_val), "r" (new_val)
|
||||
: "cc");
|
||||
return equal && !not_exclusive;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__ARM__CPU__ATOMIC_H_ */
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* \brief Allocator for core-local memory
|
||||
* \author Norman Feske
|
||||
* \date 2009-10-12
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
|
||||
/* local includes */
|
||||
#include <core_mem_alloc.h>
|
||||
#include <util.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
static const bool verbose_core_mem_alloc = false;
|
||||
|
||||
|
||||
bool Core_mem_allocator::Mapped_mem_allocator::alloc(size_t size, void **out_addr)
|
||||
{
|
||||
/* try to allocate block in cores already mapped virtual address ranges */
|
||||
if (_alloc.alloc(size, out_addr))
|
||||
return true;
|
||||
|
||||
/* there is no sufficient space in core's mapped virtual memory, expansion needed */
|
||||
size_t page_rounded_size = (size + get_page_size() - 1) & get_page_mask();
|
||||
void *phys_addr = 0, *virt_addr = 0;
|
||||
|
||||
/* allocate physical pages */
|
||||
if (!_phys_alloc->alloc(page_rounded_size, &phys_addr)) {
|
||||
PERR("Could not allocate physical memory region of size %zu\n", page_rounded_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* allocate range in core's virtual address space */
|
||||
if (!_virt_alloc->alloc(page_rounded_size, &virt_addr)) {
|
||||
PERR("Could not allocate virtual address range in core of size %zu\n", page_rounded_size);
|
||||
|
||||
/* revert physical allocation */
|
||||
_phys_alloc->free(phys_addr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (verbose_core_mem_alloc)
|
||||
printf("added core memory block of %zu bytes at virt=%p phys=%p\n",
|
||||
page_rounded_size, virt_addr, phys_addr);
|
||||
|
||||
/* make physical page accessible at the designated virtual address */
|
||||
_map_local((addr_t)virt_addr, (addr_t)phys_addr, get_page_size_log2());
|
||||
|
||||
/* add new range to core's allocator for mapped virtual memory */
|
||||
_alloc.add_range((addr_t)virt_addr, page_rounded_size);
|
||||
|
||||
/* now that we have added enough memory, try again... */
|
||||
return _alloc.alloc(size, out_addr);
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
/*
|
||||
* \brief Allocator infrastructure for core
|
||||
* \author Norman Feske
|
||||
* \date 2009-10-12
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__CORE_MEM_ALLOC_H_
|
||||
#define _CORE__INCLUDE__CORE_MEM_ALLOC_H_
|
||||
|
||||
#include <base/lock.h>
|
||||
#include <base/sync_allocator.h>
|
||||
#include <base/allocator_avl.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/**
|
||||
* Allocators for physical memory, core's virtual address space,
|
||||
* and core-local memory. The interface of this class is thread safe.
|
||||
*/
|
||||
class Core_mem_allocator : public Allocator
|
||||
{
|
||||
public:
|
||||
|
||||
typedef Synchronized_range_allocator<Allocator_avl> Phys_allocator;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Unsynchronized allocator for core-mapped memory
|
||||
*
|
||||
* This is an allocator of core-mapped memory. It is meant to be used as
|
||||
* meta-data allocator for the other allocators and as back end for core's
|
||||
* synchronized memory allocator.
|
||||
*/
|
||||
class Mapped_mem_allocator : public Allocator
|
||||
{
|
||||
private:
|
||||
|
||||
Allocator_avl _alloc;
|
||||
Range_allocator *_phys_alloc;
|
||||
Range_allocator *_virt_alloc;
|
||||
|
||||
/**
|
||||
* Initial chunk to populate the core mem allocator
|
||||
*
|
||||
* This chunk is used at platform initialization time.
|
||||
*/
|
||||
char _initial_chunk[16*1024];
|
||||
|
||||
/**
|
||||
* Map physical page locally to specified virtual address
|
||||
*
|
||||
* \param virt_addr core-local address
|
||||
* \param phys_addr physical memory address
|
||||
* \param size_log2 size of memory block to map
|
||||
* \return true on success
|
||||
*/
|
||||
bool _map_local(addr_t virt_addr, addr_t phys_addr, unsigned size_log2);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param phys_alloc allocator of physical memory
|
||||
* \param virt_alloc allocator of core-local virtual memory ranges
|
||||
*/
|
||||
Mapped_mem_allocator(Range_allocator *phys_alloc,
|
||||
Range_allocator *virt_alloc)
|
||||
: _alloc(0), _phys_alloc(phys_alloc), _virt_alloc(virt_alloc)
|
||||
{
|
||||
_alloc.add_range((addr_t)_initial_chunk, sizeof(_initial_chunk));
|
||||
}
|
||||
|
||||
|
||||
/*************************
|
||||
** Allocator interface **
|
||||
*************************/
|
||||
|
||||
bool alloc(size_t size, void **out_addr);
|
||||
void free(void *addr, size_t size) { _alloc.free(addr, size); }
|
||||
size_t consumed() { return _phys_alloc->consumed(); }
|
||||
size_t overhead(size_t size) { return _phys_alloc->overhead(size); }
|
||||
|
||||
bool need_size_for_free() const override {
|
||||
return _phys_alloc->need_size_for_free(); }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Lock used for synchronization of all operations on the
|
||||
* embedded allocators.
|
||||
*/
|
||||
Lock _lock;
|
||||
|
||||
/**
|
||||
* Synchronized allocator of physical memory ranges
|
||||
*
|
||||
* This allocator must only be used to allocate memory
|
||||
* ranges at page granularity.
|
||||
*/
|
||||
Phys_allocator _phys_alloc;
|
||||
|
||||
/**
|
||||
* Synchronized allocator of core's virtual memory ranges
|
||||
*
|
||||
* This allocator must only be used to allocate memory
|
||||
* ranges at page granularity.
|
||||
*/
|
||||
Phys_allocator _virt_alloc;
|
||||
|
||||
/**
|
||||
* Unsynchronized core-mapped memory allocator
|
||||
*
|
||||
* This allocator is internally used within this class for
|
||||
* allocating meta data for the other allocators. It is not
|
||||
* synchronized to avoid nested locking. The lock-guarded
|
||||
* access to this allocator from the outer world is
|
||||
* provided via the 'Allocator' interface implemented by
|
||||
* 'Core_mem_allocator'. The allocator works at byte
|
||||
* granularity.
|
||||
*/
|
||||
Mapped_mem_allocator _mem_alloc;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Core_mem_allocator() :
|
||||
_phys_alloc(&_lock, &_mem_alloc),
|
||||
_virt_alloc(&_lock, &_mem_alloc),
|
||||
_mem_alloc(_phys_alloc.raw(), _virt_alloc.raw())
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Access physical-memory allocator
|
||||
*/
|
||||
Phys_allocator *phys_alloc() { return &_phys_alloc; }
|
||||
|
||||
/**
|
||||
* Access core's virtual-memory allocator
|
||||
*/
|
||||
Phys_allocator *virt_alloc() { return &_virt_alloc; }
|
||||
|
||||
|
||||
/*************************
|
||||
** Allocator interface **
|
||||
*************************/
|
||||
|
||||
bool alloc(size_t size, void **out_addr)
|
||||
{
|
||||
Lock::Guard lock_guard(_lock);
|
||||
return _mem_alloc.alloc(size, out_addr);
|
||||
}
|
||||
|
||||
void free(void *addr, size_t size)
|
||||
{
|
||||
Lock::Guard lock_guard(_lock);
|
||||
_mem_alloc.free(addr, size);
|
||||
}
|
||||
|
||||
size_t consumed() { return _phys_alloc.consumed(); }
|
||||
size_t overhead(size_t size) { return _phys_alloc.overhead(size); }
|
||||
|
||||
bool need_size_for_free() const override {
|
||||
return _phys_alloc.need_size_for_free(); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__CORE_MEM_ALLOC_H_ */
|
||||
@@ -1,67 +0,0 @@
|
||||
#
|
||||
# \brief Fetch and patch iPXE source code
|
||||
# \author Stefan Kalkowski
|
||||
# \author Christian Helmuth
|
||||
# \date 2011-08-12
|
||||
#
|
||||
|
||||
VERBOSE ?= @
|
||||
ECHO = @echo
|
||||
GIT_URL = http://git.ipxe.org/ipxe.git
|
||||
GIT_REV = c4bce43c3c4d3c5ebb2d926b58ad16dc9642c19d
|
||||
CONTRIB_DIR = contrib
|
||||
PATCH_FILE = patches/dde_ipxe.patch
|
||||
|
||||
#
|
||||
# Utility to check if a tool is installed
|
||||
#
|
||||
check_tool = $(if $(shell which $(1)),,$(error Need to have '$(1)' installed.))
|
||||
|
||||
$(call check_tool,git)
|
||||
$(call check_tool,patch)
|
||||
|
||||
#
|
||||
# Print help information by default
|
||||
#
|
||||
help:
|
||||
$(ECHO)
|
||||
$(ECHO) "Prepare the dde_ipxe repository"
|
||||
$(ECHO)
|
||||
$(ECHO) "--- available commands ---"
|
||||
$(ECHO) "prepare - fetch and patch iPXE source code"
|
||||
$(ECHO) "clean - revert patch from iPXE souce code"
|
||||
$(ECHO) "cleanall - remove iPXE souce code"
|
||||
$(ECHO) "update-patch - updates patch for iPXE source code"
|
||||
$(ECHO)
|
||||
|
||||
$(CONTRIB_DIR)/.git:
|
||||
$(VERBOSE)git clone $(GIT_URL) $(CONTRIB_DIR)
|
||||
|
||||
fetch: $(CONTRIB_DIR)/.git
|
||||
$(VERBOSE)cd $(CONTRIB_DIR); git fetch origin
|
||||
|
||||
prepare: fetch clean
|
||||
$(ECHO) "apply patch to '$(CONTRIB_DIR)/'"
|
||||
$(VERBOSE)patch -p1 -d $(CONTRIB_DIR) -i $(realpath $(PATCH_FILE))
|
||||
$(ECHO)
|
||||
$(ECHO) "Preparation completed!"
|
||||
$(ECHO) "Hint: don't forget to put '$(shell pwd)' "
|
||||
$(ECHO) " as a repository into your build.conf"
|
||||
$(ECHO)
|
||||
|
||||
update-patch:
|
||||
$(ECHO) "producing a new diff and save it to '$(PATCH_FILE)'"
|
||||
$(VERBOSE)(cd $(CONTRIB_DIR); LC_COLLATE=C git diff) > $(PATCH_FILE) || true
|
||||
# $(VERBOSE)(cd $(CONTRIB_DIR); LC_COLLATE=C git diff) \
|
||||
# | sed "s/\(^--- [^\t]*\).*/\\1/" \
|
||||
# | sed "s/\(^+++ [^\t]*\).*/\\1/" \
|
||||
# > $(PATCH_FILE) || true
|
||||
|
||||
clean:
|
||||
$(VERBOSE)cd $(CONTRIB_DIR); git reset --hard $(GIT_REV)
|
||||
$(VERBOSE)cd $(CONTRIB_DIR); git ls-files -o | xargs rm -rf
|
||||
|
||||
cleanall:
|
||||
$(VERBOSE)rm -rf $(CONTRIB_DIR)
|
||||
|
||||
.PHONY: cleanall clean update-patch prepare fetch help
|
||||
@@ -1,4 +0,0 @@
|
||||
include $(REP_DIR)/lib/mk/dde_ipxe_nic.inc
|
||||
|
||||
INC_DIR += $(CONTRIB_DIR)/arch/i386/include \
|
||||
$(CONTRIB_DIR)/arch/i386/include/pcbios
|
||||
@@ -1,7 +0,0 @@
|
||||
include $(REP_DIR)/lib/mk/dde_ipxe_nic.inc
|
||||
|
||||
INC_DIR += $(CONTRIB_DIR)/arch/x86_64/include \
|
||||
$(CONTRIB_DIR)/arch/x86_64/include/efi
|
||||
|
||||
# take remaining parts from i386
|
||||
INC_DIR += $(CONTRIB_DIR)/arch/i386/include
|
||||
@@ -1,74 +0,0 @@
|
||||
#
|
||||
# \brief Download integrate Linux kernel sources with Genode
|
||||
# \author Norman Feske
|
||||
# \date 2012-01-28
|
||||
|
||||
CONTRIB_DIR = contrib
|
||||
DOWNLOAD_DIR = download
|
||||
VERBOSE ?= @
|
||||
ECHO = @echo
|
||||
PATCHES := $(shell find patches -name \*.patch)
|
||||
|
||||
LINUX = linux-3.9
|
||||
LINUX_TGZ = $(LINUX).tar.gz
|
||||
LINUX_URL = http://www.kernel.org/pub/linux/kernel/v3.x/$(LINUX_TGZ)
|
||||
|
||||
# Raspberry Pi
|
||||
DWC_OTG_GIT_URL := https://github.com/nfeske/dwc_otg.git
|
||||
DWC_OTG_GIT_BRANCH := r1
|
||||
|
||||
#
|
||||
#
|
||||
# Utility to check if a tool is installed
|
||||
#
|
||||
check_tool = $(if $(shell which $(1)),,$(error Need to have '$(1)' installed.))
|
||||
|
||||
$(call check_tool,wget)
|
||||
$(call check_tool,patch)
|
||||
|
||||
#
|
||||
# Print help information by default
|
||||
#
|
||||
help:
|
||||
$(ECHO)
|
||||
$(ECHO) "Download integrate Linux kernel sources with Genode"
|
||||
$(ECHO)
|
||||
$(ECHO) "--- available commands ---"
|
||||
$(ECHO) "prepare - download and integrate Linux source code"
|
||||
$(ECHO) "clean - remove contib sources except downloaded archives"
|
||||
$(ECHO) "cleanall - remove contib sources and downloaded archives"
|
||||
$(ECHO)
|
||||
|
||||
prepare: clean $(CONTRIB_DIR)/.prepared
|
||||
|
||||
prepare_rpi: prepare
|
||||
$(VERBOSE)cd $(CONTRIB_DIR)/drivers/usb/host; \
|
||||
git clone $(DWC_OTG_GIT_URL) dwc_otg
|
||||
$(VERBOSE)cd $(CONTRIB_DIR)/drivers/usb/host/dwc_otg; \
|
||||
git reset --hard HEAD && git checkout $(DWC_OTG_GIT_BRANCH)
|
||||
|
||||
$(CONTRIB_DIR)/.prepared: Makefile
|
||||
$(CONTRIB_DIR)/.prepared: $(DOWNLOAD_DIR)/$(LINUX_TGZ)
|
||||
$(ECHO) "extracting source code to '$(CONTRIB_DIR)'"
|
||||
$(VERBOSE)tar xfz $< --transform "s{$(LINUX){$(CONTRIB_DIR){" --files-from files.list
|
||||
$(VERBOSE)tar xfz $< --transform "s{$(LINUX){$(CONTRIB_DIR)/lxip{" --files-from lxip_header.list
|
||||
$(VERBOSE)touch $@
|
||||
$(ECHO) "applying patches to '$(CONTRIB_DIR)/'"
|
||||
$(VERBOSE)for i in $(PATCHES); do patch -d $(CONTRIB_DIR) -p1 < $$i; done
|
||||
$(VERBOSE)touch $(CONTRIB_DIR)/drivers/usb/dwc3/gadget.h
|
||||
$(VERBOSE)touch $(CONTRIB_DIR)/drivers/usb/dwc3/debug.h
|
||||
|
||||
|
||||
$(DOWNLOAD_DIR):
|
||||
$(VERBOSE)mkdir -p $@
|
||||
|
||||
$(DOWNLOAD_DIR)/$(LINUX_TGZ): $(DOWNLOAD_DIR)
|
||||
$(ECHO) "downloading source code to '$@'"
|
||||
$(VERBOSE)cd $(DOWNLOAD_DIR); wget -c $(LINUX_URL)
|
||||
$(VERBOSE)touch $@
|
||||
|
||||
clean:
|
||||
$(VERBOSE)rm -rf $(CONTRIB_DIR)
|
||||
|
||||
cleanall: clean
|
||||
$(VERBOSE)rm -rf $(DOWNLOAD_DIR)
|
||||
@@ -1,9 +0,0 @@
|
||||
SRC_C += $(addprefix usb/host/,pci-quirks.c uhci-hcd.c ehci-pci.c)
|
||||
|
||||
include $(REP_DIR)/lib/mk/usb.inc
|
||||
|
||||
CC_OPT += -DCONFIG_PCI -DCONFIG_USB_EHCI_PCI=1 -DCONFIG_USB_XHCI_HCD=0
|
||||
INC_DIR += $(LIB_INC_DIR)/x86_64 $(LIB_INC_DIR)/x86
|
||||
SRC_CC += pci_driver.cc platform.cc
|
||||
|
||||
vpath platform.cc $(LIB_DIR)/x86
|
||||
@@ -1,20 +0,0 @@
|
||||
diff -r 6978f825431c drivers/usb/host/xhci-plat.c
|
||||
--- a/drivers/usb/host/xhci-plat.c Thu May 16 15:54:34 2013 +0200
|
||||
+++ b/drivers/usb/host/xhci-plat.c Thu May 16 16:41:46 2013 +0200
|
||||
@@ -25,6 +25,16 @@
|
||||
* dev struct in order to setup MSI
|
||||
*/
|
||||
xhci->quirks |= XHCI_BROKEN_MSI;
|
||||
+
|
||||
+#ifdef DWC3_QUIRK
|
||||
+ /*
|
||||
+ * DWC3 controller
|
||||
+ * One will see 'dev_error: ERROR Transfer event TRB DMA ptr not part of
|
||||
+ * current TD' and last message was short (ep_ring->last_td_was_short, in
|
||||
+ * xhci-ring.c
|
||||
+ */
|
||||
+ xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
|
||||
+#endif
|
||||
}
|
||||
|
||||
/* called during probe() after chip reset completes */
|
||||
124
dde_oss/Makefile
124
dde_oss/Makefile
@@ -1,124 +0,0 @@
|
||||
#
|
||||
# \brief Download and setup OSS sources
|
||||
# \author Sebastian Sumpf
|
||||
# \date 2012-08-30
|
||||
|
||||
CONTRIB_DIR = contrib
|
||||
DOWNLOAD_DIR = download
|
||||
VERBOSE ?= @
|
||||
ECHO = @echo
|
||||
CC ?= gcc
|
||||
PATCHES := $(shell find patches -name \*.patch)
|
||||
|
||||
OSS = oss-v4.2-build2006-src-bsd
|
||||
OSS_TBZ2 = $(OSS).tar.bz2
|
||||
OSS_URL = http://www.4front-tech.com/developer/sources/stable/bsd/$(OSS_TBZ2)
|
||||
|
||||
|
||||
# needed for preparation
|
||||
CONTENT_SETUP = $(addprefix setup/,srcconf.c srcconf_freebsd.inc srcconf_vxworks.inc gen_driver_freebsd.inc)
|
||||
CONTENT += $(CONTENT_SETUP)
|
||||
|
||||
# oss framework
|
||||
CONTENT_FRAMEWORK = $(addprefix kernel/framework/include/,oss_config.h oss_memblk.h \
|
||||
oss_version.h audio_core.h mixer_core.h oss_calls.h \
|
||||
internal.h oss_pci.h spdif.h midi_core.h grc3.h ac97.h \
|
||||
ossddk/oss_exports.h ossddk/oss_limits.PHh ossddk/ossddk.h)
|
||||
CONTENT += $(CONTENT_FRAMEWORK)
|
||||
|
||||
# oss core
|
||||
CONTENT_CORE = $(addprefix kernel/framework/osscore/,oss_memblk.c oss_core_options.c \
|
||||
oss_core_services.c)
|
||||
CONTENT += $(CONTENT_CORE)
|
||||
CONTENT += include/soundcard.h kernel/drv/.config
|
||||
|
||||
# audio core
|
||||
CONTENT_AUDIO = $(addprefix kernel/framework/audio/,oss_audio_core.c oss_spdif.c oss_audiofmt.c \
|
||||
ulaw.h audiocnv.inc oss_grc3.c fltdata2_h.inc \
|
||||
grc3code.inc grc3inc.inc)
|
||||
CONTENT += $(CONTENT_AUDIO)
|
||||
|
||||
# mixer core
|
||||
CONTENT_MIXER = $(addprefix kernel/framework/mixer/,oss_mixer_core.c mixerdefs.h)
|
||||
CONTENT += $(CONTENT_MIXER)
|
||||
|
||||
# vmixer core
|
||||
CONTENT_VMIX = $(addprefix kernel/framework/vmix_core/,vmix_core.c vmix_input.c vmix.h db_scale.h \
|
||||
vmix_import.inc vmix_import_int.inc \
|
||||
rec_export.inc rec_export_int.inc \
|
||||
vmix_output.c outexport.inc outexport_int.inc \
|
||||
playmix.inc playmix_int.inc playmix_src.inc)
|
||||
CONTENT += $(CONTENT_VMIX)
|
||||
|
||||
# midi core
|
||||
CONTENT_MIDI = $(addprefix kernel/framework/midi/,oss_midi_core.c oss_midi_timers.c oss_midi_mapper.c \
|
||||
oss_midi_queue.c)
|
||||
CONTENT += $(CONTENT_MIDI)
|
||||
|
||||
# AC97 core
|
||||
CONTENT += kernel/framework/ac97
|
||||
|
||||
# drivers
|
||||
CONTENT_DRV += oss_ich oss_hdaudio oss_audiopci
|
||||
CONTENT += $(addprefix kernel/drv/,$(CONTENT_DRV))
|
||||
|
||||
|
||||
#
|
||||
# Utility to check if a tool is installed
|
||||
#
|
||||
check_tool = $(if $(shell which $(1)),,$(error Need to have '$(1)' installed.))
|
||||
|
||||
$(call check_tool,wget)
|
||||
$(call check_tool,patch)
|
||||
|
||||
#
|
||||
# Print help information by default
|
||||
#
|
||||
help:
|
||||
$(ECHO)
|
||||
$(ECHO) "Download integrate OSS sources with Genode"
|
||||
$(ECHO)
|
||||
$(ECHO) "--- available commands ---"
|
||||
$(ECHO) "prepare - download and integrate OSS source code"
|
||||
$(ECHO) "clean - remove contib sources except downloaded archives"
|
||||
$(ECHO) "cleanall - remove contib sources and downloaded archives"
|
||||
$(ECHO)
|
||||
|
||||
#
|
||||
# Build and execute 'srcconf' utility, build 'devices.list'
|
||||
#
|
||||
setup:
|
||||
$(VERBOSE)ln -sf srcconf_freebsd.inc $(CONTRIB_DIR)/setup/srcconf_linux.inc
|
||||
$(VERBOSE)ln -sf gen_driver_freebsd.inc $(CONTRIB_DIR)/setup/gen_driver_linux.inc
|
||||
$(VERBOSE)mkdir -p $(CONTRIB_DIR)/kernel/framework/include
|
||||
$(VERBOSE)mkdir -p $(CONTRIB_DIR)/kernel/OS/Linux
|
||||
$(VERBOSE)$(CC) -g -I$(CONTRIB_DIR)/setup -o srcconf $(CONTRIB_DIR)/setup/srcconf.c
|
||||
$(VERBOSE)cat `find $(CONTRIB_DIR)/kernel/drv -name .devices`| grep -v '^#' > $(CONTRIB_DIR)/devices.list
|
||||
$(VERBOSE)cd $(CONTRIB_DIR) && ../srcconf
|
||||
$(VERBOSE)cd $(CONTRIB_DIR)/target/build ; for f in *.c; do mv $$f pci_$$f; done
|
||||
$(VERBOSE)rm srcconf
|
||||
|
||||
prepare: $(CONTRIB_DIR)/.prepared setup
|
||||
|
||||
$(CONTRIB_DIR)/.prepared: Makefile
|
||||
$(CONTRIB_DIR)/.prepared: $(DOWNLOAD_DIR)/$(OSS_TBZ2)
|
||||
$(ECHO) "extracting source code to '$(CONTRIB_DIR)'"
|
||||
$(VERBOSE)tar xfj $< --transform "s/$(OSS)/$(CONTRIB_DIR)/" $(addprefix $(OSS)/,$(CONTENT))
|
||||
$(VERBOSE)touch $@
|
||||
$(ECHO) "applying patches to '$(CONTRIB_DIR)/'"
|
||||
$(VERBOSE)for i in $(PATCHES); do patch -d $(CONTRIB_DIR) -p1 < $$i; done
|
||||
|
||||
|
||||
$(DOWNLOAD_DIR):
|
||||
$(VERBOSE)mkdir -p $@
|
||||
|
||||
$(DOWNLOAD_DIR)/$(OSS_TBZ2): $(DOWNLOAD_DIR)
|
||||
$(ECHO) "downloading source code to '$@'"
|
||||
$(VERBOSE)cd $(DOWNLOAD_DIR); wget -c $(OSS_URL)
|
||||
$(VERBOSE)touch $@
|
||||
|
||||
clean:
|
||||
$(VERBOSE)rm -rf $(CONTRIB_DIR)
|
||||
|
||||
cleanall: clean
|
||||
$(VERBOSE)rm -rf $(DOWNLOAD_DIR)
|
||||
@@ -1,67 +0,0 @@
|
||||
#
|
||||
# \brief Checkout rump kernel source code
|
||||
# \author Sebastian Sumpf
|
||||
# \date 2013-11-27
|
||||
#
|
||||
|
||||
VERBOSE ?= @
|
||||
CONTRIB_DIR = contrib
|
||||
ECHO = @echo
|
||||
PATCHES := $(shell find patches -name \*.patch)
|
||||
|
||||
GIT_RUMP_URI = https://github.com/anttikantee/buildrump.sh.git
|
||||
GIT_RUMP_COMMIT = d604845baafa110945cb54a2d9607e6f435c6027
|
||||
|
||||
GIT_LIBS_URI = https://github.com/anttikantee/xen-nblibc.git
|
||||
GIT_LIBS_COMMIT = b86122315f338042d06ad83ac5bd763a5dbd0c00
|
||||
|
||||
GIT_NETBSD_COMMIT = ff70642c9d7a8fb4b3242b30de2efc1fd8ad9ad4
|
||||
|
||||
RUMP_SRC = src
|
||||
|
||||
#
|
||||
# Utility to check if a tool is installed
|
||||
#
|
||||
check_tool = $(if $(shell which $(1)),,$(error Need to have '$(1)' installed.))
|
||||
|
||||
$(call check_tool,git)
|
||||
|
||||
$(CONTRIB_DIR)/.git:
|
||||
$(VERBOSE) git clone $(GIT_RUMP_URI) $(CONTRIB_DIR)
|
||||
|
||||
$(CONTRIB_DIR)/nblibs:
|
||||
$(VERBOSE) git clone $(GIT_LIBS_URI) $(CONTRIB_DIR)/nblibs
|
||||
cd $(CONTRIB_DIR)/nblibs ; ln -sf ../$(RUMP_SRC)/common
|
||||
|
||||
$(CONTRIB_DIR)/$(RUMP_SRC):
|
||||
$(VERBOSE) cd $(CONTRIB_DIR); ./buildrump.sh -s $(RUMP_SRC) checkout
|
||||
$(VERBOSE) cd $(CONTRIB_DIR)/src; git reset --hard $(GIT_NETBSD_COMMIT)
|
||||
|
||||
commit:
|
||||
$(VERBOSE) cd $(CONTRIB_DIR); git fetch origin
|
||||
$(VERBOSE) cd $(CONTRIB_DIR); git reset --hard $(GIT_RUMP_COMMIT)
|
||||
$(VERBOSE) cd $(CONTRIB_DIR)/nblibs; git fetch origin
|
||||
$(VERBOSE) cd $(CONTRIB_DIR)/nblibs; git reset --hard $(GIT_LIBS_COMMIT)
|
||||
$(ECHO) "applying patches to '$(CONTRIB_DIR)/'"
|
||||
$(VERBOSE)for i in $(PATCHES); do patch -N -d $(CONTRIB_DIR) -p1 < $$i; done
|
||||
|
||||
prepare: $(CONTRIB_DIR)/.git $(CONTRIB_DIR)/nblibs $(CONTRIB_DIR)/$(RUMP_SRC) commit
|
||||
$(VERBOSE)mkdir -p include
|
||||
$(VERBOSE)ln -sf ../$(CONTRIB_DIR)/$(RUMP_SRC)/sys/rump/include/rump include/rump
|
||||
|
||||
|
||||
clean:
|
||||
$(VERBOSE) rm -rf $(CONTRIB_DIR)
|
||||
|
||||
help::
|
||||
$(ECHO)
|
||||
$(ECHO) "Check out rump kernel sources"
|
||||
$(ECHO)
|
||||
$(ECHO) "The source code will be located at the '$(CONTRIB_DIR)/' directory."
|
||||
$(ECHO)
|
||||
$(ECHO) "--- available commands ---"
|
||||
$(ECHO) "prepare - checkout source codes"
|
||||
$(ECHO) "clean - remove source codes"
|
||||
$(ECHO)
|
||||
|
||||
.NOTPARALLEL:
|
||||
@@ -787,251 +787,3 @@ contains its RM session and RAM session.
|
||||
; supplying the parent capability to the new process
|
||||
|
||||
|
||||
Framework infrastructure
|
||||
########################
|
||||
|
||||
Apart from the very fundamental mechanisms implemented by core, all
|
||||
higher-level services have to be implemented as part of the process tree on top
|
||||
of core.
|
||||
There are a number of frameworks at hand that provide convenient interfaces to
|
||||
be used by such components.
|
||||
In this section, we outline the most important frameworks.
|
||||
|
||||
|
||||
Communication
|
||||
=============
|
||||
|
||||
The basic mode of operation of our RPC framework is based on C++ streams.
|
||||
It uses four different stream classes: 'Ipc_ostream' for sending messages,
|
||||
'Ipc_istream' for receiving messages, 'Ipc_client' for performing RPC calls,
|
||||
and 'Ipc_server' for dispatching RPC calls. In the following, we use
|
||||
illustrative examples.
|
||||
|
||||
:Sending a message:
|
||||
|
||||
!Ipc_ostream sender(dst, &snd_buf);
|
||||
!sender << a << b << IPC_SEND;
|
||||
The object 'sender' is an output stream that is initialized with a
|
||||
communication endpoint ('dst') and a message buffer ('snd_buf').
|
||||
For sending the message, we sequentially insert both arguments into the stream
|
||||
to transform the arguments to a message and finally invoke the IPC mechanism of
|
||||
the kernel by inserting the special object 'IPC_SEND'.
|
||||
|
||||
:Receiving a message:
|
||||
|
||||
!int a, b;
|
||||
!Ipc_istream receiver(&rcv_buf);
|
||||
!receiver >> IPC_WAIT >> a >> b;
|
||||
For creating the 'receiver' input stream object, we specify a receive message
|
||||
buffer as argument that can hold one incoming message.
|
||||
By extracting the special object 'IPC_WAIT' from the receiver, we block for
|
||||
a new message to be stored into 'rcv_buf'.
|
||||
After returning from the blocking receive operation, we use the extraction
|
||||
operator to _unmarshal_ the message argument by argument.
|
||||
|
||||
:Performing a RPC call:
|
||||
|
||||
!Ipc_client client(dst, &snd_buf, &rcv_buf);
|
||||
!int result;
|
||||
!client << OPCODE_FUNC1 << 1 << 2
|
||||
! << IPC_CALL >> result;
|
||||
The first argument is a constant that references one among
|
||||
many server functions.
|
||||
It is followed by the actual server-function arguments.
|
||||
All arguments are marshalled into the 'snd_buf'.
|
||||
When inserting the special object 'IPC_CALL' into the 'client'
|
||||
stream, the client blocks for the result of the RPC.
|
||||
After receiving the result message in 'rcv_buf', the RPC
|
||||
results can be sequentially unmarshalled via the extraction
|
||||
operator. Note that 'rcv_buf' and 'snd_buf' may use the
|
||||
same backing store as both buffers are used interleaved.
|
||||
|
||||
:Dispatching a RPC call:
|
||||
|
||||
!Ipc_server server(&snd_buf, &rcv_buf);
|
||||
!while (1) {
|
||||
! int opcode;
|
||||
! server >> IPC_REPLY_WAIT >> opcode;
|
||||
! switch (opcode) {
|
||||
! case OPCODE_FUNC1:
|
||||
! {
|
||||
! int a, b, ret;
|
||||
! server >> a >> b;
|
||||
! server << func1(a, b);
|
||||
! break;
|
||||
! }
|
||||
! ..
|
||||
! }
|
||||
!}
|
||||
The special object 'IPC_REPLY_WAIT' replies to the request of the previous
|
||||
server-loop iteration with the message stored in 'snd_buf' (ignored for the
|
||||
first iteration) and then waits for an incoming RPC request to be received
|
||||
in 'rcv_buf'.
|
||||
By convention, the first message argument contains the opcode to identify
|
||||
the server function to handle the request.
|
||||
After extracting the opcode from the 'server' stream, we branch into
|
||||
a server-function-specific wrapper that reads the function arguments, calls the
|
||||
actual server function, and inserts the function result into the 'server' stream.
|
||||
The result message is to be delivered at the beginning of the next server-loop
|
||||
iteration.
|
||||
The two-stage argument-message parsing (the opcode to select the server function,
|
||||
reading the server-function arguments) is simply done by subsequent extraction
|
||||
operations.
|
||||
|
||||
|
||||
Server framework
|
||||
================
|
||||
|
||||
[image server_framework]
|
||||
Relationships between the classes of the server object framework
|
||||
|
||||
Each component that makes local objects remotely accessible to other components
|
||||
has to provide means to dispatch RPC requests that refer to different objects.
|
||||
This procedure highly depends on the mechanisms provided by the
|
||||
underlying kernel.
|
||||
The primary motivation of the server framework is to hide actual kernel
|
||||
paradigms for communication, control flow, and the implementation of
|
||||
local names (capabilities) behind a generic interface.
|
||||
The server framework unifies the control flow of RPC dispatching and the mapping
|
||||
between capabilities and local objects using the classes depicted in Figure [server_framework].
|
||||
|
||||
:'Object_pool': is an associative array that maps capabilities from/to local objects.
|
||||
Because capabilities are protected kernel objects, the object pool's functionality
|
||||
is supported by the kernel.
|
||||
|
||||
*Note:* _On L4v2 and Linux, capabilities are not protected by the kernel but are_
|
||||
_implemented as unique IDs. On these base platforms, the object pool performs_
|
||||
_the simple mapping of such unique IDs to object pointers in the local_
|
||||
_address space._
|
||||
|
||||
:'Server_object': is an object-pool entry that contains a dispatch function.
|
||||
To make a local object type available to remote components, the local
|
||||
object type must inherit from 'Server_object' and provide the implementation
|
||||
of the dispatch function as described in Section [Communication].
|
||||
|
||||
:'Server_entrypoint': is an object pool that acts as a logical communication entrypoint.
|
||||
It can manage any number of server objects. When registering a server object to be
|
||||
managed by a server entrypoint ('manage' method), a capability for this object
|
||||
gets created. This capability can be communicated to other processes,
|
||||
which can then use the server object's RPC interface.
|
||||
|
||||
:'Server_activation': is the stack (or thread) to be used for handling RPC requests
|
||||
of an entrypoint.
|
||||
|
||||
*Note:* _On L4v2 and Linux, exactly one server activation must be attached to_
|
||||
_a server entrypoint. This implicates that RPC requests are handled in a_
|
||||
_strictly serialized manner and one blocking server function delays all_
|
||||
_other pending RPC requests referring the same server entrypoint. Concurrent handling_
|
||||
_of RPC requests should be realized with multiple (completely independent)_
|
||||
_server entrypoints._
|
||||
|
||||
|
||||
Process environment
|
||||
===================
|
||||
|
||||
As described in Section [Interfaces and Mechanisms], a newly created process
|
||||
can only communicate to its immediate parent via its parent capability.
|
||||
This parent capability gets created "magically" dependent on the actual
|
||||
platform.
|
||||
|
||||
| For example, on the L4v2 platform, the parent writes the information about
|
||||
| the parent capability to a defined position of the new process' address space
|
||||
| after decoding the ELF image. On the Linux platform, the parent
|
||||
| uses environment variables to communicate the parent capability to the
|
||||
| child.
|
||||
|
||||
Before entering the 'main' function of the new process, the process' startup
|
||||
code 'crt0' is executed and initializes the _environment_ framework.
|
||||
The environment contains RPC communication stubs for communicating with the
|
||||
parent and the process' RM session, CPU session, PD session, and RAM
|
||||
session.
|
||||
Furthermore, the environment contains a heap that uses the process' RAM
|
||||
session as backing store.
|
||||
The environment can be used from the actual program by dereferencing the pointer
|
||||
returned by the global function:
|
||||
! Env *env();
|
||||
|
||||
|
||||
Child management
|
||||
================
|
||||
|
||||
The class 'Child' provides a generic and extensible abstraction to unify the
|
||||
creation of child processes, serve parent-interface requests, and to perform the
|
||||
book keeping of open sessions.
|
||||
Different access-control and resource-trading policies can be realized by
|
||||
inheriting from this class and supplementing suitable parent-interface server
|
||||
functions.
|
||||
|
||||
A child process can be created by instantiating a 'Child' object:
|
||||
!Child(const char *name,
|
||||
! Dataspace_capability elf_ds_cap,
|
||||
! Ram_session_capability ram_session_cap,
|
||||
! Cpu_session_capability cpu_session_cap,
|
||||
! Cap_session *cap_session,
|
||||
! char *args[])
|
||||
|
||||
*NOTE:* _The 'name' parameter is only used for debugging._
|
||||
_The 'args' parameter is not yet supported._
|
||||
|
||||
;The 'Child' serves the parent interface for the new process by a distinct thread.
|
||||
|
||||
|
||||
Heap partitioning
|
||||
=================
|
||||
|
||||
In Section [Goals and Challenges] where we introduced the different types of
|
||||
components composing our system, we highlighted _resource multiplexers_ as
|
||||
being critical for maintaining the isolation and independence of applications from
|
||||
each other.
|
||||
If a flawed resource multiplexer serves multiple clients at a time, information
|
||||
may leak from one client to another (corrupting isolation) or different clients
|
||||
may interfere in sharing limited physical resources (corrupting independence).
|
||||
One particular limited resource that is typically shared among all
|
||||
clients is the heap of the server.
|
||||
If the server performs heap allocations on behalf of one client, this resource
|
||||
may exhaust and renders the service unavailable to all other clients (denial of
|
||||
service).
|
||||
The resource-trading concept as presented in Section [Quota] enables clients to
|
||||
donate memory quota to a server during the use of a session.
|
||||
If the server's parent closes the session on request of the client, the donated
|
||||
resources must be released by the server.
|
||||
In order to comply with the request to avoid intervention by its parent, the
|
||||
server must store the state of each session on dedicated dataspaces that can be
|
||||
released independently from other sessions.
|
||||
Instead of using one heap to hold anonymous memory allocations, the server
|
||||
creates a _heap partition_ for each client and performs client-specific
|
||||
allocations exclusively on the corresponding heap partition.
|
||||
There exist two different classes to assist developers in partitioning the heap:
|
||||
:'Heap': is an allocator that allocates chunks of memory as dataspaces from a
|
||||
RAM session. Each chunk may hold multiple allocations. This kind of heap
|
||||
corresponds loosely to a classical heap and can be used to allocate a high
|
||||
number of small memory objects. The used backing store gets released on the
|
||||
destruction of the heap.
|
||||
:'Sliced_heap': is an allocator that uses a dedicated dataspace for each
|
||||
allocation. Therefore, each allocated block can be released independently
|
||||
from all other allocations.
|
||||
The 'Sliced_heap' must be used to obtain the actual session objects and store
|
||||
them in independent dataspaces.
|
||||
Dynamic memory allocations during the lifetime of a session must be performed by
|
||||
a 'Heap' as member of the session object.
|
||||
When closing a session, the session object including the heap partition gets
|
||||
destroyed and all backing-store dataspaces can be released without interfering
|
||||
other clients.
|
||||
|
||||
|
||||
Limitations and Outlook
|
||||
#######################
|
||||
|
||||
In its current incarnation, the design is subject to a number of limitations.
|
||||
As a prime example for managing resources, we focused our work on physical
|
||||
memory and ignored other prominent resource types such as processing time, bus
|
||||
bandwidth, and network bandwidth.
|
||||
We intend to apply the same methodology that we developed for physical memory to
|
||||
other resource types analogously in later design revisions.
|
||||
We do not cover features such as virtual-memory or transparent
|
||||
copy-on-write support, which we regard as non-essential at the current stage.
|
||||
At this point, we also do not provide specifics about the device-driver
|
||||
infrastructure and legacy-software containers.
|
||||
Note that the presented design does not fundamentally prevent the support
|
||||
of these features.
|
||||
|
||||
|
||||
@@ -42,31 +42,31 @@ the 'BUILD_DIR=' argument. For example:
|
||||
! ./tool/create_builddir linux_x86 BUILD_DIR=/tmp/build.linux_x86
|
||||
|
||||
This command will create a new build directory for the Linux/x86 platform
|
||||
at '/tmp/build.linux_x86/'.
|
||||
at _/tmp/build.linux_x86/_.
|
||||
|
||||
|
||||
Build-directory configuration via 'build.conf'
|
||||
==============================================
|
||||
|
||||
The fresh build directory will contain a 'Makefile', which is a symlink to
|
||||
'tool/builddir/build.mk'. This 'Makefile' is the front end of the build system
|
||||
and not supposed to be edited. Beside the 'Makefile', there is a 'etc/'
|
||||
_tool/builddir/build.mk_. This makefile is the front end of the build system
|
||||
and not supposed to be edited. Beside the makefile, there is a _etc/_
|
||||
subdirectory that contains the build-directory configuration. For most
|
||||
platforms, there is only a single 'build.conf' file, which defines the parts of
|
||||
platforms, there is only a single _build.conf_ file, which defines the parts of
|
||||
the Genode source tree incorporated in the build process. Those parts are
|
||||
called _repositories_.
|
||||
|
||||
The repository concept allows for keeping the source code well separated for
|
||||
different concerns. For example, the platform-specific code for each target
|
||||
platform is located in a dedicated 'base-<platform>' repository. Also, different
|
||||
platform is located in a dedicated _base-<platform>_ repository. Also, different
|
||||
abstraction levels and features of the system are residing in different
|
||||
repositories. The 'etc/build.conf' file defines the set of repositories to
|
||||
repositories. The _etc/build.conf_ file defines the set of repositories to
|
||||
consider in the build process. At build time, the build system overlays the
|
||||
directory structures of all repositories specified via the 'REPOSITORIES'
|
||||
declaration to form a single logical source tree. By changing the list of
|
||||
'REPOSITORIES', the view of the build system on the source tree can be altered.
|
||||
The 'etc/build.conf' as found in a fresh created build directory will list the
|
||||
'base-<platform>' repository of the platform selected at the 'create_builddir'
|
||||
The _etc/build.conf_ as found in a fresh created build directory will list the
|
||||
_base-<platform>_ repository of the platform selected at the 'create_builddir'
|
||||
command line as well as the 'base', 'os', and 'demo' repositories needed for
|
||||
compiling Genode's default demonstration scenario. Furthermore, there are a
|
||||
number of commented-out lines that can be uncommented for enabling additional
|
||||
@@ -84,7 +84,7 @@ Building targets
|
||||
================
|
||||
|
||||
To build all targets contained in the list of 'REPOSITORIES' as defined in
|
||||
'etc/build.conf', simply issue 'make'. This way, all components that are
|
||||
_etc/build.conf_, simply issue 'make'. This way, all components that are
|
||||
compatible with the build directory's base platform will be built. In practice,
|
||||
however, only some of those components may be of interest. Hence, the build
|
||||
can be tailored to those components which are of actual interest by specifying
|
||||
@@ -112,8 +112,8 @@ To remove all but kernel-related generated files, use
|
||||
To remove all generated files, use
|
||||
! make cleanall
|
||||
|
||||
Both 'clean' and 'cleanall' won't remove any files from the 'bin/'
|
||||
subdirectory. This makes the 'bin/' a safe place for files that are
|
||||
Both 'clean' and 'cleanall' won't remove any files from the _bin/_
|
||||
subdirectory. This makes the _bin/_ a safe place for files that are
|
||||
unrelated to the build process, yet required for the integration stage, e.g.,
|
||||
binary data.
|
||||
|
||||
@@ -143,7 +143,7 @@ Enabling parallel builds
|
||||
|
||||
To utilize multiple CPU cores during the build process, you may invoke 'make'
|
||||
with the '-j' argument. If manually specifying this argument becomes an
|
||||
inconvenience, you may add the following line to your 'etc/build.conf' file:
|
||||
inconvenience, you may add the following line to your _etc/build.conf_ file:
|
||||
|
||||
! MAKE += -j<N>
|
||||
|
||||
@@ -184,14 +184,6 @@ Each Genode repository has the following layout:
|
||||
'lib/mk/' | Library build descriptions
|
||||
|
||||
|
||||
For each custom source-code repository supplied to the build system, the
|
||||
following subdirectories are mandatory:
|
||||
|
||||
! lib/mk/
|
||||
! src/
|
||||
! include/
|
||||
|
||||
|
||||
Creating targets and libraries
|
||||
##############################
|
||||
|
||||
@@ -199,8 +191,8 @@ Target descriptions
|
||||
===================
|
||||
|
||||
A good starting point is to look at the init target. The source code of init is
|
||||
located at 'os/src/init/'. In this directory, you will find a target description
|
||||
file named 'target.mk'. This file contains the building instructions and it is
|
||||
located at _os/src/init/_. In this directory, you will find a target description
|
||||
file named _target.mk_. This file contains the building instructions and it is
|
||||
usually very simple. The build process is controlled by defining the following
|
||||
variables.
|
||||
|
||||
@@ -209,7 +201,7 @@ Build variables to be defined by you
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:'TARGET': is the name of the binary to be created. This is the
|
||||
only *mandatory variable* to be defined in a 'target.mk' file.
|
||||
only *mandatory variable* to be defined in a _target.mk_ file.
|
||||
|
||||
:'REQUIRES': expresses the requirements that must be satisfied in order to
|
||||
build the target. You find more details about the underlying mechanism in
|
||||
@@ -218,7 +210,7 @@ Build variables to be defined by you
|
||||
:'LIBS': is the list of libraries that are used by the target.
|
||||
|
||||
:'SRC_CC': contains the list of '.cc' source files. The default search location
|
||||
for source codes is the directory, where the 'target.mk' file resides.
|
||||
for source codes is the directory, where the _target.mk_ file resides.
|
||||
|
||||
:'SRC_C': contains the list of '.c' source files.
|
||||
|
||||
@@ -257,9 +249,9 @@ source-code repository, where your target lives:
|
||||
|
||||
:'REP_DIR': is the base directory of the current source-code repository.
|
||||
Normally, specifying locations relative to the base of the repository is
|
||||
never used by 'target.mk' files but needed by library descriptions.
|
||||
never used by _target.mk_ files but needed by library descriptions.
|
||||
|
||||
:'PRG_DIR': is the directory, where your 'target.mk' file resides. This
|
||||
:'PRG_DIR': is the directory, where your _target.mk_ file resides. This
|
||||
variable is always to be used when specifying a relative path.
|
||||
|
||||
|
||||
@@ -267,8 +259,8 @@ Library descriptions
|
||||
====================
|
||||
|
||||
In contrast to target descriptions that are scattered across the whole source
|
||||
tree, library descriptions are located at the central place 'lib/mk'. Each
|
||||
library corresponds to a '<libname>.mk' file. The base of the description file
|
||||
tree, library descriptions are located at the central place _lib/mk_. Each
|
||||
library corresponds to a _<libname>.mk_ file. The base of the description file
|
||||
is the name of the library. Therefore, no 'TARGET' variable needs to be set.
|
||||
The source-code locations are expressed as '$(REP_DIR)'-relative 'vpath'
|
||||
commands.
|
||||
@@ -277,7 +269,7 @@ Library-description files support the following additional declarations:
|
||||
|
||||
:'SHARED_LIB = yes': declares that the library should be built as a shared
|
||||
object rather than a static library. The resulting object will be called
|
||||
'<libname>.lib.so'.
|
||||
_<libname>.lib.so_.
|
||||
|
||||
|
||||
Specializations
|
||||
@@ -301,20 +293,20 @@ file.
|
||||
|
||||
The _user/customer/builder_ decides to build software for a specific platform
|
||||
and defines the platform specifics via the 'SPECS' variable per build
|
||||
directory in 'etc/specs.conf'. In addition to an (optional) 'etc/specs.conf'
|
||||
directory in _etc/specs.conf_. In addition to an (optional) _etc/specs.conf_
|
||||
file within the build directory, the build system incorporates the first
|
||||
'etc/specs.conf' file found in the repositories as configured for the
|
||||
_etc/specs.conf_ file found in the repositories as configured for the
|
||||
build directory. For example, for a 'linux_x86' build directory, the
|
||||
'base-linux/etc/specs.conf' file is used by default. The build directory's
|
||||
_base-linux/etc/specs.conf_ file is used by default. The build directory's
|
||||
'specs.conf' file can still be used to extend the 'SPECS' declarations, for
|
||||
example to enable special features.
|
||||
|
||||
Each '<specname>' in the 'SPECS' variable instructs the build system to
|
||||
|
||||
* Include the 'make'-rules of a corresponding 'base/mk/spec-<specname>.mk'
|
||||
* Include the 'make'-rules of a corresponding _base/mk/spec-<specname>.mk_
|
||||
file. This enables the customization of the build process for each platform.
|
||||
|
||||
* Search for '<libname>.mk' files in the 'lib/mk/<specname>/' subdirectory.
|
||||
* Search for _<libname>.mk_ files in the _lib/mk/<specname>/_ subdirectory.
|
||||
This way, we can provide alternative implementations of one and the same
|
||||
library interface for different platforms.
|
||||
|
||||
@@ -325,6 +317,51 @@ variable is present in the 'SPECS' variable as supplied by the build directory
|
||||
configuration.
|
||||
|
||||
|
||||
Building tools to be executed on the host platform
|
||||
===================================================
|
||||
|
||||
Sometimes, software requires custom tools that are used to generate source
|
||||
code or other ingredients for the build process, for example IDL compilers.
|
||||
Such tools won't be executed on top of Genode but on the host platform
|
||||
during the build process. Hence, they must be compiled with the tool chain
|
||||
installed on the host, not the Genode tool chain.
|
||||
|
||||
The Genode build system accommodates the building of such host tools as a side
|
||||
effect of building a library or a target. Even though it is possible to add
|
||||
the tool compilation step to a regular build description file, it is
|
||||
recommended to introduce a dedicated pseudo library for building such tools.
|
||||
This way, the rules for building host tools are kept separate from rules that
|
||||
refer to Genode programs. By convention, the pseudo library should be named
|
||||
_<package>_host_tools_ and the host tools should be built at
|
||||
_<build-dir>/tool/<package>/_. With _<package>_, we refer to the name of the
|
||||
software package the tool belongs to, e.g., qt5 or mupdf. To build a tool
|
||||
named _<tool>_, the pseudo library contains a custom make rule like the
|
||||
following:
|
||||
|
||||
! $(BUILD_BASE_DIR)/tool/<package>/<tool>:
|
||||
! $(MSG_BUILD)$(notdir $@)
|
||||
! $(VERBOSE)mkdir -p $(dir $@)
|
||||
! $(VERBOSE)...build commands...
|
||||
|
||||
To let the build system trigger the rule, add the custom target to the
|
||||
'HOST_TOOLS' variable:
|
||||
|
||||
! HOST_TOOLS += $(BUILD_BASE_DIR)/tool/<package>/<tool>
|
||||
|
||||
Once the pseudo library for building the host tools is in place, it can be
|
||||
referenced by each target or library that relies on the respective tools via
|
||||
the 'LIBS' declaration. The tool can be invoked by referring to
|
||||
'$(BUILD_BASE_DIR)/tool/<package>/tool'.
|
||||
|
||||
For an example of using custom host tools, please refer to the mupdf package
|
||||
found within the libports repository. During the build of the mupdf library,
|
||||
two custom tools fontdump and cmapdump are invoked. The tools are built via
|
||||
the _lib/mk/mupdf_host_tools.mk_ library description file. The actual mupdf
|
||||
library (_lib/mk/mupdf.mk_) has the pseudo library 'mupdf_host_tools' listed
|
||||
in its 'LIBS' declaration and refers to the tools relative to
|
||||
'$(BUILD_BASE_DIR)'.
|
||||
|
||||
|
||||
Automated integration and testing
|
||||
#################################
|
||||
|
||||
@@ -343,8 +380,8 @@ Using so-called run scripts, complete Genode systems can be described in a
|
||||
concise and kernel-independent way. Once created, a run script can be used
|
||||
to integrate and test-drive a system scenario directly from the build directory.
|
||||
The best way to get acquainted with the concept is reviewing the run script
|
||||
for the 'hello_tutorial' located at 'hello_tutorial/run/hello.run'.
|
||||
Let's revisit each step expressed in the 'hello.run' script:
|
||||
for the 'hello_tutorial' located at _hello_tutorial/run/hello.run_.
|
||||
Let's revisit each step expressed in the _hello.run_ script:
|
||||
|
||||
* Building the components needed for the system using the 'build' command.
|
||||
This command instructs the build system to compile the targets listed in
|
||||
@@ -353,7 +390,7 @@ Let's revisit each step expressed in the 'hello.run' script:
|
||||
|
||||
* Creating a new boot directory using the 'create_boot_directory' command.
|
||||
The integration of the scenario is performed in a dedicated directory at
|
||||
'<build-dir>/var/run/<run-script-name>/'. When the run script is finished,
|
||||
_<build-dir>/var/run/<run-script-name>/_. When the run script is finished,
|
||||
this directory will contain all components of the final system. In the
|
||||
following, we will refer to this directory as run directory.
|
||||
|
||||
@@ -363,7 +400,7 @@ Let's revisit each step expressed in the 'hello.run' script:
|
||||
Genode's init process.
|
||||
|
||||
* Creating a bootable system image using the 'build_boot_image' command.
|
||||
This command copies the specified list of files from the '<build-dir>/bin/'
|
||||
This command copies the specified list of files from the _<build-dir>/bin/_
|
||||
directory to the run directory and executes the platform-specific steps
|
||||
needed to transform the content of the run directory into a bootable
|
||||
form. This form depends on the actual base platform and may be an ISO
|
||||
@@ -381,7 +418,7 @@ Let's revisit each step expressed in the 'hello.run' script:
|
||||
a timeout in seconds. If the regular expression does not match until
|
||||
the timeout is reached, the run script will abort.
|
||||
|
||||
Please note that the 'hello.run' script does not contain kernel-specific
|
||||
Please note that the _hello.run_ script does not contain kernel-specific
|
||||
information. Therefore it can be executed from the build directory of any base
|
||||
platform by using:
|
||||
|
||||
@@ -392,12 +429,12 @@ will look in all repositories for a run script with the specified name. The run
|
||||
script must be located in one of the repositories 'run/' subdirectories and
|
||||
have the file extension '.run'.
|
||||
|
||||
For a more comprehensive run script, 'os/run/demo.run' serves as a good
|
||||
For a more comprehensive run script, _os/run/demo.run_ serves as a good
|
||||
example. This run script describes Genode's default demo scenario. As seen in
|
||||
'demo.run', parts of init's configuration can be made dependent on the
|
||||
platform's properties expressed as spec values. For example, the PCI driver
|
||||
gets included in init's configuration only on platforms with a PCI bus. For
|
||||
appending conditional snippets to the 'config' file, there exists the 'append_if'
|
||||
appending conditional snippets to the _config_ file, there exists the 'append_if'
|
||||
command, which takes a condition as first and the snippet as second argument.
|
||||
To test for a SPEC value, the command '[have_spec <spec-value>]' is used as
|
||||
condition. Analogously to how 'append_if' appends strings, there exists
|
||||
@@ -410,20 +447,20 @@ The run mechanism explained
|
||||
===========================
|
||||
|
||||
Under the hood, run scripts are executed by an expect interpreter. When the
|
||||
user invokes a run script via 'make run/<run-script>', the build system invokes
|
||||
the run tool at '<genode-dir>/tool/run' with the run script as argument. The
|
||||
user invokes a run script via _make run/<run-script>_, the build system invokes
|
||||
the run tool at _<genode-dir>/tool/run_ with the run script as argument. The
|
||||
run tool is an expect script that has no other purpose than defining several
|
||||
commands used by run scripts, including a platform-specific script snippet
|
||||
called run environment ('env'), and finally including the actual run script.
|
||||
Whereas 'tool/run' provides the implementations of generic and largely
|
||||
platform-independent commands, the 'env' snippet included from the platform's
|
||||
respective 'base-<platform>/run/env' file contains all platform-specific
|
||||
Whereas _tool/run_ provides the implementations of generic and largely
|
||||
platform-independent commands, the _env_ snippet included from the platform's
|
||||
respective _base-<platform>/run/env_ file contains all platform-specific
|
||||
commands. For reference, the most simplistic run environment is the one at
|
||||
'base-linux/run/env', which implements the 'create_boot_directory',
|
||||
_base-linux/run/env_, which implements the 'create_boot_directory',
|
||||
'install_config', 'build_boot_image', and 'run_genode_until' commands for Linux
|
||||
as base platform. For the other platforms, the run environments are far more
|
||||
elaborative and document precisely how the integration and boot concept works
|
||||
on each platform. Hence, the 'base-<platform>/run/env' files are not only
|
||||
on each platform. Hence, the _base-<platform>/run/env_ files are not only
|
||||
necessary parts of Genode's tooling support but serve as resource for
|
||||
peculiarities of using each kernel.
|
||||
|
||||
@@ -434,7 +471,7 @@ Using run script to implement test cases
|
||||
Because run scripts are actually expect scripts, the whole arsenal of
|
||||
language features of the Tcl scripting language is available to them. This
|
||||
turns run scripts into powerful tools for the automated execution of test
|
||||
cases. A good example is the run script at 'libports/run/lwip.run', which tests
|
||||
cases. A good example is the run script at _libports/run/lwip.run_, which tests
|
||||
the lwIP stack by running a simple Genode-based HTTP server on Qemu. It fetches
|
||||
and validates a HTML page from this server. The run script makes use of a
|
||||
regular expression as argument to the 'run_genode_until' command to detect the
|
||||
@@ -445,19 +482,19 @@ that use Qemu as execution environment.
|
||||
|
||||
To get the most out of the run mechanism, a basic understanding of the Tcl
|
||||
scripting language is required. Furthermore the functions provided by
|
||||
'tool/run' and 'base-<platform>/run/env' should be studied.
|
||||
_tool/run_ and _base-<platform>/run/env_ should be studied.
|
||||
|
||||
|
||||
Automated testing across base platforms
|
||||
=======================================
|
||||
|
||||
To execute one or multiple test cases on more than one base platform, there
|
||||
exists a dedicated tool at 'tool/autopilot'. Its primary purpose is the
|
||||
exists a dedicated tool at _tool/autopilot_. Its primary purpose is the
|
||||
nightly execution of test cases. The tool takes a list of platforms and of
|
||||
run scripts as arguments and executes each run script on each platform. The
|
||||
build directory for each platform is created at
|
||||
'/tmp/autopilot.<username>/<platform>' and the output of each run script is
|
||||
written to a file called '<platform>.<run-script>.log'. On stderr, autopilot
|
||||
_/tmp/autopilot.<username>/<platform>_ and the output of each run script is
|
||||
written to a file called _<platform>.<run-script>.log_. On stderr, autopilot
|
||||
prints the statistics about whether or not each run script executed
|
||||
successfully on each platform. If at least one run script failed, autopilot
|
||||
returns a non-zero exit code, which makes it straight forward to include
|
||||
|
||||
@@ -8,9 +8,8 @@
|
||||
Documentation
|
||||
#############
|
||||
|
||||
We use the GOSH syntax
|
||||
[http://os.inf.tu-dresden.de/~nf2/files/GOSH/current/gosh.txt]
|
||||
for documentation and README files.
|
||||
We use the GOSH syntax [https://github.com/nfeske/gosh] for documentation and
|
||||
README files.
|
||||
|
||||
|
||||
README files
|
||||
@@ -53,7 +52,7 @@ but use a meaningful subdirectory that corresponds to the component that
|
||||
provides the interfaces.
|
||||
|
||||
Each RPC interface is represented by a separate include subdirectory. For
|
||||
an example, see 'base/include/ram_session/'. The headerfile that defines
|
||||
an example, see 'base/include/ram_session/'. The header file that defines
|
||||
the RPC function interface has the same base name as the directory. The RPC
|
||||
stubs are called 'client.h' and 'server.h'. If your interface uses a custom
|
||||
capability type, it is defined in 'capability.h'. Furthermore, if your
|
||||
|
||||
@@ -88,11 +88,11 @@ steps are required:
|
||||
|
||||
# Download the kernel:
|
||||
! cd <genode-dir>
|
||||
! make -C base-okl4 prepare
|
||||
! make -C repos/base-okl4 prepare
|
||||
# Create a build directory
|
||||
! ./tool/create_builddir okl4_x86 BUILD_DIR=build.okl4
|
||||
# Uncomment the following line in 'build.okl4/etc/build.conf'
|
||||
! REPOSITORIES += $(GENODE_DIR)/libports
|
||||
! REPOSITORIES += $(GENODE_DIR)/repos/libports
|
||||
# Build and execute the demo using Qemu
|
||||
! make -C build.okl4 run/demo
|
||||
|
||||
|
||||
62
doc/news.txt
62
doc/news.txt
@@ -3,6 +3,68 @@
|
||||
Genode News
|
||||
===========
|
||||
|
||||
|
||||
An Exploration of ARM TrustZone Technology | 2014-04-10
|
||||
#######################################################
|
||||
|
||||
| A new article supplemented by a demonstration video presents our endeavour
|
||||
| of combining Genode with the security features of ARM TrustZone.
|
||||
|
||||
ARM TrustZone technology has been around for half a decade. Even though it is
|
||||
used on most ARM-based devices ranging from low-cost development boards to
|
||||
mobile phones like the Samsung Galaxy S4, there exists almost no public body
|
||||
of knowledge around this technology. This prompted us to start a series of
|
||||
experiments with ARM's security extensions. Our line of work ultimately led to
|
||||
a demonstrable prototype where Genode is used as secure OS behind the back of
|
||||
Android running on a FreeScale i.MX53 SABRE tablet. We share our experience
|
||||
(and of course the full source code) in the form of the article
|
||||
[http:/documentation/articles/trustzone - An Exploration of ARM TrustZone Technology...]
|
||||
|
||||
|
||||
Genode OS Framework release 14.02 | 2014-02-28
|
||||
##############################################
|
||||
|
||||
| The two highlights of the new release are VirtualBox running on
|
||||
| top of the NOVA microhypervisor and the added support for NetBSD's file
|
||||
| systems. Furthermore, the release comes with new or largely revised
|
||||
| storage components such as a block cache.
|
||||
|
||||
During the release cycle for version 14.02, the development was focused on the
|
||||
topics storage and virtualization, both considered as fundamental for using
|
||||
Genode as general-purpose OS.
|
||||
|
||||
Concerning storage, we took the chance to redesign the existing block-level
|
||||
components to work asynchronously. This way, block requests can be processed
|
||||
in a pipelined fashion and even out of order, which is beneficial to hide
|
||||
device latencies and to maximize throughput. Additionally, there are entirely
|
||||
new storage components, most prominently a new block cache, FUSE-based
|
||||
file-system services, and support for the file systems of the NetBSD kernel.
|
||||
The latter was made possible by the use of so-called rump kernels, which allow
|
||||
the execution of individual NetBSD kernel subsystems at user level. We use it
|
||||
to execute NetBSD's file systems as Genode components.
|
||||
|
||||
Virtualization has become a popular use case for microkernel technology. Until
|
||||
now, however, none of Genode's existing virtualization options such as L4Linux
|
||||
on top of Fiasco.OC or the Vancouver VMM on top of NOVA could be considered as
|
||||
compelling alternatives to commodity virtualization products. With the added
|
||||
support for running VirtualBox on top of the NOVA microhypervisor, we combine
|
||||
the benefits of microkernel technology and capability-based security in
|
||||
particular with a product-grade virtualization solution. Compared to the
|
||||
traditional host operating systems supported by VirtualBox, using VirtualBox
|
||||
on top of Genode/NOVA reduces the trusted computing base for the security of
|
||||
virtual machines by more than three orders of magnitude. For existing Genode
|
||||
users, VirtualBox opens up the ability to run a wide range of unmodified guest
|
||||
operating systems such as GNU/Linux and MS Windows side by side with regular
|
||||
Genode components.
|
||||
|
||||
As is the case for every release, there are many additional improvements all
|
||||
over the place, for example unified interfaces for graphics, support for POSIX
|
||||
signals in the Noux runtime for Unix programs, and a new pseudo file system
|
||||
for the interactive exploration and tracing of Genode's process tree. These
|
||||
and more topics are covered by the detailed
|
||||
[http:/documentation/release-notes/14.02 - release documentation of version 14.02...]
|
||||
|
||||
|
||||
Slides and videos of our FOSDEM talks | 2014-02-10
|
||||
##################################################
|
||||
|
||||
|
||||
@@ -31,8 +31,14 @@ sections:
|
||||
:[http:porting_device_drivers - Porting devices drivers]:
|
||||
This chapter describes the concepts of how to port a device driver to the
|
||||
Genode framework. It requires the basic knowledge introduced in the previous
|
||||
chapters and should be read last. Before reading this guide, it is strongly
|
||||
advised to read the "The Genode Build System" documentation.
|
||||
chapters and should be read last.
|
||||
|
||||
Before reading this guide, it is strongly advised to read the "The Genode
|
||||
Build System" documentation:
|
||||
|
||||
:Build-system manual:
|
||||
|
||||
[http://genode.org/documentation/developer-resources/build_system]
|
||||
|
||||
|
||||
Porting third-party code to Genode
|
||||
@@ -55,22 +61,22 @@ Steps in porting applications to Genode
|
||||
e.g. what functionality needs to be provided by the target system and
|
||||
which libraries does it use.
|
||||
|
||||
# Create a port Makefile
|
||||
# Create a port file
|
||||
|
||||
Prepare the source code of the application for the use within Genode. The
|
||||
Genode build-system infrastructure uses fetch rules, so called port-files,
|
||||
which describe how the source is obtained, what patches are applied to the
|
||||
source code, if needed, and where the source code will be stored and
|
||||
Genode build-system infrastructure uses fetch rules, so called port files,
|
||||
which declare where the source is obtained from, what patches are applied
|
||||
to the source code, and where the source code will be stored and
|
||||
configured.
|
||||
|
||||
# Check platform dependent code and create stub code
|
||||
|
||||
This step may require changes to the original source code
|
||||
of the application to be compilable to Genode. At this point, it
|
||||
of the application to be compilable for Genode. At this point, it
|
||||
is not necessary to provide a working implementation for required
|
||||
functions. Just creating stubs of the various functions is fine.
|
||||
|
||||
# Create build Makefile
|
||||
# Create build-description file
|
||||
|
||||
To compile the application we need build rules. Within these rules
|
||||
we also declare all dependencies (e.g. libraries) that are needed
|
||||
@@ -176,61 +182,75 @@ libraries are already available on Genode. For now all we have to do is to
|
||||
keep them in mind.
|
||||
|
||||
|
||||
Creating the port Makefile
|
||||
==========================
|
||||
Creating the port file
|
||||
======================
|
||||
|
||||
Since DosBox is an application, which depends on several ported
|
||||
libraries (e.g., libSDL), the 'ports' repository within the Genode
|
||||
source tree is a natural fit. On that account, the port Makefile
|
||||
_ports/ports/dosbox.mk_ is created. It is often reasonable to also
|
||||
create a corresponding _ports/ports/dosbox.inc_ file that contains
|
||||
the used version of the program which is included by _dosbox.mk_ as
|
||||
well as by the associated build Makefile. Through this approach it is
|
||||
easier to update ports whose structures stays the same but varies only
|
||||
in its version string.
|
||||
libraries (e.g., libSDL), the _ports_ repository within the Genode
|
||||
source tree is a natural fit. On that account, the port file
|
||||
_ports/ports/dosbox.port_ is created.
|
||||
|
||||
For DosBox the _dosbox.inc_ looks as follows:
|
||||
For DosBox the _dosbox.port_ looks as follows:
|
||||
|
||||
! DOSBOX_REV := 3837
|
||||
! DOSBOX_VERSION := svn-$(DOSBOX_REV)
|
||||
! DOSBOX := dosbox-$(DOSBOX_VERSION)
|
||||
|
||||
In addition, the corresponding _dosbox.mk_ contains:
|
||||
|
||||
! include ports/dosbox.inc
|
||||
! LICENSE := GPLv2
|
||||
! VERSION := svn
|
||||
! DOWNLOADS := dosbox.svn
|
||||
!
|
||||
! DOSBOX_SVN_URL = http://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk
|
||||
!
|
||||
! #
|
||||
! # Interface to top-level prepare Makefile
|
||||
! #
|
||||
! PORTS += $(DOSBOX)
|
||||
!
|
||||
! prepare:: $(CONTRIB_DIR)/$(DOSBOX)
|
||||
!
|
||||
! #
|
||||
! # Port-specific local rules
|
||||
! #
|
||||
! $(CONTRIB_DIR)/$(DOSBOX):
|
||||
! $(ECHO) "checking out 'dosbox rev. $(DOSBOX_REV)' to '$@'"
|
||||
! $(VERBOSE)svn export $(DOSBOX_SVN_URL)@$(DOSBOX_REV) $@
|
||||
! URL(dosbox) := http://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk
|
||||
! DIR(dosbox) := src/app/dosbox
|
||||
! REV(dosbox) := 3837
|
||||
|
||||
_The variable_ 'CONTRIB_DIR' _always contains the path to the directory_
|
||||
_that holds the contributed source code relatively to the particular_
|
||||
_Genode repository (e.g., ports/contrib)._
|
||||
First, we define the license, the version and the type of the source code
|
||||
origin. In case of DosBox, we checkout the source code from a Subversion
|
||||
repository. This is denoted by the '.svn' suffix of the item specified in
|
||||
the 'DOWNLOADS' declaration. Other valid types are 'file' (a plain file),
|
||||
'archive' (an archive of the types tar.gz, tar.xz, tgz, tar.bz2, or zip)
|
||||
or 'git' (a Git repository).
|
||||
To checkout the source code out from the Subversion repository, we also need
|
||||
its URL, the revision we want to check out and the destination directory
|
||||
that will contain the sources afterwards. These declarations are mandatory and
|
||||
must always be specified. Otherwise the preparation of the port will fail.
|
||||
|
||||
! PATCHES := $(addprefix src/app/dosbox/patches/,\
|
||||
! $(notdir $(wildcard $(REP_DIR)/src/app/dosbox/patches/*.patch)))
|
||||
!
|
||||
! PATCH_OPT := -p2 -d src/app/dosbox
|
||||
|
||||
As next step, we declare all patches that are needed for the DosBox port.
|
||||
Since in this case, the patches are using a different path format, we have
|
||||
to override the default patch settings by defining the _PATCH_OPT_ variable.
|
||||
|
||||
Each port file comes along with a hash file. This hash is generated by taking
|
||||
several sources into account. For one, the port file, each patch and the
|
||||
port preparation tool (_tool/ports/prepare_port_) are the ingredients for
|
||||
the hash value. If any of these files is changed, a new hash will be generated,
|
||||
For now, we just write "dummy" in the '_ports/ports/dosbox.hash_ file.
|
||||
|
||||
The DosBox port can now be prepared by executing
|
||||
|
||||
! $ make PKG=dosbox prepare
|
||||
! $ <genode-dir>/tool/ports/prepare_port dosbox
|
||||
|
||||
from within Genode's 'ports' repository. The 'prepare::' rule is evaluated
|
||||
and the checkout will be triggered.
|
||||
However, we get the following error message:
|
||||
|
||||
Error: <rep-dir>/ports/dosbox.port is out of date, expected <fingerprint>
|
||||
|
||||
We get this message because we had specified the "dummy" hash value in
|
||||
the _dosbox.hash_ file. The prepare_port tool computes a fingerprint
|
||||
of the actual version of the port and compares this fingerprint with the
|
||||
hash value specified in _dosbox.hash_. The computed fingerprint can
|
||||
be found at _<genode-dir>/contrib/dosbox-dummy/dosbox.hash_. In the final
|
||||
step of the port, we will replace the dummy fingerprint with the actual
|
||||
fingerprint of the port. But before finalizing the porting work, it is
|
||||
practical to keep using the dummy hash and suppress the fingerprint check.
|
||||
This can be done by adding 'CHECK_HASH=no' as argument to the prepare_port tool:
|
||||
|
||||
! $ <genode-dir>/tool/ports/prepare-port dosbox CHECK_HASH=no
|
||||
|
||||
|
||||
Check platform-dependent code
|
||||
=============================
|
||||
|
||||
At this point, it is important to spot platform dependent source files or
|
||||
At this point, it is important to spot platform-dependent source files or
|
||||
rather certain functions that are not yet available on Genode. These source
|
||||
files should be omitted. Of course they may be used as a guidance when
|
||||
implementing the functionality for Genode later on, when creating the
|
||||
@@ -249,11 +269,18 @@ we assemble a list of needed source files. If an application just
|
||||
uses a simple Makefile and not a build tool, it might be easier to just
|
||||
reuse the contents of this Makefile instead.
|
||||
|
||||
First we include _dosbox.inc_ and for convenience set the source directory
|
||||
of DosBox:
|
||||
First of all, we create a shortcut for the source directory of DosBox by calling
|
||||
the 'select_from_ports' function:
|
||||
|
||||
! include $(REP_DIR)/ports/dosbox.inc
|
||||
! DOSBOX_DIR = $(REP_DIR)/contrib/$(DOSBOX)
|
||||
! DOSBOX_DIR := $(call select_from_ports,dosbox)/src/app/dosbox
|
||||
|
||||
Under the hood, the 'select_from_ports' function looks up the
|
||||
fingerprint of the specified port by reading the corresponding
|
||||
<port-name>.hash file. It then uses this hash value to construct the
|
||||
directory path within the _<genode-dir>contrib/_ directory that belongs to
|
||||
the matching version of the port. If there is no hash file that matches the
|
||||
port name, or if the port directory does not exist, the build system
|
||||
will back out with an error message.
|
||||
|
||||
Examining the log file leaves us with the following list of source files:
|
||||
|
||||
@@ -274,7 +301,7 @@ Examining the log file leaves us with the following list of source files:
|
||||
! […]
|
||||
|
||||
_The only variable here that is actually evaluated by Genode's build-system is_
|
||||
'SRC_CC' _. The rest of the variables are little helpers that make our_
|
||||
'SRC_CC'. _The rest of the variables are little helpers that make our_
|
||||
_life more comfortable._
|
||||
|
||||
In this case, it is mandatory to use GNUMake's 'notdir' file name function
|
||||
@@ -286,7 +313,7 @@ why you have to use a build directory for each platform. The Genode build
|
||||
system will create the needed directory hierarchy within the build directory
|
||||
automatically. By combining GNUMake's 'notdir' and 'wildcard' function, we
|
||||
can assemble a list of all needed source files without much effort. We then
|
||||
use 'vpath' to point GNUMake to the right source file within the _contrib_
|
||||
use 'vpath' to point GNUMake to the right source file within the dosbox
|
||||
directory.
|
||||
|
||||
The remaining thing to do now is setting the right include directories and proper
|
||||
@@ -324,7 +351,7 @@ environment. Below is a skimmed diff of these changes:
|
||||
!
|
||||
! […]
|
||||
|
||||
Thereafter we specify the compiler flags:
|
||||
Thereafter, we specify the compiler flags:
|
||||
|
||||
! CC_OPT = -DHAVE_CONFIG_H -D_GNU_SOURCE=1 -D_REENTRANT
|
||||
! ifeq ($(filter-out $(SPECS),x86_32),)
|
||||
@@ -343,7 +370,7 @@ As noted in the commentary seen in the diff we define 'C_TARGETCPU'
|
||||
and adjust the include directories ourselves according to the target
|
||||
architecture.
|
||||
|
||||
While debugging compiler warnings for 3rd-party code are really helpful but
|
||||
While debugging, compiler warnings for 3rd-party code are really helpful but
|
||||
tend to be annoying after the porting work is finished, we can
|
||||
remove the hashmark to keep the compiler from complaining too
|
||||
much.
|
||||
@@ -351,13 +378,13 @@ much.
|
||||
Lastly, we need to add the required libraries, which we acquired in step 1:
|
||||
|
||||
! LIBS += libc libm libpng sdl stdcxx zlib
|
||||
! LIBS += libc_log libc_fs libc_lwip_nic_dhcp config_args
|
||||
! LIBS += libc_lwip_nic_dhcp config_args
|
||||
|
||||
In addition to the required libraries, a few Genode specific
|
||||
libraries are also needed. These libraries implement certain
|
||||
functions in the libc via the libc's plugin mechanism.
|
||||
libc_log, for example, is used to print message on stdout via
|
||||
Genode's LOG service.
|
||||
libc_lwip_nic_dhcp, for example, is used to connect the BSD socket interface
|
||||
to a NIC service such as a network device driver.
|
||||
|
||||
|
||||
Creating the run script
|
||||
@@ -418,18 +445,16 @@ Nextm we provide the scenario's configuration 'config':
|
||||
! <resource name="RAM" quantum="1M"/>
|
||||
! <provides><service name="Timer"/></provides>
|
||||
! </start>
|
||||
! <start name="tar_fs">
|
||||
! <resource name="RAM" quantum="4M"/>
|
||||
! <provides> <service name="File_system"/> </provides>
|
||||
! <config>
|
||||
! <archive name="dosbox.tar" />
|
||||
! <policy label="" root="/" />
|
||||
! </config>
|
||||
! </start>
|
||||
! <start name="dosbox">
|
||||
! <resource name="RAM" quantum="128M"/>
|
||||
! <config>
|
||||
! <sdl_audio_volume value="100"/>
|
||||
! <libc stdout="/dev/log" stderr="/dev/log">
|
||||
! <vfs>
|
||||
! <tar name="dosbox.tar"/>
|
||||
! <dir name="dev"> <log/> </dir>
|
||||
! </vfs>
|
||||
! </libc>
|
||||
! </config>
|
||||
! </start>
|
||||
! </config>}
|
||||
@@ -442,9 +467,9 @@ Thereafter we declare all boot modules:
|
||||
|
||||
! set boot_modules {
|
||||
! core init timer audio_out_drv fb_drv ps2_drv ld.lib.so
|
||||
! libc_fs.lib.so libc.lib.so libc_log.lib.so libm.lib.so
|
||||
! libc.lib.so libm.lib.so
|
||||
! lwip.lib.so libpng.lib.so stdcxx.lib.so sdl.lib.so
|
||||
! pthread.lib.so zlib.lib.so tar_fs dosbox dosbox.tar
|
||||
! pthread.lib.so zlib.lib.so dosbox dosbox.tar
|
||||
! }
|
||||
! build_boot_image $boot_modules
|
||||
|
||||
@@ -496,19 +521,15 @@ application that is ported.
|
||||
Since 'ftime(3)' is a deprecated function anyway we change the code of
|
||||
DosBox to use 'gettimeofday(2)'.
|
||||
|
||||
After this was fixed we face another problem:
|
||||
After this was fixed, we face another problem:
|
||||
|
||||
! /src/genode/ports/contrib/dosbox-svn-3837/src/ints/int10_vesa.cpp:48:33: error:
|
||||
! unable to find string literal operator ‘operator"" VERSION’
|
||||
|
||||
The fix is quite simple and the compile error was due to the fact
|
||||
that Genode uses C++11 by now. It often happens that 3rd party code
|
||||
is not well tested with a C++11 enabled compiler. In any case a patch file
|
||||
should be created which will be applied when executing the fetch-rules:
|
||||
|
||||
! $(CONTRIB_DIR)/$(DOSBOX):
|
||||
! […]
|
||||
! $(VERBOSE)patch -N -p0 < src/app/dosbox/int10_vesa.patch
|
||||
is not well tested with a C++11 enabled compiler. In any case, a patch file
|
||||
should be created which will be applied when preparing the port.
|
||||
|
||||
Furthermore it would be reasonable to report the bug to the DosBox
|
||||
developers so it can be fixed upstream. We can then get rid of our
|
||||
@@ -537,13 +558,13 @@ Debugging the application
|
||||
DosBox was successfully compiled but unfortunately it did not run.
|
||||
To be honest that was expected and here the fun begins.
|
||||
|
||||
At this point there are several options to chose from. By running
|
||||
Genode/Fiasco.OC within Qemu we can use the kernel debugger (JDB)
|
||||
to take a deeper look at what went wrong (e.g. backtraces of the
|
||||
At this point, there are several options to chose from. By running
|
||||
Genode/Fiasco.OC within Qemu, we can use the kernel debugger (JDB)
|
||||
to take a deeper look at what went wrong (e.g., backtraces of the
|
||||
running processes, memory dumps of the faulted DosBox process etc.).
|
||||
Doing this can be quite taxing but fortunately Genode runs on multiple
|
||||
kernels and often problems on one kernel can be reproduced on another
|
||||
kernel. For this reason we choose Genode/Linux where we can use all
|
||||
kernel. For this reason, we choose Genode/Linux where we can use all
|
||||
the normal debugging tools like 'gdb(1)', 'valgrind(1)' and so on. Luckily
|
||||
for us, DosBox also fails to run on Genode/Linux. The debugging steps
|
||||
are naturally dependent on the ported software. In the case of DosBox,
|
||||
@@ -553,8 +574,8 @@ Linux as a host platform.
|
||||
For the sake of completeness here is a list of all files that were created by
|
||||
porting DosBox to Genode:
|
||||
|
||||
! ports/ports/dosbox.inc
|
||||
! ports/ports/dosbox.mk
|
||||
! ports/ports/dosbox.hash
|
||||
! ports/ports/dosbox.port
|
||||
! ports/run/dosbox.run
|
||||
! ports/src/app/dosbox/config.h
|
||||
! ports/src/app/dosbox/patches/bios.patch
|
||||
@@ -566,16 +587,32 @@ porting DosBox to Genode:
|
||||
[image dosbox]
|
||||
DosBox ported to Genode
|
||||
|
||||
Finally, after having tested that both the preparation-step and the
|
||||
build of DosBox work as expected, it is time to
|
||||
finalize the fingerprint stored in the _<genode-dir>/ports/ports/dosbox.hash_
|
||||
file. This can be done by copying the content of the
|
||||
_<genode-dir>/contrib/dosbox-dummy/dosbox.hash file_.
|
||||
Alternatively, you may invoke the _tool/ports/update_hash_ tool with the
|
||||
port name "dosbox" as argument. The next time, you
|
||||
invoke the prepare_port tool, do not specify the 'CHECK_HASH=no' argument.
|
||||
So the fingerprint check will validate that the _dosbox.hash_ file
|
||||
corresponds to your _dosbox.port_ file. From now on, the
|
||||
_<genode-dir>/contrib/dosbox-dummy_ directory will no longer be used because
|
||||
the _dosbox.hash_ file points to the port directory named after the real
|
||||
fingerprint.
|
||||
|
||||
|
||||
Native Genode port of a library
|
||||
###############################
|
||||
|
||||
Porting a library to be used natively on Genode is similar to porting
|
||||
an application to run natively on Genode. The source codes has to be
|
||||
an application to run natively on Genode. The source codes have to be
|
||||
obtained and, if needed, patched to run on Genode.
|
||||
As an example on how to port a library to natively run on Genode, we
|
||||
will describe the porting of SDL_net in more detail. Ported libraries
|
||||
are placed in the _libports_ repository of Genode.
|
||||
are placed in the _libports_ repository of Genode. But this is just a
|
||||
convention. Feel free to host your library port in a custom repository
|
||||
of your's.
|
||||
|
||||
|
||||
Checking requirements/dependencies
|
||||
@@ -592,85 +629,43 @@ process:
|
||||
! $ make > build.log 2>&1
|
||||
|
||||
|
||||
Creating the port Makefile
|
||||
==========================
|
||||
Creating the port file
|
||||
======================
|
||||
|
||||
We start by creating 'libports/ports/sdl_net.inc':
|
||||
We start by creating _<genode-dir>/libports/ports/sdl_net.port:
|
||||
|
||||
! SDL_NET_VERSION = 1.2.8
|
||||
! SDL_NET = SDL_net-$(SDL_NET_VERSION)
|
||||
|
||||
Following this we create the actual fetch-rules
|
||||
in _libports/ports/sdl_net.mk_
|
||||
|
||||
! include ports/sdl_net.inc
|
||||
! LICENSE := BSD
|
||||
! VERSION := 1.2.8
|
||||
! DOWNLOADS := sdl_net.archive
|
||||
!
|
||||
! SDL_NET_TGZ = $(SDL_NET).tar.gz
|
||||
! SDL_NET_URL = http://www.libsdl.org/projects/SDL_net/release/$(SDL_NET_TGZ)
|
||||
! URL(sdl_net) := http://www.libsdl.org/projects/SDL_net/release/SDL_net-$(VERSION).tar.gz
|
||||
! SHA(sdl_net) := fd393059fef8d9925dc20662baa3b25e02b8405d
|
||||
! DIR(sdl_net) := src/lib/sdl_net
|
||||
!
|
||||
! #
|
||||
! # Interface to top-level prepare Makefile
|
||||
! #
|
||||
! # Register SDL_net port as lower case to be consistent with the
|
||||
! # other libraries.
|
||||
! #
|
||||
! PORTS += sdl_net-$(SDL_NET_VERSION)
|
||||
!
|
||||
! prepare-sdl_net: $(CONTRIB_DIR)/$(SDL_NET) include/SDL/SDL_net.h
|
||||
!
|
||||
! $(CONTRIB_DIR)/$(SDL_NET): clean-sdl_net
|
||||
! PATCHES := src/lib/sdl_net/SDLnet.patch src/lib/sdl_net/SDL_net.h.patch
|
||||
|
||||
While extracting the archive, we omit certain directories and files that we
|
||||
do not need and that otherwise would only pollute the 'contrib' directory:
|
||||
|
||||
! #
|
||||
! # Port-specific local rules
|
||||
! #
|
||||
! $(DOWNLOAD_DIR)/$(SDL_NET_TGZ):
|
||||
! $(VERBOSE)wget -c -P $(DOWNLOAD_DIR) $(SDL_NET_URL) && touch $@
|
||||
!
|
||||
! $(CONTRIB_DIR)/$(SDL_NET): $(DOWNLOAD_DIR)/$(SDL_NET_TGZ)
|
||||
! $(VERBOSE)tar xfz $< \
|
||||
! --exclude Xcode --exclude VisualC --exclude Xcode-iOS \
|
||||
! --exclude VisualCE --exclude Watcom-OS2.zip --exclude debian \
|
||||
! -C $(CONTRIB_DIR) && touch $@
|
||||
! $(VERBOSE)patch -N -p0 < src/lib/sdl_net/SDLnet.patch
|
||||
In addition to the URL the SHA1 checksum of the SDL_net archive needs to
|
||||
specified because _tool/prepare_port_ validates the downloaded archive
|
||||
by using this hash.
|
||||
|
||||
Applications that want to use SDL_net have to include the 'SDL_net.h' header
|
||||
file. Hence it is necessary to make file visible to applications. This is
|
||||
done by creating a symbolic link from the original location to
|
||||
_libports/include/SDL/SDL_net.h_
|
||||
file. Hence it is necessary to make this file visible to applications. This is
|
||||
done by populating the _<genode-dir>/contrib/sdl-<hash>/include_ directory:
|
||||
|
||||
! #
|
||||
! # Install SDL_net headers
|
||||
! #
|
||||
! include/SDL/SDL_net.h:
|
||||
! $(VERBOSE)mkdir -p $(dir $@)
|
||||
! $(VERBOSE)ln -fs ../../$(CONTRIB_DIR)/$(SDL_NET)/SDL_net.h include/SDL/
|
||||
! DIRS := include/SDL
|
||||
! DIR_CONTENT(include/SDL) := src/lib/sdl_net/SDL_net.h
|
||||
|
||||
Since we created a symbolic link that is placed in Genode's _libports_
|
||||
repository,
|
||||
we have to provide a 'clean' rule. This rule is responsible for removing all
|
||||
extracted files and the link we created:
|
||||
For now, we also use a dummy hash in the _sdl_net.hash_ file like it was done
|
||||
while porting DosBox. We will replace the dummy hash with the proper one at
|
||||
the end.
|
||||
|
||||
! clean-sdl_net:
|
||||
! $(VERBOSE)rm -rf include/SDL/SDL_net.h
|
||||
! $(VERBOSE)rmdir include/SDL 2>/dev/null || true
|
||||
! $(VERBOSE)rm -rf $(CONTRIB_DIR)/$(SDL_NET)
|
||||
|
||||
_It is important to write the_ 'clean' _rule in way that does not remove_
|
||||
_files that are still needed by other components of Genode or ported_
|
||||
_applications. In this example we only delete include/SDL if it is_
|
||||
_empty. Otherwise_ 'rmdir(1)' _will not remove the directory and we_
|
||||
_simply ignore it._
|
||||
|
||||
Creating the build Makefile
|
||||
===========================
|
||||
|
||||
We create the build rules in _libports/lib/mk/sdl_net.mk_:
|
||||
|
||||
! include $(REP_DIR)/ports/sdl_net.inc
|
||||
! SDL_NET_DIR = $(REP_DIR)/contrib/$(SDL_NET)
|
||||
! SDL_NET_DIR := $(call select_from_ports,sdl_net)/src/lib/sdl_net
|
||||
!
|
||||
! SRC_C = $(notdir $(wildcard $(SDL_NET_DIR)/SDLnet*.c))
|
||||
!
|
||||
@@ -685,11 +680,11 @@ have to add the following statement to the 'mk' file:
|
||||
|
||||
! SHARED_LIB = yes
|
||||
|
||||
_If we omit this statement, Genode's build-system will automatically_
|
||||
_If we omit this statement, Genode's build system will automatically_
|
||||
_build SDL_net as a static library called_ 'sdl_net.lib.a' _that_
|
||||
_is linked directly into the application._
|
||||
|
||||
It is a reasonable to create a dummy application that uses the
|
||||
It is reasonable to create a dummy application that uses the
|
||||
library because it is only possible to build libraries automatically
|
||||
as a dependency of an application.
|
||||
|
||||
@@ -702,16 +697,15 @@ _libports/src/test/libports/sdl_net/target.mk_ with the following content:
|
||||
|
||||
! vpath main.cc $(PRG_DIR)/..
|
||||
|
||||
At this point we normally would also create _lib/import/import-sdl_net.mk_
|
||||
At this point we also create _lib/import/import-sdl_net.mk_
|
||||
with the following content:
|
||||
|
||||
! REP_INC_DIR += include/SDL
|
||||
! SDL_NET_PORT_DIR := $(call select_from_ports,sdl_net)
|
||||
! INC_DIR += $(SDL_NET_PORT_DIR)/include $(SDL_NET_PORT_DIR)/include/SDL
|
||||
|
||||
However in this case this is not necessary because _SDL_net_ depends on
|
||||
libSDL which already provides its own _import-sdl.mk_ file with exactly
|
||||
the same content. While preparing SDL_net we placed a symbolic link in
|
||||
just this directory and therefore every user of SDL_net already knows
|
||||
about this directory.
|
||||
Each port that depends on SDL_net and has added it to its LIBS variable
|
||||
will automatically include the _import-sdl_net.mk_ file and therefore
|
||||
will use the specified include directory to find the _SDL_net.h_ header.
|
||||
|
||||
|
||||
Compiling the library
|
||||
@@ -737,13 +731,13 @@ Porting applications or libraries to Genode always may involve this kind of
|
||||
choice. Which way is the best has to be decided by closely examining the
|
||||
matter at hand. Sometimes it is better to implement the missing functions
|
||||
and sometimes it is more beneficial to change the contributed code.
|
||||
In this case we opt for changing SDL_net because the former function is
|
||||
In this case, we opt for changing SDL_net because the former function is
|
||||
obsolete anyway and implementing 'gethostbyaddr(3)' involves changes to
|
||||
several libraries in Genode, namely libc and the network related
|
||||
libc plugin. Although we have to keep in mind that is likely to encounter
|
||||
libc plugin. Although we have to keep in mind that it is likely to encounter
|
||||
another application or library that also uses this function in the future.
|
||||
|
||||
With this change in place SDL_net compiles fine.
|
||||
With this change in place, SDL_net compiles fine.
|
||||
|
||||
_(*) Actually this function is implemented in the Genode's_ libc _but is_
|
||||
_only available by using libc_resolv which we did not do for the sake of_
|
||||
@@ -755,15 +749,16 @@ Testing the library
|
||||
|
||||
The freshly ported library is best tested with the application, which was the
|
||||
reason the library was ported in the first place, since it is unlikely that
|
||||
we port a library just for fun and profit. Therefore, it is not necessary to
|
||||
we port a library just for fun and no profit. Therefore, it is not necessary to
|
||||
write a run script for a library alone.
|
||||
|
||||
For the records, here is a list of all files that were created by
|
||||
porting SDL_net to Genode:
|
||||
|
||||
! libports/lib/mk/sdl_net.mk
|
||||
! libports/ports/sdl_net.inc
|
||||
! libports/ports/sdl_net.mk
|
||||
! libports/lib/mk/import/import-sdl_net.mk
|
||||
! libports/ports/sdl_net.hash
|
||||
! libports/ports/sdl_net.port
|
||||
! libports/src/lib/sdl_net/SDLnet.patch
|
||||
! libports/test/libports/sdl_net/target.mk
|
||||
|
||||
@@ -774,14 +769,14 @@ Porting an application to Genode's Noux runtime
|
||||
Porting an application to Genode's Noux runtime is basically the same as
|
||||
porting a program to natively run on Genode. The source code has to be
|
||||
prepared and, if needed, patched to run in Noux. However in contrast to
|
||||
this there are Noux build rules (_ports/mk/noux.mk_) that enable us to use
|
||||
this, there are Noux build rules (_ports/mk/noux.mk_) that enable us to use
|
||||
the original build-tool if it is based upon Autotools. Building the
|
||||
application is done within a cross-compile environment. In this environment
|
||||
all needed variables like 'CC', 'LD', 'CFLAGS' and so on are set to their
|
||||
proper values. In addition to these precautions, using _noux.mk_ simplifies certain things.
|
||||
The system-call handling/functions is/are implemented in the libc plugin
|
||||
_libc_noux_ (the source code is found in _ports/src/lib/libc_noux_). All
|
||||
application running in Noux have to be linked against this library which is
|
||||
applications running in Noux have to be linked against this library which is
|
||||
done implicitly by using the build rules of Noux.
|
||||
|
||||
As an example on how to port an application to Genode's Noux runtime, we
|
||||
@@ -801,58 +796,33 @@ process:
|
||||
! $ make > build.log 2>&1
|
||||
|
||||
|
||||
Creating the port Makefile
|
||||
==========================
|
||||
Creating the port file
|
||||
======================
|
||||
|
||||
We start by creating the port Makefile _ports/ports/tar.mk_:
|
||||
|
||||
! GNUTAR = tar-1.27
|
||||
! GNUTAR_TXZ = $(GNUTAR).tar.xz
|
||||
! GNUTAR_SIG = $(GNUTAR_TXZ).sig
|
||||
! GNUTAR_URL = http://ftp.gnu.org/gnu/tar
|
||||
! GNUTAR_KEY = GNU
|
||||
! LICENSE := GPLv3
|
||||
! VERSION := 1.27
|
||||
! DOWNLOADS := tar.archive
|
||||
!
|
||||
! URL(tar) := http://ftp.gnu.org/gnu/tar/tar-$(VERSION).tar.xz
|
||||
! SHA(tar) := 790cf784589a9fcc1ced33517e71051e3642642f
|
||||
! SIG(tar) := ${URL(tar)}.sig
|
||||
! KEY(tar) := GNU
|
||||
! DIR(tar) := src/noux-pkg/tar
|
||||
|
||||
_As of release 13.08 Genode includes integrity checks for downloaded_
|
||||
_3rd-party software. The signature of the downloaded archive will be_
|
||||
_checked prior to extraction. New ports to Genode should always use_
|
||||
_this checks if it is possible. Unfortunately not all projects provide signature_
|
||||
_files though._
|
||||
_As of version 14.05, Genode does not check the signature specified via_
|
||||
_the SIG and KEY declaration but relies the SHA checksum only. However,_
|
||||
_as signature checks are planned in the future, we use to include the_
|
||||
_respective declarations if signature files are available._
|
||||
|
||||
The remaining part of the port Makefile looks like this:
|
||||
|
||||
! #
|
||||
! # Interface to top-level prepare Makefile
|
||||
! #
|
||||
! PORTS += $(GNUTAR)
|
||||
!
|
||||
! prepare:: $(CONTRIB_DIR)/$(GNUTAR)
|
||||
!
|
||||
! #
|
||||
! # Port-specific local rules
|
||||
! #
|
||||
! $(DOWNLOAD_DIR)/$(GNUTAR_TXZ):
|
||||
! $(VERBOSE)wget -c -P $(DOWNLOAD_DIR) $(GNUTAR_URL)/$(GNUTAR_TXZ) && touch $@
|
||||
!
|
||||
! $(DOWNLOAD_DIR)/$(GNUTAR_SIG):
|
||||
! $(VERBOSE)wget -c -P $(DOWNLOAD_DIR) $(GNUTAR_URL)/$(GNUTAR_SIG) && touch $@
|
||||
!
|
||||
! $(CONTRIB_DIR)/$(GNUTAR): $(DOWNLOAD_DIR)/$(GNUTAR_TXZ).verified
|
||||
! $(VERBOSE)tar xfJ $(<:.verified=) -C $(CONTRIB_DIR) && touch $@
|
||||
!
|
||||
! $(DOWNLOAD_DIR)/$(GNUTAR_TXZ).verified: $(DOWNLOAD_DIR)/$(GNUTAR_TXZ) \
|
||||
! $(DOWNLOAD_DIR)/$(GNUTAR_SIG)
|
||||
! $(VERBOSE)$(SIGVERIFIER) $(DOWNLOAD_DIR)/$(GNUTAR_TXZ) \
|
||||
! $(DOWNLOAD_DIR)/$(GNUTAR_SIG) $(GNUTAR_KEY)
|
||||
! $(VERBOSE)touch $@
|
||||
|
||||
Its almost the same as the previous shown port Makefile but adds rules for
|
||||
verifying the archive signature.
|
||||
While porting GNU tar we will use a dummy hash as well.
|
||||
|
||||
|
||||
Creating the build rule
|
||||
=======================
|
||||
|
||||
Build rules for Noux packages are located in _ports/src/noux-pkgs_.
|
||||
Build rules for Noux packages are located in _<genode-dir>/ports/src/noux-pkgs_.
|
||||
|
||||
The _tar/target.mk_ corresponding to GNU tar looks like this:
|
||||
|
||||
@@ -964,13 +934,8 @@ Now we can trigger the compilation of tar by executing
|
||||
_At least on the first compilation attempt, it is wise to unset_ 'VERBOSE'
|
||||
_because it enables us to see the whole output of the_ 'configure' _process._
|
||||
|
||||
If configure is not able to find a particular header file the first place
|
||||
to look is generally _libports/include/libc_. This directory is populated by
|
||||
the rules in _libports/ports/libc.mk_. So if a header file is indeed
|
||||
missing, adding the relevant header there is necessary.
|
||||
|
||||
By now Genode provides almost all libc header files that are used by
|
||||
typical POSIX programs. In most cases it is rather a matter of enabling
|
||||
By now, Genode provides almost all libc header files that are used by
|
||||
typical POSIX programs. In most cases, it is rather a matter of enabling
|
||||
the right definitions and compilation flags. It might be worth to take a
|
||||
look at FreeBSD's ports tree because Genode's libc is based upon the one
|
||||
of FreeBSD 8.2.0 and if certain changes to the contributed code are needed,
|
||||
@@ -1060,7 +1025,7 @@ system call and it is difficult to see in which.
|
||||
|
||||
Anyhow, 'fstatat' is not properly implemented. At this point, we either have
|
||||
to add this function to the Genode's libc or rather add it to libc_noux.
|
||||
If we add it to the libc not only applications running in Noux will
|
||||
If we add it to the libc, not only applications running in Noux will
|
||||
benefit but all applications using the libc. Implementing it in
|
||||
libc_noux is the preferred way if there are special circumstances because
|
||||
we have to treat the function differently when used in Noux (e.g. 'fork').
|
||||
@@ -1068,10 +1033,12 @@ we have to treat the function differently when used in Noux (e.g. 'fork').
|
||||
For the sake of completeness here is a list of all files that were created by
|
||||
porting GNU tar to Genode's Noux runtime:
|
||||
|
||||
! ports/ports/tar.mk
|
||||
! ports/ports/tar.hash
|
||||
! ports/ports/tar.port
|
||||
! ports/run/noux_tar.run
|
||||
! ports/src/noux-pkg/tar/target.mk
|
||||
|
||||
|
||||
Extensive build rules example
|
||||
=============================
|
||||
|
||||
@@ -1091,7 +1058,7 @@ porting a program to Noux:
|
||||
! --sbindir=/bin \
|
||||
! --libexecdir=/bin
|
||||
|
||||
In addition to the normal configure options we have to also define the
|
||||
In addition to the normal configure options, we have to also define the
|
||||
path prefixes. The OpenSSH build system embeds certain paths in the
|
||||
ssh binary, which need to be changed for Noux.
|
||||
|
||||
@@ -1106,7 +1073,7 @@ Noux build rules.
|
||||
|
||||
! LIBS += libcrypto libssl zlib libc_resolv
|
||||
|
||||
As OpenSSH depends on several libraries we need to include these in the
|
||||
As OpenSSH depends on several libraries, we need to include these in the
|
||||
build Makefile. These libraries are runtime dependencies and need to be
|
||||
present when running OpenSSH in Noux.
|
||||
|
||||
@@ -1138,7 +1105,7 @@ way is to do it before building the Noux package:
|
||||
The target _noux_built.tag_ is a special target defined by the Noux build
|
||||
rules. It will be used by the build rules when building the Noux package.
|
||||
We add the 'Makefile_patch' target as a dependency to it. So after configure
|
||||
is executed the generated Makefile will be patched.
|
||||
is executed, the generated Makefile will be patched.
|
||||
|
||||
Autoconf's configure script checks if all requirements are fulfilled and
|
||||
therefore, tests if all required libraries are installed on the host system.
|
||||
@@ -1162,6 +1129,7 @@ script by providing dummy libraries:
|
||||
! libz.a:
|
||||
! $(VERBOSE)$(AR) -rc $@
|
||||
|
||||
|
||||
Porting devices drivers
|
||||
#######################
|
||||
|
||||
@@ -1194,14 +1162,15 @@ Basic driver structure
|
||||
|
||||
The first step in porting a driver is to identify the driver code that has to be
|
||||
ported. Once the code is located, we usually create a new Genode repository and
|
||||
write a Makefile that downloads and extracts the code to a directory called
|
||||
_contrib_ (see 'dde_linux/Makefile') thus implementing the 'make prepare'
|
||||
command for the repository. Having the source code ready, there are three main
|
||||
tasks the environment must implement. The first is the driver back end, which is
|
||||
responsible for raw device access using Genode primitives, the actual
|
||||
environment that emulates Linux function calls the driver code is using, and the
|
||||
front end, which exposes for example some Genode-session interface (like NIC or
|
||||
block session) that client applications can connect to.
|
||||
write a port file to download and extract the code. It is good practice to name
|
||||
the port and the hash file like the new repository, e.g. _dde_linux.port_ if
|
||||
the repository directory is called _<genode-dir>/repos/dde_linux_.
|
||||
Having the source code ready, there are three main tasks the environment must
|
||||
implement. The first is the driver back end, which is responsible for raw device
|
||||
access using Genode primitives, the actual environment that emulates Linux
|
||||
function calls the driver code is using, and the front end, which exposes for
|
||||
example some Genode-session interface (like NIC or block session) that client
|
||||
applications can connect to.
|
||||
|
||||
|
||||
Further preparations
|
||||
@@ -1241,14 +1210,14 @@ following code snippet in your _*.mk_ file which does the trick:
|
||||
!# Determine the header files included by the contrib code. For each
|
||||
!# of these header files we create a symlink to _lx_emul.h_.
|
||||
!#
|
||||
!GEN_INCLUDES := $(shell grep -rh "^\#include .*\/" $(CONTRIB_DIR) |\
|
||||
!GEN_INCLUDES := $(shell grep -rh "^\#include .*\/" $(DRIVER_CONTRIB_DIR) |\
|
||||
! sed "s/^\#include [^<\"]*[<\"]\([^>\"]*\)[>\"].*/\1/" | \
|
||||
! sort | uniq)
|
||||
!
|
||||
!#
|
||||
!# Filter out original Linux headers that exist in the contrib directory
|
||||
!#
|
||||
!NO_GEN_INCLUDES := $(shell cd $(CONTRIB_DIR); find -name "*.h" | sed "s/.\///" | \
|
||||
!NO_GEN_INCLUDES := $(shell cd $(DRIVER_CONTRIB_DIR); find -name "*.h" | sed "s/.\///" | \
|
||||
! sed "s/.*include\///")
|
||||
!GEN_INCLUDES := $(filter-out $(NO_GEN_INCLUDES),$(GEN_INCLUDES))
|
||||
!
|
||||
@@ -1275,6 +1244,12 @@ following code snippet in your _*.mk_ file which does the trick:
|
||||
Make sure 'LX_INC_DIR' is the directory containing the _lx_emul.h_ file. Note
|
||||
that 'GEN_INC' is added to your 'INC_DIR' variable.
|
||||
|
||||
The 'DRIVER_CONTRIB_DIR' variable is defined by calling the _select_from_port_
|
||||
function at the beginning of a Makefile or a include file, which is used by
|
||||
all other Makefiles:
|
||||
|
||||
! DRIVER_CONTRIB_DIR := $(call select_from_ports,driver_repo)/src/lib/driver_repo
|
||||
|
||||
The process of function definition and type declaration continues until the code
|
||||
compiles. This process can be quite tiresome. When the driver code finally compiles, the
|
||||
next stage is linking. This will of course lead to another whole set of errors
|
||||
@@ -1428,7 +1403,7 @@ When 'probe' returns successful, you may either test other driver functions by
|
||||
hand or start building the front-end.
|
||||
|
||||
|
||||
The front-end
|
||||
The front end
|
||||
=============
|
||||
|
||||
An important design question is how the front end is attached to the driver. In
|
||||
|
||||
@@ -762,17 +762,19 @@ NOVA microhypervisor
|
||||
The port of VirtualBox to Genode prompted us to improve the NOVA platform in
|
||||
the following respects.
|
||||
|
||||
NOVA used to omit the saving and restoring of the FPU state of the guest OS
|
||||
during the world switch between the guest OS and the virtual machine monitor
|
||||
(VMM). With the Vancouver VMM, which is traditionally used on NOVA, the
|
||||
omission of FPU context handling did not pose any problem because Vancouver
|
||||
did not touch the FPU. So the FPU context of the guest was always preserved
|
||||
NOVA used to omit the propagation of the FPU state of the guest OS to the
|
||||
virtual machine monitor (VMM) during the world switch between the guest OS and
|
||||
the VMM. With the Vancouver VMM, which is traditionally used on NOVA, this
|
||||
omission did not pose any problem because Vancouver would never touch the FPU
|
||||
state of the guest. So the FPU context of the guest was always preserved
|
||||
throughout the handling of virtualization events. However, in contrast to the
|
||||
Vancouver VMM, VirtualBox relies on the FPU. Without properly saving and
|
||||
restoring the FPU state on each VM-enter/exit, both the guest OS and
|
||||
VirtualBox would corrupt each other's FPU state. After first implementing an
|
||||
Vancouver VMM, VirtualBox relies on the propagation of the FPU state between
|
||||
the guest running in VT-X non-root mode and the guest running within the
|
||||
VirtualBox recompiler. Without properly propagating the FPU state between both
|
||||
virtualization back ends, both the guest OS in non-root mode and VirtualBox's
|
||||
recompiler would corrupt each other's FPU state. After first implementing an
|
||||
interim solution in our custom version of the kernel, the missing FPU context
|
||||
handling had been implemented in the upstream version of NOVA as well.
|
||||
propagation had been implemented in the upstream version of NOVA as well.
|
||||
|
||||
In contrast to most kernels, NOVA did not allow a thread to yield its current
|
||||
time slice to another thread. The only way to yield CPU time was to block on
|
||||
|
||||
1124
doc/release_notes-14-05.txt
Normal file
1124
doc/release_notes-14-05.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,9 +0,0 @@
|
||||
File terminal is a service that provides Genode's Terminal_session interface
|
||||
for a given file via a File_system_session.
|
||||
|
||||
! <config>
|
||||
! <policy label="client1" filename="test.txt" />
|
||||
! <policy label="client2" filename="file.dat" io_buffer_size="4K"/>h
|
||||
! </config>
|
||||
|
||||
To keep things simple a client can only open one file at the moment.
|
||||
@@ -1,3 +0,0 @@
|
||||
TARGET = tcp_terminal
|
||||
SRC_CC = main.cc
|
||||
LIBS = libc libc_lwip_nic_dhcp libc_log libc_lock_pipe
|
||||
@@ -1,12 +0,0 @@
|
||||
<config>
|
||||
<start name="hello_server">
|
||||
<resource name="RAM" quantum="256K"/>
|
||||
<provides><service name="Hello"/></provides>
|
||||
</start>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="256K"/>
|
||||
</start>
|
||||
<start name="hello_client">
|
||||
<resource name="RAM" quantum="256K"/>
|
||||
</start>
|
||||
</config>
|
||||
@@ -1,2 +0,0 @@
|
||||
LIBAV := libav-0.8.2
|
||||
REP_INC_DIR += contrib/$(LIBAV)
|
||||
@@ -1,3 +0,0 @@
|
||||
include $(call select_from_repositories,lib/import/import-av.inc)
|
||||
|
||||
REP_INC_DIR += contrib/$(LIBAV)/libavcodec
|
||||
@@ -1,4 +0,0 @@
|
||||
include $(call select_from_repositories,lib/import/import-av.inc)
|
||||
|
||||
REP_INC_DIR += contrib/$(LIBAV)/libavutil \
|
||||
include/libavutil
|
||||
@@ -1,4 +0,0 @@
|
||||
EXPAT_VER = 2.1.0
|
||||
EXPAT = expat-$(EXPAT_VER)
|
||||
|
||||
REP_INC_DIR += contrib/$(EXPAT)/lib
|
||||
@@ -1,2 +0,0 @@
|
||||
REP_INC_DIR += include/icu/common
|
||||
REP_INC_DIR += include/icu/i18n
|
||||
@@ -1 +0,0 @@
|
||||
REP_INC_DIR += include/jbig2dec
|
||||
@@ -1,3 +0,0 @@
|
||||
JPEG = jpeg-7
|
||||
REP_INC_DIR += contrib/$(JPEG) \
|
||||
include/jpeg
|
||||
@@ -1,33 +0,0 @@
|
||||
#
|
||||
# Add generic libc headers to standard include search paths
|
||||
#
|
||||
REP_INC_DIR += include/libc
|
||||
|
||||
#
|
||||
# Add platform-specific libc headers to standard include search paths
|
||||
#
|
||||
ifeq ($(filter-out $(SPECS),x86),)
|
||||
ifeq ($(filter-out $(SPECS),32bit),)
|
||||
LIBC_REP_INC_DIR = include/libc-i386
|
||||
endif # 32bit
|
||||
|
||||
ifeq ($(filter-out $(SPECS),64bit),)
|
||||
LIBC_REP_INC_DIR = include/libc-amd64
|
||||
endif # 32bit
|
||||
LIBC_REP_INC_DIR += include/libc-x86
|
||||
endif # x86
|
||||
|
||||
ifeq ($(filter-out $(SPECS),arm),)
|
||||
LIBC_REP_INC_DIR = include/libc-arm
|
||||
endif # ARM
|
||||
|
||||
#
|
||||
# If we found no valid include path for the configured target platform,
|
||||
# we have to prevent the build system from building the target. This is
|
||||
# done by adding an artificial requirement.
|
||||
#
|
||||
ifeq ($(LIBC_REP_INC_DIR),)
|
||||
REQUIRES += libc_support_for_your_target_platform
|
||||
endif
|
||||
|
||||
REP_INC_DIR += $(LIBC_REP_INC_DIR)
|
||||
@@ -1 +0,0 @@
|
||||
REP_INC_DIR += include/exfat
|
||||
@@ -1 +0,0 @@
|
||||
REP_INC_DIR += include/fuse-ext2
|
||||
@@ -1 +0,0 @@
|
||||
REP_INC_DIR += include/iconv
|
||||
@@ -1 +0,0 @@
|
||||
REP_INC_DIR += include/ntfs-3g
|
||||
@@ -1 +0,0 @@
|
||||
REP_INC_DIR += include/libpng
|
||||
@@ -1 +0,0 @@
|
||||
REP_INC_DIR += include/libssh
|
||||
@@ -1,10 +0,0 @@
|
||||
REP_INC_DIR += include/openssl
|
||||
|
||||
ifeq ($(filter-out $(SPECS),x86_32),)
|
||||
TARGET_CPUARCH=x86_32
|
||||
else ifeq ($(filter-out $(SPECS),x86_64),)
|
||||
TARGET_CPUARCH=x86_64
|
||||
endif
|
||||
|
||||
# include architecture specific opensslconf.h
|
||||
REP_INC_DIR += src/lib/openssl/$(TARGET_CPUARCH)
|
||||
@@ -1 +0,0 @@
|
||||
REP_INC_DIR += include/lua
|
||||
@@ -1 +0,0 @@
|
||||
REP_INC_DIR += include/lua
|
||||
@@ -1 +0,0 @@
|
||||
REP_INC_DIR += include/lwip
|
||||
@@ -1,3 +0,0 @@
|
||||
MPC = mpc-0.9
|
||||
|
||||
REP_INC_DIR += include/mpc
|
||||
@@ -1 +0,0 @@
|
||||
REP_INC_DIR += include/mpfr
|
||||
@@ -1 +0,0 @@
|
||||
REP_INC_DIR += include/mupdf
|
||||
@@ -1 +0,0 @@
|
||||
REP_INC_DIR += include/ncurses
|
||||
@@ -1 +0,0 @@
|
||||
REP_INC_DIR += include/openjpeg
|
||||
@@ -1 +0,0 @@
|
||||
REP_INC_DIR += include/pcre
|
||||
@@ -1 +0,0 @@
|
||||
REP_INC_DIR += include/SDL
|
||||
@@ -1,14 +0,0 @@
|
||||
REP_INC_DIR += include/stdcxx
|
||||
REP_INC_DIR += include/stdcxx/std
|
||||
REP_INC_DIR += include/stdcxx/c_std
|
||||
REP_INC_DIR += include/stdcxx/c_global
|
||||
REP_INC_DIR += include/stdcxx-genode
|
||||
|
||||
LIBS += libc
|
||||
include $(call select_from_repositories,lib/import/import-libc.mk)
|
||||
|
||||
# prevent gcc headers from defining mbstate
|
||||
CC_OPT += -D_GLIBCXX_HAVE_MBSTATE_T
|
||||
|
||||
# use compiler-builtin atomic operations
|
||||
CC_OPT += -D_GLIBCXX_ATOMIC_BUILTINS_4
|
||||
@@ -1 +0,0 @@
|
||||
REP_INC_DIR += include/zlib
|
||||
@@ -1,11 +0,0 @@
|
||||
include $(REP_DIR)/lib/mk/av.inc
|
||||
|
||||
include $(REP_DIR)/lib/import/import-avcodec.mk
|
||||
|
||||
LIBAVCODEC_DIR = $(REP_DIR)/contrib/$(LIBAV)/libavcodec
|
||||
|
||||
include $(LIBAVCODEC_DIR)/Makefile
|
||||
|
||||
LIBS += zlib
|
||||
|
||||
vpath % $(LIBAVCODEC_DIR)
|
||||
@@ -1,12 +0,0 @@
|
||||
#
|
||||
# FAT File System Module using a Block session as disk I/O backend
|
||||
#
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/lib/ffat/contrib
|
||||
|
||||
SRC_C = ff.c ccsbcs.c
|
||||
SRC_CC = diskio_block.cc
|
||||
|
||||
vpath % $(REP_DIR)/src/lib/ffat/
|
||||
vpath % $(REP_DIR)/contrib/ff007e/src
|
||||
vpath % $(REP_DIR)/contrib/ff007e/src/option
|
||||
@@ -1,14 +0,0 @@
|
||||
include $(REP_DIR)/ports/fribidi.inc
|
||||
|
||||
FRIBIDI_DIR = $(REP_DIR)/contrib/$(FRIBIDI)
|
||||
|
||||
LIBS += libc
|
||||
INC_DIR += $(FRIBIDI_DIR) $(REP_DIR)/src/lib/fribidi $(REP_DIR)/include/fribidi
|
||||
SRC_C = $(notdir $(wildcard $(FRIBIDI_DIR)/lib/*.c))
|
||||
|
||||
CC_OPT += -DHAVE_CONFIG_H
|
||||
CC_WARN =
|
||||
|
||||
vpath %.c $(FRIBIDI_DIR)/lib
|
||||
|
||||
SHARED_LIB = yes
|
||||
@@ -1,13 +0,0 @@
|
||||
GMP_DIR = $(REP_DIR)/contrib/gmp-4.3.2
|
||||
|
||||
ifeq ($(wildcard $(GMP_DIR)),)
|
||||
REQUIRES += prepare_gmp
|
||||
endif
|
||||
|
||||
include $(REP_DIR)/lib/import/import-gmp.mk
|
||||
|
||||
LIBS += libc
|
||||
|
||||
CC_OPT += -DHAVE_CONFIG_H -D__GMP_WITHIN_GMP
|
||||
|
||||
INC_DIR += $(REP_DIR)/include/gcc
|
||||
@@ -1,7 +0,0 @@
|
||||
LIBS = libc
|
||||
|
||||
SRC_CC = plugin.cc
|
||||
|
||||
vpath %.cc $(REP_DIR)/src/lib/libc_block
|
||||
|
||||
SHARED_LIB = yes
|
||||
@@ -1,12 +0,0 @@
|
||||
FFAT_DIR = $(REP_DIR)/contrib/ff007e
|
||||
|
||||
ifeq ($(wildcard $(FFAT_DIR)),)
|
||||
REQUIRES += prepare_ffat
|
||||
endif
|
||||
|
||||
SRC_CC = plugin.cc
|
||||
LIBS += libc ffat_block
|
||||
|
||||
vpath plugin.cc $(REP_DIR)/src/lib/libc_ffat
|
||||
|
||||
SHARED_LIB = yes
|
||||
@@ -1,7 +0,0 @@
|
||||
SRC_CC = plugin.cc
|
||||
LIBS += libc
|
||||
INC_DIR += $(REP_DIR)/src/lib/libc
|
||||
|
||||
vpath plugin.cc $(REP_DIR)/src/lib/libc_fs
|
||||
|
||||
SHARED_LIB = yes
|
||||
@@ -1,6 +0,0 @@
|
||||
SRC_CC = plugin.cc
|
||||
LIBS += libc
|
||||
|
||||
vpath plugin.cc $(REP_DIR)/src/lib/libc_log
|
||||
|
||||
SHARED_LIB = yes
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user