From f1735dc1c04d21175f7cae033f6a1b7acf81b46c Mon Sep 17 00:00:00 2001 From: Paul Pan Date: Fri, 16 Feb 2024 21:00:08 +0800 Subject: [PATCH] feat: use cfg_if! to avoid conflicting features --- .../src/arch/riscv/{ => board/default}/io.rs | 3 - .../src/arch/riscv/board/default/lowlevel.rs | 19 +++++ kernel/src/arch/riscv/board/default/mod.rs | 5 ++ kernel/src/arch/riscv/board/virt/lowlevel.rs | 16 ++++ kernel/src/arch/riscv/board/virt/mod.rs | 9 ++- kernel/src/arch/riscv/board/virt/printer.rs | 6 +- kernel/src/arch/riscv/entry.rs | 2 +- kernel/src/arch/riscv/layout.rs | 3 - kernel/src/arch/riscv/lowlevel.rs | 44 +++-------- kernel/src/arch/riscv/mm/page.rs | 4 +- kernel/src/arch/riscv/mod.rs | 24 ++++-- .../src/arch/riscv/{board/virt => }/timer.rs | 3 +- kernel/src/arch/riscv/trap.rs | 17 ++-- kernel/src/mm/frame.rs | 79 ++++++++++--------- 14 files changed, 130 insertions(+), 104 deletions(-) rename kernel/src/arch/riscv/{ => board/default}/io.rs (84%) create mode 100644 kernel/src/arch/riscv/board/default/lowlevel.rs create mode 100644 kernel/src/arch/riscv/board/default/mod.rs create mode 100644 kernel/src/arch/riscv/board/virt/lowlevel.rs rename kernel/src/arch/riscv/{board/virt => }/timer.rs (86%) diff --git a/kernel/src/arch/riscv/io.rs b/kernel/src/arch/riscv/board/default/io.rs similarity index 84% rename from kernel/src/arch/riscv/io.rs rename to kernel/src/arch/riscv/board/default/io.rs index 56f42f6..fbea728 100644 --- a/kernel/src/arch/riscv/io.rs +++ b/kernel/src/arch/riscv/board/default/io.rs @@ -1,7 +1,5 @@ -#[allow(unused_imports)] use crate::plat::io::{Printer, RawConsole, Reader}; -#[cfg(feature = "board_default")] impl Printer for RawConsole { fn put_char(c: char) { #[allow(deprecated)] @@ -9,7 +7,6 @@ impl Printer for RawConsole { } } -#[cfg(feature = "board_default")] impl Reader for RawConsole { fn get_char() -> char { loop { diff --git a/kernel/src/arch/riscv/board/default/lowlevel.rs b/kernel/src/arch/riscv/board/default/lowlevel.rs new file mode 100644 index 0000000..e1887b7 --- /dev/null +++ b/kernel/src/arch/riscv/board/default/lowlevel.rs @@ -0,0 +1,19 @@ +use super::super::lowlevel::{ArchLL, ArchLLOps}; + +impl ArchLLOps for ArchLL { + fn board_shutdown(failure: bool) { + if failure { + sbi_rt::system_reset(sbi_rt::Shutdown, sbi_rt::SystemFailure); + } else { + sbi_rt::system_reset(sbi_rt::Shutdown, sbi_rt::NoReason); + } + } + + fn board_reset(failure: bool) { + if failure { + sbi_rt::system_reset(sbi_rt::ColdReboot, sbi_rt::SystemFailure); + } else { + sbi_rt::system_reset(sbi_rt::WarmReboot, sbi_rt::NoReason); + } + } +} diff --git a/kernel/src/arch/riscv/board/default/mod.rs b/kernel/src/arch/riscv/board/default/mod.rs new file mode 100644 index 0000000..8ac744c --- /dev/null +++ b/kernel/src/arch/riscv/board/default/mod.rs @@ -0,0 +1,5 @@ +pub const BOOT_HART_ID: usize = 0; +pub const TIMER_TICKS: u64 = 100_000; // 100ms + +mod io; +mod lowlevel; diff --git a/kernel/src/arch/riscv/board/virt/lowlevel.rs b/kernel/src/arch/riscv/board/virt/lowlevel.rs new file mode 100644 index 0000000..649b64b --- /dev/null +++ b/kernel/src/arch/riscv/board/virt/lowlevel.rs @@ -0,0 +1,16 @@ +use super::super::lowlevel::{ArchLL, ArchLLOps}; +use super::TEST_DEVICE; + +impl ArchLLOps for ArchLL { + fn board_shutdown(failure: bool) { + if failure { + unsafe { TEST_DEVICE.write_volatile(0x0001_3333) } + } else { + unsafe { TEST_DEVICE.write_volatile(0x0000_5555) } + } + } + + fn board_reset(_failure: bool) { + unsafe { TEST_DEVICE.write_volatile(0x0042_7777) } + } +} diff --git a/kernel/src/arch/riscv/board/virt/mod.rs b/kernel/src/arch/riscv/board/virt/mod.rs index 1516e50..d211830 100644 --- a/kernel/src/arch/riscv/board/virt/mod.rs +++ b/kernel/src/arch/riscv/board/virt/mod.rs @@ -1,10 +1,11 @@ pub const BOOT_HART_ID: usize = 0; +pub const TIMER_TICKS: u64 = 100_000; // 100ms +// devices pub const UART0_BASE: usize = 0x1000_0000; pub const UART0_LSR: usize = 0x1000_0005; pub const TEST_DEVICE: *mut u32 = 0x10_0000 as *mut u32; -pub const TIMER_TICKS: u64 = 100_000; // 100ms -pub mod printer; -pub mod reader; -pub mod timer; +mod lowlevel; +mod printer; +mod reader; diff --git a/kernel/src/arch/riscv/board/virt/printer.rs b/kernel/src/arch/riscv/board/virt/printer.rs index ed1ee02..1721558 100644 --- a/kernel/src/arch/riscv/board/virt/printer.rs +++ b/kernel/src/arch/riscv/board/virt/printer.rs @@ -1,10 +1,6 @@ use crate::plat::io::{Printer, RawConsole}; -/* - Theoretically, we should wait until - "THR Empty" bit (1<<5 in LSR) is set - before writing to UART. -*/ +// Theoretically, we should wait until "THR Empty" bit (1<<5 in LSR) is set before writing to UART. impl Printer for RawConsole { #[inline] diff --git a/kernel/src/arch/riscv/entry.rs b/kernel/src/arch/riscv/entry.rs index 077b400..ce1e18a 100644 --- a/kernel/src/arch/riscv/entry.rs +++ b/kernel/src/arch/riscv/entry.rs @@ -1,6 +1,6 @@ use core::ptr::addr_of_mut; -use crate::arch::cpu::set_hart_id; +use super::cpu::set_hart_id; #[naked] #[no_mangle] diff --git a/kernel/src/arch/riscv/layout.rs b/kernel/src/arch/riscv/layout.rs index bf41bbb..2c0dbcf 100644 --- a/kernel/src/arch/riscv/layout.rs +++ b/kernel/src/arch/riscv/layout.rs @@ -2,9 +2,6 @@ pub use super::mm::page::PAGE_SIZE; pub const KERNEL_MEM_START: usize = 0x8030_0000; -// TODO: currently a dummy value, figure out our memory layout -pub const TRAPFRAME: usize = 0x8000_0000; - extern "C" { static __kernel_end: u8; } diff --git a/kernel/src/arch/riscv/lowlevel.rs b/kernel/src/arch/riscv/lowlevel.rs index 3edb7dc..d469db3 100644 --- a/kernel/src/arch/riscv/lowlevel.rs +++ b/kernel/src/arch/riscv/lowlevel.rs @@ -2,8 +2,13 @@ use log::error; use crate::plat::lowlevel::{Hardware, LowLevel}; -#[cfg(feature = "board_virt")] -use super::board::TEST_DEVICE; +pub struct ArchLL +where ArchLL: ArchLLOps; + +pub trait ArchLLOps { + fn board_shutdown(failure: bool); + fn board_reset(failure: bool); +} impl LowLevel for Hardware { #[inline] @@ -14,25 +19,7 @@ impl LowLevel for Hardware { #[inline] fn shutdown(failure: bool) -> ! { Self::disable_interrupt(); - - if failure { - #[cfg(not(feature = "board_virt"))] - sbi_rt::system_reset(sbi_rt::Shutdown, sbi_rt::SystemFailure); - - #[cfg(feature = "board_virt")] - unsafe { - TEST_DEVICE.write_volatile(0x0001_3333) - } - } else { - #[cfg(not(feature = "board_virt"))] - sbi_rt::system_reset(sbi_rt::Shutdown, sbi_rt::NoReason); - - #[cfg(feature = "board_virt")] - unsafe { - TEST_DEVICE.write_volatile(0x0000_5555) - } - } - + ArchLL::board_shutdown(failure); loop { // in case system_reset failed Self::halt() @@ -40,19 +27,8 @@ impl LowLevel for Hardware { } #[inline] - fn reset(#[allow(unused_variables)] failure: bool) -> ! { - #[cfg(not(feature = "board_virt"))] - if failure { - sbi_rt::system_reset(sbi_rt::ColdReboot, sbi_rt::SystemFailure); - } else { - sbi_rt::system_reset(sbi_rt::WarmReboot, sbi_rt::NoReason); - } - - #[cfg(feature = "board_virt")] - unsafe { - TEST_DEVICE.write_volatile(0x0042_7777) - } - + fn reset(failure: bool) -> ! { + ArchLL::board_reset(failure); error!("[riscv/lowlevel] system_reset failed, shutdown instead"); Self::shutdown(true); } diff --git a/kernel/src/arch/riscv/mm/page.rs b/kernel/src/arch/riscv/mm/page.rs index 6628d36..6079535 100644 --- a/kernel/src/arch/riscv/mm/page.rs +++ b/kernel/src/arch/riscv/mm/page.rs @@ -4,7 +4,6 @@ use crate::mm::addr::{AddressOps, PhysAddr}; use crate::mm::page; pub const PAGE_SIZE: usize = 4096; -const PAGE_TABLE_ENTRIES: usize = 512; const PG_OFFSET: u64 = 12; const PPN_OFFSET: u64 = 10; @@ -119,16 +118,19 @@ impl page::PageTableEntry for PTE { // we'll implement sv39 paging scheme pub struct Size4KiB; + impl page::PageSize for Size4KiB { const SIZE: usize = 1 << 12; // 4KiB } pub struct Size2MiB; + impl page::PageSize for Size2MiB { const SIZE: usize = 1 << 21; // 2MiB } pub struct Size1GiB; + impl page::PageSize for Size1GiB { const SIZE: usize = 1 << 30; // 1GiB } diff --git a/kernel/src/arch/riscv/mod.rs b/kernel/src/arch/riscv/mod.rs index bdcf791..1beaf7b 100644 --- a/kernel/src/arch/riscv/mod.rs +++ b/kernel/src/arch/riscv/mod.rs @@ -1,13 +1,21 @@ +use cfg_if::cfg_if; + pub use board::BOOT_HART_ID; -#[cfg(feature = "board_virt")] -#[path = "board/virt/mod.rs"] -mod board; +cfg_if! { + if #[cfg(feature = "board_virt")] { + #[path = "board/virt/mod.rs"] + mod board; + } else { + #[path = "board/default/mod.rs"] + mod board; + } +} -pub mod cpu; -pub mod entry; -pub mod io; +mod cpu; +mod entry; pub mod layout; -pub mod lowlevel; -pub mod mm; +mod lowlevel; +mod mm; +mod timer; pub mod trap; diff --git a/kernel/src/arch/riscv/board/virt/timer.rs b/kernel/src/arch/riscv/timer.rs similarity index 86% rename from kernel/src/arch/riscv/board/virt/timer.rs rename to kernel/src/arch/riscv/timer.rs index e28570b..c304ac3 100644 --- a/kernel/src/arch/riscv/board/virt/timer.rs +++ b/kernel/src/arch/riscv/timer.rs @@ -1,5 +1,6 @@ use log::info; +use super::board::TIMER_TICKS; use crate::plat::timer::{Timer, TimerOps}; impl TimerOps for Timer { @@ -21,6 +22,6 @@ impl TimerOps for Timer { } fn tick() { - sbi_rt::set_timer(Self::read_cycle() + super::TIMER_TICKS); + sbi_rt::set_timer(Self::read_cycle() + TIMER_TICKS); } } diff --git a/kernel/src/arch/riscv/trap.rs b/kernel/src/arch/riscv/trap.rs index 06e9156..3930fae 100644 --- a/kernel/src/arch/riscv/trap.rs +++ b/kernel/src/arch/riscv/trap.rs @@ -1,15 +1,18 @@ +use cfg_if::cfg_if; use log::trace; use riscv::register::scause::{Interrupt as I, Trap as T}; -use crate::arch::cpu::get_hart_id; +use super::cpu::get_hart_id; use crate::plat::timer::{Timer, TimerOps}; use crate::plat::trap::{Trap, TrapContextOps, TrapOps}; -#[cfg(feature = "arch_riscv64")] -core::arch::global_asm!(include_str!("./asm/trap64.S")); - -#[cfg(feature = "arch_riscv32")] -core::arch::global_asm!(include_str!("./asm/trap32.S")); +cfg_if! { + if #[cfg(feature = "arch_riscv64")] { + core::arch::global_asm!(include_str!("./asm/trap64.S")); + } else if #[cfg(feature = "arch_riscv32")] { + core::arch::global_asm!(include_str!("./asm/trap32.S")); + } +} core::arch::global_asm!(include_str!("./asm/trap_common.S")); @@ -19,7 +22,7 @@ extern "C" { } #[no_mangle] -pub extern "C" fn trap_handler(tf: &mut TrapContext) { +extern "C" fn trap_handler(_tf: &mut TrapContext) { let scause = riscv::register::scause::read(); trace!( "[Interrupt] cpu@{} scause: {:?}", diff --git a/kernel/src/mm/frame.rs b/kernel/src/mm/frame.rs index d1de802..db389d5 100644 --- a/kernel/src/mm/frame.rs +++ b/kernel/src/mm/frame.rs @@ -1,49 +1,52 @@ -#[allow(unused_imports)] -use lazy_static::lazy_static; +use cfg_if::cfg_if; use log::trace; use spin::mutex::SpinMutex; use crate::arch::layout::*; use crate::mm::addr::{AddressOps, PhysAddr}; -#[allow(unused_imports)] -use crate::mm::bitmap::{Bitmap1K, BitmapOps}; -#[allow(unused_imports)] -use crate::mm::freelist::FreeList; -// 1k * 4k = 4MB, currently enough for kernel data -#[cfg(feature = "frame_bitmap")] -static ALLOCATOR: SpinMutex = SpinMutex::new(Bitmap1K::DEFAULT); +cfg_if! { + if #[cfg(feature = "frame_bitmap")] { + use crate::mm::bitmap::{Bitmap1K, BitmapOps}; -#[cfg(feature = "frame_freelist")] -lazy_static! { - static ref ALLOCATOR: SpinMutex = { - let mut list = FreeList::new(); + // 1k * 4k = 4MB, currently enough for kernel data + static ALLOCATOR: SpinMutex = SpinMutex::new(Bitmap1K::DEFAULT); + } else { // fallback to freelist + use lazy_static::lazy_static; + use crate::mm::freelist::FreeList; - for i in 0..1024 { - let addr = PhysAddr((i * PAGE_SIZE) + KERNEL_MEM_START); - list.push(addr.into()); + lazy_static! { + static ref ALLOCATOR: SpinMutex = { + let mut list = FreeList::new(); + + for i in 0..1024 { + let addr = PhysAddr((i * PAGE_SIZE) + KERNEL_MEM_START); + list.push(addr.into()); + } + + SpinMutex::new(list) + }; } - - SpinMutex::new(list) - }; + } } pub struct FrameAllocator; impl FrameAllocator { pub fn alloc(&self) -> Option { - #[cfg(feature = "frame_bitmap")] - let addr = crate::mm::frame::ALLOCATOR.lock().alloc().map(|i| { - crate::mm::addr::PhysAddr( - (i * crate::arch::arch::mm::page::PAGE_SIZE) - + crate::arch::arch::layout::KERNEL_MEM_START, - ) - }); - - #[cfg(feature = "frame_freelist")] - let addr = ALLOCATOR.lock().pop().map(|addr| addr.into()); + cfg_if! { + if #[cfg(feature = "frame_bitmap")] { + let addr = ALLOCATOR + .lock() + .alloc() + .map(|i| PhysAddr((i * PAGE_SIZE) + KERNEL_MEM_START)); + } else { + let addr = ALLOCATOR.lock().pop().map(|addr| addr.into()); + } + } trace!("[mm/frame] alloc frame: {:?}", addr); + #[cfg(debug_assertions)] fill_page(addr, 0xaa); @@ -55,17 +58,19 @@ impl FrameAllocator { debug_assert!(addr.as_usize() >= KERNEL_MEM_START); trace!("[mm/frame] dealloc frame: {:?}", addr); + #[cfg(debug_assertions)] fill_page(Some(addr), 0x55); - #[cfg(feature = "frame_bitmap")] - crate::mm::frame::ALLOCATOR.lock().dealloc( - (addr.as_usize() - crate::arch::arch::layout::KERNEL_MEM_START) - / crate::arch::arch::mm::page::PAGE_SIZE, - ); - - #[cfg(feature = "frame_freelist")] - ALLOCATOR.lock().push(addr.into()); + cfg_if! { + if #[cfg(feature = "frame_bitmap")] { + ALLOCATOR + .lock() + .dealloc((addr.as_usize() - KERNEL_MEM_START) / PAGE_SIZE); + } else { + ALLOCATOR.lock().push(addr.into()); + } + } } }