diff --git a/pcid/src/main.rs b/pcid/src/main.rs index 0477d361a8..9f552220f4 100644 --- a/pcid/src/main.rs +++ b/pcid/src/main.rs @@ -470,12 +470,11 @@ fn handle_parsed_header(state: Arc, config: &Config, addr: PciAddress, he state: Arc::clone(&state), capabilities, }; - thread::spawn(move || { - // RFLAGS are no longer kept in the relibc clone() implementation. - unsafe { syscall::iopl(3).expect("pcid: failed to set IOPL"); } - + let _handle = thread::spawn(move || { driver_handler.handle_spawn(pcid_to_client_write, pcid_from_client_read, subdriver_args); }); + // FIXME this currently deadlocks as pcid doesn't daemonize + //state.threads.lock().unwrap().push(handle); match child.wait() { Ok(_status) => (), Err(err) => error!("pcid: failed to wait for {:?}: {}", command, err), diff --git a/pcid/src/pcie/fallback.rs b/pcid/src/pcie/fallback.rs index f9c874ee0a..63f70eeb7a 100644 --- a/pcid/src/pcie/fallback.rs +++ b/pcid/src/pcie/fallback.rs @@ -1,5 +1,6 @@ +use std::cell::Cell; use std::convert::TryFrom; -use std::sync::{Mutex, Once}; +use std::sync::Mutex; #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] use syscall::io::{Io as _, Pio}; @@ -10,25 +11,36 @@ use crate::pci::{CfgAccess, PciAddress}; pub(crate) struct Pci { lock: Mutex<()>, - iopl_once: Once, } impl Pci { pub(crate) fn new() -> Self { Self { lock: Mutex::new(()), - iopl_once: Once::new(), } } fn set_iopl() { - // make sure that pcid is not granted io port permission unless pcie memory-mapped - // configuration space is not available. - info!("PCI: couldn't find or access PCIe extended configuration, and thus falling back to PCI 3.0 io ports"); - unsafe { - syscall::iopl(3).expect("pcid: failed to set iopl to 3"); + // The IO privilege level is per-thread, so we need to do the initialization on every thread. + thread_local! { + static IOPL_ONCE: Cell = Cell::new(false); } + + IOPL_ONCE.with(|iopl_once| { + if !iopl_once.replace(true) { + // make sure that pcid is not granted io port permission unless pcie memory-mapped + // configuration space is not available. + info!( + "PCI: couldn't find or access PCIe extended configuration, \ + and thus falling back to PCI 3.0 io ports" + ); + unsafe { + syscall::iopl(3).expect("pcid: failed to set iopl to 3"); + } + } + }); } + fn address(address: PciAddress, offset: u8) -> u32 { // TODO: Find the part of pcid that uses an unaligned offset! // @@ -54,7 +66,7 @@ impl CfgAccess for Pci { unsafe fn read(&self, address: PciAddress, offset: u16) -> u32 { let _guard = self.lock.lock().unwrap(); - self.iopl_once.call_once(Self::set_iopl); + Self::set_iopl(); let offset = u8::try_from(offset).expect("offset too large for PCI 3.0 configuration space"); @@ -67,7 +79,7 @@ impl CfgAccess for Pci { unsafe fn write(&self, address: PciAddress, offset: u16, value: u32) { let _guard = self.lock.lock().unwrap(); - self.iopl_once.call_once(Self::set_iopl); + Self::set_iopl(); let offset = u8::try_from(offset).expect("offset too large for PCI 3.0 configuration space"); diff --git a/pcid/src/pcie/mod.rs b/pcid/src/pcie/mod.rs index 3efb019d93..24dbee0d12 100644 --- a/pcid/src/pcie/mod.rs +++ b/pcid/src/pcie/mod.rs @@ -141,7 +141,7 @@ impl Pcie { None } }) - .collect(); + .collect::>(); Ok(Self { lock: Mutex::new(()),