refactor pci stage 3

This commit is contained in:
Runji Wang 2020-06-11 01:39:10 +08:00
parent 1cad730bde
commit 8c70da4ab4
7 changed files with 52 additions and 92 deletions

View File

@ -345,10 +345,6 @@ impl InterruptManager {
} }
} }
pub fn irq_handle(irq: u8) {
InterruptManager::handle(irq)
}
/// Get platform specific information. /// Get platform specific information.
#[linkage = "weak"] #[linkage = "weak"]
#[export_name = "hal_vdso_constants"] #[export_name = "hal_vdso_constants"]

View File

@ -203,7 +203,7 @@ fn spawn(thread: Arc<Thread>) {
match cx.trap_num { match cx.trap_num {
0x100 => exit = handle_syscall(&thread, &mut cx.general).await, 0x100 => exit = handle_syscall(&thread, &mut cx.general).await,
0x20..=0x3f => { 0x20..=0x3f => {
kernel_hal::irq_handle(cx.trap_num as u8); kernel_hal::InterruptManager::handle(cx.trap_num as u8);
if cx.trap_num == 0x20 { if cx.trap_num == 0x20 {
EXCEPTIONS_TIMER.add(1); EXCEPTIONS_TIMER.add(1);
kernel_hal::yield_now().await; kernel_hal::yield_now().await;

View File

@ -39,11 +39,12 @@ pub struct PciMsiBlock {
} }
impl PciMsiBlock { impl PciMsiBlock {
pub fn allocate_msi_block(irq_num: u32) -> ZxResult<Self> { pub fn allocate(irq_num: u32) -> ZxResult<Self> {
if irq_num == 0 || irq_num > 32 { if irq_num == 0 || irq_num > 32 {
return Err(ZxError::INVALID_ARGS); return Err(ZxError::INVALID_ARGS);
} }
if let Some((start, size)) = InterruptManager::allocate_block(irq_num) { let (start, size) =
InterruptManager::allocate_block(irq_num).ok_or(ZxError::NO_RESOURCES)?;
Ok(PciMsiBlock { Ok(PciMsiBlock {
target_addr: (0xFEE0_0000 | 0x08) & !0x4, target_addr: (0xFEE0_0000 | 0x08) & !0x4,
target_data: start as u32, target_data: start as u32,
@ -51,11 +52,8 @@ impl PciMsiBlock {
num_irq: size as u32, num_irq: size as u32,
allocated: true, allocated: true,
}) })
} else {
Err(ZxError::NO_RESOURCES)
} }
} pub fn free(&self) {
pub fn free_msi_block(&self) {
InterruptManager::free_block(self.base_irq, self.num_irq) InterruptManager::free_block(self.base_irq, self.num_irq)
} }
pub fn register_handler(&self, msi_id: u32, handle: Box<dyn Fn() + Send + Sync>) { pub fn register_handler(&self, msi_id: u32, handle: Box<dyn Fn() + Send + Sync>) {

View File

@ -73,19 +73,6 @@ pub struct MappedEcamRegion {
pub vaddr: u64, pub vaddr: u64,
} }
use numeric_enum_macro::*;
numeric_enum! {
#[repr(u32)]
#[derive(Clone, Debug, PartialEq)]
pub enum PcieIrqMode {
Disabled = 0,
Legacy = 1,
Msi = 2,
MsiX = 3,
Count = 4,
}
}
pub const PCI_INIT_ARG_MAX_SIZE: usize = core::mem::size_of::<PciInitArgsAddrWindows>() pub const PCI_INIT_ARG_MAX_SIZE: usize = core::mem::size_of::<PciInitArgsAddrWindows>()
* PCI_INIT_ARG_MAX_ECAM_WINDOWS * PCI_INIT_ARG_MAX_ECAM_WINDOWS
+ core::mem::size_of::<PciInitArgsHeader>(); + core::mem::size_of::<PciInitArgsHeader>();
@ -105,13 +92,14 @@ use super::*;
use alloc::sync::*; use alloc::sync::*;
use kernel_hal::InterruptManager; use kernel_hal::InterruptManager;
pub fn pci_configure_interrupt(arg_header: &mut PciInitArgsHeader) -> ZxResult { impl PciInitArgsHeader {
for i in 0..arg_header.num_irqs as usize { pub fn configure_interrupt(&mut self) -> ZxResult {
let irq = &mut arg_header.irqs[i]; for i in 0..self.num_irqs as usize {
let irq = &mut self.irqs[i];
let global_irq = irq.global_irq; let global_irq = irq.global_irq;
if !is_valid_interrupt(global_irq) { if !is_valid_interrupt(global_irq) {
irq.global_irq = PCI_NO_IRQ_MAPPING; irq.global_irq = PCI_NO_IRQ_MAPPING;
pci_irq_swizzle_lut_remove_irq(&mut arg_header.dev_pin_to_global_irq, global_irq); self.dev_pin_to_global_irq.remove_irq(global_irq);
} else { } else {
irq_configure( irq_configure(
global_irq, global_irq,
@ -121,6 +109,7 @@ pub fn pci_configure_interrupt(arg_header: &mut PciInitArgsHeader) -> ZxResult {
} }
} }
Ok(()) Ok(())
}
} }
fn is_valid_interrupt(irq: u32) -> bool { fn is_valid_interrupt(irq: u32) -> bool {
@ -158,10 +147,9 @@ impl PciIrqSwizzleLut {
Ok(irq as usize) Ok(irq as usize)
} }
} }
}
fn pci_irq_swizzle_lut_remove_irq(lut: &mut PciIrqSwizzleLut, irq: u32) { fn remove_irq(&mut self, irq: u32) {
for dev in lut.0.iter_mut() { for dev in self.0.iter_mut() {
for func in dev.iter_mut() { for func in dev.iter_mut() {
for pin in func.iter_mut() { for pin in func.iter_mut() {
if *pin == irq { if *pin == irq {
@ -170,4 +158,5 @@ fn pci_irq_swizzle_lut_remove_irq(lut: &mut PciIrqSwizzleLut, irq: u32) {
} }
} }
} }
}
} }

View File

@ -2,7 +2,7 @@
use super::{caps::*, config::*, *}; use super::{caps::*, config::*, *};
use crate::vm::PAGE_SIZE; use crate::vm::PAGE_SIZE;
use alloc::{boxed::Box, sync::*, vec, vec::Vec}; use alloc::{boxed::Box, sync::*, vec::Vec};
use core::convert::TryFrom; use core::convert::TryFrom;
use kernel_hal::InterruptManager; use kernel_hal::InterruptManager;
use numeric_enum_macro::*; use numeric_enum_macro::*;
@ -28,13 +28,13 @@ numeric_enum! {
} }
pub struct PcieUpstream { pub struct PcieUpstream {
pub managed_bus_id: usize, managed_bus_id: usize,
pub inner: Mutex<PcieUpstreamInner>, inner: Mutex<PcieUpstreamInner>,
} }
pub struct PcieUpstreamInner { struct PcieUpstreamInner {
pub weak_super: Weak<dyn IPciNode>, weak_super: Weak<dyn IPciNode>,
pub downstream: Vec<Option<Arc<dyn IPciNode>>>, downstream: [Option<Arc<dyn IPciNode>>; PCI_MAX_FUNCTIONS_PER_BUS],
} }
impl PcieUpstream { impl PcieUpstream {
@ -43,10 +43,11 @@ impl PcieUpstream {
managed_bus_id, managed_bus_id,
inner: Mutex::new(PcieUpstreamInner { inner: Mutex::new(PcieUpstreamInner {
weak_super: Weak::<PciRoot>::new(), weak_super: Weak::<PciRoot>::new(),
downstream: vec![None; PCI_MAX_FUNCTIONS_PER_BUS], downstream: [None; PCI_MAX_FUNCTIONS_PER_BUS],
}), }),
}) })
} }
pub fn scan_downstream(&self, driver: &PCIeBusDriver) { pub fn scan_downstream(&self, driver: &PCIeBusDriver) {
for dev_id in 0..PCI_MAX_DEVICES_PER_BUS { for dev_id in 0..PCI_MAX_DEVICES_PER_BUS {
for func_id in 0..PCI_MAX_FUNCTIONS_PER_DEVICE { for func_id in 0..PCI_MAX_FUNCTIONS_PER_DEVICE {
@ -616,7 +617,7 @@ impl PcieDevice {
} }
let upstream = upstream.upgrade(); let upstream = upstream.upgrade();
if let Some(up_ptr) = upstream { if let Some(up_ptr) = upstream {
if let Some(up) = up_ptr.to_root() { if let Some(up) = up_ptr.as_root() {
return up.swizzle(dev_id, func_id, pin as usize); return up.swizzle(dev_id, func_id, pin as usize);
} }
} }
@ -927,7 +928,7 @@ impl PcieDevice {
} else { } else {
false false
}; };
match PciMsiBlock::allocate_msi_block(irq) { match PciMsiBlock::allocate(irq) {
Ok(block) => *msi.irq_block.lock() = block, Ok(block) => *msi.irq_block.lock() = block,
Err(ex) => { Err(ex) => {
self.leave_msi_irq_mode(inner); self.leave_msi_irq_mode(inner);
@ -962,7 +963,7 @@ impl PcieDevice {
for i in 0..block.num_irq { for i in 0..block.num_irq {
block.register_handler(i, Box::new(|| {})); block.register_handler(i, Box::new(|| {}));
} }
block.free_msi_block(); block.free();
} }
} }
self.reset_irq_bookkeeping(inner); self.reset_irq_bookkeeping(inner);
@ -1159,9 +1160,9 @@ pub trait IPciNode: Send + Sync {
fn node_type(&self) -> PciNodeType; fn node_type(&self) -> PciNodeType;
fn device(&self) -> Arc<PcieDevice>; fn device(&self) -> Arc<PcieDevice>;
fn as_upstream(&self) -> Option<Arc<PcieUpstream>>; fn as_upstream(&self) -> Option<Arc<PcieUpstream>>;
fn to_root(&self) -> Option<&PciRoot>; fn as_root(&self) -> Option<&PciRoot> {
fn to_device(&mut self) -> Option<&mut PciDeviceNode>; None
fn to_bridge(&mut self) -> Option<&mut PciBridge>; }
fn allocate_bars(&self) -> ZxResult { fn allocate_bars(&self) -> ZxResult {
unimplemented!("IPciNode.allocate_bars") unimplemented!("IPciNode.allocate_bars")
} }
@ -1237,15 +1238,9 @@ impl IPciNode for PciRoot {
fn as_upstream(&self) -> Option<Arc<PcieUpstream>> { fn as_upstream(&self) -> Option<Arc<PcieUpstream>> {
Some(self.base_upstream.clone()) Some(self.base_upstream.clone())
} }
fn to_root(&self) -> Option<&PciRoot> { fn as_root(&self) -> Option<&PciRoot> {
Some(self) Some(self)
} }
fn to_device(&mut self) -> Option<&mut PciDeviceNode> {
None
}
fn to_bridge(&mut self) -> Option<&mut PciBridge> {
None
}
fn allocate_bars(&self) -> ZxResult { fn allocate_bars(&self) -> ZxResult {
unimplemented!(); unimplemented!();
} }
@ -1298,15 +1293,6 @@ impl IPciNode for PciDeviceNode {
fn as_upstream(&self) -> Option<Arc<PcieUpstream>> { fn as_upstream(&self) -> Option<Arc<PcieUpstream>> {
None None
} }
fn to_root(&self) -> Option<&PciRoot> {
None
}
fn to_device(&mut self) -> Option<&mut PciDeviceNode> {
Some(self)
}
fn to_bridge(&mut self) -> Option<&mut PciBridge> {
None
}
fn allocate_bars(&self) -> ZxResult { fn allocate_bars(&self) -> ZxResult {
self.base_device.allocate_bars() self.base_device.allocate_bars()
} }
@ -1421,15 +1407,6 @@ impl IPciNode for PciBridge {
fn as_upstream(&self) -> Option<Arc<PcieUpstream>> { fn as_upstream(&self) -> Option<Arc<PcieUpstream>> {
Some(self.base_upstream.clone()) Some(self.base_upstream.clone())
} }
fn to_root(&self) -> Option<&PciRoot> {
None
}
fn to_device(&mut self) -> Option<&mut PciDeviceNode> {
None
}
fn to_bridge(&mut self) -> Option<&mut PciBridge> {
Some(self)
}
fn pf_mmio_regions(&self) -> Arc<Mutex<RegionAllocator>> { fn pf_mmio_regions(&self) -> Arc<Mutex<RegionAllocator>> {
self.pf_mmio.clone() self.pf_mmio.clone()
} }

View File

@ -10,6 +10,7 @@
#![feature(ptr_offset_from)] #![feature(ptr_offset_from)]
#![feature(range_is_empty)] #![feature(range_is_empty)]
#![feature(new_uninit)] #![feature(new_uninit)]
#![feature(const_in_array_repeat_expressions)]
extern crate alloc; extern crate alloc;

View File

@ -87,8 +87,7 @@ impl Syscall<'_> {
} }
let mut addr_windows = UserInPtr::<PciInitArgsAddrWindows>::from(init_buf + HEADER_SIZE) let mut addr_windows = UserInPtr::<PciInitArgsAddrWindows>::from(init_buf + HEADER_SIZE)
.read_array(arg_header.addr_window_count as usize)?; .read_array(arg_header.addr_window_count as usize)?;
// Configure interrupts arg_header.configure_interrupt()?;
pci_configure_interrupt(&mut arg_header)?;
if arg_header.addr_window_count != 1 { if arg_header.addr_window_count != 1 {
return Err(ZxError::INVALID_ARGS); // for non DesignWare Controller return Err(ZxError::INVALID_ARGS); // for non DesignWare Controller
} }