diff --git a/.gitignore b/.gitignore
index 99110024b..68149e260 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,7 +3,6 @@
!.cargo/*
**/target
-*.bin
*.img
/ignored
diff --git a/Makefile b/Makefile
index 80018258f..1bac0efc8 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,7 @@
# Makefile for top level of zCore
ARCH ?= x86_64
+XTASK ?= 1
STRIP := $(ARCH)-linux-musl-strip
export PATH=$(shell printenv PATH):$(CURDIR)/ignored/target/$(ARCH)/$(ARCH)-linux-musl-cross/bin/
@@ -21,7 +22,13 @@ 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:
@@ -35,22 +42,18 @@ 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:
cargo check-style
-riscv-rootfs:
- @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
-
-riscv-image: riscv-rootfs
- @echo building riscv.img
- @rcore-fs-fuse zCore/riscv64.img rootfs/riscv zip
- @qemu-img resize -f raw zCore/riscv64.img +5M
-
# build and open project document
doc:
cargo doc --open
diff --git a/docs/README-C910.md b/docs/README-C910.md
new file mode 100644
index 000000000..2f2251a15
--- /dev/null
+++ b/docs/README-C910.md
@@ -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`。
+进入配置好网络的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. 系统初步分析并制作系统镜像
+
+
+
+C910 Light开发板如上图,在取得C910 Light开发板后,先按照官方的用户手册了解基本的硬件组件,以及电源和串口等接口的接线。
+用户手册:https://gitee.com/thead-yocto/documents/blob/master/en/user_guide/T-Head%20Yeying1520%20Yocto%20User%20Guide.pdf
+
+电源接上,以及串口连接到host机后,可以看到有四个串口`/dev/ttyUSBX`,调试用串口是,host机连上该串口,并在启动u-boot时按任意键可进入命令行模式
+u-boot命令行模式上,可以连接通有线网络,并通过tftp协议加载待启动的操作系统镜像。
+
+```
+# 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
+# setenv serverip
+
+```
+
+在这里一开始尝试fu740板子的zCore系统镜像制作以及tftp启动模式, 在u-boot命令行中配置开发板IP地址和服务器IP地址,通过tftp协议加载系统镜像,最后通过bootm运行镜像;
+
+其他正常,但这样在引导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的版本不同,导致对系统镜像格式的识别不一致。
+在fu740板子上的zCore系统镜像是基于`.its`脚本的新`FIT image`;
+而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
+
+
+
+通过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 {
+ 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 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`,打上patch:https://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的过程,找到一些参考:
+
+
+
+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中通用存在。
+
+
+
+zCore中先尝试把内核的`CACHE`,`SHARE`,`BUF`这些位在构建内核页表时置位上,启动发现问题依旧,依然停在切换页表`switch table`之后,原因不详???
+
+既然基于RISCV标准进行自定义拓展的位,理论上应该是可以关闭的吧,于是继续在芯片手册中查找,果然在拓展状态寄存器`MXSTATUS`中找到了相应的设置位`MAEE`
+
+
+
+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中设置对应位;
+
+
+
+于是直接关闭虚拟内存的页表项拓展属性,设置`MAEE = 0`,果然之前停在页表切换处`switch table`的问题通过了。zCore可以继续往下执行开始解析设备树的各node节点,后面接着会遇到设备地址过高,导致在处理解析到的node节点地址时出错...
+
+### 4. 页表项PTE的拓展属性设置MAEE于CR1825板子的尝试
+
+之前一次与DF交流CR1825目前遇到的BUG情况时,一开始有提议说可能内核的`.BSS`段可能未清除干净。
+
+因为在去年刚把增加了riscv支持的zCore移植到D1时,也出现过,spin原子指令死锁的问题,这个问题当时请教的JYK童鞋后,给思路原来`.bss`段没clear干净,导致未初始化时的原子变量存在了随机值,持续死锁。
+
+
+
+
+
+不过,这个清除`.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帮忙远程验证,幸运地原子锁的问题也通过了,的确与平头哥的拓展页表项有关!
+
+
+
+
+
+之后在群里与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:
+
+
\ No newline at end of file
diff --git a/docs/README-D1.md b/docs/README-D1.md
index 191dcaf47..c455a8b32 100644
--- a/docs/README-D1.md
+++ b/docs/README-D1.md
@@ -1,6 +1,7 @@
-# zCore on riscv64 for D1
+# 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 开发板为例。
@@ -59,7 +60,7 @@ make run LINUX=1 ARCH=riscv64 PLATFORM=d1 MODE=release
sudo xfel exec 0x40000000
```
-## 引导运行
+### 引导运行
zCore 成功引导后, OpenSBI 会将 dtb 加载到高地址 `0x5ff00000`,运行如下所示:
diff --git a/docs/img/c906-amo-1.jpg b/docs/img/c906-amo-1.jpg
new file mode 100644
index 000000000..a5325d333
Binary files /dev/null and b/docs/img/c906-amo-1.jpg differ
diff --git a/docs/img/c906-amo-2.jpg b/docs/img/c906-amo-2.jpg
new file mode 100644
index 000000000..622652310
Binary files /dev/null and b/docs/img/c906-amo-2.jpg differ
diff --git a/docs/img/c906-clear-bss.jpeg b/docs/img/c906-clear-bss.jpeg
new file mode 100644
index 000000000..538444221
Binary files /dev/null and b/docs/img/c906-clear-bss.jpeg differ
diff --git a/docs/img/c910-jtag.jpg b/docs/img/c910-jtag.jpg
new file mode 100644
index 000000000..0805ed045
Binary files /dev/null and b/docs/img/c910-jtag.jpg differ
diff --git a/docs/img/c910-light.jpeg b/docs/img/c910-light.jpeg
new file mode 100644
index 000000000..e0fa57152
Binary files /dev/null and b/docs/img/c910-light.jpeg differ
diff --git a/docs/img/c910-linux-pg.png b/docs/img/c910-linux-pg.png
new file mode 100644
index 000000000..b3225a8e3
Binary files /dev/null and b/docs/img/c910-linux-pg.png differ
diff --git a/docs/img/c910-maee.jpeg b/docs/img/c910-maee.jpeg
new file mode 100644
index 000000000..4ff3d194e
Binary files /dev/null and b/docs/img/c910-maee.jpeg differ
diff --git a/docs/img/c910-mxstatus.png b/docs/img/c910-mxstatus.png
new file mode 100644
index 000000000..09e10ee51
Binary files /dev/null and b/docs/img/c910-mxstatus.png differ
diff --git a/docs/img/c910-pte-flags.png b/docs/img/c910-pte-flags.png
new file mode 100644
index 000000000..ffcef9542
Binary files /dev/null and b/docs/img/c910-pte-flags.png differ
diff --git a/docs/img/c910-run-uart.png b/docs/img/c910-run-uart.png
new file mode 100644
index 000000000..53a80d0e4
Binary files /dev/null and b/docs/img/c910-run-uart.png differ
diff --git a/docs/img/c910-zcore-run.png b/docs/img/c910-zcore-run.png
new file mode 100644
index 000000000..748e6f5e7
Binary files /dev/null and b/docs/img/c910-zcore-run.png differ
diff --git a/kernel-hal/Cargo.toml b/kernel-hal/Cargo.toml
index bea489443..e48c087cf 100644
--- a/kernel-hal/Cargo.toml
+++ b/kernel-hal/Cargo.toml
@@ -24,6 +24,8 @@ loopback = ["zcore-drivers/loopback", "no-pci"]
# 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
diff --git a/kernel-hal/src/bare/arch/riscv/drivers.rs b/kernel-hal/src/bare/arch/riscv/drivers.rs
index 58805d07c..de804d500 100644
--- a/kernel-hal/src/bare/arch/riscv/drivers.rs
+++ b/kernel-hal/src/bare/arch/riscv/drivers.rs
@@ -13,7 +13,12 @@ struct IoMapperImpl;
impl IoMapper for IoMapperImpl {
fn query_or_map(&self, paddr: PhysAddr, size: usize) -> Option {
- 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 {
diff --git a/kernel-hal/src/bare/arch/riscv/sbi.rs b/kernel-hal/src/bare/arch/riscv/sbi.rs
index e378fa2ce..a0e5d9d35 100644
--- a/kernel-hal/src/bare/arch/riscv/sbi.rs
+++ b/kernel-hal/src/bare/arch/riscv/sbi.rs
@@ -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 {
+ 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) {
diff --git a/kernel-hal/src/bare/arch/riscv/vm.rs b/kernel-hal/src/bare/arch/riscv/vm.rs
index 97dd586af..3bb1f0d47 100644
--- a/kernel-hal/src/bare/arch/riscv/vm.rs
+++ b/kernel-hal/src/bare/arch/riscv/vm.rs
@@ -70,6 +70,18 @@ fn init_kernel_page_table() -> PagingResult {
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)),
@@ -78,6 +90,7 @@ fn init_kernel_page_table() -> PagingResult {
)?;
// 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),
diff --git a/prebuilt/firmware/riscv/c910_fw_dynamic.bin b/prebuilt/firmware/riscv/c910_fw_dynamic.bin
new file mode 100755
index 000000000..b6b55a215
Binary files /dev/null and b/prebuilt/firmware/riscv/c910_fw_dynamic.bin differ
diff --git a/zCore/Cargo.toml b/zCore/Cargo.toml
index 79647cd60..ea39f7c89 100644
--- a/zCore/Cargo.toml
+++ b/zCore/Cargo.toml
@@ -53,6 +53,8 @@ libos = [
# Run on Allwinner d1
board-d1 = ["link-user-img", "no-pci", "kernel-hal/allwinner-drivers"]
+# T-HEAD C910 Light val board
+board-c910light = ["link-user-img", "kernel-hal/board-c910light", "no-pci"]
# Run on u740
board-fu740 = ["link-user-img", "kernel-hal/fu740-drivers"]
diff --git a/zCore/Makefile b/zCore/Makefile
index 25875ce33..456c66ac7 100644
--- a/zCore/Makefile
+++ b/zCore/Makefile
@@ -102,6 +102,8 @@ else
else ifeq ($(PLATFORM), fu740)
SMP := 5
features += board-fu740
+ else ifeq ($(PLATFORM), c910light)
+ features += board-c910light link-user-img
endif
else ifeq ($(ARCH), aarch64)
ifeq ($(PLATFORM), raspi4b)
@@ -247,6 +249,10 @@ ifeq ($(PLATFORM), fu740)
gzip -9 -cvf $(build_path)/zcore.bin > ./zcore.bin.gz
mkimage -f ../prebuilt/firmware/riscv/fu740_fdt.its ./zcore-fu740.itb
@echo 'Build zcore-fu740.itb FIT-uImage done'
+else ifeq ($(PLATFORM), c910light)
+ mkimage -A riscv -O linux -C none -T kernel -a 0x200000 -e 0x200000 \
+ -n "zCore for c910" \
+ -d $(build_path)/zcore.bin uImageC910
endif
run: build justrun
debug: build debugrun
diff --git a/zCore/build.rs b/zCore/build.rs
new file mode 100644
index 000000000..c07f8f235
--- /dev/null
+++ b/zCore/build.rs
@@ -0,0 +1,28 @@
+use std::io::Write;
+
+fn main() {
+ if std::env::var("TARGET").unwrap().contains("riscv64") {
+ let board = std::env::var("PLATFORM");
+ let kernel_base_addr: u64 = if board.map_or(false, |x| x.contains("c910light")) {
+ 0xffffffe000200000
+ } else {
+ 0xffffffc080200000
+ };
+
+ let mut fout = std::fs::File::create("src/platform/riscv/kernel-vars.ld").unwrap();
+ writeln!(fout, "/* Generated by build.rs. DO NOT EDIT. */").unwrap();
+ writeln!(
+ fout,
+ "PROVIDE_HIDDEN(BASE_ADDRESS = {:#x});",
+ kernel_base_addr
+ )
+ .unwrap();
+ }
+
+ // 如果需要链接 rootfs 镜像,将镜像路径设置到环境变量
+ #[cfg(feature = "link-user-img")]
+ println!(
+ "cargo:rustc-env=USER_IMG=zCore/{}.img",
+ std::env::var("TARGET").unwrap()
+ );
+}
diff --git a/zCore/src/memory.rs b/zCore/src/memory.rs
index 83759eaa5..d0de3fd3f 100644
--- a/zCore/src/memory.rs
+++ b/zCore/src/memory.rs
@@ -32,7 +32,7 @@ const PAGE_BITS: usize = 12;
/// | qemu,virt SMP 1 | 16 KiB
/// | qemu,virt SMP 4 | 32 KiB
/// | allwinner,nezha | 256 KiB
-static mut MEMORY: [u8; 256 << 10] = [0u8; 256 << 10];
+static mut MEMORY: [u8; 2 * 1024 * 1024] = [0u8; 2 * 1024 * 1024];
unsafe impl GlobalAlloc for LockedHeap {
#[inline]
diff --git a/zCore/src/platform/riscv/boot.asm b/zCore/src/platform/riscv/boot.asm
new file mode 100644
index 000000000..6519eb556
--- /dev/null
+++ b/zCore/src/platform/riscv/boot.asm
@@ -0,0 +1,99 @@
+.equ STACK_MAX, 4096 * 16
+.equ STACK_MAX_HARTS, 8
+
+ .section .text.entry
+ .globl _start
+_start:
+ #关中断
+ csrw sie, zero
+ csrw sip, zero
+
+ #关闭mmu
+ #csrw satp, zero
+
+ #BSS节清零
+ la t0, sbss
+ la t1, ebss
+ bgeu t0, t1, primary_hart
+
+clear_bss_loop:
+ # sd: store double word (64 bits)
+ sd zero, (t0)
+ addi t0, t0, 8
+ bltu t0, t1, clear_bss_loop
+
+primary_hart:
+ call init_vm
+ la t0, primary_rust_main
+ la t1, PHY_MEM_OFS
+ ld t1, (t1)
+ add t0, t0, t1
+ jr t0
+
+.globl secondary_hart_start
+secondary_hart_start:
+ csrw sie, zero
+ csrw sip, zero
+ call init_vm
+ la t0, secondary_rust_main
+ la t1, PHY_MEM_OFS
+ ld t1, (t1)
+ add t0, t0, t1
+ jr t0
+
+init_vm:
+ #获取页表的物理地址
+ la t0, boot_page_table_sv39
+
+ #右移12位,变为satp的PPN
+ srli t0, t0, 12
+
+ #satp的MODE设为Sv39
+ li t1, 8 << 60
+
+ #写satp
+ or t0, t0, t1
+
+ #刷新TLB
+ sfence.vma
+
+ csrw satp, t0
+
+ #此时在虚拟内存空间,设置sp为虚拟地址
+ li t0, STACK_MAX
+ mul t0, t0, a0
+
+ la t1, boot_stack_top
+ la t2, PHY_MEM_OFS
+ ld t2, (t2)
+ add sp, t1, t2
+
+ #计算多个核的sp偏移
+ sub sp, sp, t0
+ ret
+
+ .section .data
+ .align 12 #12位对齐
+boot_page_table_sv39:
+ #1G的一个大页: 0x00000000_00000000 --> 0x00000000
+ #1G的一个大页: 0x00000000_80000000 --> 0x80000000
+ #1G的一个大页: 0xffffffe0_00000000 --> 0x00000000
+ #1G的一个大页: 0xffffffe0_80000000 --> 0x80000000
+
+ .quad (0 << 10) | 0xef
+ .zero 8
+ .quad (0x80000 << 10) | 0xef
+
+ .zero 8 * 381
+ .quad (0 << 10) | 0xef
+ .zero 8
+ .quad (0x80000 << 10) | 0xef
+ .zero 8 * 125
+
+ .section .bss.stack
+ .align 12
+ .global boot_stack
+boot_stack:
+ .space STACK_MAX * STACK_MAX_HARTS
+ .global boot_stack_top
+boot_stack_top:
diff --git a/zCore/src/platform/riscv/entry64.rs b/zCore/src/platform/riscv/entry64.rs
new file mode 100644
index 000000000..b05b5e83c
--- /dev/null
+++ b/zCore/src/platform/riscv/entry64.rs
@@ -0,0 +1,106 @@
+global_asm!(include_str!("boot.asm"));
+
+use core::arch::{asm, global_asm};
+use core::str::FromStr;
+use kernel_hal::arch::sbi::{hart_start, send_ipi, SBI_SUCCESS};
+use kernel_hal::KernelConfig;
+
+#[no_mangle]
+pub static PHY_MEM_OFS: usize = consts::KERNEL_BASE - consts::PHYS_MEMORY_BASE;
+
+pub mod consts {
+ cfg_if! {
+ if #[cfg(feature = "board-fu740")] {
+ pub const KERNEL_BASE: usize = 0xFFFF_FFE0_8000_0000;
+ pub const PHYS_MEMORY_BASE: usize = 0x8000_0000;
+ } else if #[cfg(feature = "board-c910light")] {
+ pub const KERNEL_BASE: usize = 0xffffffe0_00200000;
+ pub const PHYS_MEMORY_BASE: usize = 0x200000;
+ }
+ }
+ #[allow(dead_code)]
+ pub const KERNEL_HEAP_SIZE: usize = 80 * 1024 * 1024;
+ /// Get HART number from the environment variable
+ pub const SMP: &str = core::env!("SMP");
+
+ #[inline]
+ pub fn phys_to_virt_offset() -> usize {
+ KERNEL_BASE - PHYS_MEMORY_BASE
+ }
+}
+
+extern "C" {
+ fn secondary_hart_start();
+}
+
+#[no_mangle]
+pub extern "C" fn primary_rust_main(hartid: usize, device_tree_paddr: usize) -> ! {
+ unsafe {
+ asm!("mv tp, {0}", in(reg) hartid);
+
+ let mut sstatus: usize;
+ asm!("csrr {0}, sstatus", out(reg) sstatus);
+ sstatus |= 1 << 18;
+ asm!("csrw sstatus, {0}", in(reg) sstatus);
+
+ println!(
+ "\nzCore rust_main(hartid: {}, device_tree_paddr: {:#x}) sstatus={:#x}\n",
+ hartid, device_tree_paddr, sstatus
+ );
+ };
+
+ println!(" ____");
+ println!(" ____/ ___|___ _ __ ___");
+ println!("|_ / | / _ \\| '__/ _ \\");
+ println!(" / /| |__| (_) | | | __/");
+ println!("/___|\\____\\___/|_| \\___|");
+ println!();
+
+ for id in 0..usize::from_str(consts::SMP).expect("can't parse SMP as usize.") {
+ #[cfg(feature = "board-fu740")]
+ if id == 0 {
+ continue;
+ }
+
+ if id != hartid {
+ println!("hart{id} is booting");
+ let err_code = hart_start(
+ id,
+ secondary_hart_start as usize - PHY_MEM_OFS, // cal physical address
+ 0,
+ );
+ if err_code != SBI_SUCCESS {
+ panic!("start hart{} failed. error code={}", id, err_code);
+ }
+
+ let hart_mask: usize = 1 << id;
+ let err_code = send_ipi(&hart_mask as *const _ as usize);
+ if err_code != SBI_SUCCESS {
+ panic!("send ipi to hart{} failed. error code={}", id, err_code);
+ }
+ } else {
+ println!("hart{id} is the primary hart");
+ }
+ }
+
+ let config = KernelConfig {
+ phys_to_virt_offset: PHY_MEM_OFS,
+ dtb_paddr: device_tree_paddr,
+ dtb_size: 2 * 1024 * 1024,
+ };
+ crate::primary_main(config);
+ unreachable!()
+}
+
+// Don't print in this function and use console_write_early if necessary
+#[no_mangle]
+pub extern "C" fn secondary_rust_main(hartid: usize) -> ! {
+ unsafe {
+ asm!("mv tp, {0}", in(reg) hartid);
+ let mut sstatus: usize;
+ asm!("csrr {0}, sstatus", out(reg) sstatus);
+ sstatus |= 1 << 18; // set SUM=1
+ asm!("csrw sstatus, {0}", in(reg) sstatus);
+ };
+ crate::secondary_main();
+}
diff --git a/zCore/src/platform/riscv/linker.ld b/zCore/src/platform/riscv/linker.ld
index 26bf1dd56..c7ee8b642 100644
--- a/zCore/src/platform/riscv/linker.ld
+++ b/zCore/src/platform/riscv/linker.ld
@@ -1,8 +1,9 @@
OUTPUT_ARCH(riscv)
ENTRY(_start)
+INCLUDE zCore/src/platform/riscv/kernel-vars.ld
SECTIONS
{
- . = 0xffffffc080200000;
+ . = BASE_ADDRESS;
start = .;
.text : {
diff --git a/zCore/src/platform/riscv/mod.rs b/zCore/src/platform/riscv/mod.rs
index b4560191b..874879cf5 100644
--- a/zCore/src/platform/riscv/mod.rs
+++ b/zCore/src/platform/riscv/mod.rs
@@ -1,3 +1,9 @@
+cfg_if! {
+ if #[cfg(feature = "board-c910light")] {
+mod entry64;
+pub use entry64::consts;
+ } else {
mod boot_page_table;
pub mod consts;
mod entry;
+ }}
diff --git a/zCore/zcore-fu740.itb b/zCore/zcore-fu740.itb
deleted file mode 100644
index 614139c00..000000000
Binary files a/zCore/zcore-fu740.itb and /dev/null differ
diff --git a/zCore/zcore.bin.gz b/zCore/zcore.bin.gz
deleted file mode 100644
index d2ee5a04f..000000000
Binary files a/zCore/zcore.bin.gz and /dev/null differ