mmio buddy新增guard,把映射的职责交由其守卫进行处理,并且守卫被drop的时候自动释放内存 (#346)

* mmio buddy新增guard,把映射的职责交由其守卫进行处理,并且守卫被drop的时候自动释放内存
This commit is contained in:
LoGin 2023-08-28 15:54:52 +08:00 committed by GitHub
parent 8d94ea66a3
commit 2dd9f0c750
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 199 additions and 135 deletions

View File

@ -2,7 +2,10 @@ pub mod x86_64;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub use self::x86_64::*; //公开x86_64架构下的函数使外界接口统一 pub use self::x86_64::*; //公开x86_64架构下的函数使外界接口统一
use crate::driver::pci::pci::{BusDeviceFunction, PciAddr, PciError, PciRoot, SegmentGroupNumber}; use crate::{
driver::pci::pci::{BusDeviceFunction, PciAddr, PciError, PciRoot, SegmentGroupNumber},
mm::PhysAddr,
};
/// TraitPciArch Pci架构相关函数任何架构都应独立实现trait里的函数 /// TraitPciArch Pci架构相关函数任何架构都应独立实现trait里的函数
pub trait TraitPciArch { pub trait TraitPciArch {
@ -19,7 +22,7 @@ pub trait TraitPciArch {
/// @brief PCI域地址到存储器域地址的转换,x86_64架构为一一对应 /// @brief PCI域地址到存储器域地址的转换,x86_64架构为一一对应
/// @param address PCI域地址 /// @param address PCI域地址
/// @return usize 转换结果 /// @return usize 转换结果
fn address_pci_to_physical(pci_address: PciAddr) -> usize; fn address_pci_to_physical(pci_address: PciAddr) -> PhysAddr;
/// @brief 获取Segement的root地址,x86_64架构为acpi mcfg表中读取 /// @brief 获取Segement的root地址,x86_64架构为acpi mcfg表中读取
/// @param segement 组id /// @param segement 组id
/// @return Result<PciRoot, PciError> 转换结果或出错原因 /// @return Result<PciRoot, PciError> 转换结果或出错原因

View File

@ -7,6 +7,7 @@ use crate::driver::pci::pci::{
use crate::include::bindings::bindings::{ use crate::include::bindings::bindings::{
acpi_get_MCFG, acpi_iter_SDT, acpi_system_description_table_header_t, io_in32, io_out32, acpi_get_MCFG, acpi_iter_SDT, acpi_system_description_table_header_t, io_in32, io_out32,
}; };
use crate::mm::PhysAddr;
use core::ffi::c_void; use core::ffi::c_void;
use core::ptr::NonNull; use core::ptr::NonNull;
@ -40,8 +41,8 @@ impl TraitPciArch for X86_64PciArch {
} }
} }
fn address_pci_to_physical(pci_address: PciAddr) -> usize { fn address_pci_to_physical(pci_address: PciAddr) -> PhysAddr {
return pci_address.data(); return PhysAddr::new(pci_address.data());
} }
fn ecam_root(segement: SegmentGroupNumber) -> Result<PciRoot, PciError> { fn ecam_root(segement: SegmentGroupNumber) -> Result<PciRoot, PciError> {
@ -61,8 +62,10 @@ impl TraitPciArch for X86_64PciArch {
for segmentgroupconfiguration in outcome { for segmentgroupconfiguration in outcome {
if segmentgroupconfiguration.segement_group_number == segement { if segmentgroupconfiguration.segement_group_number == segement {
return Ok(PciRoot { return Ok(PciRoot {
physical_address_base: segmentgroupconfiguration.base_address, physical_address_base: PhysAddr::new(
mmio_base: None, segmentgroupconfiguration.base_address as usize,
),
mmio_guard: None,
segement_group_number: segement, segement_group_number: segement,
bus_begin: segmentgroupconfiguration.bus_begin, bus_begin: segmentgroupconfiguration.bus_begin,
bus_end: segmentgroupconfiguration.bus_end, bus_end: segmentgroupconfiguration.bus_end,

View File

@ -93,8 +93,8 @@ pub fn ahci_rust_init() -> Result<(), SystemError> {
// 最后把这个引用列表放入到全局列表 // 最后把这个引用列表放入到全局列表
let mut hba_mem_list = LOCKED_HBA_MEM_LIST.lock(); let mut hba_mem_list = LOCKED_HBA_MEM_LIST.lock();
//这里两次unsafe转引用规避rust只能有一个可变引用的检查提高运行速度 //这里两次unsafe转引用规避rust只能有一个可变引用的检查提高运行速度
let hba_mem = unsafe { (virtaddr as *mut HbaMem).as_mut().unwrap() }; let hba_mem = unsafe { (virtaddr.data() as *mut HbaMem).as_mut().unwrap() };
hba_mem_list.push(unsafe { (virtaddr as *mut HbaMem).as_mut().unwrap() }); hba_mem_list.push(unsafe { (virtaddr.data() as *mut HbaMem).as_mut().unwrap() });
let pi = volatile_read!(hba_mem.pi); let pi = volatile_read!(hba_mem.pi);
let hba_mem_index = hba_mem_list.len() - 1; let hba_mem_index = hba_mem_list.len() - 1;
drop(hba_mem_list); drop(hba_mem_list);

View File

@ -2,14 +2,15 @@
// 目前仅支持单主桥单Segment // 目前仅支持单主桥单Segment
use super::pci_irq::{IrqType, PciIrqError}; use super::pci_irq::{IrqType, PciIrqError};
use crate::arch::{PciArch, TraitPciArch}; use crate::arch::{MMArch, PciArch, TraitPciArch};
use crate::include::bindings::bindings::{PAGE_2M_SIZE, VM_DONTCOPY, VM_IO}; use crate::include::bindings::bindings::PAGE_2M_SIZE;
use crate::libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; use crate::libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use crate::mm::kernel_mapper::KernelMapper;
use crate::mm::mmio_buddy::mmio_pool; use crate::mm::mmio_buddy::{mmio_pool, MMIOSpaceGuard};
use crate::mm::page::PageFlags;
use crate::mm::{PhysAddr, VirtAddr}; use crate::mm::{PhysAddr, VirtAddr};
use crate::{kdebug, kerror, kinfo, kwarn}; use crate::{kdebug, kerror, kinfo, kwarn};
use alloc::sync::Arc;
use alloc::vec::Vec; use alloc::vec::Vec;
use alloc::{boxed::Box, collections::LinkedList}; use alloc::{boxed::Box, collections::LinkedList};
use bitflags::bitflags; use bitflags::bitflags;
@ -592,13 +593,13 @@ impl PciDeviceStructure for PciDeviceStructurePciToCardbusBridge {
} }
/// 代表一个PCI segement greoup. /// 代表一个PCI segement greoup.
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Clone, Debug)]
pub struct PciRoot { pub struct PciRoot {
pub physical_address_base: u64, //物理地址acpi获取 pub physical_address_base: PhysAddr, //物理地址acpi获取
pub mmio_base: Option<*mut u32>, //映射后的虚拟地址,为方便访问数据这里转化成指针 pub mmio_guard: Option<Arc<MMIOSpaceGuard>>, //映射后的虚拟地址,为方便访问数据这里转化成指针
pub segement_group_number: SegmentGroupNumber, //segement greoup的id pub segement_group_number: SegmentGroupNumber, //segement greoup的id
pub bus_begin: u8, //该分组中的最小bus pub bus_begin: u8, //该分组中的最小bus
pub bus_end: u8, //该分组中的最大bus pub bus_end: u8, //该分组中的最大bus
} }
///线程间共享需要,该结构体只需要在初始化时写入数据,无需读写锁保证线程安全 ///线程间共享需要,该结构体只需要在初始化时写入数据,无需读写锁保证线程安全
unsafe impl Send for PciRoot {} unsafe impl Send for PciRoot {}
@ -608,8 +609,8 @@ impl Display for PciRoot {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!( write!(
f, f,
"PCI Root with segement:{}, bus begin at {}, bus end at {}, physical address at {:#x},mapped at {:#x}", "PCI Root with segement:{}, bus begin at {}, bus end at {}, physical address at {:?},mapped at {:?}",
self.segement_group_number, self.bus_begin, self.bus_end, self.physical_address_base, self.mmio_base.unwrap() as usize self.segement_group_number, self.bus_begin, self.bus_end, self.physical_address_base, self.mmio_guard
) )
} }
} }
@ -628,36 +629,18 @@ impl PciRoot {
//kdebug!("bus_begin={},bus_end={}", self.bus_begin,self.bus_end); //kdebug!("bus_begin={},bus_end={}", self.bus_begin,self.bus_end);
let bus_number = (self.bus_end - self.bus_begin) as u32 + 1; let bus_number = (self.bus_end - self.bus_begin) as u32 + 1;
let bus_number_double = (bus_number - 1) / 2 + 1; //一个bus占据1MB空间计算全部bus占据空间相对于2MB空间的个数 let bus_number_double = (bus_number - 1) / 2 + 1; //一个bus占据1MB空间计算全部bus占据空间相对于2MB空间的个数
let mut virtaddress: u64 = 0;
let vaddr_ptr = &mut virtaddress as *mut u64;
let mut virtsize: u64 = 0;
let virtsize_ptr = &mut virtsize as *mut u64;
let size = bus_number_double * PAGE_2M_SIZE;
unsafe {
if let Err(_) = mmio_pool().create_mmio(
size as usize,
(VM_IO | VM_DONTCOPY) as u64,
vaddr_ptr,
virtsize_ptr,
) {
kerror!("Create mmio failed when initing ecam");
return Err(PciError::CreateMmioError);
};
//kdebug!("virtaddress={:#x},virtsize={:#x}",virtaddress,virtsize); let size = (bus_number_double as usize) * (PAGE_2M_SIZE as usize);
let vaddr = VirtAddr::new(virtaddress as usize); unsafe {
let paddr = PhysAddr::new(self.physical_address_base as usize); let space_guard = mmio_pool()
// kdebug!("pci root: map: vaddr={vaddr:?}, paddr={paddr:?}, size={size}"); .create_mmio(size as usize)
let page_flags = PageFlags::mmio_flags(); .map_err(|_| PciError::CreateMmioError)?;
let mut kernel_mapper = KernelMapper::lock(); let space_guard = Arc::new(space_guard);
// todo: 添加错误处理代码。因为内核映射器可能是只读的,所以可能会出错 self.mmio_guard = Some(space_guard.clone());
assert!(kernel_mapper
.map_phys_with_size(vaddr, paddr, size as usize, page_flags, true) assert!(space_guard.map_phys::<MMArch>(self.physical_address_base, size));
.is_ok());
drop(kernel_mapper);
} }
self.mmio_base = Some(virtaddress as *mut u32); return Ok(0);
Ok(0)
} }
/// @brief 获得要操作的寄存器相对于mmio_offset的偏移量 /// @brief 获得要操作的寄存器相对于mmio_offset的偏移量
/// @param bus_device_function 在同一个group中pci设备的唯一标识符 /// @param bus_device_function 在同一个group中pci设备的唯一标识符
@ -681,7 +664,9 @@ impl PciRoot {
let address = self.cam_offset(bus_device_function, register_offset); let address = self.cam_offset(bus_device_function, register_offset);
unsafe { unsafe {
// Right shift to convert from byte offset to word offset. // Right shift to convert from byte offset to word offset.
(self.mmio_base.unwrap().add((address >> 2) as usize)).read_volatile() ((self.mmio_guard.as_ref().unwrap().vaddr().data() as *mut u32)
.add((address >> 2) as usize))
.read_volatile()
} }
} }
@ -700,7 +685,9 @@ impl PciRoot {
// resulting pointer is within the MMIO range of the CAM. // resulting pointer is within the MMIO range of the CAM.
unsafe { unsafe {
// Right shift to convert from byte offset to word offset. // Right shift to convert from byte offset to word offset.
(self.mmio_base.unwrap().add((address >> 2) as usize)).write_volatile(data) ((self.mmio_guard.as_ref().unwrap().vaddr().data() as *mut u32)
.add((address >> 2) as usize))
.write_volatile(data)
} }
} }
/// @brief 返回迭代器遍历pcie设备的external_capabilities /// @brief 返回迭代器遍历pcie设备的external_capabilities
@ -1106,7 +1093,7 @@ fn pci_check_bus(bus: u8) -> Result<u8, PciError> {
pub extern "C" fn rs_pci_init() { pub extern "C" fn rs_pci_init() {
pci_init(); pci_init();
if PCI_ROOT_0.is_some() { if PCI_ROOT_0.is_some() {
kdebug!("{}", PCI_ROOT_0.unwrap()); kdebug!("{}", PCI_ROOT_0.as_ref().unwrap());
//以下为ecam的读取寄存器值测试经测试可正常读取 //以下为ecam的读取寄存器值测试经测试可正常读取
// let bus_device_function = BusDeviceFunction { // let bus_device_function = BusDeviceFunction {
// bus: 0, // bus: 0,
@ -1237,7 +1224,7 @@ impl TryFrom<u8> for MemoryBarType {
/// Information about a PCI Base Address Register. /// Information about a PCI Base Address Register.
/// BAR的三种类型 Memory/IO/Unused /// BAR的三种类型 Memory/IO/Unused
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug)]
pub enum BarInfo { pub enum BarInfo {
/// The BAR is for a memory region. /// The BAR is for a memory region.
Memory { Memory {
@ -1251,7 +1238,7 @@ pub enum BarInfo {
/// The size of the BAR in bytes. /// The size of the BAR in bytes.
size: u32, size: u32,
/// The virtaddress for a memory bar(mapped). /// The virtaddress for a memory bar(mapped).
virtaddress: u64, mmio_guard: Arc<MMIOSpaceGuard>,
}, },
/// The BAR is for an I/O region. /// The BAR is for an I/O region.
IO { IO {
@ -1279,9 +1266,9 @@ impl BarInfo {
///@brief 得到某个bar的virtaddress(前提是他的类型为Memory Bar) ///@brief 得到某个bar的virtaddress(前提是他的类型为Memory Bar)
///@param self ///@param self
///@return Option<(u64) 是Memory Bar返回映射的虚拟地址不是则返回None ///@return Option<(u64) 是Memory Bar返回映射的虚拟地址不是则返回None
pub fn virtual_address(&self) -> Option<u64> { pub fn virtual_address(&self) -> Option<VirtAddr> {
if let Self::Memory { virtaddress, .. } = self { if let Self::Memory { mmio_guard, .. } = self {
Some(*virtaddress) Some(mmio_guard.vaddr())
} else { } else {
None None
} }
@ -1296,11 +1283,11 @@ impl Display for BarInfo {
prefetchable, prefetchable,
address, address,
size, size,
virtaddress, mmio_guard,
} => write!( } => write!(
f, f,
"Memory space at {:#010x}, size {}, type {:?}, prefetchable {},mapped at {:#x}", "Memory space at {:#010x}, size {}, type {:?}, prefetchable {}, mmio_guard: {:?}",
address, size, address_type, prefetchable, virtaddress address, size, address_type, prefetchable, mmio_guard
), ),
Self::IO { address, size } => { Self::IO { address, size } => {
write!(f, "I/O space at {:#010x}, size {}", address, size) write!(f, "I/O space at {:#010x}, size {}", address, size)
@ -1315,7 +1302,7 @@ impl Display for BarInfo {
pub trait PciDeviceBar {} pub trait PciDeviceBar {}
///一个普通PCI设备非桥有6个BAR寄存器PciStandardDeviceBar存储其全部信息 ///一个普通PCI设备非桥有6个BAR寄存器PciStandardDeviceBar存储其全部信息
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug)]
pub struct PciStandardDeviceBar { pub struct PciStandardDeviceBar {
bar0: BarInfo, bar0: BarInfo,
bar1: BarInfo, bar1: BarInfo,
@ -1378,7 +1365,6 @@ pub fn pci_bar_init(
continue; continue;
} }
let bar_info; let bar_info;
let mut virtaddress: u64 = 0;
let bar_orig = PciArch::read_config(&bus_device_function, BAR0_OFFSET + 4 * bar_index); let bar_orig = PciArch::read_config(&bus_device_function, BAR0_OFFSET + 4 * bar_index);
PciArch::write_config( PciArch::write_config(
&bus_device_function, &bus_device_function,
@ -1414,45 +1400,27 @@ pub fn pci_bar_init(
bar_index_ignore = bar_index + 1; //下个bar跳过因为64位的memory bar覆盖了两个bar bar_index_ignore = bar_index + 1; //下个bar跳过因为64位的memory bar覆盖了两个bar
} }
let pci_address = PciAddr::new(address as usize); let pci_address = PciAddr::new(address as usize);
address = PciArch::address_pci_to_physical(pci_address) as u64; //PCI总线域物理地址转换为存储器域物理地址 let paddr = PciArch::address_pci_to_physical(pci_address); //PCI总线域物理地址转换为存储器域物理地址
let space_guard: Arc<MMIOSpaceGuard>;
unsafe { unsafe {
let vaddr_ptr = &mut virtaddress as *mut u64;
let mut virtsize: u64 = 0;
let virtsize_ptr = &mut virtsize as *mut u64;
let size_want = size as usize; let size_want = size as usize;
let tmp = mmio_pool()
if let Err(_) = mmio_pool().create_mmio( .create_mmio(size_want)
size_want, .map_err(|_| PciError::CreateMmioError)?;
(VM_IO | VM_DONTCOPY) as u64, space_guard = Arc::new(tmp);
vaddr_ptr, kdebug!("Pci bar init: mmio space: {space_guard:?}, paddr={paddr:?}, size_want={size_want}");
virtsize_ptr, assert!(
) { space_guard.map_phys::<MMArch>(paddr, size_want),
kerror!("Create mmio failed when initing pci bar"); "pci_bar_init: map_phys failed"
return Err(PciError::CreateMmioError); );
};
//kdebug!("virtaddress={:#x},virtsize={:#x}",virtaddress,virtsize);
let vaddr = VirtAddr::new(virtaddress as usize);
let paddr = PhysAddr::new(address as usize);
let page_flags = PageFlags::new()
.set_write(true)
.set_execute(true)
.set_page_cache_disable(true)
.set_page_write_through(true);
kdebug!("Pci bar init: vaddr={vaddr:?}, paddr={paddr:?}, size_want={size_want}, page_flags={page_flags:?}");
let mut kernel_mapper = KernelMapper::lock();
// todo: 添加错误处理代码。因为内核映射器可能是只读的,所以可能会出错
assert!(kernel_mapper
.map_phys_with_size(vaddr, paddr, size_want, page_flags, true)
.is_ok());
drop(kernel_mapper);
} }
bar_info = BarInfo::Memory { bar_info = BarInfo::Memory {
address_type, address_type,
prefetchable, prefetchable,
address, address,
size, size,
virtaddress, mmio_guard: space_guard,
}; };
} }
match bar_index { match bar_index {

View File

@ -506,10 +506,9 @@ pub trait PciInterrupt: PciDeviceStructure {
let vaddr = msix_bar let vaddr = msix_bar
.virtual_address() .virtual_address()
.ok_or(PciError::PciIrqError(PciIrqError::BarGetVaddrFailed))? .ok_or(PciError::PciIrqError(PciIrqError::BarGetVaddrFailed))?
as usize
+ msix_table_offset as usize + msix_table_offset as usize
+ msg.irq_common_message.irq_index as usize * size_of::<MsixEntry>(); + msg.irq_common_message.irq_index as usize * size_of::<MsixEntry>();
let msix_entry = NonNull::new(vaddr as *mut MsixEntry).unwrap(); let msix_entry = NonNull::new(vaddr.data() as *mut MsixEntry).unwrap();
unsafe { unsafe {
volwrite!(msix_entry, vector_control, 0); volwrite!(msix_entry, vector_control, 0);
volwrite!(msix_entry, msg_data, msg_data); volwrite!(msix_entry, msg_data, msg_data);
@ -622,10 +621,10 @@ pub trait PciInterrupt: PciDeviceStructure {
let vaddr = msix_bar let vaddr = msix_bar
.virtual_address() .virtual_address()
.ok_or(PciError::PciIrqError(PciIrqError::BarGetVaddrFailed)) .ok_or(PciError::PciIrqError(PciIrqError::BarGetVaddrFailed))
.unwrap() as usize .unwrap()
+ msix_table_offset as usize + msix_table_offset as usize
+ index as usize * size_of::<MsixEntry>(); + index as usize * size_of::<MsixEntry>();
let msix_entry = NonNull::new(vaddr as *mut MsixEntry).unwrap(); let msix_entry = NonNull::new(vaddr.data() as *mut MsixEntry).unwrap();
unsafe { unsafe {
volwrite!(msix_entry, vector_control, 0); volwrite!(msix_entry, vector_control, 0);
volwrite!(msix_entry, msg_data, 0); volwrite!(msix_entry, msg_data, 0);
@ -747,10 +746,10 @@ pub trait PciInterrupt: PciDeviceStructure {
.ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited)) .ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited))
.unwrap(); .unwrap();
let msix_bar = pcistandardbar.get_bar(msix_table_bar).unwrap(); let msix_bar = pcistandardbar.get_bar(msix_table_bar).unwrap();
let vaddr = msix_bar.virtual_address().unwrap() as usize let vaddr = msix_bar.virtual_address().unwrap()
+ msix_table_offset as usize + msix_table_offset as usize
+ irq_index as usize * size_of::<MsixEntry>(); + irq_index as usize * size_of::<MsixEntry>();
let msix_entry = NonNull::new(vaddr as *mut MsixEntry).unwrap(); let msix_entry = NonNull::new(vaddr.data() as *mut MsixEntry).unwrap();
unsafe { unsafe {
volwrite!(msix_entry, vector_control, 1); volwrite!(msix_entry, vector_control, 1);
} }
@ -867,10 +866,10 @@ pub trait PciInterrupt: PciDeviceStructure {
.ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited)) .ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited))
.unwrap(); .unwrap();
let msix_bar = pcistandardbar.get_bar(msix_table_bar).unwrap(); let msix_bar = pcistandardbar.get_bar(msix_table_bar).unwrap();
let vaddr = msix_bar.virtual_address().unwrap() as usize let vaddr = msix_bar.virtual_address().unwrap()
+ msix_table_offset as usize + msix_table_offset as usize
+ irq_index as usize * size_of::<MsixEntry>(); + irq_index as usize * size_of::<MsixEntry>();
let msix_entry = NonNull::new(vaddr as *mut MsixEntry).unwrap(); let msix_entry = NonNull::new(vaddr.data() as *mut MsixEntry).unwrap();
unsafe { unsafe {
volwrite!(msix_entry, vector_control, 0); volwrite!(msix_entry, vector_control, 0);
} }
@ -981,10 +980,10 @@ pub trait PciInterrupt: PciDeviceStructure {
.ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited)) .ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited))
.unwrap(); .unwrap();
let pending_bar = pcistandardbar.get_bar(pending_table_bar).unwrap(); let pending_bar = pcistandardbar.get_bar(pending_table_bar).unwrap();
let vaddr = pending_bar.virtual_address().unwrap() as usize let vaddr = pending_bar.virtual_address().unwrap()
+ pending_table_offset as usize + pending_table_offset as usize
+ (irq_index as usize / 64) * size_of::<PendingEntry>(); + (irq_index as usize / 64) * size_of::<PendingEntry>();
let pending_entry = NonNull::new(vaddr as *mut PendingEntry).unwrap(); let pending_entry = NonNull::new(vaddr.data() as *mut PendingEntry).unwrap();
let pending_entry = unsafe { volread!(pending_entry, entry) }; let pending_entry = unsafe { volread!(pending_entry, entry) };
return Ok(pending_entry & (1 << (irq_index as u64 % 64)) != 0); return Ok(pending_entry & (1 << (irq_index as u64 % 64)) != 0);
} }

View File

@ -8,6 +8,7 @@ use crate::driver::pci::pci::{
use crate::libs::volatile::{ use crate::libs::volatile::{
volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly, volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly,
}; };
use crate::mm::VirtAddr;
use core::{ use core::{
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
mem::{align_of, size_of}, mem::{align_of, size_of},
@ -18,7 +19,6 @@ use virtio_drivers::{
Error, Hal, PhysAddr, Error, Hal, PhysAddr,
}; };
type VirtAddr = usize;
/// The PCI vendor ID for VirtIO devices. /// The PCI vendor ID for VirtIO devices.
/// PCI Virtio设备的vendor ID /// PCI Virtio设备的vendor ID
const VIRTIO_VENDOR_ID: u16 = 0x1af4; const VIRTIO_VENDOR_ID: u16 = 0x1af4;
@ -437,7 +437,7 @@ impl Display for VirtioPciError {
Self::BarOffsetOutOfRange => write!(f, "Capability offset greater than BAR length."), Self::BarOffsetOutOfRange => write!(f, "Capability offset greater than BAR length."),
Self::Misaligned { vaddr, alignment } => write!( Self::Misaligned { vaddr, alignment } => write!(
f, f,
"Virtual address {:#018x} was not aligned to a {} byte boundary as expected.", "Virtual address {:?} was not aligned to a {} byte boundary as expected.",
vaddr, alignment vaddr, alignment
), ),
Self::BarGetVaddrFailed => write!(f, "Get bar virtaddress failed"), Self::BarGetVaddrFailed => write!(f, "Get bar virtaddress failed"),
@ -475,15 +475,15 @@ fn get_bar_region<T>(
//kdebug!("Chossed bar ={},used={}",struct_info.bar,struct_info.offset + struct_info.length); //kdebug!("Chossed bar ={},used={}",struct_info.bar,struct_info.offset + struct_info.length);
let vaddr = (bar_info let vaddr = (bar_info
.virtual_address() .virtual_address()
.ok_or(VirtioPciError::BarGetVaddrFailed)?) as usize .ok_or(VirtioPciError::BarGetVaddrFailed)?)
+ struct_info.offset as usize; + struct_info.offset as usize;
if vaddr % align_of::<T>() != 0 { if vaddr.data() % align_of::<T>() != 0 {
return Err(VirtioPciError::Misaligned { return Err(VirtioPciError::Misaligned {
vaddr, vaddr,
alignment: align_of::<T>(), alignment: align_of::<T>(),
}); });
} }
let vaddr = NonNull::new(vaddr as *mut u8).unwrap(); let vaddr = NonNull::new(vaddr.data() as *mut u8).unwrap();
Ok(vaddr.cast()) Ok(vaddr.cast())
} }

View File

@ -11,9 +11,10 @@ use crate::{kerror, kinfo, kwarn};
use alloc::{collections::LinkedList, vec::Vec}; use alloc::{collections::LinkedList, vec::Vec};
use core::mem; use core::mem;
use core::mem::MaybeUninit; use core::mem::MaybeUninit;
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
use super::VirtAddr; use super::page::PageFlags;
use super::{PhysAddr, VirtAddr};
// 最大的伙伴块的幂 // 最大的伙伴块的幂
const MMIO_BUDDY_MAX_EXP: u32 = PAGE_1G_SHIFT; const MMIO_BUDDY_MAX_EXP: u32 = PAGE_1G_SHIFT;
@ -474,20 +475,14 @@ impl MmioBuddyMemPool {
/// @return Ok(i32) 成功返回0 /// @return Ok(i32) 成功返回0
/// ///
/// @return Err(SystemError) 失败返回错误码 /// @return Err(SystemError) 失败返回错误码
pub fn create_mmio( pub fn create_mmio(&self, size: usize) -> Result<MMIOSpaceGuard, SystemError> {
&self,
size: usize,
_vm_flags: vm_flags_t,
res_vaddr: *mut u64,
res_length: *mut u64,
) -> Result<i32, SystemError> {
if size > PAGE_1G_SIZE || size == 0 { if size > PAGE_1G_SIZE || size == 0 {
return Err(SystemError::EPERM); return Err(SystemError::EPERM);
} }
let retval: i32 = 0;
// 计算前导0 // 计算前导0
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
let mut size_exp: u32 = 63 - size.leading_zeros(); let mut size_exp: u32 = 63 - size.leading_zeros();
// 记录最终申请的空间大小 // 记录最终申请的空间大小
let mut new_size = size; let mut new_size = size;
// 对齐要申请的空间大小 // 对齐要申请的空间大小
@ -502,21 +497,15 @@ impl MmioBuddyMemPool {
} }
match self.mmio_buddy_query_addr_region(size_exp) { match self.mmio_buddy_query_addr_region(size_exp) {
Ok(region) => { Ok(region) => {
// todo: 是否需要创建vma或者用新重写的机制去做 let space_guard =
// kdebug!( unsafe { MMIOSpaceGuard::from_raw(region.vaddr, new_size, false) };
// "create_mmio: vaddr = {:?}, length = {}", return Ok(space_guard);
// region.vaddr,
// new_size
// );
unsafe { *res_vaddr = region.vaddr.data() as u64 };
unsafe { *res_length = new_size as u64 };
} }
Err(_) => { Err(_) => {
kerror!("failed to create mmio. pid = {:?}", current_pcb().pid); kerror!("failed to create mmio. pid = {:?}", current_pcb().pid);
return Err(SystemError::ENOMEM); return Err(SystemError::ENOMEM);
} }
} }
return Ok(retval);
} }
/// @brief 取消mmio的映射并将地址空间归还到buddy中 /// @brief 取消mmio的映射并将地址空间归还到buddy中
@ -528,7 +517,7 @@ impl MmioBuddyMemPool {
/// @return Ok(i32) 成功返回0 /// @return Ok(i32) 成功返回0
/// ///
/// @return Err(SystemError) 失败返回错误码 /// @return Err(SystemError) 失败返回错误码
pub fn release_mmio(&self, vaddr: VirtAddr, length: usize) -> Result<i32, SystemError> { fn release_mmio(&self, vaddr: VirtAddr, length: usize) -> Result<i32, SystemError> {
assert!(vaddr.check_aligned(MMArch::PAGE_SIZE)); assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
assert!(length & (MMArch::PAGE_SIZE - 1) == 0); assert!(length & (MMArch::PAGE_SIZE - 1) == 0);
if vaddr < self.pool_start_addr if vaddr < self.pool_start_addr
@ -553,7 +542,7 @@ impl MmioBuddyMemPool {
kernel_mapper kernel_mapper
.as_mut() .as_mut()
.unwrap() .unwrap()
.unmap(vaddr + i * MMArch::PAGE_SIZE, true) .unmap_phys(vaddr + i * MMArch::PAGE_SIZE, true)
}; };
} }
@ -614,6 +603,88 @@ fn exp2index(exp: u32) -> usize {
return (exp - 12) as usize; return (exp - 12) as usize;
} }
#[derive(Debug)]
pub struct MMIOSpaceGuard {
vaddr: VirtAddr,
size: usize,
mapped: AtomicBool,
}
impl MMIOSpaceGuard {
pub unsafe fn from_raw(vaddr: VirtAddr, size: usize, mapped: bool) -> Self {
// check size
assert!(
size & (MMArch::PAGE_SIZE - 1) == 0,
"MMIO space size must be page aligned"
);
assert!(size.is_power_of_two(), "MMIO space size must be power of 2");
assert!(
vaddr.check_aligned(size),
"MMIO space vaddr must be aligned with size"
);
assert!(
vaddr.data() >= MMIO_BASE.data() && vaddr.data() + size <= MMIO_TOP.data(),
"MMIO space must be in MMIO region"
);
// 人工创建的MMIO空间认为已经映射
MMIOSpaceGuard {
vaddr,
size,
mapped: AtomicBool::new(mapped),
}
}
pub fn vaddr(&self) -> VirtAddr {
self.vaddr
}
pub fn size(&self) -> usize {
self.size
}
/// 将物理地址填写到虚拟地址空间中
///
/// ## Safety
///
/// 传入的物理地址【一定要是设备的物理地址】。
/// 如果物理地址是从内存分配器中分配的那么会造成内存泄露。因为mmio_release的时候只取消映射不会释放内存。
pub unsafe fn map_phys<Arch: MemoryManagementArch>(
&self,
paddr: PhysAddr,
length: usize,
) -> bool {
if length > self.size {
return false;
}
let check = self
.mapped
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst);
if check.is_err() {
return false;
}
let flags = PageFlags::mmio_flags();
let mut kernel_mapper = KernelMapper::lock();
let r = kernel_mapper.map_phys_with_size(self.vaddr, paddr, length, flags, true);
if r.is_err() {
return false;
}
return true;
}
}
impl Drop for MMIOSpaceGuard {
fn drop(&mut self) {
let _ = mmio_pool()
.release_mmio(self.vaddr, self.size)
.unwrap_or_else(|err| {
panic!("MMIO release failed: self: {self:?}, err msg: {:?}", err);
});
}
}
pub fn mmio_init() { pub fn mmio_init() {
kdebug!("Initializing MMIO buddy memory pool..."); kdebug!("Initializing MMIO buddy memory pool...");
// 初始化mmio内存池 // 初始化mmio内存池
@ -635,18 +706,23 @@ pub fn mmio_init() {
/// ///
/// @return int 错误码 /// @return int 错误码
#[no_mangle] #[no_mangle]
pub extern "C" fn mmio_create( pub unsafe extern "C" fn mmio_create(
size: u32, size: u32,
vm_flags: vm_flags_t, _vm_flags: vm_flags_t,
res_vaddr: *mut u64, res_vaddr: *mut u64,
res_length: *mut u64, res_length: *mut u64,
) -> i32 { ) -> i32 {
// kdebug!("mmio_create"); // kdebug!("mmio_create");
if let Err(err) = mmio_pool().create_mmio(size as usize, vm_flags, res_vaddr, res_length) { let r = mmio_pool().create_mmio(size as usize);
return err.to_posix_errno(); if r.is_err() {
} else { return r.unwrap_err().to_posix_errno();
return 0;
} }
let space_guard = r.unwrap();
*res_vaddr = space_guard.vaddr().data() as u64;
*res_length = space_guard.size() as u64;
// 由于space_guard drop的时候会自动释放内存所以这里要忽略它的释放
core::mem::forget(space_guard);
return 0;
} }
/// @brief 取消mmio的映射并将地址空间归还到buddy中 /// @brief 取消mmio的映射并将地址空间归还到buddy中
@ -659,7 +735,7 @@ pub extern "C" fn mmio_create(
/// ///
/// @return Err(i32) 失败返回错误码 /// @return Err(i32) 失败返回错误码
#[no_mangle] #[no_mangle]
pub extern "C" fn mmio_release(vaddr: u64, length: u64) -> i32 { pub unsafe extern "C" fn mmio_release(vaddr: u64, length: u64) -> i32 {
return mmio_pool() return mmio_pool()
.release_mmio(VirtAddr::new(vaddr as usize), length as usize) .release_mmio(VirtAddr::new(vaddr as usize), length as usize)
.unwrap_or_else(|err| err.to_posix_errno()); .unwrap_or_else(|err| err.to_posix_errno());

View File

@ -152,6 +152,20 @@ impl core::ops::AddAssign<PhysAddr> for PhysAddr {
} }
} }
impl core::ops::BitOrAssign<usize> for PhysAddr {
#[inline(always)]
fn bitor_assign(&mut self, rhs: usize) {
self.0 |= rhs;
}
}
impl core::ops::BitOrAssign<PhysAddr> for PhysAddr {
#[inline(always)]
fn bitor_assign(&mut self, rhs: PhysAddr) {
self.0 |= rhs.0;
}
}
impl core::ops::Sub<usize> for PhysAddr { impl core::ops::Sub<usize> for PhysAddr {
type Output = Self; type Output = Self;

View File

@ -689,6 +689,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
/// ///
/// ## 返回值 /// ## 返回值
/// 如果取消成功返回刷新器否则返回None /// 如果取消成功返回刷新器否则返回None
#[allow(dead_code)]
pub unsafe fn unmap(&mut self, virt: VirtAddr, unmap_parents: bool) -> Option<PageFlush<Arch>> { pub unsafe fn unmap(&mut self, virt: VirtAddr, unmap_parents: bool) -> Option<PageFlush<Arch>> {
let (paddr, _, flusher) = self.unmap_phys(virt, unmap_parents)?; let (paddr, _, flusher) = self.unmap_phys(virt, unmap_parents)?;
self.frame_allocator.free_one(paddr); self.frame_allocator.free_one(paddr);