From 26e47fc36f76c19f065433128a79d9d265bbe5e6 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Sun, 12 May 2019 01:11:53 +0800 Subject: [PATCH] [WIP] Initial rv64 sv39 support --- kernel/Cargo.lock | 2 +- kernel/src/arch/riscv32/consts.rs | 3 + kernel/src/arch/riscv32/memory.rs | 133 ------------------------------ kernel/src/arch/riscv32/paging.rs | 35 +++++--- 4 files changed, 28 insertions(+), 145 deletions(-) diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 3d40c59..23dea29 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#58b3c27b455bed03547cb6112a2f1479e4f4f5ee" +source = "git+https://github.com/rcore-os/riscv#8e25d63d123773145911f4a1f718fc1bc73d80c6" 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/consts.rs b/kernel/src/arch/riscv32/consts.rs index b8e02d6..559cedd 100644 --- a/kernel/src/arch/riscv32/consts.rs +++ b/kernel/src/arch/riscv32/consts.rs @@ -1,5 +1,8 @@ // Linear mapping +#[cfg(target_arch = "riscv32")] pub const PHYSICAL_MEMORY_OFFSET: usize = 0x4000_0000; +#[cfg(target_arch = "riscv64")] +pub const PHYSICAL_MEMORY_OFFSET: usize = 0xFFFF_FFFF_4000_0000; #[cfg(target_arch = "riscv32")] pub const KERNEL_OFFSET: usize = 0xC000_0000; diff --git a/kernel/src/arch/riscv32/memory.rs b/kernel/src/arch/riscv32/memory.rs index 66675d9..96428a1 100644 --- a/kernel/src/arch/riscv32/memory.rs +++ b/kernel/src/arch/riscv32/memory.rs @@ -17,11 +17,6 @@ pub fn init(dtb: usize) { // initialize heap and Frame allocator init_frame_allocator(); init_heap(); - // remap the kernel use 4K page - #[cfg(target_arch = "riscv64")] - unsafe { - super::paging::setup_recursive_mapping(); - } remap_the_kernel(dtb); } @@ -55,7 +50,6 @@ 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 { @@ -68,133 +62,6 @@ fn remap_the_kernel(_dtb: usize) { 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(); - ms.push( - stext as usize, - etext as usize, - MemoryAttr::default().execute().readonly(), - Linear::new(offset), - "text", - ); - ms.push( - sdata as usize, - edata as usize, - MemoryAttr::default(), - Linear::new(offset), - "data", - ); - ms.push( - srodata as usize, - erodata as usize, - MemoryAttr::default().readonly(), - Linear::new(offset), - "rodata", - ); - ms.push( - bootstack as usize, - bootstacktop as usize, - MemoryAttr::default(), - Linear::new(offset), - "stack", - ); - ms.push( - sbss as usize, - ebss as usize, - MemoryAttr::default(), - Linear::new(offset), - "bss", - ); - // dtb on rocket chip is embedded into kernel - #[cfg(not(feature = "board_rocket_chip"))] - ms.push( - dtb, - dtb + super::consts::MAX_DTB_SIZE, - MemoryAttr::default().readonly(), - Linear::new(offset), - "dts", - ); - // map PLIC for HiFiveU & VirtIO - let offset = -(KERNEL_OFFSET as isize); - ms.push( - KERNEL_OFFSET + 0x0C00_2000, - KERNEL_OFFSET + 0x0C00_2000 + PAGE_SIZE, - MemoryAttr::default(), - Linear::new(offset), - "plic0", - ); - ms.push( - KERNEL_OFFSET + 0x0C20_2000, - KERNEL_OFFSET + 0x0C20_2000 + PAGE_SIZE, - MemoryAttr::default(), - Linear::new(offset), - "plic1", - ); - // map UART for HiFiveU - ms.push( - KERNEL_OFFSET + 0x10010000, - KERNEL_OFFSET + 0x10010000 + PAGE_SIZE, - MemoryAttr::default(), - Linear::new(offset), - "uart", - ); - // map UART for VirtIO - ms.push( - KERNEL_OFFSET + 0x10000000, - KERNEL_OFFSET + 0x10000000 + PAGE_SIZE, - MemoryAttr::default(), - Linear::new(offset), - "uart16550", - ); - // map PLIC for Rocket Chip - #[cfg(feature = "board_rocket_chip")] - ms.push( - KERNEL_OFFSET + 0x0C20_1000, - KERNEL_OFFSET + 0x0C20_1000 + PAGE_SIZE, - MemoryAttr::default(), - Linear::new(offset), - "plic2", - ); - // map UART for Rocket Chip - #[cfg(feature = "board_rocket_chip")] - ms.push( - KERNEL_OFFSET + 0x18000000, - KERNEL_OFFSET + 0x18000000 + PAGE_SIZE, - MemoryAttr::default(), - Linear::new(-(KERNEL_OFFSET as isize + 0x18000000 - 0x60000000)), - "uartlite", - ); - // map AXI INTC for Rocket Chip - #[cfg(feature = "board_rocket_chip")] - ms.push( - KERNEL_OFFSET + 0x18100000, - KERNEL_OFFSET + 0x18100000 + PAGE_SIZE, - MemoryAttr::default(), - Linear::new(-(KERNEL_OFFSET as isize + 0x18100000 - 0x61200000)), - "axi_intc", - ); - // map AXI4-Stream Data FIFO for Rocket Chip - #[cfg(feature = "board_rocket_chip")] - ms.push( - KERNEL_OFFSET + 0x18200000, - KERNEL_OFFSET + 0x18200000 + PAGE_SIZE, - MemoryAttr::default(), - Linear::new(-(KERNEL_OFFSET as isize + 0x18200000 - 0x64A00000)), - "router", - ); - unsafe { - ms.activate(); - } - unsafe { - SATP = ms.token(); - } - mem::forget(ms); - info!("remap kernel end"); -} - // First core stores its SATP here. // Other cores load it later. static mut SATP: usize = 0; diff --git a/kernel/src/arch/riscv32/paging.rs b/kernel/src/arch/riscv32/paging.rs index 07b1379..be03f7f 100644 --- a/kernel/src/arch/riscv32/paging.rs +++ b/kernel/src/arch/riscv32/paging.rs @@ -1,9 +1,4 @@ use crate::consts::PHYSICAL_MEMORY_OFFSET; -#[cfg(target_arch = "riscv64")] -use crate::consts::RECURSIVE_INDEX; -// Depends on kernel -#[cfg(target_arch = "riscv64")] -use crate::consts::KERNEL_P4_INDEX; use crate::memory::{alloc_frame, dealloc_frame, phys_to_virt}; use log::*; use rcore_memory::paging::*; @@ -12,12 +7,19 @@ 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, TwoLevelPageTable, + RecursivePageTable }; use riscv::register::satp; +#[cfg(target_arch = "riscv32")] +type TopLevelPageTable<'a> = riscv::paging::Rv32PageTable<'a>; +#[cfg(all(target_arch = "riscv64", feature = "sv39"))] +type TopLevelPageTable<'a> = riscv::paging::Rv39PageTable<'a>; +#[cfg(all(target_arch = "riscv64", not(feature = "sv39")))] +type TopLevelPageTable<'a> = riscv::paging::Rv48PageTable<'a>; + pub struct PageTableImpl { - page_table: TwoLevelPageTable<'static>, + page_table: TopLevelPageTable<'static>, root_frame: Frame, entry: PageEntry, } @@ -151,7 +153,7 @@ impl PageTableImpl { let frame = Frame::of_ppn(PageTableImpl::active_token() & 0x7fffffff); let table = frame.as_kernel_mut(PHYSICAL_MEMORY_OFFSET); PageTableImpl { - page_table: TwoLevelPageTable::new(table, PHYSICAL_MEMORY_OFFSET), + page_table: TopLevelPageTable::new(table, PHYSICAL_MEMORY_OFFSET), root_frame: frame, entry: unsafe { core::mem::uninitialized() }, } @@ -167,7 +169,7 @@ impl PageTableExt for PageTableImpl { table.zero(); PageTableImpl { - page_table: TwoLevelPageTable::new(table, PHYSICAL_MEMORY_OFFSET), + page_table: TopLevelPageTable::new(table, PHYSICAL_MEMORY_OFFSET), root_frame: frame, entry: unsafe { core::mem::uninitialized() }, } @@ -178,16 +180,28 @@ impl PageTableExt for PageTableImpl { let table = unsafe { &mut *(phys_to_virt(self.root_frame.start_address().as_usize()) as *mut RvPageTable) }; + #[cfg(target_arch = "riscv32")] for i in 256..1024 { let flags = EF::VALID | EF::READABLE | EF::WRITABLE | EF::EXECUTABLE | EF::ACCESSED | EF::DIRTY; let frame = Frame::of_addr(PhysAddr::new((i << 22) - PHYSICAL_MEMORY_OFFSET)); table[i].set(frame, flags); } + #[cfg(all(target_arch = "riscv64", feature = "sv39"))] + for i in 509..512 { + let flags = + EF::VALID | EF::READABLE | EF::WRITABLE | EF::EXECUTABLE | EF::ACCESSED | EF::DIRTY; + let frame = Frame::of_addr(PhysAddr::new((0xFFFFFF80_00000000 + (i << 30)) - PHYSICAL_MEMORY_OFFSET)); + table[i].set(frame, flags); + } + // TODO: sv48 } fn token(&self) -> usize { - self.root_frame.number() | (1 << 31) + #[cfg(target_arch = "riscv32")] + return self.root_frame.number() | (1 << 31); + #[cfg(all(target_arch = "riscv64", feature = "sv39"))] + return self.root_frame.number() | (8 << 60); } unsafe fn set_token(token: usize) { @@ -203,7 +217,6 @@ impl PageTableExt for PageTableImpl { } fn flush_tlb() { - debug!("flushing token {:x}", Self::active_token()); unsafe { sfence_vma_all(); }