diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000..2d7932f
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,21 @@
+{
+ "name": "rcore-tutorial-v3",
+ "build": {
+ "dockerfile": "../Dockerfile",
+ "args": {
+ "QEMU_VERSION": "7.0.0",
+ "DEBIAN_FRONTEND": "noninteractive",
+ "GDB_VERSION": "14.1"
+ }
+ },
+ "postCreateCommand": "rustup show",
+ "customizations": {
+ "vscode": {
+ "extensions": [
+ "rust-lang.rust-analyzer",
+ "ms-vscode.cpptools",
+ "tamasfe.even-better-toml"
+ ]
+ }
+ }
+}
diff --git a/.github/workflows/doc-and-test.yml b/.github/workflows/doc-and-test.yml
index b1ea980..f4027c2 100644
--- a/.github/workflows/doc-and-test.yml
+++ b/.github/workflows/doc-and-test.yml
@@ -4,7 +4,7 @@ on: [push]
env:
CARGO_TERM_COLOR: always
- rust_toolchain: nightly-2023-10-09
+ rust_toolchain: nightly-2024-01-18
jobs:
build-doc:
diff --git a/.gitignore b/.gitignore
index 852c161..45fffb0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
.*/*
!.github/*
!.vscode/settings.json
+!.devcontainer/devcontainer.json
**/target/
**/Cargo.lock
diff --git a/Dockerfile b/Dockerfile
index acc2c45..b9bf31b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1
-# Stage 1 Set up QEMU RISC-V
+# Stage 1 Build QEMU
# - https://www.qemu.org/download/
# - https://wiki.qemu.org/Hosts/Linux#Building_QEMU_for_Linux
# - https://wiki.qemu.org/Documentation/Platforms/RISCV
@@ -20,30 +20,34 @@ RUN wget https://download.qemu.org/qemu-${QEMU_VERSION}.tar.xz && \
make -j$(nproc) && \
make install
-# Stage 2 Lab Environment
+# Stage 2 Set Lab Environment
FROM ubuntu:20.04 as build
WORKDIR /tmp
-# 0. Install general tools
+# 2.0. Install general tools
RUN sed -i 's/archive.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list && \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y jq curl git python3 wget build-essential \
# qemu dependency
- libglib2.0-0 libfdt1 libpixman-1-0 zlib1g
+ libglib2.0-0 libfdt1 libpixman-1-0 zlib1g \
+ # gdb
+ gdb-multiarch
-# 1. Copy qemu
+# 2.1. Copy qemu
COPY --from=build_qemu /usr/local/bin/* /usr/local/bin
-# 2. Install Rust
+# 2.2. Install Rust
# - https://www.rust-lang.org/tools/install
ENV RUSTUP_HOME=/usr/local/rustup \
CARGO_HOME=/usr/local/cargo \
- PATH=/usr/local/cargo/bin:$PATH
+ PATH=/usr/local/cargo/bin:$PATH \
+ RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static \
+ RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \
sh -s -- -y --no-modify-path --profile minimal --default-toolchain nightly
-# 3. Build env for labs
+# 2.3. Build env for labs
# See os/Makefile `env:` for example.
# This avoids having to wait for these steps each time using a new container.
COPY rust-toolchain.toml rust-toolchain.toml
@@ -54,10 +58,14 @@ RUN rustup target add riscv64gc-unknown-none-elf && \
rustup install $RUST_VERSION && \
rustup component add --toolchain $RUST_VERSION $Components
+# 2.4. Set GDB
+RUN ln -s /usr/bin/gdb-multiarch /usr/bin/riscv64-unknown-elf-gdb
+
# Stage 3 Sanity checking
FROM build as test
RUN qemu-system-riscv64 --version && \
qemu-riscv64 --version && \
rustup --version && \
cargo --version && \
- rustc --version
\ No newline at end of file
+ rustc --version && \
+ riscv64-unknown-elf-gdb --version
\ No newline at end of file
diff --git a/os/src/boards/qemu.rs b/os/src/boards/qemu.rs
index 35ac031..5daf541 100644
--- a/os/src/boards/qemu.rs
+++ b/os/src/boards/qemu.rs
@@ -1,4 +1,5 @@
pub const CLOCK_FREQ: usize = 12500000;
+pub const MEMORY_END: usize = 0x8800_0000;
pub const MMIO: &[(usize, usize)] = &[
(0x0010_0000, 0x00_2000), // VIRT_TEST/RTC in virt machine
diff --git a/os/src/config.rs b/os/src/config.rs
index 8f8b709..d9b9b71 100644
--- a/os/src/config.rs
+++ b/os/src/config.rs
@@ -3,11 +3,10 @@
pub const USER_STACK_SIZE: usize = 4096 * 2;
pub const KERNEL_STACK_SIZE: usize = 4096 * 2;
pub const KERNEL_HEAP_SIZE: usize = 0x100_0000;
-pub const MEMORY_END: usize = 0x88000000;
pub const PAGE_SIZE: usize = 0x1000;
pub const PAGE_SIZE_BITS: usize = 0xc;
pub const TRAMPOLINE: usize = usize::MAX - PAGE_SIZE + 1;
pub const TRAP_CONTEXT_BASE: usize = TRAMPOLINE - PAGE_SIZE;
-pub use crate::board::{CLOCK_FREQ, MMIO};
+pub use crate::board::{CLOCK_FREQ, MEMORY_END, MMIO};
diff --git a/os/src/drivers/mod.rs b/os/src/drivers/mod.rs
index e16c51e..605397d 100644
--- a/os/src/drivers/mod.rs
+++ b/os/src/drivers/mod.rs
@@ -8,7 +8,6 @@ pub mod plic;
pub use block::BLOCK_DEVICE;
pub use bus::*;
-pub use chardev::UART;
pub use gpu::*;
pub use input::*;
pub use net::*;
diff --git a/os/src/fs/mod.rs b/os/src/fs/mod.rs
index 221d68b..cbde739 100644
--- a/os/src/fs/mod.rs
+++ b/os/src/fs/mod.rs
@@ -11,6 +11,6 @@ pub trait File: Send + Sync {
fn write(&self, buf: UserBuffer) -> usize;
}
-pub use inode::{list_apps, open_file, OSInode, OpenFlags, ROOT_INODE};
-pub use pipe::{make_pipe, Pipe};
+pub use inode::{list_apps, open_file, OpenFlags};
+pub use pipe::make_pipe;
pub use stdio::{Stdin, Stdout};
diff --git a/os/src/mm/mod.rs b/os/src/mm/mod.rs
index 574cea0..642d0b7 100644
--- a/os/src/mm/mod.rs
+++ b/os/src/mm/mod.rs
@@ -7,12 +7,11 @@ mod page_table;
pub use address::VPNRange;
pub use address::{PhysAddr, PhysPageNum, StepByOne, VirtAddr, VirtPageNum};
pub use frame_allocator::{frame_alloc, frame_alloc_more, frame_dealloc, FrameTracker};
-pub use memory_set::remap_test;
pub use memory_set::{kernel_token, MapArea, MapPermission, MapType, MemorySet, KERNEL_SPACE};
use page_table::PTEFlags;
pub use page_table::{
translated_byte_buffer, translated_ref, translated_refmut, translated_str, PageTable,
- PageTableEntry, UserBuffer, UserBufferIterator,
+ PageTableEntry, UserBuffer,
};
pub fn init() {
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index 732feea..8193d6f 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,5 +1,6 @@
[toolchain]
profile = "minimal"
# use the nightly version of the last stable toolchain, see
-channel = "nightly-2023-10-09"
+channel = "nightly-2024-01-18"
components = ["rust-src", "llvm-tools", "rustfmt", "clippy"]
+targets = ["riscv64gc-unknown-none-elf"]
\ No newline at end of file
diff --git a/user/src/bin/adder.rs b/user/src/bin/adder.rs
index d1addf1..1cdce95 100644
--- a/user/src/bin/adder.rs
+++ b/user/src/bin/adder.rs
@@ -6,6 +6,7 @@ extern crate user_lib;
extern crate alloc;
use alloc::vec::Vec;
+use core::ptr::addr_of_mut;
use user_lib::{exit, get_time, thread_create, waittid};
static mut A: usize = 0;
@@ -14,7 +15,7 @@ const THREAD_COUNT_DEFAULT: usize = 16;
static mut PER_THREAD: usize = 0;
unsafe fn critical_section(t: &mut usize) {
- let a = &mut A as *mut usize;
+ let a = addr_of_mut!(A);
let cur = a.read_volatile();
for _ in 0..500 {
*t = (*t) * (*t) % 10007;
diff --git a/user/src/bin/adder_atomic.rs b/user/src/bin/adder_atomic.rs
index 8fb5639..5e216c6 100644
--- a/user/src/bin/adder_atomic.rs
+++ b/user/src/bin/adder_atomic.rs
@@ -6,6 +6,7 @@ extern crate user_lib;
extern crate alloc;
use alloc::vec::Vec;
+use core::ptr::addr_of_mut;
use core::sync::atomic::{AtomicBool, Ordering};
use user_lib::{exit, get_time, thread_create, waittid, yield_};
@@ -16,7 +17,7 @@ const THREAD_COUNT_DEFAULT: usize = 16;
static mut PER_THREAD: usize = 0;
unsafe fn critical_section(t: &mut usize) {
- let a = &mut A as *mut usize;
+ let a = addr_of_mut!(A);
let cur = a.read_volatile();
for _ in 0..500 {
*t = (*t) * (*t) % 10007;
diff --git a/user/src/bin/adder_mutex_blocking.rs b/user/src/bin/adder_mutex_blocking.rs
index 79bb3c3..7fcb80b 100644
--- a/user/src/bin/adder_mutex_blocking.rs
+++ b/user/src/bin/adder_mutex_blocking.rs
@@ -6,6 +6,7 @@ extern crate user_lib;
extern crate alloc;
use alloc::vec::Vec;
+use core::ptr::addr_of_mut;
use user_lib::{exit, get_time, thread_create, waittid};
use user_lib::{mutex_blocking_create, mutex_lock, mutex_unlock};
@@ -15,7 +16,7 @@ const THREAD_COUNT_DEFAULT: usize = 16;
static mut PER_THREAD: usize = 0;
unsafe fn critical_section(t: &mut usize) {
- let a = &mut A as *mut usize;
+ let a = addr_of_mut!(A);
let cur = a.read_volatile();
for _ in 0..500 {
*t = (*t) * (*t) % 10007;
diff --git a/user/src/bin/adder_mutex_spin.rs b/user/src/bin/adder_mutex_spin.rs
index 315a338..f5750af 100644
--- a/user/src/bin/adder_mutex_spin.rs
+++ b/user/src/bin/adder_mutex_spin.rs
@@ -6,6 +6,7 @@ extern crate user_lib;
extern crate alloc;
use alloc::vec::Vec;
+use core::ptr::addr_of_mut;
use user_lib::{exit, get_time, thread_create, waittid};
use user_lib::{mutex_create, mutex_lock, mutex_unlock};
@@ -15,7 +16,7 @@ const THREAD_COUNT_DEFAULT: usize = 16;
static mut PER_THREAD: usize = 0;
unsafe fn critical_section(t: &mut usize) {
- let a = &mut A as *mut usize;
+ let a = addr_of_mut!(A);
let cur = a.read_volatile();
for _ in 0..500 {
*t = (*t) * (*t) % 10007;
diff --git a/user/src/bin/adder_peterson_spin.rs b/user/src/bin/adder_peterson_spin.rs
index 35fd0d3..44e8096 100644
--- a/user/src/bin/adder_peterson_spin.rs
+++ b/user/src/bin/adder_peterson_spin.rs
@@ -2,13 +2,13 @@
#![no_std]
#![no_main]
-#![feature(core_intrinsics)]
#[macro_use]
extern crate user_lib;
extern crate alloc;
use alloc::vec::Vec;
+use core::ptr::addr_of_mut;
use core::sync::atomic::{compiler_fence, Ordering};
use user_lib::{exit, get_time, thread_create, waittid};
@@ -20,7 +20,7 @@ const THREAD_COUNT_DEFAULT: usize = 2;
static mut PER_THREAD: usize = 0;
unsafe fn critical_section(t: &mut usize) {
- let a = &mut A as *mut usize;
+ let a = addr_of_mut!(A);
let cur = a.read_volatile();
for _ in 0..500 {
*t = (*t) * (*t) % 10007;
@@ -39,7 +39,7 @@ unsafe fn lock(id: usize) {
// Otherwise the compiler will assume that they will never
// be changed on this thread. Thus, they will be accessed
// only once!
- while vload!(&FLAG[j]) && vload!(&TURN) == j {}
+ while vload!(FLAG[j]) && vload!(TURN) == j {}
}
unsafe fn unlock(id: usize) {
diff --git a/user/src/bin/adder_peterson_yield.rs b/user/src/bin/adder_peterson_yield.rs
index 7b905e3..b25adf6 100644
--- a/user/src/bin/adder_peterson_yield.rs
+++ b/user/src/bin/adder_peterson_yield.rs
@@ -2,14 +2,16 @@
#![no_std]
#![no_main]
-#![feature(core_intrinsics)]
#[macro_use]
extern crate user_lib;
extern crate alloc;
use alloc::vec::Vec;
-use core::sync::atomic::{compiler_fence, Ordering};
+use core::{
+ ptr::addr_of_mut,
+ sync::atomic::{compiler_fence, Ordering},
+};
use user_lib::{exit, get_time, thread_create, waittid, yield_};
static mut A: usize = 0;
@@ -20,7 +22,7 @@ const THREAD_COUNT_DEFAULT: usize = 2;
static mut PER_THREAD: usize = 0;
unsafe fn critical_section(t: &mut usize) {
- let a = &mut A as *mut usize;
+ let a = addr_of_mut!(A);
let cur = a.read_volatile();
for _ in 0..500 {
*t = (*t) * (*t) % 10007;
diff --git a/user/src/bin/adder_simple_spin.rs b/user/src/bin/adder_simple_spin.rs
index ad5b328..be99d28 100644
--- a/user/src/bin/adder_simple_spin.rs
+++ b/user/src/bin/adder_simple_spin.rs
@@ -1,12 +1,12 @@
#![no_std]
#![no_main]
-#![feature(core_intrinsics)]
#[macro_use]
extern crate user_lib;
extern crate alloc;
use alloc::vec::Vec;
+use core::ptr::addr_of_mut;
use user_lib::{exit, get_time, thread_create, waittid};
static mut A: usize = 0;
@@ -16,7 +16,7 @@ const THREAD_COUNT_DEFAULT: usize = 16;
static mut PER_THREAD: usize = 0;
unsafe fn critical_section(t: &mut usize) {
- let a = &mut A as *mut usize;
+ let a = addr_of_mut!(A);
let cur = a.read_volatile();
for _ in 0..500 {
*t = (*t) * (*t) % 10007;
@@ -25,7 +25,7 @@ unsafe fn critical_section(t: &mut usize) {
}
unsafe fn lock() {
- while vload!(&OCCUPIED) {}
+ while vload!(OCCUPIED) {}
OCCUPIED = true;
}
diff --git a/user/src/bin/adder_simple_yield.rs b/user/src/bin/adder_simple_yield.rs
index 355b401..2de7924 100644
--- a/user/src/bin/adder_simple_yield.rs
+++ b/user/src/bin/adder_simple_yield.rs
@@ -1,12 +1,12 @@
#![no_std]
#![no_main]
-#![feature(core_intrinsics)]
#[macro_use]
extern crate user_lib;
extern crate alloc;
use alloc::vec::Vec;
+use core::ptr::addr_of_mut;
use user_lib::{exit, get_time, thread_create, waittid, yield_};
static mut A: usize = 0;
@@ -16,7 +16,7 @@ const THREAD_COUNT_DEFAULT: usize = 16;
static mut PER_THREAD: usize = 0;
unsafe fn critical_section(t: &mut usize) {
- let a = &mut A as *mut usize;
+ let a = addr_of_mut!(A);
let cur = a.read_volatile();
for _ in 0..500 {
*t = (*t) * (*t) % 10007;
diff --git a/user/src/bin/eisenberg.rs b/user/src/bin/eisenberg.rs
index 5f5b309..49a1d45 100644
--- a/user/src/bin/eisenberg.rs
+++ b/user/src/bin/eisenberg.rs
@@ -1,6 +1,5 @@
#![no_std]
#![no_main]
-#![feature(core_intrinsics)]
#[macro_use]
extern crate user_lib;
@@ -8,7 +7,9 @@ extern crate alloc;
extern crate core;
use alloc::vec::Vec;
-use core::sync::atomic::{AtomicUsize, Ordering};
+use core::{
+ sync::atomic::{AtomicUsize, Ordering},
+};
use user_lib::{exit, sleep, thread_create, waittid};
const N: usize = 2;
@@ -38,19 +39,19 @@ fn critical_test_exit() {
assert_eq!(GUARD.fetch_sub(1, Ordering::SeqCst), 1);
}
-fn eisenberg_enter_critical(id: usize) {
+unsafe fn eisenberg_enter_critical(id: usize) {
/* announce that we want to enter */
loop {
println!("Thread[{}] try enter", id);
- vstore!(&FLAG[id], FlagState::Want);
+ vstore!(FLAG[id], FlagState::Want);
loop {
/* check if any with higher priority is `Want` or `In` */
let mut prior_thread: Option = None;
- let turn = vload!(&TURN);
+ let turn = vload!(TURN);
let ring_id = if id < turn { id + THREAD_NUM } else { id };
// FLAG.iter() may lead to some errors, use for-loop instead
for i in turn..ring_id {
- if vload!(&FLAG[i % THREAD_NUM]) != FlagState::Out {
+ if vload!(FLAG[i % THREAD_NUM]) != FlagState::Out {
prior_thread = Some(i % THREAD_NUM);
break;
}
@@ -66,13 +67,13 @@ fn eisenberg_enter_critical(id: usize) {
sleep(1);
}
/* now tentatively claim the resource */
- vstore!(&FLAG[id], FlagState::In);
+ vstore!(FLAG[id], FlagState::In);
/* enforce the order of `claim` and `conflict check`*/
memory_fence!();
/* check if anthor thread is also `In`, which imply a conflict*/
let mut conflict = false;
for i in 0..THREAD_NUM {
- if i != id && vload!(&FLAG[i]) == FlagState::In {
+ if i != id && vload!(FLAG[i]) == FlagState::In {
conflict = true;
}
}
@@ -83,28 +84,28 @@ fn eisenberg_enter_critical(id: usize) {
/* no need to sleep */
}
/* clain the trun */
- vstore!(&TURN, id);
+ vstore!(TURN, id);
println!("Thread[{}] enter", id);
}
-fn eisenberg_exit_critical(id: usize) {
+unsafe fn eisenberg_exit_critical(id: usize) {
/* find next one who wants to enter and give the turn to it*/
let mut next = id;
let ring_id = id + THREAD_NUM;
for i in (id + 1)..ring_id {
let idx = i % THREAD_NUM;
- if vload!(&FLAG[idx]) == FlagState::Want {
+ if vload!(FLAG[idx]) == FlagState::Want {
next = idx;
break;
}
}
- vstore!(&TURN, next);
+ vstore!(TURN, next);
/* All done */
- vstore!(&FLAG[id], FlagState::Out);
+ vstore!(FLAG[id], FlagState::Out);
println!("Thread[{}] exit, give turn to {}", id, next);
}
-pub fn thread_fn(id: usize) -> ! {
+pub unsafe fn thread_fn(id: usize) -> ! {
println!("Thread[{}] init.", id);
for _ in 0..N {
eisenberg_enter_critical(id);
diff --git a/user/src/bin/peterson.rs b/user/src/bin/peterson.rs
index ee8ff93..e03e2a4 100644
--- a/user/src/bin/peterson.rs
+++ b/user/src/bin/peterson.rs
@@ -1,6 +1,5 @@
#![no_std]
#![no_main]
-#![feature(core_intrinsics)]
#[macro_use]
extern crate user_lib;
@@ -28,12 +27,12 @@ fn critical_test_exit() {
assert_eq!(GUARD.fetch_sub(1, Ordering::SeqCst), 1);
}
-fn peterson_enter_critical(id: usize, peer_id: usize) {
+unsafe fn peterson_enter_critical(id: usize, peer_id: usize) {
// println!("Thread[{}] try enter", id);
- vstore!(&FLAG[id], true);
- vstore!(&TURN, peer_id);
+ vstore!(FLAG[id], true);
+ vstore!(TURN, peer_id);
memory_fence!();
- while vload!(&FLAG[peer_id]) && vload!(&TURN) == peer_id {
+ while vload!(FLAG[peer_id]) && vload!(TURN) == peer_id {
// println!("Thread[{}] enter fail", id);
sleep(1);
// println!("Thread[{}] retry enter", id);
@@ -41,12 +40,12 @@ fn peterson_enter_critical(id: usize, peer_id: usize) {
// println!("Thread[{}] enter", id);
}
-fn peterson_exit_critical(id: usize) {
- vstore!(&FLAG[id], false);
+unsafe fn peterson_exit_critical(id: usize) {
+ vstore!(FLAG[id], false);
// println!("Thread[{}] exit", id);
}
-pub fn thread_fn(id: usize) -> ! {
+pub unsafe fn thread_fn(id: usize) -> ! {
// println!("Thread[{}] init.", id);
let peer_id: usize = id ^ 1;
for iter in 0..N {
diff --git a/user/src/bin/race_adder_arg.rs b/user/src/bin/race_adder_arg.rs
index ba99b62..f33c660 100644
--- a/user/src/bin/race_adder_arg.rs
+++ b/user/src/bin/race_adder_arg.rs
@@ -7,6 +7,7 @@ extern crate alloc;
use crate::alloc::string::ToString;
use alloc::vec::Vec;
+use core::ptr::addr_of_mut;
use user_lib::{exit, get_time, thread_create, waittid};
static mut A: usize = 0;
@@ -16,7 +17,7 @@ const THREAD_COUNT: usize = 16;
unsafe fn f(count: usize) -> ! {
let mut t = 2usize;
for _ in 0..PER_THREAD {
- let a = &mut A as *mut usize;
+ let a = addr_of_mut!(A);
let cur = a.read_volatile();
for _ in 0..count {
t = t * t % 10007;
diff --git a/user/src/lib.rs b/user/src/lib.rs
index bda0e8b..8c709fc 100644
--- a/user/src/lib.rs
+++ b/user/src/lib.rs
@@ -2,7 +2,6 @@
#![feature(linkage)]
#![feature(panic_info_message)]
#![feature(alloc_error_handler)]
-#![feature(core_intrinsics)]
#[macro_use]
pub mod console;
@@ -71,15 +70,17 @@ fn main(_argc: usize, _argv: &[&str]) -> i32 {
#[macro_export]
macro_rules! vstore {
- ($var_ref: expr, $value: expr) => {
- unsafe { core::intrinsics::volatile_store($var_ref as *const _ as _, $value) }
+ ($var: expr, $value: expr) => {
+ // unsafe { core::intrinsics::volatile_store($var_ref as *const _ as _, $value) }
+ unsafe { core::ptr::write_volatile(core::ptr::addr_of_mut!($var), $value); }
};
}
#[macro_export]
macro_rules! vload {
- ($var_ref: expr) => {
- unsafe { core::intrinsics::volatile_load($var_ref as *const _ as _) }
+ ($var: expr) => {
+ // unsafe { core::intrinsics::volatile_load($var_ref as *const _ as _) }
+ unsafe { core::ptr::read_volatile(core::ptr::addr_of!($var)) }
};
}