Skip to content

Commit a6c8f38

Browse files
committed
feat: test-kernel 使用自己的串口驱动
1 parent ff916db commit a6c8f38

File tree

9 files changed

+70
-75
lines changed

9 files changed

+70
-75
lines changed

Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rustsbi-qemu/Cargo.toml

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

99
[dependencies]
10-
rustsbi = { git = "https://github.com/YdrMaster/rustsbi.git", rev = "bdd67f8" }
10+
rustsbi = { git = "https://github.com/YdrMaster/rustsbi.git", rev = "e17920b" }
1111
riscv = "0.8"
1212
spin = "0.9"
1313
r0 = "1"

rustsbi-qemu/src/main.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ use device_tree::BoardInfo;
111111
use spin::Once;
112112

113113
#[link_section = ".bss.uninit"]
114-
static mut SERIAL: Option<ns16550a::Ns16550a> = None;
114+
static SERIAL: Once<ns16550a::Ns16550a> = Once::new();
115115

116116
#[link_section = ".bss.uninit"]
117117
static HSM: Once<qemu_hsm::QemuHsm> = Once::new();
@@ -136,10 +136,10 @@ extern "C" fn rust_main(_hartid: usize, opaque: usize) {
136136
// 初始化外设
137137
clint::init(board_info.clint.start);
138138
test_device::init(board_info.test.start);
139-
unsafe { SERIAL = Some(ns16550a::Ns16550a::new(board_info.uart.start)) };
139+
let serial = SERIAL.call_once(|| unsafe { ns16550a::Ns16550a::new(board_info.uart.start) });
140140
let hsm = HSM.call_once(|| qemu_hsm::QemuHsm::new(clint::get(), NUM_HART_MAX, opaque));
141141
// 初始化 SBI 服务
142-
rustsbi::legacy_stdio::init_legacy_stdio(unsafe { SERIAL.as_mut() }.unwrap());
142+
rustsbi::legacy_stdio::init_legacy_stdio(serial);
143143
rustsbi::init_ipi(clint::get());
144144
rustsbi::init_timer(clint::get());
145145
rustsbi::init_reset(test_device::get());
@@ -238,7 +238,7 @@ fn set_pmp(board_info: &BoardInfo) {
238238
pmpcfg0::set_pmp(3, Range::TOR, Permission::RWX, false);
239239
pmpaddr3::write(dtb.start >> 2);
240240
// 设备树
241-
pmpcfg0::set_pmp(4, Range::TOR, Permission::R, false);
241+
pmpcfg0::set_pmp(4, Range::TOR, Permission::RW, false);
242242
pmpaddr4::write(dtb.end >> 2);
243243
//主存
244244
pmpcfg0::set_pmp(5, Range::TOR, Permission::RWX, false);

rustsbi-qemu/src/ns16550a.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
1+
use core::fmt::Write;
12
use rustsbi::legacy_stdio::LegacyStdio;
3+
use spin::Mutex;
24
use uart_16550::MmioSerialPort;
35

4-
pub(crate) struct Ns16550a(MmioSerialPort);
6+
pub(crate) struct Ns16550a(Mutex<MmioSerialPort>);
57

68
impl Ns16550a {
79
pub unsafe fn new(base: usize) -> Self {
8-
Self(MmioSerialPort::new(base))
10+
Self(Mutex::new(MmioSerialPort::new(base)))
911
}
1012
}
1113

1214
impl LegacyStdio for Ns16550a {
13-
fn getchar(&mut self) -> u8 {
14-
self.0.receive()
15+
fn getchar(&self) -> u8 {
16+
self.0.lock().receive()
1517
}
1618

17-
fn putchar(&mut self, ch: u8) {
18-
self.0.send(ch);
19+
fn putchar(&self, ch: u8) {
20+
self.0.lock().send(ch);
21+
}
22+
23+
fn write_str(&self, s: &str) {
24+
self.0.lock().write_str(s).unwrap();
1925
}
2026
}

test-kernel/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ spin = "0.9"
1414
r0 = "1"
1515
lazy_static = { version = "1", features = ["spin_no_std"] }
1616
dtb-walker = { git = "https://github.com/YdrMaster/dtb-walker.git", rev = "0ef2209" }
17+
uart_16550 = "0.2"

test-kernel/src/console.rs

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,15 @@
1-
use core::fmt::{Arguments, Result, Write};
2-
use spin::Mutex;
1+
use core::fmt::{Arguments, Write};
2+
use spin::{Mutex, Once};
3+
use uart_16550::MmioSerialPort;
34

4-
struct Stdout;
5+
static NS16550A: Once<Mutex<MmioSerialPort>> = Once::new();
56

6-
impl Write for Stdout {
7-
fn write_str(&mut self, s: &str) -> Result {
8-
let mut buffer = [0u8; 4];
9-
for c in s.chars() {
10-
for code_point in c.encode_utf8(&mut buffer).as_bytes().iter() {
11-
sbi::legacy::console_putchar(*code_point as usize);
12-
}
13-
}
14-
Ok(())
15-
}
7+
pub(crate) fn init(base: usize) {
8+
NS16550A.call_once(|| Mutex::new(unsafe { MmioSerialPort::new(base) }));
169
}
1710

1811
pub fn print(args: Arguments) {
19-
lazy_static::lazy_static! {
20-
static ref STDOUT: Mutex<Stdout> = Mutex::new(Stdout);
21-
}
22-
23-
STDOUT.lock().write_fmt(args).unwrap();
12+
NS16550A.wait().lock().write_fmt(args).unwrap();
2413
}
2514

2615
#[macro_export]
@@ -32,9 +21,9 @@ macro_rules! print {
3221

3322
#[macro_export]
3423
macro_rules! println {
35-
() => ($crate::print!("\r\n"));
24+
() => ($crate::print!("\n"));
3625
($($arg:tt)*) => {
3726
$crate::console::print(core::format_args!($($arg)*));
38-
$crate::print!("\r\n");
27+
$crate::print!("\n");
3928
}
4029
}

test-kernel/src/main.rs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ static mut EXPECTED: [Option<Trap>; 8] = [None; 8];
6767
extern "C" fn primary_rust_main(hartid: usize, dtb_pa: usize) -> ! {
6868
zero_bss();
6969

70-
let smp = parse_smp(dtb_pa);
70+
let BoardInfo { smp, uart } = parse_smp(dtb_pa);
71+
console::init(uart);
7172
println!(
7273
r"
7374
_____ _ _ __ _
@@ -256,25 +257,37 @@ fn zero_bss() {
256257
unsafe { r0::zero_bss(&mut sbss, &mut ebss) };
257258
}
258259

259-
fn parse_smp(dtb_pa: usize) -> usize {
260-
use dtb_walker::{Dtb, DtbObj, WalkOperation};
260+
struct BoardInfo {
261+
smp: usize,
262+
uart: usize,
263+
}
264+
265+
fn parse_smp(dtb_pa: usize) -> BoardInfo {
266+
use dtb_walker::{Dtb, DtbObj, Property, WalkOperation::*};
261267

262-
let mut smp = 0usize;
268+
let mut ans = BoardInfo { smp: 0, uart: 0 };
263269
unsafe { Dtb::from_raw_parts(dtb_pa as _) }
264270
.unwrap()
265271
.walk(|path, obj| match obj {
266272
DtbObj::SubNode { name } => {
267-
if path.last().is_empty() && name == b"cpus" {
268-
WalkOperation::StepInto
273+
if path.last().is_empty() && (name == b"cpus" || name == b"soc") {
274+
StepInto
269275
} else if path.last() == b"cpus" && name.starts_with(b"cpu@") {
270-
smp += 1;
271-
WalkOperation::StepOver
276+
ans.smp += 1;
277+
StepOver
278+
} else if path.last() == b"soc" && name.starts_with(b"uart") {
279+
StepInto
272280
} else {
273-
WalkOperation::StepOver
281+
StepOver
274282
}
275283
}
276-
DtbObj::Property(_) => WalkOperation::StepOver,
284+
DtbObj::Property(Property::Reg(mut reg)) => {
285+
if path.last().starts_with(b"uart") {
286+
ans.uart = reg.next().unwrap().start;
287+
}
288+
StepOut
289+
}
290+
DtbObj::Property(_) => StepOver,
277291
});
278-
279-
smp
292+
ans
280293
}

test-kernel/src/test.rs

Lines changed: 14 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
use core::sync::atomic::{AtomicUsize, Ordering};
2-
3-
pub(crate) fn base_extension() {
1+
pub(crate) fn base_extension() {
42
println!(
53
"
64
[test-kernel] Testing base extension"
@@ -88,7 +86,8 @@ pub(crate) fn trap_delegate(hartid: usize) {
8886
/// 所有核一起等待原子变量归零,然后副核调用 [`sbi::hart_stop`] 关闭。
8987
/// 主核等待所有副核关闭,然后退出。
9088
pub(crate) fn start_stop_harts(hartid: usize, smp: usize) {
91-
static STARTED: AtomicUsize = AtomicUsize::new(0);
89+
use spin::{Barrier, Once};
90+
static BARRIER: Once<Barrier> = Once::new();
9291

9392
#[naked]
9493
unsafe extern "C" fn test_start_entry(hartid: usize) -> ! {
@@ -102,12 +101,9 @@ pub(crate) fn start_stop_harts(hartid: usize, smp: usize) {
102101
)
103102
}
104103

105-
extern "C" fn secondary_rust_main(_hart_id: usize) -> ! {
106-
STARTED.fetch_sub(1, Ordering::AcqRel);
107-
while STARTED.load(Ordering::Acquire) != 0 {
108-
delay(0x8000_0000usize);
109-
}
110-
sbi::hart_stop();
104+
extern "C" fn secondary_rust_main(hart_id: usize) -> ! {
105+
BARRIER.wait().wait();
106+
println!("stop [{hart_id}] but {:?}", sbi::hart_stop());
111107
unreachable!()
112108
}
113109

@@ -117,10 +113,10 @@ pub(crate) fn start_stop_harts(hartid: usize, smp: usize) {
117113
);
118114

119115
// 启动副核
116+
let barrier = BARRIER.call_once(|| Barrier::new(smp));
120117
for id in 0..smp {
121118
if id != hartid {
122119
println!("[test-kernel] Hart{id} is booting...");
123-
STARTED.fetch_add(1, Ordering::AcqRel);
124120
let ret = sbi::hart_start(id, test_start_entry as usize, 0);
125121
if ret.error != sbi::SBI_SUCCESS {
126122
panic!("[test-kernel] Start hart{id} failed: {ret:?}");
@@ -130,30 +126,19 @@ pub(crate) fn start_stop_harts(hartid: usize, smp: usize) {
130126
}
131127
}
132128
// 等待副核启动完成
133-
while STARTED.load(Ordering::Acquire) != 0 {
134-
for id in 0..smp {
135-
print!("{:?}", sbi::hart_get_status(id));
136-
}
137-
println!("({}/{smp})", STARTED.load(Ordering::SeqCst));
138-
delay(0x8000_0000usize);
139-
}
140-
println!("[test-kernel] All harts boot successfully!");
129+
barrier.wait();
130+
print!("[test-kernel] All harts boot successfully!\n");
141131
// 等待副核关闭
142132
for id in 0..smp {
143133
const STOPPED: sbi::SbiRet = sbi::SbiRet { error: 0, value: 1 };
144134
if id != hartid {
145-
while sbi::hart_get_status(id) != STOPPED {
146-
delay(0x8000_0000usize);
135+
let status = sbi::hart_get_status(id);
136+
if status != STOPPED {
137+
println!("[test-kernel] Hart{id} waiting: {:?}.", status);
138+
} else {
139+
println!("[test-kernel] Hart{id} stopped.");
147140
}
148-
println!("[test-kernel] Hart{id} stopped.");
149141
}
150142
}
151143
println!("[test-kernel] All harts stop successfully!");
152144
}
153-
154-
#[inline(always)]
155-
fn delay(cycle: usize) {
156-
for _ in 0..cycle {
157-
core::hint::spin_loop();
158-
}
159-
}

xtask/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ fn xtask_qemu_run(xtask_env: &XtaskEnv) {
216216
.args(&["-machine", "virt"])
217217
.args(&["-bios", "rustsbi-qemu.bin"])
218218
.args(&["-kernel", "test-kernel.bin"])
219-
.args(&["-smp", "8"]) // 8 cores
219+
.args(&["-smp", "3"]) // 8 cores
220220
.arg("-nographic")
221221
.status()
222222
.unwrap();
@@ -233,7 +233,7 @@ fn xtask_qemu_debug(xtask_env: &XtaskEnv) {
233233
.args(&["-machine", "virt"])
234234
.args(&["-bios", "rustsbi-qemu.bin"])
235235
.args(&["-kernel", "test-kernel.bin"])
236-
.args(&["-smp", "8"]) // 8 cores
236+
.args(&["-smp", "3"]) // 8 cores
237237
.arg("-nographic")
238238
.args(&["-gdb", "tcp::1234", "-S"])
239239
.status()

0 commit comments

Comments
 (0)