Skip to content

Commit 9284987

Browse files
authored
riscv: 完成UEFI初始化,能正确设置memblock的信息 (#501)
* riscv: 完成UEFI初始化,能正确设置memblock的信息 * sbi增加reset功能 * 把虚拟CPU修改为sifive-u54,使qemu能更正确地模拟硬件行为 * 修复内存页面映射未设置“DIRTY”、”ACCESSED“、”GLOBAL“位,导致真机page fault的问题
1 parent a381e48 commit 9284987

File tree

22 files changed

+754
-130
lines changed

22 files changed

+754
-130
lines changed

kernel/src/arch/riscv64/asm/head.S

+39-16
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
#define SR_VS 0x00000600
1818
#define SR_FS_VS (SR_FS | SR_VS) /* Vector and Floating-Point Unit */
1919

20-
#define SATP_MODE_39 0x8000000000000000UL
21-
#define SATP_MODE_48 0x9000000000000000UL
22-
#define SATP_MODE_57 0xa000000000000000UL
20+
#define SATP_MODE_39 0x8000000000000000ULL
21+
#define SATP_MODE_48 0x9000000000000000ULL
22+
#define SATP_MODE_57 0xa000000000000000ULL
2323

2424
#define PAGE_OFFSET 0xffffffc000000000
2525
#define KERNEL_LINK_OFFSET 0x1000000
@@ -84,7 +84,6 @@ ENTRY(_start)
8484
call initial_map_1g_identical
8585

8686
__init_set_pgtable_loop_end:
87-
8887
call __initial_reloacate_enable_mmu
8988

9089
.option push
@@ -119,6 +118,7 @@ __initial_reloacate_enable_mmu:
119118
// 计算起始物理地址与内核高虚拟地址的偏移量
120119
la t0, __initial_start_load_paddr
121120
ld t0, 0(t0)
121+
122122

123123
li t1, KERNEL_VIRT_START
124124
sub t1, t1, t0
@@ -128,18 +128,27 @@ __initial_reloacate_enable_mmu:
128128

129129
/* Point stvec to virtual address of intruction after satp write */
130130
/* Set trap vector to spin forever to help debug */
131-
la a2, __initial_Lsecondary_park
131+
la a2, 1f
132132
add a2, a2, t1
133133
csrw CSR_TVEC, a2
134-
135134
// enable MMU
136135
la a2, __initial_pgtable
137136
srli a2, a2, 12
138137
la a0, __initial_satp_mode
139138
ld a0, 0(a0)
140139
or a2, a2, a0
140+
141+
141142
sfence.vma
142143
csrw satp, a2
144+
145+
1:
146+
la a0, __initial_Lsecondary_park
147+
add a0, a0, t1
148+
csrw CSR_TVEC, a0
149+
150+
csrw satp, a2
151+
sfence.vma
143152

144153
ret
145154

@@ -165,7 +174,7 @@ initial_map_256M_phys_addr:
165174
and t2, t2, t1
166175

167176
// 计算L0页表项的索引
168-
srl t2, t2, 30
177+
srli t2, t2, 30
169178
andi t2, t2, 511
170179

171180

@@ -220,7 +229,7 @@ __initial_set_l1_pgtable_loop:
220229
li t1, 0x3FFFFFFFFFFFFF
221230
and t3, t3, t1 // t3 = t3 & 0x3FFFFFFFFFFFFF
222231
slli t3, t3, 10 // t3 = t3 << 10
223-
ori t3, t3, 0xf // 设置L1页表项属性,R/W/X/V = 1
232+
ori t3, t3, 0xEF // 设置L1页表项属性,set R/W/X/V/A/D/G = 1
224233
// 设置L1页表项的值
225234
sd t3, 0(t0)
226235

@@ -262,41 +271,55 @@ initial_map_1g_identical:
262271
// 计算起始物理地址,存放在t0中
263272
and t0, t0, a0
264273

265-
274+
266275
// 把起始虚拟地址存储到t2中
267276
mv t2, a1
268277
// 按照1g对齐
269278
li t1, -0x40000000
270279
and t2, t2, t1
280+
271281

272282
// 右移30位,得到L0页表项的索引
273-
srl t2, t2, 30
283+
srli t2, t2, 30
274284
// 与511进行与运算,得到L0页表项的索引
275285
andi t2, t2, 511
276286

277287

278288
// 填写页表项
279-
// li t2, 0xf // 页表项属性, R/W/X/V = 1
280289
la t4, __initial_pgtable
281290
slli t3, t2, 3 // t3 = t2 * 8
282291
add t4, t4, t3 // t4 = t4 + t3
283292

293+
284294
mv t3, t0
285295
srli t3, t3, 12 // t3 = t0 >> 12 (page frame number)
286296
slli t3, t3, 10 // t3 = t3 << 10
287-
ori t3, t3, 0xf // set R/W/X/V = 1
288-
// 设置t0地址在L0页表中的值
297+
ori t3, t3, 0xEF // set R/W/X/V/A/D/G = 1
298+
299+
// 计算delta的pfn
300+
li t2, 0x40000000
301+
srli t2, t2, 12
302+
// 把delta pfn移位到页表项的第10位的位置
303+
slli t2, t2, 10
304+
li t1, 2
305+
306+
__loop_set_8g:
307+
308+
289309
sd t3, 0(t4)
290310

291311
// 增加 t4 的值
292312
addi t4, t4, 8
293-
// 增加 t3 的值(1G)
294-
li t2, 0x40000000
313+
// 增加1G的pfn
295314
add t3, t3, t2
296-
sd t3, 0(t4)
315+
316+
317+
addi t1, t1, -1
318+
bnez t1, __loop_set_8g
297319

298320
ret
299321

322+
300323
// 用于清空页表的空间
301324
// 参数:
302325
// a0: page table address

kernel/src/arch/riscv64/driver/sbi/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use self::legacy::console_putchar;
55
/// Some code takes from `https://github.com/repnop/sbi.git`
66
mod ecall;
77
pub mod legacy;
8+
pub mod reset;
89

910
/// Error codes returned by SBI calls
1011
///
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#![allow(dead_code)]
2+
use super::{ecall::ecall2, SbiError};
3+
4+
/// System reset extension ID
5+
pub const EXTENSION_ID: usize = 0x53525354;
6+
7+
/// The type of reset to perform
8+
#[derive(Debug, Clone, Copy)]
9+
pub enum ResetType {
10+
/// Shutdown the system
11+
Shutdown,
12+
/// Power off all hardware and perform a cold boot
13+
ColdReboot,
14+
/// Reset processors and some hardware
15+
WarmReboot,
16+
/// Platform specific reset type. The variant value is a value within the
17+
/// range `0x00000000..=0x0FFFFFFF`. A value outside of that range will be
18+
/// clamped to the maximum possible valid value for this reset type.
19+
PlatformSpecific(u32),
20+
}
21+
22+
impl ResetType {
23+
fn to_u32(self) -> u32 {
24+
match self {
25+
ResetType::Shutdown => 0,
26+
ResetType::ColdReboot => 1,
27+
ResetType::WarmReboot => 2,
28+
ResetType::PlatformSpecific(n) => n.min(0x0FFFFFFF) + 0xF0000000,
29+
}
30+
}
31+
}
32+
33+
/// The reason for performing the reset
34+
#[derive(Debug, Clone, Copy)]
35+
pub enum ResetReason {
36+
/// No reason for reset
37+
NoReason,
38+
/// System failure
39+
SystemFailure,
40+
/// SBI implementation specific reset reason. The variant value is a value
41+
/// within the range `0x00000000..=0x0FFFFFFF`. A value outside of that
42+
/// range will be clamped to the maximum possible valid value for this reset
43+
/// reason type.
44+
SbiSpecific(u32),
45+
/// Platform specific reset reason. The variant value is a value within the
46+
/// range `0x00000000..=0x0FFFFFFF`. A value outside of that range will be
47+
/// clamped to the maximum possible valid value for this reset reason type.
48+
PlatformSpecific(u32),
49+
}
50+
51+
impl ResetReason {
52+
fn to_u32(self) -> u32 {
53+
match self {
54+
ResetReason::NoReason => 0,
55+
ResetReason::SystemFailure => 1,
56+
ResetReason::SbiSpecific(n) => n.min(0x0FFFFFFF) + 0xE0000000,
57+
ResetReason::PlatformSpecific(n) => n.min(0x0FFFFFFF) + 0xF0000000,
58+
}
59+
}
60+
}
61+
62+
/// Attempt to reset the system in the provided method, with a reason for the
63+
/// reset.
64+
///
65+
/// ### Possible errors
66+
///
67+
/// [`SbiError::NotSupported`]: The [`ResetType`] is valid but not implemented.
68+
///
69+
/// [`SbiError::Failed`]: The system reset request failed for an unknown reason.
70+
pub fn system_reset(
71+
kind: ResetType,
72+
reason: ResetReason,
73+
) -> Result<core::convert::Infallible, SbiError> {
74+
match unsafe {
75+
ecall2(
76+
kind.to_u32() as usize,
77+
reason.to_u32() as usize,
78+
EXTENSION_ID,
79+
0,
80+
)
81+
} {
82+
Ok(_) => unreachable!("SBI returned `Ok` after a system reset call"),
83+
Err(e) => Err(e),
84+
}
85+
}

kernel/src/arch/riscv64/init/mod.rs

+5-14
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,11 @@ use core::intrinsics::unreachable;
33
use fdt::node::FdtNode;
44

55
use crate::{
6-
arch::{mm::init::mm_early_init, MMArch},
7-
driver::{
8-
firmware::efi::init::efi_init, open_firmware::fdt::open_firmware_fdt_driver,
9-
tty::serial::serial8250::send_to_default_serial8250_port,
10-
},
6+
arch::mm::init::mm_early_init,
7+
driver::{firmware::efi::init::efi_init, open_firmware::fdt::open_firmware_fdt_driver},
118
init::{boot_params, init_before_mem_init},
129
kdebug, kinfo,
13-
mm::{MemoryManagementArch, PhysAddr, VirtAddr},
10+
mm::{PhysAddr, VirtAddr},
1411
print, println,
1512
};
1613

@@ -39,14 +36,8 @@ impl ArchBootParams {
3936
#[no_mangle]
4037
unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! {
4138
let fdt_paddr = PhysAddr::new(fdt_paddr);
42-
39+
// system_reset(sbi::reset::ResetType::Shutdown, sbi::reset::ResetReason::NoReason);
4340
init_before_mem_init();
44-
extern "C" {
45-
fn BSP_IDLE_STACK_SPACE();
46-
}
47-
kdebug!("BSP_IDLE_STACK_SPACE={:#x}", BSP_IDLE_STACK_SPACE as u64);
48-
kdebug!("PAGE_ADDRESS_SIZE={}", MMArch::PAGE_ADDRESS_SIZE);
49-
kdebug!("PAGE_ADDRESS_SHIFT={}", MMArch::PAGE_ADDRESS_SHIFT);
5041

5142
boot_params().write().arch.fdt_paddr = fdt_paddr;
5243
kinfo!(
@@ -58,7 +49,7 @@ unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! {
5849
mm_early_init();
5950

6051
let fdt = fdt::Fdt::from_ptr(fdt_paddr.data() as *const u8).expect("Failed to parse fdt!");
61-
print_node(fdt.find_node("/").unwrap(), 0);
52+
// print_node(fdt.find_node("/").unwrap(), 0);
6253

6354
parse_dtb();
6455

kernel/src/arch/riscv64/mm/init.rs

+2-12
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,7 @@
1-
use system_error::SystemError;
2-
31
use crate::{
4-
arch::{
5-
mm::{KERNEL_BEGIN_PA, KERNEL_BEGIN_VA, KERNEL_END_PA, KERNEL_END_VA},
6-
MMArch,
7-
},
2+
arch::mm::{KERNEL_BEGIN_PA, KERNEL_BEGIN_VA, KERNEL_END_PA, KERNEL_END_VA},
83
kdebug,
9-
mm::{
10-
allocator::page_frame::PageFrameCount,
11-
no_init::{pseudo_map_phys, EARLY_IOREMAP_PAGES},
12-
page::{PageEntry, PageMapper, PageTable},
13-
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
14-
},
4+
mm::{PhysAddr, VirtAddr},
155
};
166

177
#[inline(never)]

kernel/src/arch/riscv64/mm/mod.rs

+15-16
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
use riscv::register::satp;
22
use system_error::SystemError;
33

4-
use crate::{
5-
kdebug,
6-
mm::{
7-
allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
8-
page::PageFlags,
9-
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
10-
},
4+
use crate::mm::{
5+
allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
6+
page::PageFlags,
7+
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
118
};
129

1310
pub mod bump;
@@ -28,6 +25,9 @@ pub(self) static mut KERNEL_END_VA: VirtAddr = VirtAddr::new(0);
2825
#[derive(Debug, Clone, Copy, Hash)]
2926
pub struct RiscV64MMArch;
3027

28+
impl RiscV64MMArch {
29+
pub const ENTRY_FLAG_GLOBAL: usize = 1 << 5;
30+
}
3131
impl MemoryManagementArch for RiscV64MMArch {
3232
const PAGE_SHIFT: usize = 12;
3333

@@ -38,13 +38,17 @@ impl MemoryManagementArch for RiscV64MMArch {
3838

3939
const ENTRY_ADDRESS_SHIFT: usize = 39;
4040

41-
const ENTRY_FLAG_DEFAULT_PAGE: usize = Self::ENTRY_FLAG_PRESENT;
41+
const ENTRY_FLAG_DEFAULT_PAGE: usize = Self::ENTRY_FLAG_PRESENT
42+
| Self::ENTRY_FLAG_READWRITE
43+
| Self::ENTRY_FLAG_DIRTY
44+
| Self::ENTRY_FLAG_ACCESSED
45+
| Self::ENTRY_FLAG_GLOBAL;
4246

4347
const ENTRY_FLAG_DEFAULT_TABLE: usize = Self::ENTRY_FLAG_PRESENT;
4448

4549
const ENTRY_FLAG_PRESENT: usize = 1 << 0;
4650

47-
const ENTRY_FLAG_READONLY: usize = 1 << 1;
51+
const ENTRY_FLAG_READONLY: usize = 0;
4852

4953
const ENTRY_FLAG_READWRITE: usize = (1 << 2) | (1 << 1);
5054

@@ -57,6 +61,8 @@ impl MemoryManagementArch for RiscV64MMArch {
5761
const ENTRY_FLAG_NO_EXEC: usize = 0;
5862

5963
const ENTRY_FLAG_EXEC: usize = (1 << 3);
64+
const ENTRY_FLAG_ACCESSED: usize = (1 << 6);
65+
const ENTRY_FLAG_DIRTY: usize = (1 << 7);
6066

6167
const PHYS_OFFSET: usize = 0xffff_ffc0_0000_0000;
6268

@@ -89,14 +95,11 @@ impl MemoryManagementArch for RiscV64MMArch {
8995

9096
let paddr = PhysPageFrame::from_ppn(ppn).phys_address();
9197

92-
kdebug!("table(): {paddr:?}, ppn: {ppn}");
93-
9498
return paddr;
9599
}
96100

97101
unsafe fn set_table(_table_kind: PageTableKind, table: PhysAddr) {
98102
let ppn = PhysPageFrame::new(table).ppn();
99-
kdebug!("set_table(): {table:?}, ppn:{ppn}");
100103
riscv::asm::sfence_vma_all();
101104
satp::set(satp::Mode::Sv39, 0, ppn);
102105
}
@@ -131,13 +134,11 @@ impl MemoryManagementArch for RiscV64MMArch {
131134
unsafe fn virt_2_phys(virt: VirtAddr) -> Option<PhysAddr> {
132135
if virt >= KERNEL_BEGIN_VA && virt < KERNEL_END_VA {
133136
let r = KERNEL_BEGIN_PA + (virt - KERNEL_BEGIN_VA);
134-
kdebug!("virt_2_phys: kernel address: virt = {virt:?}, paddr = {r:?}");
135137
return Some(r);
136138
}
137139

138140
if let Some(paddr) = virt.data().checked_sub(Self::PHYS_OFFSET) {
139141
let r = PhysAddr::new(paddr);
140-
kdebug!("virt_2_phys: non-kernel address: virt = {virt:?}, paddr = {r:?}");
141142
return Some(r);
142143
} else {
143144
return None;
@@ -147,8 +148,6 @@ impl MemoryManagementArch for RiscV64MMArch {
147148
fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize {
148149
let ppn = PhysPageFrame::new(paddr).ppn();
149150
let r = ((ppn & ((1 << 44) - 1)) << 10) | page_flags;
150-
151-
kdebug!("make entry: r={r:#x}");
152151
return r;
153152
}
154153
}

0 commit comments

Comments
 (0)