Skip to content

Commit d0c4c40

Browse files
committed
Update worker thread sender on x86
On x86, use the same sender as we would for macOS. Additionally, rather than using an EventFd to determine when the thread work is done, use a response sender/receiver like macOS. Signed-off-by: Jake Correnti <[email protected]>
1 parent 5a51449 commit d0c4c40

File tree

4 files changed

+60
-42
lines changed

4 files changed

+60
-42
lines changed

src/devices/src/legacy/ioapic.rs

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crossbeam_channel::{unbounded, Receiver, Sender};
12
use kvm_bindings::{
23
kvm_enable_cap, kvm_irq_routing, kvm_irq_routing_entry, kvm_irq_routing_entry__bindgen_ty_1,
34
kvm_irq_routing_msi, KVM_CAP_SPLIT_IRQCHIP, KVM_IRQ_ROUTING_MSI,
@@ -96,22 +97,21 @@ pub struct IoApic {
9697
version: u8,
9798
irq_eoi: [i32; IOAPIC_NUM_PINS],
9899
irq_routes: Vec<kvm_irq_routing_entry>,
99-
irq_sender: crossbeam_channel::Sender<(WorkerMessage, EventFd)>,
100-
event_fd: EventFd,
100+
irq_sender: Sender<WorkerMessage>,
101+
response_sender: Sender<bool>,
102+
response_receiver: Receiver<bool>,
101103
}
102104

103105
impl IoApic {
104-
pub fn new(
105-
vm: &VmFd,
106-
_irq_sender: crossbeam_channel::Sender<(WorkerMessage, EventFd)>,
107-
) -> Result<Self, Error> {
106+
pub fn new(vm: &VmFd, _irq_sender: Sender<WorkerMessage>) -> Result<Self, Error> {
108107
let mut cap = kvm_enable_cap {
109108
cap: KVM_CAP_SPLIT_IRQCHIP,
110109
..Default::default()
111110
};
112111
cap.args[0] = 24;
113112
vm.enable_cap(&cap)?;
114113

114+
let (response_sender, response_receiver) = unbounded();
115115
let mut ioapic = Self {
116116
id: 0,
117117
ioregsel: 0,
@@ -121,7 +121,8 @@ impl IoApic {
121121
irq_eoi: [0; IOAPIC_NUM_PINS],
122122
irq_routes: Vec::with_capacity(IOAPIC_NUM_PINS),
123123
irq_sender: _irq_sender,
124-
event_fd: EventFd::new(libc::EFD_SEMAPHORE).unwrap(),
124+
response_sender,
125+
response_receiver,
125126
};
126127

127128
(0..IOAPIC_NUM_PINS).for_each(|i| ioapic.add_msi_route(i));
@@ -175,14 +176,6 @@ impl IoApic {
175176
}
176177
}
177178

178-
fn send_irq_worker_message(&self, msg: WorkerMessage) {
179-
self.irq_sender
180-
.send((msg, self.event_fd.try_clone().unwrap()))
181-
.unwrap();
182-
183-
self.event_fd.read().unwrap();
184-
}
185-
186179
fn parse_entry(&self, entry: &RedirectionTableEntry) -> IoApicEntryInfo {
187180
let vector = (entry & IOAPIC_VECTOR_MASK) as u8;
188181
let dest_idx = ((entry >> IOAPIC_LVT_DEST_IDX_SHIFT) & 0xffff) as u16;
@@ -249,7 +242,15 @@ impl IoApic {
249242
}
250243
}
251244

252-
self.send_irq_worker_message(WorkerMessage::GsiRoute(self.irq_routes.clone()));
245+
self.irq_sender
246+
.send(WorkerMessage::GsiRoute(
247+
self.response_sender.clone(),
248+
self.irq_routes.clone(),
249+
))
250+
.unwrap();
251+
if !self.response_receiver.recv().unwrap() {
252+
error!("failed to update IO APIC routes");
253+
}
253254
}
254255

255256
fn service(&mut self) {
@@ -274,10 +275,37 @@ impl IoApic {
274275
}
275276

276277
if info.trig_mode as u64 == IOAPIC_TRIGGER_EDGE {
277-
self.send_irq_worker_message(WorkerMessage::IrqLine(i as u32, true));
278-
self.send_irq_worker_message(WorkerMessage::IrqLine(i as u32, false));
278+
self.irq_sender
279+
.send(WorkerMessage::IrqLine(
280+
self.response_sender.clone(),
281+
i as u32,
282+
true,
283+
))
284+
.unwrap();
285+
if !self.response_receiver.recv().unwrap() {
286+
error!("failed to fully service edge triggered interrupt on irq {} with active state", i);
287+
}
288+
self.irq_sender
289+
.send(WorkerMessage::IrqLine(
290+
self.response_sender.clone(),
291+
i as u32,
292+
false,
293+
))
294+
.unwrap();
295+
if !self.response_receiver.recv().unwrap() {
296+
error!("failed to fully service edge triggered interrupt on irq {} with inactive state", i);
297+
}
279298
} else {
280-
self.send_irq_worker_message(WorkerMessage::IrqLine(i as u32, true));
299+
self.irq_sender
300+
.send(WorkerMessage::IrqLine(
301+
self.response_sender.clone(),
302+
i as u32,
303+
true,
304+
))
305+
.unwrap();
306+
if !self.response_receiver.recv().unwrap() {
307+
error!("failed to service level triggered interrupt on irq {} with active state", i);
308+
}
281309
}
282310
}
283311
}

src/utils/src/worker_message.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ use crossbeam_channel::Sender;
33
#[derive(Debug)]
44
pub enum WorkerMessage {
55
#[cfg(target_arch = "x86_64")]
6-
GsiRoute(Vec<kvm_bindings::kvm_irq_routing_entry>),
6+
GsiRoute(Sender<bool>, Vec<kvm_bindings::kvm_irq_routing_entry>),
77
#[cfg(target_arch = "x86_64")]
8-
IrqLine(u32, bool),
8+
IrqLine(Sender<bool>, u32, bool),
99
#[cfg(target_os = "macos")]
1010
GpuAddMapping(Sender<bool>, u64, u64, u64),
1111
#[cfg(target_os = "macos")]

src/vmm/src/builder.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,7 @@ pub fn build_microvm(
508508
vm_resources: &super::resources::VmResources,
509509
event_manager: &mut EventManager,
510510
_shutdown_efd: Option<EventFd>,
511-
#[cfg(target_os = "macos")] _sender: Sender<WorkerMessage>,
512-
#[cfg(target_arch = "x86_64")] _sender: Sender<(WorkerMessage, EventFd)>,
511+
_sender: Sender<WorkerMessage>,
513512
) -> std::result::Result<Arc<Mutex<Vmm>>, StartMicrovmError> {
514513
let payload = choose_payload(vm_resources)?;
515514

src/vmm/src/lib.rs

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -383,37 +383,27 @@ impl Vmm {
383383

384384
pub fn start_worker_thread(
385385
vmm: Arc<Mutex<Vmm>>,
386-
#[cfg(target_os = "macos")] receiver: Receiver<WorkerMessage>,
387-
#[cfg(not(target_os = "macos"))] receiver: Receiver<(WorkerMessage, EventFd)>,
386+
receiver: Receiver<WorkerMessage>,
388387
) -> io::Result<()> {
389388
std::thread::Builder::new()
390389
.name("vmm worker".into())
391390
.spawn(move || loop {
392391
match receiver.recv() {
393392
Err(e) => error!("error receiving message from vmm worker thread: {:?}", e),
394-
#[cfg(target_os = "macos")]
395393
Ok(message) => vmm.lock().unwrap().match_worker_message(message),
396-
#[cfg(target_os = "linux")]
397-
Ok((message, evt_fd)) => {
398-
vmm.lock().unwrap().match_worker_message(message, evt_fd)
399-
}
400394
}
401395
})?;
402396
Ok(())
403397
}
404398

405-
fn match_worker_message(
406-
&self,
407-
msg: WorkerMessage,
408-
#[cfg(target_os = "linux")] evt_fd: EventFd,
409-
) {
399+
fn match_worker_message(&self, msg: WorkerMessage) {
410400
match msg {
411401
#[cfg(target_os = "macos")]
412402
WorkerMessage::GpuAddMapping(s, h, g, l) => self.add_mapping(s, h, g, l),
413403
#[cfg(target_os = "macos")]
414404
WorkerMessage::GpuRemoveMapping(s, g, l) => self.remove_mapping(s, g, l),
415405
#[cfg(target_arch = "x86_64")]
416-
WorkerMessage::GsiRoute(entries) => {
406+
WorkerMessage::GsiRoute(sender, entries) => {
417407
let mut irq_routing = utils::sized_vec::vec_with_array_field::<
418408
kvm_bindings::kvm_irq_routing,
419409
kvm_bindings::kvm_irq_routing_entry,
@@ -427,14 +417,15 @@ impl Vmm {
427417
entries_slice.copy_from_slice(&entries);
428418
}
429419

430-
self.vm.fd().set_gsi_routing(&irq_routing[0]).unwrap();
431-
432-
evt_fd.write(1).unwrap();
420+
sender
421+
.send(self.vm.fd().set_gsi_routing(&irq_routing[0]).is_ok())
422+
.unwrap();
433423
}
434424
#[cfg(target_arch = "x86_64")]
435-
WorkerMessage::IrqLine(irq, active) => {
436-
self.vm.fd().set_irq_line(irq, active).unwrap();
437-
evt_fd.write(1).unwrap();
425+
WorkerMessage::IrqLine(sender, irq, active) => {
426+
sender
427+
.send(self.vm.fd().set_irq_line(irq, active).is_ok())
428+
.unwrap();
438429
}
439430
}
440431
}

0 commit comments

Comments
 (0)