Merge pull request #226 from chyyuu/refactor-ddk-hal

Refactor ddk hal
This commit is contained in:
Yuekai Jia 2021-09-04 16:20:31 +08:00 committed by GitHub
commit de809efca2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 264 additions and 283 deletions

View File

@ -88,8 +88,7 @@ pub fn irq_handle(irq: u8) {
}
/// Add a handle to IRQ table. Return the specified irq or an allocated irq on success
#[export_name = "hal_irq_add_handle"]
pub fn irq_add_handle(irq: u8, handle: InterruptHandle) -> Option<u8> {
fn irq_add_handle(irq: u8, handle: InterruptHandle) -> Option<u8> {
info!("IRQ add handle {:#x?}", irq);
let mut table = IRQ_TABLE.lock();
// allocate a valid irq number
@ -115,8 +114,7 @@ pub fn irq_add_handle(irq: u8, handle: InterruptHandle) -> Option<u8> {
}
}
#[export_name = "hal_irq_remove_handle"]
pub fn irq_remove_handle(irq: u8) -> bool {
fn irq_remove_handle(irq: u8) -> bool {
info!("IRQ remove handle {:#x?}", irq);
let irq = irq as usize;
let mut table = IRQ_TABLE.lock();
@ -129,50 +127,6 @@ pub fn irq_remove_handle(irq: u8) -> bool {
}
}
/*
#[export_name = "hal_irq_allocate_block"]
pub fn allocate_block(irq_num: u32) -> Option<(usize, usize)> {
info!("hal_irq_allocate_block: count={:#x?}", irq_num);
let irq_num = u32::next_power_of_two(irq_num) as usize;
let mut irq_start = 0x20;
let mut irq_cur = irq_start;
let mut table = IRQ_TABLE.lock();
while irq_cur < TABLE_SIZE && irq_cur < irq_start + irq_num {
if table[irq_cur].is_none() {
irq_cur += 1;
} else {
irq_start = (irq_cur - irq_cur % irq_num) + irq_num;
irq_cur = irq_start;
}
}
for i in irq_start..irq_start + irq_num {
table[i] = Some(Box::new(|| {}));
}
info!(
"hal_irq_allocate_block: start={:#x?} num={:#x?}",
irq_start, irq_num
);
Some((irq_start, irq_num))
}
#[export_name = "hal_irq_free_block"]
pub fn free_block(irq_start: u32, irq_num: u32) {
let mut table = IRQ_TABLE.lock();
for i in irq_start..irq_start + irq_num {
table[i as usize] = None;
}
}
*/
#[export_name = "hal_irq_overwrite_handler"]
pub fn overwrite_handler(msi_id: u32, handle: Box<dyn Fn() + Send + Sync>) -> bool {
info!("IRQ overwrite handle {:#x?}", msi_id);
let mut table = IRQ_TABLE.lock();
let set = table[msi_id as usize].is_none();
table[msi_id as usize] = Some(handle);
set
}
fn breakpoint(sepc: &mut usize) {
bare_println!("Exception::Breakpoint: A breakpoint set @0x{:x} ", sepc);

View File

@ -121,8 +121,8 @@ pub fn irq_handle(irq: u8) {
}
}
#[export_name = "hal_ioapic_set_handle"]
pub fn set_handle(global_irq: u32, handle: InterruptHandle) -> Option<u8> {
#[export_name = "hal_irq_register_handler"]
pub fn register_irq_handler(global_irq: u32, handle: InterruptHandle) -> Option<u32> {
info!("set_handle irq={:#x?}", global_irq);
// if global_irq == 1 {
// irq_add_handle(global_irq as u8 + IRQ0, handle);
@ -147,12 +147,12 @@ pub fn set_handle(global_irq: u32, handle: InterruptHandle) -> Option<u8> {
global_irq, x
);
ioapic.set_irq_vector(offset, x);
x
x as u32
})
}
#[export_name = "hal_ioapic_reset_handle"]
pub fn reset_handle(global_irq: u32) -> bool {
#[export_name = "hal_irq_unregister_handler"]
pub fn unregister_irq_handler(global_irq: u32) -> bool {
info!("reset_handle");
let ioapic_info = if let Some(x) = get_ioapic(global_irq) {
x
@ -171,8 +171,7 @@ pub fn reset_handle(global_irq: u32) -> bool {
}
/// Add a handle to IRQ table. Return the specified irq or an allocated irq on success
#[export_name = "hal_irq_add_handle"]
pub fn irq_add_handle(irq: u8, handle: InterruptHandle) -> Option<u8> {
fn irq_add_handle(irq: u8, handle: InterruptHandle) -> Option<u8> {
info!("IRQ add handle {:#x?}", irq);
let mut table = IRQ_TABLE.lock();
// allocate a valid irq number
@ -196,8 +195,7 @@ pub fn irq_add_handle(irq: u8, handle: InterruptHandle) -> Option<u8> {
}
}
#[export_name = "hal_irq_remove_handle"]
pub fn irq_remove_handle(irq: u8) -> bool {
fn irq_remove_handle(irq: u8) -> bool {
// TODO: ioapic redirection entries associated with this should be reset.
info!("IRQ remove handle {:#x?}", irq);
let irq = irq as usize;
@ -211,8 +209,16 @@ pub fn irq_remove_handle(irq: u8) -> bool {
}
}
#[export_name = "hal_irq_allocate_block"]
pub fn allocate_block(irq_num: u32) -> Option<(usize, usize)> {
fn irq_overwrite_handler(irq: u8, handle: Box<dyn Fn() + Send + Sync>) -> bool {
info!("IRQ overwrite handle {:#x?}", irq);
let mut table = IRQ_TABLE.lock();
let set = table[irq as usize].is_none();
table[irq as usize] = Some(handle);
set
}
#[export_name = "hal_msi_allocate_block"]
pub fn msi_allocate_block(irq_num: u32) -> Option<(usize, usize)> {
info!("hal_irq_allocate_block: count={:#x?}", irq_num);
let irq_num = u32::next_power_of_two(irq_num) as usize;
let mut irq_start = 0x20;
@ -236,21 +242,22 @@ pub fn allocate_block(irq_num: u32) -> Option<(usize, usize)> {
Some((irq_start, irq_num))
}
#[export_name = "hal_irq_free_block"]
pub fn free_block(irq_start: u32, irq_num: u32) {
#[export_name = "hal_msi_free_block"]
pub fn msi_free_block(irq_start: u32, irq_num: u32) {
let mut table = IRQ_TABLE.lock();
for i in irq_start..irq_start + irq_num {
table[i as usize] = None;
}
}
#[export_name = "hal_irq_overwrite_handler"]
pub fn overwrite_handler(msi_id: u32, handle: Box<dyn Fn() + Send + Sync>) -> bool {
info!("IRQ overwrite handle {:#x?}", msi_id);
let mut table = IRQ_TABLE.lock();
let set = table[msi_id as usize].is_none();
table[msi_id as usize] = Some(handle);
set
#[export_name = "hal_msi_register_handler"]
pub fn msi_register_handler(
irq_start: u32,
_irq_num: u32,
msi_id: u32,
handle: Box<dyn Fn() + Send + Sync>,
) {
irq_overwrite_handler((irq_start + msi_id) as u8, handle);
}
#[export_name = "hal_irq_enable"]
@ -283,26 +290,21 @@ pub fn irq_disable(irq: u32) {
}
#[export_name = "hal_irq_configure"]
pub fn irq_configure(
global_irq: u32,
vector: u8,
dest: u8,
level_trig: bool,
active_high: bool,
) -> bool {
pub fn irq_configure(vector: u32, trig_mode: bool, polarity: bool) -> bool {
info!(
"irq_configure: irq={:#x?}, vector={:#x?}, dest={:#x?}, level_trig={:#x?}, active_high={:#x?}",
global_irq, vector, dest, level_trig, active_high
"irq_configure: vector={:#x?}, trig_mode={:#x?}, polarity={:#x?}",
vector, trig_mode, polarity
);
get_ioapic(global_irq)
let dest = super::apic_local_id();
get_ioapic(vector)
.map(|x| {
let mut ioapic = ioapic_controller(&x);
ioapic.config(
(global_irq - x.global_system_interrupt_base) as u8,
vector,
(vector - x.global_system_interrupt_base) as u8,
0,
dest,
level_trig,
active_high,
trig_mode,
polarity,
false, /* physical */
true, /* mask */
);
@ -310,8 +312,7 @@ pub fn irq_configure(
.is_some()
}
#[export_name = "hal_irq_maxinstr"]
pub fn ioapic_maxinstr(ioapic_addr: u32) -> Option<u8> {
fn ioapic_maxinstr(ioapic_addr: u32) -> Option<u8> {
let mut table = MAX_INSTR_TABLE.lock();
for (addr, v) in table.iter() {
if *addr == ioapic_addr as usize {
@ -329,7 +330,7 @@ lazy_static! {
}
#[export_name = "hal_irq_isvalid"]
pub fn irq_is_valid(irq: u32) -> bool {
pub fn is_valid_irq(irq: u32) -> bool {
trace!("irq_is_valid: irq={:#x?}", irq);
get_ioapic(irq).is_some()
}

View File

@ -315,86 +315,76 @@ pub fn timer_tick() {
pub struct InterruptManager {}
impl InterruptManager {
/// Handle IRQ.
#[linkage = "weak"]
#[export_name = "hal_irq_handle"]
pub fn handle(_irq: u8) {
unimplemented!()
}
///
#[linkage = "weak"]
#[export_name = "hal_ioapic_set_handle"]
pub fn set_ioapic_handle(_global_irq: u32, _handle: Box<dyn Fn() + Send + Sync>) -> Option<u8> {
unimplemented!()
}
/// Add an interrupt handle to an irq
#[linkage = "weak"]
#[export_name = "hal_irq_add_handle"]
pub fn add_handle(_global_irq: u8, _handle: Box<dyn Fn() + Send + Sync>) -> Option<u8> {
unimplemented!()
}
///
#[linkage = "weak"]
#[export_name = "hal_ioapic_reset_handle"]
pub fn reset_ioapic_handle(_global_irq: u32) -> bool {
unimplemented!()
}
/// Remove the interrupt handle of an irq
#[linkage = "weak"]
#[export_name = "hal_irq_remove_handle"]
pub fn remove_handle(_irq: u8) -> bool {
unimplemented!()
}
/// Allocate contiguous positions for irq
#[linkage = "weak"]
#[export_name = "hal_irq_allocate_block"]
pub fn allocate_block(_irq_num: u32) -> Option<(usize, usize)> {
unimplemented!()
}
#[linkage = "weak"]
#[export_name = "hal_irq_free_block"]
pub fn free_block(_irq_start: u32, _irq_num: u32) {
unimplemented!()
}
#[linkage = "weak"]
#[export_name = "hal_irq_overwrite_handler"]
pub fn overwrite_handler(_msi_id: u32, _handle: Box<dyn Fn() + Send + Sync>) -> bool {
unimplemented!()
}
/// Enable IRQ.
#[linkage = "weak"]
#[export_name = "hal_irq_enable"]
pub fn enable(_global_irq: u32) {
pub fn enable_irq(_vector: u32) {
unimplemented!()
}
/// Disable IRQ.
#[linkage = "weak"]
#[export_name = "hal_irq_disable"]
pub fn disable(_global_irq: u32) {
unimplemented!()
}
/// Get IO APIC maxinstr
#[linkage = "weak"]
#[export_name = "hal_irq_maxinstr"]
pub fn maxinstr(_irq: u32) -> Option<u8> {
unimplemented!()
}
#[linkage = "weak"]
#[export_name = "hal_irq_configure"]
pub fn configure(
_irq: u32,
_vector: u8,
_dest: u8,
_level_trig: bool,
_active_high: bool,
) -> bool {
pub fn disable_irq(_vector: u32) {
unimplemented!()
}
/// Is a valid IRQ number.
#[linkage = "weak"]
#[export_name = "hal_irq_isvalid"]
pub fn is_valid(_irq: u32) -> bool {
pub fn is_valid_irq(_vector: u32) -> bool {
unimplemented!()
}
/// Configure the specified interrupt vector. If it is invoked, it muust be
/// invoked prior to interrupt registration.
#[linkage = "weak"]
#[export_name = "hal_irq_configure"]
pub fn configure_irq(_vector: u32, _trig_mode: bool, _polarity: bool) -> bool {
unimplemented!()
}
/// Add an interrupt handle to an IRQ
#[linkage = "weak"]
#[export_name = "hal_irq_register_handler"]
pub fn register_irq_handler(_vector: u32, _handle: Box<dyn Fn() + Send + Sync>) -> Option<u32> {
unimplemented!()
}
/// Remove the interrupt handle to an IRQ
#[linkage = "weak"]
#[export_name = "hal_irq_unregister_handler"]
pub fn unregister_irq_handler(_vector: u32) -> bool {
unimplemented!()
}
/// Handle IRQ.
#[linkage = "weak"]
#[export_name = "hal_irq_handle"]
pub fn handle_irq(_vector: u32) {
unimplemented!()
}
/// Method used for platform allocation of blocks of MSI and MSI-X compatible
/// IRQ targets.
#[linkage = "weak"]
#[export_name = "hal_msi_allocate_block"]
pub fn msi_allocate_block(_irq_num: u32) -> Option<(usize, usize)> {
unimplemented!()
}
/// Method used to free a block of MSI IRQs previously allocated by msi_alloc_block().
/// This does not unregister IRQ handlers.
#[linkage = "weak"]
#[export_name = "hal_msi_free_block"]
pub fn msi_free_block(_irq_start: u32, _irq_num: u32) {
unimplemented!()
}
/// Register a handler function for a given msi_id within an msi_block_t. Passing a
/// NULL handler will effectively unregister a handler for a given msi_id within the
/// block.
#[linkage = "weak"]
#[export_name = "hal_msi_register_handler"]
pub fn msi_register_handler(
_irq_start: u32,
_irq_num: u32,
_msi_id: u32,
_handle: Box<dyn Fn() + Send + Sync>,
) {
unimplemented!()
}
}

View File

@ -94,7 +94,7 @@ async fn new_thread(thread: CurrentThread) {
match cx.trap_num {
0x100 => handle_syscall(&thread, &mut cx.general).await,
0x20..=0x3f => {
kernel_hal::InterruptManager::handle(cx.trap_num as u8);
kernel_hal::InterruptManager::handle_irq(cx.trap_num as u32);
if cx.trap_num == 0x20 {
kernel_hal::yield_now().await;
}
@ -129,7 +129,7 @@ async fn new_thread(thread: CurrentThread) {
match trap_num {
//Irq
0 | 4 | 5 | 8 | 9 => {
kernel_hal::InterruptManager::handle(trap_num as u8);
kernel_hal::InterruptManager::handle_irq(trap_num as u32);
//Timer
if trap_num == 4 || trap_num == 5 {
@ -144,7 +144,7 @@ async fn new_thread(thread: CurrentThread) {
kernel_hal::yield_now().await;
}
//kernel_hal::InterruptManager::handle(trap_num as u8);
//kernel_hal::InterruptManager::handle_irq(trap_num as u32);
}
_ => panic!(
"not supported pid: {} interrupt {} from user mode. {:#x?}",

View File

@ -53,3 +53,7 @@
/libc-test/src/functional/popen.exe
/libc-test/src/regression/statvfs-static.exe
/libc-test/src/regression/sem_close-unmap-static.exe
/libc-test/src/regression/execle-env-static.exe
/libc-test/src/regression/execle-env.exe
/libc-test/src/functional/pthread_tsd-static.exe
/libc-test/src/functional/tls_init-static.exe

View File

@ -217,7 +217,7 @@ async fn new_thread(thread: CurrentThread) {
match trap_num {
0x100 => handle_syscall(&thread).await,
0x20..=0x3f => {
kernel_hal::InterruptManager::handle(trap_num as u8);
kernel_hal::InterruptManager::handle_irq(trap_num as u32);
if trap_num == 0x20 {
EXCEPTIONS_TIMER.add(1);
kernel_hal::yield_now().await;

View File

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

View File

@ -25,14 +25,14 @@ impl InterruptTrait for EventInterrupt {
fn mask(&self) {
let inner = self.inner.lock();
if inner.register {
InterruptManager::disable(self.vector as u32);
InterruptManager::disable_irq(self.vector as u32);
}
}
fn unmask(&self) {
let inner = self.inner.lock();
if inner.register {
InterruptManager::enable(self.vector as u32);
InterruptManager::enable_irq(self.vector as u32);
}
}
@ -41,7 +41,7 @@ impl InterruptTrait for EventInterrupt {
if inner.register {
return Err(ZxError::ALREADY_BOUND);
}
if InterruptManager::set_ioapic_handle(self.vector, handle).is_some() {
if InterruptManager::register_irq_handler(self.vector, handle).is_some() {
inner.register = true;
Ok(())
} else {
@ -54,7 +54,7 @@ impl InterruptTrait for EventInterrupt {
if !inner.register {
return Ok(());
}
if InterruptManager::reset_ioapic_handle(self.vector) {
if InterruptManager::unregister_irq_handler(self.vector) {
inner.register = false;
Ok(())
} else {

View File

@ -2,7 +2,7 @@ use {
self::event_interrupt::*,
self::pci_interrupt::*,
self::virtual_interrupt::*,
super::IPciNode,
crate::dev::pci::IPciNode,
crate::object::*,
crate::signal::*,
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 {
device: Arc<dyn IPciNode>,

View File

@ -1,11 +1,10 @@
//! Objects for Device Drivers.
use super::*;
mod bti;
mod interrupt;
mod iommu;
mod pci;
pub mod pci;
mod pmt;
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::config::*;
use super::*;
use super::nodes::{
IPciNode, PciNodeType, PciRoot, PcieBarInfo, PcieIrqMode, PcieIrqModeCaps,
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::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::marker::{Send, Sync};
use lazy_static::*;

View File

@ -1,6 +1,6 @@
use super::super::{ZxError, ZxResult};
use super::config::PciConfig;
use super::nodes::PcieDeviceType;
use super::{config::PciConfig, nodes::PcieDeviceType};
use crate::{ZxError, ZxResult};
use alloc::boxed::Box;
use core::convert::TryFrom;
use kernel_hal::InterruptManager;
@ -47,7 +47,7 @@ impl PciMsiBlock {
return Err(ZxError::INVALID_ARGS);
}
let (start, size) =
InterruptManager::allocate_block(irq_num).ok_or(ZxError::NO_RESOURCES)?;
InterruptManager::msi_allocate_block(irq_num).ok_or(ZxError::NO_RESOURCES)?;
Ok(PciMsiBlock {
target_addr: (0xFEE0_0000 | 0x08) & !0x4,
target_data: start as u32,
@ -57,12 +57,12 @@ impl PciMsiBlock {
})
}
pub fn free(&self) {
InterruptManager::free_block(self.base_irq, self.num_irq)
InterruptManager::msi_free_block(self.base_irq, self.num_irq)
}
pub fn register_handler(&self, msi_id: u32, handle: Box<dyn Fn() + Send + Sync>) {
assert!(self.allocated);
assert!(msi_id < self.num_irq);
InterruptManager::overwrite_handler(self.base_irq + msi_id, handle);
InterruptManager::msi_register_handler(self.base_irq, self.num_irq, msi_id, handle);
}
}

View File

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

View File

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

View File

@ -1,12 +1,22 @@
#![allow(dead_code)]
#![allow(missing_docs)]
use super::{caps::*, config::*, *};
use crate::vm::PAGE_SIZE;
use alloc::{boxed::Box, sync::*, vec::Vec};
use super::caps::{
PciCapAdvFeatures, PciCapPcie, PciCapability, PciCapabilityMsi, PciCapabilityStd, PciMsiBlock,
};
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 numeric_enum_macro::*;
use numeric_enum_macro::numeric_enum;
use region_alloc::RegionAllocator;
use spin::*;
use spin::{Mutex, MutexGuard};
numeric_enum! {
#[repr(u8)]
@ -182,13 +192,13 @@ impl SharedLegacyIrqHandler {
/// Create a new SharedLegacyIrqHandler.
pub fn create(irq_id: u32) -> Option<Arc<SharedLegacyIrqHandler>> {
info!("SharedLegacyIrqHandler created for {:#x?}", irq_id);
InterruptManager::disable(irq_id);
InterruptManager::disable_irq(irq_id);
let handler = Arc::new(SharedLegacyIrqHandler {
irq_id,
device_handler: Mutex::new(Vec::new()),
});
let handler_copy = handler.clone();
if InterruptManager::set_ioapic_handle(irq_id, Box::new(move || handler_copy.handle()))
if InterruptManager::register_irq_handler(irq_id, Box::new(move || handler_copy.handle()))
.is_some()
{
Some(handler)
@ -201,7 +211,7 @@ impl SharedLegacyIrqHandler {
pub fn handle(&self) {
let device_handler = self.device_handler.lock();
if device_handler.is_empty() {
InterruptManager::disable(self.irq_id);
InterruptManager::disable_irq(self.irq_id);
return;
}
for dev in device_handler.iter() {
@ -250,7 +260,7 @@ impl SharedLegacyIrqHandler {
let is_first = device_handler.is_empty();
device_handler.push(device);
if is_first {
InterruptManager::enable(self.irq_id);
InterruptManager::enable_irq(self.irq_id);
}
}
pub fn remove_device(&self, device: Arc<PcieDevice>) {
@ -262,7 +272,7 @@ impl SharedLegacyIrqHandler {
let mut device_handler = self.device_handler.lock();
device_handler.retain(|h| Arc::ptr_eq(h, &device));
if device_handler.is_empty() {
InterruptManager::disable(self.irq_id);
InterruptManager::disable_irq(self.irq_id);
}
}
}
@ -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 initially_masked = if msi.has_pvm {
self.cfg
@ -1134,7 +1144,7 @@ impl PcieDevice {
inner.irq.legacy.shared_handler.add_device(inner.arc_self());
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),
_ => Err(ZxError::INVALID_ARGS),
}

View File

@ -3,6 +3,9 @@
//!
//! reference: zircon/system/public/zircon/syscalls/pci.h
use super::constants::*;
use crate::{ZxError, ZxResult};
#[repr(transparent)]
#[derive(Clone, Copy)]
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
+ core::mem::size_of::<PciInitArgsHeader>();
use super::*;
use kernel_hal::InterruptManager;
impl PciInitArgsHeader {
@ -50,41 +52,21 @@ impl PciInitArgsHeader {
for i in 0..self.num_irqs as usize {
let irq = &mut self.irqs[i];
let global_irq = irq.global_irq;
if !is_valid_interrupt(global_irq) {
if !InterruptManager::is_valid_irq(global_irq) {
irq.global_irq = PCI_NO_IRQ_MAPPING;
self.dev_pin_to_global_irq.remove_irq(global_irq);
} else {
irq_configure(
global_irq,
irq.level_triggered, /* Trigger mode */
irq.active_high, /* Polarity */
)?;
} else if !InterruptManager::configure_irq(
global_irq,
irq.level_triggered, /* Trigger mode */
irq.active_high, /* Polarity */
) {
return Err(ZxError::INVALID_ARGS);
}
}
Ok(())
}
}
fn is_valid_interrupt(irq: u32) -> bool {
InterruptManager::is_valid(irq)
}
fn irq_configure(irq: u32, level_trigger: bool, active_high: bool) -> ZxResult {
// In fuchsia source code, 'BSP' stands for bootstrap processor
let dest = kernel_hal::apic_local_id();
if InterruptManager::configure(
irq,
0, // vector
dest,
level_trigger,
active_high,
) {
Ok(())
} else {
Err(ZxError::INVALID_ARGS)
}
}
impl PciIrqSwizzleLut {
pub(super) fn swizzle(&self, dev_id: usize, func_id: usize, pin: usize) -> ZxResult<usize> {
if dev_id >= PCI_MAX_DEVICES_PER_BUS

View File

@ -1,12 +1,6 @@
#![allow(missing_docs)]
use super::super::*;
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;
use crate::{ZxError, ZxResult};
/// 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 {
@ -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
}
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> {
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(
bus: u8,
dev: u8,
@ -41,21 +71,3 @@ pub fn pio_config_write(
) -> ZxResult {
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" }
kernel-hal = { path = "../kernel-hal" }
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(
&self,
resource: HandleValue,
@ -142,10 +143,16 @@ impl Syscall<'_> {
let proc = self.thread.proc();
proc.get_object::<Resource>(resource)?
.validate(ResourceKind::ROOT)?;
let (acpi_rsdp, smbios) = kernel_hal::pc_firmware_tables();
acpi_rsdp_ptr.write(acpi_rsdp)?;
smbios_ptr.write(smbios)?;
Ok(())
cfg_if::cfg_if! {
if #[cfg(all(target_arch = "x86_64", target_os = "none"))] {
let (acpi_rsdp, smbios) = kernel_hal::pc_firmware_tables();
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.

View File

@ -322,7 +322,6 @@ impl Syscall<'_> {
Sys::PCI_ADD_SUBTRACT_IO_RANGE => {
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(
a0 as _,
a1 as _,

View File

@ -1,7 +1,14 @@
use super::*;
use alloc::sync::Arc;
use core::convert::TryFrom;
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},
};
@ -33,8 +40,7 @@ impl Syscall<'_> {
}
}
#[allow(clippy::too_many_arguments)]
#[cfg(target_arch = "x86_64")]
#[allow(clippy::too_many_arguments, unused_variables, unused_mut)]
pub fn sys_pci_cfg_pio_rw(
&self,
handle: HandleValue,
@ -50,17 +56,24 @@ impl Syscall<'_> {
"pci.cfg_pio_rw: handle={:#x}, addr={:x}:{:x}:{:x}, offset={:#x}, width={:#x}, write={:#}",
handle, bus, dev, func, offset, width, write
);
let proc = self.thread.proc();
proc.get_object::<Resource>(handle)?
.validate(ResourceKind::ROOT)?;
if write {
let value = value_ptr.read()?;
pio_config_write(bus, dev, func, offset, value, width)?;
} else {
let value = pio_config_read(bus, dev, func, offset, width)?;
value_ptr.write(value)?;
cfg_if::cfg_if! {
if #[cfg(all(target_arch = "x86_64", target_os = "none"))] {
use zircon_object::dev::pci::{pio_config_read, pio_config_write};
let proc = self.thread.proc();
proc.get_object::<Resource>(handle)?
.validate(ResourceKind::ROOT)?;
if write {
let value = value_ptr.read()?;
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