Compare commits

..

366 Commits

Author SHA1 Message Date
Luoyuan Xiao ba3fcb2c56
Merge pull request #395 from shzhxh/light-merge
light board support
2022-10-20 04:23:10 -04:00
Luoyuan Xiao 0258181a7a Merge remote-tracking branch 'remotes/origin/master' into xly/master 2022-10-20 10:57:15 +08:00
Luoyuan Xiao 92df4cb134
Merge pull request #394 from YdrMaster/main
使用 feature 控制哪吒打开所有串口
2022-10-16 21:58:54 -04:00
YdrMaster 587b591f2b feat(drivers): 基于新的 feature,打开全志所有串口外设
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-17 08:06:25 +08:00
YdrMaster f53587c78f
Merge pull request #392 from YdrMaster/main
fix(zCore): 支持核数变成 5,以支持 u740 的 1-4 号核
2022-10-16 19:45:37 +08:00
YdrMaster b188c2f9fc fix(zCore): 支持核数变成 5,以支持 u740 的 1-4 号核
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-14 17:22:48 +08:00
YdrMaster c07cf1f5f0
Merge pull request #391 from YdrMaster/main
fix(zCore): nezha 上启动需要更大的启动堆
2022-10-14 12:18:55 +08:00
YdrMaster 76155047aa fix(zCore): nezha 上启动需要更大的启动堆
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-14 10:33:05 +08:00
YdrMaster 2a0d7b20cc
Merge pull request #390 from YdrMaster/dev-alloc
在 risc-v64 和 aarch64 上实现动态内核堆
2022-10-13 16:57:43 +08:00
YdrMaster 502adc8600 fix(zCore): 多核启动需要更多内存
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-13 15:58:48 +08:00
YdrMaster e9c47b9240 docs: 补充一些文档
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-13 15:52:52 +08:00
YdrMaster 6be657d777 feat(zCore): 大大降低 riscv64 和 aarch64 启动的内存需求
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-13 15:16:07 +08:00
YdrMaster a6db4e4cad build(zCore): update Cargo.toml
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-13 15:16:07 +08:00
YdrMaster 2dcddd6376 refactor(zCore): 修改 riscv64 和 aarch64 的内存分配,用同一个分配器分配内核堆和页帧
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-13 15:16:07 +08:00
Zhenxing d9b4252480
Merge pull request #389 from yuoo655/nvme
add nvme driver
2022-10-13 15:08:49 +08:00
Zhenxing 81912dd90f
Merge branch 'master' into nvme 2022-10-13 13:59:30 +08:00
YdrMaster a2899a3541
Merge pull request #381 from YdrMaster/dev-thead
feat: 增加 feature thead-maee,设置时为 pte 补充 平头哥的 vm flag 位
2022-10-13 13:55:06 +08:00
yuoo655 69e014493d add nvme driver 2022-10-13 10:13:24 +08:00
YdrMaster 6710c68df2 docs: update README for reinvoke ci
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-13 09:27:54 +08:00
Luoyuan Xiao 72bdc21c1a c910 development readme 2022-10-12 18:02:52 +08:00
YdrMaster fe4de7ca0c docs: update README.md
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-12 15:43:04 +08:00
YdrMaster e7cff60008 fix: fix ci for xtask
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-12 15:27:05 +08:00
YdrMaster e7b3174921 build: 支持通过配置文件配置硬件编译选项
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-12 15:14:02 +08:00
YdrMaster bccedf481d build: cleanup features for kernel-hal and zCore
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-12 12:38:53 +08:00
YdrMaster 6726dc2779 build: rename and cleanup features for hardwares
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-12 11:52:30 +08:00
YdrMaster b202762e00 build: remove kernel-hal/link-user-img
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-12 11:37:05 +08:00
YdrMaster f715165fc7 build: update command-ext to os-xtask-utils
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-10 17:46:18 +08:00
Luoyuan Xiao 6e4d6160d9 add C910 doc 2022-10-10 17:18:48 +08:00
YdrMaster ff4e1d95ee feat: board-vision 明确为 board-no-pci,增加 cr1825 上文档
build: 更新到 sbi-rt 0.0.2

Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-10 11:15:37 +08:00
YdrMaster 7a8bc0c782 feat: try SO bit
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-10 10:06:18 +08:00
YdrMaster ae914cec8e fix: sbi probe
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-09 09:04:50 +08:00
YdrMaster cb7a001c31 build: update sbi-rt
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-08 15:36:14 +08:00
YdrMaster d373e15a9f build(xtask): replace lazy_static with once_cell
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-08 09:28:33 +08:00
YdrMaster fe432a558a build: update deps
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-08 09:20:32 +08:00
YdrMaster 6329b8727c feat: try thead
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-10-08 09:20:32 +08:00
Luoyuan Xiao 3e141a8db9
Merge pull request #379 from shzhxh/master
修改Makefile以减小测试镜像的大小;添加星光开发板所需的二进制以优化编译步骤
2022-10-01 18:49:58 +08:00
Luoyuan Xiao 588b0601e7
Update README-D1.md 2022-09-30 22:48:21 +08:00
Luoyuan Xiao 08df82fc43 Support T-HEAD C910 Light val board 2022-09-30 22:45:44 +08:00
shzhxh 5a1135b412 修改Makefile以减小测试镜像的大小;添加星光开发板所需的二进制以优化编译步骤 2022-09-27 13:27:10 +08:00
Yiren Zhang 38902a5b9a
Merge pull request #375 from DeathWish5/master
Simulating a fast disk with physics cores and more elegent porting about fu740
2022-09-26 15:27:08 +08:00
YdrMaster 19568bd2bb
Merge pull request #378 from shzhxh/master
add 'cargo bin' test in CI
2022-09-23 16:47:42 +08:00
shzhxh 79fb4fe0d4 add 'cargo bin' test in CI 2022-09-23 16:07:38 +08:00
Yiren Zhang ddeba2fec7
Merge branch 'master' into master 2022-09-23 15:18:19 +08:00
yfblock 822e30152a
修复了 riscv 平台 cargo bin 编译错误 (#377)
* 修复了 riscv 平台 cargo bin 编译错误

* Update build.rs

* Update build.rs
2022-09-23 08:38:01 +08:00
DeathWish5 6101d14254 cargo doc fix 2022-09-22 14:27:42 +08:00
DeathWish5 b168bce495 cargo fmt and clippy 2022-09-21 23:01:04 +08:00
DeathWish5 566bbe97db fu740 can use all the memory 2022-09-21 22:15:57 +08:00
DeathWish5 5e4642995d rename some mpsc_queue interface 2022-09-21 18:03:30 +08:00
DeathWish5 7e13a6bf9c merge master form rcore-os 2022-09-21 18:00:20 +08:00
DeathWish5 69804e142e Merge branch 'master' of github.com:rcore-os/zCore 2022-09-21 17:48:51 +08:00
DeathWish5 2b9608079c feat: simulating a fast disk with a core 2022-09-20 21:02:10 +08:00
Luoyuan Xiao ea7324ff2e
Merge pull request #374 from workerwork/master
fix: 删除 libc-test 不需要的文件
2022-09-16 18:07:24 +08:00
Luoyuan Xiao f9adf71924
Merge pull request #373 from elliott10/master
Support for FU740 board
2022-09-16 18:06:18 +08:00
Luoyuan Xiao 7be9f36ae9 combining makefile target for riscv64 image 2022-09-16 17:30:36 +08:00
workerwork 5528f51e00 fix: 删除 libc-test 不必要的文件 2022-09-16 16:43:02 +08:00
workerwork c2973bb036 fix: 删除 libc-test 不需要的文件 2022-09-16 16:39:16 +08:00
Luoyuan Xiao b08d291ac2 update tests 2022-09-15 11:21:04 +08:00
Luoyuan Xiao 53c4f7df36 modified boot.asm 2022-09-14 21:05:36 +08:00
Luoyuan Xiao 3d64bda6fd fix submodule linux-user and net temp files 2022-09-14 18:48:33 +08:00
Luoyuan Xiao 9f4563cfbf modified README 2022-09-14 11:08:07 +08:00
Luoyuan Xiao 318b2a93a4 modified docs 2022-09-14 10:53:09 +08:00
Luoyuan Xiao 5ca2d05e7b Merge branch 'xly/zCore/master' 2022-09-14 10:14:52 +08:00
Luoyuan Xiao 6f763b789b
Merge pull request #372 from YdrMaster/main
修改 README
2022-09-13 08:43:04 +08:00
YdrMaster b14a0dff33 docs: 修改方框
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-09-10 10:07:01 +08:00
YdrMaster 38ff054369 fix(ci): 修正脚本
docs: 同步英文版自述文件
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-09-10 09:58:27 +08:00
YdrMaster 5bcbcd53b3 docs: 更新自述文件,增加命令递归关系图
refacotr(xtask): 移除 initialize,改为 zircon-init

refacotr(xtask): 只要 bin + feature linux,就递归 image

Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-09-10 08:51:15 +08:00
YdrMaster 9f58d51bcd
Merge pull request #370 from workerwork/master
docs: add visionfive support doc
2022-09-09 17:17:04 +08:00
Luoyuan Xiao 7b37df3359 Add README-fu740.md for fu740 and clean dtb mem range 2022-09-09 14:59:42 +08:00
workerwork 95cb3eb2de docs: add visionfive support doc 2022-09-09 14:57:01 +08:00
Luoyuan Xiao f5075edaa4 Add firmware for aarch64 and riscv
Regain "make run" for riscv d1 platform
2022-09-09 14:09:47 +08:00
Luoyuan Xiao b743ed754f Merge branch 'zCore/fu740' into rcore-os/zCore/master 2022-09-09 13:47:22 +08:00
Luoyuan Xiao b9286f834d update kernel-sync version 2022-09-07 14:45:23 +08:00
Luoyuan Xiao 34e08b5240 Merge remote-tracking branch 'OSLab-zCore/zCore/u740'
Sorting out the startup process
2022-09-07 13:27:59 +08:00
Luoyuan Xiao fb15105dea
Merge pull request #369 from workerwork/master
feat: support visionfive
2022-09-06 21:20:23 +08:00
workerwork 55b3145442 feat: support visionfive 2022-09-06 17:13:56 +08:00
Luoyuan Xiao a2483e1f4f
Merge pull request #368 from YdrMaster/main
fix: 内核链接位置提前,初始映射 64 GiB 以支持较大的物理内存
2022-09-06 11:05:06 +08:00
YdrMaster 16772b9363 refacotr: 升级页表库,启动时直接映射物理地址空间的前 128 GiB,包括内核之前的
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-09-06 09:45:37 +08:00
YdrMaster 6994330864 cleanup
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-09-05 14:32:06 +08:00
YdrMaster 227956d5df fix: 初始映射多映点
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-09-05 14:00:31 +08:00
YdrMaster 5b4b399f75 update
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-09-05 09:18:51 +08:00
YdrMaster e594a7b96e
Merge pull request #366 from YdrMaster/main
fix: 修复定时 CI 不过的问题
2022-08-19 17:08:56 +08:00
YdrMaster 77062c9a02 fix: 修复定时 CI 不过的问题
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-08-19 16:15:30 +08:00
YdrMaster 110d92264d
Merge pull request #365 from YdrMaster/main
fix: 移除 lfs
2022-08-17 09:17:11 +08:00
YdrMaster 8a0fd10268 fix: 没有默认的 ZBI 了,都用 core-tests
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-08-16 16:03:02 +08:00
YdrMaster 99713908aa fix: donnot cache from github
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-08-16 15:08:09 +08:00
YdrMaster 60829f10c8 fix(ci): 很多地方要 zircon
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-08-16 14:46:00 +08:00
YdrMaster 6598412820 feat: remove prebuilt
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-08-16 14:33:33 +08:00
YdrMaster e472f5867e
Merge pull request #364 from shzhxh/master-szx
uninstall git-lfs
2022-08-16 14:04:45 +08:00
shzhxh 4c43a88033 fs::create_dir_all instead of fs::create_dir in xtask 2022-08-16 10:49:29 +08:00
shzhxh bf6a7b9efb uninstall git-lfs 2022-08-15 16:59:17 +08:00
Luoyuan Xiao 9b52c8230f
Merge pull request #363 from YdrMaster/main
build: update toolchain to 2022-08-05
2022-08-12 13:08:53 +08:00
YdrMaster 22710ee86f build: update toolchain to 2022-08-05
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-08-12 12:15:29 +08:00
Zhenxing dea9b80a2f
Merge pull request #362 from YdrMaster/main
fix(kernel-hal): vdso version string 可能超过 64 字节
2022-08-04 21:15:15 +08:00
YdrMaster 18c883e437 fix(kernel-hal): vdso version string 可能超过 64 字节
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-08-04 11:56:43 +08:00
YdrMaster df265eecf9 Revert "Disable dtb version check to be compatible with more Qemu version"
This reverts commit a60a2801ca.

Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-08-04 11:56:43 +08:00
Zhenxing ba54f4508f
Merge pull request #361 from elliott10/master
Refactor of the socket framework and fix the issue of UDP RTSP packet receiving
2022-08-04 10:50:53 +08:00
Luoyuan Xiao 5f79f5a491 Merge branch 'xly/socket' into main 2022-08-04 09:23:25 +08:00
Luoyuan Xiao 9660bb4107 update socket testcases 2022-08-04 09:21:24 +08:00
YdrMaster 185fc38eb0
Merge pull request #360 from whfuyn/fix-linux-libos-run
fix(xtask): libos模式运行需指定zcore的libos feature
2022-08-03 15:29:07 +08:00
Zhishi ff1b8736f1
fix(xtask): libos模式运行需指定zcore的libos feature 2022-08-03 11:57:56 +08:00
YdrMaster 86b42af106
Merge pull request #359 from YdrMaster/main
更新文档,介绍 zCore 硬件支持情况
2022-08-03 06:33:16 +08:00
YdrMaster b5697cd78d fix: 解决下载不到工具链的问题
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-08-02 13:37:32 +08:00
YdrMaster 5d948f1436 docs: 更新文档,介绍 zCore 硬件支持情况
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-08-02 10:12:43 +08:00
Luoyuan Xiao 4e2eee250c fix when run socket testcases 2022-08-01 20:58:27 +08:00
Luoyuan Xiao 8e40a258a2 cargo fmt&clippy code style 2022-08-01 18:10:15 +08:00
Luoyuan Xiao 796f834167 Add poll() parameter
Test camera module with UDP rtsp
2022-08-01 18:01:55 +08:00
Luoyuan Xiao c6eb067cf0 fix syscall poll 2022-07-29 13:07:04 +08:00
Luoyuan Xiao 0183747570 fix getsocket syscall, and add get_buffer_capacity interface
fix socket deadlock problem in tcp/udp
modified tcp/udp read write functions
2022-07-28 23:45:36 +08:00
Luoyuan Xiao 3464219f9c Binding FileLike trait to Socket trait;
Modified the mut lock of Socket object;
Clean up the socket code in linux process file;
2022-07-28 11:43:36 +08:00
YdrMaster f9959b433d build: update deps
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-27 16:09:57 +08:00
Luoyuan Xiao 3fbbfcea8a implemented FileLike for TCP and UDP 2022-07-26 22:40:04 +08:00
Luoyuan Xiao a60a2801ca Disable dtb version check to be compatible with more Qemu version 2022-07-25 19:01:22 +08:00
Luoyuan Xiao 4b78d0548b Adjust tcp/udp buffer;
Disable CRC check and keep FCS in rtl net driver;
2022-07-25 18:49:10 +08:00
Luoyuan Xiao 7ae38f02a6
Merge pull request #355 from YdrMaster/main
fix: update rboot, lock toolchain at 2022-07-20
2022-07-24 22:57:48 +08:00
YdrMaster 419871ee6f docs: typo
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-24 12:52:23 +08:00
YdrMaster 334ec18fa4 docs: 完成开发者注意事项草案
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-23 19:27:07 +08:00
YdrMaster 79830533e8 fix: 用指针绕过互持弱引用对象的构造问题
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-23 18:44:33 +08:00
YdrMaster 877112308a fix: 整理 deny warnings,更新文档
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-23 18:13:24 +08:00
YdrMaster 09a7e89eab refactor: 移除不稳定特性 drain_filter
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-23 15:44:07 +08:00
YdrMaster fe04d2d8ed refactor: 移除不稳定特性 get_mut_unchecked
docs: 撰写开发者注意事项(草案)
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-23 15:41:36 +08:00
YdrMaster da653a63c7 fix & cleanup & todo:
remove unnecessary unstable features and global allowings

Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-23 10:24:18 +08:00
YdrMaster 522032eef5 fix & cleanup & todo:
remove unnecessary unstable features and global allowings

Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-23 10:13:36 +08:00
YdrMaster 44cbbbe72e fix & cleanup & todo:
remove unnecessary unstable features and global allowings

Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-23 10:00:17 +08:00
YdrMaster 00b07def45 fix & cleanup & todo:
remove unnecessary unstable features and global allowings

Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-23 09:47:16 +08:00
YdrMaster 65aa04464b fix & cleanup & todo:
remove unnecessary unstable features and global allowings

Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-23 08:00:05 +08:00
YdrMaster 289c4ed0b9 build: reset rboot to rcore-os
fix: update sbi-rt
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-22 17:41:42 +08:00
YdrMaster cba5f1d46c fix: update rboot, lock toolchain at 2022-07-20
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-22 17:28:13 +08:00
YdrMaster 35969e2d64 fix(d1): 在老式串口助手上换行
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-21 16:39:13 +08:00
Zhenxing 757c63d96d
Merge pull request #353 from YdrMaster/main
feat(xtask): 提供方便的命令生成系统镜像
2022-07-21 10:00:42 +08:00
YdrMaster ed58938a48 refactor(xtask): 合并需要指定输出位置的两个命令参数
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-20 19:06:28 +08:00
YdrMaster c993079425 feat(xtask): 编译类命令增加一个参数,支持选择 features
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-20 17:41:58 +08:00
YdrMaster 9230966bfc feat(zcore): 删除 board-qemu feature
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-20 17:24:06 +08:00
YdrMaster 046743e1c3 feat(xtask): 增加 bin 命令
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-20 17:09:11 +08:00
YdrMaster e7b16842bf feat: 不再需要为 d1 准备一个不同的地址
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-20 15:34:08 +08:00
YdrMaster 86e65a12de build: update to dtb-walker.alpha.3
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-20 07:10:02 +08:00
YdrMaster c292db9b8c
Merge pull request #352 from YdrMaster/main
fix(github action): 生成整个工作空间的文档
2022-07-19 13:24:30 +08:00
YdrMaster d10c4cbc35 fix(github action): 生成整个工作空间的文档
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-19 12:33:26 +08:00
YdrMaster 8eeb2efeb7
Merge pull request #350 from shzhxh/master
[fix bug] Solve the problem that socket.exe testcase fails on D1 platform.
2022-07-18 15:14:19 +08:00
szx 386770f69a Fix compile failure 2022-07-18 14:25:36 +08:00
Zhenxing acef3f902a
Merge branch 'master' into master 2022-07-18 13:31:50 +08:00
YdrMaster aeee46d620 build: update to latest toolchain
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-18 13:29:55 +08:00
YdrMaster d39388e5d0 feat(drivers): 为 d1 的串口提供专用驱动
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-18 13:29:55 +08:00
YdrMaster c3131990b1 build: update dtb-walker to 0.2.0-alpha.1
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-18 13:29:55 +08:00
YdrMaster 6678774766 buid: deps upgrade & 使用发布版本页表库
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-18 13:29:55 +08:00
szx 0de805102a [fix bug] Solve the problem that socket.exe testcase fails on D1 platform."
[update testcases] update testcases of aarch64_bare and riscv64_d1
2022-07-18 13:18:52 +08:00
Luoyuan Xiao bba3a00310
Merge pull request #348 from shzhxh/master
update tests, add seiral port test
2022-07-14 16:28:26 +08:00
shzhxh 3e45f77805 update tests, add seiral port test 2022-07-13 14:12:44 +08:00
Luoyuan Xiao b0f170e7ee
Merge pull request #347 from shzhxh/master
udpate testcases for aarch64
2022-07-11 19:15:47 +08:00
shzhxh 51d424219c udpate testcases for aarch64 2022-07-11 14:19:57 +08:00
Luoyuan Xiao 0981460d2b
Merge pull request #346 from shzhxh/master
update tests
2022-07-07 16:57:28 +08:00
Luoyuan Xiao 18a9d6b068
Merge pull request #345 from YdrMaster/main
将 RISC-V 上内核虚实地址的对齐要求降低到 2 MiB
2022-07-07 16:56:53 +08:00
shzhxh 6a73c86a10 update tests 2022-07-07 12:51:40 +08:00
shzhxh 4ca2261f7b update tests 2022-07-07 11:21:43 +08:00
shzhxh a25f4d79f9 update tests 2022-07-06 22:16:29 +08:00
shzhxh 9fc2f90f62 update tests 2022-07-06 20:34:27 +08:00
YdrMaster 2020f6d193 fix: 正确处理小于 2 MiB 的偏移对齐
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-06 16:03:00 +08:00
YdrMaster d3af8e50e9 feat: 内核虚拟地址和物理地址的对齐要求降低到 2 MiB
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-06 15:28:47 +08:00
YdrMaster 49545fb4e8 refactor(zCore): 在启动阶段使用二级页表
进一步的调整将产生对不同 bootloader 的兼容性

Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-06 13:45:11 +08:00
YdrMaster fa9cae9c28 refactor(zCore): 扩充页表库,简化页表构建过程
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-06 08:26:08 +08:00
YdrMaster 21682a9b6c cleanup
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-05 20:29:18 +08:00
YdrMaster 99f24bf96b refactor(zCore): 封装页表定义
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-05 19:37:23 +08:00
Luoyuan Xiao 5bacf8d7d2
Merge pull request #344 from YdrMaster/main
fix(zCore): riscv 上内核统一映射到虚存最后一页
2022-07-05 15:15:45 +08:00
YdrMaster db1ebfce85 fix(zCore): riscv 上内核统一映射到虚存最后一页
部分解决内核虚地址在不同硬件需要映射到不同位置的问题,并且看到了完整支持内核重定位的可能性。

现在内核会在启动时定位自己在物理内存上的位置,而在虚存上的位置是一个硬件无关的常量。

Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-05 12:28:37 +08:00
Zhenxing 813002d1f6
Merge pull request #341 from YdrMaster/main
update toolchain to latest nightly, and update the README file
2022-07-04 14:09:19 +08:00
YdrMaster a3c65c2f0d docs: 替换 README
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-04 13:06:40 +08:00
YdrMaster 3f1d3bfd5c refactor(xtask): update command-ext for qemu
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-04 13:06:40 +08:00
YdrMaster 299df6af99 fix: update to latest nightly
build: update rboot submodule
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-04 13:06:40 +08:00
YdrMaster 4004f6c888 build: update
- 工具链升级到 latest nightly
- command-ext 升级到新版
- 同步 Cargo.lock

Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-04 13:06:40 +08:00
YdrMaster f3a38fc51c
Merge pull request #343 from workerwork/syscall-socket
feat(socket): add raw socket
2022-07-04 13:04:58 +08:00
workerwork b9dba0d3c9 feat(socket): add raw socket 2022-07-04 10:41:19 +08:00
YdrMaster a069efe05b
Merge pull request #340 from workerwork/syscall-socket
refactor(net): 修正socket trait实现
2022-07-01 13:40:43 +08:00
YdrMaster e9df84e768 refactor(zCore): update dtb-walker to 0.1.3
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-07-01 12:07:23 +08:00
workerwork 301a00bedd refactor(net): 修正socket trait实现 2022-07-01 11:19:56 +08:00
DeathWish5 f36e83c7bb Merge branch 'master' of github.com:rcore-os/zCore 2022-06-30 16:38:18 +08:00
Luoyuan Xiao 04156053c7
Merge pull request #338 from YdrMaster/main
fix: format
2022-06-29 19:05:39 +08:00
YdrMaster ee471b9102 fix: format
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-06-29 18:21:19 +08:00
Luoyuan Xiao 94f550f1ab
Merge pull request #335 from DeathWish5/master
Some updates: fix dead lock, fix signal handle alignment issus, remove redundant memory copy.
2022-06-29 18:13:27 +08:00
YdrMaster 4e293968a9
Merge pull request #337 from sunshine-lcc/master
solve shell running problem
2022-06-29 18:07:40 +08:00
luchangcheng2333 2ce9e13788 fix clippy 2022-06-29 17:14:12 +08:00
luchangcheng2333 4aac371cb5 cargo fmt 2022-06-29 17:01:23 +08:00
sunshine 07b6be8aaa
Merge branch 'rcore-os:master' into master 2022-06-29 17:00:07 +08:00
luchangcheng2333 9e118abffe solve the shell running problem
solve the shell running problem, now it can run shell and libc-test normally
2022-06-29 16:58:29 +08:00
Yiren Zhang 3f9616aedc
Merge branch 'master' into master 2022-06-29 16:54:49 +08:00
YdrMaster 4f2bb3fb08
Merge pull request #336 from workerwork/syscall-socket
feat(syscall): add getsockopt
2022-06-29 16:37:39 +08:00
DeathWish5 73ef70040b Merge branch 'master' of github.com:rcore-os/zCore 2022-06-29 15:07:31 +08:00
DeathWish5 0175bb7f68 bug fix: pin_count error 2022-06-29 15:06:54 +08:00
workerwork 18224e7e1e add getsockopt syscall 2022-06-29 13:52:26 +08:00
Luoyuan Xiao c275b2ac34
Merge pull request #334 from YdrMaster/main
xtask 文档 & kernel-hal smp
2022-06-29 00:19:20 +08:00
DeathWish5 38b8457998 remove memory copy in load elf image 2022-06-28 21:41:46 +08:00
DeathWish5 da98d9075b minor update 2022-06-28 17:16:34 +08:00
DeathWish5 450df55e7b bug fix: error length of Sigset 2022-06-27 23:51:37 +08:00
DeathWish5 51dae46a83 minor update 2022-06-27 18:09:33 +08:00
DeathWish5 bf7e66ffcc bug fix: x86_64 align error 2022-06-27 17:03:44 +08:00
DeathWish5 1b12fd12c9 bug fix: multi-threads proc may dead lock. use lock::Mutex replace all spin::Mutex. 2022-06-26 22:07:36 +08:00
YdrMaster 0619c572f0 refactor(kernel-hal): remove smp feature
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-06-25 12:46:56 +08:00
YdrMaster afa9ca5d35 feat: 使用 build-args 整合 clippy 和 build,避免使用 make
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-06-25 12:28:00 +08:00
YdrMaster 66e4a09f54 docs(xtask): 补充全部命令说明
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-06-25 11:38:02 +08:00
YdrMaster 4dd8e551aa style(xtask): 补充文档,调整部分命令
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-06-25 07:26:14 +08:00
YdrMaster c63e1b4b85 feat: 分离 command_ext 给其他项目
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-06-25 06:02:17 +08:00
0400h 90e6f67ef7 Add ubuntu:20.04 docker develop environment support
Signed-off-by: 0400h <git@0400h.cn>
2022-06-24 15:11:06 +08:00
Ydr 0780201b3a
Merge pull request #333 from DeathWish5/master
miner update: add sbss sdata srodata in linker.ld
2022-06-24 09:06:09 +08:00
DeathWish5 ca25593c51 bug fix: add sbss sdata srodata in linker.ld 2022-06-23 17:30:51 +08:00
Ydr 5df4ce775b
Merge pull request #331 from YdrMaster/dev-clean
增加两个命令,以不同级别清理目录
2022-06-22 15:08:36 +08:00
YdrMaster 191f56b0b4 feat(make): 增加两个命令,以不同级别清理目录
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-06-22 12:22:42 +08:00
YdrMaster 41fbdc6418 style(xtask): 整理
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-06-22 12:22:42 +08:00
Luoyuan Xiao 2fc70e5685
Merge pull request #329 from YdrMaster/main
update dtb & sbi
2022-06-22 11:34:42 +08:00
Luoyuan Xiao 106882edec
Merge pull request #324 from DeathWish5/master
executor bug fix: lmbench may cause panic.
2022-06-22 11:34:01 +08:00
YdrMaster 16b001d28a refactor(kernel-hal): 使用 sbi-rt
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-06-20 22:58:24 +08:00
DeathWish5 f8cc81a24e minor udpate: typo fix 2022-06-20 18:37:32 +08:00
DeathWish5 e0a744b8c1 Merge branch 'master' of github.com:rcore-os/zCore 2022-06-20 18:30:04 +08:00
DeathWish5 e42ba4cc36 minor update 2022-06-20 18:24:56 +08:00
YdrMaster 9d44107384 refactor(kernel-hal): use dtb-walker
in primary_init_early

Signed-off-by: YdrMaster <ydrml@hotmail.com>
2022-06-20 10:44:09 +08:00
Ydr 0c37bb3485
Merge pull request #328 from elliott10/master 2022-06-19 10:37:07 +08:00
DeathWish5 1a7dec1667 cargo fmt and clippy 2022-06-17 22:21:26 +08:00
DeathWish5 7f50b1cbb9 feat: add kernel PF support 2022-06-17 21:53:21 +08:00
Luoyuan Xiao b3efb22e4b TCP connection occurred that segment not in receive window, will send challenge ACK
then the connection stuck
The smoltcp ACK timer made the connection stuck in network congestion
After analysis, this problem was caused by clock driver offer
2022-06-17 21:39:52 +08:00
Luoyuan Xiao 56c9926558 To fix nanosleep fault 2022-06-17 20:27:47 +08:00
Luoyuan Xiao 39b3dd1a57
Merge pull request #325 from YdrMaster/main
remove alphine
adjust the structure of download directory
2022-06-17 09:11:23 +08:00
YdrMaster 3ac0f6acdb fix(xtask): opencv 找 ffmpeg 目录错误 2022-06-16 17:52:17 +08:00
YdrMaster aaca104cb4 feat(xtask): 自动安装 binutils 2022-06-16 15:01:56 +08:00
YdrMaster d3c41dd4eb refactor(xtask): 不要使用当前目录的相对路径,以支持在任何位置使用 xtask 2022-06-15 19:09:24 +08:00
DeathWish5 1f8ae39dad Merge branch 'master' of github.com:rcore-os/zCore 2022-06-15 16:37:56 +08:00
DeathWish5 842f12f65b bug fix: cow may fail 2022-06-15 16:37:38 +08:00
YdrMaster d97069f718 cleanup(xtask): 不需要为 libos 修改 x86_64 的 rootfs 2022-06-15 12:58:01 +08:00
YdrMaster aed06c039f feat(libos): 下载 libos 的 rootfs 2022-06-15 12:52:01 +08:00
YdrMaster f7c20c335d feat(libos): 为 ci 提供一个专用的命令,添加 libc-test 2022-06-15 12:07:46 +08:00
YdrMaster c2a2691284 feat(libos): libos 使用专用的 rootfs 目录 2022-06-15 11:48:52 +08:00
YdrMaster 2388ae6319 temp
libos 使用专用的 rootfs 目录
2022-06-15 11:47:09 +08:00
YdrMaster e3ded55049 temp
已实现编译 busybox,但 libos 只能使用专门的 busybox 和 ld-musl-x86_64.so.1
2022-06-15 11:47:09 +08:00
Luoyuan Xiao 0b2ac1ef28
Merge pull request #322 from YdrMaster/main
refactor(xtask): 统一各种架构编译测例的过程
2022-06-14 18:26:40 +08:00
YdrMaster 904644e61e fix(xtask): ld-musl-{arch}.so.1 不能用符号链接 2022-06-14 16:32:50 +08:00
YdrMaster cfbc8d2fe6 fix(xtask): clap 版本限制在 3.1 2022-06-14 14:44:17 +08:00
YdrMaster ff3eff6f75 feat(xtask): 拷贝库先 strip 2022-06-14 12:48:36 +08:00
YdrMaster 85c89d883a feat(xtask): `cargo musl-libs --args <args>`
拷贝实际编译使用的 musl 工具链提供的动态库到 rootfs
2022-06-14 12:17:42 +08:00
YdrMaster aece9fe392 fix(ci): 补充 zircon-core-test-libos 2022-06-14 08:39:03 +08:00
DeathWish5 bd392b2d0c Merge branch 'master' of github.com:rcore-os/zCore 2022-06-13 17:54:09 +08:00
YdrMaster 69baa92da0 fix(xtask): 符号链接不能用 fs::copy 拷贝 2022-06-13 17:15:47 +08:00
DeathWish5 c4160883fe cargo fmt and clippy 2022-06-13 15:59:43 +08:00
YdrMaster 3049bc4d9f feat(xtask): 支持 linux libos 模式启动 2022-06-13 09:41:44 +08:00
YdrMaster 0290a9fc49 refactor(ci): 恢复全部测试 2022-06-12 12:40:21 +08:00
YdrMaster 3156ab4b7f temp(ci): 暂时去掉不关心的测试 2022-06-12 12:27:29 +08:00
YdrMaster 974dde8005 refactor(xtask): 统一各种架构编译测例的过程
refactor(ci): 缓存 musl toolchain
2022-06-12 11:39:52 +08:00
YdrMaster dceaac60c0 style(xtask) 2022-06-12 09:57:22 +08:00
Ydr fd67f173df
Merge pull request #320 from Luchangcheng2333/master
fix input problem in aarch64
2022-06-12 09:35:26 +08:00
liusm18 b6e28c5d3b Fix some bugs 2022-06-11 11:43:28 +08:00
Luchangcheng2333 8073606805
fix format error 2022-06-11 11:22:11 +08:00
luchangcheng2333 d4b32809aa fix copy error 2022-06-11 11:13:33 +08:00
Luchangcheng2333 5cb95b0276
Update mod.rs 2022-06-11 10:34:44 +08:00
luchangcheng2333 42fef4f333 Merge remote-tracking branch 'origin/master' 2022-06-11 10:28:31 +08:00
luchangcheng2333 32ab5b677d merge upstream 2022-06-11 10:26:03 +08:00
luchangcheng2333 1f28f410f9 fix aarch64 CI problem 2022-06-11 10:22:31 +08:00
Luoyuan Xiao 5045b0e1ed
Merge pull request #319 from YdrMaster/main
fix(xtask): 编译支持 ffmpeg 的 opencv
2022-06-11 10:07:32 +08:00
Luchangcheng2333 da11619efa
Delete prebuilt/linux directory 2022-06-11 10:03:18 +08:00
luchangcheng2333 2c8f615dfc download aarch64 firmware instead of prestore 2022-06-11 10:00:12 +08:00
luchangcheng2333 ea88973b3f Add rayboot to target_arch aarch64 in toml, ignore some files 2022-06-11 08:53:27 +08:00
luchangcheng2333 0878e44f7d solve input problem in aarch64 2022-06-10 23:16:33 +08:00
YdrMaster ec6698653e feat(xtask): git clone 增加 `--depth=x` 选项以减少流量需求 2022-06-10 19:26:34 +08:00
YdrMaster c178193d0a fix(xtask): opencv 自动关联 ffmpeg 2022-06-10 19:15:52 +08:00
YdrMaster 4e2d15e094 build(zCore): 为 riscv64 生成链接文件 2022-06-10 16:37:35 +08:00
YdrMaster 8255af3e71 build: 清理 Cargo.toml 2022-06-10 15:49:11 +08:00
Ydr 3a246a88d0
Merge pull request #316 from elliott10/master
Disable D1 PCI Scan
2022-06-10 15:28:32 +08:00
Luoyuan Xiao 6415b5eec4
Merge pull request #314 from YdrMaster/main
支持放置第三方库到 rootfs/riscv64
2022-06-10 11:14:51 +08:00
YdrMaster c2210f4346 refactor(xtask): 支持自动放置 ffmpeg 库文件 2022-06-10 08:49:30 +08:00
YdrMaster a35032b540 refactor(xtask): 支持自动放置 opencv 库文件 2022-06-09 23:13:39 +08:00
liusm18 b6988ffd9b Fix a bug in plic (U740) 2022-06-09 22:13:06 +08:00
liusm18 b16b49bf43 Fix a small bug 2022-06-09 21:59:54 +08:00
liusm18 494eb6249a Driver for Uart in U740 2022-06-09 21:59:20 +08:00
Luoyuan Xiao c9aa18d655 Disable D1 PCI Scan 2022-06-09 20:02:06 +08:00
YdrMaster 19e465f23e refactor(ci): remove macos from build ci 2022-06-09 18:28:12 +08:00
YdrMaster 6823456c9f refactor(xtask):linux rootfs 添加测试集、构造镜像操作分离到独立的文件 2022-06-09 18:08:39 +08:00
YdrMaster 3987a25b3f refactor(xtask): 重构架构相关操作
将操作架构相关的 linux rootfs 的操作与架构定义分离,放到独立的模块中
2022-06-09 17:18:08 +08:00
DeathWish5 b0e14fffa8 merge master 2022-06-08 17:53:43 +08:00
Luoyuan Xiao a853beb1b6
Merge pull request #312 from YdrMaster/main
feat(zCore): 使用更轻量的设备树解析
2022-06-07 22:36:21 +08:00
YdrMaster 0c76f177dd style 2022-06-07 09:35:37 +08:00
YdrMaster 105b9b45a5 feat(zCore): 跳过状态不是 "okay" 的核 2022-06-06 20:53:44 +08:00
YdrMaster e1ada366b1 feat(zCore): 支持不连续的 cpu 序号 2022-06-06 20:07:29 +08:00
YdrMaster dc979de656 feat(zCore): 使用更轻量的设备树解析 2022-06-06 19:44:49 +08:00
Luoyuan Xiao 38bb64ee36
Merge pull request #311 from YdrMaster/main
小修小补
2022-06-05 12:31:39 +08:00
Luoyuan Xiao 70aa0d9684
Merge pull request #310 from shzhxh/master-merge
add test to aarch64 platform
2022-06-05 12:30:49 +08:00
YdrMaster d8732725f2 fix(linux-syscall): deny warnings
fix(xtask): 将环境变量永远限制在最小的子进程上

fix: new gitignore
2022-06-04 11:22:54 +08:00
Zichun Yu fe961844c1 Add support for libctest 2022-06-03 22:18:51 +08:00
liusm18 8984842ea6 Fix two bugs after merging 2022-06-03 20:47:39 +08:00
liusm18 2bb3ede698 Merge branch 'rcore-os-master' into u740 2022-06-03 20:16:52 +08:00
liusm18 887821954b Merge branch 'master' of rcore-os/zCore into rcore-os-master 2022-06-03 20:13:28 +08:00
liusm18 9edd6b6c01 Revert the two dependencies 2022-06-03 19:40:29 +08:00
liusm18 af152b62f7 Fix a bug in timer 2022-06-03 16:59:49 +08:00
liusm18 6b1d0d4624 Configure cpu index for u740 2022-06-03 16:59:39 +08:00
liusm18 4930d740e0 Patch two denpendencies 2022-06-03 16:59:18 +08:00
shzhxh 8df01a9eb5 add test to aarch64 platform 2022-06-02 20:43:16 +08:00
Luoyuan Xiao c7e10d3e17
Merge pull request #306 from Luchangcheng2333/master
Add aarch64 support
2022-06-02 19:19:22 +08:00
Luoyuan Xiao 909f382deb
Merge pull request #309 from CL-a11y/netlink
add NetLink socket, support ip addr command.
2022-06-02 19:18:45 +08:00
yuoo655 85caf74ce9 fix bug in get socket endpoint 2022-06-01 16:40:47 +08:00
luchangcheng2333 6a915ca176 解决other-test的问题 2022-06-01 16:18:44 +08:00
luchangcheng2333 db73afb60e 解决other-test的问题 2022-06-01 15:40:37 +08:00
yuoo655 3b466f83ac fmt 2022-06-01 15:05:30 +08:00
yuoo655 640b28e11c add netlink socket support ip addr command 2022-06-01 14:59:30 +08:00
luchangcheng2333 da881c4fac 支持在树莓派4b上启动 2022-06-01 09:23:20 +08:00
luchangcheng2333 c70912e7f2 修复xtask构建的问题 2022-05-31 11:13:18 +08:00
luchangcheng2333 aec55d2656 更新tests 2022-05-31 11:00:24 +08:00
luchangcheng2333 d0dcc65019 调整存在的格式问题 2022-05-31 10:43:12 +08:00
luchangcheng2333 aaf369efe8 merge upstream 2022-05-31 10:33:05 +08:00
luchangcheng2333 78d5ef94ca 去掉ATF,实现构建test镜像 2022-05-31 10:24:29 +08:00
Zhenxing fc8a32542a
add CI test of build for aarch64 (#11) 2022-05-31 01:15:04 +00:00
liusm18 25b73d7340 Fix a bug of time int handler 2022-05-30 21:17:35 +08:00
luchangcheng2333 98f8c7b4ef 实现了获取cmdline功能,修复关机问题 2022-05-30 12:24:43 +08:00
luchangcheng2333 f98da37ed9 实现了使用xtask启动zCore aarch64 2022-05-28 22:25:42 +08:00
liusm18 aad8232674 Map the memory of dtb 2022-05-28 10:27:13 +08:00
liusm18 da08dd6908 Remove useless consts 2022-05-28 00:42:16 +08:00
liusm18 e83600f39b Support plic of dtb in U740 2022-05-28 00:28:54 +08:00
DeathWish5 48c36173f1 update tests 2022-05-27 20:17:39 +08:00
DeathWish5 0043e00b9f delete unused code 2022-05-27 17:42:41 +08:00
DeathWish5 d3df748ade bug fix: exit_linux may cause kernel pagefault 2022-05-27 16:20:14 +08:00
luchangcheng2333 af48cce1f1 解决一个merge错误 2022-05-21 21:48:20 +08:00
luchangcheng2333 d53432fab7 merge from upstream 2022-05-21 21:46:10 +08:00
luchangcheng2333 eddc5fbc0d 调整格式 2022-05-21 21:37:16 +08:00
liusm18 2e01318c30 Update u740 makefile 2022-05-13 20:31:23 +08:00
luchangcheng2333 d2acb4386e merge upstream 2022-05-10 21:14:52 +08:00
luchangcheng2333 a90b5dadc5 暂时使用自己修改的lock 2022-05-10 21:13:35 +08:00
111 aacf26c831 merge from upstream 2022-05-09 19:16:38 +08:00
liusm18 87f66d8035 Adapt u740 support to current version 2022-04-29 20:15:53 +08:00
liusm18 51a3641768 Remove abundant downloads 2022-04-29 18:18:25 +08:00
liusm18 1f19abd1ac Add u740 supports 2022-04-29 18:17:48 +08:00
Zichun Yu b8396a878b
Merge pull request #2 from DeathWish5/add-linux-user
feat: add rcore-user as linux-user
2022-04-29 17:38:55 +08:00
DeathWish5 b15c313075 feat: add rcore-user as linux-user 2022-04-29 17:27:58 +08:00
luchangcheng2333 eea3209fc0 Merge remote-tracking branch 'origin/master' 2022-04-25 21:12:31 +08:00
luchangcheng2333 92aece0aee 待查使用shell运行程序出现不能解决的pagefault的问题 2022-04-25 21:12:21 +08:00
Luchangcheng2333 dd06615d42
Merge branch 'rcore-os:master' into master 2022-04-25 19:48:28 +08:00
luchangcheng2333 23c33e6fbf 解决设备内存标志没设的问题 2022-04-24 11:39:58 +08:00
luchangcheng2333 1c8be756c4 更新可在树莓派4b及qemu通用的UEFI固件 2022-04-24 11:07:59 +08:00
luchangcheng2333 9ba285d00a merge from rcore-os 2022-04-22 17:34:55 +08:00
luchangcheng2333 f89487d3b0 调整代码格式,以通过检查 2022-04-22 17:30:35 +08:00
luchangcheng2333 e86a3a8ac9 调整GIC驱动,后续可适应更多设备 2022-04-22 17:26:51 +08:00
luchangcheng2333 ec3dbb84f5 解决了不能输入的问题,实现了中断开关 2022-04-22 11:08:00 +08:00
luchangcheng2333 158d366478 调整构建根文件系统镜像中的一些不合适的地方 2022-04-21 19:57:48 +08:00
luchangcheng2333 bbaa25072c Merge branch 'master' of https://github.com/Luchangcheng2333/zCore 2022-04-21 19:37:38 +08:00
Wynn 39f312fb18
在Makefile中添加了aarch64 rootfs (#4)
Signed-off-by: Wynn <1052209675@qq.com>
2022-04-21 11:37:25 +00:00
luchangcheng2333 78d7e6dac2 Merge branch 'master' of https://github.com/Luchangcheng2333/zCore 2022-04-21 19:28:10 +08:00
luchangcheng2333 b941c1c557 to merge from upstream 2022-04-21 19:28:06 +08:00
Luchangcheng2333 6672dbc197
Merge branch 'rcore-os:master' into master 2022-04-21 18:02:16 +08:00
luchangcheng2333 93cea0ddce 实现了运行shell,但不能正常输入 2022-04-21 09:51:22 +08:00
luchangcheng2333 66c868ba32 规范aarch64异常类型的定义 2022-04-20 15:58:33 +08:00
luchangcheng2333 c32b06b53c 解决合并上游更新导致的在aarch64架构下编译不通过问题 2022-04-20 08:27:35 +08:00
luchangcheng2333 fe0e5346dc merge from rcore-os/zcore 2022-04-19 20:46:10 +08:00
luchangcheng2333 6be3091d83 更新tests 2022-04-19 20:06:55 +08:00
luchangcheng2333 620280ad45 更新test子模块到最新版本 2022-04-19 19:35:14 +08:00
luchangcheng2333 eaccc38ba6 按照GitHub工作流要求规范格式,添加aarch64系统调用定义 2022-04-19 15:54:53 +08:00
luchangcheng2333 ad3f546c50 实现了切换到用户态的功能,用户态程序访存异常待查 2022-04-19 08:47:33 +08:00
luchangcheng2333 a1ae6c51aa 实现调用了virtio磁盘驱动,修复一个可能导致panic对的内存分配问题 2022-04-18 14:55:05 +08:00
12212 dba47cee81 统一常量的放置位置 2022-04-17 16:50:02 +08:00
12212 f0d66578c7 修补之前commit带来的问题 2022-04-17 16:29:22 +08:00
12212 b7ffaa0f8e Merge remote-tracking branch 'origin/master' 2022-04-17 16:28:10 +08:00
12212 58dafb925a 把UEFI移到prebuilt目录;调整适应串口驱动 2022-04-17 16:25:49 +08:00
Wynn 0613277267
Merge branch 'master' into master 2022-04-17 12:53:01 +08:00
12212 9e10b80df9 修复了一个可能导致崩溃的内存大小设置问题 2022-04-17 12:14:38 +08:00
12212 0992f71137 实现异常处理,GIC中断控制器时钟 2022-04-17 10:25:46 +08:00
12212 6ab09a1f6e 修复了虚存管理中存在的问题,实现了部分异常处理的功能 2022-04-17 09:10:53 +08:00
luchangcheng2333 6d2dd8787d 待解决开启虚拟内存的问题 2022-04-16 09:47:18 +08:00
12212 ce8270f170 Merge branch 'master' of https://github.com/Luchangcheng2333/zCore.git; branch 'master' of https://github.com/Luchangcheng2333/zCore 2022-04-14 22:29:26 +08:00
12212 44c5f4d0aa 添加部分内存重映射相关代码 2022-04-14 22:28:55 +08:00
Wynn 2ad3ca5a0b
调整了目录结构,将树莓派的串口驱动放在了drivers crate下面 (#2)
Signed-off-by: Wynn <1052209675@qq.com>
2022-04-14 22:21:20 +08:00
Wynn 5e49df946e 调整了目录结构,将树莓派的串口驱动放在了drivers crate下面
Signed-off-by: Wynn <1052209675@qq.com>
2022-04-14 21:00:01 +08:00
12212 dfca35c854 适配了zcore驱动标准到uart驱动上 2022-04-14 08:48:36 +08:00
12212 9453f269d4 实现了串口输出 2022-04-13 19:47:41 +08:00
12212 671337d26c achieve aarch64 vm controller, add controler for aarch64 syscall 2022-04-13 15:53:21 +08:00
Luchangcheng2333 c2c9eb7d2e
Merge pull request #1 from rcore-os/master
merge upstream to me
2022-04-13 10:56:11 +08:00
12212 a34f520842 加入aarch64需要实现的框架,使得kernel-hal成功编译 2022-04-13 10:54:17 +08:00
293 changed files with 13547 additions and 4138 deletions

View File

@ -1,16 +1,22 @@
[alias]
xtask = "run --package xtask --release --"
git-proxy = "xtask git-proxy"
setup = "xtask setup"
zircon-init = "xtask zircon-init"
update-all = "xtask update-all"
check-style = "xtask check-style"
rootfs = "xtask rootfs"
musl-libs = "xtask musl-libs"
opencv = "xtask opencv"
ffmpeg = "xtask ffmpeg"
libc-test = "xtask libc-test"
other-test = "xtask other-test"
image = "xtask image"
linux-libos = "xtask linux-libos"
asm = "xtask asm"
bin = "xtask bin"
qemu = "xtask qemu"
gdb = "xtask gdb"

1
.gitattributes vendored
View File

@ -1 +0,0 @@
prebuilt/**/* filter=lfs diff=lfs merge=lfs -text

View File

@ -1,5 +0,0 @@
#!/usr/bin/env bash
sudo apt-get update
sudo apt-get install -y $@
pip3 install -r tests/requirements.txt

View File

@ -3,5 +3,5 @@
wget https://download.qemu.org/qemu-$1.tar.xz
tar -xJf qemu-$1.tar.xz
cd qemu-$1
./configure --target-list=x86_64-softmmu,riscv64-softmmu
make -j$nproc > /dev/null 2>&1
./configure --target-list=x86_64-softmmu,riscv64-softmmu,aarch64-softmmu
make -j > /dev/null 2>&1

View File

@ -7,11 +7,11 @@ on:
- cron: '0 22 * * *' # every day at 22:00 UTC
env:
rust_toolchain: nightly-2022-01-20
rust_toolchain: nightly-2022-08-05
jobs:
workspace:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
@ -40,54 +40,23 @@ jobs:
command: clippy
args: --all-features
- name: Pull prebuilt images
if: github.event_name == 'schedule'
run: make zircon-init
- name: Build docs
if: github.event_name == 'schedule'
uses: actions-rs/cargo@v1
with:
command: doc
args: --all-features --no-deps
build-aarch64:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ env.rust_toolchain }}
override: true
target: aarch64-unknown-linux-gnu
- uses: actions-rs/cargo@v1
with:
command: build
use-cross: true
args: --target aarch64-unknown-linux-gnu --workspace --exclude linux-syscall --exclude zcore-loader --exclude zcore
build-user:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Pull prebuilt images
run: git lfs pull -I prebuilt/zircon/x64/libc.so,prebuilt/zircon/x64/libfdio.so,prebuilt/zircon/x64/libunwind.so,prebuilt/zircon/x64/libzircon.so,prebuilt/zircon/x64/Scrt1.o
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ env.rust_toolchain }}
target: x86_64-fuchsia
- name: Build Zircon user programs
run: cd zircon-user && make build MODE=release
args: --no-deps --all-features --workspace
test-libos:
runs-on: ${{ matrix.os }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
mode: [linux, zircon]
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@v3
@ -97,6 +66,10 @@ jobs:
toolchain: ${{ env.rust_toolchain }}
components: rust-src, llvm-tools-preview, clippy
- name: Pull prebuilt images
if: matrix.mode == 'zircon'
run: make zircon-init
- name: Build
uses: actions-rs/cargo@v1
with:
@ -110,12 +83,11 @@ jobs:
args: --package zcore --features "${{ matrix.mode }} libos"
test-bare-metal:
runs-on: ${{ matrix.os }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
arch: [x86_64, riscv64]
os: [ubuntu-latest, macos-latest]
arch: [x86_64, riscv64, aarch64]
steps:
- uses: actions/checkout@v3
with:
@ -132,18 +104,44 @@ jobs:
crate: cargo-binutils
version: latest
- name: Install qemu-utils
run: sudo apt update && sudo apt install qemu-utils
- name: Pull prebuilt images
if: matrix.arch == 'x86_64'
run: make zircon-init
- name: Build ${{ matrix.arch }} bare-metal zircon
if: matrix.arch == 'x86_64'
run: cd zCore && make build ARCH=${{ matrix.arch }}
run: cd zCore && make build ARCH=${{ matrix.arch }} ZBI=core-tests
- name: Clippy ${{ matrix.arch }} bare-metal zircon
if: matrix.arch == 'x86_64'
run: cd zCore && make clippy ARCH=${{ matrix.arch }}
run: cd zCore && make clippy ARCH=${{ matrix.arch }} ZBI=core-tests
- name: Build ${{ matrix.arch }} bare-metal linux
if: matrix.arch == 'riscv64'
if: matrix.arch != 'x86_64'
run: cd zCore && make build ARCH=${{ matrix.arch }} LINUX=1
- name: Clippy ${{ matrix.arch }} bare-metal linux
if: matrix.arch == 'riscv64'
run: cd zCore && make clippy ARCH=${{ matrix.arch }} LINUX=1
- name: Xtask Build bare-metal linux
run: cargo bin -m virt-${{ matrix.arch }}
build-user:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install prebuilt images
run: make zircon-init
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly-2022-01-20
target: x86_64-fuchsia
- name: Build Zircon user programs
run: cd zircon-user && make build MODE=release

View File

@ -1,26 +1,29 @@
name: Deploy docs
name: Deploy docs
on:
push:
pull_request:
env:
rust_toolchain: nightly-2022-01-20
rust_toolchain: nightly-2022-08-05
jobs:
doc:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ env.rust_toolchain }}
- name: Pull prebuilt images
run: make zircon-init
- name: Build docs
run: |
cargo doc --no-deps --all-features
cargo doc --no-deps --all-features --workspace
.github/scripts/add-doc-index.sh
- name: Deploy to Github Pages

