Skip to content

Commit e3023e9

Browse files
committed
Generify worker threads on x86
Rather than spawning a new worker thread every time some functionality needs it, which results in it's own Message type, create something generic that can be used in one thread. Signed-off-by: Jake Correnti <[email protected]>
1 parent 73352c9 commit e3023e9

File tree

10 files changed

+88
-74
lines changed

10 files changed

+88
-74
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/devices/src/legacy/ioapic.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use kvm_bindings::{
55
use kvm_ioctls::{Error, VmFd};
66

77
use utils::eventfd::EventFd;
8+
use utils::worker_message::WorkerMessage;
89

910
use crate::bus::BusDevice;
1011
use crate::legacy::irqchip::IrqChipT;
@@ -67,12 +68,6 @@ const IOAPIC_TRIGGER_EDGE: u64 = 0;
6768
/// 7:0 Interrupt Vector (INTVEC) (RW)
6869
type RedirectionTableEntry = u64;
6970

70-
#[derive(Debug)]
71-
pub enum IrqWorkerMessage {
72-
GsiRoute(Vec<kvm_irq_routing_entry>),
73-
IrqLine(u32, bool),
74-
}
75-
7671
#[derive(Debug, Default)]
7772
pub struct IoApicEntryInfo {
7873
masked: u8,
@@ -101,14 +96,14 @@ pub struct IoApic {
10196
version: u8,
10297
irq_eoi: [i32; IOAPIC_NUM_PINS],
10398
irq_routes: Vec<kvm_irq_routing_entry>,
104-
irq_sender: crossbeam_channel::Sender<(IrqWorkerMessage, EventFd)>,
99+
irq_sender: crossbeam_channel::Sender<(WorkerMessage, EventFd)>,
105100
event_fd: EventFd,
106101
}
107102

108103
impl IoApic {
109104
pub fn new(
110105
vm: &VmFd,
111-
_irq_sender: crossbeam_channel::Sender<(IrqWorkerMessage, EventFd)>,
106+
_irq_sender: crossbeam_channel::Sender<(WorkerMessage, EventFd)>,
112107
) -> Result<Self, Error> {
113108
let mut cap = kvm_enable_cap {
114109
cap: KVM_CAP_SPLIT_IRQCHIP,
@@ -180,7 +175,7 @@ impl IoApic {
180175
}
181176
}
182177

183-
fn send_irq_worker_message(&self, msg: IrqWorkerMessage) {
178+
fn send_irq_worker_message(&self, msg: WorkerMessage) {
184179
self.irq_sender
185180
.send((msg, self.event_fd.try_clone().unwrap()))
186181
.unwrap();
@@ -254,7 +249,7 @@ impl IoApic {
254249
}
255250
}
256251

257-
self.send_irq_worker_message(IrqWorkerMessage::GsiRoute(self.irq_routes.clone()));
252+
self.send_irq_worker_message(WorkerMessage::GsiRoute(self.irq_routes.clone()));
258253
}
259254

260255
fn service(&mut self) {
@@ -279,10 +274,10 @@ impl IoApic {
279274
}
280275

281276
if info.trig_mode as u64 == IOAPIC_TRIGGER_EDGE {
282-
self.send_irq_worker_message(IrqWorkerMessage::IrqLine(i as u32, true));
283-
self.send_irq_worker_message(IrqWorkerMessage::IrqLine(i as u32, false));
277+
self.send_irq_worker_message(WorkerMessage::IrqLine(i as u32, true));
278+
self.send_irq_worker_message(WorkerMessage::IrqLine(i as u32, false));
284279
} else {
285-
self.send_irq_worker_message(IrqWorkerMessage::IrqLine(i as u32, true));
280+
self.send_irq_worker_message(WorkerMessage::IrqLine(i as u32, true));
286281
}
287282
}
288283
}

src/devices/src/legacy/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub use self::hvfgicv3::HvfGicV3;
4242
pub use self::i8042::Error as I8042DeviceError;
4343
pub use self::i8042::I8042Device;
4444
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
45-
pub use self::ioapic::{IoApic, IrqWorkerMessage};
45+
pub use self::ioapic::IoApic;
4646
pub use self::irqchip::{IrqChip, IrqChipDevice, IrqChipT};
4747
#[cfg(all(target_os = "linux", target_arch = "aarch64"))]
4848
pub use self::kvmgicv3::KvmGicV3;

src/libkrun/src/lib.rs

Lines changed: 5 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ use std::sync::atomic::{AtomicI32, Ordering};
2222
use std::sync::LazyLock;
2323
use std::sync::Mutex;
2424

25-
#[cfg(any(target_os = "macos", feature = "tee"))]
2625
use crossbeam_channel::unbounded;
2726
#[cfg(feature = "blk")]
2827
use devices::virtio::block::ImageType;
@@ -1510,29 +1509,29 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 {
15101509
#[cfg(target_os = "macos")]
15111510
let (sender, receiver) = unbounded();
15121511

1513-
#[cfg(target_arch = "x86_64")]
1514-
let (irq_sender, irq_receiver) = crossbeam_channel::unbounded();
15151512
#[cfg(feature = "tee")]
15161513
let (pm_sender, pm_receiver) = unbounded();
15171514
#[cfg(feature = "tee")]
15181515
let pm_efd =
15191516
EventFd::new(EFD_SEMAPHORE).expect("unable to create TEE memory properties eventfd");
1517+
#[cfg(target_arch = "x86_64")]
1518+
let (sender, receiver) = unbounded();
15201519

15211520
let _vmm = match vmm::builder::build_microvm(
15221521
&ctx_cfg.vmr,
15231522
&mut event_manager,
15241523
ctx_cfg.shutdown_efd,
15251524
#[cfg(target_os = "macos")]
15261525
sender,
1527-
#[cfg(target_arch = "x86_64")]
1528-
irq_sender,
15291526
#[cfg(feature = "tee")]
15301527
(
15311528
pm_sender,
15321529
pm_efd
15331530
.try_clone()
15341531
.expect("unable to clone TEE memory properties eventfd"),
15351532
),
1533+
#[cfg(target_arch = "x86_64")]
1534+
sender,
15361535
) {
15371536
Ok(vmm) => vmm,
15381537
Err(e) => {
@@ -1544,9 +1543,6 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 {
15441543
#[cfg(any(target_os = "macos", feature = "tee"))]
15451544
let mapper_vmm = _vmm.clone();
15461545

1547-
#[cfg(target_arch = "x86_64")]
1548-
let irq_vmm = _vmm.clone();
1549-
15501546
#[cfg(target_os = "macos")]
15511547
if ctx_cfg.gpu_virgl_flags.is_some() {
15521548
std::thread::Builder::new()
@@ -1569,50 +1565,7 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 {
15691565

15701566
#[cfg(target_arch = "x86_64")]
15711567
if ctx_cfg.vmr.split_irqchip {
1572-
std::thread::Builder::new()
1573-
.name("irq worker".into())
1574-
.spawn(move || loop {
1575-
match irq_receiver.recv() {
1576-
Err(e) => error!("Error in receiver: {:?}", e),
1577-
Ok((message, evt_fd)) => match message {
1578-
devices::legacy::IrqWorkerMessage::GsiRoute(entries) => {
1579-
let mut irq_routing = utils::sized_vec::vec_with_array_field::<
1580-
kvm_bindings::kvm_irq_routing,
1581-
kvm_bindings::kvm_irq_routing_entry,
1582-
>(entries.len());
1583-
irq_routing[0].nr = entries.len() as u32;
1584-
irq_routing[0].flags = 0;
1585-
1586-
unsafe {
1587-
let entries_slice: &mut [kvm_bindings::kvm_irq_routing_entry] =
1588-
irq_routing[0].entries.as_mut_slice(entries.len());
1589-
entries_slice.copy_from_slice(&entries);
1590-
}
1591-
1592-
irq_vmm
1593-
.lock()
1594-
.unwrap()
1595-
.kvm_vm()
1596-
.fd()
1597-
.set_gsi_routing(&irq_routing[0])
1598-
.unwrap();
1599-
1600-
evt_fd.write(1).unwrap();
1601-
}
1602-
devices::legacy::IrqWorkerMessage::IrqLine(irq, active) => {
1603-
irq_vmm
1604-
.lock()
1605-
.unwrap()
1606-
.kvm_vm()
1607-
.fd()
1608-
.set_irq_line(irq, active)
1609-
.unwrap();
1610-
evt_fd.write(1).unwrap();
1611-
}
1612-
},
1613-
}
1614-
})
1615-
.unwrap();
1568+
vmm::worker::start_worker_thread(_vmm.clone(), receiver.clone()).unwrap();
16161569
}
16171570

16181571
#[cfg(feature = "tee")]

src/utils/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ env_logger = "0.9.0"
1010
libc = ">=0.2.85"
1111
log = "0.4.0"
1212
vmm-sys-util = "0.12.1"
13+
14+
[target.'cfg(target_os = "linux")'.dependencies]
15+
kvm-bindings = { version = ">=0.10", features = ["fam-wrappers"] }

src/utils/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ pub mod sized_vec;
2323
pub mod sm;
2424
pub mod syscall;
2525
pub mod time;
26+
pub mod worker_message;

src/utils/src/worker_message.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#[derive(Debug)]
2+
pub enum WorkerMessage {
3+
#[cfg(target_arch = "x86_64")]
4+
GsiRoute(Vec<kvm_bindings::kvm_irq_routing_entry>),
5+
#[cfg(target_arch = "x86_64")]
6+
IrqLine(u32, bool),
7+
}

src/vmm/src/builder.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@
55
66
#[cfg(target_os = "macos")]
77
use crossbeam_channel::unbounded;
8-
9-
#[cfg(any(target_os = "macos", feature = "tee"))]
108
use crossbeam_channel::Sender;
11-
129
use kernel::cmdline::Cmdline;
1310
#[cfg(target_os = "macos")]
1411
use std::collections::HashMap;
@@ -82,6 +79,7 @@ use linux_loader::loader::{self, KernelLoader};
8279
use nix::unistd::isatty;
8380
use polly::event_manager::{Error as EventManagerError, EventManager};
8481
use utils::eventfd::EventFd;
82+
use utils::worker_message::WorkerMessage;
8583
#[cfg(all(target_arch = "x86_64", not(feature = "efi"), not(feature = "tee")))]
8684
use vm_memory::mmap::MmapRegion;
8785
#[cfg(not(feature = "tee"))]
@@ -516,11 +514,8 @@ pub fn build_microvm(
516514
event_manager: &mut EventManager,
517515
_shutdown_efd: Option<EventFd>,
518516
#[cfg(target_os = "macos")] _map_sender: Sender<MemoryMapping>,
519-
#[cfg(target_arch = "x86_64")] irq_sender: crossbeam_channel::Sender<(
520-
devices::legacy::IrqWorkerMessage,
521-
EventFd,
522-
)>,
523517
#[cfg(feature = "tee")] pm_sender: (Sender<MemoryProperties>, EventFd),
518+
#[cfg(target_arch = "x86_64")] _sender: Sender<(WorkerMessage, EventFd)>,
524519
) -> std::result::Result<Arc<Mutex<Vmm>>, StartMicrovmError> {
525520
let payload = choose_payload(vm_resources)?;
526521

@@ -675,7 +670,7 @@ pub fn build_microvm(
675670
#[cfg(target_arch = "x86_64")]
676671
{
677672
let ioapic: Box<dyn IrqChipT> = if vm_resources.split_irqchip {
678-
Box::new(IoApic::new(vm.fd(), irq_sender).map_err(StartMicrovmError::CreateKvmIrqChip)?)
673+
Box::new(IoApic::new(vm.fd(), _sender).map_err(StartMicrovmError::CreateKvmIrqChip)?)
679674
} else {
680675
Box::new(KvmIoapic::new(vm.fd()).map_err(StartMicrovmError::CreateKvmIrqChip)?)
681676
};

src/vmm/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use crate::linux::vstate;
3131
#[cfg(target_os = "macos")]
3232
mod macos;
3333
mod terminal;
34+
pub mod worker;
3435

3536
#[cfg(target_os = "macos")]
3637
pub use hvf::MemoryMapping;

src/vmm/src/worker.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use std::io;
2+
use std::sync::{Arc, Mutex};
3+
4+
use utils::eventfd::EventFd;
5+
use utils::worker_message::WorkerMessage;
6+
7+
use crossbeam_channel::Receiver;
8+
9+
pub fn start_worker_thread(
10+
vmm: Arc<Mutex<super::Vmm>>,
11+
#[cfg(not(target_os = "macos"))] receiver: Receiver<(WorkerMessage, EventFd)>,
12+
) -> io::Result<()> {
13+
std::thread::Builder::new()
14+
.name("vmm worker".into())
15+
.spawn(move || loop {
16+
match receiver.recv() {
17+
Err(e) => error!("error receiving message from vmm worker thread: {:?}", e),
18+
#[cfg(target_os = "linux")]
19+
Ok((message, evt_fd)) => vmm.lock().unwrap().match_worker_message(message, evt_fd),
20+
}
21+
})?;
22+
Ok(())
23+
}
24+
25+
impl super::Vmm {
26+
fn match_worker_message(
27+
&self,
28+
msg: WorkerMessage,
29+
#[cfg(target_os = "linux")] evt_fd: EventFd,
30+
) {
31+
match msg {
32+
#[cfg(target_arch = "x86_64")]
33+
WorkerMessage::GsiRoute(entries) => {
34+
let mut irq_routing = utils::sized_vec::vec_with_array_field::<
35+
kvm_bindings::kvm_irq_routing,
36+
kvm_bindings::kvm_irq_routing_entry,
37+
>(entries.len());
38+
irq_routing[0].nr = entries.len() as u32;
39+
irq_routing[0].flags = 0;
40+
41+
unsafe {
42+
let entries_slice: &mut [kvm_bindings::kvm_irq_routing_entry] =
43+
irq_routing[0].entries.as_mut_slice(entries.len());
44+
entries_slice.copy_from_slice(&entries);
45+
}
46+
47+
self.vm.fd().set_gsi_routing(&irq_routing[0]).unwrap();
48+
49+
evt_fd.write(1).unwrap();
50+
}
51+
#[cfg(target_arch = "x86_64")]
52+
WorkerMessage::IrqLine(irq, active) => {
53+
self.vm.fd().set_irq_line(irq, active).unwrap();
54+
evt_fd.write(1).unwrap();
55+
}
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)