diff --git a/.cargo/config.toml b/kernel/.cargo/config.toml similarity index 100% rename from .cargo/config.toml rename to kernel/.cargo/config.toml diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 37da659..57404be 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -2,6 +2,16 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "allocator" +version = "0.1.0" +dependencies = [ + "spin 0.9.8", + "static_assertions", + "utils", + "vspace", +] + [[package]] name = "api" version = "0.1.0" @@ -62,6 +72,7 @@ checksum = "784a4df722dc6267a04af36895398f59d21d07dce47232adf31ec0ff2fa45e67" name = "kernel" version = "0.1.0" dependencies = [ + "allocator", "api", "bitflags 2.5.0", "cfg-if", @@ -75,6 +86,8 @@ dependencies = [ "spin 0.9.8", "static_assertions", "uart_16550", + "utils", + "vspace", ] [[package]] @@ -235,6 +248,22 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "utils" +version = "0.1.0" +dependencies = [ + "vspace", +] + +[[package]] +name = "vspace" +version = "0.1.0" +dependencies = [ + "bitflags 2.5.0", + "num-derive", + "num-traits", +] + [[package]] name = "x86" version = "0.52.0" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index fcdcca0..68b3094 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [features] default = ["riscv.board.virt", "log_color"] -legacy = [] +legacy = ["utils/legacy", "vspace/legacy"] riscv = [] @@ -33,9 +33,12 @@ panic = "abort" lto = "thin" [dependencies] +allocator = { path = "../lib/allocator" } api = { path = "../api" } +utils = { path = "../lib/utils", default-features = false } +vspace = { path = "../lib/vspace", default-features = false } -bitflags = "2.4" +bitflags = "2.5" cfg-if = "1.0" fdt = "0.1" lazy_static = { version = "1.4", features = ["spin_no_std"] } diff --git a/kernel/build.rs b/kernel/build.rs index d73b97e..d49c770 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -9,7 +9,7 @@ fn main() { const TARGET_LDS: &[TargetConfig] = &[ TargetConfig { target: "riscv64", - lds: "src/arch/riscv/linker.ld", + lds: "src/arch/riscv/linker64.ld", }, TargetConfig { target: "riscv32", diff --git a/kernel/src/arch/mod.rs b/kernel/src/arch/mod.rs index 1bfeaa9..6416040 100644 --- a/kernel/src/arch/mod.rs +++ b/kernel/src/arch/mod.rs @@ -1,7 +1,4 @@ -pub use arch::*; - -// Arch Level #[cfg(feature = "riscv")] -#[path = "riscv/mod.rs"] -#[allow(clippy::module_inception)] -mod arch; +mod riscv; +#[cfg(feature = "riscv")] +pub use riscv::*; diff --git a/kernel/src/arch/riscv/entry.rs b/kernel/src/arch/riscv/entry.rs index d8fffde..232e5e4 100644 --- a/kernel/src/arch/riscv/entry.rs +++ b/kernel/src/arch/riscv/entry.rs @@ -1,9 +1,6 @@ -use super::board::console::init_early_console; -use super::vspace::utils::setup_kernel_paging; use crate::arch::layout::zero_bss; -use crate::arch::vspace::utils::setup_memory; -use crate::vspace::allocator::RamBlock; -use fdt::Fdt; +use crate::arch::vspace::utils::{setup_kernel_paging, setup_memory}; +use allocator::RamBlock; #[naked] #[no_mangle] diff --git a/kernel/src/arch/riscv/layout.rs b/kernel/src/arch/riscv/layout.rs index 4c46416..9559a2b 100644 --- a/kernel/src/arch/riscv/layout.rs +++ b/kernel/src/arch/riscv/layout.rs @@ -1,7 +1,7 @@ -use crate::utils::extern_addr::ExternSymbol; -use crate::utils::size::KIB; -use crate::vspace::addr::{AddressOps, PhysAddr, VirtAddr}; use core::alloc::Layout; +use utils::extern_addr::ExternSymbol; +use utils::size::KIB; +use vspace::addr::{AddressOps, PhysAddr, VirtAddr}; extern "C" { pub static KERNEL_START: ExternSymbol; diff --git a/kernel/src/arch/riscv/mod.rs b/kernel/src/arch/riscv/mod.rs index f3e5130..27af3f8 100644 --- a/kernel/src/arch/riscv/mod.rs +++ b/kernel/src/arch/riscv/mod.rs @@ -12,6 +12,7 @@ cfg_if! { } // Console: plat/console.rs +pub use board::console::init_early_console; pub use board::console::EarlyConsole; mod entry; diff --git a/kernel/src/arch/riscv/vspace/entry.rs b/kernel/src/arch/riscv/vspace/entry.rs index 836efdc..23ad2a5 100644 --- a/kernel/src/arch/riscv/vspace/entry.rs +++ b/kernel/src/arch/riscv/vspace/entry.rs @@ -1,6 +1,7 @@ -use crate::vspace::addr::{AddressOps, PhysAddr}; -use crate::vspace::paging::{EntryOps, MapAttr}; +use super::traits::PhysAddrPaging; use bitflags::bitflags; +use vspace::addr::PhysAddr; +use vspace::paging::{EntryOps, MapAttr}; bitflags! { #[derive(Debug)] @@ -79,45 +80,6 @@ assert_eq_size!(Entry, u64); #[cfg(feature = "riscv.pagetable.sv32")] assert_eq_size!(Entry, u32); -#[cfg(feature = "riscv.pagetable.sv32")] -impl PhysAddr { - const PA_PPN_MASK: usize = ((1 << Self::PPN_BITS) - 1) << Self::PG_OFFSET; - const PG_OFFSET: usize = 12; - const PPN_BITS: usize = 22; - const PPN_OFFSET: usize = 10; - const PTE_PPN_MASK: usize = ((1 << Self::PPN_BITS) - 1) << Self::PPN_OFFSET; -} - -#[cfg(feature = "riscv.pagetable.sv39")] -impl PhysAddr { - const PA_PPN_MASK: usize = ((1 << Self::PPN_BITS) - 1) << Self::PG_OFFSET; - const PG_OFFSET: usize = 12; - const PPN_BITS: usize = 44; - const PPN_OFFSET: usize = 10; - const PTE_PPN_MASK: usize = ((1 << Self::PPN_BITS) - 1) << Self::PPN_OFFSET; -} - -impl PhysAddr { - pub fn to_ppn(self) -> usize { - (self.as_usize() & Self::PA_PPN_MASK) >> Self::PG_OFFSET - } - - fn to_ppn_shifted(self) -> usize { - self.to_ppn() << Self::PPN_OFFSET - } - - fn from_pte(pte: usize) -> Self { - let ppn = (pte & Self::PTE_PPN_MASK) >> Self::PPN_OFFSET; - let paddr = ppn << Self::PG_OFFSET; - PhysAddr::from(paddr) - } - - fn merge_pte(self, pte: usize) -> usize { - let ppn = self.to_ppn_shifted(); - (pte & !Self::PTE_PPN_MASK) | ppn - } -} - #[derive(Clone, Copy, Default)] pub struct Entry(usize); diff --git a/kernel/src/arch/riscv/vspace/mod.rs b/kernel/src/arch/riscv/vspace/mod.rs index 8e37a61..d05123b 100644 --- a/kernel/src/arch/riscv/vspace/mod.rs +++ b/kernel/src/arch/riscv/vspace/mod.rs @@ -1,6 +1,4 @@ mod entry; mod table; +mod traits; pub mod utils; - -pub use entry::Entry; -pub use table::Table; diff --git a/kernel/src/arch/riscv/vspace/table.rs b/kernel/src/arch/riscv/vspace/table.rs index 664fc80..2f531f0 100644 --- a/kernel/src/arch/riscv/vspace/table.rs +++ b/kernel/src/arch/riscv/vspace/table.rs @@ -1,63 +1,9 @@ +use super::entry::Entry; +use super::traits::{TableLevelSize, VirtAddrPaging}; use crate::arch::layout::{kernel_phys_to_virt, PAGE_SIZE}; -use crate::utils::size::*; -use crate::vspace::addr::*; -use crate::vspace::paging::*; use num_traits::ToPrimitive; - -#[cfg(feature = "riscv.pagetable.sv32")] -impl VirtAddr { - const PG_OFFSET: usize = 12; - const VPN_BITS: usize = 10; - const VPN_MASK: usize = (1 << Self::VPN_BITS) - 1; -} - -#[cfg(feature = "riscv.pagetable.sv39")] -impl VirtAddr { - const PG_OFFSET: usize = 12; - const VPN_BITS: usize = 9; - const VPN_MASK: usize = (1 << Self::VPN_BITS) - 1; -} - -impl VirtAddr { - fn to_vpn(self, level: TableLevel) -> usize { - self.0 >> (Self::PG_OFFSET + Self::VPN_BITS * level.to_usize().unwrap()) & Self::VPN_MASK - } - - fn merge_vpn(&self, vpn: usize, size: TableLevel) -> Self { - let shift = Self::PG_OFFSET + Self::VPN_BITS * size.to_usize().unwrap(); - let mask = Self::VPN_MASK << shift; - VirtAddr((self.0 & !mask) | ((vpn & Self::VPN_MASK) << shift)) - } - - fn lower_bits(self, level: usize) -> usize { - self.0 & ((1 << (Self::PG_OFFSET + Self::VPN_BITS * (level + 1))) - 1) - } -} - -impl TableLevel { - pub fn level_size(&self) -> usize { - match self { - Self::Level0 => 4 * KIB, - #[cfg(feature = "riscv.pagetable.sv32")] - Self::Level1 => 4 * MIB, - #[cfg(not(feature = "riscv.pagetable.sv32"))] - Self::Level1 => 2 * MIB, - Self::Level2 => 1 * GIB, - #[cfg(not(feature = "legacy"))] - Self::Level3 => 512 * GIB, - #[cfg(not(feature = "legacy"))] - Self::Level4 => 256 * TIB, - } - } - - pub fn align(&self, addr: A) -> A { - addr.align_down(self.level_size()) - } - - pub fn is_aligned(&self, addr: A) -> bool { - self.align(addr) == addr - } -} +use vspace::addr::*; +use vspace::paging::*; #[repr(C, align(4096))] pub struct Table { @@ -84,6 +30,17 @@ impl Table { table = unsafe { Self::new(kernel_phys_to_virt(entry.addr()).as_usize().into()) }; } } + + pub fn mode() -> riscv::register::satp::Mode { + #[cfg(feature = "riscv.pagetable.sv32")] + return riscv::register::satp::Mode::Sv32; + #[cfg(feature = "riscv.pagetable.sv39")] + return riscv::register::satp::Mode::Sv39; + #[cfg(feature = "riscv.pagetable.sv48")] + return riscv::register::satp::Mode::Sv48; + #[cfg(feature = "riscv.pagetable.sv57")] + return riscv::register::satp::Mode::Sv57; + } } impl TableOps for Table { diff --git a/kernel/src/arch/riscv/vspace/traits.rs b/kernel/src/arch/riscv/vspace/traits.rs new file mode 100644 index 0000000..231fb47 --- /dev/null +++ b/kernel/src/arch/riscv/vspace/traits.rs @@ -0,0 +1,113 @@ +use num_traits::ToPrimitive; +use utils::size::{GIB, KIB, MIB, TIB}; +use vspace::addr::{AddressOps, PhysAddr, VirtAddr}; +use vspace::paging::TableLevel; + +pub trait PhysAddrPaging { + const PG_OFFSET: usize; + const PPN_BITS: usize; + const PPN_OFFSET: usize; + + const PA_PPN_MASK: usize = ((1 << Self::PPN_BITS) - 1) << Self::PG_OFFSET; + const PTE_PPN_MASK: usize = ((1 << Self::PPN_BITS) - 1) << Self::PPN_OFFSET; + + fn to_ppn(&self) -> usize + where Self: AddressOps { + (self.as_usize() & Self::PA_PPN_MASK) >> Self::PG_OFFSET + } + + fn to_ppn_shifted(&self) -> usize + where Self: PhysAddrPaging + AddressOps { + self.to_ppn() << Self::PPN_OFFSET + } + + fn from_pte(pte: usize) -> PhysAddr { + let ppn = (pte & Self::PTE_PPN_MASK) >> Self::PPN_OFFSET; + let paddr = ppn << Self::PG_OFFSET; + PhysAddr::from(paddr) + } + + fn merge_pte(&self, pte: usize) -> usize + where Self: PhysAddrPaging + AddressOps { + let ppn = self.to_ppn_shifted(); + (pte & !Self::PTE_PPN_MASK) | ppn + } +} + +#[cfg(feature = "riscv.pagetable.sv32")] +impl PhysAddrPaging for PhysAddr { + const PG_OFFSET: usize = 12; + const PPN_BITS: usize = 22; + const PPN_OFFSET: usize = 10; +} + +#[cfg(feature = "riscv.pagetable.sv39")] +impl PhysAddrPaging for PhysAddr { + const PG_OFFSET: usize = 12; + const PPN_BITS: usize = 44; + const PPN_OFFSET: usize = 10; +} + +pub trait VirtAddrPaging { + const PG_OFFSET: usize; + const VPN_BITS: usize; + + const VPN_MASK: usize = (1 << Self::VPN_BITS) - 1; + + fn to_vpn(&self, level: TableLevel) -> usize + where Self: AddressOps { + self.as_usize() >> (Self::PG_OFFSET + Self::VPN_BITS * level.to_usize().unwrap()) + & Self::VPN_MASK + } + + fn merge_vpn(&self, vpn: usize, size: TableLevel) -> VirtAddr + where Self: AddressOps { + let shift = Self::PG_OFFSET + Self::VPN_BITS * size.to_usize().unwrap(); + let mask = Self::VPN_MASK << shift; + VirtAddr((self.as_usize() & !mask) | ((vpn & Self::VPN_MASK) << shift)) + } + + fn lower_bits(&self, level: usize) -> usize + where Self: AddressOps { + self.as_usize() & ((1 << (Self::PG_OFFSET + Self::VPN_BITS * (level + 1))) - 1) + } +} + +#[cfg(feature = "riscv.pagetable.sv32")] +impl VirtAddrPaging for VirtAddr { + const PG_OFFSET: usize = 12; + const VPN_BITS: usize = 10; +} + +#[cfg(feature = "riscv.pagetable.sv39")] +impl VirtAddrPaging for VirtAddr { + const PG_OFFSET: usize = 12; + const VPN_BITS: usize = 9; +} + +pub trait TableLevelSize { + fn level_size(&self) -> usize; + fn align(&self, addr: A) -> A { + addr.align_down(self.level_size()) + } + fn is_aligned(&self, addr: A) -> bool { + self.align(addr) == addr + } +} + +impl TableLevelSize for TableLevel { + fn level_size(&self) -> usize { + match self { + Self::Level0 => 4 * KIB, + #[cfg(feature = "riscv.pagetable.sv32")] + Self::Level1 => 4 * MIB, + #[cfg(not(feature = "riscv.pagetable.sv32"))] + Self::Level1 => 2 * MIB, + Self::Level2 => 1 * GIB, + #[cfg(not(feature = "legacy"))] + Self::Level3 => 512 * GIB, + #[cfg(not(feature = "legacy"))] + Self::Level4 => 256 * TIB, + } + } +} diff --git a/kernel/src/arch/riscv/vspace/utils.rs b/kernel/src/arch/riscv/vspace/utils.rs index 0790547..004ea7e 100644 --- a/kernel/src/arch/riscv/vspace/utils.rs +++ b/kernel/src/arch/riscv/vspace/utils.rs @@ -1,11 +1,15 @@ +use super::table::Table; +use super::traits::{PhysAddrPaging, TableLevelSize}; use crate::arch::layout::*; -use crate::utils::size::GIB; -use crate::vspace::addr::{align_up, AddressOps, PhysAddr, VirtAddr}; -use crate::vspace::allocator::RamBlock; -use crate::vspace::paging::PageError::{AlreadyMapped, MissingEntry}; -use crate::vspace::paging::{MapAttr, Table, TableLevel, TableOps}; +use allocator::RamBlock; +use fdt::Fdt; +use utils::size::GIB; +use vspace::addr::*; +use vspace::paging::{MapAttr, PageError::*, TableLevel, TableOps}; + +pub unsafe fn setup_memory(fdt_addr: usize, mem: &mut RamBlock<8>) { + let fdt = unsafe { Fdt::from_ptr(fdt_addr as *const u8).unwrap() }; -pub unsafe fn setup_memory(fdt: &fdt::Fdt, fdt_addr: usize, mem: &mut RamBlock) { // Add main memory regions to allocator for region in fdt.memory().regions() { mem.dealloc( @@ -46,7 +50,11 @@ pub unsafe fn setup_memory(fdt: &fdt::Fdt, fdt_addr: usize, mem: mem.reserve(fdt_addr, fdt_size); } -pub unsafe fn setup_kernel_paging(allocator: &mut RamBlock) { +pub unsafe fn setup_kernel_paging( + allocator: &mut RamBlock<8>, + hart_id: usize, + fdt_addr: usize, +) -> ! { let mut alloc = || { allocator .alloc(PAGE_LAYOUT) diff --git a/kernel/src/entry.rs b/kernel/src/entry.rs index e2e89e1..d1d7aa7 100644 --- a/kernel/src/entry.rs +++ b/kernel/src/entry.rs @@ -1,16 +1,19 @@ -use core::cell::Cell; -use log::{debug, error, info, warn}; - +use crate::arch::init_early_console; use crate::plat::console::{set_console, ConsoleDevice, ConsoleDriver, CONSOLE}; use crate::plat::lowlevel::{Hardware, LowLevel}; use crate::plat::timer::{Timer, TimerOps}; use crate::plat::trap::{Trap, TrapOps}; -use crate::vspace::allocator::RamBlock; +use allocator::RamBlock; +use core::cell::Cell; +use fdt::Fdt; +use log::{debug, error, info, warn}; #[thread_local] pub static HART_ID: Cell = Cell::new(0); -pub fn rust_main(hart_id: usize, fdt: fdt::Fdt, mut _allocator: RamBlock) -> ! { +// NOTE: we will call rust_main through trap (stvec), make sure it is aligned +#[repr(align(4))] +pub extern "C" fn rust_main(hart_id: usize, fdt_addr: usize, allocator: &mut RamBlock<8>) -> ! { HART_ID.set(hart_id); info!("Kernel Started"); diff --git a/kernel/src/main.rs b/kernel/src/main.rs index f369301..237be05 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -6,10 +6,10 @@ #![feature(concat_idents)] #![feature(const_mut_refs)] #![feature(extern_types)] +#![feature(fn_align)] #![feature(let_chains)] #![feature(naked_functions)] #![feature(panic_info_message)] -#![feature(step_trait)] #![feature(stmt_expr_attributes)] #![feature(thread_local)] // Test Infrastructure @@ -21,9 +21,6 @@ #[macro_use] extern crate static_assertions; -#[macro_use] -extern crate num_derive; - mod arch; mod drivers; mod entry; @@ -31,8 +28,6 @@ mod lang; mod logging; mod objects; mod plat; -mod utils; -mod vspace; // test infrastructure #[cfg(test)] diff --git a/kernel/src/vspace/mod.rs b/kernel/src/vspace/mod.rs deleted file mode 100644 index 2bb91c2..0000000 --- a/kernel/src/vspace/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod addr; -pub mod allocator; -pub mod paging;