View File

@ -7,13 +7,13 @@ on:
- cron: '0 22 * * *' # every day at 22:00 UTC
env:
rust_toolchain: nightly-2022-01-20
rust_toolchain: nightly-2022-08-05
qemu_version: 7.0.0
jobs:
unit-test:
name: Unit Test
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
@ -21,7 +21,7 @@ jobs:
with:
profile: minimal
toolchain: ${{ env.rust_toolchain }}
components: rust-src, llvm-tools-preview, rustfmt, clippy
components: rust-src, llvm-tools-preview
- name: Run unit test
uses: actions-rs/cargo@v1
@ -49,26 +49,9 @@ jobs:
# github-token: ${{ secrets.GITHUB_TOKEN }}
# path-to-lcov: ${{ steps.coverage.outputs.report }}
bench-test:
name: Bench Test
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ env.rust_toolchain }}
components: rust-src, llvm-tools-preview, rustfmt, clippy
- name: Run bench test
uses: actions-rs/cargo@v1
with:
command: bench
zircon-core-test-libos:
name: Zircon Core Test Libos
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
@ -78,16 +61,13 @@ jobs:
with:
profile: minimal
toolchain: ${{ env.rust_toolchain }}
components: rust-src, llvm-tools-preview, rustfmt, clippy
components: rust-src, llvm-tools-preview
- name: Pull prebuilt images
run: |
git lfs pull -I prebuilt/zircon/x64/core-tests.zbi
git lfs pull -I prebuilt/zircon/x64/libzircon-libos.so
git lfs pull -I prebuilt/zircon/x64/userboot-libos.so
run: make zircon-init
- name: Install python dependencies
run: .github/scripts/install-deps.sh
run: pip3 install -r tests/requirements.txt
- name: Run fast tests
if: github.event_name != 'schedule'
@ -97,37 +77,9 @@ jobs:
if: github.event_name == 'schedule'
run: cd tests && python3 zircon_core_test.py --libos
linux-libc-test-libos:
name: Linux Libc Test Libos
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
with:
submodules: 'recursive'
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ env.rust_toolchain }}
components: rust-src, llvm-tools-preview, rustfmt, clippy
- name: Install dependencies
run: .github/scripts/install-deps.sh musl-tools musl-dev
- name: Prepare rootfs
run: make libc-test
- name: Run fast tests
if: github.event_name != 'schedule'
run: cd tests && python3 linux_libc_test.py --libos --fast
- name: Run full tests
if: github.event_name == 'schedule'
run: cd tests && python3 linux_libc_test.py --libos
zircon-core-test-baremetal:
zircon-core-test:
name: Zircon Core Test Baremetal
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
@ -137,33 +89,33 @@ jobs:
with:
profile: minimal
toolchain: ${{ env.rust_toolchain }}
components: rust-src, llvm-tools-preview, rustfmt, clippy
components: rust-src, llvm-tools-preview
- name: Pull prebuilt images
run: |
git lfs pull -I prebuilt/zircon/x64/core-tests.zbi
git lfs pull -I prebuilt/zircon/x64/libzircon.so
git lfs pull -I prebuilt/zircon/x64/userboot.so
- name: Install dependencies
run: .github/scripts/install-deps.sh ninja-build
run: make zircon-init
- name: Cache QEMU
id: cache-qemu
uses: actions/cache@v3
with:
path: qemu-${{ env.qemu_version }}
key: qemu-${{ env.qemu_version }}-x86_64-riscv64
key: qemu-${{ env.qemu_version }}
- name: Install ninja-build
run: sudo apt-get update && sudo apt-get install -y ninja-build
- name: Download and Compile QEMU
if: steps.cache-qemu.outputs.cache-hit != 'true'
run: .github/scripts/install-qemu.sh ${{ env.qemu_version }}
run: .github/scripts/make-qemu.sh ${{ env.qemu_version }}
- name: Install QEMU
run: |
cd qemu-${{ env.qemu_version }} && sudo make install
qemu-system-x86_64 --version
- name: Install python dependencies
run: pip3 install -r tests/requirements.txt
- name: Run fast tests
if: github.event_name != 'schedule'
run: cd tests && python3 zircon_core_test.py --fast
@ -172,13 +124,9 @@ jobs:
if: github.event_name == 'schedule'
run: cd tests && python3 zircon_core_test.py
linux-libc-test-baremetal:
name: Linux Libc Test Baremetal
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
arch: [x86_64, riscv64]
linux-libc-test-libos:
name: Linux Libc Test Libos
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
@ -188,27 +136,53 @@ jobs:
with:
profile: minimal
toolchain: ${{ env.rust_toolchain }}
components: rust-src, llvm-tools-preview, rustfmt, clippy
components: rust-src, llvm-tools-preview
- if: matrix.arch == 'riscv64'
uses: actions-rs/install@v0.1
- name: Prepare rootfs
run: cargo xtask libos-libc-test
- name: Install python dependencies
run: pip3 install -r tests/requirements.txt
- name: Run fast tests
if: github.event_name != 'schedule'
run: cd tests && python3 linux_libc_test.py --libos --fast
- name: Run full tests
if: github.event_name == 'schedule'
run: cd tests && python3 linux_libc_test.py --libos
linux-libc-test-baremetal:
name: Linux Libc Test Baremetal
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
arch: [x86_64, riscv64, aarch64]
steps:
- uses: actions/checkout@v3
with:
crate: cargo-binutils
version: latest
submodules: 'recursive'
- name: Install dependencies
run: .github/scripts/install-deps.sh musl-tools musl-dev ninja-build
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ env.rust_toolchain }}
components: rust-src, llvm-tools-preview
- name: Cache QEMU
id: cache-qemu
uses: actions/cache@v3
with:
path: qemu-${{ env.qemu_version }}
key: qemu-${{ env.qemu_version }}-x86_64-riscv64
key: qemu-${{ env.qemu_version }}
- name: Install ninja-build
run: sudo apt-get update && sudo apt-get install -y ninja-build
- name: Download and Compile QEMU
if: steps.cache-qemu.outputs.cache-hit != 'true'
run: .github/scripts/install-qemu.sh ${{ env.qemu_version }}
run: .github/scripts/make-qemu.sh ${{ env.qemu_version }}
- name: Install QEMU
run: |
@ -216,7 +190,16 @@ jobs:
qemu-system-${{ matrix.arch }} --version
- name: Prepare rootfs
run: make libc-test ARCH=${{ matrix.arch }} && make image ARCH=${{ matrix.arch }}
run: cargo libc-test --arch ${{ matrix.arch }} && cargo image --arch ${{ matrix.arch }}
- if: matrix.arch == 'riscv64'
uses: actions-rs/install@v0.1
with:
crate: cargo-binutils
version: latest
- name: Install python dependencies
run: pip3 install -r tests/requirements.txt
- name: Run fast tests
if: github.event_name != 'schedule'
@ -228,11 +211,11 @@ jobs:
linux-other-test-baremetal:
name: Linux Other Test Baremetal
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
arch: [x86_64, riscv64]
arch: [x86_64, riscv64, aarch64]
steps:
- uses: actions/checkout@v3
with:
@ -242,27 +225,21 @@ jobs:
with:
profile: minimal
toolchain: ${{ env.rust_toolchain }}
components: rust-src, llvm-tools-preview, rustfmt, clippy
- if: matrix.arch == 'riscv64'
uses: actions-rs/install@v0.1
with:
crate: cargo-binutils
version: latest
- name: Install dependencies
run: .github/scripts/install-deps.sh musl-tools musl-dev ninja-build
components: rust-src, llvm-tools-preview
- name: Cache QEMU
id: cache-qemu
uses: actions/cache@v3
with:
path: qemu-${{ env.qemu_version }}
key: qemu-${{ env.qemu_version }}-x86_64-riscv64
key: qemu-${{ env.qemu_version }}
- name: Install ninja-build
run: sudo apt-get update && sudo apt-get install -y ninja-build
- name: Download and Compile QEMU
if: steps.cache-qemu.outputs.cache-hit != 'true'
run: .github/scripts/install-qemu.sh ${{ env.qemu_version }}
run: .github/scripts/make-qemu.sh ${{ env.qemu_version }}
- name: Install QEMU
run: |
@ -270,7 +247,16 @@ jobs:
qemu-system-${{ matrix.arch }} --version
- name: Prepare rootfs
run: make other-test ARCH=${{ matrix.arch }} && make image ARCH=${{ matrix.arch }}
run: cargo other-test --arch ${{ matrix.arch }} && cargo image --arch ${{ matrix.arch }}
- if: matrix.arch == 'riscv64'
uses: actions-rs/install@v0.1
with:
crate: cargo-binutils
version: latest
- name: Install python dependencies
run: pip3 install -r tests/requirements.txt
- name: Run fast tests
if: github.event_name != 'schedule'

14
.gitignore vendored
View File

