From e7db766e48775f2fe5cfe68dd00f1d6e4f8f9e7a Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Thu, 23 Jun 2022 23:28:25 +0800 Subject: [PATCH] add CI autotest, update README --- .github/workflows/build-doc.yml | 25 --------- .github/workflows/doc-and-test.yml | 69 +++++++++++++++++++++++++ README.md | 82 +++++++++++++++++++++--------- os/Cargo.toml | 6 ++- os/Makefile | 2 +- os/src/boards/qemu.rs | 79 ++++++++++++++++++++++++++++ os/src/main.rs | 4 ++ os/src/sbi.rs | 10 ++++ os/src/task/mod.rs | 8 +++ 9 files changed, 235 insertions(+), 50 deletions(-) delete mode 100644 .github/workflows/build-doc.yml create mode 100644 .github/workflows/doc-and-test.yml create mode 100644 os/src/boards/qemu.rs diff --git a/.github/workflows/build-doc.yml b/.github/workflows/build-doc.yml deleted file mode 100644 index a48f1474..00000000 --- a/.github/workflows/build-doc.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Build Rust Doc - -on: [push] - -env: - CARGO_TERM_COLOR: always - -jobs: - build-doc: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Build doc - run: | - rustup target add riscv64gc-unknown-none-elf - rustup component add llvm-tools-preview - rustup component add rust-src - cd os - cargo doc --no-deps --verbose - - name: Deploy to Github Pages - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./os/target/riscv64gc-unknown-none-elf/doc - destination_dir: ${{ github.ref_name }} \ No newline at end of file diff --git a/.github/workflows/doc-and-test.yml b/.github/workflows/doc-and-test.yml new file mode 100644 index 00000000..0ddd1d3d --- /dev/null +++ b/.github/workflows/doc-and-test.yml @@ -0,0 +1,69 @@ +name: Build Rust Doc And Run tests + +on: [push] + +env: + CARGO_TERM_COLOR: always + +jobs: + build-doc: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly-2022-04-11 + components: rust-src, llvm-tools-preview + target: riscv64gc-unknown-none-elf + - name: Build doc + run: cd os && cargo doc --no-deps --verbose --features "board_qemu" + - name: Deploy to Github Pages + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./os/target/riscv64gc-unknown-none-elf/doc + destination_dir: ${{ github.ref_name }} + + run-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly-2022-04-11 + components: rust-src, llvm-tools-preview + target: riscv64gc-unknown-none-elf + - uses: actions-rs/install@v0.1 + with: + crate: cargo-binutils + version: latest + use-tool-cache: true + - name: Cache QEMU + uses: actions/cache@v3 + with: + path: qemu-7.0.0 + key: qemu-7.0.0-x86_64-riscv64 + - name: Install QEMU + run: | + sudo apt-get update + sudo apt-get install ninja-build -y + if [ ! -d qemu-7.0.0 ]; then + wget https://download.qemu.org/qemu-7.0.0.tar.xz + tar -xf qemu-7.0.0.tar.xz + cd qemu-7.0.0 + ./configure --target-list=riscv64-softmmu + make -j + else + cd qemu-7.0.0 + fi + sudo make install + qemu-system-riscv64 --version + + - name: Run usertests + run: cd os && make run TEST=1 + timeout-minutes: 10 + + - name: Build for k210 + run: cd os && make build BOARD=k210 \ No newline at end of file diff --git a/README.md b/README.md index 5f27d55e..767cb147 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,14 @@ # rCore-Tutorial-v3 -rCore-Tutorial version 3.5. See the [Documentation in Chinese](https://rcore-os.github.io/rCore-Tutorial-Book-v3/). +rCore-Tutorial version 3.6. See the [Documentation in Chinese](https://rcore-os.github.io/rCore-Tutorial-Book-v3/). rCore-Tutorial API Docs. See the [API Docs of Ten OSes ](#OS-API-DOCS) +If you don't know Rust Language and try to learn it, please visit [Rust Learning Resources](https://github.com/rcore-os/rCore/wiki/study-resource-of-system-programming-in-RUST) + Official QQ group number: 735045051 ## news -- 25/01/2022: Version 3.6.0 is on the way! Now we directly update the code on chX branches, please periodically check if there are any updates. +- 23/06/2022: Version 3.6.0 is on the way! Now we directly update the code on chX branches, please periodically check if there are any updates. ## Overview @@ -42,7 +44,7 @@ $ rustup component add rust-src ### Install Qemu -Here we manually compile and install Qemu 5.0.0. For example, on Ubuntu 18.04: +Here we manually compile and install Qemu 7.0.0. For example, on Ubuntu 18.04: ```sh # install dependency packages @@ -50,10 +52,10 @@ $ sudo apt install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev l gawk build-essential bison flex texinfo gperf libtool patchutils bc \ zlib1g-dev libexpat-dev pkg-config libglib2.0-dev libpixman-1-dev git tmux python3 python3-pip # download Qemu source code -$ wget https://download.qemu.org/qemu-5.0.0.tar.xz -# extract to qemu-5.0.0/ -$ tar xvJf qemu-5.0.0.tar.xz -$ cd qemu-5.0.0 +$ wget https://download.qemu.org/qemu-7.0.0.tar.xz +# extract to qemu-7.0.0/ +$ tar xvJf qemu-7.0.0.tar.xz +$ cd qemu-7.0.0 # build $ ./configure --target-list=riscv64-softmmu,riscv64-linux-user $ make -j$(nproc) @@ -62,9 +64,9 @@ $ make -j$(nproc) Then, add following contents to `~/.bashrc`(please adjust these paths according to your environment): ``` -export PATH=$PATH:/home/shinbokuow/Downloads/built/qemu-5.0.0 -export PATH=$PATH:/home/shinbokuow/Downloads/built/qemu-5.0.0/riscv64-softmmu -export PATH=$PATH:/home/shinbokuow/Downloads/built/qemu-5.0.0/riscv64-linux-user +export PATH=$PATH:/home/shinbokuow/Downloads/built/qemu-7.0.0 +export PATH=$PATH:/home/shinbokuow/Downloads/built/qemu-7.0.0/riscv64-softmmu +export PATH=$PATH:/home/shinbokuow/Downloads/built/qemu-7.0.0/riscv64-linux-user ``` Finally, update the current shell: @@ -77,7 +79,7 @@ Now we can check the version of Qemu: ```sh $ qemu-system-riscv64 --version -QEMU emulator version 5.0.0 +QEMU emulator version 7.0.0 Copyright (c) 2003-2020 Fabrice Bellard and the QEMU Project developers ``` @@ -188,6 +190,46 @@ $ make run BOARD=k210 Type `Ctrl+]` to disconnect from K210. + +## Show runtime debug info of OS kernel version +The branch of ch9-log contains a lot of debug info. You could try to run rcore tutorial +for understand the internal behavior of os kernel. + +```sh +$ git clone https://github.com/rcore-os/rCore-Tutorial-v3.git +$ cd rCore-Tutorial-v3/os +$ git checkout ch9-log +$ make run +...... +[rustsbi] RustSBI version 0.2.0-alpha.10, adapting to RISC-V SBI v0.3 +.______ __ __ _______.___________. _______..______ __ +| _ \ | | | | / | | / || _ \ | | +| |_) | | | | | | (----`---| |----`| (----`| |_) || | +| / | | | | \ \ | | \ \ | _ < | | +| |\ \----.| `--' |.----) | | | .----) | | |_) || | +| _| `._____| \______/ |_______/ |__| |_______/ |______/ |__| + +[rustsbi] Implementation: RustSBI-QEMU Version 0.0.2 +[rustsbi-dtb] Hart count: cluster0 with 1 cores +[rustsbi] misa: RV64ACDFIMSU +[rustsbi] mideleg: ssoft, stimer, sext (0x222) +[rustsbi] medeleg: ima, ia, bkpt, la, sa, uecall, ipage, lpage, spage (0xb1ab) +[rustsbi] pmp0: 0x10000000 ..= 0x10001fff (rw-) +[rustsbi] pmp1: 0x2000000 ..= 0x200ffff (rw-) +[rustsbi] pmp2: 0xc000000 ..= 0xc3fffff (rw-) +[rustsbi] pmp3: 0x80000000 ..= 0x8fffffff (rwx) +[rustsbi] enter supervisor 0x80200000 +[KERN] rust_main() begin +[KERN] clear_bss() begin +[KERN] clear_bss() end +[KERN] mm::init() begin +[KERN] mm::init_heap() begin +[KERN] mm::init_heap() end +[KERN] mm::init_frame_allocator() begin +[KERN] mm::frame_allocator::lazy_static!FRAME_ALLOCATOR begin +...... +``` + ## Rustdoc Currently it can only help you view the code since only a tiny part of the code has been documented. @@ -209,13 +251,9 @@ The API Docs for Ten OS ## Working in progress -Our first release 3.5.0 (chapter 1-7) has been published. +Our first release 3.6.0 (chapter 1-9) has been published, and we are still working on it. -There will be 9 chapters in our next release 3.6.0, where 2 new chapters will be added: -* chapter 8: synchronization on a uniprocessor -* chapter 9: I/O devices - -Current version is 3.6.0-alpha.1 and we are still working on it. +* chapter 9: need more descripts about different I/O devices Here are the updates since 3.5.0: @@ -237,18 +275,16 @@ Here are the updates since 3.5.0: * [x] switch the code of chapter 6 and chapter 7 * [x] support signal mechanism in chapter 7/8(only works for apps with a single thread) * [x] Add boards/ directory and support rustdoc, for example you can use `cargo doc --no-deps --open` to view the documentation of a crate - +* [x] code of chapter 9: device drivers based on interrupts, including UART, block, keyboard, mouse, gpu devices +* [x] add CI autotest and doc in github ### Todo(High priority) -* [ ] review documentation, current progress: 5/9 -* [ ] support user-level sync primitives in chapter 8 -* [ ] code of chapter 9: device drivers based on interrupts, including UART and block devices +* [ ] review documentation, current progress: 8/9 * [ ] use old fs image optionally, do not always rebuild the image -* [ ] add new system calls: getdents64/fstat * [ ] shell functionality improvement(to be continued...) * [ ] give every non-zero process exit code an unique and clear error type * [ ] effective error handling of mm module - +* [ ] add more os functions for understanding os conecpts and principles ### Todo(Low priority) * [ ] rewrite practice doc and remove some inproper questions diff --git a/os/Cargo.toml b/os/Cargo.toml index 25e91d10..f84e6f37 100644 --- a/os/Cargo.toml +++ b/os/Cargo.toml @@ -2,7 +2,7 @@ name = "os" version = "0.1.0" authors = ["Yifan Wu "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -10,5 +10,9 @@ edition = "2018" riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } lazy_static = { version = "1.4.0", features = ["spin_no_std"] } +[features] +board_qemu = [] +board_k210 = [] + [profile.release] debug = true diff --git a/os/Makefile b/os/Makefile index 259bd9fc..fea0ef55 100644 --- a/os/Makefile +++ b/os/Makefile @@ -56,7 +56,7 @@ kernel: @cd ../user && make build @echo Platform: $(BOARD) @cp src/linker-$(BOARD).ld src/linker.ld - @cargo build $(MODE_ARG) + @cargo build $(MODE_ARG) --features "board_$(BOARD)" @rm src/linker.ld clean: diff --git a/os/src/boards/qemu.rs b/os/src/boards/qemu.rs new file mode 100644 index 00000000..285be40f --- /dev/null +++ b/os/src/boards/qemu.rs @@ -0,0 +1,79 @@ +//ref:: https://github.com/andre-richter/qemu-exit +use core::arch::asm; + +const EXIT_SUCCESS: u32 = 0x5555; // Equals `exit(0)`. qemu successful exit + +const EXIT_FAILURE_FLAG: u32 = 0x3333; +const EXIT_FAILURE: u32 = exit_code_encode(1); // Equals `exit(1)`. qemu failed exit +const EXIT_RESET: u32 = 0x7777; // qemu reset + +pub trait QEMUExit { + /// Exit with specified return code. + /// + /// Note: For `X86`, code is binary-OR'ed with `0x1` inside QEMU. + fn exit(&self, code: u32) -> !; + + /// Exit QEMU using `EXIT_SUCCESS`, aka `0`, if possible. + /// + /// Note: Not possible for `X86`. + fn exit_success(&self) -> !; + + /// Exit QEMU using `EXIT_FAILURE`, aka `1`. + fn exit_failure(&self) -> !; +} + +/// RISCV64 configuration +pub struct RISCV64 { + /// Address of the sifive_test mapped device. + addr: u64, +} + +/// Encode the exit code using EXIT_FAILURE_FLAG. +const fn exit_code_encode(code: u32) -> u32 { + (code << 16) | EXIT_FAILURE_FLAG +} + +impl RISCV64 { + /// Create an instance. + pub const fn new(addr: u64) -> Self { + RISCV64 { addr } + } +} + +impl QEMUExit for RISCV64 { + /// Exit qemu with specified exit code. + fn exit(&self, code: u32) -> ! { + // If code is not a special value, we need to encode it with EXIT_FAILURE_FLAG. + let code_new = match code { + EXIT_SUCCESS | EXIT_FAILURE | EXIT_RESET => code, + _ => exit_code_encode(code), + }; + + unsafe { + asm!( + "sw {0}, 0({1})", + in(reg)code_new, in(reg)self.addr + ); + + // For the case that the QEMU exit attempt did not work, transition into an infinite + // loop. Calling `panic!()` here is unfeasible, since there is a good chance + // this function here is the last expression in the `panic!()` handler + // itself. This prevents a possible infinite loop. + loop { + asm!("wfi", options(nomem, nostack)); + } + } + } + + fn exit_success(&self) -> ! { + self.exit(EXIT_SUCCESS); + } + + fn exit_failure(&self) -> ! { + self.exit(EXIT_FAILURE); + } +} + +const VIRT_TEST: u64 = 0x100000; + +pub const QEMU_EXIT_HANDLE: RISCV64 = RISCV64::new(VIRT_TEST); diff --git a/os/src/main.rs b/os/src/main.rs index dcb29e04..76f13dcb 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -23,6 +23,10 @@ use core::arch::global_asm; +#[cfg(feature = "board_qemu")] +#[path = "boards/qemu.rs"] +mod board; + #[macro_use] mod console; mod config; diff --git a/os/src/sbi.rs b/os/src/sbi.rs index adf606e4..f272dde4 100644 --- a/os/src/sbi.rs +++ b/os/src/sbi.rs @@ -3,6 +3,8 @@ use core::arch::asm; const SBI_CONSOLE_PUTCHAR: usize = 1; + +#[cfg(feature = "board_k210")] const SBI_SHUTDOWN: usize = 8; // const SBI_SET_TIMER: usize = 0; // const SBI_CONSOLE_GETCHAR: usize = 2; @@ -39,8 +41,16 @@ pub fn console_putchar(c: usize) { // sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0) // } +#[cfg(feature = "board_qemu")] +use crate::board::QEMUExit; /// use sbi call to shutdown the kernel pub fn shutdown() -> ! { + #[cfg(feature = "board_k210")] sbi_call(SBI_SHUTDOWN, 0, 0, 0); + + #[cfg(feature = "board_qemu")] + crate::board::QEMU_EXIT_HANDLE.exit_failure(); + + #[cfg(feature = "board_k210")] panic!("It should shutdown!"); } diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index 8ac68ab0..57cd6409 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -133,6 +133,14 @@ impl TaskManager { } // go back to user mode } else { + println!("All applications completed!"); + + #[cfg(feature = "board_qemu")] + use crate::board::QEMUExit; + #[cfg(feature = "board_qemu")] + crate::board::QEMU_EXIT_HANDLE.exit_success(); + + #[cfg(feature = "board_k210")] panic!("All applications completed!"); } }