mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-12-22 05:35:20 +00:00
vm-device: support batch update interrupt source group GSI
Split interrupt source group restore into two steps, first restore the irqfd for each interrupt source entry, and second restore the GSI routing of the entire interrupt source group. This patch will reduce restore latency of interrupt source group, and in a 200-concurrent restore test, the patch reduced the average IOAPIC restore time from 15ms to 1ms. Signed-off-by: Yong He <alexyonghe@tencent.com>
This commit is contained in:
parent
ecf3db5092
commit
0149e65081
@ -98,9 +98,14 @@ impl Gic {
|
||||
i as InterruptIndex,
|
||||
InterruptSourceConfig::LegacyIrq(config),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
.map_err(Error::EnableInterrupt)?;
|
||||
}
|
||||
|
||||
self.interrupt_source_group
|
||||
.set_gsi()
|
||||
.map_err(Error::EnableInterrupt)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -237,9 +237,14 @@ impl Ioapic {
|
||||
if state.is_some() {
|
||||
for (irq, entry) in ioapic.used_entries.iter().enumerate() {
|
||||
if *entry {
|
||||
ioapic.update_entry(irq)?;
|
||||
ioapic.update_entry(irq, false)?;
|
||||
}
|
||||
}
|
||||
|
||||
ioapic
|
||||
.interrupt_source_group
|
||||
.set_gsi()
|
||||
.map_err(Error::UpdateInterrupt)?;
|
||||
}
|
||||
|
||||
Ok(ioapic)
|
||||
@ -278,7 +283,7 @@ impl Ioapic {
|
||||
}
|
||||
// The entry must be updated through the interrupt source
|
||||
// group.
|
||||
if let Err(e) = self.update_entry(index) {
|
||||
if let Err(e) = self.update_entry(index, true) {
|
||||
error!("Failed updating IOAPIC entry: {:?}", e);
|
||||
}
|
||||
// Store the information this IRQ is now being used.
|
||||
@ -329,7 +334,7 @@ impl Ioapic {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_entry(&self, irq: usize) -> Result<()> {
|
||||
fn update_entry(&self, irq: usize, set_gsi: bool) -> Result<()> {
|
||||
let entry = self.reg_entries[irq];
|
||||
|
||||
// Validate Destination Mode value, and retrieve Destination ID
|
||||
@ -386,6 +391,7 @@ impl Ioapic {
|
||||
irq as InterruptIndex,
|
||||
InterruptSourceConfig::MsiIrq(config),
|
||||
interrupt_mask(entry) == 1,
|
||||
set_gsi,
|
||||
)
|
||||
.map_err(Error::UpdateInterrupt)?;
|
||||
|
||||
|
@ -361,10 +361,15 @@ mod tests {
|
||||
_index: InterruptIndex,
|
||||
_config: InterruptSourceConfig,
|
||||
_masked: bool,
|
||||
_set_gsi: bool,
|
||||
) -> result::Result<(), std::io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_gsi(&self) -> result::Result<(), std::io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
|
||||
Some(self.event_fd.try_clone().unwrap())
|
||||
}
|
||||
|
@ -413,10 +413,15 @@ mod tests {
|
||||
_index: InterruptIndex,
|
||||
_config: InterruptSourceConfig,
|
||||
_masked: bool,
|
||||
_set_gsi: bool,
|
||||
) -> result::Result<(), std::io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_gsi(&self) -> result::Result<(), std::io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
|
||||
Some(self.event_fd.try_clone().unwrap())
|
||||
}
|
||||
|
@ -365,9 +365,13 @@ mod tests {
|
||||
_index: InterruptIndex,
|
||||
_config: InterruptSourceConfig,
|
||||
_masked: bool,
|
||||
_set_gsi: bool,
|
||||
) -> result::Result<(), std::io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
fn set_gsi(&self) -> result::Result<(), std::io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
|
||||
Some(self.event_fd.try_clone().unwrap())
|
||||
}
|
||||
|
@ -485,9 +485,13 @@ mod tests {
|
||||
_index: InterruptIndex,
|
||||
_config: InterruptSourceConfig,
|
||||
_masked: bool,
|
||||
_set_gsi: bool,
|
||||
) -> result::Result<(), std::io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
fn set_gsi(&self) -> result::Result<(), std::io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
|
||||
Some(self.event_fd.try_clone().unwrap())
|
||||
}
|
||||
|
@ -59,9 +59,13 @@ impl InterruptSourceGroup for TestInterrupt {
|
||||
_index: InterruptIndex,
|
||||
_config: InterruptSourceConfig,
|
||||
_masked: bool,
|
||||
_set_gsi: bool,
|
||||
) -> Result<(), std::io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
fn set_gsi(&self) -> Result<(), std::io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
|
||||
Some(self.event_fd.try_clone().unwrap())
|
||||
}
|
||||
|
@ -205,10 +205,15 @@ impl MsiConfig {
|
||||
idx as InterruptIndex,
|
||||
InterruptSourceConfig::MsiIrq(config),
|
||||
state.cap.vector_masked(idx),
|
||||
false,
|
||||
)
|
||||
.map_err(Error::UpdateInterruptRoute)?;
|
||||
}
|
||||
|
||||
interrupt_source_group
|
||||
.set_gsi()
|
||||
.map_err(Error::EnableInterruptRoute)?;
|
||||
|
||||
interrupt_source_group
|
||||
.enable()
|
||||
.map_err(Error::EnableInterruptRoute)?;
|
||||
@ -262,6 +267,7 @@ impl MsiConfig {
|
||||
idx as InterruptIndex,
|
||||
InterruptSourceConfig::MsiIrq(config),
|
||||
self.cap.vector_masked(idx),
|
||||
true,
|
||||
) {
|
||||
error!("Failed updating vector: {:?}", e);
|
||||
}
|
||||
|
@ -107,6 +107,7 @@ impl MsixConfig {
|
||||
idx as InterruptIndex,
|
||||
InterruptSourceConfig::MsiIrq(config),
|
||||
state.masked,
|
||||
true,
|
||||
)
|
||||
.map_err(Error::UpdateInterruptRoute)?;
|
||||
|
||||
@ -182,6 +183,7 @@ impl MsixConfig {
|
||||
idx as InterruptIndex,
|
||||
InterruptSourceConfig::MsiIrq(config),
|
||||
table_entry.masked(),
|
||||
true,
|
||||
) {
|
||||
error!("Failed updating vector: {:?}", e);
|
||||
}
|
||||
@ -320,6 +322,7 @@ impl MsixConfig {
|
||||
index as InterruptIndex,
|
||||
InterruptSourceConfig::MsiIrq(config),
|
||||
table_entry.masked(),
|
||||
true,
|
||||
) {
|
||||
error!("Failed updating vector: {:?}", e);
|
||||
}
|
||||
|
@ -147,10 +147,15 @@ pub trait InterruptSourceGroup: Send + Sync {
|
||||
/// * index: sub-index into the group.
|
||||
/// * config: configuration data for the interrupt source.
|
||||
/// * masked: if the interrupt is masked
|
||||
/// * set_gsi: whehter update the GSI routing table.
|
||||
fn update(
|
||||
&self,
|
||||
index: InterruptIndex,
|
||||
config: InterruptSourceConfig,
|
||||
masked: bool,
|
||||
set_gsi: bool,
|
||||
) -> Result<()>;
|
||||
|
||||
/// Set the interrupt group GSI routing table.
|
||||
fn set_gsi(&self) -> Result<()>;
|
||||
}
|
||||
|
@ -170,6 +170,7 @@ impl InterruptSourceGroup for MsiInterruptGroup {
|
||||
index: InterruptIndex,
|
||||
config: InterruptSourceConfig,
|
||||
masked: bool,
|
||||
set_gsi: bool,
|
||||
) -> Result<()> {
|
||||
if let Some(route) = self.irq_routes.get(&index) {
|
||||
let entry = RoutingEntry {
|
||||
@ -183,7 +184,11 @@ impl InterruptSourceGroup for MsiInterruptGroup {
|
||||
}
|
||||
let mut routes = self.gsi_msi_routes.lock().unwrap();
|
||||
routes.insert(route.gsi, entry);
|
||||
return self.set_gsi_routes(&routes);
|
||||
if set_gsi {
|
||||
return self.set_gsi_routes(&routes);
|
||||
} else {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
Err(io::Error::new(
|
||||
@ -191,6 +196,11 @@ impl InterruptSourceGroup for MsiInterruptGroup {
|
||||
format!("update: Invalid interrupt index {index}"),
|
||||
))
|
||||
}
|
||||
|
||||
fn set_gsi(&self) -> Result<()> {
|
||||
let routes = self.gsi_msi_routes.lock().unwrap();
|
||||
self.set_gsi_routes(&routes)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LegacyUserspaceInterruptGroup {
|
||||
@ -223,10 +233,15 @@ impl InterruptSourceGroup for LegacyUserspaceInterruptGroup {
|
||||
_index: InterruptIndex,
|
||||
_config: InterruptSourceConfig,
|
||||
_masked: bool,
|
||||
_set_gsi: bool,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_gsi(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
|
||||
self.ioapic.lock().unwrap().notifier(self.irq as usize)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user