@ -1,18 +1,14 @@
**/.*
!.github/
!.cargo/
!.vscode/settings.json
**/.*/*
!.github/*
!.cargo/*
**/target
**/*.rs.bk
*.img
*.bin
*.log
Cargo.lock
/ignored
/rootfs
zCore/src/platform/riscv/kernel-vars.ld
# for aarch64 only
/zCore/disk
.DS_Store
__pycache__

10
.vscode/settings.json vendored
View File

@ -1,10 +0,0 @@
{
// Prevent "can't find crate for `test`" error on no_std
// Ref: https://github.com/rust-lang/vscode-rust/issues/729
// For vscode-rust plugin users:
"rust.target": "riscv64imac-unknown-none-elf",
"rust.all_targets": false,
// For Rust Analyzer plugin users:
"rust-analyzer.cargo.target": "riscv64imac-unknown-none-elf",
"rust-analyzer.checkOnSave.enable": false
}

2671
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,7 @@ members = [
"linux-syscall",
"loader",
"zCore",
"z-config",
"xtask",
]
default-members = ["xtask"]
@ -15,3 +16,4 @@ exclude = ["zircon-user", "rboot"]
[profile.release]
lto = true
debug = true

View File

@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.

View File

@ -1,16 +1,20 @@
# Makefile for top level of zCore
ARCH ?= x86_64
XTASK ?= 1
.PHONY: help setup update rootfs libc-test other-test image check doc clean
STRIP := $(ARCH)-linux-musl-strip
export PATH=$(shell printenv PATH):$(CURDIR)/ignored/target/$(ARCH)/$(ARCH)-linux-musl-cross/bin/
.PHONY: help zircon-init update rootfs libc-test other-test image check doc clean
# print top level help
help:
cargo xtask help
cargo xtask
# setup git lfs and git submodules
setup:
cargo setup
# download zircon binaries
zircon-init:
cargo zircon-init
# update toolchain and dependencies
update:
@ -18,11 +22,19 @@ update:
# put rootfs for linux mode
rootfs:
ifeq ($(XTASK), 1)
cargo rootfs --arch $(ARCH)
else ifeq ($(ARCH), riscv64)
@rm -rf rootfs/riscv && mkdir -p rootfs/riscv/bin
@wget https://github.com/rcore-os/busybox-prebuilts/raw/master/busybox-1.30.1-riscv64/busybox -O rootfs/riscv/bin/busybox
@ln -s busybox rootfs/riscv/bin/ls
endif
# put libc tests into rootfs
libc-test:
cargo libc-test --arch $(ARCH)
find rootfs/$(ARCH)/libc-test -type f \
-name "*so" -o -name "*exe" -exec $(STRIP) {} \;
# put other tests into rootfs
other-test:
@ -30,7 +42,13 @@ other-test:
# build image from rootfs
image:
ifeq ($(XTASK), 1)
cargo image --arch $(ARCH)
else ifeq ($(ARCH), riscv64)
@echo building riscv.img
@rcore-fs-fuse zCore/riscv64.img rootfs/riscv zip
@qemu-img resize -f raw zCore/riscv64.img +5M
endif
# check code style
check:
@ -43,11 +61,21 @@ doc:
# clean targets
clean:
cargo clean
rm -f *.asm
rm -rf rootfs
rm -rf ignored/target
rm -rf zCore/disk
find zCore -maxdepth 1 -name "*.img" -delete
find zCore -maxdepth 1 -name "*.bin" -delete
rt-test:
cd rootfs/x86_64 && git clone https://kernel.googlesource.com/pub/scm/linux/kernel/git/clrkwllms/rt-tests --depth 1
cd rootfs/x86_64/rt-tests && make
echo x86 gcc build rt-test,now need manual modificy.
# delete targets, including those that are large and compile slowly
cleanup: clean
rm -rf ignored/target
# delete everything, including origin files that are downloaded directly
clean-everything: clean
rm -rf ignored
# rt-test:
# cd rootfs/x86_64 && git clone https://kernel.googlesource.com/pub/scm/linux/kernel/git/clrkwllms/rt-tests --depth 1
# cd rootfs/x86_64/rt-tests && make
# echo x86 gcc build rt-test,now need manual modificy.

278
README-arch.md Normal file
View File

@ -0,0 +1,278 @@
# zCore
[![CI](https://github.com/rcore-os/zCore/workflows/CI/badge.svg?branch=master)](https://github.com/rcore-os/zCore/actions)
[![Docs](https://img.shields.io/badge/docs-alpha-blue)](https://rcore-os.github.io/zCore/)
[![Coverage Status](https://coveralls.io/repos/github/rcore-os/zCore/badge.svg?branch=master)](https://coveralls.io/github/rcore-os/zCore?branch=master)
Reimplement [Zircon][zircon] microkernel in safe Rust as a userspace program!
## Dev Status
🚧 Working In Progress
- 2020.04.16: Zircon console is working on zCore! 🎉
## Quick start for RISCV64
```sh
make riscv-image
cd zCore
make run ARCH=riscv64 LINUX=1
```
## Getting started
Environments
- [Rust toolchain](http://rustup.rs)
- [QEMU](https://www.qemu.org)
### Developing environment info
- current rustc -- rustc 1.60.0-nightly (5e57faa78 2022-01-19)
- current rust-toolchain -- nightly-2022-01-20
- current qemu -- 5.2.0 -> 6.2.0
Clone repo and pull prebuilt fuchsia images:
```sh
git clone https://github.com/rcore-os/zCore --recursive
cd zCore
make setup
```
For users in China, there's a mirror you can try:
```sh
git clone https://github.com.cnpmjs.org/rcore-os/zCore --recursive
```
Use docker container as standand develop environment, please refer to [tootls/docker](https://github.com/rcore-os/zCore/tree/master/tools/docker).
### Run zcore in libos mode
#### Run zcore in linux-libos mode
- step 1: Prepare Alpine Linux rootfs:
```sh
make rootfs
```
- step 2: Compile & Run native Linux program (Busybox) in libos mode:
```sh
cargo run --release --features "linux libos" -- /bin/busybox [args]
```
You can also add the feature `graphic` to show the graphical output (with [sdl2](https://www.libsdl.org) installed).
To debug, set the `LOG` environment variable to one of `error`, `warn`, `info`, `debug`, `trace`.
#### Run native Zircon program (shell) in zircon-libos mode:
- step 1: Compile and Run Zircon shell
```sh
cargo run --release --features "zircon libos" -- prebuilt/zircon/x64/bringup.zbi
```
The `graphic` and `LOG` options are the same as Linux.
### Run zcore in bare-metal mode
#### Run Linux shell in linux-bare-metal mode:
- step 1: Prepare Alpine Linux rootfs:
```sh
make rootfs
```
- step 2: Create Linux rootfs image:
Note: Before below step, you can add some special apps in zCore/rootfs
```sh
make image
```
- step 3: Build and run zcore in linux-bare-metal mode:
```sh
cd zCore && make run MODE=release LINUX=1 [LOG=warn] [GRAPHIC=on] [ACCEL=1]
```
#### Run Zircon shell in zircon-bare-metal mode:
- step 1: Build and run zcore in zircon-bare-metal mode:
```sh
cd zCore && make run MODE=release [LOG=warn] [GRAPHIC=on] [ACCEL=1]
```
- step 2: Build and run your own Zircon user programs:
```sh
# See template in zircon-user
cd zircon-user && make zbi MODE=release
# Run your programs in zCore
cd zCore && make run MODE=release USER=1 [LOG=warn] [GRAPHIC=on] [ACCEL=1]
```
## Testing
### LibOS Mode Testing
#### Zircon related
Run Zircon official core-tests:
```sh
pip3 install pexpect
cd scripts && python3 unix-core-testone.py 'Channel.*'
```
Run all (non-panicked) core-tests for CI:
```sh
pip3 install pexpect
cd scripts && python3 unix-core-tests.py
# Check `zircon/test-result.txt` for results.
```
#### Linux related
Run Linux musl libc-tests for CI:
```sh
make rootfs && make libc-test
cd scripts && python3 libos-libc-tests.py
# Check `linux/test-result.txt` for results.
```
### Bare-metal Mode Testing
#### Zircon related
Run Zircon official core-tests on bare-metal:
```sh
cd zCore && make test MODE=release [ACCEL=1] TEST_FILTER='Channel.*'
```
Run all (non-panicked) core-tests for CI:
```sh
pip3 install pexpect
cd scripts && python3 core-tests.py
# Check `zircon/test-result.txt` for results.
```
#### x86-64 Linux related
Run Linux musl libc-tests for CI:
```sh
## Prepare rootfs with libc-test apps
make baremetal-test-img
## Build zCore kernel
cd zCore && make build MODE=release LINUX=1 ARCH=x86_64
## Testing
cd scripts && python3 baremetal-libc-test.py
##
```
You can use [`scripts/baremetal-libc-test-ones.py`](./scripts/baremetal-libc-test-ones.py) & [`scripts/linux/baremetal-test-ones.txt`](./scripts/linux/baremetal-test-ones.txt) to test specified apps.
[`scripts/linux/baremetal-test-fail.txt`](./scripts/linux/baremetal-test-fail.txt) includes all failed x86-64 apps (We need YOUR HELP to fix bugs!)
#### riscv-64 Linux related
Run Linux musl libc-tests for CI:
```sh
## Prepare rootfs with libc-test & oscomp apps
make riscv-image
## Build zCore kernel & Testing
cd scripts && python3 baremetal-test-riscv64.py
##
```
You can use[scripts/baremetal-libc-test-ones-riscv64.py](./scripts/baremetal-libc-test-ones-riscv64.py) & [`scripts/linux/baremetal-test-ones-rv64.txt`](scripts/linux/baremetal-test-ones-rv64.txt)to test
specified apps.
[`scripts/linux/baremetal-test-fail-riscv64.txt`](./scripts/linux/baremetal-test-fail-riscv64.txt)includes all failed riscv-64 apps (We need YOUR HELP to fix bugs!)
## Graph/Game
snake game: <https://github.com/rcore-os/rcore-user/blob/master/app/src/snake.c>
### Step1: compile usr app
We can use musl-gcc compile it in x86_64 mode
### Step2: change zcore for run snake app first.
change zCore/zCore/main.rs L176
vec!["/bin/busybox".into(), "sh".into()]
TO
vec!["/bin/snake".into(), "sh".into()]
### Step3: prepare root fs image, run zcore in linux-bare-metal mode
exec:
```sh
cd zCore #zCore ROOT DIR
make rootfs
cp ../rcore-user/app/snake rootfs/bin #copy snake ELF file to rootfs/bin
make image # build rootfs image
cd zCore #zCore kernel dir
make run MODE=release LINUX=1 GRAPHIC=on
```
Then you can play the game.
Operation
- Keyboard
- `W`/`A`/`S`/`D`: Move
- `R`: Restart
- `ESC`: End
- Mouse
- `Left`: Speed up
- `Right`: Slow down
- `Middle`: Pause/Resume
## Doc
```
make doc
```
### RISC-V 64 porting info
- [porting riscv64 doc](./docs/porting-rv64.md)
## Components
### Overview
![](./docs/structure.svg)
[zircon]: https://fuchsia.googlesource.com/fuchsia/+/master/zircon/README.md
[kernel-objects]: https://github.com/PanQL/zircon/blob/master/docs/objects.md
[syscalls]: https://github.com/PanQL/zircon/blob/master/docs/syscalls.md
### Hardware Abstraction Layer
| | Bare Metal | Linux / macOS |
| :------------------------ | ---------- | ----------------- |
| Virtual Memory Management | Page Table | Mmap |
| Thread Management | `executor` | `async-std::task` |
| Exception Handling | Interrupt | Signal |
### Small Goal & Little Plans
- <https://github.com/rcore-os/zCore/wiki/Plans>

418
README.md
View File

@ -1,282 +1,270 @@
# zCore
[![CI](https://github.com/rcore-os/zCore/workflows/CI/badge.svg?branch=master)](https://github.com/rcore-os/zCore/actions)
[![Docs](https://img.shields.io/badge/docs-alpha-blue)](https://rcore-os.github.io/zCore/)
[![CI](https://github.com/rcore-os/zCore/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/rcore-os/zCore/actions)
[![Docs](https://img.shields.io/badge/docs-pages-green)](https://rcore-os.github.io/zCore/)
[![Coverage Status](https://coveralls.io/repos/github/rcore-os/zCore/badge.svg?branch=master)](https://coveralls.io/github/rcore-os/zCore?branch=master)
[![issue](https://img.shields.io/github/issues/rcore-os/zCore)](https://github.com/rcore-os/zCore/issues)
[![forks](https://img.shields.io/github/forks/rcore-os/zCore)](https://github.com/rcore-os/zCore/fork)
![stars](https://img.shields.io/github/stars/rcore-os/zCore)
![license](https://img.shields.io/github/license/rcore-os/zCore)
Reimplement [Zircon][zircon] microkernel in safe Rust as a userspace program!
基于 zircon 并提供 Linux 兼容性的操作系统内核。
## Manual
## 原版README
[This](docs/Manual.md) is a new simple chinese manual.
Reimplement `Zircon` microkernel in safe Rust as a userspace program!
## Dev Status
- zCore设计架构概述
- 支持bare-metal模式的Zircon & Linux
- 支持libos模式的Zircon & Linux
- 支持的图形应用程序等更多指导请查看[原版README文档](README-arch.md)。
🚧 Working In Progress
## 启动内核
- 2020.04.16: Zircon console is working on zCore! 🎉
```bash
cargo qemu --arch riscv64
```
## Quick start for RISCV64
这个命令会使用 qemu-system-riscv64 启动 zCore。
```sh
make riscv-image
cd zCore
make run ARCH=riscv64 LINUX=1
默认的文件系统中将包含 busybox 应用程序和 musl-libc 链接器。它们是用自动下载的 musl-libc RISC-V 交叉编译工具链编译的。
## 目录
- [启动内核](#启动内核)
- [项目构建](#项目构建)
- [构建命令](#构建命令)
- [命令参考](#命令参考)
- [平台支持](#平台支持)
- [Qemu/virt](#qemuvirt)
- [全志/哪吒](#全志哪吒)
- [赛昉/星光](#赛昉星光)
- [晶视/cr1825](#晶视cr1825)
## 项目构建
项目构建采用 [xtask 模式](https://github.com/matklad/cargo-xtask),常用操作被封装成 cargo 命令。
另外,还通过 [Makefile](Makefile) 提供 make 调用,以兼容一些旧脚本。
目前已测试的开发环境包括 Ubuntu20.04、Ubuntu22.04 和 Debian11Ubuntu22.04 不能正确编译 x86_64 的 libc 测试。若不需要烧写到物理硬件,使用 WSL2 或其他虚拟机的操作与真机并无不同之处。
### 构建命令
命令的基本格式为 `cargo <command> [--args [value]]`,这实际上是 `cargo run --package xtask --release -- <command> [--args [value]]` 的简写。`command` 被传递给 xtask 应用程序,解析并执行。
许多命令的效果受到仓库环境的影响,也会影响仓库的环境。为了使用方便,如果一个命令依赖于另一个命令的效果,它们被设计为递归的。命令的递归关系图如下,对于它们的详细解释在下一节:
---
> **NOTICE** 建议使用等宽字体
---
```text
┌────────────┐ ┌─────────────┐ ┌─────────────┐
| update-all | | check-style | | zircon-init |
└────────────┘ └─────────────┘ └─────────────┘
┌─────┐ ┌──────┐ ┌─────┐ ┌─────────────┐ ┌─────────────────┐
| asm | | qemu |─→| bin | | linux-libos | | libos-libc-test |
└─────┘ └──────┘ └─────┘ └─────────────┘ └─────────────────┘
| └───┐┌─────┘ ┌───────────┐
↓ ↓↓ ┌──| libc-test |
┌───────┐ ┌────────┐←─┘ └───────────┘
| image |───────→| rootfs |←─┐ ┌────────────┐
└───────┘ └────────┘ └─| other-test |
┌────────┐ ↑ └────────────┘
| opencv |────→┌───────────┐
└────────┘ ┌─→| musl-libc |
┌────────┐ | └───────────┘
| ffmpeg |──┘
└────────┘
-------------------------------------------------------------------
图例A 递归执行 BA 依赖 B 的结果,执行 A 时自动先执行 B
┌───┐ ┌───┐
| A |─→| B |
└───┘ └───┘
```
## Getting started
### 命令参考
Environments
如果下面的命令描述与行为不符,或怀疑此文档更新不及时,亦可直接查看[内联文档](xtask/src/main.rs#L48)。
如果发现 `error: no such subcommand: ...`,查看[命令简写](.cargo/config.toml)为哪些命令设置了别名。
- [Rust toolchain](http://rustup.rs)
- [QEMU](https://www.qemu.org)
- [Git LFS](https://git-lfs.github.com)
---
### Developing environment info
> **NOTICE** 内联文档也是中英双语
- current rustc -- rustc 1.60.0-nightly (5e57faa78 2022-01-19)
- current rust-toolchain -- nightly-2022-01-20
- current qemu -- 5.2.0 -> 6.2.0
---
Clone repo and pull prebuilt fuchsia images:
#### **update-all**
```sh
git clone https://github.com/rcore-os/zCore --recursive
cd zCore
git lfs install
git lfs pull
更新工具链、依赖和 git 子模块。
如果没有递归克隆子模块,可以使用这个命令克隆。
```bash
cargo update-all
```
For users in China, there's a mirror you can try:
#### **check-style**
```sh
git clone https://github.com.cnpmjs.org/rcore-os/zCore --recursive
静态检查。设置多种编译选项,检查代码能否编译。
```bash
cargo check-style
```
### Run zcore in libos mode
#### **zircon-init**
#### Run zcore in linux-libos mode
下载 zircon 模式所需的二进制文件。
- step 1: Prepare Alpine Linux rootfs:
```sh
make rootfs
```
- step 2: Compile & Run native Linux program (Busybox) in libos mode:
```sh
cargo run --release --features "linux libos" -- /bin/busybox [args]
```
You can also add the feature `graphic` to show the graphical output (with [sdl2](https://www.libsdl.org) installed).
To debug, set the `LOG` environment variable to one of `error`, `warn`, `info`, `debug`, `trace`.
#### Run native Zircon program (shell) in zircon-libos mode:
- step 1: Compile and Run Zircon shell
```sh
cargo run --release --features "zircon libos" -- prebuilt/zircon/x64/bringup.zbi
```
The `graphic` and `LOG` options are the same as Linux.
### Run zcore in bare-metal mode
#### Run Linux shell in linux-bare-metal mode:
- step 1: Prepare Alpine Linux rootfs:
```sh
make rootfs
```
- step 2: Create Linux rootfs image:
Note: Before below step, you can add some special apps in zCore/rootfs
```sh
make image
```
- step 3: Build and run zcore in linux-bare-metal mode:
```sh
cd zCore && make run MODE=release LINUX=1 [LOG=warn] [GRAPHIC=on] [ACCEL=1]
```
#### Run Zircon shell in zircon-bare-metal mode:
- step 1: Build and run zcore in zircon-bare-metal mode:
```sh
cd zCore && make run MODE=release [LOG=warn] [GRAPHIC=on] [ACCEL=1]
```
- step 2: Build and run your own Zircon user programs:
```sh
# See template in zircon-user
cd zircon-user && make zbi MODE=release
# Run your programs in zCore
cd zCore && make run MODE=release USER=1 [LOG=warn] [GRAPHIC=on] [ACCEL=1]
```
## Testing
### LibOS Mode Testing
#### Zircon related
Run Zircon official core-tests:
```sh
pip3 install pexpect
cd scripts && python3 unix-core-testone.py 'Channel.*'
```bash
cargo zircon-init
```
Run all (non-panicked) core-tests for CI:
#### **asm**
```sh
pip3 install pexpect
cd scripts && python3 unix-core-tests.py
# Check `zircon/test-result.txt` for results.
反汇并保存编指定架构的内核。默认保存到 `target/zcore.asm`
```bash
cargo asm -m virt-riscv64 -o z.asm
```
#### Linux related
#### **bin**
Run Linux musl libc-tests for CI:
生成内核 raw 镜像到指定位置。默认输出到 `target/{arch}/release/zcore.bin`
```sh
make rootfs && make libc-test
cd scripts && python3 libos-libc-tests.py
# Check `linux/test-result.txt` for results.
```bash
cargo bin -m virt-riscv64 -o z.bin
```
### Bare-metal Mode Testing
#### **qemu**
#### Zircon related
在 Qemu 中启动 zCore。这需要 Qemu 已经安装好了。
Run Zircon official core-tests on bare-metal:
```sh
cd zCore && make test MODE=release [ACCEL=1] TEST_FILTER='Channel.*'
```bash
cargo qemu --arch riscv64 --smp 4
```
Run all (non-panicked) core-tests for CI:
支持将 qemu 连接到 gdb
```sh
pip3 install pexpect
cd scripts && python3 core-tests.py
# Check `zircon/test-result.txt` for results.
```bash
cargo qemu --arch riscv64 --smp 4 --gdb 1234
```
#### x86-64 Linux related
#### **rootfs**
Run Linux musl libc-tests for CI:
重建 Linux rootfs。直接执行这个命令会清空已有的为此架构构造的 rootfs 目录,重建最小的 rootfs。
```sh
## Prepare rootfs with libc-test apps
make baremetal-test-img
## Build zCore kernel
cd zCore && make build MODE=release LINUX=1 ARCH=x86_64
## Testing
cd scripts && python3 baremetal-libc-test.py
##
```bash
cargo rootfs --arch riscv64
```
You can use [`scripts/baremetal-libc-test-ones.py`](./scripts/baremetal-libc-test-ones.py) & [`scripts/linux/baremetal-test-ones.txt`](./scripts/linux/baremetal-test-ones.txt) to test specified apps.
#### **musl-libs**
[`scripts/linux/baremetal-test-fail.txt`](./scripts/linux/baremetal-test-fail.txt) includes all failed x86-64 apps (We need YOUR HELP to fix bugs!)
将 musl 动态库拷贝到 rootfs 目录对应位置。
#### riscv-64 Linux related
Run Linux musl libc-tests for CI:
```sh
## Prepare rootfs with libc-test & oscomp apps
make riscv-image
## Build zCore kernel & Testing
cd scripts && python3 baremetal-test-riscv64.py
##
```bash
cargo musl-libs --arch riscv64
```
You can use[scripts/baremetal-libc-test-ones-riscv64.py](./scripts/baremetal-libc-test-ones-riscv64.py) & [`scripts/linux/baremetal-test-ones-rv64.txt`](scripts/linux/baremetal-test-ones-rv64.txt)to test
specified apps.
#### **ffmpeg**
[`scripts/linux/baremetal-test-fail-riscv64.txt`](./scripts/linux/baremetal-test-fail-riscv64.txt)includes all failed riscv-64 apps (We need YOUR HELP to fix bugs!)
将 ffmpeg 动态库拷贝到 rootfs 目录对应位置。
## Graph/Game
snake game: <https://github.com/rcore-os/rcore-user/blob/master/app/src/snake.c>
### Step1: compile usr app
We can use musl-gcc compile it in x86_64 mode
### Step2: change zcore for run snake app first.
change zCore/zCore/main.rs L176
vec!["/bin/busybox".into(), "sh".into()]
TO
vec!["/bin/snake".into(), "sh".into()]
### Step3: prepare root fs image, run zcore in linux-bare-metal mode
exec:
```sh
cd zCore #zCore ROOT DIR
make rootfs
cp ../rcore-user/app/snake rootfs/bin #copy snake ELF file to rootfs/bin
make image # build rootfs image
cd zCore #zCore kernel dir
make run MODE=release LINUX=1 GRAPHIC=on
```bash
cargo ffmpeg --arch riscv64
```
Then you can play the game.
Operation
#### **opencv**
- Keyboard
- `W`/`A`/`S`/`D`: Move
- `R`: Restart
- `ESC`: End
- Mouse
- `Left`: Speed up
- `Right`: Slow down
- `Middle`: Pause/Resume
将 opencv 动态库拷贝到 rootfs 目录对应位置。如果 ffmpeg 已经放好了opencv 将会编译出包含 ffmepg 支持的版本。
## Doc
```
make doc
```bash
cargo opencv --arch riscv64
```
### RISC-V 64 porting info
#### **libc-test**
- [porting riscv64 doc](./docs/porting-rv64.md)
将 libc 测试集拷贝到 rootfs 目录对应位置。
## Components
```bash
cargo libc-test --arch riscv64
```
### Overview
#### **other-test**
![](./docs/structure.svg)
将其他测试集拷贝到 rootfs 目录对应位置。
[zircon]: https://fuchsia.googlesource.com/fuchsia/+/master/zircon/README.md
[kernel-objects]: https://github.com/PanQL/zircon/blob/master/docs/objects.md
[syscalls]: https://github.com/PanQL/zircon/blob/master/docs/syscalls.md
```bash
cargo other-test --arch riscv64
```
### Hardware Abstraction Layer
#### **image**
| | Bare Metal | Linux / macOS |
| :------------------------ | ---------- | ----------------- |
| Virtual Memory Management | Page Table | Mmap |
| Thread Management | `executor` | `async-std::task` |
| Exception Handling | Interrupt | Signal |
从 rootfs 目录构建 Linux rootfs 镜像文件。
### Small Goal & Little Plans
```bash
cargo image --arch riscv64
```
- <https://github.com/rcore-os/zCore/wiki/Plans>
#### **linux-libos**
在 linux libos 模式下启动 zCore 并执行位于指定路径的应用程序。
> **NOTICE** libos 模式只能执行单个应用程序,完成就会退出。
```bash
cargo linux-libos --args "/bin/busybox"
```
可以直接给应用程序传参数:
```bash
cargo linux-libos --args "/bin/busybox ls"
```
## 平台支持
### Qemu/virt
直接使用命令启动,参见[启动内核](#启动内核)和 [`qemu` 命令](#qemu)。
### 全志/哪吒
使用以下命令构造系统镜像:
```bash
cargo bin -m nezha -o z.bin
```
然后使用 [rustsbi-d1](https://github.com/rustsbi/rustsbi-d1) 将镜像部署到 Flash 或 DRAM。
另: 可以查看[README for D1 文档](docs/README-D1.md)获知更多D1开发板有关的操作指导。
### 赛昉/星光
使用以下命令构造系统镜像:
```bash
cargo bin -m visionfive -o z.bin
```
然后根据[此文档](docs/README-visionfive.md)的详细说明通过 u-boot 网络启动系统。
### 晶视/cr1825
使用以下命令构造系统镜像:
```bash
cargo bin -m cr1825 -o z.bin
```
然后通过 u-boot 网络启动系统。
## 其他
- [An English README](docs/README_EN.md)
- [开发者注意事项(草案)](docs/for-developers.md)
- [构建系统更新日志](xtask/CHANGELOG.md)

View File

@ -0,0 +1,31 @@
[qemu.virt-riscv64]
arch = "riscv64"
[qemu.virt-aarch64]
arch = "aarch64"
[qemu.virt-x86_64]
arch = "x86_64"
[allwinner.nezha]
arch = "riscv64"
link-user-img = "zCore/riscv64.img"
pci-support = false
features = ["allwinner-drivers"]
[cvitek.cr1825]
arch = "riscv64"
link-user-img = "zCore/riscv64.img"
pci-support = false
features = ["thead-maee"]
[starfive.visionfive]
arch = "riscv64"
link-user-img = "zCore/riscv64.img"
pci-support = false
[sifive.fu740]
arch = "riscv64"
link-user-img = "zCore/riscv64.img"
pci-support = true
features = ["fu740-drivers"]

View File

@ -1,86 +0,0 @@
# zCore 项目使用指南
## 预定功能
预定功能指的是 zCore 作为一个项目,为开发者和用户常用操作提供的封装。
由于历史原因,目前预定功能分为顶层预定功能和内核预定功能。
所有顶层提供的预定功能都定义于 [顶层 Makefile](../Makefile)
并且所有预定功能最终都将移动到顶层。
## 常规操作流程
对于一般开发者和用户,可以按以下步骤设置 zCore 项目。
1. 先决条件
目前已测试的开发环境包括 Ubuntu20.04、Ubuntu22.04 和 Debian11
Ubuntu22.04 不能正确编译 x86_64 的 libc 测试。
若不需要烧写到物理硬件,使用 WSL2 或其他虚拟机的操作与真机并无不同之处。
在开始之前,确保你的计算机上安装了 git 和 rustup。要在虚拟环境开发或测试需要 QEMU。
2. 克隆项目
```bash
git clone https://github.com/rcore-os/zCore.git
```
3. 初始化存储库
```bash
make setup
```
4. 保持更新
```bash
make update
```
5. 探索更多操作
```bash
make help
```
6. 推到仓库前,现在本机执行测试
```bash
make check # CI/build 的一部分,未来会实现更多快速测试指令
```
## Linux 模式
zCore 根据向用户提供的系统调用的不同,可分为 zircon 模式和 linux 模式。
要以 linux 模式启动,需要先构建 linux 的启动文件系统。
这个指令构建适于 x86_64 架构的启动文件系统。
```bash
make rootfs ARCH=x86_64
```
这个指令构建适于 riscv64 架构的启动文件系统。
```bash
make rootfs ARCH=riscv64
```
要执行 musl-libc 测试集,需要向文件系统中添加 libc 测试集:
```bash
make libc-test <ARCH=?>
```
要执行 CI 的其他测试,需要向文件系统中添加相应测试集:
```bash
make other-test <ARCH=?>
```
要以裸机模式启动 zCore需要构造将放到设备或虚拟环境中的镜像文件
```bash
make image <ARCH=?>
```

277
docs/README-C910.md Normal file
View File

@ -0,0 +1,277 @@
# zCore on riscv64
## T-HEAD C910 Light val board 操作说明
### 编译zCore内核镜像
编译zCore内核:
```
cd zCore/zCore
make build LINUX=1 MODE=release ARCH=riscv64 PLATFORM=c910light
```
制作u-boot系统镜像:
```
mkimage -A riscv -O linux -C none -T kernel -a 0x200000 -e 0x200000 -n "zCore for c910" -d ../target/riscv64/release/zcore.bin uImageC910
```
### 编译opensbi镜像
```
git clone https://github.com/elliott10/opensbi.git -b thead_light-c910
cd opensbi
make PLATFORM=generic CROSS_COMPILE=/path/to/toolchain/bin/riscv64-unknown-linux-gnu-
# 生成所需的fw_dynamic.bin
```
原编译工具链基于官方仓库https://gitee.com/thead-yocto/xuantie-yocto.git 编译生成出来的。理论上可以使用其他工具链替代之
### 基于u-boot运行
在搭建好tftp服务的服务器目录中放入编译好的opensbi镜像`fw_dynamic.bin`和系统镜像`uImageC910`。<br>
进入配置好网络的C910 Light板子的u-boot命令行上运行
```
ext4load mmc 0:2 $aon_ram_addr light_aon_fpga.bin; ext4load mmc 0:2 $dtb_addr ${fdt_file};
tftp $opensbi_addr fw_dynamic.bin;
tftp $kernel_addr uImageC910;
bootslave; run finduuid; run set_bootargs; bootm $kernel_addr - $dtb_addr;
```
## T-HEAD C910 Light val board 移植说明
### 1. 系统初步分析并制作系统镜像
<img src="img/c910-light.jpeg" alt="c910-light" style="zoom:25%;" />
C910 Light开发板如上图在取得C910 Light开发板后先按照官方的用户手册了解基本的硬件组件以及电源和串口等接口的接线。<br>
用户手册https://gitee.com/thead-yocto/documents/blob/master/en/user_guide/T-Head%20Yeying1520%20Yocto%20User%20Guide.pdf <br>
电源接上以及串口连接到host机后可以看到有四个串口`/dev/ttyUSBX`调试用串口是host机连上该串口并在启动u-boot时按任意键可进入命令行模式<br>
u-boot命令行模式上可以连接通有线网络并通过tftp协议加载待启动的操作系统镜像。<br>
```
# minicom -b 115200 -D /dev/ttyUSB2
U-Boot 2020.01-ge0ddd4721a (Dec 14 2021 - 22:26:59 +0800)
CPU: rv64imafdcvsu
Model: T-HEAD c910 light
DRAM: 1 GiB
C910 CPU FREQ: 1500MHz
AHB2_CPUSYS_HCLK FREQ: 250MHz
AHB3_CPUSYS_PCLK FREQ: 125MHz
PERISYS_AHB_HCLK FREQ: 250MHz
PERISYS_APB_PCLK FREQ: 62MHz
GMAC PLL POSTDIV FREQ: 1000MHZ
DPU0 PLL POSTDIV FREQ: 1188MHZ
DPU1 PLL POSTDIV FREQ: 1188MHZ
MMC: sdhci@ffe7080000: 0, sd@ffe7090000: 1
Loading Environment from MMC... OK
In: serial@ffe7014000
Out: serial@ffe7014000
Err: serial@ffe7014000
Net: eth0: ethernet@ffe7070000
Hit any key to stop autoboot: 0
C910 Light#
# setenv ipaddr <IP>
# setenv serverip <Server IP>
```
在这里一开始尝试fu740板子的zCore系统镜像制作以及tftp启动模式, 在u-boot命令行中配置开发板IP地址和服务器IP地址通过tftp协议加载系统镜像最后通过bootm运行镜像; <br>
其他正常但这样在引导zCore系统镜像时会出现报错显示无法识别该系统镜像.
```
Filename 'uImageC910'.
Load address: 0x200000
Loading: #################################################################
#############################################
5.1 MiB/s
done
Bytes transferred = 1609651 (188fb3 hex)
Wrong Image Format for bootm command
ERROR: can't get kernel image!
```
这个问题分析后发现由于u-boot的版本不同导致对系统镜像格式的识别不一致。<br>
在fu740板子上的zCore系统镜像是基于`.its`脚本的新`FIT image`;<br>
而C910 Light的板子上的u-boot则只支持`old legacy image`,需要这样制作:
```
mkimage -A riscv -O linux -C none -T kernel -a 0x200000 -e 0x200000 -n "zCore for c910" -d ../target/riscv64/release/zcore.bin uImageC910
```
### 2. zCore系统引导构建
根据板子已有的Linux系统镜像可获知加载地址是`Load Address: 0x200000`, 执行入口地址是`Entry Point: 0x200000`.
由`0x200000`入口地址修改zCore的linker.ld链接脚本文件的`BASE_ADDRESS`变量为相应的值编译出zCore系统镜像在u-boot中使用`tftp`命令网络加载镜像,`bootm`命令尝试引导镜像,发现在跳转内核后无任何反应。
这里分析可能有两种可能第一可能zCore默认串口输出调用的opensbi print不正确第二则可能在开始构建虚拟内存并跳转时出错。于是这里先让zCore引导启动时用物理内存的方式把`zCore/src/platform/riscv/`目录中的引导有关的偏移地址变量暂修改成以`0x200000`为入口地址的相应的值即可便没有了问题二剩下了问题一关于opensbi的输出问题。
为了验证opensbi的输出是否正常先尝试最精简的zCore镜像在启动到rust代码的最早阶段调用opensbi的`SBI_CONSOLE_PUTCHAR`输出功能。问题依旧无任何反应,这里陷入了问题僵局;
C910 Light开发板是一块四方形大板配置接口很丰富包括了调试CPU的JTAG口。根据平头哥的官方调试文档连接部署好调试环境 https://occ.t-head.cn/document?temp=linux&slug=t-head-debug-server-user-manual
<img src="img/c910-jtag.jpg" alt="jtag" style="zoom:25%;" />
通过gdb连接JTAG DEBUG Server后便可以单步调试C910 CPU的指令执行了不过偶尔也会有无法下断点的问题需要先把zCore系统镜像加载到内存之后再下函数断点。
在JTAG的单步调试过程中发现在执行指令`ecall SBI_CONSOLE_PUTCHAR`之后没有任何反应理论上应该会有字符从串口输出。这里考虑没有有效的opensbi要么串口驱动有问题。
解决print问题解决串口输出比较直接于是参照u-boot的串口代码把串口输出的基本功能使能代码如下
```
// T-HEAD C910 light
pub fn uart_put(c: u8) {
let ptr = BADDR as *mut u32;
unsafe {
//LSR bit:THRE
while ptr.add(5).read_volatile() & (1 << 5) == 0 {}
//此时transmitter empty, THR有效位是8
ptr.add(0).write_volatile(c as u32);
}
}
pub fn uart_get() -> Option<u8> {
let ptr = BADDR as *mut u32;
unsafe {
//查看LSR的DR位为1则有数据
if ptr.add(5).read_volatile() & 0b1 == 0 {
None
} else {
Some((ptr.add(0).read_volatile() & 0xff) as u8)
}
}
}
```
于是zCore便可以运行输出了。
这里出现device tree解析DTB失败的问题经研究尝试发现是由于DTB加载到内存的空间被zCore内核覆盖了把DTB地址往高地址再移一段偏移便可以正常解析到DTB。
![c910 uart](img/c910-run-uart.png)
后面与平头哥的技术支持人员沟通获得了C910 light板子的文档和代码据此获知更多有效信息可以自定义编译u-boot、Linux内核、以及文件系统等板子必要组件
通过结合分析C910 light板子的文档和源代码理清楚了C910 light板子的启动链:
```
U-Boot 运行于M态
|
V
OpenSBI 由U-Boot来加载会从M态跳转至S态
|
V
Linux 由U-Boot来加载并运行于S态
```
所有若直接使用U-Boot单独加载一个zCore Kernel是没有OpenSBI可print的效果便是无任何输出这里定位了问题便着手修复。
试验使用u-boot单独运行opensbi发现并没有常见的“OPENSBI”大LOGO输出于是尝试修复opensbi的串口串口驱动缺少了对C910 light板子型号`snps,dw-apb-uart`的解析,于是走的通用串口型号`ns16550`打上patchhttps://github.com/elliott10/opensbi/commit/404951dd5b047873fa023545eafeb1fa2a9c5838
编译运行OpenSBI的输出work
### 3. zCore虚拟内存页表问题
zCore继续往下运行便会遇到新的问题停在切换页表`switch table`之后。
这是个很奇怪的问题正常流程这里会映射好zCore kernel的所有sections以及其他的内存地址空间到一个新创建的页表中映射的参数和过程都是复用的其他板子类型如qemu或D1等的。理论上这里没理由出现BUG停在的地点如下
```
[ 48.117274 INFO 0 0:0 kernel_hal::imp::arch::vm] initialized kernel page table @ 0x5c18000
[ 48.128044 DEBUG 0 0:0 kernel_hal::imp::arch::vm] cpu 0 switch table 2ec000 -> 5c18000
```
这个奇怪的问题再次上JTAG调试器跟踪CPU运行到这里后单步指令的行为。
在`switch table`切换页表前下断点,单步跟踪,发现在`csrw satp`之后程序便跑飞了触发异常。于是怀疑satp使用的页表有问题。
Linux代码是zCore开发中非常好的参照这里开始对照Linux的切换页表写satp的过程找到一些参考
<img src="img/c910-linux-pg.png" alt="c910 pagetable" style="zoom:75%;" />
Linux源码中的riscv架构下在构建虚拟内存页表项时
为内核镜像内存地址空间`PAGE_KERNEL`添加相比普通页表的额外的flags属性`CACHE`,`SHARE`,`BUF`
为设备地址空间`PAGE_IOREMAP`添加额外的属性:`SHARE`,`SO`;
这些页表项的额外的flags属性位可以通过查询C910芯片手册获知其定义信息C910额外页面属性位于`63:59`位,包括了`SO`, `CACHE`, `BUF`, `SHARE`, `SEC`
更加其他CPU芯片手册可指导这些平头哥CPU的拓展属性不单在C910中存在在C906 CPU中通用存在。
![c910 pte flags](img/c910-pte-flags.png)
zCore中先尝试把内核的`CACHE`,`SHARE`,`BUF`这些位在构建内核页表时置位上,启动发现问题依旧,依然停在切换页表`switch table`之后,原因不详???
既然基于RISCV标准进行自定义拓展的位理论上应该是可以关闭的吧于是继续在芯片手册中查找果然在拓展状态寄存器`MXSTATUS`中找到了相应的设置位`MAEE`
![c910 mxstatus](img/c910-mxstatus.png)
C910 CPU的MAEE拓展位可以设置是否打开拓展的MMU地址属性即是否使能`SO`, `CACHE`, `BUF`, `SHARE`, `SEC`
设置`MAEE = 0`时, 不拓展MMU地址属性`SO`, `CACHE`, `BUF`, `SHARE`, `SEC`
设置`MAEE = 1`时, 使能拓展MMU中PTE的地址属性`SO`, `CACHE`, `BUF`, `SHARE`, `SEC`并可以在页表项PTE中设置对应位
![c910 mxstatus](img/c910-maee.jpeg)
于是直接关闭虚拟内存的页表项拓展属性,设置`MAEE = 0`,果然之前停在页表切换处`switch table`的问题通过了。zCore可以继续往下执行开始解析设备树的各node节点后面接着会遇到设备地址过高导致在处理解析到的node节点地址时出错...
### 4. 页表项PTE的拓展属性设置MAEE于CR1825板子的尝试
之前一次与DF交流CR1825目前遇到的BUG情况时一开始有提议说可能内核的`.BSS`段可能未清除干净。
因为在去年刚把增加了riscv支持的zCore移植到D1时也出现过spin原子指令死锁的问题这个问题当时请教的JYK童鞋后给思路原来`.bss`段没clear干净导致未初始化时的原子变量存在了随机值持续死锁。
<img src="img/c906-clear-bss.jpeg" alt="c906 clear bsss" style="zoom:50%;" />
不过,这个清除`.bss`段应该是随后就加上了。虽然后来引导启动部分有重构过DF也确认确有执行`.bss`段清除。
我在调试C910的期间在芯片手册中了解页表属性及其相关的其他寄存器位的同时也对比C906手册发现基本两CPU在属性设置方面没有大的区别。
在修复好C910 light板子的停在页表切换处`switch table`的问题后与DF交流并取得cr1825的opensbi, u-boot, Linux等的源代码主要对比与C910 light板子的启动代码的区别。
发现带C906 CPU的cr1825与C910 CPU的light板子的启动代码很相似包括虚拟内存的构建过程同样也对内核虚拟内存的页表项配置了拓展位`cache`, `share`, `buf`而原生zCore从未对这些位进行配置。
于是猜想也许页表项PTE的拓展位设置问题与当前cr1825遇到的原子锁问题有很大的关联原子操作即是需要对虚拟内存中的某个值进行判断改写。
为了验证该猜想制作了一个cr1825的启动引导镜像`fip.bin`, 方式是直接关闭虚拟内存的页表项拓展属性,设置`MAEE = 0`代码修改如https://github.com/elliott10/opensbi/commit/404951dd5b047873fa023545eafeb1fa2a9c5838
请DF帮忙远程验证幸运地原子锁的问题也通过了的确与平头哥的拓展页表项有关
<img src="img/c906-amo-1.jpg" alt="c906 amo 1" style="zoom:50%;" />
<img src="img/c906-amo-2.jpg" alt="c906 amo 1" style="zoom:50%;" />
之后在群里与YDR等人继续交流关于平头哥拓展位的原理问题并获得平头哥技术人员的确认: "PTE中cacheable代表该page可以被906 cache缓存如果为0则不会进入缓存。PTE中bufferable位控制总线传输时的bufferable信号是否拉起在行为上cpu并不关心"“amo指令需要cache支持也就是不能在非cache的区域使用amo指令”。
cr1825锁卡住的问题通了后后面进展较顺利了。
在打开`maee`的情况下,这里可能需要注意内核镜像和设备地址空间所设置的`PTE`额外属性值不同。
根据Linux源码在构建虚拟内存页表项时
为内核镜像内存地址空间`PAGE_KERNEL`添加相比普通页表的额外的flags属性`CACHE`,`SHARE`,`BUF`
为设备地址空间`PAGE_IOREMAP`添加额外的属性:`SHARE`,`SO`;
### 5. 设备地址过高的问题
前面讲到zCore构建好虚拟内存之后解析设备树的各node节点时后面接着会遇到设备地址过高的问题导致在处理解析到的node节点地址时出错。
例如从设备树中,取得的串口基地址是`0xffe7014000`该地址比一般的设备地址大例如相比Qemu的串口基地址`0x10000000`。C910 light板子的多种设备基地址都类似的这么大。在物理地址空间中这些大的设备地址不会出问题但在zCore构建好内核虚拟内存后当统一加上一个`offset`如`0xffffffe000200000`便溢出了SV39模式的虚拟内存地址空间。
对于地址溢出时,对该问题做一个简单的判断处理,把溢出的保留位重新置为`1`即可:
```
paddr | (0x1ffffff << 39)
```
### 5. C910 light板子运行
zCore顺利运行进busybox shell
![c910 zcore](img/c910-zcore-run.png)

View File

@ -1,6 +1,7 @@
# zCore for riscv64
# zCore on riscv64
## 编译 zCore 系统镜像
## D1开发板
### 编译 zCore 系统镜像
先在源码根目录下编译 riscv64 的文件系统。
@ -12,7 +13,7 @@ cd zCore
make build LINUX=1 ARCH=riscv64 PLATFORM=d1 MODE=release
```
## riscv64 开发板的烧写
### riscv64 开发板的烧写
以全志 D1 c906 开发板为例。
@ -29,10 +30,10 @@ make
安装好工具 `xfel`,开发板进入 FEL 模式,可在开发板的 Linux 系统中执行 `reboot efex` 命令进入 FEL 模式。然后运行:
```sh
make run_d1 LINUX=1 ARCH=riscv64 PLATFORM=d1 MODE=release
make run LINUX=1 ARCH=riscv64 PLATFORM=d1 MODE=release
```
### 手动烧写运行:
### (可选)手动烧写运行:
1. 下载 D1 开发板的 [OpenSBI](https://github.com/elliott10/opensbi) 源码,并编译出镜像 build/platform/thead/c910/firmware/fw_payload.elf
@ -42,7 +43,7 @@ make run_d1 LINUX=1 ARCH=riscv64 PLATFORM=d1 MODE=release
make PLATFORM=thead/c910 CROSS_COMPILE=/path/to/toolchain/bin/riscv64-unknown-linux-gnu- SUNXI_CHIP=sun20iw1p1 PLATFORM_RISCV_ISA=rv64gcxthead
```
或使用预编译的镜像 [prebuilt/firmware/d1/fw_payload.elf](../prebuilt/firmware/d1/fw_payload.elf)。
或使用预编译的镜像 [prebuilt/firmware/riscv/d1_fw_payload.elf](../prebuilt/firmware/riscv/d1_fw_payload.elf).
2. 生成包含了 OpenSBI, dtb, zCore 的待烧写固件:
@ -54,12 +55,12 @@ make run_d1 LINUX=1 ARCH=riscv64 PLATFORM=d1 MODE=release
3. 启动全志 D1 c906 开发板,并进入 FEL 模式。然后通过烧写工具 `xfel` 把 zCore 系统镜像载入到 DDR 中:
```
sudo xfel ddr ddr3
sudo xfel ddr d1
sudo xfel write 0x40000000 zcore_d1.bin
sudo xfel exec 0x40000000
```
## 引导运行
### 引导运行
zCore 成功引导后, OpenSBI 会将 dtb 加载到高地址 `0x5ff00000`,运行如下所示:

40
docs/README-fu740.md Normal file
View File

@ -0,0 +1,40 @@
# zCore on riscv64 for fu740
### 编译zCore for fu740系统镜像
先在源码根目录下编译 riscv64 的文件系统。
然后进入子目录 zCore 编译内核,会生成系统镜像`zcore-fu740.itb`
系统镜像会包含fu740板子的设备树, dtb设备树可以从fu740自带的Linux中的`/boot`目录中获取;
也可以从sifive官方镜像中获取https://github.com/sifive/freedom-u-sdk/releases/download/2022.04.00/demo-coreip-cli-unmatched-2022.04.00.rootfs.wic.xz
```sh
make riscv-image
cd zCore
make build MODE=release LINUX=1 ARCH=riscv64 PLATFORM=fu740
```
### 基于U-Boot启动系统镜像
首先搭建一台tftp服务器, 例如在Linux服务器中安装`tftpd-hpa`, 一般tftp服务的目录会在`/srv/tftp/`;
然后把编译出的zCore for fu740系统镜像`zcore-fu740.itb`拷贝到tftp服务目录
开发板fu740开机并进入U-Boot命令行
```
# 配置开发板IP地址和服务器IP地址
setenv ipaddr <IP>
setenv serverip <Server IP>
# 通过tftp协议加载系统镜像
tftp 0xa0000000 zcore-fu740.itb
# 运行
bootm 0xa0000000
```
### fu740资料汇集
Unmatched fu740 板子资料整理, 请见:
https://github.com/oscomp/DocUnmatchedU740/blob/main/unmatched.md

287
docs/README-visionfive.md Normal file
View File

@ -0,0 +1,287 @@
# 在 visionfive 上运行zCore
## 一. visionfive 开发板烧写
> **NOTICE** 本文描述的上位机操作在 Ubuntu20.04 上测试可用
### 1. 在工控机上部署必要服务
```bash
# 部署 dhcpd
# 1. 安装 dhcp3-server
sudo apt install isc-dhcp-server
# 2. 设置 dhcp 服务接口,这个接口为实际的物理网卡接口
vim /etc/default/isc-dhcp-server
------------------------------------------------
INTERFACESv4="enp2s0" # 设置 dhcpv4 端口为 enp2s0
INTERFACESv6=""
------------------------------------------------
# 3. 给这个接口配置 IP 地址,并 up 接口
vim /etc/netplan/01-network-manager-all.yaml
-----------------------------------------------------------
# Let NetworkManager manage all devices on this system
network:
version: 2
renderer: NetworkManager
ethernets:
eno1:
addresses: []
dhcp4: true
optional: true
enp2s0:
addresses: [192.168.10.10/24]
gateway4: 192.168.10.1
nameservers:
addresses: [114.114.114.114,8.8.8.8]
dhcp4: no
------------------------------------------------------------
sudo netplan appply
# 4. 设置 dhcp 相关配置
vim /etc/dhcp/dhcpd.conf
----------------------------------------------------
subnet 192.168.10.0 netmask 255.255.255.0 {
range 192.168.10.120 192.168.10.128;
option routers 192.168.10.10;
option subnet-mask 255.255.255.0;
option broadcast-address 192.168.10.255;
option domain-name-servers 192.168.10.10;
}
-----------------------------------------------------
# 5. 启动 dhcpd 服务
systemctl restart isc-dhcp-server
# 6. 检查 dhcpd 服务状态
systemctl status isc-dhcp-server
# 部署 tftpd
# 1. 安装 tftpd-hpa
sudo apt install tftpd-hpa
# 2. 修改配置
--------------------------------------------------------------
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/root/work/tftpboot" # 此项为 tftp 文件下载路径
TFTP_ADDRESS=":69"
TFTP_OPTIONS="--secure"
--------------------------------------------------------------
# 3. 启动 tftpd 服务
systemctl restart tftpd-hpa
# 4. 检查 tftpd 服务状态
systemctl status tftpd-hpa
```
### 2. 连接工控机和 visionfive 开发板
![avatar](visionfive.jpg)
```bash
# 圆头黑色线为工控机电源线
# 黄色网线是用来板子 dhcp 获取地址的
# 蓝色网线是工控机用来连接公网下载资源的,这里可以忽略
# 白色 USB 接口是给板子供电的5v/3A
# 黑色 USB 接口是串口控制台
```
在工控机上打开串口助手minicom开发板上电后过几秒钟会自动进入 u-boot 命令行模式
```bash
Welcome to minicom 2.7.1
OPTIONS: I18n
Compiled on Dec 23 2019, 02:06:26.
Port /dev/ttyUSB0, 12:54:20
Press CTRL-A Z for help on special keys
VisionFive #
VisionFive #
VisionFive #
# 此时可以使用 `help` 查看有哪些可用命令
# 使用 `printenv` 查看配置了哪些环境变量
# 1. 输入 `dhcp` 命令,让开发板获取 IP 地址
# 注意此时可能会自动下载服务器中的镜像, 请通过Ctrl+C打断
dhcp
# 2. 设置 tftp 客户端地址(本机)
setenv ipaddr 192.168.10.121 # 设置 dhcp 获取的那个地址
# 3. 设置 tftp 服务端地址(工控机)
setenv serverip 192.168.10.10 # 需要与自己 IP 在同一网段
# 4. 测试一下网络是否通畅
ping 192.168.10.10 # 试一下ping主机可选
# 5. 保存上述配置
saveenv # 保存配置到 flash之后就不再需要配置
```
### 3. 制作 itb 格式镜像
```bash
# 1. 从 visionfive 官方库下载 `starfive_fb.h` `starfive_vic7100_clk.dtsi` `starfive_vic7100_evb.dts`
# 2. 使用以下命令编译 dtb
cpp -nostdinc -I include -undef -x assembler-with-cpp starfive_vic7100_evb.dts starfive.dts.0
dtc -o starfive.dtb starfive.dts.0 # 预编译的starfive.dtb已放在prebuilt目录
# 3. 压缩内核镜像到 `z.bin.gz`
gzip -9 -cvf z.bin > z.bin.gz
# 4. 制作 itb 文件
mkimage -f zcore-starfive.its z.itb # zcore-starfive.its即prebuilt目录下的starfive_fdt.its故也可使用mkimage -f prebuilt/firmware/riscv/starfive_fdt.its z.itb达到相同的效果
下面是 zcore-starfive.its 内容
--------------------------------------------------------------------
/*
* U-Boot uImage source file for "zCore-visionfive"
*/
/dts-v1/;
/ {
description = "U-Boot uImage source file for zCore-visionfive";
#address-cells = <1>;
images {
kernel {
description = "Linux kernel for zCore-visionfive";
data = /incbin/("./z.bin.gz");
type = "kernel";
arch = "riscv";
os = "linux";
compression = "gzip";
load = <0x80200000>;
entry = <0x80200000>;
};
fdt {
description = "Flattened Device Tree blob for zCore-visionfive";
data = /incbin/("./starfive.dtb");
type = "flat_dt";
arch = "riscv";
compression = "none";
};
};
configurations {
default = "conf";
conf {
description = "Boot Linux kernel with FDT blob";
kernel = "kernel";
fdt = "fdt";
};
};
};
--------------------------------------------------------------------
# 5. 将 `z.itb` 放入 tftp 服务器指定的下载路径
cp z.itb /path/to/tftpboot
```
### 4. 上传 itb 文件到开发板内存,并从指定位置启动
```bash
VisionFive #tftpboot 0xc0000000 z.itb
Speed: 1000, full duplex
Using dwmac.10020000 device
TFTP from server 192.168.10.10; our IP address is 192.168.10.121
Filename 'z.itb'.
Load address: 0xc0000000
Loading: ################################################## 1.5 MiB
11.4 MiB/s
done
Bytes transferred = 1584003 (182b83 hex)
VisionFive #bootm 0xc0000000
## Loading kernel from FIT Image at c0000000 ...
Using 'conf' configuration
Trying 'kernel' kernel subimage
Description: Linux kernel for zCore-FU740
Type: Kernel Image
Compression: gzip compressed
Data Start: 0xc00000e8
Data Size: 1564993 Bytes = 1.5 MiB
Architecture: RISC-V
OS: Linux
Load Address: 0x80200000
Entry Point: 0x80200000
Verifying Hash Integrity ... OK
## Loading fdt from FIT Image at c0000000 ...
Using 'conf' configuration
Trying 'fdt' fdt subimage
Description: Flattened Device Tree blob for zCoreFU740
Type: Flat Device Tree
Compression: uncompressed
Data Start: 0xc017e2ec
Data Size: 17270 Bytes = 16.9 KiB
Architecture: RISC-V
Verifying Hash Integrity ... OK
Booting using the fdt blob at 0xc017e2ec
Uncompressing Kernel Image
Loading Device Tree to 00000000ff6e1000, end 00000000ff6e8375 ... OK
Starting kernel ...
boot page table launched, sstatus = 0x8000000200046000
kernel (physical): 0000000080200000..0000000085ce70b8
kernel (remapped): ffffffc080200000..ffffffc085ce70b8
device tree: 00000000ff6e1000..00000000ff6e6000
hart0 is booting...
hart1 is the primary hart.
[ 28.007868 WARN 1 0:0 zcore_drivers::builder::devicetree] device-tree: failed to parsing node "gpio@11910000": InvalidParam
[ 28.022102 ERROR 1 0:0 zcore_drivers::irq::riscv_intc] invalid SCAUSE value 0xb!
[ 28.032369 ERROR 1 0:0 zcore_drivers::irq::riscv_intc] invalid SCAUSE value 0xb!
[ 28.074321 WARN 1 0:0 linux_syscall] brk: unimplemented
[ 28.082355 WARN 1 0:0 linux_syscall] brk: unimplemented
[ 28.090609 WARN 1 0:0 linux_syscall::vm] mprotect: unimplemented
[ 28.100315 WARN 1 0:0 linux_syscall::vm] mprotect: unimplemented
[ 28.109179 WARN 1 0:0 linux_syscall] getuid: unimplemented
[ 28.117922 WARN 1 0:0 linux_syscall] getpgid: unimplemented
[ 28.126330 WARN 1 0:0 linux_syscall] setpgid: unimplemented
[ 28.134857 WARN 1 0:0 linux_object::fs::stdio] stdout TCGETS | TIOCSPGRP, pretend to be tty.
[ 28.146419 WARN 1 0:0 linux_object::fs::stdio] stdin TCGETS | TIOCSPGRP, pretend to be tty.
[ 28.157926 WARN 1 0:0 linux_syscall] geteuid: unimplemented
[ 28.166389 WARN 1 0:0 linux_syscall] geteuid: unimplemented
/ #
```
## 二. visionfive 移植问题处理
### 1. 烧录问题
我们使用 `tftpboot 0xc0000000 z.itb` 命令烧录,这个 `0xc0000000` 地址要留足内核解压后的空间。
### 2. 内存映射问题
星光开发板的 u-boot 需要给内核和设备树设置加载位置, 然后通过 `a1` 寄存器将设备树的位置通知内核,实际上设备树被放置到超过 1 GiB 的位置上,而 zCore 只支持 1 GiB所以报非法内存问题。我们需要修改内存映射布局修改参考这 2 个commit
[commit1](https://github.com/rcore-os/zCore/commit/227956d5df401c8f8f2fa746f8aa911d3530637f)
[commit2](https://github.com/rcore-os/zCore/commit/16772b9363d02945863008c6a4639ad1cb37eed4)
### 3. 中断处理中有 bug需要使用当前核去处理对应中断修复见
[commit](https://github.com/rcore-os/zCore/commit/55b3145442f0f70c01527c20e87988d26c01a39b)
### 4. 串口驱动
星光开发板支持 `16550` 驱动,只需做相应的代码适配即可,修改见
[commit](https://github.com/rcore-os/zCore/commit/55b3145442f0f70c01527c20e87988d26c01a39b)
### 5. 未注册中断处理
我们发现星光开发板从 `1` 号核心启动后会报一个 `131` 的中断,这个中断在设备树中是没有的,所以也没有在内核中注册,所以会报错,我们在中断处理的时候,将它的优先级降低做屏蔽处理了,见:
[commit](https://github.com/rcore-os/zCore/commit/55b3145442f0f70c01527c20e87988d26c01a39b)

257
docs/README_EN.md Normal file
View File

@ -0,0 +1,257 @@
# zCore
[![CI](https://github.com/rcore-os/zCore/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/rcore-os/zCore/actions)
[![Docs](https://img.shields.io/badge/docs-pages-green)](https://rcore-os.github.io/zCore/)
[![Coverage Status](https://coveralls.io/repos/github/rcore-os/zCore/badge.svg?branch=master)](https://coveralls.io/github/rcore-os/zCore?branch=master)
[![issue](https://img.shields.io/github/issues/rcore-os/zCore)](https://github.com/rcore-os/zCore/issues)
[![forks](https://img.shields.io/github/forks/rcore-os/zCore)](https://github.com/rcore-os/zCore/fork)
![stars](https://img.shields.io/github/stars/rcore-os/zCore)
![license](https://img.shields.io/github/license/rcore-os/zCore)
An OS kernel based on zircon, provides Linux compatible mode.
- [中文自述文档](../README.md)
- [legacy README](README_LEGACY.md)
> you may want to check the legacy for setting up docker, running graphical applications, etc. But many of these scripts are deprecated
## Launch zCore
```bash
cargo qemu --arch riscv64
```
This command will launch zCore using qemu-system-riscv64。
The default file system will contain a busybox application and a musl-libc linker. They are compiled by automatic downloaded musl-libc RISC-V cross-compilation tool chain.
## Table of contents
- [Launch zCore](#launch-zcore)
- [Build the project](#build-the-project)
- [Commands](#commands)
- [Commands reference](#commands-reference)
- [Platform support](#platform-support)
- [Qemu/virt](#qemuvirt)
- [Allwinner/nezha](#allwinnernezha)
- [starfivetech/visionfive](#starfivetechvisionfive)
- [cvitek/cr1825](#cvitekcr1825)
## Build the project
The project will be built with [xtask](https://github.com/matklad/cargo-xtask). The common operations are provided as cargo commands.
An extra [Makefile](../Makefile) provides make calls for compatibility with some legacy scripts.
Currently tested development environments include Ubuntu 20.04, Ubuntu 22.04 and Debian 11.
The libc tests for x86_64 cannot compile on Ubuntu22.04.
If you do not need to flash to physical hardware, using WSL2 or other virtual machines does not operate any differently from the real machine.
### Commands
The basic format of the command is `cargo <command> [--rags [value]]`, which is actually `cargo run --package xtask --release -- <command> [--args [value]]`. `command` is passed to the xtask application to parse and execute.
The effects of many commands are affected by the repo environment and will also affect the repo environment. For convenience, if one command depends on the result of another command, they are designed to recursion. The recursive relationship diagram of the commands is as follows. The detailed explanation of them is in the next section:
---
> **NOTICE** It is recommended to use equivalent fonts
---
```text
┌────────────┐ ┌─────────────┐ ┌─────────────┐
| update-all | | check-style | | zircon-init |
└────────────┘ └─────────────┘ └─────────────┘
┌─────┐ ┌──────┐ ┌─────┐ ┌─────────────┐ ┌─────────────────┐
| asm | | qemu |─→| bin | | linux-libos | | libos-libc-test |
└─────┘ └──────┘ └─────┘ └─────────────┘ └─────────────────┘
| └───┐┌─────┘ ┌───────────┐
↓ ↓↓ ┌──| libc-test |
┌───────┐ ┌────────┐←─┘ └───────────┘
| image |───────→| rootfs |←─┐ ┌────────────┐
└───────┘ └────────┘ └─| other-test |
┌────────┐ ↑ └────────────┘
| opencv |────→┌───────────┐
└────────┘ ┌─→| musl-libc |
┌────────┐ | └───────────┘
| ffmpeg |──┘
└────────┘
-------------------------------------------------------------------
Example`A` recursively executing `B` (`A` depends on the results of `B`, and `B` is executed before `A` automatically)
┌───┐ ┌───┐
| A |─→| B |
└───┘ └───┘
```
### Commands reference
If the following command description does not match its behavior, or if you suspect that this documentation is not up to date, you can check the [inline documentation](../xtask/src/main.rs#L48) as well.
If you find `error: no such subcommand: ...`, check [command alias](../.cargo/config.toml) to see which commands have aliases set for them.
---
> **NOTICE** inline documentation is also bilingual
---
#### **update-all**
Updates toolchain、dependencies and submodules.
```bash
cargo update-all
```
#### **check-style**
Checks code without running. Try to compile the project with various different features.
```bash
cargo check-style
```
#### **zircon-init**
Download zircon binaries.
```bash
cargo zircon-init
```
#### **asm**
Dumps the asm of kernel for specific architecture.
The default output is `target/zcore.asm`.
```bash
cargo asm -m virt-riscv64 -o z.asm
```
#### **bin**
Strips kernel binary for specific architecture.
The default output is `target/{arch}/release/zcore.bin`.
```bash
cargo bin -m virt-riscv64 -o z.bin
```
#### **qemu**
Runs zCore in qemu.
```bash
cargo qemu --arch riscv64 --smp 4
```
Connects qemu to gdb
```bash
cargo qemu --arch riscv64 --smp 4 --gdb 1234
```
#### **rootfs**
Rebuilds the linux rootfs.
This command will remove the existing rootfs directory for this architecture,
and rebuild a minimum rootfs.
```bash
cargo rootfs --arch riscv64
```
#### **musl-libs**
Copies musl so files to rootfs directory.
```bash
cargo musl-libs --arch riscv64
```
#### **ffmpeg**
Copies ffmpeg so files to rootfs directory.
```bash
cargo ffmpeg --arch riscv64
```
#### **opencv**
Copies opencv so files to rootfs directory.
If ffmpeg is already there, this opencv will build with ffmpeg support.
```bash
cargo opencv --arch riscv64
```
#### **libc-test**
Copies libc test files to rootfs directory.
```bash
cargo libc-test --arch riscv64
```
#### **other-test**
Copies other test files to rootfs directory.
```bash
cargo other-test --arch riscv64
```
#### **image**
Builds the linux rootfs image file.
```bash
cargo image --arch riscv64
```
#### **linux-libos**
Runs zCore in linux libos mode and runs an executable at the specified path.
> **NOTICE** zCore can only run a single executable in libos mode, and it will exit after finishing.
```bash
cargo linux-libos --args /bin/busybox
```
## Platform support
### Qemu/virt
Launch with command directly, see [launch zCore](#launch-zcore).
### Allwinner/nezha
Build kernel binary with the following command:
```bash
cargo bin -m nezha -o z.bin
```
Then deploy the binary to Flash or DRAM with [rustsbi-d1](https://github.com/rustsbi/rustsbi-d1).
### Starfivetech/visionfive
Build kernel binary with the following command:
```bash
cargo bin -m visionfive -o z.bin
```
Then, see [this document](docs/README-visionfive.md) for detailed description, launching the system through u-boot network.
### cvitek/cr1825
Build kernel binary with the following command:
```bash
cargo bin -m cr1825 -o z.bin
```
Then launch the system through u-boot network.

145
docs/for-developers.md Normal file
View File

@ -0,0 +1,145 @@
# 开发者注意事项(草案)
本文用于同步开发 zCore 的一些策略选择并提醒开发者某些需要注意的信息。
> 本文暂时是一份草案,欢迎在相关微信群或 github [讨论区](https://github.com/rcore-os/zCore/discussions/356)发表对形式和内容的意见
## 目录
- [工具链支持策略](#工具链支持策略)
>
> - 确定跟踪工具链的时间点
> - 汇总使用到的不稳定特性,以及使用的原因
>
- [代码质量保障](#代码质量保障)
> 介绍如何使用 `#[deny(...)]``#[allow(...)]`
- [依赖管理策略](#依赖管理策略)
> 介绍何时应以何种方式引入依赖项
- [features and cfg](#features-and-cfg)
> 介绍如何使用编译条件
## 工具链支持策略
由于[下文](#使用的不稳定特性)详述的具体原因,本项目依赖一些不稳定特性,只能使用 nightly 工具链编译。仓库将测试可用的工具链记录在 cargo 可识别的[工具链配置文件](../rust-toolchain.toml),使用 cargo 构建项目时会自动安装可靠的工具链。
仓库使用的工具链虽然是 nightly 的,但将伴随 stable 工具链的版本更新而更新。每当 stable 工具链更新,就将默认工具链更新到最接近最新 stable 的版本,周期约为 6 周。参考[版本信息网站](https://forge.rust-lang.org/)记录的最新稳定版分叉发生时间,使用对应的 nightly 即可。
下一次更新的版本为 1.642022-08-05进行更新的日期为 2022 年 9 月 22 日。
> 本文档记录的预期更新时间将随着每次工具链更新而更新。
### 使用的不稳定特性
#### [`doc_cfg`](https://doc.rust-lang.org/unstable-book/language-features/doc-cfg.html)
用到的模块:`zcore-drivers`、`kernel-hal`、`zcore-loader`
用于在文档上标记对象可使用的平台信息。
标注有助于提升文档质量,但不影响使用,必要时可去除。
#### [`naked_functions`](https://doc.rust-lang.org/unstable-book/language-features/naked-functions.html), [`asm_sym`](https://doc.rust-lang.org/unstable-book/language-features/asm-sym.html), [`asm_const`](https://doc.rust-lang.org/unstable-book/language-features/asm-const.html)
用到的模块:`zcore`
这三项用于支撑一个 rust 裸函数。裸函数不会自动插入栈操作,因此可用于设置栈之前的阶段。配合用于向内联汇编导入 rust 常量的 `asm_const` 和向内联汇编导入 rust 符号的 `asm_sym`,可以将整个启动阶段尽量置于 rust 的保护之下(避免硬编码常量或导出全局符号)。
可以移除,但不建议。
#### [`default_alloc_error_handler`](https://doc.rust-lang.org/unstable-book/language-features/default-alloc-error-handler.html)
用到的模块:`zcore`
要求 `alloc` 提供一个默认的分配失败回调。
只要同时使用 `no_std``alloc` 就必然需要分配失败回调,可选默认的或通过另一个不稳定特性 [`alloc-error-handler`](https://doc.rust-lang.org/unstable-book/language-features/alloc-error-handler.html) 提供一个自定义的。
## 代码质量保障
代码质量主要依赖 **clippy** 来保障。因此,需要创造利于 clippy 运行的环境,这包括三个部分:
1. rust-analyzer 绑定
如果使用 vs code 开发rust-analyzer 支持 checkOnSave 功能,即保存时自动检查(得益于现代编译器的效率,这是可能的)。如果配合自动保存功能,可实现随时检查,只要将检查方式默认为 clippy即可随时 clippy。
当然 clippy 运行比较慢,如果电脑性能不适应,只好关掉。
2. `#![deny(warnings)]`
这个选项将当前模块当然也包括子模块产生的警告视为错误这会禁止产生警告的代码完成编译有助于及早解决问题。clippy 也将产生警告,这些警告也被视作错误。
目前所有模块都添加了这个选项有些还禁止了别的东西unsafe_code 及 missing_docs 等,这不在我们的讨论范围内),且处在可通过编译的状态。开发时为了方便当然可以注释掉它们,但如果发布 PR务必恢复这些选项。
3. github actions
使用 clippy 检查代码已经写入 github 工作流,每次提交都会自动执行。这可以向其他开发者证明你的代码质量受到保障。可以在本地使用 `cargo check-style` 命令检查代码的合规性,其流程和使用 clippy 的方式与 github 工作流保持一致。
## 依赖管理策略
依赖从特殊到一般,分为以下 4 种形式:
1. [git 子模块](#git-子模块)
2. [个人仓库中基于 cargo 的项目](#个人仓库中基于-cargo-的项目)
3. [组织仓库中基于 cargo 的项目](#组织仓库中基于-cargo-的项目)
4. [发布到 crates.io 上的 crate](#发布到-cratesio-上的-crate)
### git 子模块
最特殊的依赖方式,对于那些不使用 cargo由于不是 rust 编写)的项目不得不如此。
目前使用此方式依赖的项目包括:
- libc-test
musl libc 的测例。使用 c 语言实现。
- tests
测试框架。主要使用 python。
- rboot
uefi 引导程序,使用 rust 实现。作为子模块是一个遗留问题,未来会解决。
### 个人仓库中基于 cargo 的项目
比较特殊的依赖方式,当且仅当一个项目具有下列情况之一:
- 属于实验性质,不稳定甚至可能放弃;
- 稳定,但不适合发布到 crates.io也没有组织愿意收录
- 从组织项目分叉,已提交 PR 但尚未采纳;
- 从组织项目分叉,且出于充分的理由决定永久分叉,成为一个独立的项目;
可以直接从个人项目中直接依赖。
如有可能,上述情况应当积极解决。
必须锁定提交哈希。
### 组织仓库中基于 cargo 的项目
正常的依赖方式,但若有可能,尽量发布到 crates.io。
必须锁定提交哈希。
### 发布到 crates.io 上的 crate
正常的依赖方式,可以随意使用。
尽量跟踪最新版本。对于无法跟踪的依赖,应记录理由。
## features and cfg
zCore 支持多种平台的不同硬件,难以避免使用编译选项。但是不当使用编译选项,可能导致混乱,或者干扰测试的覆盖性。因此,建议遵从如下标准设置 `#[cfg(...)]`
1. 仅与由平台决定的,设置 target_arch
2. 受到其他因素影响的,考虑通过设备树等方式动态决定;
3. 无法动态决定的,可以设置 feature但应在所在项目的入口lib.rs 或 main.rs注明设置 feature 的原因;
4. 平台相关的 feature应增加如下的约束而不是使用 `all(target_arch = ..., feature = ...)`
```rust
#[cfg(all(feature = "sbi", not(target_arch = "riscv64")))]
compile_error!("`sbi` is only available on RISC-V platforms");
```
> 现有代码不完全满足以上标准,将逐步改正

BIN
docs/img/c906-amo-1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

BIN
docs/img/c906-amo-2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 KiB

BIN
docs/img/c910-jtag.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 MiB

BIN
docs/img/c910-light.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 MiB

BIN
docs/img/c910-linux-pg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

BIN
docs/img/c910-maee.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
docs/img/c910-mxstatus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
docs/img/c910-pte-flags.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

BIN
docs/img/c910-run-uart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

BIN
docs/img/c910-zcore-run.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

BIN
docs/visionfive.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

View File

@ -11,10 +11,16 @@ description = "Device drivers of zCore"
graphic = ["rcore-console"]
mock = ["async-std", "sdl2"]
virtio = ["virtio-drivers"]
loopback = []
no-pci = []
# special drivers for hardwares
allwinner = ["d1-pac"]
fu740 = []
[dependencies]
log = "0.4"
spin = "0.9"
cfg-if = "1.0"
bitflags = "1.3"
lazy_static = "1.4"
@ -24,23 +30,37 @@ bitmap-allocator = { git = "https://github.com/rcore-os/bitmap-allocator", rev =
pci = { git = "https://github.com/elliott10/pci-rs", rev = "8f33774b" }
virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "2aaf7d6", optional = true }
rcore-console = { git = "https://github.com/rcore-os/rcore-console", default-features = false, rev = "ca5b1bc", optional = true }
lock = { git = "https://github.com/DeathWish5/kernel-sync", rev = "01b2e70" }
isomorphic_drivers = { git = "https://github.com/rcore-os/isomorphic_drivers", rev = "f7cd97a8", features = ["log"] }
smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp", rev = "35e833e3", default-features = false, features = ["log", "alloc", "verbose", "proto-ipv4", "proto-ipv6", "proto-igmp", "medium-ip", "medium-ethernet", "socket-raw", "socket-udp", "socket-tcp", "socket-icmp", "async"] }
lock = { git = "https://github.com/DeathWish5/kernel-sync", rev = "8486b8" }
isomorphic_drivers = { git = "https://github.com/rcore-os/isomorphic_drivers", rev = "f7cd97a8", features = [
"log",
] }
smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp", rev = "35e833e3", default-features = false, features = [
"log",
"alloc",
"verbose",
"proto-ipv4",
"proto-ipv6",
"proto-igmp",
"medium-ip",
"medium-ethernet",
"socket-raw",
"socket-udp",
"socket-tcp",
"socket-icmp",
"async",
] }
d1-pac = { version = "0.0.27", optional = true }
volatile = "0.3"
# LibOS mode
[target.'cfg(not(target_os = "none"))'.dependencies]
async-std = { version = "1.10", optional = true }
sdl2 = { version = "0.34", optional = true }
# Bare-metal mode
[target.'cfg(target_os = "none")'.dependencies]
[target.'cfg(target_arch = "x86_64")'.dependencies]
acpi = "4.1"
x2apic = "0.4"
x86_64 = "0.14"
[target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies]
riscv = "0.8"
riscv = "0.9"

View File

@ -17,15 +17,14 @@
//!
//! Specification: <https://github.com/devicetree-org/devicetree-specification/releases/download/v0.3/devicetree-specification-v0.3.pdf>.
use alloc::{collections::BTreeMap, sync::Arc, vec::Vec};
use super::IoMapper;
use crate::{
utils::devicetree::{
parse_interrupts, parse_reg, Devicetree, InheritProps, InterruptsProp, Node, StringList,
},
Device, DeviceError, DeviceResult, VirtAddr,
Device, DeviceError, DeviceResult, PhysAddr, VirtAddr,
};
use alloc::{collections::BTreeMap, sync::Arc, vec::Vec};
const MODULE: &str = "device-tree";
@ -63,6 +62,48 @@ impl<M: IoMapper> DevicetreeDriverBuilder<M> {
let mut intc_map = BTreeMap::new(); // phandle -> intc
let mut dev_list = Vec::new(); // devices
// 为 d1 启动 uart5
// 硬编码只是一个临时的方案
#[cfg(feature = "allwinner")]
{
use d1_pac::{ccu::RegisterBlock as Ccu, gpio::RegisterBlock as Gpio, CCU, GPIO};
let gpio = unsafe { &*(self.mmap(GPIO::PTR as _, 0x1000)? as *const Gpio) };
let ccu = unsafe { &*(self.mmap(CCU::PTR as _, 0x800)? as *const Ccu) };
#[rustfmt::skip]
gpio.pb_cfg0.modify(|r, w| unsafe {
w.bits(r.bits())
.pb0_select().uart2_tx()
.pb1_select().uart2_rx()
.pb4_select().uart5_tx()
.pb5_select().uart5_rx()
});
#[rustfmt::skip]
gpio.pb_cfg1.modify(|r, w| unsafe {
w.bits(r.bits())
.pb8_select().uart0_tx()
.pb9_select().uart0_rx()
});
#[rustfmt::skip]
gpio.pd_cfg1.modify(|r, w| unsafe {
w.bits(r.bits())
.pd10_select().uart3_tx()
.pd11_select().uart3_rx()
});
#[rustfmt::skip]
ccu.uart_bgr.write(|w| w
.uart0_rst() .deassert()
.uart0_gating().pass()
.uart2_rst() .deassert()
.uart2_gating().pass()
.uart3_rst() .deassert()
.uart3_gating().pass()
.uart5_rst() .deassert()
.uart5_gating().pass()
);
}
// 解析设备树
self.dt.walk(&mut |node, comp, props| {
debug!(
@ -86,10 +127,11 @@ impl<M: IoMapper> DevicetreeDriverBuilder<M> {
match comp {
#[cfg(feature = "virtio")]
c if c.contains("virtio,mmio") => self.parse_virtio(node, props),
#[cfg(not(feature = "loopback"))]
c if c.contains("allwinner,sunxi-gmac") => {
self.parse_ethernet(node, comp, props)
}
c if c.contains("ns16550a") || c.contains("allwinner,sun20i-uart") => {
c if c.contains("ns16550a") || c.iter().any(|str| str.ends_with("uart")) => {
self.parse_uart(node, comp, props)
}
_ => Err(DeviceError::NotSupported),
@ -133,6 +175,12 @@ impl<M: IoMapper> DevicetreeDriverBuilder<M> {
// 丢弃中断信息
Ok(dev_list.into_iter().map(|(dev, _)| dev).collect())
}
fn mmap(&self, phys_addr: PhysAddr, len: usize) -> DeviceResult<VirtAddr> {
self.io_mapper
.query_or_map(phys_addr, len)
.ok_or(DeviceError::NoResources)
}
}
#[allow(dead_code)]
@ -154,17 +202,16 @@ impl<M: IoMapper> DevicetreeDriverBuilder<M> {
.prop_u32("#interrupt-cells")
.map_err(|_| DeviceError::InvalidParam)?;
let interrupts_extended = parse_interrupts(node, props)?;
let base_vaddr = parse_reg(node, props).and_then(|(paddr, size)| {
self.io_mapper
.query_or_map(paddr as usize, size as usize)
.ok_or(DeviceError::NoResources)
});
let base_vaddr =
parse_reg(node, props).and_then(|(paddr, size)| self.mmap(paddr as _, size as _));
use crate::irq::*;
let dev = Device::Irq(match comp {
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
c if c.contains("riscv,cpu-intc") => Arc::new(riscv::Intc::new()),
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
c if c.contains("riscv,plic0") => Arc::new(riscv::Plic::new(base_vaddr?)),
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
c if c.contains("sifive,fu540-c000-plic") => Arc::new(riscv::Plic::new(base_vaddr?)),
_ => return Err(DeviceError::NotSupported),
});
@ -184,11 +231,8 @@ impl<M: IoMapper> DevicetreeDriverBuilder<M> {
use virtio_drivers::{DeviceType, VirtIOHeader};
let interrupts_extended = parse_interrupts(node, props)?;
let base_vaddr = parse_reg(node, props).and_then(|(paddr, size)| {
self.io_mapper
.query_or_map(paddr as usize, size as usize)
.ok_or(DeviceError::NoResources)
})?;
let base_vaddr =
parse_reg(node, props).and_then(|(paddr, size)| self.mmap(paddr as _, size as _))?;
let header = unsafe { &mut *(base_vaddr as *mut VirtIOHeader) };
if !header.verify() {
return Err(DeviceError::NotSupported);
@ -218,11 +262,8 @@ impl<M: IoMapper> DevicetreeDriverBuilder<M> {
props: &InheritProps,
) -> DeviceResult<DevWithInterrupt> {
let interrupts_extended = parse_interrupts(node, props)?;
let base_vaddr = parse_reg(node, props).and_then(|(paddr, size)| {
self.io_mapper
.query_or_map(paddr as usize, size as usize)
.ok_or(DeviceError::NoResources)
});
let base_vaddr =
parse_reg(node, props).and_then(|(paddr, size)| self.mmap(paddr as _, size as _));
info!("Ethernet gmac init ...");
let irq_num = interrupts_extended[1];
@ -248,19 +289,22 @@ impl<M: IoMapper> DevicetreeDriverBuilder<M> {
props: &InheritProps,
) -> DeviceResult<DevWithInterrupt> {
let interrupts_extended = parse_interrupts(node, props)?;
let base_vaddr = parse_reg(node, props).and_then(|(paddr, size)| {
self.io_mapper
.query_or_map(paddr as usize, size as usize)
.ok_or(DeviceError::NoResources)
});
let base_vaddr =
parse_reg(node, props).and_then(|(paddr, size)| self.mmap(paddr as _, size as _))?;
use crate::uart::*;
let dev = Device::Uart(match comp {
c if c.contains("ns16550a") => {
Arc::new(unsafe { Uart16550Mmio::<u8>::new(base_vaddr?) })
Arc::new(unsafe { Uart16550Mmio::<u8>::new(base_vaddr) })
}
c if c.contains("allwinner,sun20i-uart") => {
Arc::new(unsafe { Uart16550Mmio::<u32>::new(base_vaddr?) })
c if c.contains("snps,dw-apb-uart") => {
Arc::new(unsafe { Uart16550Mmio::<u32>::new(base_vaddr) })
}
#[cfg(feature = "allwinner")]
c if c.contains("allwinner,sun20i-uart") => Arc::new(UartAllwinner::new(base_vaddr)),
#[cfg(feature = "fu740")]
c if c.contains("sifive,fu740-c000-uart") => {
Arc::new(unsafe { UartU740Mmio::<u32>::new(base_vaddr) })
}
_ => return Err(DeviceError::NotSupported),
});

View File

@ -1,5 +1,3 @@
#![allow(unused)]
#[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
pub mod pci;
@ -11,6 +9,7 @@ pub fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
unsafe { drivers_virt_to_phys(vaddr) }
}
#[allow(unused)]
extern "C" {
fn drivers_dma_alloc(pages: usize) -> PhysAddr;
fn drivers_dma_dealloc(paddr: PhysAddr, pages: usize) -> i32;

View File

@ -1,22 +1,23 @@
use super::{phys_to_virt, PAGE_SIZE};
use crate::builder::IoMapper;
use crate::{Device, DeviceError, DeviceResult, VirtAddr};
use alloc::{collections::BTreeMap, format, sync::Arc, vec::Vec};
use crate::{Device, DeviceError, DeviceResult};
use alloc::{format, sync::Arc, vec::Vec};
use pci::*;
use spin::Mutex;
const PCI_COMMAND: u16 = 0x04;
const BAR0: u16 = 0x10;
const PCI_CAP_PTR: u16 = 0x34;
const PCI_INTERRUPT_LINE: u16 = 0x3c;
const PCI_INTERRUPT_PIN: u16 = 0x3d;
const _PCI_INTERRUPT_LINE: u16 = 0x3c;
const _PCI_INTERRUPT_PIN: u16 = 0x3d;
const PCI_MSI_CTRL_CAP: u16 = 0x00;
const PCI_MSI_ADDR: u16 = 0x04;
const PCI_MSI_UPPER_ADDR: u16 = 0x08;
const _PCI_MSI_UPPER_ADDR: u16 = 0x08;
const PCI_MSI_DATA_32: u16 = 0x08;
const PCI_MSI_DATA_64: u16 = 0x0C;
// const PCI_COMMAND_INTX_DISABLE:u16 = 0x400;
const PCI_CAP_ID_MSI: u8 = 0x05;
struct PortOpsImpl;
@ -99,7 +100,7 @@ unsafe fn enable(loc: Location, paddr: u64) -> Option<usize> {
// reveal PCI regs by setting paddr
let bar0_raw = am.read32(ops, loc, BAR0);
am.write32(ops, loc, BAR0, (paddr & !0xfff) as u32); //Only for 32-bit decoding
debug!(
warn!(
"BAR0 set from {:#x} to {:#x}",
bar0_raw,
am.read32(ops, loc, BAR0)
@ -109,9 +110,9 @@ unsafe fn enable(loc: Location, paddr: u64) -> Option<usize> {
// 23 and lower are used
static mut MSI_IRQ: u32 = 23;
let orig = am.read16(ops, loc, PCI_COMMAND);
let _orig = am.read16(ops, loc, PCI_COMMAND);
// IO Space | MEM Space | Bus Mastering | Special Cycles | PCI Interrupt Disable
am.write32(ops, loc, PCI_COMMAND, (orig | 0x40f) as u32);
// am.write32(ops, loc, PCI_COMMAND, (orig | 0x40f) as u32);
// find MSI cap
let mut msi_found = false;
@ -151,13 +152,13 @@ unsafe fn enable(loc: Location, paddr: u64) -> Option<usize> {
}
if !msi_found {
// Use PCI legacy interrupt instead
// IO Space | MEM Space | Bus Mastering | Special Cycles
am.write32(ops, loc, PCI_COMMAND, (orig | 0xf) as u32);
// am.write16(ops, loc, PCI_COMMAND, (0x2) as u16);
am.write16(ops, loc, PCI_COMMAND, 0x6);
am.write32(ops, loc, _PCI_INTERRUPT_LINE, 33);
debug!("MSI not found, using PCI interrupt");
}
info!("pci device enable done");
warn!("pci device enable done");
assigned_irq
}
@ -166,15 +167,7 @@ pub fn init_driver(dev: &PCIDevice, mapper: &Option<Arc<dyn IoMapper>>) -> Devic
let name = format!("enp{}s{}f{}", dev.loc.bus, dev.loc.device, dev.loc.function);
match (dev.id.vendor_id, dev.id.device_id) {
(0x8086, 0x100e) | (0x8086, 0x100f) | (0x8086, 0x10d3) => {
// 0x100e
// 82540EM Gigabit Ethernet Controller
// 0x100f
// 82545EM Gigabit Ethernet Controller (Copper)
// 0x10d3
// 82574L Gigabit Network Connection
// (e1000e 8086:10d3)
if let Some(BAR::Memory(addr, len, _, _)) = dev.bars[0] {
info!("Found e1000e dev {:?} BAR0 {:#x?}", dev, addr);
#[cfg(target_arch = "riscv64")]
let addr = if addr == 0 { E1000_BASE as u64 } else { addr };
@ -193,9 +186,28 @@ pub fn init_driver(dev: &PCIDevice, mapper: &Option<Arc<dyn IoMapper>>) -> Devic
return Ok(dev);
}
}
(0x1b36, 0x10) => {
if let Some(BAR::Memory(addr, _len, _, _)) = dev.bars[0] {
#[cfg(target_arch = "riscv64")]
let addr = if addr == 0 { E1000_BASE as u64 } else { addr };
if let Some(m) = mapper {
m.query_or_map(addr as usize, PAGE_SIZE * 8);
}
let irq = unsafe { enable(dev.loc, addr) };
let vaddr = phys_to_virt(addr as usize);
let blk = Arc::new(crate::nvme::NvmeInterface::new(vaddr, irq.unwrap_or(33))?);
let dev = Device::Block(blk);
return Ok(dev);
}
}
(0x8086, 0x10fb) => {
// 82599ES 10-Gigabit SFI/SFP+ Network Connection
if let Some(BAR::Memory(addr, len, _, _)) = dev.bars[0] {
if let Some(BAR::Memory(addr, _len, _, _)) = dev.bars[0] {
let irq = unsafe { enable(dev.loc, 0) };
let vaddr = phys_to_virt(addr as usize);
info!("Found ixgbe dev {:#x}, irq: {:?}", vaddr, irq);
@ -210,14 +222,14 @@ pub fn init_driver(dev: &PCIDevice, mapper: &Option<Arc<dyn IoMapper>>) -> Devic
}
}
(0x8086, 0x1533) => {
if let Some(BAR::Memory(addr, len, _, _)) = dev.bars[0] {
if let Some(BAR::Memory(addr, _len, _, _)) = dev.bars[0] {
info!("Intel Corporation I210 Gigabit Network Connection");
info!("DEV: {:?}, BAR0: {:#x}", dev, addr);
return Err(DeviceError::NotSupported);
}
}
(0x8086, 0x1539) => {
if let Some(BAR::Memory(addr, len, _, _)) = dev.bars[0] {
if let Some(BAR::Memory(addr, _len, _, _)) = dev.bars[0] {
info!(
"Found Intel I211 ethernet controller dev {:?}, addr: {:x?}",
dev, addr
@ -230,7 +242,7 @@ pub fn init_driver(dev: &PCIDevice, mapper: &Option<Arc<dyn IoMapper>>) -> Devic
if dev.id.class == 0x01 && dev.id.subclass == 0x06 {
// Mass storage class
// SATA subclass
if let Some(BAR::Memory(addr, len, _, _)) = dev.bars[5] {
if let Some(BAR::Memory(addr, _len, _, _)) = dev.bars[5] {
info!("Found AHCI dev {:?} BAR5 {:x?}", dev, addr);
/*
let irq = unsafe { enable(dev.loc) };
@ -247,7 +259,7 @@ pub fn init_driver(dev: &PCIDevice, mapper: &Option<Arc<dyn IoMapper>>) -> Devic
Err(DeviceError::NoResources)
}
pub fn detach_driver(loc: &Location) -> bool {
pub fn detach_driver(_loc: &Location) -> bool {
/*
match PCI_DRIVERS.lock().remove(loc) {
Some(driver) => {

View File

@ -2,9 +2,6 @@
//!
//! Reference: <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/input-event-codes.h>
#![allow(dead_code)]
#![allow(unused_parens)]
/// Device properties and quirks
pub mod input_prop {
/// needs a pointer
@ -23,7 +20,7 @@ pub mod input_prop {
pub const INPUT_PROP_ACCELEROMETER: u16 = 0x06;
pub const INPUT_PROP_MAX: u16 = 0x1f;
pub const INPUT_PROP_CNT: u16 = (INPUT_PROP_MAX + 1);
pub const INPUT_PROP_CNT: u16 = INPUT_PROP_MAX + 1;
}
/// Event types
@ -41,7 +38,7 @@ pub mod ev {
pub const EV_PWR: u16 = 0x16;
pub const EV_FF_STATUS: u16 = 0x17;
pub const EV_MAX: u16 = 0x1f;
pub const EV_CNT: u16 = (EV_MAX + 1);
pub const EV_CNT: u16 = EV_MAX + 1;
}
/// Synchronization events
@ -51,7 +48,7 @@ pub mod syn {
pub const SYN_MT_REPORT: u16 = 2;
pub const SYN_DROPPED: u16 = 3;
pub const SYN_MAX: u16 = 0xf;
pub const SYN_CNT: u16 = (SYN_MAX + 1);
pub const SYN_CNT: u16 = SYN_MAX + 1;
}
/// Keys and buttons
@ -661,7 +658,7 @@ pub mod key {
pub const KEY_MIN_INTERESTING: u16 = KEY_MUTE;
pub const KEY_MAX: u16 = 0x2ff;
pub const KEY_CNT: u16 = (KEY_MAX + 1);
pub const KEY_CNT: u16 = KEY_MAX + 1;
}
/// Relative axes
@ -681,7 +678,7 @@ pub mod rel {
pub const REL_WHEEL_HI_RES: u16 = 0x0b;
pub const REL_HWHEEL_HI_RES: u16 = 0x0c;
pub const REL_MAX: u16 = 0x0f;
pub const REL_CNT: u16 = (REL_MAX + 1);
pub const REL_CNT: u16 = REL_MAX + 1;
}
/// Absolute axes
@ -734,7 +731,7 @@ pub mod abs {
pub const ABS_MT_TOOL_Y: u16 = 0x3d;
pub const ABS_MAX: u16 = 0x3f;
pub const ABS_CNT: u16 = (ABS_MAX + 1);
pub const ABS_CNT: u16 = ABS_MAX + 1;
}
/// Switch events
@ -758,7 +755,7 @@ pub mod sw {
pub const SW_MUTE_DEVICE: u16 = 0x0e;
pub const SW_PEN_INSERTED: u16 = 0x0f;
pub const SW_MAX: u16 = 0x0f;
pub const SW_CNT: u16 = (SW_MAX + 1);
pub const SW_CNT: u16 = SW_MAX + 1;
}
/// Misc events
@ -770,7 +767,7 @@ pub mod msc {
pub const MSC_SCAN: u16 = 0x04;
pub const MSC_TIMESTAMP: u16 = 0x05;
pub const MSC_MAX: u16 = 0x07;
pub const MSC_CNT: u16 = (MSC_MAX + 1);
pub const MSC_CNT: u16 = MSC_MAX + 1;
}
/// LEDs
@ -787,7 +784,7 @@ pub mod led {
pub const LED_MAIL: u16 = 0x09;
pub const LED_CHARGING: u16 = 0x0a;
pub const LED_MAX: u16 = 0x0f;
pub const LED_CNT: u16 = (LED_MAX + 1);
pub const LED_CNT: u16 = LED_MAX + 1;
}
/// Autorepeat values
@ -795,7 +792,7 @@ pub mod rep {
pub const REP_DELAY: u16 = 0x00;
pub const REP_PERIOD: u16 = 0x01;
pub const REP_MAX: u16 = 0x01;
pub const REP_CNT: u16 = (REP_MAX + 1);
pub const REP_CNT: u16 = REP_MAX + 1;
}
/// Sounds
@ -804,5 +801,5 @@ pub mod snd {
pub const SND_BELL: u16 = 0x01;
pub const SND_TONE: u16 = 0x02;
pub const SND_MAX: u16 = 0x07;
pub const SND_CNT: u16 = (SND_MAX + 1);
pub const SND_CNT: u16 = SND_MAX + 1;
}

200
drivers/src/irq/gic_400.rs Normal file
View File

@ -0,0 +1,200 @@
use crate::prelude::IrqHandler;
use crate::scheme::{IrqScheme, Scheme};
use crate::utils::IrqManager;
use crate::DeviceResult;
use lock::Mutex;
pub static GICC_SIZE: usize = 0x1000;
pub static GICD_SIZE: usize = 0x1000;
static GICD_CTLR: u32 = 0x000;
static GICD_TYPER: u32 = 0x004;
static GICD_ISENABLER: u32 = 0x100;
static GICD_ICENABLER: u32 = 0x180;
static GICD_IPRIORITY: u32 = 0x400;
static GICD_ITARGETSR: u32 = 0x800;
static GICD_ICFGR: u32 = 0xc00;
static GICC_IAR: u32 = 0x000c;
static GICC_EOIR: u32 = 0x0010;
static GICC_CTLR: u32 = 0x0000;
static GICC_PMR: u32 = 0x0004;
pub struct IntController {
gicc: GicCpuIf,
gicd: GicDistIf,
manager: Mutex<IrqManager<50>>,
}
struct GicDistIf {
pub address: usize,
pub ncpus: u32,
pub nirqs: u32,
}
struct GicCpuIf {
address: usize,
}
impl IntController {
pub fn new(gicc_base: usize, gicd_base: usize) -> Self {
Self {
gicc: GicCpuIf { address: gicc_base },
gicd: GicDistIf {
address: gicd_base,
ncpus: 0,
nirqs: 0,
},
manager: Mutex::new(IrqManager::new(0..50)),
}
}
fn init(&mut self) {
unsafe {
// Disable IRQ Distribution
self.gicd.write(GICD_CTLR, 0);
let typer = self.gicd.read(GICD_TYPER);
self.gicd.ncpus = ((typer & (0x7 << 5)) >> 5) + 1;
self.gicd.nirqs = ((typer & 0x1f) + 1) * 32;
// Set all SPIs to level triggered
for irq in (32..self.gicd.nirqs).step_by(16) {
self.gicd.write(GICD_ICFGR + ((irq / 16) * 4), 0);
}
// Disable all SPIs
for irq in (32..self.gicd.nirqs).step_by(32) {
self.gicd
.write(GICD_ICENABLER + ((irq / 32) * 4), 0xffff_ffff);
}
// Affine all SPIs to CPU0 and set priorities for all IRQs
for irq in 0..self.gicd.nirqs {
if irq > 31 {
let ext_offset = GICD_ITARGETSR + (4 * (irq / 4));
let int_offset = irq % 4;
let mut val = self.gicd.read(ext_offset);
val |= 0b0000_0001 << (8 * int_offset);
self.gicd.write(ext_offset, val);
}
let ext_offset = GICD_IPRIORITY + (4 * (irq / 4));
let int_offset = irq % 4;
let mut val = self.gicd.read(ext_offset);
val |= 0b0000_0000 << (8 * int_offset);
self.gicd.write(ext_offset, val);
}
// Enable CPU0's GIC interface
self.gicc.write(GICC_CTLR, 1);
// Set CPU0's Interrupt Priority Mask
self.gicc.write(GICC_PMR, 0xff);
// Enable IRQ distribution
self.gicd.write(GICD_CTLR, 0x1);
}
}
pub fn irq_enable(&self, irq: u32) {
unsafe {
let offset = GICD_ISENABLER + (4 * (irq / 32));
self.gicd.write(offset, 1 << (irq % 32));
}
}
pub fn irq_disable(&self, irq: u32) {
unsafe {
let offset = GICD_ICENABLER + (4 * (irq / 32));
self.gicd.write(offset, 1 << (irq % 32));
}
}
pub fn irq_eoi(&self, irq: u32) {
unsafe {
self.gicc.write(GICC_EOIR, irq);
}
}
pub fn pending_irq(&self) -> usize {
let iar = unsafe { self.gicc.read(GICC_IAR) as usize };
if iar >= 0x3fe {
usize::MAX
} else {
iar
}
}
}
impl Scheme for IntController {
fn name(&self) -> &str {
"ARM Generic Interrupt Controller"
}
fn handle_irq(&self, irq_num: usize) {
if irq_num != usize::MAX {
self.manager.lock().handle(irq_num).ok();
}
self.irq_eoi(irq_num as u32);
}
}
impl IrqScheme for IntController {
fn is_valid_irq(&self, irq_num: usize) -> bool {
irq_num != usize::MAX
}
fn mask(&self, irq_num: usize) -> DeviceResult {
self.irq_disable(irq_num as u32);
Ok(())
}
fn unmask(&self, irq_num: usize) -> DeviceResult {
self.irq_enable(irq_num as u32);
Ok(())
}
fn register_handler(&self, irq_num: usize, handler: IrqHandler) -> DeviceResult {
self.manager
.lock()
.register_handler(irq_num, handler)
.map_err(|irq_num| {
trace!("Unknown irq_num: {:?}", irq_num);
})
.ok();
Ok(())
}
fn unregister(&self, _irq_num: usize) -> DeviceResult {
todo!()
}
}
impl GicDistIf {
unsafe fn read(&self, reg: u32) -> u32 {
core::ptr::read_volatile((self.address + reg as usize) as *const u32)
}
unsafe fn write(&self, reg: u32, value: u32) {
core::ptr::write_volatile((self.address + reg as usize) as *mut u32, value);
}
}
impl GicCpuIf {
unsafe fn read(&self, reg: u32) -> u32 {
core::ptr::read_volatile((self.address + reg as usize) as *const u32)
}
unsafe fn write(&self, reg: u32, value: u32) {
core::ptr::write_volatile((self.address + reg as usize) as *mut u32, value);
}
}
pub fn init(gicc_base: usize, gicd_base: usize) -> IntController {
let mut controller = IntController::new(gicc_base, gicd_base);
controller.init();
controller
}
pub fn get_irq_num(gicc_base: usize, gicd_base: usize) -> usize {
IntController::new(gicc_base, gicd_base).pending_irq()
}

View File

@ -18,5 +18,7 @@ cfg_if::cfg_if! {
pub mod x86 {
pub use super::x86_apic::Apic;
}
} else if #[cfg(target_arch = "aarch64")] {
pub mod gic_400;
}
}

View File

@ -1,19 +1,25 @@
use core::arch::asm;
use core::ops::Range;
use lock::Mutex;
use crate::io::{Io, Mmio};
use crate::prelude::IrqHandler;
use crate::scheme::{IrqScheme, Scheme};
use crate::{utils::IrqManager, DeviceError, DeviceResult};
use cfg_if::cfg_if;
use lock::Mutex;
const IRQ_RANGE: Range<usize> = 1..1024;
const PLIC_PRIORITY_BASE: usize = 0x0;
const PLIC_ENABLE_BASE: usize = 0x2080;
const PLIC_CONTEXT_BASE: usize = 0x20_1000;
cfg_if! {
if #[cfg(feature = "fu740")] {
const PLIC_ENABLE_BASE: usize = 0x2000;
const PLIC_CONTEXT_BASE: usize = 0x20_0000;
} else {
const PLIC_ENABLE_BASE: usize = 0x2080;
const PLIC_CONTEXT_BASE: usize = 0x20_1000;
}
}
const PLIC_CONTEXT_THRESHOLD: usize = 0x0;
const PLIC_CONTEXT_CLAIM: usize = 0x4 / core::mem::size_of::<u32>();
@ -87,7 +93,7 @@ impl PlicUnlocked {
}
fn init_hart(&mut self) {
self.set_threshold(0);
self.set_threshold(1);
}
}
@ -116,6 +122,7 @@ impl Scheme for Plic {
while let Some(irq_num) = inner.pending_irq() {
if inner.manager.handle(irq_num).is_err() {
warn!("no registered handler for IRQ {}!", irq_num);
inner.set_priority(irq_num, 0);
}
trace!("riscv plic handle irq: {}", irq_num);
inner.eoi(irq_num);

View File

@ -1,6 +1,7 @@
//! Device drivers of zCore.
#![cfg_attr(not(feature = "mock"), no_std)]
#![deny(warnings)]
#![feature(doc_cfg)]
extern crate alloc;
@ -26,6 +27,7 @@ pub mod input;
pub mod io;
pub mod irq;
pub mod net;
pub mod nvme;
pub mod prelude;
pub mod scheme;
pub mod uart;

View File

@ -1,5 +1,5 @@
//! Intel PRO/1000 Network Adapter i.e. e1000 network driver
//! Datasheet: https://www.intel.ca/content/dam/doc/datasheet/82574l-gbe-controller-datasheet.pdf
//! Datasheet: <https://www.intel.ca/content/dam/doc/datasheet/82574l-gbe-controller-datasheet.pdf>
use alloc::collections::BTreeMap;
use alloc::string::String;
@ -12,8 +12,7 @@ use smoltcp::time::Instant;
use smoltcp::wire::*;
use smoltcp::Result;
use super::ProviderImpl;
use super::PAGE_SIZE;
use super::{timer_now_as_micros, ProviderImpl};
use crate::net::get_sockets;
use crate::scheme::{NetScheme, Scheme};
use crate::{DeviceError, DeviceResult};
@ -46,9 +45,7 @@ impl Scheme for E1000Interface {
let data = self.driver.0.lock().handle_interrupt();
if data {
//let timestamp = Instant::from_millis(crate::trap::uptime_msec() as i64);
// Fix me
let timestamp = Instant::from_millis(0);
let timestamp = Instant::from_micros(timer_now_as_micros() as i64);
let sockets = get_sockets();
let mut sockets = sockets.lock();
match self.iface.lock().poll(&mut sockets, timestamp) {
@ -79,14 +76,13 @@ impl NetScheme for E1000Interface {
}
fn poll(&self) -> DeviceResult {
//let timestamp = Instant::from_millis(crate::trap::uptime_msec() as i64);
let timestamp = Instant::from_millis(0);
let timestamp = Instant::from_micros(timer_now_as_micros() as i64);
let sockets = get_sockets();
let mut sockets = sockets.lock();
match self.iface.lock().poll(&mut sockets, timestamp) {
Ok(p) => {
//SOCKET_ACTIVITY.notify_all();
info!("e1000 NetScheme poll: {:?}", p);
trace!("e1000 NetScheme poll: {:?}", p);
Ok(())
}
Err(err) => {
@ -127,7 +123,7 @@ impl phy::Device<'_> for E1000Driver {
self.0
.lock()
.receive()
.map(|vec| (E1000RxToken(vec), E1000TxToken(self.clone())))
.map(|vec_recv| (E1000RxToken(vec_recv), E1000TxToken(self.clone())))
}
fn transmit(&mut self) -> Option<Self::TxToken> {
@ -160,11 +156,11 @@ impl phy::TxToken for E1000TxToken {
where
F: FnOnce(&mut [u8]) -> Result<R>,
{
let mut buffer = [0u8; PAGE_SIZE];
let mut buffer = [0u8; 1536];
let result = f(&mut buffer[..len]);
let mut driver = (self.0).0.lock();
driver.send(&buffer);
driver.send(&buffer[..len]);
result
}
@ -193,8 +189,8 @@ pub fn init(
static mut ROUTES_STORAGE: [Option<(IpCidr, Route)>; 1] = [None; 1];
let mut routes = unsafe { Routes::new(&mut ROUTES_STORAGE[..]) };
routes.add_default_ipv4_route(default_v4_gw).unwrap();
let neighbor_cache = NeighborCache::new(BTreeMap::new());
let iface = InterfaceBuilder::new(net_driver.clone())
.ethernet_addr(ethernet_addr)
.neighbor_cache(neighbor_cache)

View File

@ -49,12 +49,14 @@ impl NetScheme for LoopbackInterface {
}
fn get_mac(&self) -> EthernetAddress {
unimplemented!()
self.iface.lock().ethernet_addr()
}
fn get_ifname(&self) -> String {
unimplemented!()
self.name.clone()
}
fn get_ip_address(&self) -> Vec<IpCidr> {
unimplemented!()
Vec::from(self.iface.lock().ip_addrs())
}
}

View File

@ -1,6 +1,15 @@
//! LAN driver, only for Realtek currently.
#![allow(unused)]
use alloc::{sync::Arc, vec};
use lock::Mutex;
use smoltcp::socket::SocketSet;
pub mod e1000;
pub mod loopback;
pub use isomorphic_drivers::provider::Provider;
pub use loopback::LoopbackInterface;
cfg_if::cfg_if! {
if #[cfg(target_arch = "riscv64")] {
mod realtek;
@ -25,7 +34,6 @@ pub trait Provider {
fn dealloc_dma(vaddr: usize, size: usize);
}
*/
pub use isomorphic_drivers::provider::Provider;
pub struct ProviderImpl;
@ -52,11 +60,16 @@ pub fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
unsafe { drivers_virt_to_phys(vaddr) }
}
pub fn timer_now_as_micros() -> u64 {
unsafe { drivers_timer_now_as_micros() }
}
extern "C" {
fn drivers_dma_alloc(pages: usize) -> PhysAddr;
fn drivers_dma_dealloc(paddr: PhysAddr, pages: usize) -> i32;
fn drivers_phys_to_virt(paddr: PhysAddr) -> VirtAddr;
fn drivers_virt_to_phys(vaddr: VirtAddr) -> PhysAddr;
fn drivers_timer_now_as_micros() -> u64;
}
pub const PAGE_SIZE: usize = 4096;
@ -64,20 +77,12 @@ pub const PAGE_SIZE: usize = 4096;
type VirtAddr = usize;
type PhysAddr = usize;
pub mod loopback;
pub use loopback::LoopbackInterface;
use alloc::sync::Arc;
use alloc::vec;
use lock::Mutex;
use smoltcp::socket::SocketSet;
lazy_static::lazy_static! {
pub static ref SOCKETS: Arc<Mutex<SocketSet<'static>>> =
Arc::new(Mutex::new(SocketSet::new(vec![])));
}
// 注意!这个容易出现死锁
pub fn get_sockets() -> Arc<Mutex<SocketSet<'static>>> {
SOCKETS.clone()
}

View File

@ -97,8 +97,8 @@ pub const LPA_RFAULT: u32 = 0x2000;
pub const LPA_LPACK: u32 = 0x4000;
pub const LPA_NPAGE: u32 = 0x8000;
pub const LPA_DUPLEX: u32 = (LPA_10FULL | LPA_100FULL);
pub const LPA_100: u32 = (LPA_100FULL | LPA_100HALF | LPA_100BASE4);
pub const LPA_DUPLEX: u32 = LPA_10FULL | LPA_100FULL;
pub const LPA_100: u32 = LPA_100FULL | LPA_100HALF | LPA_100BASE4;
/* 1000BASE-T Control register */
pub const ADVERTISE_1000FULL: u32 = 0x0200;

View File

@ -1,8 +1,4 @@
#![allow(unused)]
#![allow(non_camel_case_types)]
use super::Provider;
use super::{phys_to_virt, virt_to_phys};
use super::{phys_to_virt, virt_to_phys, Provider};
#[macro_use]
mod log {

View File

@ -1,7 +1,5 @@
// Supports Realtek RTL8211F on Allwinner D1
extern crate alloc;
use super::mii::*;
use super::utils::*;
@ -10,9 +8,7 @@ use core::mem::size_of;
use super::Provider;
use super::{phys_to_virt, virt_to_phys};
use alloc::boxed::Box;
use alloc::slice;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
@ -135,7 +131,7 @@ const AUTONEG_ENABLE: usize = 1;
const FLOW_OFF: u32 = 0;
const FLOW_RX: u32 = 1;
const FLOW_TX: u32 = 2;
const FLOW_AUTO: u32 = (FLOW_TX | FLOW_RX);
const FLOW_AUTO: u32 = FLOW_TX | FLOW_RX;
const HASH_TABLE_SIZE: u32 = 64;
const PAUSE_TIME: u32 = 0x200;
const GMAC_MAX_UNICAST_ADDRESSES: u32 = 8;
@ -159,7 +155,7 @@ const BMCR_PDOWN: u32 = 0x0800;
#[derive(Debug, Copy, Clone)]
#[repr(packed)]
pub struct dma_desc {
pub struct DmaDesc {
// size: 16
desc0: u32, // Status
desc1: u32, // Buffer Size
@ -167,18 +163,18 @@ pub struct dma_desc {
desc3: u32, // Next Desc
}
pub enum rx_frame_status {
pub enum RxFrameStatus {
/* IPC status */
good_frame = 0,
discard_frame = 1,
csum_none = 2,
llc_snap = 4,
GoodFrame = 0,
DiscardFrame = 1,
CsumNone = 2,
LlcSnap = 4,
}
pub enum tx_dma_irq_status {
tx_hard_error = 1,
tx_hard_error_bump_tc = 2,
handle_tx_rx = 3,
pub enum TxDmaIrqStatus {
TxHardError = 1,
TxHardErrorBumpTc = 2,
HandleTxRx = 3,
}
pub struct RTL8211F<P: Provider> {
@ -190,10 +186,10 @@ pub struct RTL8211F<P: Provider> {
mac: [u8; 6],
recv_buffers: Vec<usize>,
recv_ring: &'static mut [dma_desc],
recv_ring: &'static mut [DmaDesc],
send_buffers: Vec<usize>,
send_ring: &'static mut [dma_desc],
send_ring: &'static mut [DmaDesc],
phy_mode: usize,
@ -215,7 +211,7 @@ where
P: Provider,
{
pub fn new(mac_addr: &[u8; 6]) -> Self {
assert_eq!(size_of::<dma_desc>(), 16);
assert_eq!(size_of::<DmaDesc>(), 16);
let mut mac: [u8; 6] = [0; 6];
let v_addr = mac_addr[0] as u32
@ -249,25 +245,25 @@ where
let (recv_ring_va, recv_ring_pa) = P::alloc_dma(P::PAGE_SIZE);
let send_ring = unsafe {
slice::from_raw_parts_mut(
send_ring_va as *mut dma_desc,
P::PAGE_SIZE / size_of::<dma_desc>(), // 4096/16 = 256 个 dma_desc
send_ring_va as *mut DmaDesc,
P::PAGE_SIZE / size_of::<DmaDesc>(), // 4096/16 = 256 个 dma_desc
)
};
let recv_ring = unsafe {
slice::from_raw_parts_mut(
recv_ring_va as *mut dma_desc,
P::PAGE_SIZE / size_of::<dma_desc>(),
recv_ring_va as *mut DmaDesc,
P::PAGE_SIZE / size_of::<DmaDesc>(),
)
};
send_ring.fill(dma_desc {
send_ring.fill(DmaDesc {
desc0: 0,
desc1: 0,
desc2: 0,
desc3: 0,
});
recv_ring.fill(dma_desc {
recv_ring.fill(DmaDesc {
desc0: 0,
desc1: 0,
desc2: 0,
@ -283,15 +279,15 @@ where
let (buffer_page_va, buffer_page_pa) = P::alloc_dma(P::PAGE_SIZE); // 其实buffer申请2K左右就可以
// desc1.all |= (1 << 24) Chain mode
send_ring[i].desc1 |= (1 << 24);
send_ring[i].desc1 |= 1 << 24;
send_ring[i].desc2 = buffer_page_pa as u32;
if (i + 1) == send_ring.len() {
send_ring[i].desc3 = virt_to_phys(&send_ring[0] as *const dma_desc as usize) as u32;
send_ring[i].desc3 = virt_to_phys(&send_ring[0] as *const DmaDesc as usize) as u32;
} else {
send_ring[i].desc3 =
virt_to_phys(&send_ring[i + 1] as *const dma_desc as usize) as u32;
virt_to_phys(&send_ring[i + 1] as *const DmaDesc as usize) as u32;
}
send_buffers.push(buffer_page_va);
@ -302,21 +298,21 @@ where
for i in 0..recv_ring.len() {
let (buffer_page_va, buffer_page_pa) = P::alloc_dma(P::PAGE_SIZE);
recv_ring[i].desc1 |= (1 << 24);
recv_ring[i].desc1 |= 1 << 24;
//recv_ring[i].desc2 = buffer_page_pa as u32;
if (i + 1) == recv_ring.len() {
recv_ring[i].desc3 = virt_to_phys(&recv_ring[0] as *const dma_desc as usize) as u32;
recv_ring[i].desc3 = virt_to_phys(&recv_ring[0] as *const DmaDesc as usize) as u32;
} else {
recv_ring[i].desc3 =
virt_to_phys(&recv_ring[i + 1] as *const dma_desc as usize) as u32;
virt_to_phys(&recv_ring[i + 1] as *const DmaDesc as usize) as u32;
}
recv_buffers.push(buffer_page_va);
// geth_rx_refill, 实际运行refill时却是priv->rx_clean: 0 ~ 254 ?
// desc_buf_set(&mut recv_ring[i], buffer_page_pa as u32, MAX_BUF_SZ);
recv_ring[i].desc1 &= (!((1 << 11) - 1));
recv_ring[i].desc1 |= (MAX_BUF_SZ & ((1 << 11) - 1));
recv_ring[i].desc1 &= !((1 << 11) - 1);
recv_ring[i].desc1 |= MAX_BUF_SZ & ((1 << 11) - 1);
recv_ring[i].desc2 = buffer_page_pa as u32;
// sync memery, fence指令
@ -392,10 +388,10 @@ where
}
let mii_bmcr_value = self.mdio_read(phyaddr, MII_BMCR);
self.mdio_write(phyaddr, MII_BMCR, (mii_bmcr_value & !BMCR_PDOWN));
self.mdio_write(phyaddr, MII_BMCR, mii_bmcr_value & !BMCR_PDOWN);
info!("Read MII_BMCR: {:#x}", mii_bmcr_value);
self.mac_reset();
self.mac_reset().unwrap();
self.mac_init(1, 1);
@ -408,18 +404,18 @@ where
self.rx_refill();
flush_cache(
virt_to_phys(&self.recv_ring[0] as *const dma_desc as usize) as u64,
(size_of::<dma_desc>() * self.recv_ring.len()) as u64,
virt_to_phys(&self.recv_ring[0] as *const DmaDesc as usize) as u64,
(size_of::<DmaDesc>() * self.recv_ring.len()) as u64,
);
flush_cache(
virt_to_phys(&self.send_ring[0] as *const dma_desc as usize) as u64,
(size_of::<dma_desc>() * self.send_ring.len()) as u64,
virt_to_phys(&self.send_ring[0] as *const DmaDesc as usize) as u64,
(size_of::<DmaDesc>() * self.send_ring.len()) as u64,
);
// phy_start
// 注意地址32位对齐
self.start_rx(virt_to_phys(&self.recv_ring[0] as *const dma_desc as usize) as u32);
self.start_tx(virt_to_phys(&self.send_ring[0] as *const dma_desc as usize) as u32);
self.start_rx(virt_to_phys(&self.recv_ring[0] as *const DmaDesc as usize) as u32);
self.start_tx(virt_to_phys(&self.send_ring[0] as *const DmaDesc as usize) as u32);
// Enable the Rx/Tx
self.mac_enable();
@ -510,7 +506,7 @@ where
/* Setup standard advertisement */
let adv = ADVERTISE_ALL;
self.phy_modify(
let _ = self.phy_modify(
MII_ADVERTISE,
ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
adv,
@ -520,7 +516,7 @@ where
let bmcr = self.mdio_read(phyaddr, MII_BMSR);
if (bmcr & BMSR_ESTATEN) != 0 {
let adv = ADVERTISE_1000FULL;
self.phy_modify(MII_CTRL1000, ADVERTISE_1000FULL | ADVERTISE_1000HALF, adv);
let _ = self.phy_modify(MII_CTRL1000, ADVERTISE_1000FULL | ADVERTISE_1000HALF, adv);
}
self.phy_restart_aneg();
@ -601,7 +597,7 @@ where
//let ctl = BMCR_SPEED1000 | BMCR_FULLDPLX;
// 默认设成 100/FULL
let ctl = BMCR_SPEED100 | BMCR_FULLDPLX;
self.phy_modify(MII_BMCR, !(BMCR_LOOPBACK | BMCR_ISOLATE | BMCR_PDOWN), ctl);
let _ = self.phy_modify(MII_BMCR, !(BMCR_LOOPBACK | BMCR_ISOLATE | BMCR_PDOWN), ctl);
// 开始check网卡link状态, 然后设置speed/duplex
// genphy_read_status()
@ -630,7 +626,7 @@ where
let status = self.mdio_read(phyaddr, MII_BMSR);
link = status & BMSR_LSTATUS;
if (link == BMSR_LSTATUS) {
if link == BMSR_LSTATUS {
info!("Link is up! status: {:#x}", status);
break;
}
@ -653,8 +649,8 @@ where
pub fn can_recv(&mut self) -> bool {
let desc = &self.recv_ring[self.rx_dirty];
invalidate_dcache(
virt_to_phys(desc as *const dma_desc as usize) as u64,
size_of::<dma_desc>() as u64,
virt_to_phys(desc as *const DmaDesc as usize) as u64,
size_of::<DmaDesc>() as u64,
);
desc_get_own(desc) == 0
}
@ -672,8 +668,8 @@ where
let mut desc = &mut self.recv_ring[entry];
invalidate_dcache(
virt_to_phys(desc as *const dma_desc as usize) as u64,
size_of::<dma_desc>() as u64,
virt_to_phys(desc as *const DmaDesc as usize) as u64,
size_of::<DmaDesc>() as u64,
);
if desc_get_own(desc) != 0 {
@ -689,9 +685,9 @@ where
//discard frame when last_desc, err_sum, len_err, mii_err
let status = if (((desc.desc0 >> 8) & 0x1) == 0) || ((desc.desc0 & 0x9008) != 0) {
rx_frame_status::discard_frame as i32
RxFrameStatus::DiscardFrame as i32
} else {
rx_frame_status::good_frame as i32
RxFrameStatus::GoodFrame as i32
};
info!("RX frame size {}, status: {:?}", frame_len, status);
@ -713,7 +709,7 @@ where
info!("========== RX PKT DATA: <<<<<<<<<<");
print_hex_dump(skb, 64);
if status == rx_frame_status::discard_frame as i32 {
if status == RxFrameStatus::DiscardFrame as i32 {
debug!("Get error packet");
// Just need to clear 64 bits header
@ -725,7 +721,7 @@ where
continue;
}
if status != rx_frame_status::llc_snap as i32 {
if status != RxFrameStatus::LlcSnap as i32 {
frame_len -= 4; // ETH_FCS_LEN, 帧出错检验
}
@ -794,7 +790,7 @@ where
pub fn can_send(&mut self) -> bool {
let avail_tx = if self.tx_clean >= (self.tx_dirty + 1) {
(self.tx_clean - (self.tx_dirty + 1))
self.tx_clean - (self.tx_dirty + 1)
} else {
DMA_DESC_TX - ((self.tx_dirty + 1) - self.tx_clean)
};
@ -807,8 +803,8 @@ where
let desc = &self.send_ring[self.tx_dirty];
invalidate_dcache(
virt_to_phys(desc as *const dma_desc as usize) as u64,
size_of::<dma_desc>() as u64,
virt_to_phys(desc as *const DmaDesc as usize) as u64,
size_of::<DmaDesc>() as u64,
);
if desc_get_own(desc) != 0 {
return false;
@ -864,7 +860,7 @@ where
/* Don't set the first's own bit, here */
// (first != desc)
if (first != entry) {
if first != entry {
//self.send_buffers[entry] = 0;
desc_set_own(desc);
}
@ -884,8 +880,8 @@ where
// 再判断下环形缓冲区的空间
flush_cache(
virt_to_phys(&self.send_ring[desc_count] as *const dma_desc as usize) as u64,
size_of::<dma_desc>() as u64,
virt_to_phys(&self.send_ring[desc_count] as *const DmaDesc as usize) as u64,
size_of::<DmaDesc>() as u64,
);
flush_cache(
virt_to_phys(self.send_buffers[desc_count] as usize) as u64,
@ -920,7 +916,7 @@ where
pub fn rx_refill(&mut self) {
while if self.rx_dirty >= (self.rx_clean + 1) {
(self.rx_dirty - (self.rx_clean + 1))
self.rx_dirty - (self.rx_clean + 1)
} else {
DMA_DESC_RX - ((self.rx_clean + 1) - self.rx_dirty)
// (self.rx_dirty - (self.rx_clean + 1)) & (DMA_DESC_RX - 1)
@ -948,8 +944,8 @@ where
desc_buf_set(desc, paddr, MAX_BUF_SZ);
desc_set_own(desc);
flush_cache(
virt_to_phys(&self.recv_ring[entry] as *const dma_desc as usize) as u64,
size_of::<dma_desc>() as u64,
virt_to_phys(&self.recv_ring[entry] as *const DmaDesc as usize) as u64,
size_of::<DmaDesc>() as u64,
);
// sync memery
@ -966,7 +962,7 @@ where
let mut tx_errors: u64 = 0;
while if self.tx_dirty >= self.tx_clean {
(self.tx_dirty - self.tx_clean)
self.tx_dirty - self.tx_clean
} else {
DMA_DESC_TX - (self.tx_clean - self.tx_dirty)
//(self.tx_dirty - self.tx_clean) & (DMA_DESC_TX - 1)
@ -981,8 +977,8 @@ where
let mut desc = &mut self.send_ring[entry];
invalidate_dcache(
virt_to_phys(desc as *const dma_desc as usize) as u64,
size_of::<dma_desc>() as u64,
virt_to_phys(desc as *const DmaDesc as usize) as u64,
size_of::<DmaDesc>() as u64,
);
if desc_get_own(desc) != 0 {
warn!("tx_complete get desc own failed !");
@ -1021,7 +1017,7 @@ where
// Enable and Restart Autonegotiation
pub fn phy_restart_aneg(&mut self) {
// Don't isolate the PHY if we're negotiating
self.phy_modify(MII_BMCR, BMCR_ISOLATE, BMCR_ANENABLE | BMCR_ANRESTART);
let _ = self.phy_modify(MII_BMCR, BMCR_ISOLATE, BMCR_ANENABLE | BMCR_ANRESTART);
info!("Enable and Restart Autonegotiation ...");
// NOLINK --> autoneg_complete --> set speed and duplex --> LINK
@ -1089,10 +1085,10 @@ where
if self.phy_mode == RGMII {
clk_value |= 0x00000004; // set RGMII
} else {
clk_value &= (!0x00000004);
clk_value &= !0x00000004;
}
clk_value &= (!0x00002003); // clear RMII_EN, ETCS
clk_value &= !0x00002003; // clear RMII_EN, ETCS
if (self.phy_mode == RGMII) || (self.phy_mode == GMII) {
clk_value |= 0x00000002; // set ETCS=2
@ -1104,9 +1100,9 @@ where
// Adjust Tx/Rx clock delay
clk_value &= !(0x07 << 10);
clk_value |= ((self.tx_delay & 0x07) << 10);
clk_value |= (self.tx_delay & 0x07) << 10;
clk_value &= !(0x1F << 5);
clk_value |= ((self.rx_delay & 0x1F) << 5);
clk_value |= (self.rx_delay & 0x1F) << 5;
info!("clk enable, write clk value: {:#x}", clk_value);
write_volatile((self.base_phy + EMAC_EPHY_CLK_REG0) as *mut u32, clk_value);
@ -1118,7 +1114,7 @@ where
value &= !(1 << 16); // assert reset
write_volatile((self.base_ccu + EMAC_BGR_REG) as *mut u32, value);
value |= (1 << 16); // deassert reset
value |= 1 << 16; // deassert reset
value |= 1; // enable bus clock
write_volatile((self.base_ccu + EMAC_BGR_REG) as *mut u32, value);
}
@ -1135,16 +1131,16 @@ where
let mut status = 0;
// 不正常的中断
if (intr_status & TX_UNF_INT) != 0 {
status = tx_dma_irq_status::tx_hard_error_bump_tc as i32;
status = TxDmaIrqStatus::TxHardErrorBumpTc as i32;
}
if (intr_status & TX_STOP_INT) != 0 {
status = tx_dma_irq_status::tx_hard_error as i32;
status = TxDmaIrqStatus::TxHardError as i32;
}
/* 正常的 TX/RX NORMAL interrupts */
// (intr_status & (TX_INT | RX_INT | RX_EARLY_INT | TX_UA_INT)) != 0
if (intr_status & (TX_INT | RX_INT)) != 0 {
status = tx_dma_irq_status::handle_tx_rx as i32;
status = TxDmaIrqStatus::HandleTxRx as i32;
}
/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
write_volatile((self.base + GETH_INT_STA) as *mut u32, intr_status & 0x3FFF);
@ -1156,7 +1152,7 @@ where
let status = self.interrupt_status();
// 处理
if status == tx_dma_irq_status::handle_tx_rx as i32 {
if status == TxDmaIrqStatus::HandleTxRx as i32 {
self.int_disable();
// geth_poll()
@ -1166,7 +1162,7 @@ where
if work_done < BUDGET as i32 {
self.int_enable();
}
} else if status == tx_dma_irq_status::tx_hard_error as i32 {
} else if status == TxDmaIrqStatus::TxHardError as i32 {
error!("gmac interrupt handle tx error !");
} else {
info!("gmac interrupt handle status: {}, Do nothing ...", status);
@ -1187,7 +1183,7 @@ where
pub fn desc_tx_close(&mut self, first: usize, end: usize, csum_insert: usize) {
let mut count = first;
let mut desc = (&mut self.send_ring[first]) as *mut dma_desc;
let mut desc = (&mut self.send_ring[first]) as *mut DmaDesc;
//let mut desc = first as *mut dma_desc;
self.send_ring[first].desc1 |= 1 << 29; //First Segment,
@ -1219,8 +1215,8 @@ where
}
pub fn dma_init(&mut self) {
write_volatile((self.base + GETH_BASIC_CTL1) as *mut u32, (8 << 24)); // burst
// 打开网卡中断
write_volatile((self.base + GETH_BASIC_CTL1) as *mut u32, 8 << 24); // burst
// 打开网卡中断
self.int_enable();
}
@ -1249,20 +1245,20 @@ where
/* Initialize the core component */
let mut value: u32 = read_volatile((self.base + GETH_TX_CTL0) as *mut u32);
value |= (1 << 30); /* Jabber Disable */
value |= 1 << 30; /* Jabber Disable */
write_volatile((self.base + GETH_TX_CTL0) as *mut u32, value);
info!("mac init, write TX_CTL0 {:#x}", value);
let mut value: u32 = read_volatile((self.base + GETH_RX_CTL0) as *mut u32);
value |= (1 << 27); /* Enable CRC & IPv4 Header Checksum */
value |= (1 << 28); /* Automatic Pad/CRC Stripping */
value |= (1 << 29); /* Jumbo Frame Enable */
value &= !(1 << 27); /* Disable CRC & IPv4 Header Checksum */
value &= !(1 << 28); /* Keep Pad/CRC */
value |= 1 << 29; /* Jumbo Frame Enable */
write_volatile((self.base + GETH_RX_CTL0) as *mut u32, value);
info!("mac init, write RX_CTL0 {:#x}", value);
write_volatile(
(self.base + GETH_MDIO_ADDR) as *mut u32,
(MDC_CLOCK_RATIO << 20),
MDC_CLOCK_RATIO << 20,
); /* MDC_DIV_RATIO */
/* Set the Rx&Tx mode */
@ -1306,18 +1302,18 @@ where
}
}
/* Forward frames with error and undersized good frame. */
value |= (RX_ERR_FRM | RX_RUNT_FRM);
value |= RX_ERR_FRM | RX_RUNT_FRM;
write_volatile((self.base + GETH_RX_CTL1) as *mut u32, value);
info!("mac init, write RX_CTL1 {:#x}", value);
}
pub fn mac_enable(&mut self) {
let mut value: u32 = read_volatile((self.base + GETH_TX_CTL0) as *mut u32);
value |= (1 << 31);
value |= 1 << 31;
write_volatile((self.base + GETH_TX_CTL0) as *mut u32, value);
let mut value: u32 = read_volatile((self.base + GETH_RX_CTL0) as *mut u32);
value |= (1 << 31);
value |= 1 << 31;
write_volatile((self.base + GETH_RX_CTL0) as *mut u32, value);
}
@ -1433,7 +1429,7 @@ where
1000 => ctrl &= !0x0C,
_ => {
ctrl |= 0x08;
if (speed == 100) {
if speed == 100 {
ctrl |= 0x04;
} else {
ctrl &= !0x04;
@ -1481,7 +1477,7 @@ where
if duplex != 0 {
flow = read_volatile((self.base + GETH_TX_FLOW_CTL) as *mut u32);
flow |= (pause << 4);
flow |= pause << 4;
write_volatile((self.base + GETH_TX_FLOW_CTL) as *mut u32, flow);
}
}
@ -1489,9 +1485,9 @@ where
pub fn mdio_read(&mut self, phyaddr: u32, phyreg: u32) -> u32 {
let mut value: u32 = 0;
value |= ((MDC_CLOCK_RATIO & 0x07) << 20);
value |= (MDC_CLOCK_RATIO & 0x07) << 20;
value |= (((phyaddr << 12) & (0x0001F000)) | ((phyreg << 4) & (0x000007F0)) | MII_BUSY);
value |= ((phyaddr << 12) & (0x0001F000)) | ((phyreg << 4) & (0x000007F0)) | MII_BUSY;
while (read_volatile((self.base + GETH_MDIO_ADDR) as *mut u32) & MII_BUSY) == 1 {}
@ -1507,9 +1503,8 @@ where
}
pub fn mdio_write(&mut self, phyaddr: u32, phyreg: u32, data: u32) {
let mut value: u32 = ((0x07 << 20)
& read_volatile((self.base + GETH_MDIO_ADDR) as *mut u32)
| (MDC_CLOCK_RATIO << 20));
let mut value: u32 = (0x07 << 20) & read_volatile((self.base + GETH_MDIO_ADDR) as *mut u32)
| (MDC_CLOCK_RATIO << 20);
value |= (((phyaddr << 12) & (0x0001F000)) | ((phyreg << 4) & (0x000007F0)))
| MII_WRITE
@ -1524,31 +1519,31 @@ where
}
pub fn mdio_reset(&mut self) {
write_volatile((self.base + GETH_MDIO_ADDR) as *mut u32, (4 << 2));
write_volatile((self.base + GETH_MDIO_ADDR) as *mut u32, 4 << 2);
}
}
pub fn desc_set_own(desc: &mut dma_desc) {
pub fn desc_set_own(desc: &mut DmaDesc) {
desc.desc0 |= 0x80000000;
}
pub fn desc_get_own(desc: &dma_desc) -> u32 {
pub fn desc_get_own(desc: &DmaDesc) -> u32 {
desc.desc0 & 0x80000000
}
pub fn desc_get_tx_ls(desc: &dma_desc) -> u32 {
pub fn desc_get_tx_ls(desc: &DmaDesc) -> u32 {
desc.desc1 & 0x40000000 // Last Segment
}
pub fn desc_buf_set(desc: &mut dma_desc, paddr: u32, size: u32) {
desc.desc1 &= (!((1 << 11) - 1));
desc.desc1 |= (size & ((1 << 11) - 1));
pub fn desc_buf_set(desc: &mut DmaDesc, paddr: u32, size: u32) {
desc.desc1 &= !((1 << 11) - 1);
desc.desc1 |= size & ((1 << 11) - 1);
desc.desc2 = paddr;
}
pub fn desc_init(desc: &mut dma_desc) {
pub fn desc_init(desc: &mut DmaDesc) {
desc.desc1 = 0;
desc.desc1 |= (1 << 24);
desc.desc1 |= 1 << 24;
// 这里用的Buffer Addr不发生改变
//desc.desc2 = 0;

View File

@ -86,6 +86,7 @@ pub fn usdelay(us: u64) {
}
// 毫秒(ms)
#[allow(unused)]
pub fn msdelay(ms: u64) {
usdelay(ms * 1000);
}

View File

@ -1,7 +1,6 @@
use alloc::collections::BTreeMap;
use alloc::string::String;
use alloc::sync::Arc;
// use alloc::vec;
use alloc::vec::Vec;
use lock::Mutex;
@ -12,11 +11,8 @@ use smoltcp::time::Instant;
use smoltcp::wire::*;
use smoltcp::Result;
use super::realtek::rtl8211f;
use super::realtek::rtl8211f::RTL8211F;
use super::ProviderImpl;
use super::PAGE_SIZE;
//use kernel_hal::drivers::{Driver, DeviceType, NetDriver, DRIVERS, NET_DRIVERS, SOCKETS};
use super::realtek::rtl8211f::{self, RTL8211F};
use super::{timer_now_as_micros, ProviderImpl, PAGE_SIZE};
use crate::net::get_sockets;
use crate::scheme::{NetScheme, Scheme};
@ -48,7 +44,7 @@ impl Scheme for RTLxInterface {
let handle_tx_rx = 3;
if status == handle_tx_rx {
let timestamp = Instant::from_millis(0);
let timestamp = Instant::from_micros(timer_now_as_micros() as i64);
let sockets = get_sockets();
let mut sockets = sockets.lock();
@ -81,7 +77,7 @@ impl NetScheme for RTLxInterface {
}
fn poll(&self) -> DeviceResult {
let timestamp = Instant::from_millis(0);
let timestamp = Instant::from_micros(timer_now_as_micros() as i64);
let sockets = get_sockets();
let mut sockets = sockets.lock();
match self.iface.lock().poll(&mut sockets, timestamp) {

View File

@ -0,0 +1,656 @@
use alloc::string::String;
use alloc::vec;
use alloc::vec::Vec;
// use core::mem::size_of;
use alloc::sync::Arc;
use core::ptr::{read_volatile, write_volatile};
use crate::scheme::{BlockScheme, Scheme};
use crate::DeviceResult;
use lock::Mutex;
use super::nvme_queue::*;
pub struct NvmeInterface {
name: String,
admin_queue: Arc<Mutex<NvmeQueue<ProviderImpl>>>,
io_queues: Vec<Arc<Mutex<NvmeQueue<ProviderImpl>>>>,
bar: usize,
irq: usize,
}
impl NvmeInterface {
pub fn new(bar: usize, irq: usize) -> DeviceResult<NvmeInterface> {
let admin_queue = Arc::new(Mutex::new(NvmeQueue::new(0, 0)));
let io_queues = vec![Arc::new(Mutex::new(NvmeQueue::<ProviderImpl>::new(1, 0x8)))];
let mut interface = NvmeInterface {
name: String::from("nvme"),
admin_queue,
io_queues,
bar,
irq,
};
interface.init();
Ok(interface)
}
// config admin queue ,io queue
pub fn init(&mut self) {
self.nvme_configure_admin_queue();
self.nvme_alloc_io_queue();
}
pub fn get_name_irq(&self) -> (String, usize) {
(self.name.clone(), self.irq)
}
}
impl NvmeInterface {
pub fn nvme_configure_admin_queue(&mut self) {
let mut admin_queue = self.admin_queue.lock();
let bar = self.bar;
let dbs = bar + NVME_REG_DBS;
let sq_dma_pa = admin_queue.sq_pa as u32;
let cq_dma_pa = admin_queue.cq_pa as u32;
let data_dma_pa = admin_queue.data_pa as u64;
let aqa_low_16 = 31_u16;
let aqa_high_16 = 31_u16;
let aqa = (aqa_high_16 as u32) << 16 | aqa_low_16 as u32;
let aqa_address = bar + NVME_REG_AQA;
// 将admin queue配置信息写入nvme设备寄存器AQA (admin_queue_attributes)
unsafe {
write_volatile(aqa_address as *mut u32, aqa);
}
// 将admin queue的sq dma物理地址写入nvme设备上的寄存器ASQ
let asq_address = bar + NVME_REG_ASQ;
unsafe {
write_volatile(asq_address as *mut u32, sq_dma_pa);
}
// 将admin queue的cq dma物理地址写入nvme设备上的寄存器ACQ
let acq_address = bar + NVME_REG_ACQ;
unsafe {
write_volatile(acq_address as *mut u32, cq_dma_pa);
}
// enable ctrl
let mut ctrl_config = NVME_CC_ENABLE | NVME_CC_CSS_NVM;
ctrl_config |= 0 << NVME_CC_MPS_SHIFT;
ctrl_config |= NVME_CC_ARB_RR | NVME_CC_SHN_NONE;
ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;
unsafe { write_volatile((bar + NVME_REG_CC) as *mut u32, ctrl_config) }
let _dev_status = unsafe { read_volatile((bar + NVME_REG_CSTS) as *mut u32) };
// warn!("nvme status {}", _dev_status);
// config identify
let mut cmd = NvmeIdentify::new();
cmd.prp1 = data_dma_pa;
cmd.command_id = 0x1018; //random number
cmd.nsid = 1;
let common_cmd = unsafe { core::mem::transmute(cmd) };
admin_queue.sq[0].write(common_cmd);
admin_queue.sq_tail += 1;
let admin_q_db = dbs + admin_queue.db_offset;
unsafe { write_volatile(admin_q_db as *mut u32, 1) }
loop {
let status = admin_queue.cq[0].read();
if status.status != 0 {
// warn!("nvme cq :{:#x?}", status);
unsafe { write_volatile((admin_q_db + 0x4) as *mut u32, 1) }
break;
}
}
}
pub fn nvme_alloc_io_queue(&mut self) {
let mut admin_queue = self.admin_queue.lock();
// let io_queue = self.io_queues[0].lock();
let bar = self.bar;
let dev_dbs = bar + NVME_REG_DBS;
let admin_q_db = dev_dbs;
// nvme_set_queue_count
let mut cmd = NvmeCommonCommand::new();
cmd.opcode = 0x09;
cmd.command_id = 0x2;
cmd.nsid = 1;
cmd.cdw10 = 0x7;
admin_queue.sq[1].write(cmd);
admin_queue.sq_tail += 1;
unsafe { write_volatile(admin_q_db as *mut u32, 2) }
loop {
let status = admin_queue.cq[1].read();
if status.status != 0 {
// warn!("nvme cq :{:#x?}", status);
unsafe { write_volatile((admin_q_db + 0x4) as *mut u32, 2) }
break;
}
}
//nvme create cq
let mut cmd = NvmeCreateCq::new();
cmd.opcode = 0x05;
cmd.command_id = 0x3;
cmd.nsid = 1;
cmd.prp1 = admin_queue.cq_pa as u64;
cmd.cqid = 1;
cmd.qsize = 1023;
cmd.cq_flags = NVME_QUEUE_PHYS_CONTIG | NVME_CQ_IRQ_ENABLED;
// let mut cmd = NvmeCommonCommand::new();
// cmd.opcode = 0x05;
// cmd.command_id = 0x3;
// cmd.nsid = 1;
// cmd.prp1 = admin_queue.cq_pa as u64;
// cmd.cdw10 = 0x3ff0001;
// cmd.cdw11 = 0x3;
let common_cmd = unsafe { core::mem::transmute(cmd) };
admin_queue.sq[2].write(common_cmd);
admin_queue.sq_tail += 1;
unsafe { write_volatile(admin_q_db as *mut u32, 3) }
loop {
let status = admin_queue.cq[2].read();
if status.status != 0 {
// warn!("nvme cq :{:#x?}", status);
unsafe { write_volatile((admin_q_db + 0x4) as *mut u32, 3) }
break;
}
}
// nvme create sq
let mut cmd = NvmeCreateSq::new();
cmd.opcode = 0x01;
cmd.command_id = 0x4;
cmd.nsid = 1;
cmd.prp1 = admin_queue.sq_pa as u64;
cmd.sqid = 1;
cmd.qsize = 1023;
cmd.sq_flags = 0x1;
cmd.cqid = 0x1;
// let mut cmd = NvmeCommonCommand::new();
// cmd.opcode = 0x01;
// cmd.command_id = 0x2018;
// cmd.nsid = 1;
// cmd.prp1 = admin_queue.sq_pa as u64;
// cmd.cdw10 = 0x3ff0001;
// cmd.cdw11 = 0x10001;
let common_cmd = unsafe { core::mem::transmute(cmd) };
// write command to sq
admin_queue.sq[3].write(common_cmd);
admin_queue.sq_tail += 1;
// write doorbell register
unsafe { write_volatile(admin_q_db as *mut u32, 4) }
// wait for command complete
loop {
let status = admin_queue.cq[3].read();
if status.status != 0 {
// warn!("nvme cq :{:#x?}", status);
// write doorbell register
unsafe { write_volatile((admin_q_db + 0x4) as *mut u32, 4) }
break;
}
}
}
}
impl BlockScheme for NvmeInterface {
// 每个NVMe命令中有两个域PRP1和PRP2Host就是通过这两个域告诉SSD数据在内存中的位置或者数据需要写入的地址
// 首先对prp1进行读写如果数据还没完就看数据量是不是在一个page内在的话只需要读写prp2内存地址就可以了数据量大于1个page就需要读出prp list
// 由于只读一块, 小于一页, 所以只需要prp1
// prp1 = dma_addr
// prp2 = 0
// prp设置
// uboot中对应实现 nvme_setup_prps
// linux中对应实现 nvme_pci_setup_prps
// SLBA = start logical block address
// length = 1 = 512B
// 1 SLBA = 512B
fn read_block(&self, block_id: usize, read_buf: &mut [u8]) -> DeviceResult {
let io_queue = self.io_queues[0].lock();
let db_offset = io_queue.db_offset;
let mut admin_queue = self.admin_queue.lock();
let bar = self.bar;
let dbs = bar + NVME_REG_DBS;
// let db_offset = io_queue.db_offset;
// 这里dma addr 就是buffer的地址
let ptr = read_buf.as_mut_ptr();
let addr = virt_to_phys(ptr as usize);
// build nvme read command
let mut cmd = NvmeRWCommand::new_read_command();
cmd.nsid = 1;
cmd.prp1 = addr as u64;
cmd.command_id = 101;
cmd.length = 1;
cmd.slba = block_id as u64;
//transfer to common command
let common_cmd = unsafe { core::mem::transmute(cmd) };
let tail = admin_queue.sq_tail;
// write command to sq
admin_queue.sq[tail].write(common_cmd);
admin_queue.sq_tail += 1;
// write doorbell register
unsafe { write_volatile((dbs + db_offset) as *mut u32, (tail + 1) as u32) }
// wait for command complete
loop {
let status = admin_queue.cq[tail].read();
if status.status != 0 {
// warn!("nvme cq :{:#x?}", status);
// write doorbell
unsafe { write_volatile((dbs + db_offset + 0x4) as *mut u32, (tail + 1) as u32) }
break;
}
}
// admin_queue.cq_head = admin_queue.sq_tail;
Ok(())
}
// prp1 = write_buf physical address
// prp2 = 0
// SLBA = start logical block address
// length = 1 = 512B
fn write_block(&self, block_id: usize, write_buf: &[u8]) -> DeviceResult {
// warn!("write block");
let io_queue = self.io_queues[0].lock();
let db_offset = io_queue.db_offset;
let mut admin_queue = self.admin_queue.lock();
let bar = self.bar;
let dbs = bar + NVME_REG_DBS;
let ptr = write_buf.as_ptr();
let addr = virt_to_phys(ptr as usize);
// build nvme write command
let mut cmd = NvmeRWCommand::new_write_command();
cmd.nsid = 1;
cmd.prp1 = addr as u64;
cmd.length = 1;
cmd.command_id = 100;
cmd.slba = block_id as u64;
// transmute to common command
let common_cmd = unsafe { core::mem::transmute(cmd) };
let mut tail = admin_queue.sq_tail;
if tail > 1023 {
tail = 0;
}
// push command to sq
admin_queue.sq[tail].write(common_cmd);
admin_queue.sq_tail += 1;
// write doorbell register
unsafe { write_volatile((dbs + db_offset) as *mut u32, (tail + 1) as u32) }
// wait for command complete
loop {
let status = admin_queue.cq[tail].read();
if status.status != 0 {
// warn!("nvme cq :{:#x?}", status);
// write doorbell
unsafe { write_volatile((dbs + db_offset + 0x4) as *mut u32, (tail + 1) as u32) }
break;
}
}
Ok(())
}
fn flush(&self) -> DeviceResult {
Ok(())
}
}
impl Scheme for NvmeInterface {
fn name(&self) -> &str {
"nvme"
}
fn handle_irq(&self, irq: usize) {
warn!("nvme device irq {}", irq);
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Default)]
//64B
pub struct NvmeCommonCommand {
opcode: u8,
flags: u8,
command_id: u16,
nsid: u32,
cdw2: [u32; 2],
metadata: u64,
prp1: u64,
prp2: u64,
cdw10: u32,
cdw11: u32,
cdw12: u32,
cdw13: u32,
cdw14: u32,
cdw15: u32,
}
impl NvmeCommonCommand {
pub fn new() -> Self {
Self {
opcode: 0,
flags: 0,
command_id: 0,
nsid: 0,
cdw2: [0; 2],
metadata: 0,
prp1: 0,
prp2: 0,
cdw10: 0,
cdw11: 0,
cdw12: 0,
cdw13: 0,
cdw14: 0,
cdw15: 0,
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Default)]
pub struct NvmeIdentify {
opcode: u8,
flags: u8,
command_id: u16,
nsid: u32,
rsvd2: [u64; 2],
prp1: u64,
prp2: u64,
cns: u8,
rsvd3: u8,
ctrlid: u16,
rsvd11: [u8; 3],
csi: u8,
rsvd12: [u32; 4],
}
impl NvmeIdentify {
pub fn new() -> Self {
Self {
opcode: 0x06,
flags: 0,
command_id: 0x1,
nsid: 1,
rsvd2: [0; 2],
prp1: 0,
prp2: 0,
cns: 1,
rsvd3: 0,
ctrlid: 0,
rsvd11: [0; 3],
csi: 0,
rsvd12: [0; 4],
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Default)]
pub struct NvmeCreateCq {
pub opcode: u8,
pub flags: u8,
pub command_id: u16,
pub nsid: u32,
pub rsvd1: [u32; 4],
pub prp1: u64,
pub rsvd8: u64,
pub cqid: u16,
pub qsize: u16,
pub cq_flags: u16,
pub irq_vector: u16,
pub rsvd12: [u32; 4],
}
impl NvmeCreateCq {
fn new() -> Self {
Self {
opcode: 0x05,
flags: 0,
command_id: 0,
nsid: 0,
rsvd1: [0; 4],
prp1: 0,
rsvd8: 0,
cqid: 0,
qsize: 0,
cq_flags: 0,
irq_vector: 0,
rsvd12: [0; 4],
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Default)]
pub struct NvmeCreateSq {
pub opcode: u8,
pub flags: u8,
pub command_id: u16,
pub nsid: u32,
pub rsvd1: [u32; 4],
pub prp1: u64,
pub rsvd8: u64,
pub sqid: u16,
pub qsize: u16,
pub sq_flags: u16,
pub cqid: u16,
pub rsvd12: [u32; 4],
}
impl NvmeCreateSq {
fn new() -> Self {
Self {
opcode: 0x01,
flags: 0,
command_id: 0,
nsid: 0,
rsvd1: [0; 4],
prp1: 0,
rsvd8: 0,
sqid: 0,
qsize: 0,
sq_flags: 0,
cqid: 0,
rsvd12: [0; 4],
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
pub struct NvmeRWCommand {
pub opcode: u8,
pub flags: u8,
pub command_id: u16,
pub nsid: u32,
pub rsvd2: u64,
pub metadata: u64,
pub prp1: u64,
pub prp2: u64,
pub slba: u64,
pub length: u16,
pub control: u16,
pub dsmgmt: u32,
pub reftag: u32,
pub apptag: u16,
pub appmask: u16,
}
impl NvmeRWCommand {
pub fn new_write_command() -> Self {
Self {
opcode: 0x01,
flags: 0,
command_id: 0,
nsid: 0,
rsvd2: 0,
metadata: 0,
prp1: 0,
prp2: 0,
slba: 0,
length: 0,
control: 0,
dsmgmt: 0,
reftag: 0,
apptag: 0,
appmask: 0,
}
}
pub fn new_read_command() -> Self {
Self {
opcode: 0x02,
flags: 0,
command_id: 0,
nsid: 0,
rsvd2: 0,
metadata: 0,
prp1: 0,
prp2: 0,
slba: 0,
length: 0,
control: 0,
dsmgmt: 0,
reftag: 0,
apptag: 0,
appmask: 0,
}
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Default)]
pub struct NvmeCompletion {
pub result: u64,
// pub rsvd: u32,
pub sq_head: u16,
pub sq_id: u16,
pub command_id: u16,
pub status: u16,
}
// NvmeRegister
pub const NVME_REG_CAP: usize = 0x0000; /* Controller Capabilities */
pub const NVME_REG_VS: usize = 0x0008; /* Version */
pub const NVME_REG_INTMS: usize = 0x000c; /* Interrupt Mask Set */
pub const NVME_REG_INTMC: usize = 0x0010; /* Interrupt Mask Clear */
pub const NVME_REG_CC: usize = 0x0014; /* Controller Configuration */
pub const NVME_REG_CSTS: usize = 0x001c; /* Controller Status */
pub const NVME_REG_NSSR: usize = 0x0020; /* NVM Subsystem Reset */
pub const NVME_REG_AQA: usize = 0x0024; /* Admin Queue Attributes */
pub const NVME_REG_ASQ: usize = 0x0028; /* Admin SQ Base Address */
pub const NVME_REG_ACQ: usize = 0x0030; /* Admin CQ Base Address */
pub const NVME_REG_CMBLOC: usize = 0x0038; /* Controller Memory Buffer Location */
pub const NVME_REG_CMBSZ: usize = 0x003c; /* Controller Memory Buffer Size */
pub const NVME_REG_BPINFO: usize = 0x0040; /* Boot Partition Information */
pub const NVME_REG_BPRSEL: usize = 0x0044; /* Boot Partition Read Select */
pub const NVME_REG_BPMBL: usize = 0x0048; /* Boot Partition Memory Buffer
* Location
*/
pub const NVME_REG_CMBMSC: usize = 0x0050; /* Controller Memory Buffer Memory
* Space Control
*/
pub const NVME_REG_CRTO: usize = 0x0068; /* Controller Ready Timeouts */
pub const NVME_REG_PMRCAP: usize = 0x0e00; /* Persistent Memory Capabilities */
pub const NVME_REG_PMRCTL: usize = 0x0e04; /* Persistent Memory Region Control */
pub const NVME_REG_PMRSTS: usize = 0x0e08; /* Persistent Memory Region Status */
pub const NVME_REG_PMREBS: usize = 0x0e0c; /* Persistent Memory Region Elasticity
* Buffer Size
*/
pub const NVME_REG_PMRSWTP: usize = 0x0e10; /* Persistent Memory Region Sustained
* Write Throughput
*/
pub const NVME_REG_DBS: usize = 0x1000; /* SQ 0 Tail Doorbell */
// NVME CONST
pub const NVME_CC_ENABLE: u32 = 1 << 0;
pub const NVME_CC_CSS_NVM: u32 = 0 << 4;
pub const NVME_CC_MPS_SHIFT: u32 = 7;
pub const NVME_CC_ARB_RR: u32 = 0 << 11;
pub const NVME_CC_ARB_WRRU: u32 = 1 << 11;
pub const NVME_CC_ARB_VS: u32 = 7 << 11;
pub const NVME_CC_SHN_NONE: u32 = 0 << 14;
pub const NVME_CC_SHN_NORMAL: u32 = 1 << 14;
pub const NVME_CC_SHN_ABRUPT: u32 = 2 << 14;
pub const NVME_CC_IOSQES: u32 = 6 << 16;
pub const NVME_CC_IOCQES: u32 = 4 << 20;
pub const NVME_CSTS_RDY: u32 = 1 << 0;
pub const NVME_CSTS_CFS: u32 = 1 << 1;
pub const NVME_CSTS_SHST_NORMAL: u32 = 0 << 2;
pub const NVME_CSTS_SHST_OCCUR: u32 = 1 << 2;
pub const NVME_CSTS_SHST_CMPLT: u32 = 2 << 2;
pub const NVME_QUEUE_PHYS_CONTIG: u16 = 1 << 0;
pub const NVME_CQ_IRQ_ENABLED: u16 = 1 << 1;
pub const NVME_SQ_PRIO_URGENT: u16 = 0 << 1;
pub const NVME_SQ_PRIO_HIGH: u16 = 1 << 1;
pub const NVME_SQ_PRIO_MEDIUM: u16 = 2 << 1;
pub const NVME_SQ_PRIO_LOW: u16 = 3 << 1;
pub const NVME_FEAT_ARBITRATION: u32 = 0x01;
pub const NVME_FEAT_POWER_MGMT: u32 = 0x02;
pub const NVME_FEAT_LBA_RANGE: u32 = 0x03;
pub const NVME_FEAT_TEMP_THRESH: u32 = 0x04;
pub const NVME_FEAT_ERR_RECOVERY: u32 = 0x05;
pub const NVME_FEAT_VOLATILE_WC: u32 = 0x06;
pub const NVME_FEAT_NUM_QUEUES: u32 = 0x07;
pub const NVME_FEAT_IRQ_COALESCE: u32 = 0x08;
pub const NVME_FEAT_IRQ_CONFIG: u32 = 0x09;
pub const NVME_FEAT_WRITE_ATOMIC: u32 = 0x0a;
pub const NVME_FEAT_ASYNC_EVENT: u32 = 0x0b;
pub const NVME_FEAT_SW_PROGRESS: u32 = 0x0c;

5
drivers/src/nvme/mod.rs Normal file
View File

@ -0,0 +1,5 @@
pub mod interface;
pub mod nvme_queue;
pub use interface::*;
pub use nvme_queue::*;

View File

@ -0,0 +1,120 @@
use alloc::slice;
use core::marker::PhantomData;
use volatile::Volatile;
use super::NvmeCommonCommand;
use super::NvmeCompletion;
#[derive(Debug)]
pub struct NvmeQueue<P: Provider> {
provider: PhantomData<P>,
pub sq: &'static mut [Volatile<NvmeCommonCommand>],
pub cq: &'static mut [Volatile<NvmeCompletion>],
pub db_offset: usize,
pub qid: usize,
pub cq_head: usize,
pub cq_phase: usize,
pub sq_tail: usize,
pub last_sq_tail: usize,
pub sq_pa: usize,
pub cq_pa: usize,
pub data_pa: usize,
}
impl<P: Provider> NvmeQueue<P> {
pub fn new(qid: usize, db_offset: usize) -> Self {
let (data_va, data_pa) = P::alloc_dma(P::PAGE_SIZE * 2);
let (sq_va, sq_pa) = P::alloc_dma(P::PAGE_SIZE * 2);
let (cq_va, cq_pa) = P::alloc_dma(P::PAGE_SIZE * 2);
trace!("data_va: {:x}, data_pa: {:x}", data_va, data_pa);
let submit_queue = unsafe {
slice::from_raw_parts_mut(sq_va as *mut Volatile<NvmeCommonCommand>, PAGE_SIZE)
};
let complete_queue =
unsafe { slice::from_raw_parts_mut(cq_va as *mut Volatile<NvmeCompletion>, PAGE_SIZE) };
NvmeQueue {
provider: PhantomData,
sq: submit_queue,
cq: complete_queue,
db_offset,
qid,
cq_head: 0,
cq_phase: 0,
sq_tail: 0,
last_sq_tail: 0,
sq_pa,
cq_pa,
data_pa,
}
}
}
/// External functions that drivers must use
pub trait Provider {
/// Page size (usually 4K)
const PAGE_SIZE: usize;
/// Allocate consequent physical memory for DMA.
/// Return (`virtual address`, `physical address`).
/// The address is page aligned.
fn alloc_dma(size: usize) -> (usize, usize);
/// Deallocate DMA
fn dealloc_dma(vaddr: usize, size: usize);
}
pub struct ProviderImpl;
impl Provider for ProviderImpl {
const PAGE_SIZE: usize = PAGE_SIZE;
fn alloc_dma(size: usize) -> (usize, usize) {
let paddr = unsafe { drivers_dma_alloc(size / PAGE_SIZE) };
let vaddr = phys_to_virt(paddr);
(vaddr, paddr)
}
fn dealloc_dma(vaddr: usize, size: usize) {
let paddr = virt_to_phys(vaddr);
unsafe { drivers_dma_dealloc(paddr, size / PAGE_SIZE) };
}
}
pub fn phys_to_virt(paddr: PhysAddr) -> VirtAddr {
unsafe { drivers_phys_to_virt(paddr) }
}
pub fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
unsafe { drivers_virt_to_phys(vaddr) }
}
pub fn timer_now_as_micros() -> u64 {
unsafe { drivers_timer_now_as_micros() }
}
extern "C" {
fn drivers_dma_alloc(pages: usize) -> PhysAddr;
fn drivers_dma_dealloc(paddr: PhysAddr, pages: usize) -> i32;
fn drivers_phys_to_virt(paddr: PhysAddr) -> VirtAddr;
fn drivers_virt_to_phys(vaddr: VirtAddr) -> PhysAddr;
fn drivers_timer_now_as_micros() -> u64;
}
pub const PAGE_SIZE: usize = 4096;
type VirtAddr = usize;
type PhysAddr = usize;

View File

@ -8,3 +8,21 @@ pub use uart_16550::Uart16550Mmio;
#[cfg(target_arch = "x86_64")]
pub use uart_16550::Uart16550Pmio;
#[cfg(target_arch = "aarch64")]
mod uart_pl011;
#[cfg(target_arch = "aarch64")]
pub use uart_pl011::Pl011Uart;
#[cfg(feature = "allwinner")]
mod uart_allwinner;
#[cfg(feature = "allwinner")]
pub use uart_allwinner::UartAllwinner;
#[cfg(feature = "fu740")]
mod uart_u740;
#[cfg(feature = "fu740")]
pub use uart_u740::UartU740Mmio;

View File

@ -0,0 +1,132 @@
use crate::{
scheme::{impl_event_scheme, Scheme, UartScheme},
utils::EventListener,
DeviceResult, VirtAddr,
};
use d1_pac::uart;
use lock::Mutex;
pub struct UartAllwinner {
inner: Mutex<Inner>,
listener: EventListener,
}
impl_event_scheme!(UartAllwinner);
impl UartAllwinner {
pub fn new(base: VirtAddr) -> Self {
let inner = Inner(base);
inner.init();
Self {
inner: Mutex::new(inner),
listener: EventListener::new(),
}
}
}
impl Scheme for UartAllwinner {
#[inline]
fn name(&self) -> &str {
"uart-allwinner"
}
#[inline]
fn handle_irq(&self, _irq_num: usize) {
self.listener.trigger(());
}
}
impl UartScheme for UartAllwinner {
#[inline]
fn try_recv(&self) -> DeviceResult<Option<u8>> {
self.inner.lock().try_recv()
}
#[inline]
fn send(&self, ch: u8) -> DeviceResult {
self.inner.lock().send(ch)
}
#[inline]
fn write_str(&self, s: &str) -> DeviceResult {
self.inner.lock().write_str(s)
}
}
struct Inner(VirtAddr);
impl Inner {
/// 初始化串口控制器
/// BAUD 115200
/// FIFO ON
fn init(&self) {
let block = self.block();
// disable interrupts
block.ier().reset();
// enable fifo
block.fcr().write(|w| w.fifoe().set_bit());
{
block.halt.write(|w| w.halt_tx().set_bit());
block.lcr.write(|w| w.dlab().set_bit());
// 13 for 115200
block.dll().write(|w| w.dll().variant(13));
block.dlh().write(|w| w.dlh().variant(0));
// no break | parity disabled | 1 stop bit | 8 data bits
block.lcr.write(|w| w.dls().eight());
#[rustfmt::skip]
block.halt.write(|w| w
.change_update().set_bit()
.chcfg_at_busy().set_bit());
}
// reset fifo
#[rustfmt::skip]
block.fcr().write(|w| w
.xfifor().set_bit()
.rfifor().set_bit()
.fifoe() .set_bit()
);
// uart mode
block.mcr.reset();
// enable interrupts
block.ier().write(|w| w.erbfi().set_bit());
}
/// 接收
fn try_recv(&self) -> DeviceResult<Option<u8>> {
let block = self.block();
if block.lsr.read().dr().bit_is_set() {
Ok(Some(block.rbr().read().bits() as _))
} else {
Ok(None)
}
}
/// 发送
fn send(&self, ch: u8) -> DeviceResult {
let block = self.block();
// 等待 FIFO 空位
while block.usr.read().tfnf().is_full() {
core::hint::spin_loop();
}
block.thr().write(|w| w.thr().variant(ch));
Ok(())
}
fn write_str(&mut self, s: &str) -> DeviceResult {
for b in s.bytes() {
match b {
b'\n' => {
self.send(b'\r')?;
self.send(b'\n')?;
}
_ => self.send(b)?,
}
}
Ok(())
}
#[inline]
fn block(&self) -> &uart::RegisterBlock {
unsafe { &*(self.0 as *const _) }
}
}

View File

@ -0,0 +1,185 @@
//! PL011 UART.
use crate::scheme::{impl_event_scheme, Scheme, UartScheme};
use crate::utils::EventListener;
use crate::DeviceResult;
use bitflags::*;
use core::ptr;
bitflags! {
/// UARTFR
struct UartFrFlags: u16 {
const TXFE = 1 << 7;
const RXFF = 1 << 6;
const TXFF = 1 << 5;
const RXFE = 1 << 4;
const BUSY = 1 << 3;
}
}
bitflags! {
/// UARTCR
struct UartCrFlags: u16 {
const RXE = 1 << 9;
const TXE = 1 << 8;
const UARTEN = 1 << 0;
}
}
bitflags! {
// UARTIMSC
struct UartImscFlags: u16 {
const RTIM = 1 << 6;
const TXIM = 1 << 5;
const RXIM = 1 << 4;
}
}
bitflags! {
// UARTICR
struct UartIcrFlags: u16 {
const RTIC = 1 << 6;
const TXIC = 1 << 5;
const RXIC = 1 << 4;
}
}
bitflags! {
//UARTMIS
struct UartMisFlags: u16 {
const TXMIS = 1 << 5;
const RXMIS = 1 << 4;
}
}
bitflags! {
//UARTLCR_H
struct UartLcrhFlags: u16 {
const FEN = 1 << 4;
}
}
#[allow(dead_code)]
pub struct Pl011Uart {
inner: Pl011Inner,
listener: EventListener,
}
impl Pl011Uart {
pub fn new(base: usize) -> Self {
Self {
inner: {
let inner = Pl011Inner::new(base);
inner.init();
inner
},
listener: EventListener::new(),
}
}
fn getchar(&self) -> Option<u8> {
self.inner.getchar()
}
fn putchar(&self, data: u8) {
self.inner.putchar(data);
}
}
struct Pl011Inner {
base: usize,
data_reg: u8,
flag_reg: u8,
line_ctrl_reg: u8,
ctrl_reg: u8,
intr_mask_setclr_reg: u8,
intr_clr_reg: u8,
}
impl Pl011Inner {
pub fn new(base: usize) -> Pl011Inner {
Pl011Inner {
base,
data_reg: 0x00,
flag_reg: 0x18,
line_ctrl_reg: 0x2c,
ctrl_reg: 0x30,
intr_mask_setclr_reg: 0x38,
intr_clr_reg: 0x44,
}
}
fn read_reg(&self, register: u8) -> u16 {
unsafe { ptr::read_volatile((self.base + register as usize) as *mut u16) }
}
fn write_reg(&self, register: u8, data: u16) {
unsafe {
ptr::write_volatile((self.base + register as usize) as *mut u16, data);
}
}
fn init(&self) {
// Enable RX, TX, UART
let flags = UartCrFlags::RXE | UartCrFlags::TXE | UartCrFlags::UARTEN;
self.write_reg(self.ctrl_reg, flags.bits());
// Disable FIFOs (use character mode instead)
let mut flags = UartLcrhFlags::from_bits_truncate(self.read_reg(self.line_ctrl_reg));
flags.remove(UartLcrhFlags::FEN);
self.write_reg(self.line_ctrl_reg, flags.bits());
// Enable IRQs
let flags = UartImscFlags::RXIM;
self.write_reg(self.intr_mask_setclr_reg, flags.bits);
// Clear pending interrupts
self.write_reg(self.intr_clr_reg, 0x7ff);
}
fn line_sts(&self) -> UartFrFlags {
UartFrFlags::from_bits_truncate(self.read_reg(self.flag_reg))
}
fn getchar(&self) -> Option<u8> {
if self.line_sts().contains(UartFrFlags::RXFF) {
Some(self.read_reg(self.data_reg) as u8)
} else {
None
}
}
fn putchar(&self, data: u8) {
while !self.line_sts().contains(UartFrFlags::TXFE) {}
self.write_reg(self.data_reg, data as u16);
}
}
impl Scheme for Pl011Uart {
fn name(&self) -> &str {
"Pl011 ARM series uart"
}
fn handle_irq(&self, _irq_num: usize) {
self.listener.trigger(())
}
}
impl_event_scheme!(Pl011Uart);
impl UartScheme for Pl011Uart {
fn try_recv(&self) -> DeviceResult<Option<u8>> {
Ok(self.getchar())
}
fn send(&self, ch: u8) -> DeviceResult {
self.putchar(ch);
Ok(())
}
fn write_str(&self, s: &str) -> DeviceResult {
for c in s.bytes() {
self.send(c)?;
}
Ok(())
}
}

View File

@ -0,0 +1,214 @@
use bitflags::bitflags;
use core::convert::TryInto;
use core::ops::{BitAnd, BitOr, Not};
use lock::Mutex;
use crate::io::{Io, Mmio, ReadOnly};
use crate::scheme::{impl_event_scheme, Scheme, UartScheme};
use crate::utils::EventListener;
use crate::DeviceResult;
bitflags! {
/// TXDATA fields
struct TXDATAFlags: u32 {
const TXFULL = 1 << 31;
}
}
bitflags! {
/// RXDATA fields
struct RXDATAFlags: u32 {
const RXEMPTY = 1 << 31;
}
}
bitflags! {
/// TXCTRL fields
struct TXCTRLFlags: u32 {
const TXEN = 1;
const NSTOP = 1 << 1;
}
}
bitflags! {
/// RXCTRL fields
struct RXCTRLFlags: u32 {
const RXEN = 1;
}
}
bitflags! {
/// IE fields
struct IEFlags: u32 {
const TXWM = 1;
const RXWM = 1 << 1;
}
}
#[repr(C)]
struct UartU740Inner<T: Io> {
/// Transmit data register
tx_data: T,
/// Receive data register
rx_data: ReadOnly<T>,
/// Transmit control register
tx_ctrl: T,
/// Receive control register
rx_ctrl: T,
/// UART interrupt enable
ie: T,
/// UART interrupt pending
ip: ReadOnly<T>,
/// Baud rate divisor
div: T,
}
impl<T: Io> UartU740Inner<T>
where
T::Value: From<u8> + TryInto<u8> + From<u32> + TryInto<u32>,
{
fn init(&mut self) {
// Enable transmit and set 1 stop bit and interrupt watermark
self.tx_ctrl
.write((self.tx_ctrl.read().try_into().unwrap_or(0) | TXCTRLFlags::TXEN.bits()).into());
// Enable receive and set interrupt watermark
self.rx_ctrl
.write((self.rx_ctrl.read().try_into().unwrap_or(0) | RXCTRLFlags::RXEN.bits()).into());
// Enable TX & RX interrupt
self.ie.write(
(self.ie.read().try_into().unwrap_or(0) | IEFlags::TXWM.bits() | IEFlags::RXWM.bits())
.into(),
);
}
fn try_recv(&mut self) -> DeviceResult<Option<u8>> {
let ch = self.rx_data.read();
if RXDATAFlags::from_bits_truncate(ch.try_into().unwrap_or(0))
.contains(RXDATAFlags::RXEMPTY)
{
Ok(None)
} else {
Ok(Some(ch.try_into().unwrap_or(0) & 0xFF))
}
}
fn send(&mut self, ch: u8) -> DeviceResult {
let mut status;
loop {
status = self.tx_data.read();
if !TXDATAFlags::from_bits_truncate(status.try_into().unwrap_or(0))
.contains(TXDATAFlags::TXFULL)
{
break;
}
}
self.tx_data.write(ch.into());
Ok(())
}
fn write_str(&mut self, s: &str) -> DeviceResult {
for b in s.bytes() {
match b {
b'\n' => {
self.send(b'\r')?;
self.send(b'\n')?;
}
_ => {
self.send(b)?;
}
}
}
Ok(())
}
}
/// MMIO driver for UART 16550
pub struct UartU740Mmio<V: 'static>
where
V: Copy + BitAnd<Output = V> + BitOr<Output = V> + Not<Output = V>,
{
inner: Mutex<&'static mut UartU740Inner<Mmio<V>>>,
listener: EventListener,
}
impl_event_scheme!(UartU740Mmio<V>
where
V: Copy
+ BitAnd<Output = V>
+ BitOr<Output = V>
+ Not<Output = V>
+ From<u8>
+ TryInto<u8>
+ Send
);
impl<V> Scheme for UartU740Mmio<V>
where
V: Copy + BitAnd<Output = V> + BitOr<Output = V> + Not<Output = V> + Send,
{
fn name(&self) -> &str {
"uart-u740-mmio"
}
fn handle_irq(&self, _irq_num: usize) {
self.listener.trigger(());
}
}
impl<V> UartScheme for UartU740Mmio<V>
where
V: Copy
+ BitAnd<Output = V>
+ BitOr<Output = V>
+ Not<Output = V>
+ From<u8>
+ TryInto<u8>
+ From<u32>
+ TryInto<u32>
+ Send,
{
fn try_recv(&self) -> DeviceResult<Option<u8>> {
self.inner.lock().try_recv()
}
fn send(&self, ch: u8) -> DeviceResult {
self.inner.lock().send(ch)
}
fn write_str(&self, s: &str) -> DeviceResult {
self.inner.lock().write_str(s)
}
}
impl<V> UartU740Mmio<V>
where
V: Copy
+ BitAnd<Output = V>
+ BitOr<Output = V>
+ Not<Output = V>
+ From<u8>
+ TryInto<u8>
+ From<u32>
+ TryInto<u32>
+ Send,
{
unsafe fn new_common(base: usize) -> Self {
let uart: &mut UartU740Inner<Mmio<V>> = Mmio::<V>::from_base_as(base);
uart.init();
Self {
inner: Mutex::new(uart),
listener: EventListener::new(),
}
}
}
impl UartU740Mmio<u32> {
/// # Safety
///
/// This function is unsafe because `base_addr` may be an arbitrary address.
pub unsafe fn new(base: usize) -> Self {
Self::new_common(base)
}
}

View File

@ -31,6 +31,7 @@ pub struct InheritProps {
impl Devicetree {
/// Load the device tree blob from the given virtual address.
pub fn from(dtb_base_vaddr: VirtAddr) -> DeviceResult<Self> {
info!("Loading device tree blob from {:#x}", dtb_base_vaddr);
match unsafe { DeviceTreeInner::load_from_raw_pointer(dtb_base_vaddr as *const _) } {
Ok(dt) => Ok(Self(dt)),
Err(err) => {

View File

@ -1,9 +1,6 @@
#![allow(dead_code)]
use core::ops::Range;
use super::IdAllocator;
use crate::{prelude::IrqHandler, DeviceError, DeviceResult};
use core::ops::Range;
pub struct IrqManager<const IRQ_COUNT: usize> {
irq_range: Range<usize>,
@ -23,6 +20,7 @@ impl<const IRQ_COUNT: usize> IrqManager<IRQ_COUNT> {
}
}
#[allow(unused)]
pub fn alloc_block(&mut self, count: usize) -> DeviceResult<usize> {
info!("IRQ alloc_block {}", count);
debug_assert!(count.is_power_of_two());
@ -30,6 +28,7 @@ impl<const IRQ_COUNT: usize> IrqManager<IRQ_COUNT> {
self.allocator.alloc_contiguous(count, align_log2 as _)
}
#[allow(unused)]
pub fn free_block(&mut self, start: usize, count: usize) -> DeviceResult {
info!("IRQ free_block {:#x?}", start..start + count);
self.allocator.free(start, count)
@ -52,6 +51,7 @@ impl<const IRQ_COUNT: usize> IrqManager<IRQ_COUNT> {
Ok(irq_num)
}
#[cfg(not(target_arch = "aarch64"))]
pub fn unregister_handler(&mut self, irq_num: usize) -> DeviceResult {
info!("IRQ unregister handler {}", irq_num);
if !self.allocator.is_alloced(irq_num) {
@ -63,6 +63,7 @@ impl<const IRQ_COUNT: usize> IrqManager<IRQ_COUNT> {
}
}
#[allow(unused)]
pub fn overwrite_handler(&mut self, irq_num: usize, handler: IrqHandler) -> DeviceResult {
info!("IRQ overwrite handle {}", irq_num);
if !self.allocator.is_alloced(irq_num) {

View File

@ -1,7 +1,5 @@
//! Event handler and device tree.
#![allow(unused_imports)]
mod event_listener;
mod id_allocator;
mod irq_manager;

View File

@ -9,6 +9,7 @@ pub use blk::VirtIoBlk;
pub use console::VirtIoConsole;
pub use gpu::VirtIoGpu;
pub use input::VirtIoInput;
pub use virtio_drivers::VirtIOHeader;
use crate::DeviceError;
use core::convert::From;

View File

@ -2,8 +2,8 @@
name = "kernel-hal"
version = "0.1.0"
authors = [
"Runji Wang <wangrunji0408@163.com>",
"Yuekai Jia <equation618@gmail.com>",
"Runji Wang <wangrunji0408@163.com>",
"Yuekai Jia <equation618@gmail.com>",
]
edition = "2018"
description = "Kernel HAL interface definations."
@ -12,17 +12,28 @@ description = "Kernel HAL interface definations."
[features]
default = ["libos"]
smp = []
libos = [
"nix",
"tempfile",
"async-std",
"bitmap-allocator",
"zcore-drivers/mock",
"nix",
"tempfile",
"async-std",
"bitmap-allocator",
"zcore-drivers/mock",
]
graphic = ["zcore-drivers/graphic"]
# TODO
loopback = ["zcore-drivers/loopback", "no-pci"]
loopback = []
# Enable graphical output
graphic = ["zcore-drivers/graphic"]
board-c910light = []
link-user-img = []
# Enable extra page table falgs for T-Head CPU with MAEE on
thead-maee = []
# Disable PCI
no-pci = ["zcore-drivers/no-pci"]
# Enable allwinner drivers
allwinner-drivers = ["zcore-drivers/allwinner"]
# Enable fu740 drivers
fu740-drivers = ["zcore-drivers/fu740"]
[dependencies]
log = "0.4"
@ -34,11 +45,22 @@ git-version = "0.3"
numeric-enum-macro = "0.2"
lazy_static = { version = "1.4", features = ["spin_no_std"] }
zcore-drivers = { path = "../drivers", features = ["virtio"] }
lock = { git = "https://github.com/DeathWish5/kernel-sync", rev = "01b2e70" }
smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp", rev = "35e833e3", default-features = false, features = ["log", "alloc", "verbose", "proto-ipv4", "proto-ipv6", "proto-igmp", "medium-ip", "medium-ethernet", "socket-raw", "socket-udp", "socket-tcp", "socket-icmp", "async"] }
# LibOS mode
[target.'cfg(not(target_os = "none"))'.dependencies]
lock = { git = "https://github.com/DeathWish5/kernel-sync", rev = "8486b8" }
smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp", rev = "35e833e3", default-features = false, features = [
"log",
"alloc",
"verbose",
"proto-ipv4",
"proto-ipv6",
"proto-igmp",
"medium-ip",
"medium-ethernet",
"socket-raw",
"socket-udp",
"socket-tcp",
"socket-icmp",
"async",
] }
nix = { version = "0.23", optional = true }
tempfile = { version = "3", optional = true }
async-std = { version = "1.10", optional = true }
@ -46,21 +68,27 @@ bitmap-allocator = { git = "https://github.com/rcore-os/bitmap-allocator.git", r
# Bare-metal mode
[target.'cfg(target_os = "none")'.dependencies]
executor = { git = "https://github.com/DeathWish5/PreemptiveScheduler", rev = "3b04ba4" }
naive-timer = "0.2.0"
executor = { git = "https://github.com/DeathWish5/PreemptiveScheduler", rev = "e8cd353" }
# All mode on x86_64
# For riscv
[target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies]
riscv = "0.9"
sbi-rt = { version = "0.0.2", features = ["legacy"] }
# For x86_64
[target.'cfg(target_arch = "x86_64")'.dependencies]
x86 = "0.46"
x86_64 = "0.14"
# For aarch64
[target.'cfg(target_arch = "aarch64")'.dependencies]
tock-registers = "0.7"
cortex-a = "7.2.0"
# Bare-metal mode on x86_64
[target.'cfg(all(target_os = "none", target_arch = "x86_64"))'.dependencies]
uefi = "0.11"
uefi = "0.16"
raw-cpuid = "9.0"
x86-smpboot = { git = "https://github.com/rcore-os/x86-smpboot", rev = "1069df3" }
x2apic = "0.4"
# Bare-metal mode on riscv64
[target.'cfg(all(target_os = "none", target_arch = "riscv64"))'.dependencies]
riscv = "0.8"

View File

@ -0,0 +1,28 @@
//! Kernel configuration.
use crate::PAGE_SIZE;
/// Kernel configuration passed by kernel when calls [`crate::primary_init_early()`].
#[repr(C)]
#[derive(Debug, Clone)]
pub struct KernelConfig {
/// boot cmd line
pub cmdline: &'static str,
/// firmware type
pub firmware_type: &'static str,
/// UART base address
pub uart_base: usize,
/// GIC base address
pub gic_base: usize,
/// phystovirt offset
pub phys_to_virt_offset: usize,
}
pub const PHYS_MEMORY_BASE: usize = 0x4000_0000;
pub const UART_SIZE: usize = 0x1000;
pub const VIRTIO_BASE: usize = 0x0a00_0000;
pub const VIRTIO_SIZE: usize = 0x100;
pub const PA_1TB_BITS: usize = 40;
pub const PHYS_ADDR_MAX: usize = (1 << PA_1TB_BITS) - 1;
pub const PHYS_ADDR_MASK: usize = PHYS_ADDR_MAX & !(PAGE_SIZE - 1);
pub const PHYS_MEMORY_END: usize = PHYS_MEMORY_BASE + 100 * 1024 * 1024;
pub const USER_TABLE_FLAG: usize = 0xabcd_0000_0000_0000;

View File

@ -0,0 +1,29 @@
//! CPU information.
use cortex_a::registers::*;
use tock_registers::interfaces::Readable;
hal_fn_impl! {
impl mod crate::hal_fn::cpu {
fn cpu_id() -> u8 {
let id = MPIDR_EL1.get() & 0x3;
id as u8
}
fn cpu_frequency() -> u16 {
0
}
fn reset() -> ! {
info!("shutdown...");
let psci_system_off = 0x8400_0008_usize;
unsafe {
core::arch::asm!(
"hvc #0",
in("x0") psci_system_off
);
}
unreachable!()
}
}
}

View File

@ -0,0 +1,38 @@
use crate::arch::timer::set_next_trigger;
use crate::drivers;
use crate::hal_fn::mem::phys_to_virt;
use crate::imp::config::VIRTIO_BASE;
use crate::KCONFIG;
use alloc::boxed::Box;
use alloc::sync::Arc;
use zcore_drivers::irq::gic_400;
use zcore_drivers::scheme::IrqScheme;
use zcore_drivers::uart::{BufferedUart, Pl011Uart};
use zcore_drivers::virtio::{VirtIOHeader, VirtIoBlk};
use zcore_drivers::Device;
pub fn init_early() {
let uart = Pl011Uart::new(phys_to_virt(KCONFIG.uart_base));
let uart = Arc::new(uart);
let gic = gic_400::init(
phys_to_virt(KCONFIG.gic_base + 0x1_0000),
phys_to_virt(KCONFIG.gic_base),
);
gic.irq_enable(30);
gic.irq_enable(33);
gic.register_handler(33, Box::new(handle_uart_irq)).ok();
gic.register_handler(30, Box::new(set_next_trigger)).ok();
drivers::add_device(Device::Irq(Arc::new(gic)));
drivers::add_device(Device::Uart(BufferedUart::new(uart)));
}
pub fn init() {
let virtio_blk = Arc::new(
VirtIoBlk::new(unsafe { &mut *(phys_to_virt(VIRTIO_BASE) as *mut VirtIOHeader) }).unwrap(),
);
drivers::add_device(Device::Block(virtio_blk));
}
fn handle_uart_irq() {
crate::drivers::all_uart().first_unwrap().handle_irq(0);
}

View File

@ -0,0 +1,49 @@
//! Interrupts management.
use crate::HalResult;
use alloc::vec::Vec;
use cortex_a::asm::wfi;
hal_fn_impl! {
impl mod crate::hal_fn::interrupt {
fn wait_for_interrupt() {
intr_on();
wfi();
intr_off();
}
fn handle_irq(vector: usize) {
// TODO: timer and other devices with GIC interrupt controller
crate::drivers::all_irq().first_unwrap().handle_irq(vector);
if vector == 30 {
debug!("Timer");
}
}
fn intr_off() {
unsafe {
core::arch::asm!("msr daifset, #2");
}
}
fn intr_on() {
unsafe {
core::arch::asm!("msr daifclr, #2");
}
}
fn intr_get() -> bool {
use cortex_a::registers::DAIF;
use tock_registers::interfaces::Readable;
!DAIF.is_set(DAIF::I)
}
fn send_ipi(cpuid: usize, reason: usize) -> HalResult {
trace!("ipi [{}] => [{}]: {:x}", super::cpu::cpu_id(), cpuid, reason);
panic!("send_ipi unsupported for aarch64");
}
fn ipi_reason() -> Vec<usize> {
panic!("ipi_reason unsupported for aarch64");
}
}
}

View File

@ -0,0 +1,20 @@
use crate::imp::config::*;
use crate::PhysAddr;
use alloc::vec::Vec;
use core::ops::Range;
extern "C" {
fn ekernel();
}
pub fn free_pmem_regions() -> Vec<Range<PhysAddr>> {
let mut regions = Vec::new();
let start = ekernel as usize & PHYS_ADDR_MASK;
regions.push(start as PhysAddr..PHYS_MEMORY_END as PhysAddr);
regions
}
/// Flush the physical frame.
pub fn frame_flush(_target: PhysAddr) {
unimplemented!()
}

View File

@ -0,0 +1,50 @@
pub mod config;
pub mod cpu;
pub mod drivers;
pub mod interrupt;
pub mod mem;
pub mod timer;
pub mod trap;
pub mod vm;
use crate::KCONFIG;
use crate::{mem::phys_to_virt, utils::init_once::InitOnce, PhysAddr};
use alloc::string::{String, ToString};
use core::ops::Range;
hal_fn_impl_default!(crate::hal_fn::console);
static INITRD_REGION: InitOnce<Option<Range<PhysAddr>>> = InitOnce::new_with_default(None);
static CMDLINE: InitOnce<String> = InitOnce::new_with_default(String::new());
pub fn cmdline() -> String {
CMDLINE.clone()
}
pub fn init_ram_disk() -> Option<&'static mut [u8]> {
INITRD_REGION.as_ref().map(|range| unsafe {
core::slice::from_raw_parts_mut(phys_to_virt(range.start) as *mut u8, range.len())
})
}
pub fn primary_init_early() {
CMDLINE.init_once_by(KCONFIG.cmdline.to_string());
drivers::init_early();
}
pub fn primary_init() {
vm::init();
drivers::init();
}
pub fn secondary_init() {
unimplemented!()
}
pub const fn timer_interrupt_vector() -> usize {
30
}
pub fn timer_init() {
timer::init();
}

View File

@ -0,0 +1,22 @@
//! ARM Generic Timer.
use crate::timer::TICKS_PER_SEC;
use core::time::Duration;
use cortex_a::{asm::barrier, registers::*};
use tock_registers::interfaces::{Readable, Writeable};
pub fn timer_now() -> Duration {
unsafe { barrier::isb(barrier::SY) }
let cur_cnt = CNTPCT_EL0.get() * 1_000_000_000;
let freq = CNTFRQ_EL0.get() as u64;
Duration::from_nanos(cur_cnt / freq)
}
pub fn set_next_trigger() {
CNTP_TVAL_EL0.set(CNTFRQ_EL0.get() / TICKS_PER_SEC);
}
pub fn init() {
CNTP_CTL_EL0.write(CNTP_CTL_EL0::ENABLE::SET);
set_next_trigger();
}

View File

@ -0,0 +1,51 @@
use crate::context::TrapReason;
use crate::{Info, Kind, Source, KCONFIG};
use cortex_a::registers::FAR_EL1;
use tock_registers::interfaces::Readable;
use trapframe::TrapFrame;
use zcore_drivers::irq::gic_400::get_irq_num;
#[no_mangle]
pub extern "C" fn trap_handler(tf: &mut TrapFrame) {
let info = Info {
source: Source::from(tf.trap_num & 0xffff),
kind: Kind::from((tf.trap_num >> 16) & 0xffff),
};
trace!("Exception from {:?}", info.source);
match info.kind {
Kind::Synchronous => {
sync_handler(tf);
}
Kind::Irq => {
use crate::hal_fn::mem::phys_to_virt;
crate::interrupt::handle_irq(get_irq_num(
phys_to_virt(KCONFIG.gic_base + 0x1_0000),
phys_to_virt(KCONFIG.gic_base),
));
}
_ => {
panic!(
"Unsupported exception type: {:?}, TrapFrame: {:?}",
info.kind, tf
);
}
}
trace!("Exception end");
}
fn breakpoint(elr: &mut usize) {
info!("Exception::Breakpoint: A breakpoint set @0x{:x} ", elr);
*elr += 4;
}
fn sync_handler(tf: &mut TrapFrame) {
match TrapReason::from(tf.trap_num) {
TrapReason::PageFault(vaddr, flags) => crate::KHANDLER.handle_page_fault(vaddr, flags),
TrapReason::SoftwareBreakpoint => breakpoint(&mut tf.elr),
other => error!(
"Unsupported trap in kernel: {:?}, FAR_EL1: {:#x?}",
other,
FAR_EL1.get()
),
}
}

View File

@ -0,0 +1,353 @@
use crate::hal_fn::mem::phys_to_virt;
use crate::imp::config::*;
use crate::utils::page_table::{GenericPTE, PageTableImpl, PageTableLevel4};
use crate::MMUFlags;
use crate::{PhysAddr, VirtAddr, KCONFIG};
use core::fmt::{Debug, Formatter, Result};
use cortex_a::registers::*;
use lock::Mutex;
use tock_registers::interfaces::{Readable, Writeable};
use zcore_drivers::irq::gic_400::{GICC_SIZE, GICD_SIZE};
lazy_static! {
static ref KERNEL_PT: Mutex<PageTable> = Mutex::new(init_kernel_page_table().unwrap());
}
/// remap kernel ELF segments with 4K page
fn init_kernel_page_table() -> PagingResult<PageTable> {
extern "C" {
fn stext();
fn etext();
fn srodata();
fn erodata();
fn sdata();
fn edata();
fn sbss();
fn ebss();
fn boot_stack();
fn boot_stack_top();
}
let mut pt = PageTable::new();
let mut map_range = |start: VirtAddr, end: VirtAddr, flags: MMUFlags| -> PagingResult {
pt.map_cont(
crate::addr::align_down(start),
crate::addr::align_up(end - start),
start - KCONFIG.phys_to_virt_offset,
flags,
)
};
map_range(
stext as usize,
etext as usize,
MMUFlags::READ | MMUFlags::EXECUTE,
)?;
map_range(srodata as usize, erodata as usize, MMUFlags::READ)?;
map_range(
sdata as usize,
edata as usize,
MMUFlags::READ | MMUFlags::WRITE,
)?;
map_range(
sbss as usize,
ebss as usize,
MMUFlags::READ | MMUFlags::WRITE,
)?;
// stack
map_range(
boot_stack as usize,
boot_stack_top as usize,
MMUFlags::READ | MMUFlags::WRITE,
)?;
// uart
map_range(
phys_to_virt(KCONFIG.uart_base),
phys_to_virt(KCONFIG.uart_base) + UART_SIZE,
MMUFlags::READ | MMUFlags::WRITE | MMUFlags::DEVICE,
)?;
// gic
map_range(
phys_to_virt(KCONFIG.gic_base + 0x1_0000),
phys_to_virt(KCONFIG.gic_base + 0x1_0000) + GICC_SIZE,
MMUFlags::READ | MMUFlags::WRITE | MMUFlags::DEVICE,
)?;
map_range(
phys_to_virt(KCONFIG.gic_base),
phys_to_virt(KCONFIG.gic_base) + GICD_SIZE,
MMUFlags::READ | MMUFlags::WRITE | MMUFlags::DEVICE,
)?;
// virtio_drivers
map_range(
phys_to_virt(VIRTIO_BASE),
phys_to_virt(VIRTIO_BASE) + VIRTIO_SIZE,
MMUFlags::READ | MMUFlags::WRITE | MMUFlags::DEVICE,
)?;
// physical frames
for r in crate::mem::free_pmem_regions() {
map_range(
phys_to_virt(r.start),
phys_to_virt(r.end),
MMUFlags::READ | MMUFlags::WRITE,
)?;
}
Ok(pt)
}
pub fn init() {
let mut pt = KERNEL_PT.lock();
info!("initialized kernel page table @ {:#x}", pt.table_phys());
unsafe {
pt.activate();
TTBR0_EL1.set(0);
flush_tlb_all();
}
}
pub fn flush_tlb_all() {
unsafe {
core::arch::asm!(
"dsb ishst
tlbi vmalle1is
dsb ish
isb"
);
}
}
hal_fn_impl! {
impl mod crate::hal_fn::vm {
fn activate_paging(vmtoken: PhysAddr) {
let check_if_user = (vmtoken & USER_TABLE_FLAG) != 0;
let vmtoken = vmtoken & PHYS_ADDR_MASK;
info!("set {} page_table @ {:#x}", if check_if_user { "user" } else { "kernel" }, vmtoken);
if check_if_user {
TTBR0_EL1.set(vmtoken as _);
} else {
TTBR1_EL1.set(vmtoken as _);
}
flush_tlb_all();
}
fn current_vmtoken() -> PhysAddr {
TTBR1_EL1.get() as _
}
fn flush_tlb(vaddr: Option<VirtAddr>) {
// Translations used at EL1 for the specified address, for all ASID values,
// in the Inner Shareable shareability domain.
if let Some(vaddr) = vaddr {
unsafe {
core::arch::asm!(
"dsb ishst
tlbi vaae1is, {0}
dsb ish
isb",
in(reg) vaddr >> 12
);
}
} else {
flush_tlb_all();
}
}
fn pt_clone_kernel_space(dst_pt_root: PhysAddr, src_pt_root: PhysAddr) {
let entry_range = 0x100..0x200; // 0xffff_0000_8000_0000..0xffff_0000_c000_0000
let dst_table = unsafe { core::slice::from_raw_parts_mut(phys_to_virt(dst_pt_root) as *mut AARCH64PTE, 512) };
let src_table = unsafe { core::slice::from_raw_parts(phys_to_virt(src_pt_root) as *const AARCH64PTE, 512) };
for i in entry_range {
dst_table[i] = src_table[i];
if dst_table[i].is_unused() {
dst_table[i].0 |= PTF::NG.bits() as u64;
}
}
}
}
}
bitflags::bitflags! {
/// Possible flags for a page table entry.
struct PTF: usize {
// Attribute fields in stage 1 VMSAv8-64 Block and Page descriptors:
/// Whether the descriptor is valid.
const VALID = 1 << 0;
/// The descriptor gives the address of the next level of translation table or 4KB page.
/// (not a 2M, 1G block)
const NON_BLOCK = 1 << 1;
/// Memory attributes index field.
const ATTR_INDX = 0b111 << 2;
/// Non-secure bit. For memory accesses from Secure state, specifies whether the output
/// address is in Secure or Non-secure memory.
const NS = 1 << 5;
/// Access permission: accessable at EL0.
const AP_EL0 = 1 << 6;
/// Access permission: read-only.
const AP_RO = 1 << 7;
/// Shareability: Inner Shareable (otherwise Outer Shareable).
const INNER = 1 << 8;
/// Shareability: Inner or Outer Shareable (otherwise Non-shareable).
const SHAREABLE = 1 << 9;
/// The Access flag.
const AF = 1 << 10;
/// The not global bit.
const NG = 1 << 11;
/// Indicates that 16 adjacent translation table entries point to contiguous memory regions.
const CONTIGUOUS = 1 << 52;
/// The Privileged execute-never field.
const PXN = 1 << 53;
/// The Execute-never or Unprivileged execute-never field.
const UXN = 1 << 54;
// Next-level attributes in stage 1 VMSAv8-64 Table descriptors:
/// PXN limit for subsequent levels of lookup.
const PXN_TABLE = 1 << 59;
/// XN limit for subsequent levels of lookup.
const XN_TABLE = 1 << 60;
/// Access permissions limit for subsequent levels of lookup: access at EL0 not permitted.
const AP_NO_EL0_TABLE = 1 << 61;
/// Access permissions limit for subsequent levels of lookup: write access not permitted.
const AP_NO_WRITE_TABLE = 1 << 62;
/// For memory accesses from Secure state, specifies the Security state for subsequent
/// levels of lookup.
const NS_TABLE = 1 << 63;
}
}
#[repr(u64)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
enum MemType {
#[allow(dead_code)]
Device = 0,
Normal = 1,
}
impl PTF {
const ATTR_INDEX_MASK: u64 = 0b111_00;
const fn from_mem_type(mem_type: MemType) -> Self {
let mut bits = (mem_type as u64) << 2;
if matches!(mem_type, MemType::Normal) {
bits |= (Self::INNER.bits() | Self::SHAREABLE.bits()) as u64;
}
Self::from_bits_truncate(bits as usize)
}
#[allow(dead_code)]
fn mem_type(&self) -> MemType {
let idx = (self.bits() as u64 & Self::ATTR_INDEX_MASK) >> 2;
match idx {
0 => MemType::Device,
1 => MemType::Normal,
_ => panic!("Invalid memory attribute index"),
}
}
}
impl From<MMUFlags> for PTF {
fn from(f: MMUFlags) -> Self {
let mut flags = Self::from_mem_type(if f.contains(MMUFlags::DEVICE) {
MemType::Device
} else {
MemType::Normal
});
if f.is_empty() {
return flags;
}
if f.contains(MMUFlags::READ) {
flags |= PTF::VALID;
}
if !f.contains(MMUFlags::WRITE) {
flags |= PTF::AP_RO;
}
if f.contains(MMUFlags::USER) {
flags |= PTF::AP_EL0 | PTF::PXN;
if !f.contains(MMUFlags::EXECUTE) {
flags |= PTF::UXN;
}
} else {
flags |= PTF::UXN;
if !f.contains(MMUFlags::EXECUTE) {
flags |= PTF::PXN;
}
}
flags
}
}
impl From<PTF> for MMUFlags {
fn from(f: PTF) -> Self {
let mut ret = Self::empty();
if f.contains(PTF::VALID) {
ret |= Self::READ;
}
if !f.contains(PTF::AP_RO) {
ret |= Self::WRITE;
}
if f.contains(PTF::AP_EL0) {
ret |= Self::USER;
if !f.contains(PTF::UXN) {
ret |= Self::EXECUTE;
}
} else if f.intersects(PTF::PXN) {
ret |= Self::EXECUTE;
}
if f.mem_type() == MemType::Device {
ret |= Self::DEVICE;
}
ret
}
}
/// Page table entry.
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct AARCH64PTE(u64);
impl GenericPTE for AARCH64PTE {
fn addr(&self) -> PhysAddr {
(self.0 as usize & PHYS_ADDR_MASK) as _
}
fn flags(&self) -> MMUFlags {
PTF::from_bits_truncate(self.0 as usize).into()
}
fn is_unused(&self) -> bool {
self.0 == 0
}
fn is_present(&self) -> bool {
PTF::from_bits_truncate(self.0 as usize).contains(PTF::VALID)
}
fn is_leaf(&self) -> bool {
!PTF::from_bits_truncate(self.0 as usize).intersects(PTF::NON_BLOCK)
}
fn set_addr(&mut self, paddr: PhysAddr) {
self.0 = (paddr & PHYS_ADDR_MASK) as u64;
}
fn set_flags(&mut self, flags: MMUFlags, is_huge: bool) {
let mut flags = PTF::from(flags) | PTF::AF;
if !is_huge {
flags |= PTF::NON_BLOCK
}
self.0 = (self.0 & PHYS_ADDR_MASK as u64) | flags.bits() as u64;
}
fn set_table(&mut self, paddr: PhysAddr) {
self.0 = (((paddr as usize) & PHYS_ADDR_MASK) | PTF::VALID.bits() | PTF::NON_BLOCK.bits())
as u64;
}
fn clear(&mut self) {
self.0 = 0
}
}
impl Debug for AARCH64PTE {
fn fmt(&self, f: &mut Formatter) -> Result {
let mut f = f.debug_struct("AARCH64PTE");
f.field("raw", &self.0);
f.field("addr", &self.addr());
f.field("flags", &self.flags());
f.finish()
}
}
/// Sv48: Page-Based 48-bit Virtual-Memory System.
pub type PageTable = PageTableImpl<PageTableLevel4, AARCH64PTE>;

View File

@ -5,4 +5,5 @@
pub struct KernelConfig {
pub phys_to_virt_offset: usize,
pub dtb_paddr: usize,
pub dtb_size: usize,
}

View File

@ -1,7 +1,7 @@
//! CPU information.
use crate::utils::init_once::InitOnce;
pub(super) static CPU_FREQ_MHZ: InitOnce<u16> = InitOnce::new_with_default(10);
pub(super) static CPU_FREQ_MHZ: InitOnce<u16> = InitOnce::new_with_default(1000); // 1GHz
hal_fn_impl! {
impl mod crate::hal_fn::cpu {
@ -17,7 +17,8 @@ hal_fn_impl! {
fn reset() -> ! {
info!("shutdown...");
super::sbi::shutdown()
sbi_rt::system_reset(sbi_rt::Shutdown, sbi_rt::NoReason);
unreachable!()
}
}
}

View File

@ -13,7 +13,12 @@ struct IoMapperImpl;
impl IoMapper for IoMapperImpl {
fn query_or_map(&self, paddr: PhysAddr, size: usize) -> Option<VirtAddr> {
let vaddr = phys_to_virt(paddr);
let vaddr = if paddr > (1 << 39) {
// To retrieve avaliable sv39 vaddr
paddr | (0x1ffffff << 39)
} else {
phys_to_virt(paddr)
};
let mut pt = super::vm::kernel_page_table().lock();
if let Ok((paddr_mapped, _, _)) = pt.query(vaddr) {
if paddr_mapped == paddr {
@ -30,6 +35,7 @@ impl IoMapper for IoMapperImpl {
let flags = MMUFlags::READ
| MMUFlags::WRITE
| MMUFlags::HUGE_PAGE
| MMUFlags::DEVICE
| MMUFlags::from_bits_truncate(CachePolicy::UncachedDevice as usize);
if let Err(err) = pt.map_cont(vaddr, size, paddr, flags) {
warn!(
@ -62,7 +68,7 @@ pub(super) fn init() -> DeviceResult {
}
}
#[cfg(not(feature = "loopback"))]
#[cfg(not(feature = "no-pci"))]
{
use alloc::sync::Arc;
use zcore_drivers::bus::pci;

View File

@ -1,5 +1,6 @@
//! Interrupts management.
use crate::{HalError, HalResult};
use alloc::vec::Vec;
use riscv::{asm, register::sstatus};
hal_fn_impl! {
@ -17,7 +18,10 @@ hal_fn_impl! {
fn handle_irq(cause: usize) {
trace!("Handle irq cause: {}", cause);
crate::drivers::all_irq().first_unwrap().handle_irq(cause)
let irq = crate::drivers::all_irq()
.find(alloc::format!("riscv-intc-cpu{}", crate::cpu::cpu_id()).as_str())
.expect("IRQ device 'riscv-intc' not initialized!");
irq.handle_irq(cause)
}
fn intr_on() {
@ -31,5 +35,25 @@ hal_fn_impl! {
fn intr_get() -> bool {
sstatus::read().sie()
}
#[allow(deprecated)]
fn send_ipi(cpuid: usize, reason: usize) -> HalResult {
trace!("ipi [{}] => [{}]", super::cpu::cpu_id(), cpuid);
let queue = crate::common::ipi::ipi_queue(cpuid);
let idx = queue.alloc_entry();
if let Some(idx) = idx {
let entry = queue.entry_at(idx);
*entry = reason;
queue.commit_entry(idx);
let mask:usize = 1 << cpuid;
sbi_rt::legacy::send_ipi(&mask as *const usize as usize);
return Ok(());
}
Err(HalError)
}
fn ipi_reason() -> Vec<usize> {
crate::common::ipi::ipi_reason()
}
}
}

View File

@ -5,6 +5,24 @@ use crate::addr::{align_down, align_up};
use crate::utils::init_once::InitOnce;
use crate::{PhysAddr, KCONFIG, PAGE_SIZE};
fn cut_off(total: Range<PhysAddr>, cut: &Range<PhysAddr>) -> Vec<Range<PhysAddr>> {
let mut regions = Vec::new();
// no overlap at all
if cut.end <= total.start || total.end <= cut.start {
regions.push(total);
} else {
// no overlap on the left
if total.start < cut.start {
regions.push(total.start..align_down(cut.start));
}
// no overlap on the right
if cut.end < total.end {
regions.push(align_up(cut.end)..total.end);
}
}
regions
}
pub fn free_pmem_regions() -> Vec<Range<PhysAddr>> {
extern "C" {
fn end();
@ -13,30 +31,23 @@ pub fn free_pmem_regions() -> Vec<Range<PhysAddr>> {
static FREE_PMEM_REGIONS: InitOnce<Vec<Range<PhysAddr>>> = InitOnce::new();
FREE_PMEM_REGIONS.init_once(|| {
let initrd = super::INITRD_REGION.as_ref();
let dtb = Range::<PhysAddr> {
start: KCONFIG.dtb_paddr,
end: KCONFIG.dtb_paddr + KCONFIG.dtb_size,
};
let min_start = align_up(end as usize + PAGE_SIZE) - KCONFIG.phys_to_virt_offset;
let mut regions = Vec::new();
for r in super::MEMORY_REGIONS.iter() {
let (start, end) = (align_up(r.start.max(min_start)), align_down(r.end));
if start >= end {
continue;
}
let base = align_up(r.start.max(min_start))..align_down(r.end);
let mut no_dtb = cut_off(base, &dtb);
if let Some(initrd) = initrd {
// no overlap at all
if initrd.end <= start || end <= initrd.start {
regions.push(start..end);
continue;
}
// no overlap on the left
if start < initrd.start {
regions.push(start..align_down(initrd.start));
}
// no overlap on the right
if initrd.end < end {
regions.push(align_up(initrd.end)..end);
for range in no_dtb {
let mut no_initrd = cut_off(range, initrd);
regions.append(&mut no_initrd);
}
} else {
regions.push(start..end);
regions.append(&mut no_dtb);
}
}
regions

View File

@ -9,12 +9,11 @@ pub mod sbi;
pub mod timer;
pub mod vm;
use crate::{mem::phys_to_virt, utils::init_once::InitOnce, PhysAddr};
use alloc::{string::String, vec::Vec};
use core::ops::Range;
use zcore_drivers::utils::devicetree::Devicetree;
use crate::{mem::phys_to_virt, utils::init_once::InitOnce, PhysAddr};
static CMDLINE: InitOnce<String> = InitOnce::new_with_default(String::new());
static INITRD_REGION: InitOnce<Option<Range<PhysAddr>>> = InitOnce::new_with_default(None);
static MEMORY_REGIONS: InitOnce<Vec<Range<PhysAddr>>> = InitOnce::new_with_default(Vec::new());
@ -56,8 +55,6 @@ pub fn primary_init_early() {
pub fn primary_init() {
vm::init();
drivers::init().unwrap();
// We should set first time interrupt before run into first user program
// timer::init();
}
pub fn timer_init() {
@ -66,9 +63,15 @@ pub fn timer_init() {
pub fn secondary_init() {
vm::init();
info!("cpu {} drivers init ...", crate::cpu::cpu_id());
drivers::intc_init().unwrap();
let plic = crate::drivers::all_irq()
.find("riscv-plic")
.expect("IRQ device 'riscv-plic' not initialized!");
info!(
"cpu {} enable plic: {:?}",
crate::cpu::cpu_id(),
plic.name()
);
plic.init_hart();
}

View File

@ -95,6 +95,30 @@ pub fn hart_stop() -> usize {
sbi_call(HSM_EID, SBI_HART_STOP_FID, 0, 0, 0)
}
// Just for T-HEAD C910 light
pub const BADDR: u64 = 0xffffffffe7014000;
pub fn uart_put(c: u8) {
let ptr = BADDR as *mut u32;
unsafe {
//LSR bit:THRE
while ptr.add(5).read_volatile() & (1 << 5) == 0 {}
//此时transmitter empty, THR有效位是8
ptr.add(0).write_volatile(c as u32);
}
}
pub fn uart_get() -> Option<u8> {
let ptr = BADDR as *mut u32;
unsafe {
//查看LSR的DR位为1则有数据
if ptr.add(5).read_volatile() & 0b1 == 0 {
None
} else {
Some((ptr.add(0).read_volatile() & 0xff) as u8)
}
}
}
hal_fn_impl! {
impl mod crate::hal_fn::console {
fn console_write_early(s: &str) {

View File

@ -7,7 +7,7 @@ fn get_cycle() -> u64 {
pub(super) fn timer_set_next() {
let cycles =
super::cpu::cpu_frequency() as u64 * 1_000_000 / super::super::timer::TICKS_PER_SEC;
super::sbi::set_timer(get_cycle() + cycles);
sbi_rt::set_timer(get_cycle() + cycles);
}
pub(super) fn init() {

View File

@ -1,7 +1,9 @@
use crate::context::TrapReason;
use crate::thread::{get_current_thread, set_current_thread};
use crate::IpiReason;
use alloc::vec::Vec;
use riscv::register::scause;
use trapframe::TrapFrame;
use crate::context::TrapReason;
pub(super) const SUPERVISOR_TIMER_INT_VEC: usize = 5; // scause::Interrupt::SupervisorTimer
fn breakpoint(sepc: &mut usize) {
@ -19,8 +21,13 @@ pub(super) fn super_timer() {
}
pub(super) fn super_soft() {
super::sbi::clear_ipi();
info!("Interrupt::SupervisorSoft!");
#[allow(deprecated)]
sbi_rt::legacy::clear_ipi();
let reasons: Vec<IpiReason> = crate::interrupt::ipi_reason()
.iter()
.map(|x| IpiReason::from(*x))
.collect();
debug!("Interrupt::SupervisorSoft, reason = {:?}", reasons);
}
#[no_mangle]
@ -38,7 +45,10 @@ pub extern "C" fn trap_handler(tf: &mut TrapFrame) {
TrapReason::Interrupt(vector) => {
crate::interrupt::handle_irq(vector);
if vector == SUPERVISOR_TIMER_INT_VEC {
let current_thread = get_current_thread();
set_current_thread(None);
executor::handle_timeout();
set_current_thread(current_thread);
}
}
other => panic!("Undefined trap: {:x?} {:#x?}", other, tf),

View File

@ -6,6 +6,7 @@ use core::slice;
use lock::Mutex;
use riscv::{asm, register::satp};
use crate::addr::{align_down, align_up};
use crate::utils::page_table::{GenericPTE, PageTableImpl, PageTableLevel3};
use crate::{mem::phys_to_virt, MMUFlags, PhysAddr, VirtAddr, KCONFIG};
@ -69,8 +70,27 @@ fn init_kernel_page_table() -> PagingResult<PageTable> {
MMUFlags::READ | MMUFlags::WRITE,
)?;
}
cfg_if! {
if #[cfg(any(feature = "board-fu740", feature = "board-c910light"))] {
extern "C" {
fn boot_stack();
fn boot_stack_top();
}
map_range(
boot_stack as usize,
boot_stack_top as usize,
MMUFlags::READ | MMUFlags::WRITE,
)?;
}}
// device tree
map_range(
phys_to_virt(align_down(KCONFIG.dtb_paddr)),
phys_to_virt(align_up(KCONFIG.dtb_paddr + KCONFIG.dtb_size)),
MMUFlags::READ,
)?;
// physical frames
for r in crate::mem::free_pmem_regions() {
info!("FREE PHY MEM: {:x?}", r);
map_range(
phys_to_virt(r.start),
phys_to_virt(r.end),
@ -97,11 +117,11 @@ hal_fn_impl! {
if old_token != vmtoken {
#[cfg(target_arch = "riscv64")]
let mode = satp::Mode::Sv39;
debug!("switch table {:x?} -> {:x?}", old_token, vmtoken);
unsafe {
satp::set(mode, 0, vmtoken >> 12);
asm::sfence_vma_all();
}
debug!("cpu {} switch table {:x?} -> {:x?}", crate::cpu::cpu_id(), old_token, vmtoken);
}
}
@ -136,16 +156,20 @@ hal_fn_impl! {
bitflags::bitflags! {
/// Possible flags for a page table entry.
struct PTF: usize {
const VALID = 1 << 0;
const READABLE = 1 << 1;
const WRITABLE = 1 << 2;
const EXECUTABLE = 1 << 3;
const USER = 1 << 4;
const GLOBAL = 1 << 5;
const ACCESSED = 1 << 6;
const DIRTY = 1 << 7;
const RESERVED1 = 1 << 8;
const RESERVED2 = 1 << 9;
const VALID = 1 << 0;
const READABLE = 1 << 1;
const WRITABLE = 1 << 2;
const EXECUTABLE = 1 << 3;
const USER = 1 << 4;
const GLOBAL = 1 << 5;
const ACCESSED = 1 << 6;
const DIRTY = 1 << 7;
const RESERVED1 = 1 << 8;
const RESERVED2 = 1 << 9;
#[cfg(feature = "thead-maee")]
const CACHEABLE = 1 << 62;
#[cfg(feature = "thead-maee")]
const STRONG_ORDER = 1 << 63;
}
}
@ -155,11 +179,18 @@ impl From<MMUFlags> for PTF {
return PTF::empty();
}
let mut flags = PTF::VALID;
if f.contains(MMUFlags::READ) {
flags |= PTF::READABLE;
}
if f.contains(MMUFlags::WRITE) {
flags |= PTF::READABLE | PTF::WRITABLE;
#[cfg(feature = "thead-maee")]
{
flags |= PTF::CACHEABLE;
}
} else if f.contains(MMUFlags::READ) {
flags |= PTF::READABLE;
#[cfg(feature = "thead-maee")]
{
flags |= PTF::CACHEABLE;
}
}
if f.contains(MMUFlags::EXECUTE) {
flags |= PTF::EXECUTABLE;
@ -167,6 +198,10 @@ impl From<MMUFlags> for PTF {
if f.contains(MMUFlags::USER) {
flags |= PTF::USER;
}
#[cfg(feature = "thead-maee")]
if f.contains(MMUFlags::DEVICE) {
flags |= PTF::STRONG_ORDER;
}
flags
}
}

View File

@ -47,7 +47,7 @@ pub(super) fn init() -> DeviceResult {
drivers::add_device(Device::Irq(irq));
#[cfg(not(feature = "loopback"))]
#[cfg(not(feature = "no-pci"))]
{
// PCI scan
use zcore_drivers::bus::pci;

View File

@ -5,6 +5,7 @@ use core::ops::Range;
use crate::drivers::all_irq;
use crate::drivers::prelude::{IrqHandler, IrqPolarity, IrqTriggerMode};
use crate::HalResult;
use alloc::vec::Vec;
use x86_64::instructions::interrupts;
hal_fn_impl! {
@ -72,5 +73,14 @@ hal_fn_impl! {
) -> HalResult {
Ok(all_irq().first_unwrap().msi_register_handler(block, msi_id, handler)?)
}
fn send_ipi(cpuid: usize, reason: usize) -> HalResult {
trace!("ipi [{}] => [{}]: {:x}", super::cpu::cpu_id(), cpuid, reason);
panic!("send_ipi unsupported for x86_64");
}
fn ipi_reason() -> Vec<usize> {
panic!("ipi_reason unsupported for x86_64");
}
}
}

View File

@ -1,24 +1,20 @@
#![allow(dead_code)]
#![allow(clippy::identity_op)]
use crate::context::TrapReason;
use trapframe::TrapFrame;
use crate::context::TrapReason;
pub(super) const X86_INT_LOCAL_APIC_BASE: usize = 0xf0;
pub(super) const X86_INT_APIC_SPURIOUS: usize = X86_INT_LOCAL_APIC_BASE + 0x0;
pub(super) const _X86_INT_APIC_SPURIOUS: usize = X86_INT_LOCAL_APIC_BASE;
pub(super) const X86_INT_APIC_TIMER: usize = X86_INT_LOCAL_APIC_BASE + 0x1;
pub(super) const X86_INT_APIC_ERROR: usize = X86_INT_LOCAL_APIC_BASE + 0x2;
pub(super) const _X86_INT_APIC_ERROR: usize = X86_INT_LOCAL_APIC_BASE + 0x2;
// ISA IRQ numbers
pub(super) const X86_ISA_IRQ_PIT: usize = 0;
pub(super) const X86_ISA_IRQ_KEYBOARD: usize = 1;
pub(super) const X86_ISA_IRQ_PIC2: usize = 2;
pub(super) const _X86_ISA_IRQ_PIT: usize = 0;
pub(super) const _X86_ISA_IRQ_KEYBOARD: usize = 1;
pub(super) const _X86_ISA_IRQ_PIC2: usize = 2;
pub(super) const X86_ISA_IRQ_COM2: usize = 3;
pub(super) const X86_ISA_IRQ_COM1: usize = 4;
pub(super) const X86_ISA_IRQ_CMOSRTC: usize = 8;
pub(super) const X86_ISA_IRQ_MOUSE: usize = 12;
pub(super) const X86_ISA_IRQ_IDE: usize = 14;
pub(super) const _X86_ISA_IRQ_CMOSRTC: usize = 8;
pub(super) const _X86_ISA_IRQ_MOUSE: usize = 12;
pub(super) const _X86_ISA_IRQ_IDE: usize = 14;
fn breakpoint() {
panic!("\nEXCEPTION: Breakpoint");

View File

@ -7,6 +7,10 @@ cfg_if! {
#[path = "arch/riscv/mod.rs"]
pub mod arch;
pub use self::arch::{sbi, timer_interrupt_vector};
} else if #[cfg(target_arch = "aarch64")] {
#[path = "arch/aarch64/mod.rs"]
pub mod arch;
pub use self::arch::timer_interrupt_vector;
}
}
@ -20,11 +24,3 @@ pub use self::arch::{config, cpu, interrupt, vm};
pub use super::hal_fn::{rand, vdso};
hal_fn_impl_default!(rand, vdso);
/// Non-SMP initialization.
#[cfg(any(not(feature = "smp"), doc))]
#[doc(cfg(not(feature = "smp")))]
pub fn init(cfg: crate::KernelConfig, handler: &'static impl crate::KernelHandler) {
boot::primary_init_early(cfg, handler);
boot::primary_init();
}

View File

@ -1,6 +1,15 @@
//! Thread spawning.
use core::future::Future;
use alloc::sync::Arc;
use core::{any::Any, future::Future};
use crate::{config::MAX_CORE_NUM, utils::PerCpuCell};
#[allow(clippy::declare_interior_mutable_const)]
const DEFAULT_THREAD: PerCpuCell<Option<Arc<dyn Any + Send + Sync>>> = PerCpuCell::new(None);
static CURRENT_THREAD: [PerCpuCell<Option<Arc<dyn Any + Send + Sync>>>; MAX_CORE_NUM] =
[DEFAULT_THREAD; MAX_CORE_NUM];
hal_fn_impl! {
impl mod crate::hal_fn::thread {
@ -8,10 +17,18 @@ hal_fn_impl! {
executor::spawn(future);
}
fn set_tid(_tid: u64, _pid: u64) {}
fn set_current_thread(thread: Option<Arc<dyn Any + Send + Sync>>) {
let cpu_id = super::cpu::cpu_id() as usize;
*CURRENT_THREAD[cpu_id].get_mut() = thread;
}
fn get_tid() -> (u64, u64) {
(0, 0)
fn get_current_thread() -> Option<Arc<dyn Any + Send + Sync>> {
let cpu_id = super::cpu::cpu_id() as usize;
if let Some(arc_thread) = CURRENT_THREAD[cpu_id].get().as_ref() {
Some(arc_thread.clone())
} else {
None
}
}
}
}

View File

@ -3,25 +3,20 @@
use alloc::boxed::Box;
use core::time::Duration;
use core::sync::atomic::{AtomicBool, Ordering};
use lock::Mutex;
use naive_timer::Timer;
#[allow(dead_code)]
pub(super) const TICKS_PER_SEC: u64 = 100;
pub(super) const TICKS_PER_SEC: u64 = 1;
lazy_static! {
static ref NAIVE_TIMER: Mutex<Timer> = Mutex::new(Timer::default());
static ref FIRST: AtomicBool = AtomicBool::new(false);
lazy_static::lazy_static! {
static ref NAIVE_TIMER:Mutex<Timer> = Mutex::new(Timer::default());
}
hal_fn_impl! {
impl mod crate::hal_fn::timer {
fn timer_enable() {
if !FIRST.load(Ordering::Relaxed) {
FIRST.store(true, Ordering::Relaxed);
super::arch::timer_init();
}
super::arch::timer_init();
}
fn timer_now() -> Duration {
@ -29,6 +24,7 @@ hal_fn_impl! {
}
fn timer_set(deadline: Duration, callback: Box<dyn FnOnce(Duration) + Send + Sync>) {
debug!("Set timer at: {:?}", deadline);
NAIVE_TIMER.lock().add(deadline, callback);
}

View File

@ -19,6 +19,17 @@ impl Write for SerialWriter {
}
}
struct DebugWriter;
static DEBUG_WRITER: Mutex<DebugWriter> = Mutex::new(DebugWriter);
impl Write for DebugWriter {
fn write_str(&mut self, s: &str) -> Result {
crate::hal_fn::console::console_write_early(s);
Ok(())
}
}
cfg_if! {
if #[cfg(feature = "graphic")] {
use crate::utils::init_once::InitOnce;
@ -53,6 +64,16 @@ pub fn serial_write_fmt(fmt: Arguments) {
SERIAL_WRITER.lock().write_fmt(fmt).unwrap();
}
/// Writes a string slice into the serial through sbi call.
pub fn debug_write_str(s: &str) {
DEBUG_WRITER.lock().write_str(s).unwrap();
}
/// Writes formatted data into the serial through sbi call..
pub fn debug_write_fmt(fmt: Arguments) {
DEBUG_WRITER.lock().write_fmt(fmt).unwrap();
}
/// Writes a string slice into the graphic console.
#[allow(unused_variables)]
pub fn graphic_console_write_str(s: &str) {

View File

@ -112,6 +112,53 @@ impl TrapReason {
_ => Self::GernelFault(scause.code()),
}
}
#[cfg(target_arch = "aarch64")]
pub fn from(esr: usize) -> Self {
// TODO: check if is right
use crate::{Fault, Info, Kind, Source, Syndrome};
use cortex_a::registers::{ESR_EL1, FAR_EL1};
use tock_registers::interfaces::Readable;
let info = Info {
source: Source::from(esr & 0xffff),
kind: Kind::from((esr >> 16) & 0xffff),
};
let esr = ESR_EL1.get() as u32;
match info.kind {
Kind::Synchronous => match Syndrome::from(esr) {
Syndrome::Breakpoint => Self::SoftwareBreakpoint,
Syndrome::Svc(_) => Self::Syscall,
Syndrome::DataAbort { kind: _, level: _ } => Self::PageFault(
FAR_EL1.get() as _,
MMUFlags::READ | MMUFlags::WRITE | MMUFlags::USER,
),
Syndrome::InstructionAbort {
kind: Fault::Permission,
level: _,
} => Self::PageFault(FAR_EL1.get() as _, MMUFlags::EXECUTE | MMUFlags::USER),
Syndrome::PCAlignmentFault | Syndrome::SpAlignmentFault => Self::UnalignedAccess,
_ => Self::GernelFault(esr as usize),
},
Kind::Irq => Self::Interrupt(
#[cfg(not(feature = "libos"))]
{
use crate::hal_fn::mem::phys_to_virt;
use crate::KCONFIG;
zcore_drivers::irq::gic_400::get_irq_num(
phys_to_virt(KCONFIG.gic_base + 0x1_0000),
phys_to_virt(KCONFIG.gic_base),
)
},
#[cfg(feature = "libos")]
{
// TODO: interrupt in libOS
usize::MAX
},
),
_ => Self::GernelFault(esr as usize),
}
}
}
/// User context saved on trap.
@ -168,6 +215,8 @@ impl UserContext {
self.0.general.ra = _ra;
} else if #[cfg(target_arch = "x86_64")] {
error!("Please set return addr via stack!");
} else if #[cfg(target_arch = "aarch64")] {
self.0.general.x30 = _ra;
} else {
unimplemented!("Unsupported arch!");
}
@ -198,7 +247,7 @@ impl UserContext {
if #[cfg(target_arch = "x86_64")] {
TrapReason::from(self.0.trap_num, self.0.error_code)
} else if #[cfg(target_arch = "aarch64")] {
unimplemented!() // ESR_EL1
TrapReason::from(self.0.trap_num)
} else if #[cfg(target_arch = "riscv64")] {
TrapReason::from(riscv::register::scause::read())
} else {

View File

@ -20,12 +20,13 @@ bitflags! {
const EXECUTE = 1 << 4;
const USER = 1 << 5;
const HUGE_PAGE = 1 << 6;
const DEVICE = 1 << 7;
const RXW = Self::READ.bits | Self::WRITE.bits | Self::EXECUTE.bits;
}
}
numeric_enum! {
#[repr(u32)]
#[derive(Debug, PartialEq, Clone, Copy)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
/// Generic cache policy.
pub enum CachePolicy {
Cached = 0,
@ -35,6 +36,164 @@ numeric_enum! {
}
}
cfg_if! {
if #[cfg(target_arch = "aarch64")] {
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Kind {
Synchronous = 0,
Irq = 1,
Fiq = 2,
SError = 3,
}
impl Kind {
pub fn from(x: usize) -> Kind {
match x {
x if x == Kind::Synchronous as usize => Kind::Synchronous,
x if x == Kind::Irq as usize => Kind::Irq,
x if x == Kind::Fiq as usize => Kind::Fiq,
x if x == Kind::SError as usize => Kind::SError,
_ => panic!("bad kind"),
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Source {
CurrentSpEl0 = 0,
CurrentSpElx = 1,
LowerAArch64 = 2,
LowerAArch32 = 3,
}
impl Source {
pub fn from(x: usize) -> Source {
match x {
x if x == Source::CurrentSpEl0 as usize => Source::CurrentSpEl0,
x if x == Source::CurrentSpElx as usize => Source::CurrentSpElx,
x if x == Source::LowerAArch64 as usize => Source::LowerAArch64,
x if x == Source::LowerAArch32 as usize => Source::LowerAArch32,
_ => panic!("bad kind"),
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct Info {
pub source: Source,
pub kind: Kind,
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Fault {
AddressSize,
Translation,
AccessFlag,
Permission,
Alignment,
TlbConflict,
Other(u8),
}
impl From<u32> for Fault {
fn from(val: u32) -> Fault {
use self::Fault::*;
// IFSC or DFSC bits (ref: D10.2.39, Page 2457~2464).
match val & 0b111100 {
0b000000 => AddressSize,
0b000100 => Translation,
0b001000 => AccessFlag,
0b001100 => Permission,
0b100000 => Alignment,
0b110000 => TlbConflict,
_ => Other((val & 0b111111) as u8),
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Syndrome {
Unknown,
WfiWfe,
McrMrc,
McrrMrrc,
LdcStc,
SimdFp,
Vmrs,
Mrrc,
IllegalExecutionState,
Svc(u16),
Hvc(u16),
Smc(u16),
MsrMrsSystem,
InstructionAbort { kind: Fault, level: u8 },
PCAlignmentFault,
DataAbort { kind: Fault, level: u8 },
SpAlignmentFault,
TrappedFpu,
SError,
Breakpoint,
Step,
Watchpoint,
Brk(u16),
Other(u32),
}
/// Converts a raw syndrome value (ESR) into a `Syndrome` (ref: D1.10.4, D10.2.39).
impl From<u32> for Syndrome {
fn from(esr: u32) -> Syndrome {
use self::Syndrome::*;
let ec = esr >> 26;
let iss = esr & 0xFFFFFF;
match ec {
0b000000 => Unknown,
0b000001 => WfiWfe,
0b000011 => McrMrc,
0b000100 => McrrMrrc,
0b000101 => McrMrc,
0b000110 => LdcStc,
0b000111 => SimdFp,
0b001000 => Vmrs,
0b001100 => Mrrc,
0b001110 => IllegalExecutionState,
0b010001 => Svc((iss & 0xFFFF) as u16),
0b010010 => Hvc((iss & 0xFFFF) as u16),
0b010011 => Smc((iss & 0xFFFF) as u16),
0b010101 => Svc((iss & 0xFFFF) as u16),
0b010110 => Hvc((iss & 0xFFFF) as u16),
0b010111 => Smc((iss & 0xFFFF) as u16),
0b011000 => MsrMrsSystem,
0b100000 | 0b100001 => InstructionAbort {
kind: Fault::from(iss),
level: (iss & 0b11) as u8,
},
0b100010 => PCAlignmentFault,
0b100100 | 0b100101 => DataAbort {
kind: Fault::from(iss),
level: (iss & 0b11) as u8,
},
0b100110 => SpAlignmentFault,
0b101000 => TrappedFpu,
0b101100 => TrappedFpu,
0b101111 => SError,
0b110000 => Breakpoint,
0b110001 => Breakpoint,
0b110010 => Step,
0b110011 => Step,
0b110100 => Watchpoint,
0b110101 => Watchpoint,
0b111100 => Brk((iss & 0xFFFF) as u16),
other => Other(other),
}
}
}
}
}
/// The smallest size of a page (4K).
pub const PAGE_SIZE: usize = super::vm::PageSize::Size4K as usize;

View File

@ -0,0 +1,82 @@
use crate::{config::MAX_CORE_NUM, utils::mpsc_queue::MpscQueue};
use alloc::vec::Vec;
const REASON_SIZE: usize = 16;
static mut IPI_REASON0: [IpiEntry; REASON_SIZE] = [0; REASON_SIZE];
static mut IPI_REASON1: [IpiEntry; REASON_SIZE] = [0; REASON_SIZE];
static mut IPI_REASON2: [IpiEntry; REASON_SIZE] = [0; REASON_SIZE];
static mut IPI_REASON3: [IpiEntry; REASON_SIZE] = [0; REASON_SIZE];
static mut IPI_REASON4: [IpiEntry; REASON_SIZE] = [0; REASON_SIZE];
static mut IPI_REASON5: [IpiEntry; REASON_SIZE] = [0; REASON_SIZE];
static mut IPI_REASON6: [IpiEntry; REASON_SIZE] = [0; REASON_SIZE];
static mut IPI_REASON7: [IpiEntry; REASON_SIZE] = [0; REASON_SIZE];
pub type IpiEntry = usize;
type IRQueue = MpscQueue<'static, IpiEntry>;
lazy_static::lazy_static! {
static ref IPI_QUEUE: [IRQueue; MAX_CORE_NUM] = [
IRQueue::new(unsafe {&mut IPI_REASON0} ),
IRQueue::new(unsafe {&mut IPI_REASON1} ),
IRQueue::new(unsafe {&mut IPI_REASON2} ),
IRQueue::new(unsafe {&mut IPI_REASON3} ),
IRQueue::new(unsafe {&mut IPI_REASON4} ),
IRQueue::new(unsafe {&mut IPI_REASON5} ),
IRQueue::new(unsafe {&mut IPI_REASON6} ),
IRQueue::new(unsafe {&mut IPI_REASON7} ),
];
}
pub(crate) fn ipi_queue(cpuid: usize) -> &'static IRQueue {
&IPI_QUEUE[cpuid]
}
pub(crate) fn ipi_reason() -> Vec<usize> {
let cpu_id = crate::cpu::cpu_id() as usize;
let queue = ipi_queue(cpu_id);
queue.consume_entrys().iter().map(|entry| entry.1).collect()
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum IpiReason {
Invalid,
MockBlock { block_info: usize },
TlbShutdown { vpn: usize }, // unused
}
/// usize : 64bit
/// | type reason : 4bit | ipi info : 60bit |
///
/// MockBlock info : 60bit
/// | reserved : 60 bit |
///
const TYPE_SHIFT: usize = 60;
const TYPE_INVALID: usize = 0x0;
const TYPE_MOCK_BLOCK: usize = 0x1;
const TYPE_TLB_SHUTDOWN: usize = 0x2;
impl From<IpiEntry> for IpiReason {
fn from(r: IpiEntry) -> Self {
let ipi_type = r >> TYPE_SHIFT;
let ipi_info = r & 0x000FFFFFFFFFFFFF;
match ipi_type {
TYPE_MOCK_BLOCK => Self::MockBlock {
block_info: ipi_info,
},
TYPE_TLB_SHUTDOWN => Self::TlbShutdown { vpn: ipi_info },
_ => Self::Invalid,
}
}
}
impl From<IpiReason> for IpiEntry {
fn from(reason: IpiReason) -> Self {
match reason {
IpiReason::MockBlock { block_info: info } => (TYPE_MOCK_BLOCK << TYPE_SHIFT) | info,
IpiReason::TlbShutdown { vpn: info } => (TYPE_TLB_SHUTDOWN << TYPE_SHIFT) | info,
IpiReason::Invalid => 0,
}
}
}

View File

@ -8,4 +8,5 @@ pub(super) mod vm;
pub mod addr;
pub mod console;
pub mod context;
pub mod ipi;
pub mod user;

View File

@ -12,6 +12,7 @@ use core::{
// 来自用户空间的裸指针
/// Raw pointer from user land.
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct UserPtr<T, P: Policy>(*mut T, PhantomData<P>);
// 标识用户指针功能的基特征。
@ -177,6 +178,7 @@ impl<T, P: Read> UserPtr<T, P> {
/// Copies elements into a new [`Vec`].
///
/// The `len` argument is the number of **elements**, not the number of bytes.
#[allow(clippy::uninit_vec)]
pub fn read_array(&self, len: usize) -> Result<Vec<T>> {
if len == 0 {
Ok(Vec::default())
@ -277,24 +279,39 @@ impl<P: Write> UserPtr<u8, P> {
}
}
#[derive(Debug)]
#[repr(C)]
pub struct IoVec<P: 'static + Policy> {
pub struct IoVec<P: Policy> {
/// Starting address
ptr: UserPtr<u8, P>,
/// Number of bytes to transfer
len: usize,
}
impl<P: Policy> core::fmt::Debug for IoVec<P> {
fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
write!(f, "IoVec ptr:{:?} len :{:?}", self.ptr.0, self.len)
}
}
pub type IoVecIn = IoVec<In>;
pub type IoVecOut = IoVec<Out>;
pub type IoVecsOut = IoVecs<Out>;
/// A valid IoVecs request from user
#[derive(Debug)]
pub struct IoVecs<P: 'static + Policy> {
vec: Vec<IoVec<P>>,
}
impl<P: Policy> Debug for IoVecs<P> {
fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
write!(f, "IoVec len :{:?}", self.vec.len())
}
}
impl IoVecs<Out> {
pub fn new(iov_ptr: UserInPtr<IoVec<Out>>, iov_count: usize) -> IoVecs<Out> {
iov_ptr.read_iovecs(iov_count).unwrap()
}
}
impl<P: Policy> UserInPtr<IoVec<P>> {
pub fn read_iovecs(&self, count: usize) -> Result<IoVecs<P>> {
if self.0.is_null() {

View File

@ -47,9 +47,10 @@ pub struct Features {
impl VdsoConstants {
/// Set version string.
pub fn set_version_string(&mut self, s: &str) {
let len = s.len().min(64);
let bytes = s.as_bytes();
let len = bytes.len().min(64);
self.version_string_len = len as u64;
self.version_string.0[..len].copy_from_slice(s.as_bytes());
self.version_string.0[..len].copy_from_slice(&bytes[..len]);
}
}

View File

@ -145,7 +145,11 @@ pub trait GenericPageTable: Sync + Send {
fn unmap_cont(&mut self, start_vaddr: VirtAddr, size: usize) -> PagingResult {
assert!(is_aligned(start_vaddr));
assert!(is_aligned(size));
debug!("unmap_cont: {:#x?}", start_vaddr..start_vaddr + size);
debug!(
"{:#x?} unmap_cont: {:#x?}",
self.table_phys(),
start_vaddr..start_vaddr + size
);
let mut vaddr = start_vaddr;
let end_vaddr = vaddr + size;
while vaddr < end_vaddr {

View File

@ -7,3 +7,5 @@ pub(crate) static KCONFIG: InitOnce<KernelConfig> = InitOnce::new_with_default(K
#[cfg(not(feature = "libos"))]
pub(crate) static KCONFIG: InitOnce<KernelConfig> = InitOnce::new();
pub const MAX_CORE_NUM: usize = 8;

View File

@ -186,4 +186,10 @@ mod drivers_ffi {
extern "C" fn drivers_virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
vaddr - KCONFIG.phys_to_virt_offset
}
use crate::hal_fn::timer::timer_now;
#[no_mangle]
extern "C" fn drivers_timer_now_as_micros() -> u64 {
timer_now().as_micros() as _
}
}

View File

@ -1,5 +1,5 @@
use alloc::{boxed::Box, string::String, vec::Vec};
use core::{future::Future, ops::Range, time::Duration};
use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
use core::{any::Any, future::Future, ops::Range, time::Duration};
use crate::drivers::prelude::{IrqHandler, IrqPolarity, IrqTriggerMode};
use crate::{common, HalResult, KernelConfig, KernelHandler, PhysAddr, VirtAddr};
@ -18,15 +18,12 @@ hal_fn_def! {
}
/// Initialize the primary CPU at an early stage (before the physical frame allocator).
#[doc(cfg(feature = "smp"))]
pub fn primary_init_early(cfg: KernelConfig, handler: &'static impl KernelHandler) {}
/// The main part of the primary CPU initialization.
#[doc(cfg(feature = "smp"))]
pub fn primary_init();
/// Initialize the secondary CPUs.
#[doc(cfg(feature = "smp"))]
pub fn secondary_init() {}
}
@ -45,7 +42,7 @@ hal_fn_def! {
/// Physical memory operations.
pub mod mem: common::mem {
/// Convert physical address to virtual address.
pub(crate) fn phys_to_virt(paddr: PhysAddr) -> VirtAddr;
pub fn phys_to_virt(paddr: PhysAddr) -> VirtAddr;
/// Convert virtual address to physical address.
pub fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr;
@ -137,6 +134,10 @@ hal_fn_def! {
/// NULL handler will effectively unregister a handler for a given msi_id within the
/// block.
pub fn msi_register_handler(block: Range<usize>, msi_id: usize, handler: IrqHandler) -> HalResult;
pub fn send_ipi(cpuid: usize, reason: usize) -> HalResult;
pub fn ipi_reason() -> Vec<usize>;
}
pub mod console {
@ -149,10 +150,10 @@ hal_fn_def! {
pub fn spawn(future: impl Future<Output = ()> + Send + 'static);
/// Set tid and pid of current task.
pub fn set_tid(tid: u64, pid: u64);
pub fn set_current_thread(thread: Option<Arc<dyn Any + Send + Sync>>) {}
/// Get tid and pid of current task.
pub fn get_tid() -> (u64, u64);
pub fn get_current_thread() -> Option<Arc<dyn Any + Send + Sync>> { None }
}
/// Time and clock functions.

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