Skip to content

Commit 701042f

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 701042f

File tree

4 files changed

+60
-39
lines changed

4 files changed

+60
-39
lines changed

src/devices/src/legacy/ioapic.rs

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crossbeam_channel::{unbounded, Sender, Receiver};
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,14 +97,15 @@ 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 {
104106
pub fn new(
105107
vm: &VmFd,
106-
_irq_sender: crossbeam_channel::Sender<(WorkerMessage, EventFd)>,
108+
_irq_sender: Sender<WorkerMessage>,
107109
) -> Result<Self, Error> {
108110
let mut cap = kvm_enable_cap {
109111
cap: KVM_CAP_SPLIT_IRQCHIP,
@@ -112,6 +114,7 @@ impl IoApic {
112114
cap.args[0] = 24;
113115
vm.enable_cap(&cap)?;
114116

117+
let (response_sender, response_receiver) = unbounded();
115118
let mut ioapic = Self {
116119
id: 0,
117120
ioregsel: 0,
@@ -121,7 +124,8 @@ impl IoApic {
121124
irq_eoi: [0; IOAPIC_NUM_PINS],
122125
irq_routes: Vec::with_capacity(IOAPIC_NUM_PINS),
123126
irq_sender: _irq_sender,
124-
event_fd: EventFd::new(libc::EFD_SEMAPHORE).unwrap(),
127+
response_sender,
128+
response_receiver,
125129
};
126130

127131
(0..IOAPIC_NUM_PINS).for_each(|i| ioapic.add_msi_route(i));
@@ -175,14 +179,6 @@ impl IoApic {
175179
}
176180
}
177181

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-
186182
fn parse_entry(&self, entry: &RedirectionTableEntry) -> IoApicEntryInfo {
187183
let vector = (entry & IOAPIC_VECTOR_MASK) as u8;
188184
let dest_idx = ((entry >> IOAPIC_LVT_DEST_IDX_SHIFT) & 0xffff) as u16;
@@ -249,7 +245,15 @@ impl IoApic {
249245
}
250246
}
251247

252-
self.send_irq_worker_message(WorkerMessage::GsiRoute(self.irq_routes.clone()));
248+
self.irq_sender
249+
.send(WorkerMessage::GsiRoute(
250+
self.response_sender.clone(),
251+
self.irq_routes.clone(),
252+
))
253+
.unwrap();
254+
if !self.response_receiver.recv().unwrap() {
255+
error!("failed to update IO APIC routes");
256+
}
253257
}
254258

255259
fn service(&mut self) {
@@ -274,10 +278,37 @@ impl IoApic {
274278
}
275279

276280
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));
281+
self.irq_sender
282+
.send(WorkerMessage::IrqLine(
283+
self.response_sender.clone(),
284+
i as u32,
285+
true,
286+
))
287+
.unwrap();
288+
if !self.response_receiver.recv().unwrap() {
289+
error!("failed to fully service edge triggered interrupt on irq {} with active state", i);
290+
}
291+
self.irq_sender
292+
.send(WorkerMessage::IrqLine(
293+
self.response_sender.clone(),
294+
i as u32,
295+
false,
296+
))
297+
.unwrap();
298+
if !self.response_receiver.recv().unwrap() {
299+
error!("failed to fully service edge triggered interrupt on irq {} with inactive state", i);
300+
}
279301
} else {
280-
self.send_irq_worker_message(WorkerMessage::IrqLine(i as u32, true));
302+
self.irq_sender
303+
.send(WorkerMessage::IrqLine(
304+
self.response_sender.clone(),
305+
i as u32,
306+
true,
307+
))
308+
.unwrap();
309+
if !self.response_receiver.recv().unwrap() {
310+
error!("failed to service level triggered interrupt on irq {} with active state", i);
311+
}
281312
}
282313
}
283314
}

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)