소스 검색

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>
LoGin 5 일 전
부모
커밋
03015e2559

+ 8 - 8
.github/workflows/makefile.yml

@@ -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:

+ 1 - 1
kernel/Cargo.lock

@@ -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",

+ 23 - 8
kernel/src/arch/riscv64/interrupt/handle.rs

@@ -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();

+ 1 - 1
kernel/src/driver/irqchip/riscv_sifive_plic.rs

@@ -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) {

+ 1 - 0
kernel/src/init/cmdline.rs

@@ -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,

+ 1 - 0
kernel/src/init/initial_kthread.rs

@@ -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());
 

+ 5 - 0
kernel/src/syscall/mod.rs

@@ -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)

+ 1 - 1
tools/BUILD_CONTAINER_VERSION

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

+ 2 - 0
tools/bootstrap.sh

@@ -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

+ 1 - 1
tools/build_in_docker.sh

@@ -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

+ 38 - 16
tools/run-qemu.sh

@@ -85,7 +85,10 @@ QEMU_ACCELARATE=""
 QEMU_ARGUMENT=" -no-reboot "
 QEMU_DEVICES=""
 
-KERNEL_CMDLINE=""
+# 设置无图形界面模式
+QEMU_NOGRAPHIC=false
+
+KERNEL_CMDLINE=" "
 
 BIOS_TYPE=""
 #这个变量为true则使用virtio磁盘
@@ -116,15 +119,12 @@ fi
 
 if [ ${ARCH} == "riscv64" ]; then
 # 如果是riscv64架构,就不需要图形界面
-    QEMU_ARGUMENT+=" --nographic "
-    # 从控制台显示
-    QEMU_MONITOR=""
-    QEMU_SERIAL=""
+    QEMU_NOGRAPHIC=true
 fi
 
 while true;do
     case "$1" in
-        --bios) 
+        --bios)
         case "$2" in
               uefi) #uefi启动新增ovmf.fd固件
               BIOS_TYPE=uefi
@@ -141,21 +141,43 @@ 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;;
         *) break
-      esac 
+      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

+ 7 - 2
user/apps/riscv_init/Makefile

@@ -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:

+ 2 - 0
user/apps/riscv_init/riscv_rust_init/.cargo/config.toml

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

+ 1 - 0
user/apps/riscv_init/riscv_rust_init/.gitignore

@@ -0,0 +1 @@
+/target

+ 6 - 0
user/apps/riscv_init/riscv_rust_init/Cargo.toml

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

+ 50 - 0
user/apps/riscv_init/riscv_rust_init/Makefile

@@ -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

+ 4 - 0
user/apps/riscv_init/riscv_rust_init/src/main.rs

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