Better module usage in zircon-object/dev/pci

This commit is contained in:
Yuekai Jia 2021-09-03 17:57:53 +08:00
parent dee715c4a2
commit 5c33799a04
15 changed files with 139 additions and 87 deletions

View File

@ -25,6 +25,7 @@ xmas-elf = { version = "0.7", optional = true }
region-alloc = { git = "https://github.com/rzswh/region-allocator", rev = "122c7a71" } region-alloc = { git = "https://github.com/rzswh/region-allocator", rev = "122c7a71" }
lazy_static = { version = "1.4", features = ["spin_no_std" ] } lazy_static = { version = "1.4", features = ["spin_no_std" ] }
acpi = "1.1" acpi = "1.1"
cfg-if = "1.0"
#rvm = { git = "https://github.com/rcore-os/RVM", rev = "382fc60", optional = true } #rvm = { git = "https://github.com/rcore-os/RVM", rev = "382fc60", optional = true }
[dev-dependencies] [dev-dependencies]

View File

@ -2,7 +2,7 @@ use {
self::event_interrupt::*, self::event_interrupt::*,
self::pci_interrupt::*, self::pci_interrupt::*,
self::virtual_interrupt::*, self::virtual_interrupt::*,
super::IPciNode, crate::dev::pci::IPciNode,
crate::object::*, crate::object::*,
crate::signal::*, crate::signal::*,
alloc::{boxed::Box, sync::Arc}, alloc::{boxed::Box, sync::Arc},

View File

@ -1,4 +1,9 @@
use {super::super::pci::PCIE_IRQRET_MASK, super::super::IPciNode, super::*, spin::Mutex}; use alloc::{boxed::Box, sync::Arc};
use spin::Mutex;
use super::InterruptTrait;
use crate::dev::pci::{constants::PCIE_IRQRET_MASK, IPciNode};
use crate::{ZxError, ZxResult};
pub struct PciInterrupt { pub struct PciInterrupt {
device: Arc<dyn IPciNode>, device: Arc<dyn IPciNode>,

View File

@ -1,11 +1,10 @@
//! Objects for Device Drivers. //! Objects for Device Drivers.
use super::*;
mod bti; mod bti;
mod interrupt; mod interrupt;
mod iommu; mod iommu;
mod pci; pub mod pci;
mod pmt; mod pmt;
mod resource; mod resource;
pub use self::{bti::*, interrupt::*, iommu::*, pci::*, pmt::*, resource::*}; pub use self::{bti::*, interrupt::*, iommu::*, pmt::*, resource::*};

View File

@ -1,9 +1,18 @@
use super::super::*; use super::nodes::{
use super::config::*; IPciNode, PciNodeType, PciRoot, PcieBarInfo, PcieIrqMode, PcieIrqModeCaps,
use super::*; SharedLegacyIrqHandler,
};
use super::{
config::PciConfig, constants::*, pci_init_args::PciIrqSwizzleLut, pio::pci_bdf_raw_addr,
MappedEcamRegion, PciAddrSpace, PciEcamRegion,
};
use crate::dev::Interrupt;
use crate::object::*; use crate::object::*;
use crate::vm::{kernel_allocate_physical, CachePolicy, MMUFlags, PhysAddr, VirtAddr}; use crate::vm::{kernel_allocate_physical, CachePolicy, MMUFlags, PhysAddr, VirtAddr};
use alloc::{collections::BTreeMap, sync::Arc, vec::Vec}; use crate::ZxResult;
use alloc::sync::{Arc, Weak};
use alloc::{collections::BTreeMap, vec::Vec};
use core::cmp::min; use core::cmp::min;
use core::marker::{Send, Sync}; use core::marker::{Send, Sync};
use lazy_static::*; use lazy_static::*;

View File

@ -1,6 +1,6 @@
use super::super::{ZxError, ZxResult}; use super::{config::PciConfig, nodes::PcieDeviceType};
use super::config::PciConfig; use crate::{ZxError, ZxResult};
use super::nodes::PcieDeviceType;
use alloc::boxed::Box; use alloc::boxed::Box;
use core::convert::TryFrom; use core::convert::TryFrom;
use kernel_hal::InterruptManager; use kernel_hal::InterruptManager;

View File

@ -1,5 +1,6 @@
use super::*; use super::pio::{pio_config_read_addr, pio_config_write_addr};
use numeric_enum_macro::*; use super::PciAddrSpace;
use numeric_enum_macro::numeric_enum;
#[derive(Debug)] #[derive(Debug)]
pub struct PciConfig { pub struct PciConfig {

View File

@ -1,3 +1,5 @@
#![allow(missing_docs)]
mod bus; mod bus;
mod caps; mod caps;
mod config; mod config;
@ -5,17 +7,11 @@ mod nodes;
pub mod pci_init_args; pub mod pci_init_args;
mod pio; mod pio;
use super::*;
use alloc::sync::*;
pub(crate) use nodes::*;
use pci_init_args::*;
use pio::*;
pub use self::bus::{ pub use self::bus::{
MmioPcieAddressProvider, PCIeBusDriver, PcieDeviceInfo, PcieDeviceKObject, MmioPcieAddressProvider, PCIeBusDriver, PcieDeviceInfo, PcieDeviceKObject,
PioPcieAddressProvider, PioPcieAddressProvider,
}; };
pub use self::nodes::PcieIrqMode; pub use self::nodes::{IPciNode, PcieIrqMode};
pub use self::pio::{pio_config_read, pio_config_write}; pub use self::pio::{pio_config_read, pio_config_write};
/// Type of PCI address space. /// Type of PCI address space.
@ -46,10 +42,8 @@ pub struct MappedEcamRegion {
vaddr: u64, vaddr: u64,
} }
pub use constants::*;
#[allow(missing_docs)] #[allow(missing_docs)]
mod constants { pub mod constants {
pub const PCI_MAX_DEVICES_PER_BUS: usize = 32; pub const PCI_MAX_DEVICES_PER_BUS: usize = 32;
pub const PCI_MAX_FUNCTIONS_PER_DEVICE: usize = 8; pub const PCI_MAX_FUNCTIONS_PER_DEVICE: usize = 8;
pub const PCI_MAX_LEGACY_IRQ_PINS: usize = 4; pub const PCI_MAX_LEGACY_IRQ_PINS: usize = 4;

View File

@ -1,12 +1,22 @@
#![allow(dead_code)] #![allow(dead_code)]
#![allow(missing_docs)]
use super::{caps::*, config::*, *}; use super::caps::{
use crate::vm::PAGE_SIZE; PciCapAdvFeatures, PciCapPcie, PciCapability, PciCapabilityMsi, PciCapabilityStd, PciMsiBlock,
use alloc::{boxed::Box, sync::*, vec::Vec}; };
use super::config::{
PciConfig, PciReg16, PciReg32, PciReg8, PCIE_BASE_CONFIG_SIZE, PCIE_EXTENDED_CONFIG_SIZE,
};
use super::constants::*;
use super::{bus::PCIeBusDriver, pci_init_args::PciIrqSwizzleLut};
use crate::{vm::PAGE_SIZE, ZxError, ZxResult};
use alloc::sync::{Arc, Weak};
use alloc::{boxed::Box, vec::Vec};
use kernel_hal::InterruptManager; use kernel_hal::InterruptManager;
use numeric_enum_macro::*; use numeric_enum_macro::numeric_enum;
use region_alloc::RegionAllocator; use region_alloc::RegionAllocator;
use spin::*; use spin::{Mutex, MutexGuard};
numeric_enum! { numeric_enum! {
#[repr(u8)] #[repr(u8)]
@ -953,7 +963,7 @@ impl PcieDevice {
})) }))
} }
} }
fn enable_msi_irq_mode(&self, inner: &mut MutexGuard<PcieDeviceInner>, irq: u32) -> ZxResult { fn enter_msi_irq_mode(&self, inner: &mut MutexGuard<PcieDeviceInner>, irq: u32) -> ZxResult {
let (_std, msi) = inner.msi().ok_or(ZxError::NOT_SUPPORTED)?; let (_std, msi) = inner.msi().ok_or(ZxError::NOT_SUPPORTED)?;
let initially_masked = if msi.has_pvm { let initially_masked = if msi.has_pvm {
self.cfg self.cfg
@ -1134,7 +1144,7 @@ impl PcieDevice {
inner.irq.legacy.shared_handler.add_device(inner.arc_self()); inner.irq.legacy.shared_handler.add_device(inner.arc_self());
Ok(()) Ok(())
} }
PcieIrqMode::Msi => self.enable_msi_irq_mode(&mut inner, irq_count), PcieIrqMode::Msi => self.enter_msi_irq_mode(&mut inner, irq_count),
PcieIrqMode::MsiX => Err(ZxError::NOT_SUPPORTED), PcieIrqMode::MsiX => Err(ZxError::NOT_SUPPORTED),
_ => Err(ZxError::INVALID_ARGS), _ => Err(ZxError::INVALID_ARGS),
} }

View File

@ -3,6 +3,9 @@
//! //!
//! reference: zircon/system/public/zircon/syscalls/pci.h //! reference: zircon/system/public/zircon/syscalls/pci.h
use super::constants::*;
use crate::{ZxError, ZxResult};
#[repr(transparent)] #[repr(transparent)]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct PciIrqSwizzleLut( pub struct PciIrqSwizzleLut(
@ -42,7 +45,6 @@ pub const PCI_INIT_ARG_MAX_SIZE: usize = core::mem::size_of::<PciInitArgsAddrWin
* PCI_INIT_ARG_MAX_ECAM_WINDOWS * PCI_INIT_ARG_MAX_ECAM_WINDOWS
+ core::mem::size_of::<PciInitArgsHeader>(); + core::mem::size_of::<PciInitArgsHeader>();
use super::*;
use kernel_hal::InterruptManager; use kernel_hal::InterruptManager;
impl PciInitArgsHeader { impl PciInitArgsHeader {

View File

@ -1,12 +1,6 @@
#![allow(missing_docs)] #![allow(missing_docs)]
use super::super::*;
use kernel_hal::{inpd, outpd};
use spin::Mutex;
static PIO_LOCK: Mutex<()> = Mutex::new(()); use crate::{ZxError, ZxResult};
const PCI_CONFIG_ADDR: u16 = 0xcf8;
const PCI_CONFIG_DATA: u16 = 0xcfc;
const PCI_CONFIG_ENABLE: u32 = 1 << 31;
/// Returns the BDF address without the bottom two bits masked off. /// Returns the BDF address without the bottom two bits masked off.
pub fn pci_bdf_raw_addr(bus: u8, dev: u8, func: u8, offset: u8) -> u32 { pub fn pci_bdf_raw_addr(bus: u8, dev: u8, func: u8, offset: u8) -> u32 {
@ -16,21 +10,57 @@ pub fn pci_bdf_raw_addr(bus: u8, dev: u8, func: u8, offset: u8) -> u32 {
| (offset as u32 & 0xff) // bits 7-2 reg, with bottom 2 bits as well | (offset as u32 & 0xff) // bits 7-2 reg, with bottom 2 bits as well
} }
cfg_if::cfg_if! {
if #[cfg(all(target_arch = "x86_64", target_os = "none"))] {
use kernel_hal::{inpd, outpd};
use spin::Mutex;
static PIO_LOCK: Mutex<()> = Mutex::new(());
const PCI_CONFIG_ADDR: u16 = 0xcf8;
const PCI_CONFIG_DATA: u16 = 0xcfc;
const PCI_CONFIG_ENABLE: u32 = 1 << 31;
pub fn pio_config_read_addr(addr: u32, width: usize) -> ZxResult<u32> {
let _lock = PIO_LOCK.lock();
let shift = ((addr & 0x3) << 3) as usize;
if shift + width > 32 {
return Err(ZxError::INVALID_ARGS);
}
outpd(PCI_CONFIG_ADDR, (addr & !0x3) | PCI_CONFIG_ENABLE);
let tmp_val = u32::from_le(inpd(PCI_CONFIG_DATA));
Ok((tmp_val >> shift) & (((1u64 << width) - 1) as u32))
}
pub fn pio_config_write_addr(addr: u32, val: u32, width: usize) -> ZxResult {
let _lock = PIO_LOCK.lock();
let shift = ((addr & 0x3) << 3) as usize;
if shift + width > 32 {
return Err(ZxError::INVALID_ARGS);
}
outpd(PCI_CONFIG_ADDR, (addr & !0x3) | PCI_CONFIG_ENABLE);
let width_mask = ((1u64 << width) - 1) as u32;
let val = val & width_mask;
let tmp_val = if width < 32 {
(u32::from_le(inpd(PCI_CONFIG_DATA)) & !(width_mask << shift)) | (val << shift)
} else {
val
};
outpd(PCI_CONFIG_DATA, u32::to_le(tmp_val));
Ok(())
}
} else {
pub fn pio_config_read_addr(_addr: u32, _width: usize) -> ZxResult<u32> {
Err(ZxError::NOT_SUPPORTED)
}
pub fn pio_config_write_addr(_addr: u32, _val: u32, _width: usize) -> ZxResult {
Err(ZxError::NOT_SUPPORTED)
}
}
} // cfg_if!
pub fn pio_config_read(bus: u8, dev: u8, func: u8, offset: u8, width: usize) -> ZxResult<u32> { pub fn pio_config_read(bus: u8, dev: u8, func: u8, offset: u8, width: usize) -> ZxResult<u32> {
pio_config_read_addr(pci_bdf_raw_addr(bus, dev, func, offset), width) pio_config_read_addr(pci_bdf_raw_addr(bus, dev, func, offset), width)
} }
pub fn pio_config_read_addr(addr: u32, width: usize) -> ZxResult<u32> {
let _lock = PIO_LOCK.lock();
let shift = ((addr & 0x3) << 3) as usize;
if shift + width > 32 {
return Err(ZxError::INVALID_ARGS);
}
outpd(PCI_CONFIG_ADDR, (addr & !0x3) | PCI_CONFIG_ENABLE);
let tmp_val = u32::from_le(inpd(PCI_CONFIG_DATA));
Ok((tmp_val >> shift) & (((1u64 << width) - 1) as u32))
}
pub fn pio_config_write( pub fn pio_config_write(
bus: u8, bus: u8,
dev: u8, dev: u8,
@ -41,21 +71,3 @@ pub fn pio_config_write(
) -> ZxResult { ) -> ZxResult {
pio_config_write_addr(pci_bdf_raw_addr(bus, dev, func, offset), val, width) pio_config_write_addr(pci_bdf_raw_addr(bus, dev, func, offset), val, width)
} }
pub fn pio_config_write_addr(addr: u32, val: u32, width: usize) -> ZxResult {
let _lock = PIO_LOCK.lock();
let shift = ((addr & 0x3) << 3) as usize;
if shift + width > 32 {
return Err(ZxError::INVALID_ARGS);
}
outpd(PCI_CONFIG_ADDR, (addr & !0x3) | PCI_CONFIG_ENABLE);
let width_mask = ((1u64 << width) - 1) as u32;
let val = val & width_mask;
let tmp_val = if width < 32 {
(u32::from_le(inpd(PCI_CONFIG_DATA)) & !(width_mask << shift)) | (val << shift)
} else {
val
};
outpd(PCI_CONFIG_DATA, u32::to_le(tmp_val));
Ok(())
}

View File

@ -22,4 +22,4 @@ numeric-enum-macro = "0.2"
zircon-object = { path = "../zircon-object" } zircon-object = { path = "../zircon-object" }
kernel-hal = { path = "../kernel-hal" } kernel-hal = { path = "../kernel-hal" }
futures = { version = "0.3", default-features = false, features = ["alloc", "async-await"] } futures = { version = "0.3", default-features = false, features = ["alloc", "async-await"] }
cfg-if = "1.0"

View File

@ -132,6 +132,7 @@ impl Syscall<'_> {
} }
/// ///
#[allow(unused_variables, unused_mut)]
pub fn sys_pc_firmware_tables( pub fn sys_pc_firmware_tables(
&self, &self,
resource: HandleValue, resource: HandleValue,
@ -142,10 +143,16 @@ impl Syscall<'_> {
let proc = self.thread.proc(); let proc = self.thread.proc();
proc.get_object::<Resource>(resource)? proc.get_object::<Resource>(resource)?
.validate(ResourceKind::ROOT)?; .validate(ResourceKind::ROOT)?;
let (acpi_rsdp, smbios) = kernel_hal::pc_firmware_tables(); cfg_if::cfg_if! {
acpi_rsdp_ptr.write(acpi_rsdp)?; if #[cfg(all(target_arch = "x86_64", target_os = "none"))] {
smbios_ptr.write(smbios)?; let (acpi_rsdp, smbios) = kernel_hal::pc_firmware_tables();
Ok(()) acpi_rsdp_ptr.write(acpi_rsdp)?;
smbios_ptr.write(smbios)?;
Ok(())
} else {
Err(ZxError::NOT_SUPPORTED)
}
}
} }
/// Creates an interrupt object which represents a physical or virtual interrupt. /// Creates an interrupt object which represents a physical or virtual interrupt.

View File

@ -322,7 +322,6 @@ impl Syscall<'_> {
Sys::PCI_ADD_SUBTRACT_IO_RANGE => { Sys::PCI_ADD_SUBTRACT_IO_RANGE => {
self.sys_pci_add_subtract_io_range(a0 as _, a1 != 0, a2 as _, a3 as _, a4 != 0) self.sys_pci_add_subtract_io_range(a0 as _, a1 != 0, a2 as _, a3 as _, a4 != 0)
} }
#[cfg(target_arch = "x86_64")]
Sys::PCI_CFG_PIO_RW => self.sys_pci_cfg_pio_rw( Sys::PCI_CFG_PIO_RW => self.sys_pci_cfg_pio_rw(
a0 as _, a0 as _,
a1 as _, a1 as _,

View File

@ -1,7 +1,14 @@
use super::*; use super::*;
use alloc::sync::Arc;
use core::convert::TryFrom; use core::convert::TryFrom;
use zircon_object::{ use zircon_object::{
dev::{pci_init_args::*, *}, dev::pci::{
constants::*,
pci_init_args::{PciInitArgsAddrWindows, PciInitArgsHeader, PCI_INIT_ARG_MAX_SIZE},
MmioPcieAddressProvider, PCIeBusDriver, PciAddrSpace, PciEcamRegion, PcieDeviceInfo,
PcieDeviceKObject, PcieIrqMode, PioPcieAddressProvider,
},
dev::{Resource, ResourceKind},
vm::{pages, VmObject}, vm::{pages, VmObject},
}; };
@ -33,8 +40,7 @@ impl Syscall<'_> {
} }
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments, unused_variables, unused_mut)]
#[cfg(target_arch = "x86_64")]
pub fn sys_pci_cfg_pio_rw( pub fn sys_pci_cfg_pio_rw(
&self, &self,
handle: HandleValue, handle: HandleValue,
@ -50,17 +56,24 @@ impl Syscall<'_> {
"pci.cfg_pio_rw: handle={:#x}, addr={:x}:{:x}:{:x}, offset={:#x}, width={:#x}, write={:#}", "pci.cfg_pio_rw: handle={:#x}, addr={:x}:{:x}:{:x}, offset={:#x}, width={:#x}, write={:#}",
handle, bus, dev, func, offset, width, write handle, bus, dev, func, offset, width, write
); );
let proc = self.thread.proc(); cfg_if::cfg_if! {
proc.get_object::<Resource>(handle)? if #[cfg(all(target_arch = "x86_64", target_os = "none"))] {
.validate(ResourceKind::ROOT)?; use zircon_object::dev::pci::{pio_config_read, pio_config_write};
if write { let proc = self.thread.proc();
let value = value_ptr.read()?; proc.get_object::<Resource>(handle)?
pio_config_write(bus, dev, func, offset, value, width)?; .validate(ResourceKind::ROOT)?;
} else { if write {
let value = pio_config_read(bus, dev, func, offset, width)?; let value = value_ptr.read()?;
value_ptr.write(value)?; pio_config_write(bus, dev, func, offset, value, width)?;
} else {
let value = pio_config_read(bus, dev, func, offset, width)?;
value_ptr.write(value)?;
}
Ok(())
} else {
Err(ZxError::NOT_SUPPORTED)
}
} }
Ok(())
} }
// TODO: review // TODO: review