Checkpoint: kernel remap

This commit is contained in:
luojia65 2021-01-25 15:11:59 +08:00
parent 791b0c5a3d
commit 7d64ab8335
8 changed files with 62 additions and 26 deletions

View File

@ -22,6 +22,22 @@ pub struct TrapFrame {
sepc: usize,
}
use core::fmt;
impl fmt::Display for TrapFrame {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let x = self.x;
writeln!(f, "")?;
writeln!(f, "x0: {:016x}, ra: {:016x}, sp: {:016x}, gp: {:016x}", 0, x[1], x[2], x[3])?;
writeln!(f, "tp: {:016x}, t0: {:016x}, t1: {:016x}, t2: {:016x}", x[4], x[5], x[6], x[7])?;
writeln!(f, "s0: {:016x}, s1: {:016x}, a0: {:016x}, a1: {:016x}", x[8], x[9], x[10], x[11])?;
writeln!(f, "a2: {:016x}, a3: {:016x}, a4: {:016x}, a5: {:016x}", x[12], x[13], x[14], x[15])?;
writeln!(f, "a6: {:016x}, a7: {:016x}, s2: {:016x}, s3: {:016x}", x[16], x[17], x[18], x[19])?;
writeln!(f, "s4: {:016x}, s5: {:016x}, s6: {:016x}, s7: {:016x}", x[20], x[21], x[22], x[23])?;
writeln!(f, "s8: {:016x}, s9: {:016x}, s10:{:016x}, s11:{:016x}", x[24], x[25], x[26], x[27])?;
writeln!(f, "t3: {:016x}, t4: {:016x}, t5: {:016x}, t6: {:016x}", x[28], x[29], x[30], x[31])
}
}
#[export_name = "rust_supervisor_timer"]
pub extern "C" fn supervisor_timer(trap_frame: &mut TrapFrame) -> *mut TrapFrame {
// panic!("Supervisor timer: {:08x}", sepc::read());
@ -44,7 +60,7 @@ pub extern "C" fn trap_exception(trap_frame: &mut TrapFrame) -> *mut TrapFrame {
match scause::read().cause() {
Trap::Exception(Exception::Breakpoint) => breakpoint(trap_frame),
Trap::Exception(e) =>
panic!("Exception! {:?}, sepc: {:#08x}", e, sepc::read()),
panic!("Exception! {:?}, sepc: {:#08x}, trap_frame: {}", e, sepc::read(), trap_frame),
Trap::Interrupt(_) => unreachable!("SBI or CPU design fault")
}
}

View File

@ -35,7 +35,8 @@ SECTIONS
*(.sbss .bss .bss.*)
_ebss = .;
}
. = ALIGN(4K);
free_memory_start = .;
/DISCARD/ : {

View File

@ -45,9 +45,7 @@ pub extern "C" fn rust_main() -> ! {
}
println!("heap test passed");
#[cfg(riscv)]
let remap = memory::MemorySet::new_kernel().unwrap();
#[cfg(riscv)]
remap.activate();
println!("kernel remapped");

View File

@ -70,6 +70,11 @@ impl VirtualAddress {
pub unsafe fn deref_virtual<T>(self) -> &'static mut T {
&mut *(self.0 as *mut T)
}
// 线性映射下,得到物理地址对应的虚拟地址
pub fn physical_address_linear(self) -> PhysicalAddress {
let pa = self.0.wrapping_sub(KERNEL_MAP_OFFSET);
PhysicalAddress(pa)
}
}
impl core::ops::Add<usize> for VirtualAddress {
@ -88,7 +93,7 @@ impl core::ops::Sub<VirtualAddress> for VirtualAddress {
}
}
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug)]
pub struct VirtualPageNumber(usize);
impl VirtualPageNumber {
@ -106,8 +111,9 @@ impl VirtualPageNumber {
}
// 线性映射下,得到虚拟页号对应的物理页号
pub fn physical_page_number_linear(self) -> PhysicalPageNumber {
let pa = self.0.wrapping_sub(KERNEL_MAP_OFFSET);
PhysicalPageNumber(pa / PAGE_SIZE)
let va = self.start_address();
let pa = va.physical_address_linear();
PhysicalPageNumber(pa.0 / PAGE_SIZE)
}
/// 对于Sv39得到一、二、三级页号
pub fn levels(&self) -> [usize; 3] {

View File

@ -1,4 +1,4 @@
use crate::memory::PhysicalAddress;
use crate::memory::{PhysicalAddress, VirtualAddress};
use lazy_static::lazy_static;
pub const KERNEL_HEAP_SIZE: usize = 0x80_0000;
@ -6,11 +6,11 @@ pub const KERNEL_HEAP_SIZE: usize = 0x80_0000;
pub const MEMORY_END_ADDRESS: PhysicalAddress = PhysicalAddress(0x8800_0000);
lazy_static! {
pub static ref FREE_MEMORY_START: PhysicalAddress = {
pub static ref FREE_MEMORY_START: VirtualAddress = {
extern "C" {
fn free_memory_start();
}
PhysicalAddress(free_memory_start as usize)
VirtualAddress(free_memory_start as usize)
};
}

View File

@ -1,5 +1,5 @@
use crate::algorithm::{Allocator, StackedAllocator};
use crate::memory::{PhysicalAddress, PhysicalPageNumber, frame::FrameTracker};
use crate::memory::{PhysicalPageNumber, frame::FrameTracker};
use crate::memory::config::{FREE_MEMORY_START, MEMORY_END_ADDRESS};
use core::ops::Range;
use lazy_static::lazy_static;
@ -8,7 +8,7 @@ use spin::Mutex;
lazy_static! {
/// 帧分配器
pub static ref FRAME_ALLOCATOR: Mutex<FrameAllocator<StackedAllocator>> = {
let pa_start = PhysicalAddress::from(*FREE_MEMORY_START);
let pa_start = FREE_MEMORY_START.physical_address_linear();
let ppn_start = PhysicalPageNumber::ceil(pa_start);
let ppn_end = PhysicalPageNumber::floor(MEMORY_END_ADDRESS);
return Mutex::new(FrameAllocator::new(

View File

@ -126,14 +126,22 @@ impl Mapping {
None
}
/// 把当前的映射保存到satp寄存器
#[cfg(riscv)]
pub fn activate(&self) {
use riscv::{register::satp::{self, Mode}, asm};
// use riscv::{register::satp::{self, Mode}, asm};
// unsafe {
// // 保存到satp寄存器
// satp::set(Mode::Sv39, 0 /* asid */, self.root_ppn.into());
// // 刷新页表缓存
// asm::sfence_vma_all();
// }
// satp 低 27 位为页号,高 4 位为模式8 表示 Sv39
let root_ppn: usize = self.root_ppn.into();
let new_satp = root_ppn | (8 << 60);
unsafe {
// 保存到satp寄存器
satp::set(Mode::Sv39, 0 /* asid */, self.root_ppn.into());
// 刷新页表缓存
asm::sfence_vma_all();
// 将 new_satp 的值写到 satp 寄存器
llvm_asm!("csrw satp, $0" :: "r"(new_satp) :: "volatile");
// 刷新 TLB
llvm_asm!("sfence.vma" :::: "volatile");
}
}
}
@ -149,7 +157,9 @@ fn range_vpn_contains_va(src: Range<VirtualAddress>) -> Range<VirtualPageNumber>
// 一个虚拟页号段区间的迭代器
struct VpnRangeIter {
// 区间结束,不包含
end_addr: usize,
// 区间开始,包含
current_addr: usize,
}
@ -159,11 +169,11 @@ impl Iterator for VpnRangeIter {
if self.current_addr == self.end_addr {
return None;
}
// 这里只要右移12位即可ceil和floor区别不大
let current_vpn = VirtualPageNumber::ceil(VirtualAddress(self.current_addr));
let next_addr = self.current_addr.wrapping_add(PAGE_SIZE);
let next_va = VirtualAddress(next_addr);
let next_vpn = VirtualPageNumber::ceil(next_va);
self.current_addr = next_addr;
Some(next_vpn)
Some(current_vpn)
}
}

View File

@ -25,6 +25,12 @@ impl MemorySet {
fn _sbss();
fn _ebss();
}
println!("text: {:x?}", VirtualAddress(_stext as usize)..VirtualAddress(_etext as usize));
println!("rodata: {:x?}", VirtualAddress(_srodata as usize)..VirtualAddress(_erodata as usize));
println!("data: {:x?}", VirtualAddress(_sdata as usize)..VirtualAddress(_edata as usize));
println!("bss: {:x?}", VirtualAddress(_sbss as usize)..VirtualAddress(_ebss as usize));
println!("free: {:x?}", *FREE_MEMORY_START..MEMORY_END_ADDRESS.virtual_address_linear());
// 建立字段
let segments = vec![
@ -37,25 +43,25 @@ impl MemorySet {
// .rodata 段r--
Segment {
map_type: MapType::Linear,
range: VirtualAddress(_stext as usize)..VirtualAddress(_etext as usize),
range: VirtualAddress(_srodata as usize)..VirtualAddress(_erodata as usize),
flags: Flags::READABLE,
},
// .data 段rw-
Segment {
map_type: MapType::Linear,
range: VirtualAddress(_stext as usize)..VirtualAddress(_etext as usize),
range: VirtualAddress(_sdata as usize)..VirtualAddress(_edata as usize),
flags: Flags::READABLE | Flags::WRITABLE,
},
// .bss 段rw-
Segment {
map_type: MapType::Linear,
range: VirtualAddress(_stext as usize)..VirtualAddress(_etext as usize),
range: VirtualAddress(_sbss as usize)..VirtualAddress(_ebss as usize),
flags: Flags::READABLE | Flags::WRITABLE,
},
// 剩余内存空间rw-
Segment {
map_type: MapType::Linear,
range: FREE_MEMORY_START.virtual_address_linear()..MEMORY_END_ADDRESS.virtual_address_linear(),
range: *FREE_MEMORY_START..MEMORY_END_ADDRESS.virtual_address_linear(),
flags: Flags::READABLE | Flags::WRITABLE,
},
];
@ -71,7 +77,6 @@ impl MemorySet {
/// 替换 `satp` 以激活页表
///
/// 如果当前页表就是自身,则不会替换,但仍然会刷新 TLB。
#[cfg(riscv)]
pub fn activate(&self) {
self.mapping.activate()
}