feat: 支持在rv64下,运行rust编写的helloworld程序 (#1125)

* 添加 riscv_rust_init 这个helloworld程序

Signed-off-by: longjin <longjin@DragonOS.org>

* feat: 支持在riscv下启动rust编写的hello world程序

TODO: 支持sys ppoll

Signed-off-by: longjin <longjin@DragonOS.org>

* chore: 更新构建容器版本至v1.9

Signed-off-by: longjin <longjin@DragonOS.org>

* 1

---------

Signed-off-by: longjin <longjin@DragonOS.org>
This commit is contained in:
LoGin 2025-03-30 01:28:41 +08:00 committed by GitHub
parent 55833537f1
commit 03015e2559
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 152 additions and 38 deletions

View File

@ -11,14 +11,14 @@ jobs:
name: Format check ${{ matrix.arch }}
runs-on: ubuntu-latest
continue-on-error: true
container: dragonos/dragonos-dev:v1.8
container: dragonos/dragonos-dev:v1.9
strategy:
matrix:
arch: [x86_64, riscv64]
steps:
- run: echo "Running in dragonos/dragonos-dev:v1.8"
- run: echo "Running in dragonos/dragonos-dev:v1.9"
- uses: actions/checkout@v3
- name: Format check
@ -35,14 +35,14 @@ jobs:
name: Kernel static test ${{ matrix.arch }}
runs-on: ubuntu-latest
continue-on-error: true
container: dragonos/dragonos-dev:v1.8
container: dragonos/dragonos-dev:v1.9
strategy:
matrix:
arch: [x86_64, riscv64]
steps:
- run: echo "Running in dragonos/dragonos-dev:v1.8"
- run: echo "Running in dragonos/dragonos-dev:v1.9"
- uses: actions/checkout@v3
@ -55,10 +55,10 @@ jobs:
build-x86_64:
runs-on: ubuntu-latest
container: dragonos/dragonos-dev:v1.8
container: dragonos/dragonos-dev:v1.9
steps:
- run: echo "Running in dragonos/dragonos-dev:v1.8"
- run: echo "Running in dragonos/dragonos-dev:v1.9"
- uses: actions/checkout@v3
- name: build the DragonOS
@ -77,10 +77,10 @@ jobs:
build-riscv64:
runs-on: ubuntu-latest
container: dragonos/dragonos-dev:v1.8
container: dragonos/dragonos-dev:v1.9
steps:
- run: echo "Running in dragonos/dragonos-dev:v1.8"
- run: echo "Running in dragonos/dragonos-dev:v1.9"
- uses: actions/checkout@v3
with:

2
kernel/Cargo.lock generated
View File

@ -1839,7 +1839,7 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "virtio-drivers"
version = "0.7.2"
source = "git+https://git.mirrors.dragonos.org.cn/DragonOS-Community/virtio-drivers?rev=f91c807965#f91c8079658dbc7cc230bf041325b94a0ab2e301"
source = "git+https://git.mirrors.dragonos.org.cn/DragonOS-Community/virtio-drivers?rev=415ab38ff9#415ab38ff99f3c8e150269c04f65d684ba9d1365"
dependencies = [
"bitflags 2.9.0",
"log",

View File

@ -151,10 +151,18 @@ fn do_trap_insn_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError
let vaddr = trap_frame.badaddr;
let cause = trap_frame.cause;
let epc = trap_frame.epc;
error!(
"riscv64_do_irq: do_insn_page_fault vaddr: {:#x}, cause: {:?} epc: {:#x}",
vaddr, cause, epc
);
if trap_frame.is_from_user() {
error!(
"riscv64_do_irq: do_trap_insn_page_fault(user mode): epc: {epc:#x}, vaddr={:#x}, cause={:?}",
vaddr, cause
);
} else {
panic!(
"riscv64_do_irq: do_trap_insn_page_fault(kernel mode): epc: {epc:#x}, vaddr={:#x}, cause={:?}",
vaddr, cause
);
}
loop {
spin_loop();
}
@ -165,10 +173,17 @@ fn do_trap_load_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError
let vaddr = trap_frame.badaddr;
let cause = trap_frame.cause;
let epc = trap_frame.epc;
error!(
"riscv64_do_irq: do_trap_load_page_fault: epc: {epc:#x}, vaddr={:#x}, cause={:?}",
vaddr, cause
);
if trap_frame.is_from_user() {
error!(
"riscv64_do_irq: do_trap_load_page_fault(user mode): epc: {epc:#x}, vaddr={:#x}, cause={:?}",
vaddr, cause
);
} else {
panic!(
"riscv64_do_irq: do_trap_load_page_fault(kernel mode): epc: {epc:#x}, vaddr={:#x}, cause={:?}",
vaddr, cause
);
}
loop {
spin_loop();

View File

@ -649,7 +649,7 @@ pub(super) fn do_plic_irq(trap_frame: &mut TrapFrame) {
if claim == 0 {
break;
}
debug!("plic: claim: {claim:?}");
// debug!("plic: claim: {claim:?}");
let hwirq = HardwareIrqNumber::new(claim);
if let Err(e) = GenericIrqHandler::handle_domain_irq(domain.clone(), hwirq, trap_frame) {

View File

@ -321,6 +321,7 @@ impl KernelCmdlineManager {
continue;
}
log::debug!("cmdline: argument: {:?} ", argument);
let (node, option, value) = match self.split_arg(argument) {
Some(v) => v,
None => continue,

View File

@ -128,6 +128,7 @@ fn try_to_run_init_process(
ext_args: &Option<&str>,
trap_frame: &mut TrapFrame,
) -> Result<(), SystemError> {
log::debug!("Trying to run init process at {:?}", path);
let mut args_to_insert = alloc::vec::Vec::new();
args_to_insert.push(CString::new(path).unwrap());

View File

@ -885,6 +885,11 @@ impl Syscall {
Self::poll(fds, nfds, timeout)
}
SYS_PPOLL => {
log::warn!("SYS_PPOLL has not yet been implemented");
Ok(0)
}
SYS_SETPGID => {
warn!("SYS_SETPGID has not yet been implemented");
Ok(0)

View File

@ -1 +1 @@
v1.8
v1.9

View File

@ -249,6 +249,8 @@ rustInstall() {
rustup target add riscv64imac-unknown-none-elf --toolchain $RUST_VERSION-riscv64gc-unknown-linux-gnu
rustup target add riscv64gc-unknown-none-elf --toolchain $RUST_VERSION_OLD-riscv64gc-unknown-linux-gnu
rustup target add riscv64imac-unknown-none-elf --toolchain $RUST_VERSION_OLD-riscv64gc-unknown-linux-gnu
rustup target add riscv64gc-unknown-linux-musl --toolchain $RUST_VERSION-riscv64gc-unknown-linux-gnu
rustup target add riscv64gc-unknown-linux-musl --toolchain $RUST_VERSION_OLD-riscv64gc-unknown-linux-gnu
rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
rustup component add rust-src

View File

@ -1,6 +1,6 @@
docker rm -f dragonos-build || echo "No existed container"
cpu_count=$(cat /proc/cpuinfo |grep "processor"|wc -l)
docker run --rm --privileged=true --cap-add SYS_ADMIN --cap-add MKNOD -v $(pwd):/data -v /dev:/dev -v dragonos-build-cargo:/root/.cargo/registry --name dragonos-build -i dragonos/dragonos-dev:v1.8 bash << EOF
docker run --rm --privileged=true --cap-add SYS_ADMIN --cap-add MKNOD -v $(pwd):/data -v /dev:/dev -v dragonos-build-cargo:/root/.cargo/registry --name dragonos-build -i dragonos/dragonos-dev:v1.9 bash << EOF
source ~/.cargo/env
source ~/.bashrc
cd /data

View File

@ -85,7 +85,10 @@ QEMU_ACCELARATE=""
QEMU_ARGUMENT=" -no-reboot "
QEMU_DEVICES=""
KERNEL_CMDLINE=""
# 设置无图形界面模式
QEMU_NOGRAPHIC=false
KERNEL_CMDLINE=" "
BIOS_TYPE=""
#这个变量为true则使用virtio磁盘
@ -116,10 +119,7 @@ fi
if [ ${ARCH} == "riscv64" ]; then
# 如果是riscv64架构就不需要图形界面
QEMU_ARGUMENT+=" --nographic "
# 从控制台显示
QEMU_MONITOR=""
QEMU_SERIAL=""
QEMU_NOGRAPHIC=true
fi
while true;do
@ -141,14 +141,7 @@ while true;do
window)
;;
nographic)
QEMU_SERIAL=" -serial chardev:mux -monitor chardev:mux -chardev stdio,id=mux,mux=on,signal=off,logfile=${QEMU_SERIAL_LOG_FILE} "
# 添加 virtio console 设备
QEMU_DEVICES+=" -device virtio-serial -device virtconsole,chardev=mux "
KERNEL_CMDLINE+=" console=/dev/hvc0 "
QEMU_MONITOR=""
QEMU_ARGUMENT+=" --nographic "
QEMU_ARGUMENT+=" -kernel ../bin/kernel/kernel.elf "
QEMU_ARGUMENT+="-append ${KERNEL_CMDLINE}"
QEMU_NOGRAPHIC=true
;;
esac;shift 2;;
@ -156,6 +149,35 @@ while true;do
esac
done
if [ ${QEMU_NOGRAPHIC} == true ]; then
QEMU_SERIAL=" -serial chardev:mux -monitor chardev:mux -chardev stdio,id=mux,mux=on,signal=off,logfile=${QEMU_SERIAL_LOG_FILE} "
# 添加 virtio console 设备
if [${ARCH} == "x86_64" ]; then
QEMU_DEVICES+=" -device virtio-serial -device virtconsole,chardev=mux "
elif [ ${ARCH} == "riscv64" ]; then
QEMU_DEVICES+=" -device virtio-serial-device -device virtconsole,chardev=mux "
fi
KERNEL_CMDLINE+=" console=/dev/hvc0 "
QEMU_MONITOR=""
QEMU_ARGUMENT+=" --nographic "
if [ ${ARCH} == "x86_64" ]; then
QEMU_ARGUMENT+=" -kernel ../bin/kernel/kernel.elf "
fi
fi
setup_kernel_init_program() {
if [ ${ARCH} == "x86_64" ]; then
KERNEL_CMDLINE+=" init=/bin/dragonreach "
elif [ ${ARCH} == "riscv64" ]; then
KERNEL_CMDLINE+=" init=/bin/riscv_rust_init "
fi
}
# 设置内核init程序
setup_kernel_init_program
# ps: 下面这条使用tap的方式无法dhcp获取到ip暂时不知道为什么
# QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -net nic,netdev=nic0 -netdev tap,id=nic0,model=virtio-net-pci,script=qemu/ifup-nat,downscript=qemu/ifdown-nat -usb -device qemu-xhci,id=xhci,p2=8,p3=4 "
@ -222,7 +244,7 @@ else
elif [ ${ARCH} == riscv64 ] ;then
# 如果是riscv64架构就与efi启动一样
install_riscv_uboot
sudo ${QEMU} -kernel ${RISCV64_UBOOT_PATH}/u-boot.bin ${QEMU_ARGUMENT}
sudo ${QEMU} -kernel ${RISCV64_UBOOT_PATH}/u-boot.bin ${QEMU_ARGUMENT} -append "${KERNEL_CMDLINE}"
else
echo "不支持的架构: ${ARCH}"
fi

View File

@ -6,15 +6,20 @@ endif
CC=$(CROSS_COMPILE)gcc
.PHONY: all
all: main.c
$(CC) -static -o init main.c
# $(CC) -static -o init main.c
$(MAKE) -C riscv_rust_init ARCH=$(ARCH) install
.PHONY: install clean
install: all
mv init $(DADK_CURRENT_BUILD_DIR)/init
$(MAKE) -C riscv_rust_init ARCH=$(ARCH) install
# mv init $(DADK_CURRENT_BUILD_DIR)/init
clean:
rm init *.o
$(MAKE) -C riscv_rust_init ARCH=$(ARCH) clean
fmt:

View File

@ -0,0 +1,2 @@
[target.riscv64gc-unknown-linux-musl]
linker = "riscv64-linux-gnu-gcc"

View File

@ -0,0 +1 @@
/target

View File

@ -0,0 +1,6 @@
[package]
name = "riscv_rust_init"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@ -0,0 +1,50 @@
# The toolchain we use.
# You can get it by running DragonOS' `tools/bootstrap.sh`
TOOLCHAIN="+nightly-2024-11-05-x86_64-unknown-linux-gnu"
ifeq ($(ARCH), riscv64)
RUSTFLAGS+="-C target-feature=+crt-static"
endif
ifdef DADK_CURRENT_BUILD_DIR
# 如果是在dadk中编译那么安装到dadk的安装目录中
INSTALL_DIR = $(DADK_CURRENT_BUILD_DIR)
else
# 如果是在本地编译那么安装到当前目录下的install目录中
INSTALL_DIR = ./install
endif
ifeq ($(ARCH), x86_64)
export RUST_TARGET=x86_64-unknown-linux-musl
else ifeq ($(ARCH), riscv64)
export RUST_TARGET=riscv64gc-unknown-linux-musl
else
# 默认为x86_64用于本地编译
export RUST_TARGET=x86_64-unknown-linux-musl
endif
build:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET)
run-dragonreach:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET) --bin DragonReach
clean:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean
build-release:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET) --release
clean-release:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET) --release
fmt:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt
fmt-check:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt --check
.PHONY: install
install:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --target $(RUST_TARGET) --path . --no-track --root $(INSTALL_DIR) --force

View File

@ -0,0 +1,4 @@
fn main() {
println!("rs: Hello, world!");
loop {}
}