diff --git a/.gitmodules b/.gitmodules index 022aec1..ab860af 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "vmm"] path = vmm url = https://github.com/rcore-os/rcore-vmm.git +[submodule "rust-rvm-vmm"] + path = rust-rvm-vmm + url = https://github.com/rcore-riscv-hypervisor-dev/rust-rvm-vmm.git diff --git a/Makefile b/Makefile index 0084488..15cc02a 100644 --- a/Makefile +++ b/Makefile @@ -6,9 +6,12 @@ # targets: build, pack ARCH ?= riscv32 MODE ?= debug +export ARCH +export MODE EN_RUST ?= y EN_UCORE ?= y EN_VMM ?= n +EN_RUST_RVM_VMM ?= n ifneq ($(shell uname), Darwin) EN_BISCUIT ?= y EN_APP ?= y @@ -57,7 +60,7 @@ else ifeq ($(MODE), debug) cmake_build_args += -DCMAKE_BUILD_TYPE=Debug endif -.PHONY: all clean build rust ucore biscuit app bin busybox nginx redis alpine iperf3 musl-gcc pre make libc-test vmm rust-rvm-vmm +.PHONY: all clean build rust ucore biscuit app bin busybox nginx redis alpine iperf3 musl-gcc pre make libc-test vmm rust-rvm-vmm rcore-guest all: build @@ -221,12 +224,34 @@ vmm: | vmm/* ifeq ($(EN_VMM), y) @echo Building rcore-vmm @mkdir -p $(out_dir)/vmm - @cd vmm && make ARCH=$(ARCH) + @cd vmm && make build-$(ARCH) ARCH=$(ARCH) @cp vmm/build/$(ARCH)/* $(out_dir)/vmm/ else @echo rcore-vmm disabled endif +# rust-rvm-vmm +rust-rvm-vmm: | rust-rvm-vmm/* rcore-guest +ifeq ($(EN_RUST_RVM_VMM), y) + @echo Building rust-rvm-vmm + @cd rust-rvm-vmm && cargo build $(rust_build_args) && make strip + @rm -rf $(out_dir)/rust-rvm-vmm && mkdir -p $(out_dir)/rust-rvm-vmm + @cp rust-rvm-vmm/target/$(ARCH)-rcore/$(MODE)/rust-rvm-vmm-strip $(out_dir)/rust-rvm-vmm/vmm +else + @echo rust-rvm-vmm disabled +endif + +# prebuilt rCore guest image + +rcore_guest_image := build/$(ARCH)/vmm/rcore +rcore-guest: $(rcore_guest_image) +$(rcore_guest_image): +ifeq ($(ARCH), riscv64) + @mkdir -p build/$(ARCH)/vmm + @wget "https://github.com/rcore-riscv-hypervisor-dev/rcore-guest-image-blob/blob/master/kernel.img?raw=true" -O $@ +else + @echo rcore guest image not supported +endif # prebuilt prebuilt_version := 0.1.2 prebuilt_tar := build/$(ARCH)_v$(prebuilt_version).tar.gz @@ -239,7 +264,7 @@ ifdef PREBUILT build: $(prebuilt_tar) @tar -xzf $< -C build else -build: rcore-fs-fuse pre alpine rust ucore biscuit app busybox nginx redis iperf3 test musl-gcc make libc-test vmm +build: rcore-fs-fuse pre alpine rust ucore biscuit app busybox nginx redis iperf3 test musl-gcc make libc-test vmm rust-rvm-vmm rcore-guest endif sfsimg: $(out_qcow2) diff --git a/README.md b/README.md index f6ef8af..1b56691 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ User programs for [rCore OS](https://github.com/rcore-os/rCore). -Now it has 6 parts: +Now it has 7 parts: * `ucore`: C-lang, from the original [ucore_os_lab](https://github.com/chyyuu/ucore_os_plus) * `biscuit`: C/C++, from [Biscuit](https://github.com/mit-pdos/biscuit), based on a `musl` instead of original `litc`. @@ -25,6 +25,7 @@ Now it has 6 parts: * `app`: C-lang, custom test programs based on `musl`. * `nginx`, `redis`, `busybox`, `alpine`, `gcc`: Real world applications. * `vmm`: Simple VMM (Virtual Machine Monitor) runs on top of [RVM](https://github.com/rcore-os/RVM), can run the unmodified [ucore_os_lab](https://github.com/chyyuu/os_kernel_lab/tree/master) as a guest OS. +* `rust-rvm-vmm`: VMM (Virtual Machine Monitor) runs on top of [RVM](https://github.com/rcore-os/RVM) written in Rust. Can run unmodified (except drivers) rCore as a guest OS. ## Build @@ -45,19 +46,20 @@ A rootfs is created at `build/$(arch)` and converted to `qcow2`. ## Support matrix -| | x86_64 | aarch64 | riscv32 | riscv64 | mipsel | -| ------------------ | ------ | ------- | ------- | ------- | ------ | -| ucore | ✅ | ✅ | ✅ | ✅ | ❗ | -| rust | ✅ | ✅ | ✅ | ✅ | ✅ | -| biscuit | ✅ | ✅ | ✅ | ✅ | ✅ | -| app | ✅ | ✅ | ✅ | ✅ | ✅ | -| nginx (linux only) | ✅ | ✅ | ❗ | ✅ | ❗ | -| redis (linux only) | ✅ | ✅ | ✅ | ✅ | ✅ | -| busybox | ✅ | ✅ | ✅ | ✅ | ✅ | -| alpine rootfs | ✅ | ✅ | ❌ | ❌ | ❌ | -| iperf3 | ✅ | ❌ | ❌ | ❌ | ❌ | -| test | ✅ | ❌ | ❌ | ❌ | ❌ | -| vmm (linux only) | ✅ | ❌ | ❌ | ❌ | ❌ | +| | x86_64 | aarch64 | riscv32 | riscv64 | mipsel | +| --------------------------- | ------ | ------- | ------- | ------- | ------ | +| ucore | ✅ | ✅ | ✅ | ✅ | ❗ | +| rust | ✅ | ✅ | ✅ | ✅ | ✅ | +| biscuit | ✅ | ✅ | ✅ | ✅ | ✅ | +| app | ✅ | ✅ | ✅ | ✅ | ✅ | +| nginx (linux only) | ✅ | ✅ | ❗ | ✅ | ❗ | +| redis (linux only) | ✅ | ✅ | ✅ | ✅ | ✅ | +| busybox | ✅ | ✅ | ✅ | ✅ | ✅ | +| alpine rootfs | ✅ | ✅ | ❌ | ❌ | ❌ | +| iperf3 | ✅ | ❌ | ❌ | ❌ | ❌ | +| test | ✅ | ❌ | ❌ | ❌ | ❌ | +| vmm (linux only) | ✅ | ❌ | ❌ | ❌ | ❌ | +| rust-rvm-vmm (linux only) | ❌ | ❌ | ❌ | ✅ | ❌ | Note: ❗ means workarounds are used so that they may not work properly. ❌ means failure in compiling or not existed on such platform. @@ -228,3 +230,57 @@ vcpu_id = 1 ``` Now uCore is booting and your can get uCore's shell soon. + + +### How to run rCore in rCore +Clone this repo recursively with [rust-rvm-vmm](https://github.com/rcore-riscv-hypervisor-dev/rust-rvm-vmm). + +```bash +$ git clone https://github.com/rcore-os/rcore-user.git --recursive +``` + +Note: Currently guest rCore is provided as blob and will be downloaded while building sfsimg, but you can easily build your own guest rCore image using the flags mentioned in the [blob repo](https://github.com/rcore-riscv-hypervisor-dev/rcore-guest-image-blob). + + +Build with `EN_RUST_RVM_VMM=y`: + +```bash +$ make sfsimg ARCH=riscv64 EN_RUST_RVM_VMM=y +``` + +Build and run [rCore](https://github.com/rcore-os/rCore) with `HYPERVISOR=on` and second uart `UART2=on`: + +```bash +$ cd $(RCORE_ROOT)/kernel +$ make run mode=release ARCH=riscv64 HYPERVISOR=on UART2=on +``` + +Run the `vmm` app in rCore shell: + +``` +/ # cd rust-rvm-vmm +/rust-rvm-vmm # ./vmm +rust-rvm-vmm starting +starting + +``` + + +And connect to the secondary UART using `nc`: + +```bash +$ nc -U /tmp/rcore_uart2 +hello, vmm[vmm] Bad ecall eid=4739917 fid=0. Ignore. +[vmm] Bad ecall eid=4739917 fid=0. Ignore. +... +[vmm] Bad ecall eid=4739917 fid=0. Ignore. +/ # /busybox +/busybox +BusyBox v1.30.1 (2019-03-22 15:43:23 CST) multi-call binary. +BusyBox is copyrighted by many authors between 1998-2015. +Licensed under GPLv2. See source distribution for detailed +copyright notices. +... +``` + +Now you can use rCore shell from the secondary UART. \ No newline at end of file diff --git a/rcore b/rcore new file mode 100755 index 0000000..933ba99 Binary files /dev/null and b/rcore differ diff --git a/rust-rvm-vmm b/rust-rvm-vmm new file mode 160000 index 0000000..5e51f21 --- /dev/null +++ b/rust-rvm-vmm @@ -0,0 +1 @@ +Subproject commit 5e51f21c0aa30f957b547ee1ab096e160c9b95fe diff --git a/rust/src/bin/uart2.rs b/rust/src/bin/uart2.rs new file mode 100644 index 0000000..eb91c8f --- /dev/null +++ b/rust/src/bin/uart2.rs @@ -0,0 +1,37 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate rcore_user; +use rcore_user::io::{putc, O_RDONLY}; +use rcore_user::syscall::sys_open; +use rcore_user::syscall::sys_read; +use rcore_user::syscall::sys_write; +pub fn putc_uart2(fd: usize, c: u8) { + sys_write(fd, &c, 1); +} + +pub fn getc_uart2(fd: usize) -> u8 { + let mut c = 0u8; + loop { + let len = sys_read(fd, &mut c, 1); + match len { + 1 => return c, + 0 => continue, + _ => panic!("read uart2 len = {}", len), + } + } +} +// IMPORTANT: Must define main() like this +#[no_mangle] +pub fn main() { + let fd = sys_open("/dev/ttyS1", O_RDONLY); + if (fd < 0) { + panic!("no /dev/ttyS1"); + } + let fd = fd as usize; + println!("Start spinning."); + loop { + putc(getc_uart2(fd)); + } +}