linux: x86_64: Initialize direct-irq before irqchip finalize

In general irqchip finalizes setup and finalize_devices() should be called
once all devices have registered irq events and been added to the io_bus
and mmio_bus.

Split irqchip finilize_device() implementation in particular,
hands over requested irq events to IOAPIC in order to emulate pin state
and do proper forwarding when needed.

Move direct-irq registration before irqchip finalizes so that direct-irq
is taken into account. Note that direct-irq does work with kernel irqchip
implementation because its finalize_devices() is empty.

BUG=b:184871003
TEST=boot guest using crosvm --split-irqchip flag and check if IOAPIC
related IRQs are working

Change-Id: I78dbace08eee4a5bc91695fd8b8d41a84e58cde9
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3494284
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Steven Richman <srichman@google.com>
Commit-Queue: Tomasz Nowicki <tnowicki@google.com>
This commit is contained in:
Tomasz Nowicki 2022-02-22 14:14:45 +00:00 committed by Commit Bot
parent 70f44d9672
commit 64f4355a4b

View file

@ -1184,6 +1184,42 @@ where
}))
.context("failed to calculate init balloon size")?;
#[cfg(feature = "direct")]
let mut irqs = Vec::new();
#[cfg(feature = "direct")]
for irq in &cfg.direct_level_irq {
if !sys_allocator.reserve_irq(*irq) {
warn!("irq {} already reserved.", irq);
}
let trigger = Event::new().context("failed to create event")?;
let resample = Event::new().context("failed to create event")?;
irq_chip
.register_irq_event(*irq, &trigger, Some(&resample))
.unwrap();
let direct_irq = devices::DirectIrq::new(trigger, Some(resample))
.context("failed to enable interrupt forwarding")?;
direct_irq
.irq_enable(*irq)
.context("failed to enable interrupt forwarding")?;
irqs.push(direct_irq);
}
#[cfg(feature = "direct")]
for irq in &cfg.direct_edge_irq {
if !sys_allocator.reserve_irq(*irq) {
warn!("irq {} already reserved.", irq);
}
let trigger = Event::new().context("failed to create event")?;
irq_chip.register_irq_event(*irq, &trigger, None).unwrap();
let direct_irq = devices::DirectIrq::new(trigger, None)
.context("failed to enable interrupt forwarding")?;
direct_irq
.irq_enable(*irq)
.context("failed to enable interrupt forwarding")?;
irqs.push(direct_irq);
}
let mut iommu_attached_endpoints: BTreeMap<u32, Arc<Mutex<Box<dyn MemoryMapperTrait>>>> =
BTreeMap::new();
let mut devices = create_devices(
@ -1333,46 +1369,6 @@ where
}
};
#[cfg(feature = "direct")]
let mut irqs = Vec::new();
#[cfg(feature = "direct")]
for irq in &cfg.direct_level_irq {
if !sys_allocator.reserve_irq(*irq) {
warn!("irq {} already reserved.", irq);
}
let trigger = Event::new().context("failed to create event")?;
let resample = Event::new().context("failed to create event")?;
linux
.irq_chip
.register_irq_event(*irq, &trigger, Some(&resample))
.unwrap();
let direct_irq = devices::DirectIrq::new(trigger, Some(resample))
.context("failed to enable interrupt forwarding")?;
direct_irq
.irq_enable(*irq)
.context("failed to enable interrupt forwarding")?;
irqs.push(direct_irq);
}
#[cfg(feature = "direct")]
for irq in &cfg.direct_edge_irq {
if !sys_allocator.reserve_irq(*irq) {
warn!("irq {} already reserved.", irq);
}
let trigger = Event::new().context("failed to create event")?;
linux
.irq_chip
.register_irq_event(*irq, &trigger, None)
.unwrap();
let direct_irq = devices::DirectIrq::new(trigger, None)
.context("failed to enable interrupt forwarding")?;
direct_irq
.irq_enable(*irq)
.context("failed to enable interrupt forwarding")?;
irqs.push(direct_irq);
}
let gralloc = RutabagaGralloc::new().context("failed to create gralloc")?;
run_control(
linux,