Skip to content

Commit 780ee4b

Browse files
committed
Init the ch3
1 parent 2730c60 commit 780ee4b

File tree

22 files changed

+642
-44
lines changed

22 files changed

+642
-44
lines changed

.github/workflows/build.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,51 @@ jobs:
2424
github_token: ${{ secrets.GITHUB_TOKEN }}
2525
publish_dir: ./os/target/riscv64gc-unknown-none-elf/doc
2626
destination_dir: ${{ github.ref_name }}
27+
basic-test:
28+
runs-on: ubuntu-latest
29+
outputs:
30+
points: ${{ steps.end.outputs.points}}
31+
container:
32+
image: duskmoon/dev-env:rcore-ci
33+
steps:
34+
- uses: actions/checkout@v4
35+
- name: Run tests
36+
run: |
37+
qemu-system-riscv64 --version
38+
rustup target add riscv64gc-unknown-none-elf
39+
git config --global --add safe.directory /__w/${{ github.event.repository.name }}/${{ github.event.repository.name }}
40+
git clone https://github.com/LearningOS/rCore-Tutorial-Checker.git ci-user
41+
git clone https://github.com/LearningOS/rCore-Tutorial-Test.git ci-user/user
42+
ID=`git rev-parse --abbrev-ref HEAD | grep -oP 'ch\K[0-9]'`
43+
# cd ci-user && make test CHAPTER=$ID passwd=${{ secrets.BASE_TEST_TOKEN }}
44+
cd ci-user && make test CHAPTER=$ID passwd=${{ secrets.BASE_TEST_TOKEN }} > ../output.txt
45+
cat ../output.txt
46+
- name: end
47+
id: end
48+
run: |
49+
cat output.txt | grep -a "Test passed" | grep -oP "\d{1,}/\d{1,}" | xargs -i echo "points={}"
50+
cat output.txt | grep -a "Test passed" | grep -oP "\d{1,}/\d{1,}" | xargs -i echo "points={}" >> $GITHUB_OUTPUT
51+
deploy:
52+
if: github.repository != 'LearningOS/rCore-Tutorial-Code'
53+
name: Deploy to pages
54+
needs: basic-test
55+
runs-on: ubuntu-latest
56+
permissions: write-all
57+
steps:
58+
- uses: actions/checkout@v3
59+
continue-on-error: true
60+
with:
61+
ref: 'gh-pages'
62+
- name: Save Log File
63+
uses: yfblock/multi-rank-log@main
64+
with:
65+
public-dir: classroom
66+
points: ${{ needs.basic-test.outputs.points }}
67+
- name: GitHub Pages
68+
uses: crazy-max/ghaction-github-pages@v3
69+
with:
70+
target_branch: gh-pages
71+
build_dir: ./classroom
72+
keep_history: true
73+
env:
74+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.gitignore

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@ os/src/link_app.S
88
os/last-*
99
os/Cargo.lock
1010
os/.gdb_history
11-
user/build
12-
user/target/*
13-
user/.idea/*
14-
user/Cargo.lock
1511
easy-fs/Cargo.lock
1612
easy-fs/target/*
1713
easy-fs-fuse/Cargo.lock
1814
easy-fs-fuse/target/*
1915
tools/
2016
pushall.sh
2117
*.bak
18+
ci-user/
19+
user/
20+
os/vendor/

Dockerfile

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,6 @@ RUN rustup --version && \
6565
cargo --version && \
6666
rustc --version
6767

68-
ARG RUST_VERSION=nightly-2025-09-18
69-
7068
# Install Rust components and tools for rCore development
7169
RUN rustup default $RUST_VERSION; \
7270
cargo install cargo-binutils; \

bootloader/rustsbi-qemu.bin

-328 Bytes
Binary file not shown.

os/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ edition = "2021"
77
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
88

99
[dependencies]
10+
buddy_system_allocator = "0.6"
1011
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
1112
log = "0.4"
12-
riscv = { git = "https://gitee.com/rcore-os/riscv", features = ["inline-asm"] }
13+
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] }

os/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ MODE := release
44
KERNEL_ELF := target/$(TARGET)/$(MODE)/os
55
KERNEL_BIN := $(KERNEL_ELF).bin
66
DISASM_TMP := target/$(TARGET)/$(MODE)/asm
7+
OFFLINE :=
78

89
# BOARD
910
BOARD := qemu
@@ -32,10 +33,12 @@ DISASM ?= -x
3233
build: env $(KERNEL_BIN)
3334

3435
env:
36+
ifeq ($(OFFLINE),)
3537
(rustup target list | grep "riscv64gc-unknown-none-elf (installed)") || rustup target add $(TARGET)
3638
cargo install cargo-binutils
3739
rustup component add rust-src
3840
rustup component add llvm-tools-preview
41+
endif
3942

4043
$(KERNEL_BIN): kernel
4144
@$(OBJCOPY) $(KERNEL_ELF) --strip-all -O binary $@

os/src/config.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//! Constants in the kernel
2+
3+
#[allow(unused)]
4+
5+
/// user app's stack size
6+
pub const USER_STACK_SIZE: usize = 4096;
7+
/// kernel stack size
8+
pub const KERNEL_STACK_SIZE: usize = 4096 * 2;
9+
/// kernel heap size
10+
pub const KERNEL_HEAP_SIZE: usize = 0x20000;
11+
/// the max number of apps
12+
pub const MAX_APP_NUM: usize = 16;
13+
/// base_addr(changed) of app
14+
pub const APP_BASE_ADDRESS: usize = 0x80400000;
15+
/// size limit of app
16+
pub const APP_SIZE_LIMIT: usize = 0x20000;
17+
18+
/// clock frequency
19+
pub const CLOCK_FREQ: usize = 12500000;
20+
/// the physical memory end
21+
pub const MEMORY_END: usize = 0x88000000;

os/src/heap_alloc.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//! The global allocator
2+
3+
use crate::config::KERNEL_HEAP_SIZE;
4+
use buddy_system_allocator::LockedHeap;
5+
6+
#[global_allocator]
7+
/// heap allocator instance
8+
static HEAP_ALLOCATOR: LockedHeap = LockedHeap::empty();
9+
10+
/// heap space ([u8; KERNEL_HEAP_SIZE])
11+
static mut HEAP_SPACE: [u8; KERNEL_HEAP_SIZE] = [0; KERNEL_HEAP_SIZE];
12+
13+
/// initiate heap allocator
14+
pub fn init_heap() {
15+
unsafe {
16+
HEAP_ALLOCATOR
17+
.lock()
18+
.init(HEAP_SPACE.as_ptr() as usize, KERNEL_HEAP_SIZE);
19+
}
20+
}
21+
22+
#[alloc_error_handler]
23+
/// panic when heap allocation error occurs
24+
pub fn handle_alloc_error(layout: core::alloc::Layout) -> ! {
25+
panic!("Heap allocation error, layout = {:?}", layout);
26+
}

os/src/loader.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//! Loading user applications into memory
2+
//!
3+
//! For chapter 3, user applications are simply part of the data included in the
4+
//! kernel binary, so we only need to copy them to the space allocated for each
5+
//! app to load them. We also allocate fixed spaces for each task's
6+
//! [`KernelStack`] and [`UserStack`].
7+
8+
use crate::config::*;
9+
use crate::trap::TrapContext;
10+
use core::arch::asm;
11+
12+
#[repr(align(4096))]
13+
#[derive(Copy, Clone)]
14+
struct KernelStack {
15+
data: [u8; KERNEL_STACK_SIZE],
16+
}
17+
18+
#[repr(align(4096))]
19+
#[derive(Copy, Clone)]
20+
struct UserStack {
21+
data: [u8; USER_STACK_SIZE],
22+
}
23+
24+
static KERNEL_STACK: [KernelStack; MAX_APP_NUM] = [KernelStack {
25+
data: [0; KERNEL_STACK_SIZE],
26+
}; MAX_APP_NUM];
27+
28+
static USER_STACK: [UserStack; MAX_APP_NUM] = [UserStack {
29+
data: [0; USER_STACK_SIZE],
30+
}; MAX_APP_NUM];
31+
32+
impl KernelStack {
33+
fn get_sp(&self) -> usize {
34+
self.data.as_ptr() as usize + KERNEL_STACK_SIZE
35+
}
36+
pub fn push_context(&self, trap_cx: TrapContext) -> usize {
37+
let trap_cx_ptr = (self.get_sp() - core::mem::size_of::<TrapContext>()) as *mut TrapContext;
38+
unsafe {
39+
*trap_cx_ptr = trap_cx;
40+
}
41+
trap_cx_ptr as usize
42+
}
43+
}
44+
45+
impl UserStack {
46+
fn get_sp(&self) -> usize {
47+
self.data.as_ptr() as usize + USER_STACK_SIZE
48+
}
49+
}
50+
51+
/// Get base address of app i.
52+
fn get_base_i(app_id: usize) -> usize {
53+
APP_BASE_ADDRESS + app_id * APP_SIZE_LIMIT
54+
}
55+
56+
/// Get the total number of applications.
57+
pub fn get_num_app() -> usize {
58+
extern "C" {
59+
fn _num_app();
60+
}
61+
unsafe { (_num_app as usize as *const usize).read_volatile() }
62+
}
63+
64+
/// Load nth user app at
65+
/// [APP_BASE_ADDRESS + n * APP_SIZE_LIMIT, APP_BASE_ADDRESS + (n+1) * APP_SIZE_LIMIT).
66+
pub fn load_apps() {
67+
extern "C" {
68+
fn _num_app();
69+
}
70+
let num_app_ptr = _num_app as usize as *const usize;
71+
let num_app = get_num_app();
72+
let app_start = unsafe { core::slice::from_raw_parts(num_app_ptr.add(1), num_app + 1) };
73+
// load apps
74+
for i in 0..num_app {
75+
let base_i = get_base_i(i);
76+
// clear region
77+
(base_i..base_i + APP_SIZE_LIMIT)
78+
.for_each(|addr| unsafe { (addr as *mut u8).write_volatile(0) });
79+
// load app from data section to memory
80+
let src = unsafe {
81+
core::slice::from_raw_parts(app_start[i] as *const u8, app_start[i + 1] - app_start[i])
82+
};
83+
let dst = unsafe { core::slice::from_raw_parts_mut(base_i as *mut u8, src.len()) };
84+
dst.copy_from_slice(src);
85+
}
86+
// Memory fence about fetching the instruction memory
87+
// It is guaranteed that a subsequent instruction fetch must
88+
// observes all previous writes to the instruction memory.
89+
// Therefore, fence.i must be executed after we have loaded
90+
// the code of the next app into the instruction memory.
91+
// See also: riscv non-priv spec chapter 3, 'Zifencei' extension.
92+
unsafe {
93+
asm!("fence.i");
94+
}
95+
}
96+
97+
/// get app info with entry and sp and save `TrapContext` in kernel stack
98+
pub fn init_app_cx(app_id: usize) -> usize {
99+
KERNEL_STACK[app_id].push_context(TrapContext::app_init_context(
100+
get_base_i(app_id),
101+
USER_STACK[app_id].get_sp(),
102+
))
103+
}

os/src/main.rs

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,40 +4,45 @@
44
//! important ones are:
55
//!
66
//! - [`trap`]: Handles all cases of switching from userspace to the kernel
7+
//! - [`task`]: Task management
78
//! - [`syscall`]: System call handling and implementation
89
//!
910
//! The operating system also starts in this module. Kernel code starts
1011
//! executing from `entry.asm`, after which [`rust_main()`] is called to
1112
//! initialize various pieces of functionality. (See its source code for
1213
//! details.)
1314
//!
14-
//! We then call [`batch::run_next_app()`] and for the first time go to
15+
//! We then call [`task::run_first_task()`] and for the first time go to
1516
//! userspace.
1617
1718
#![deny(missing_docs)]
1819
#![deny(warnings)]
1920
#![no_std]
2021
#![no_main]
2122
#![feature(panic_info_message)]
23+
#![feature(alloc_error_handler)]
24+
2225
#[macro_use]
2326
extern crate log;
2427

25-
use core::arch::global_asm;
26-
#[path = "boards/qemu.rs"]
27-
mod board;
28-
use log::*;
28+
extern crate alloc;
29+
2930
#[macro_use]
3031
mod console;
31-
pub mod batch;
32+
pub mod config;
33+
mod heap_alloc;
3234
pub mod lang_items;
35+
mod loader;
3336
pub mod logging;
3437
pub mod sbi;
3538
pub mod sync;
3639
pub mod syscall;
40+
pub mod task;
41+
pub mod timer;
3742
pub mod trap;
3843

39-
global_asm!(include_str!("entry.asm"));
40-
global_asm!(include_str!("link_app.S"));
44+
core::arch::global_asm!(include_str!("entry.asm"));
45+
core::arch::global_asm!(include_str!("link_app.S"));
4146

4247
/// clear BSS segment
4348
fn clear_bss() {
@@ -51,9 +56,8 @@ fn clear_bss() {
5156
}
5257
}
5358

54-
/// the rust entry-point of os
55-
#[no_mangle]
56-
pub fn rust_main() -> ! {
59+
/// kernel log info
60+
fn kernel_log_info() {
5761
extern "C" {
5862
fn stext(); // begin addr of text segment
5963
fn etext(); // end addr of text segment
@@ -66,7 +70,6 @@ pub fn rust_main() -> ! {
6670
fn boot_stack_lower_bound(); // stack lower bound
6771
fn boot_stack_top(); // stack top
6872
}
69-
clear_bss();
7073
logging::init();
7174
println!("[kernel] Hello, world!");
7275
trace!(
@@ -87,7 +90,18 @@ pub fn rust_main() -> ! {
8790
boot_stack_top as usize, boot_stack_lower_bound as usize
8891
);
8992
error!("[kernel] .bss [{:#x}, {:#x})", sbss as usize, ebss as usize);
93+
}
94+
95+
#[no_mangle]
96+
/// the rust entry-point of os
97+
pub fn rust_main() -> ! {
98+
clear_bss();
99+
kernel_log_info();
100+
heap_alloc::init_heap();
90101
trap::init();
91-
batch::init();
92-
batch::run_next_app();
102+
loader::load_apps();
103+
trap::enable_timer_interrupt();
104+
timer::set_next_trigger();
105+
task::run_first_task();
106+
panic!("Unreachable in rust_main!");
93107
}

0 commit comments

Comments
 (0)