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
9 changed files with 199 additions and 135 deletions

View File

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

View File

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

View File

@ -506,10 +506,9 @@ pub trait PciInterrupt: PciDeviceStructure {
let vaddr = msix_bar
.virtual_address()
.ok_or(PciError::PciIrqError(PciIrqError::BarGetVaddrFailed))?
as usize
+ msix_table_offset as usize
+ 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 {
volwrite!(msix_entry, vector_control, 0);
volwrite!(msix_entry, msg_data, msg_data);
@ -622,10 +621,10 @@ pub trait PciInterrupt: PciDeviceStructure {
let vaddr = msix_bar
.virtual_address()
.ok_or(PciError::PciIrqError(PciIrqError::BarGetVaddrFailed))
.unwrap() as usize
.unwrap()
+ msix_table_offset as usize
+ 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 {
volwrite!(msix_entry, vector_control, 0);
volwrite!(msix_entry, msg_data, 0);
@ -747,10 +746,10 @@ pub trait PciInterrupt: PciDeviceStructure {
.ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited))
.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
+ 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 {
volwrite!(msix_entry, vector_control, 1);
}
@ -867,10 +866,10 @@ pub trait PciInterrupt: PciDeviceStructure {
.ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited))
.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
+ 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 {
volwrite!(msix_entry, vector_control, 0);
}
@ -981,10 +980,10 @@ pub trait PciInterrupt: PciDeviceStructure {
.ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited))
.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
+ (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) };
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::{
volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly,
};
use crate::mm::VirtAddr;
use core::{
fmt::{self, Display, Formatter},
mem::{align_of, size_of},
@ -18,7 +19,6 @@ use virtio_drivers::{
Error, Hal, PhysAddr,
};
type VirtAddr = usize;
/// The PCI vendor ID for VirtIO devices.
/// PCI Virtio设备的vendor ID
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::Misaligned { vaddr, alignment } => write!(
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
),
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);
let vaddr = (bar_info
.virtual_address()
.ok_or(VirtioPciError::BarGetVaddrFailed)?) as usize
.ok_or(VirtioPciError::BarGetVaddrFailed)?)
+ struct_info.offset as usize;
if vaddr % align_of::<T>() != 0 {
if vaddr.data() % align_of::<T>() != 0 {
return Err(VirtioPciError::Misaligned {
vaddr,
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())
}