Only set iopl for helper threads when actually necessary

This commit is contained in:
bjorn3
2024-01-20 14:17:51 +01:00
parent 3cbfbf6442
commit cb7dc2abd2
3 changed files with 26 additions and 15 deletions
+3 -4
View File
@@ -470,12 +470,11 @@ fn handle_parsed_header(state: Arc<State>, 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),
+22 -10
View File
@@ -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<bool> = 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");
+1 -1
View File
@@ -141,7 +141,7 @@ impl Pcie {
None
}
})
.collect();
.collect::<Vec<_>>();
Ok(Self {
lock: Mutex::new(()),