From 5656805520121e9192c1a4137a6ff1785d4aea03 Mon Sep 17 00:00:00 2001 From: Yuke Peng Date: Fri, 5 May 2023 03:07:26 -0700 Subject: [PATCH] Impl MMIO access method --- framework/jinux-frame/src/arch/x86/mmio.rs | 19 ++++ framework/jinux-frame/src/arch/x86/mod.rs | 1 + framework/jinux-frame/src/lib.rs | 2 + framework/jinux-frame/src/mmio.rs | 104 +++++++++++++++++++++ 4 files changed, 126 insertions(+) create mode 100644 framework/jinux-frame/src/arch/x86/mmio.rs create mode 100644 framework/jinux-frame/src/mmio.rs diff --git a/framework/jinux-frame/src/arch/x86/mmio.rs b/framework/jinux-frame/src/arch/x86/mmio.rs new file mode 100644 index 000000000..fa6105521 --- /dev/null +++ b/framework/jinux-frame/src/arch/x86/mmio.rs @@ -0,0 +1,19 @@ +use acpi::PciConfigRegions; + +pub fn start_address() -> usize { + let start = PciConfigRegions::new( + &*crate::arch::x86::kernel::acpi::ACPI_TABLES + .get() + .unwrap() + .lock(), + ) + .unwrap(); + + // all zero to get the start address + start.physical_address(0, 0, 0, 0).unwrap() as usize +} + +pub fn end_address() -> usize { + // 4G-20M + 0xFEC0_0000 +} diff --git a/framework/jinux-frame/src/arch/x86/mod.rs b/framework/jinux-frame/src/arch/x86/mod.rs index dce3cc7fe..f3b2724ac 100644 --- a/framework/jinux-frame/src/arch/x86/mod.rs +++ b/framework/jinux-frame/src/arch/x86/mod.rs @@ -4,6 +4,7 @@ pub mod device; pub(crate) mod irq; mod kernel; pub(crate) mod mm; +pub(crate) mod mmio; pub(crate) mod timer; use alloc::fmt; diff --git a/framework/jinux-frame/src/lib.rs b/framework/jinux-frame/src/lib.rs index 6dbc55618..5efb51168 100644 --- a/framework/jinux-frame/src/lib.rs +++ b/framework/jinux-frame/src/lib.rs @@ -20,6 +20,7 @@ pub mod config; pub mod cpu; mod error; pub mod logger; +pub mod mmio; pub mod prelude; pub mod sync; pub mod task; @@ -47,6 +48,7 @@ pub fn init() { vm::init(); trap::init(); arch::after_all_init(); + mmio::init(); register_irq_common_callback(); invoke_c_init_funcs(); } diff --git a/framework/jinux-frame/src/mmio.rs b/framework/jinux-frame/src/mmio.rs new file mode 100644 index 000000000..cd7b686e3 --- /dev/null +++ b/framework/jinux-frame/src/mmio.rs @@ -0,0 +1,104 @@ +use core::{mem::size_of, ops::Range}; +use pod::Pod; +use spin::Once; + +use crate::{ + vm::{Paddr, Vaddr, VmIo}, + Error, +}; + +static CHECKER: Once = Once::new(); + +pub(crate) fn init() { + CHECKER.call_once(|| MmioChecker { + start: crate::arch::mmio::start_address(), + end: crate::arch::mmio::end_address(), + }); + log::info!( + "MMIO start: 0x{:x}, end: 0x{:x}", + CHECKER.get().unwrap().start, + CHECKER.get().unwrap().end + ); +} + +#[derive(Debug, Clone)] +pub struct Mmio { + virtual_address: Vaddr, + limit: usize, +} + +impl VmIo for Mmio { + fn read_bytes(&self, offset: usize, buf: &mut [u8]) -> crate::Result<()> { + self.check_range(offset, buf.len())?; + unsafe { + core::ptr::copy( + self.virtual_address as *const u8, + buf.as_mut_ptr(), + buf.len(), + ); + } + Ok(()) + } + + fn write_bytes(&self, offset: usize, buf: &[u8]) -> crate::Result<()> { + self.check_range(offset, buf.len())?; + unsafe { + core::ptr::copy(buf.as_ptr(), self.virtual_address as *mut u8, buf.len()); + } + Ok(()) + } + + fn read_val(&self, offset: usize) -> crate::Result { + self.check_range(offset, size_of::())?; + Ok(unsafe { core::ptr::read((self.virtual_address + offset) as *const T) }) + } + + fn write_val(&self, offset: usize, new_val: &T) -> crate::Result<()> { + self.check_range(offset, size_of::())?; + unsafe { core::ptr::write((self.virtual_address + offset) as *mut T, *new_val) }; + Ok(()) + } +} + +impl Mmio { + pub fn new(range: Range) -> Option { + if CHECKER.get().unwrap().check(&range) { + Some(Mmio { + virtual_address: crate::vm::paddr_to_vaddr(range.start), + limit: range.len(), + }) + } else { + None + } + } + + pub fn paddr(&self) -> Paddr { + crate::vm::vaddr_to_paddr(self.virtual_address).unwrap() + } + + fn check_range(&self, offset: usize, len: usize) -> crate::Result<()> { + let sum = offset.checked_add(len).ok_or(Error::InvalidArgs)?; + if sum > self.limit { + log::error!( + "attempt to access address out of bounds, limit:0x{:x}, access position:0x{:x}", + self.limit, + sum + ); + Err(Error::InvalidArgs) + } else { + Ok(()) + } + } +} + +struct MmioChecker { + start: Paddr, + end: Paddr, +} + +impl MmioChecker { + /// Check whether the physical address is in MMIO region. + fn check(&self, range: &Range) -> bool { + range.start >= self.start && range.end < self.end + } +}