From d66df43ec0944e98e6183c56440fba9a4da6c538 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Sat, 11 May 2019 12:21:03 +0800 Subject: [PATCH] [WIP] rv32 linear mapping --- kernel/Cargo.lock | 2 +- kernel/src/arch/riscv32/boot/entry32.asm | 31 +++-- kernel/src/arch/riscv32/consts.rs | 5 +- kernel/src/arch/riscv32/memory.rs | 16 +++ kernel/src/arch/riscv32/paging.rs | 138 ++++++++++++++++------- kernel/src/drivers/block/virtio_blk.rs | 9 ++ kernel/src/drivers/bus/virtio_mmio.rs | 4 + kernel/src/drivers/net/virtio_net.rs | 8 ++ 8 files changed, 160 insertions(+), 53 deletions(-) diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 92615ea..3d40c59 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -450,7 +450,7 @@ dependencies = [ [[package]] name = "riscv" version = "0.5.0" -source = "git+https://github.com/rcore-os/riscv#e8be9f93513225596709a2dccd9064324591fc3c" +source = "git+https://github.com/rcore-os/riscv#58b3c27b455bed03547cb6112a2f1479e4f4f5ee" dependencies = [ "bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/kernel/src/arch/riscv32/boot/entry32.asm b/kernel/src/arch/riscv32/boot/entry32.asm index 3ea0676..4fb39b9 100644 --- a/kernel/src/arch/riscv32/boot/entry32.asm +++ b/kernel/src/arch/riscv32/boot/entry32.asm @@ -12,11 +12,27 @@ _start: lui sp, %hi(bootstack) add sp, sp, t0 - # 2. enable paging + # 2. paging # satp = (1 << 31) | PPN(boot_page_table_sv32) lui t0, %hi(boot_page_table_sv32) li t1, 0xc0000000 - 0x80000000 sub t0, t0, t1 + # 2.1 linear mapping (0xc0000000 -> 0x80000000) + li t2, 768*4 + li t4, 0x400 << 10 + li t5, 4 + add t1, t0, t2 + li t6, 1024*4 + add t6, t0, t6 + li t3, (0x80000 << 10) | 0xcf # VRWXAD +loop: + sw t3, 0(t1) + add t3, t3, t4 + add t1, t1, t5 + bne t1, t6, loop + + + # 2.2 enable paging srli t0, t0, 12 li t1, 1 << 31 or t0, t0, t1 @@ -41,15 +57,16 @@ bootstacktop: boot_page_table_sv32: # NOTE: assume kernel image < 16M # 0x80000000 -> 0x80000000 (4M * 4) - # 0xc0000000 -> 0x80000000 (4M * 4) + # 0xc0000000 -> 0x80000000 (mapped in code above) .zero 4 * 512 .word (0x80000 << 10) | 0xcf # VRWXAD .word (0x80400 << 10) | 0xcf # VRWXAD .word (0x80800 << 10) | 0xcf # VRWXAD .word (0x80c00 << 10) | 0xcf # VRWXAD .zero 4 * 252 - .word (0x80000 << 10) | 0xcf # VRWXAD - .word (0x80400 << 10) | 0xcf # VRWXAD - .word (0x80800 << 10) | 0xcf # VRWXAD - .word (0x80c00 << 10) | 0xcf # VRWXAD - .zero 4 * 252 + .zero 4 * 256 + + .align 12 # page align + .global _root_page_table_ptr +_root_page_table_ptr: + .space 4 # 4bytes diff --git a/kernel/src/arch/riscv32/consts.rs b/kernel/src/arch/riscv32/consts.rs index 01b9f46..6929ac6 100644 --- a/kernel/src/arch/riscv32/consts.rs +++ b/kernel/src/arch/riscv32/consts.rs @@ -1,7 +1,5 @@ // Physical address available on THINPAD: // [0x80000000, 0x80800000] -#[cfg(target_arch = "riscv32")] -pub const RECURSIVE_INDEX: usize = 0x3fd; #[cfg(target_arch = "riscv64")] pub const RECURSIVE_INDEX: usize = 0o774; // Under riscv64, upon booting, paging is enabled by bbl and @@ -12,6 +10,9 @@ pub const RECURSIVE_INDEX: usize = 0o774; // root_table[0775] points to root_table itself as leaf page // root_table[0776] points to a temp page table as leaf page +// Linear mapping +pub const LINEAR_OFFSET: usize = 0x4000_0000; + #[cfg(target_arch = "riscv32")] pub const KERNEL_OFFSET: usize = 0xC000_0000; #[cfg(target_arch = "riscv64")] diff --git a/kernel/src/arch/riscv32/memory.rs b/kernel/src/arch/riscv32/memory.rs index b5f3161..66675d9 100644 --- a/kernel/src/arch/riscv32/memory.rs +++ b/kernel/src/arch/riscv32/memory.rs @@ -18,6 +18,7 @@ pub fn init(dtb: usize) { init_frame_allocator(); init_heap(); // remap the kernel use 4K page + #[cfg(target_arch = "riscv64")] unsafe { super::paging::setup_recursive_mapping(); } @@ -54,6 +55,21 @@ fn init_frame_allocator() { } /// Remap the kernel memory address with 4K page recorded in p1 page table +#[cfg(target_arch = "riscv32")] +fn remap_the_kernel(_dtb: usize) { + let mut ms = MemorySet::new(); + unsafe { + ms.activate(); + } + unsafe { + SATP = ms.token(); + } + mem::forget(ms); + info!("remap kernel end"); +} + +/// Remap the kernel memory address with 4K page recorded in p1 page table +#[cfg(target_arch = "riscv64")] fn remap_the_kernel(dtb: usize) { let offset = -(KERNEL_OFFSET as isize - MEMORY_OFFSET as isize); let mut ms = MemorySet::new_bare(); diff --git a/kernel/src/arch/riscv32/paging.rs b/kernel/src/arch/riscv32/paging.rs index d501d6f..a0f347e 100644 --- a/kernel/src/arch/riscv32/paging.rs +++ b/kernel/src/arch/riscv32/paging.rs @@ -1,3 +1,5 @@ +use crate::consts::LINEAR_OFFSET; +#[cfg(target_arch = "riscv64")] use crate::consts::RECURSIVE_INDEX; // Depends on kernel #[cfg(target_arch = "riscv32")] @@ -12,10 +14,14 @@ use riscv::asm::{sfence_vma, sfence_vma_all}; use riscv::paging::{FrameAllocator, FrameDeallocator}; use riscv::paging::{ Mapper, PageTable as RvPageTable, PageTableEntry, PageTableFlags as EF, PageTableType, - RecursivePageTable, + RecursivePageTable, TwoLevelPageTable }; use riscv::register::satp; +#[cfg(target_arch = "riscv32")] +pub struct ActivePageTable(usize, PageEntry); + +#[cfg(target_arch = "riscv64")] pub struct ActivePageTable(RecursivePageTable<'static>, PageEntry); /// PageTableEntry: the contents of this entry. @@ -31,7 +37,8 @@ impl PageTable for ActivePageTable { let frame = Frame::of_addr(PhysAddr::new(target)); // map the page to the frame using FrameAllocatorForRiscv // we may need frame allocator to alloc frame for new page table(first/second) - self.0 + info!("map"); + self.get_table() .map_to(page, frame, flags, &mut FrameAllocatorForRiscv) .unwrap() .flush(); @@ -40,13 +47,13 @@ impl PageTable for ActivePageTable { fn unmap(&mut self, addr: usize) { let page = Page::of_addr(VirtAddr::new(addr)); - let (_, flush) = self.0.unmap(page).unwrap(); + let (_, flush) = self.get_table().unmap(page).unwrap(); flush.flush(); } fn get_entry(&mut self, vaddr: usize) -> Option<&mut Entry> { let page = Page::of_addr(VirtAddr::new(vaddr)); - if let Ok(e) = self.0.ref_entry(page.clone()) { + if let Ok(e) = self.get_table().ref_entry(page.clone()) { let e = unsafe { &mut *(e as *mut PageTableEntry) }; self.1 = PageEntry(e, page); Some(&mut self.1 as &mut Entry) @@ -56,12 +63,30 @@ impl PageTable for ActivePageTable { } } +extern "C" { + fn _root_page_table_ptr(); +} + +pub fn set_root_page_table_ptr(ptr: usize) { + unsafe { + sfence_vma_all(); + *(_root_page_table_ptr as *mut usize) = ptr; + } +} + +pub fn get_root_page_table_ptr() -> usize { + unsafe { *(_root_page_table_ptr as *mut usize) } +} + +pub fn root_page_table_buffer() -> &'static mut RvPageTable { + unsafe { &mut *(_root_page_table_ptr as *mut RvPageTable) } +} + impl PageTableExt for ActivePageTable {} +static mut __page_table_with_mode: bool = false; + /// The virtual address of root page table -#[cfg(target_arch = "riscv32")] -const ROOT_PAGE_TABLE: *mut RvPageTable = - ((RECURSIVE_INDEX << 12 << 10) | ((RECURSIVE_INDEX + 1) << 12)) as *mut RvPageTable; #[cfg(all(target_arch = "riscv64", feature = "sv39"))] const ROOT_PAGE_TABLE: *mut RvPageTable = ((0xFFFF_0000_0000_0000) | (0o777 << 12 << 9 << 9 << 9) @@ -79,7 +104,7 @@ impl ActivePageTable { #[cfg(target_arch = "riscv32")] pub unsafe fn new() -> Self { ActivePageTable( - RecursivePageTable::new(&mut *ROOT_PAGE_TABLE).unwrap(), + get_root_page_table_ptr(), ::core::mem::uninitialized(), ) } @@ -94,6 +119,18 @@ impl ActivePageTable { ::core::mem::uninitialized(), ) } + + unsafe fn get_raw_table(&mut self) -> *mut RvPageTable { + if __page_table_with_mode { + get_root_page_table_ptr() as *mut RvPageTable + } else { + self.0 as *mut RvPageTable + } + } + + fn get_table(&mut self) -> TwoLevelPageTable<'static> { + unsafe { TwoLevelPageTable::new(&mut *self.get_raw_table(), LINEAR_OFFSET) } + } } /// implementation for the Entry trait in /crate/memory/src/paging/mod.rs @@ -184,6 +221,12 @@ impl InactivePageTable for InactivePageTable0 { fn new_bare() -> Self { let target = alloc_frame().expect("failed to allocate frame"); let frame = Frame::of_addr(PhysAddr::new(target)); + #[cfg(arch = "riscv32")] + unsafe { + let table = unsafe { &mut *(target as *mut RvPageTable) }; + table.zero(); + } + #[cfg(arch = "riscv64")] active_table().with_temporary_map(target, |_, table: &mut RvPageTable| { table.zero(); table.set_recursive(RECURSIVE_INDEX, frame.clone()); @@ -193,25 +236,13 @@ impl InactivePageTable for InactivePageTable0 { #[cfg(target_arch = "riscv32")] fn map_kernel(&mut self) { - let table = unsafe { &mut *ROOT_PAGE_TABLE }; - extern "C" { - fn start(); - fn end(); - } - let mut entrys: [PageTableEntry; 256] = unsafe { core::mem::uninitialized() }; - let entry_start = start as usize >> 22; - let entry_end = (end as usize >> 22) + 1; - let entry_count = entry_end - entry_start; - for i in 0..entry_count { - entrys[i] = table[entry_start + i]; + info!("mapping kernel linear mapping"); + let table: &mut RvPageTable = unsafe { self.root_frame.as_kernel_mut(LINEAR_OFFSET)}; + for i in 256..1024 { + let flags = EF::VALID | EF::READABLE | EF::WRITABLE | EF::EXECUTABLE; + let frame = Frame::of_addr(PhysAddr::new((i - 256) << 22)); + table[i].set(frame, flags); } - - self.edit(|_| { - // NOTE: 'table' now refers to new page table - for i in 0..entry_count { - table[entry_start + i] = entrys[i]; - } - }); } #[cfg(target_arch = "riscv64")] @@ -256,27 +287,47 @@ impl InactivePageTable for InactivePageTable0 { } fn edit(&mut self, f: impl FnOnce(&mut Self::Active) -> T) -> T { - let target = satp::read().frame().start_address().as_usize(); - active_table().with_temporary_map(target, |active_table, root_table: &mut RvPageTable| { - let backup = root_table[RECURSIVE_INDEX].clone(); - - // overwrite recursive mapping - root_table[RECURSIVE_INDEX].set(self.root_frame.clone(), EF::VALID); - unsafe { - sfence_vma_all(); - } + #[cfg(target_arch = "riscv32")] + { + debug!( + "edit table {:x?} -> {:x?}", + Self::active_token(), + self.token() + ); + let mut active = unsafe { ActivePageTable(self.token(), ::core::mem::uninitialized()) }; - // execute f in the new context - let ret = f(active_table); + let ret = f(&mut active); + debug!("finish table"); - // restore recursive mapping to original p2 table - root_table[RECURSIVE_INDEX] = backup; - unsafe { - sfence_vma_all(); - } + Self::flush_tlb(); ret - }) + } + #[cfg(target_arch = "riscv64")] + { + let target = satp::read().frame().start_address().as_usize(); + active_table().with_temporary_map(target, |active_table, root_table: &mut RvPageTable| { + let backup = root_table[RECURSIVE_INDEX].clone(); + + // overwrite recursive mapping + root_table[RECURSIVE_INDEX].set(self.root_frame.clone(), EF::VALID); + unsafe { + sfence_vma_all(); + } + + // execute f in the new context + let ret = f(active_table); + + // restore recursive mapping to original p2 table + root_table[RECURSIVE_INDEX] = backup; + unsafe { + sfence_vma_all(); + } + + ret + }) + + } } } @@ -300,6 +351,7 @@ impl FrameDeallocator for FrameAllocatorForRiscv { } } +#[cfg(target_arch = "riscv64")] pub unsafe fn setup_recursive_mapping() { let frame = satp::read().frame(); let root_page_table = unsafe { &mut *(frame.start_address().as_usize() as *mut RvPageTable) }; diff --git a/kernel/src/drivers/block/virtio_blk.rs b/kernel/src/drivers/block/virtio_blk.rs index e3b281a..514b6eb 100644 --- a/kernel/src/drivers/block/virtio_blk.rs +++ b/kernel/src/drivers/block/virtio_blk.rs @@ -13,6 +13,7 @@ use volatile::Volatile; use crate::drivers::BlockDriver; use crate::sync::SpinNoIrqLock as Mutex; +use crate::arch::consts::LINEAR_OFFSET; use super::super::bus::virtio_mmio::*; use super::super::{DeviceType, Driver, BLK_DRIVERS, DRIVERS}; @@ -124,6 +125,10 @@ impl Driver for VirtIOBlkDriver { fn read_block(&self, block_id: usize, buf: &mut [u8]) -> bool { let mut driver = self.0.lock(); +<<<<<<< HEAD +======= + +>>>>>>> [WIP] rv32 linear mapping let mut req = VirtIOBlkReadReq::default(); req.req_type = VIRTIO_BLK_T_IN; req.reserved = 0; @@ -149,6 +154,10 @@ impl Driver for VirtIOBlkDriver { fn write_block(&self, block_id: usize, buf: &[u8]) -> bool { let mut driver = self.0.lock(); +<<<<<<< HEAD +======= + +>>>>>>> [WIP] rv32 linear mapping let mut req: VirtIOBlkWriteReq = unsafe { zeroed() }; req.req_type = VIRTIO_BLK_T_OUT; req.reserved = 0; diff --git a/kernel/src/drivers/bus/virtio_mmio.rs b/kernel/src/drivers/bus/virtio_mmio.rs index 2cfc11f..1fccb27 100644 --- a/kernel/src/drivers/bus/virtio_mmio.rs +++ b/kernel/src/drivers/bus/virtio_mmio.rs @@ -11,7 +11,11 @@ use log::*; use rcore_memory::PAGE_SIZE; use volatile::{ReadOnly, Volatile, WriteOnly}; +<<<<<<< HEAD use crate::arch::consts::{KERNEL_OFFSET, MEMORY_OFFSET}; +======= +use crate::arch::consts::{KERNEL_OFFSET, MEMORY_OFFSET, LINEAR_OFFSET}; +>>>>>>> [WIP] rv32 linear mapping use crate::HEAP_ALLOCATOR; use super::super::block::virtio_blk; diff --git a/kernel/src/drivers/net/virtio_net.rs b/kernel/src/drivers/net/virtio_net.rs index c2fee7d..819e23e 100644 --- a/kernel/src/drivers/net/virtio_net.rs +++ b/kernel/src/drivers/net/virtio_net.rs @@ -134,6 +134,10 @@ impl phy::RxToken for VirtIONetRxToken { { let (input, output, _, user_data) = { let mut driver = (self.0).0.lock(); +<<<<<<< HEAD +======= + +>>>>>>> [WIP] rv32 linear mapping driver.queues[VIRTIO_QUEUE_RECEIVE].get().unwrap() }; let result = f(&input[0][size_of::()..]); @@ -151,6 +155,10 @@ impl phy::TxToken for VirtIONetTxToken { { let output = { let mut driver = (self.0).0.lock(); +<<<<<<< HEAD +======= + +>>>>>>> [WIP] rv32 linear mapping if let Some((_, output, _, _)) = driver.queues[VIRTIO_QUEUE_TRANSMIT].get() { unsafe { slice::from_raw_parts_mut(output[0].as_ptr() as *mut u8, output[0].len()) } } else {