Skip to content

Commit 96fa4a6

Browse files
authored
Merge pull request #15 from Ivans-11/lab
fix: add CI workflow for qemu-base testing
2 parents 57b795e + 6c22ed2 commit 96fa4a6

17 files changed

Lines changed: 405 additions & 30 deletions

File tree

.github/workflows/workflow.yml

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: CI
1+
name: CI
22

33
on:
44
push:
@@ -21,6 +21,66 @@ jobs:
2121
- name: Check format
2222
run: cargo fmt --all --check
2323

24+
qemu-base:
25+
runs-on: ubuntu-latest
26+
timeout-minutes: 60
27+
steps:
28+
- uses: actions/checkout@v4
29+
30+
- name: Install system dependencies
31+
run: |
32+
sudo apt-get update
33+
sudo apt-get install -y \
34+
qemu-system-misc \
35+
python3 \
36+
git \
37+
curl \
38+
build-essential
39+
40+
- name: Sanity check system tools
41+
run: |
42+
set -eux
43+
qemu-system-riscv64 --version
44+
python3 --version
45+
git --version
46+
47+
- name: Install Rust toolchain
48+
uses: dtolnay/rust-toolchain@stable
49+
with:
50+
targets: riscv64gc-unknown-none-elf
51+
components: rust-src, llvm-tools-preview
52+
53+
- name: Sanity check Rust
54+
run: |
55+
set -eux
56+
rustc --version
57+
cargo --version
58+
rustup --version
59+
60+
- name: Mark workspace as safe git directory
61+
run: |
62+
git config --global --add safe.directory "$GITHUB_WORKSPACE"
63+
64+
- name: Checkout checker
65+
run: |
66+
git clone --depth 1 https://github.com/LearningOS/rCore-Tutorial-Checker-2025S.git checker
67+
68+
- name: Run base tests (ch2-8)
69+
run: |
70+
set -ux
71+
failed=0
72+
for ch in 2 3 4 5 6 7 8; do
73+
echo "========== Testing ch${ch} base =========="
74+
if timeout 6m cargo qemu --ch ${ch} --nobios --ci 2>&1 \
75+
| python3 checker/check/ch${ch}b.py; then
76+
echo "ch${ch} PASSED"
77+
else
78+
echo "ch${ch} FAILED"
79+
failed=1
80+
fi
81+
done
82+
exit $failed
83+
2484
qemu-exercise:
2585
runs-on: ubuntu-latest
2686
timeout-minutes: 30

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@
88
*.bin
99
!/rustsbi-qemu.bin
1010
!/**/m_entry.asm
11-
Cargo.lock
11+
Cargo.lock
12+
checker/

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ riscv = "0.10"
4747
numeric-enum-macro = "0.2"
4848

4949
# 内部 crate 依赖
50-
tg-console = { path = "tg-console", version = "0.1.0-preview.1" }
50+
tg-console = { path = "tg-console", version = "0.1.0-preview.2" }
5151
tg-linker = { path = "tg-linker", version = "0.1.0-preview.2" }
5252
tg-syscall = { path = "tg-syscall", version = "0.1.0-preview.2" }
5353
tg-kernel-context = { path = "tg-kernel-context", version = "0.1.0-preview.1" }

ch2/src/main.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use tg_syscall::{Caller, SyscallId};
1515
// 用户程序内联进来。
1616
core::arch::global_asm!(include_str!(env!("APP_ASM")));
1717
// 定义内核入口。
18-
tg_linker::boot0!(rust_main; stack = 4 * 4096);
18+
tg_linker::boot0!(rust_main; stack = 8 * 4096);
1919

