Skip to content

Commit 2d4a1c7

Browse files
committed
feat: 恢复从设备树解析外设地址
- 使用解析的外设地址初始化 SBI 依赖的外设 - 细致配置 pmp 保护区段
1 parent 59fbedb commit 2d4a1c7

File tree

3 files changed

+80
-29
lines changed

3 files changed

+80
-29
lines changed

rustsbi-qemu/src/device_tree.rs

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use alloc::{string::String, vec, vec::Vec};
22
use core::ops::Range;
33

4+
#[derive(Debug)]
45
pub(crate) struct BoardInfo {
56
pub dtb: Range<usize>,
67
pub model: String,
@@ -12,45 +13,72 @@ pub(crate) struct BoardInfo {
1213
}
1314

1415
pub(crate) fn parse(opaque: usize) -> BoardInfo {
15-
use dtb_walker::{Dtb, DtbObj, Property, WalkOperation};
16+
use dtb_walker::{Dtb, DtbObj, Property, WalkOperation::*};
17+
const CPUS: &[u8] = b"cpus";
18+
const MEMORY: &[u8] = b"memory";
19+
const SOC: &[u8] = b"soc";
20+
const UART: &[u8] = b"uart";
21+
const TEST: &[u8] = b"test";
22+
const CLINT: &[u8] = b"clint";
1623

1724
let mut ans = BoardInfo {
1825
dtb: opaque..opaque,
1926
model: String::new(),
2027
smp: 0,
2128
mem: vec![],
22-
uart: 0x1000_0000..0x1000_0100,
23-
test: 0x10_0000..0x10_1000,
24-
clint: 0x200_0000..0x201_0000,
29+
uart: 0..0,
30+
test: 0..0,
31+
clint: 0..0,
2532
};
2633
let dtb = unsafe { Dtb::from_raw_parts(opaque as _) }.unwrap();
2734
ans.dtb.end += dtb.total_size();
2835
dtb.walk(|path, obj| match obj {
2936
DtbObj::SubNode { name } => {
30-
if path.last().is_empty() && name == b"cpus" {
31-
WalkOperation::StepInto
32-
} else if path.last() == b"cpus" && name.starts_with(b"cpu@") {
33-
ans.smp += 1;
34-
WalkOperation::StepOver
35-
} else if path.last().is_empty() && name.starts_with(b"memory") {
36-
WalkOperation::StepInto
37+
let current = path.last();
38+
if current.is_empty() {
39+
if name == CPUS || name == SOC || name.starts_with(MEMORY) {
40+
StepInto
41+
} else {
42+
StepOver
43+
}
44+
} else if current == SOC {
45+
if name.starts_with(UART) || name.starts_with(TEST) || name.starts_with(CLINT) {
46+
StepInto
47+
} else {
48+
StepOver
49+
}
3750
} else {
38-
WalkOperation::StepOver
51+
if current == CPUS && name.starts_with(b"cpu@") {
52+
ans.smp += 1;
53+
}
54+
StepOver
3955
}
4056
}
4157
DtbObj::Property(Property::Model(model)) if path.last().is_empty() => {
4258
if let Ok(model) = model.as_str() {
4359
ans.model = model.into();
4460
}
45-
WalkOperation::StepOver
61+
StepOver
4662
}
47-
DtbObj::Property(Property::Reg(reg)) if path.last().starts_with(b"memory") => {
48-
for region in reg {
49-
ans.mem.push(region);
63+
DtbObj::Property(Property::Reg(mut reg)) => {
64+
let node = path.last();
65+
if node.starts_with(UART) {
66+
ans.uart = reg.next().unwrap();
67+
StepOut
68+
} else if node.starts_with(TEST) {
69+
ans.test = reg.next().unwrap();
70+
StepOut
71+
} else if node.starts_with(CLINT) {
72+
ans.clint = reg.next().unwrap();
73+
StepOut
74+
} else if node.starts_with(MEMORY) {
75+
ans.mem = reg.into_iter().collect();
76+
StepOut
77+
} else {
78+
StepOver
5079
}
51-
WalkOperation::StepOut
5280
}
53-
DtbObj::Property(_) => WalkOperation::StepOver,
81+
DtbObj::Property(_) => StepOver,
5482
});
5583

5684
ans

rustsbi-qemu/src/hart_csr_utils.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ use riscv::register::{
44
misa::{self, MXL},
55
};
66

7-
pub fn print_hart_csrs() {
7+
pub(crate) fn print_hart_csrs() {
88
print_misa();
99
print_mideleg();
1010
print_medeleg();
11-
print_pmps();
1211
}
1312

1413
#[inline]
@@ -112,7 +111,7 @@ fn print_medeleg() {
112111
);
113112
}
114113

115-
fn print_pmps() {
114+
pub(crate) fn print_pmps() {
116115
const ITEM_PER_CFG: usize = core::mem::size_of::<usize>();
117116
const CFG_STEP: usize = ITEM_PER_CFG / core::mem::size_of::<u32>();
118117

rustsbi-qemu/src/main.rs

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ extern crate alloc;
1212
mod clint;
1313
mod device_tree;
1414
mod execute;
15+
mod hart_csr_utils;
1516
mod ns16550a;
1617
mod qemu_hsm;
1718
mod test_device;
@@ -106,6 +107,7 @@ extern "C" fn early_trap() -> ! {
106107
}
107108

108109
use core::sync::atomic::{AtomicBool, Ordering::AcqRel};
110+
use device_tree::BoardInfo;
109111
use spin::Once;
110112

111113
#[link_section = ".bss.uninit"]
@@ -117,6 +119,8 @@ extern "C" fn rust_main(_hartid: usize, opaque: usize) {
117119

118120
#[link_section = ".bss.uninit"]
119121
static GENESIS: AtomicBool = AtomicBool::new(false);
122+
static CSR_PRINT: AtomicBool = AtomicBool::new(false);
123+
static BOARD_INFO: Once<BoardInfo> = Once::new();
120124

121125
// 全局初始化过程
122126
if !GENESIS.swap(true, AcqRel) {
@@ -125,7 +129,7 @@ extern "C" fn rust_main(_hartid: usize, opaque: usize) {
125129
// 初始化堆和分配器
126130
init_heap();
127131
// 解析设备树,需要堆来保存结果里的字符串等
128-
let board_info = device_tree::parse(opaque);
132+
let board_info = BOARD_INFO.call_once(|| device_tree::parse(opaque));
129133
// 初始化外设
130134
clint::init(board_info.clint.start);
131135
test_device::init(board_info.test.start);
@@ -165,7 +169,10 @@ extern "C" fn rust_main(_hartid: usize, opaque: usize) {
165169

166170
let hsm = HSM.wait();
167171
if let Some(supervisor) = hsm.take_supervisor() {
168-
set_pmp();
172+
set_pmp(BOARD_INFO.wait());
173+
if !CSR_PRINT.swap(true, AcqRel) {
174+
hart_csr_utils::print_pmps();
175+
}
169176
execute::execute_supervisor(hsm, supervisor);
170177
}
171178
}
@@ -209,14 +216,31 @@ fn init_heap() {
209216
}
210217

211218
/// 设置 PMP。
212-
fn set_pmp() {
213-
use riscv::register::{pmpaddr0, pmpaddr1, pmpcfg0, Permission, Range};
219+
fn set_pmp(board_info: &BoardInfo) {
220+
use riscv::register::{
221+
pmpaddr0, pmpaddr1, pmpaddr2, pmpaddr3, pmpaddr4, pmpaddr5, pmpcfg0, Permission, Range,
222+
};
223+
let mem = &board_info.mem[0];
224+
let dtb = &board_info.dtb;
214225
unsafe {
215-
pmpcfg0::set_pmp(0, Range::NAPOT, Permission::RWX, false);
216-
pmpcfg0::set_pmp(1, Range::NAPOT, Permission::NONE, false);
226+
pmpcfg0::set_pmp(0, Range::OFF, Permission::NONE, true);
227+
pmpaddr0::write(0);
228+
// 外设
229+
pmpcfg0::set_pmp(1, Range::TOR, Permission::RW, false);
230+
pmpaddr1::write(mem.start >> 2);
231+
// SBI
232+
pmpcfg0::set_pmp(2, Range::TOR, Permission::NONE, false);
233+
pmpaddr2::write(SUPERVISOR_ENTRY >> 2);
234+
// 主存
235+
pmpcfg0::set_pmp(3, Range::TOR, Permission::RWX, true);
236+
pmpaddr3::write(dtb.start >> 2);
237+
// 设备树
238+
pmpcfg0::set_pmp(4, Range::TOR, Permission::R, false);
239+
pmpaddr4::write(dtb.end >> 2);
240+
//主存
241+
pmpcfg0::set_pmp(5, Range::TOR, Permission::RWX, true);
242+
pmpaddr5::write(mem.end >> 2);
217243
}
218-
pmpaddr0::write(usize::MAX);
219-
pmpaddr1::write((entry as usize >> 2) | 0x10_0000 >> 2);
220244
}
221245

222246
#[inline(always)]

0 commit comments

Comments
 (0)