2020
extern "C" fn rust_main() -> ! {
2121
// bss 段清零
@@ -34,9 +34,9 @@ extern "C" fn rust_main() -> ! {
3434
// 初始化上下文
3535
let mut ctx = LocalContext::user(app_base);
3636
// 设置用户栈(使用 MaybeUninit 避免 release 模式下零初始化的问题)
37-
let mut user_stack: core::mem::MaybeUninit<[usize; 256]> = core::mem::MaybeUninit::uninit();
37+
let mut user_stack: core::mem::MaybeUninit<[usize; 512]> = core::mem::MaybeUninit::uninit();
3838
let user_stack_ptr = user_stack.as_mut_ptr() as *mut usize;
39-
*ctx.sp_mut() = unsafe { user_stack_ptr.add(256) } as usize;
39+
*ctx.sp_mut() = unsafe { user_stack_ptr.add(512) } as usize;
4040
loop {
4141
unsafe { ctx.execute() };
4242

ch3/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ core::arch::global_asm!(include_str!(env!("APP_ASM")));
1818
// 应用程序数量。
1919
const APP_CAPACITY: usize = 32;
2020
// 定义内核入口。
21-
tg_linker::boot0!(rust_main; stack = (APP_CAPACITY + 2) * 4096);
21+
tg_linker::boot0!(rust_main; stack = (APP_CAPACITY + 2) * 8192);
2222

2323
extern "C" fn rust_main() -> ! {
2424
// bss 段清零

ch3/src/task.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use tg_kernel_context::LocalContext;
1+
use tg_kernel_context::LocalContext;
22
use tg_syscall::{Caller, SyscallId};
33

44
/// 任务控制块。
@@ -7,7 +7,7 @@ use tg_syscall::{Caller, SyscallId};
77
pub struct TaskControlBlock {
88
ctx: LocalContext,
99
pub finish: bool,
10-
stack: [usize; 256],
10+
stack: [usize; 1024], // 8KB 用户栈,避免栈溢出覆盖上下文
1111
}
1212

1313
/// 调度事件。
@@ -22,7 +22,7 @@ impl TaskControlBlock {
2222
pub const ZERO: Self = Self {
2323
ctx: LocalContext::empty(),
2424
finish: false,
25-
stack: [0; 256],
25+
stack: [0; 1024],
2626
};
2727

2828
/// 初始化一个任务。

tg-console/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "tg-console"
33
description = "Provides `print!`, `println!` and `log::Log` with customizable implementations for rCore tutorial."
4-
version = "0.1.0-preview.1"
4+
version = "0.1.0-preview.2"
55
edition = "2021"
66
authors = ["YdrMaster <ydrml@hotmail.com>"]
77
repository = "https://github.com/rcore-os/rCore-Tutorial-in-single-workspace"

tg-console/src/lib.rs

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! 提供可定制实现的 `print!`、`println!` 和 `log::Log`。
1+
//! 提供可定制实现的 `print!`、`println!` 和 `log::Log`。
22
33
#![no_std]
44
#![deny(warnings, missing_docs)]
@@ -31,6 +31,66 @@ pub trait Console: Sync {
3131
/// 库找到输出的方法:保存一个对象引用,这是一种单例。
3232
static CONSOLE: Once<&'static dyn Console> = Once::new();
3333

34+
/// 打印缓冲区大小。
35+
const BUFFER_SIZE: usize = 64;
36+
37+
/// 打印缓冲区,用于收集格式化输出后一次性输出,避免抢占导致输出交错。
38+
struct PrintBuffer {
39+
buffer: [u8; BUFFER_SIZE],
40+
pos: usize,
41+
}
42+
43+
impl PrintBuffer {
44+
/// 创建一个新的打印缓冲区。
45+
const fn new() -> Self {
46+
Self {
47+
buffer: [0u8; BUFFER_SIZE],
48+
pos: 0,
49+
}
50+
}
51+
52+
/// 刷新缓冲区,将内容输出到控制台。
53+
fn flush(&mut self) {
54+
if self.pos > 0 {
55+
if let Some(console) = CONSOLE.get() {
56+
// SAFETY: buffer 中的内容是从 str 写入的,保证是有效的 UTF-8
57+
let s = unsafe { core::str::from_utf8_unchecked(&self.buffer[..self.pos]) };
58+
console.put_str(s);
59+
}
60+
self.pos = 0;
61+
}
62+
}
63+
64+
/// 写入字符串到缓冲区,必要时刷新。
65+
fn write(&mut self, s: &str) {
66+
let bytes = s.as_bytes();
67+
let mut offset = 0;
68+
69+
while offset < bytes.len() {
70+
let remaining_buffer = BUFFER_SIZE - self.pos;
71+
let remaining_input = bytes.len() - offset;
72+
let to_copy = remaining_buffer.min(remaining_input);
73+
74+
self.buffer[self.pos..self.pos + to_copy]
75+
.copy_from_slice(&bytes[offset..offset + to_copy]);
76+
self.pos += to_copy;
77+
offset += to_copy;
78+
79+
// 缓冲区满了,刷新
80+
if self.pos == BUFFER_SIZE {
81+
self.flush();
82+
}
83+
}
84+
}
85+
}
86+
87+
impl Write for PrintBuffer {
88+
fn write_str(&mut self, s: &str) -> fmt::Result {
89+
self.write(s);
90+
Ok(())
91+
}
92+
}
93+
3494
/// 用户调用这个函数设置输出的方法。
3595
pub fn init_console(console: &'static dyn Console) {
3696
CONSOLE.call_once(|| console);
@@ -65,10 +125,13 @@ pub fn test_log() {
65125
/// 打印。
66126
///
67127
/// 给宏用的,用户不会直接调它。
128+
/// 使用栈上缓冲区收集格式化输出,然后一次性输出到控制台。
68129
#[doc(hidden)]
69130
#[inline]
70131
pub fn _print(args: fmt::Arguments) {
71-
Logger.write_fmt(args).unwrap();
132+
let mut buffer = PrintBuffer::new();
133+
buffer.write_fmt(args).unwrap();
134+
buffer.flush();
72135
}
73136

74137
/// 格式化打印。

tg-kernel-vm/src/space/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ impl<Meta: VmMeta, M: PageManager<Meta>> AddressSpace<Meta, M> {
116116
}
117117
vpn = vpn + 1;
118118
}
119+
120+
// 刷新地址空间
121+
#[cfg(target_arch = "riscv64")]
122+
unsafe {
123+
core::arch::asm!("sfence.vma")
124+
};
119125
}
120126

121127
/// 查找指定 VPN 的 PTE 指针(用于修改)

user/cases.toml

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ cases = [
77
"02power",
88
"03priv_inst",
99
"04priv_csr",
10+
"08power_3",
11+
"09power_5",
12+
"10power_7",
1013
]
1114

1215
[ch3]
@@ -51,13 +54,20 @@ cases = [
5154
"02power",
5255
"03priv_inst",
5356
"04priv_csr",
57+
"05write_a",
58+
"06write_b",
59+
"07write_c",
60+
"08power_3",
61+
"09power_5",
62+
"10power_7",
5463
"12forktest",
5564
"13forktree",
5665
"14forktest2",
5766
"15matrix",
5867
"fork_exit",
5968
"forktest_simple",
6069
"sbrk",
70+
"ch5b_usertest",
6171
"user_shell",
6272
"initproc",
6373
]
@@ -69,17 +79,24 @@ cases = [
6979
"02power",
7080
"03priv_inst",
7181
"04priv_csr",
82+
"05write_a",
83+
"06write_b",
84+
"07write_c",
85+
"08power_3",
86+
"09power_5",
87+
"10power_7",
7288
"12forktest",
7389
"13forktree",
7490
"14forktest2",
7591
"15matrix",
7692
"fork_exit",
7793
"forktest_simple",
7894
"sbrk",
79-
"user_shell",
80-
"initproc",
8195
"filetest_simple",
8296
"cat_filea",
97+
"ch6b_usertest",
98+
"user_shell",
99+
"initproc",
83100
]
84101

85102
[ch7]
@@ -89,15 +106,19 @@ cases = [
89106
"02power",
90107
"03priv_inst",
91108
"04priv_csr",
109+
"05write_a",
110+
"06write_b",
111+
"07write_c",
112+
"08power_3",
113+
"09power_5",
114+
"10power_7",
92115
"12forktest",
93116
"13forktree",
94117
"14forktest2",
95118
"15matrix",
96119
"fork_exit",
97120
"forktest_simple",
98121
"sbrk",
99-
"user_shell",
100-
"initproc",
101122
"filetest_simple",
102123
"cat_filea",
103124
"sig_simple",
@@ -106,6 +127,9 @@ cases = [
106127
"sig_tests",
107128
"pipetest",
108129
"pipe_large_test",
130+
"ch7b_usertest",
131+
"user_shell",
132+
"initproc",
109133
]
110134

111135
[ch8]
@@ -115,14 +139,18 @@ cases = [
115139
"02power",
116140
"03priv_inst",
117141
"04priv_csr",
142+
"05write_a",
143+
"06write_b",
144+
"07write_c",
145+
"08power_3",
146+
"09power_5",
147+
"10power_7",
118148
"12forktest",
119149
"13forktree",
120150
"14forktest2",
121151
"15matrix",
122152
"fork_exit",
123153
"forktest_simple",
124-
"user_shell",
125-
"initproc",
126154
"filetest_simple",
127155
"cat_filea",
128156
"sig_simple",
@@ -134,9 +162,13 @@ cases = [
134162
"mpsc_sem",
135163
"sync_sem",
136164
"race_adder_mutex_blocking",
165+
"phil_din_mutex",
137166
"test_condvar",
138167
"pipetest",
139168
"pipe_large_test",
169+
"ch8b_usertest",
170+
"user_shell",
171+
"initproc",
140172
]
141173

142174
[ch3_exercise]

0 commit comments

Comments
 (0)