vm-device, pci, devices: Remove InterruptSourceGroup::{un}mask

The calls to these functions are always preceded by a call to
InterruptSourceGroup::update(). By adding a masked boolean to that
function call it possible to remove 50% of the calls to the
KVM_SET_GSI_ROUTING ioctl as the the update will correctly handle the
masked or unmasked case.

This causes the ioctl to disappear from the perf report for a boot of
the VM.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2022-04-11 16:21:20 +01:00
parent 6a099257e8
commit ed87e42e6f
10 changed files with 52 additions and 105 deletions

View File

@ -76,6 +76,7 @@ impl InterruptController for Gic {
.update(
i as InterruptIndex,
InterruptSourceConfig::LegacyIrq(config),
false,
)
.map_err(Error::EnableInterrupt)?;
}

View File

@ -367,19 +367,13 @@ impl Ioapic {
};
self.interrupt_source_group
.update(irq as InterruptIndex, InterruptSourceConfig::MsiIrq(config))
.update(
irq as InterruptIndex,
InterruptSourceConfig::MsiIrq(config),
interrupt_mask(entry) == 1,
)
.map_err(Error::UpdateInterrupt)?;
if interrupt_mask(entry) == 1 {
self.interrupt_source_group
.mask(irq as InterruptIndex)
.map_err(Error::MaskInterrupt)?;
} else {
self.interrupt_source_group
.unmask(irq as InterruptIndex)
.map_err(Error::UnmaskInterrupt)?;
}
Ok(())
}
}

View File

@ -356,6 +356,7 @@ mod tests {
&self,
_index: InterruptIndex,
_config: InterruptSourceConfig,
_masked: bool,
) -> result::Result<(), std::io::Error> {
Ok(())
}

View File

@ -430,6 +430,7 @@ mod tests {
&self,
_index: InterruptIndex,
_config: InterruptSourceConfig,
_masked: bool,
) -> result::Result<(), std::io::Error> {
Ok(())
}

View File

@ -339,6 +339,7 @@ mod tests {
&self,
_index: InterruptIndex,
_config: InterruptSourceConfig,
_masked: bool,
) -> result::Result<(), std::io::Error> {
Ok(())
}

View File

@ -450,6 +450,7 @@ mod tests {
&self,
_index: InterruptIndex,
_config: InterruptSourceConfig,
_masked: bool,
) -> result::Result<(), std::io::Error> {
Ok(())
}

View File

@ -201,20 +201,13 @@ impl MsiConfig {
devid: 0,
};
if let Err(e) = self
.interrupt_source_group
.update(idx as InterruptIndex, InterruptSourceConfig::MsiIrq(config))
{
if let Err(e) = self.interrupt_source_group.update(
idx as InterruptIndex,
InterruptSourceConfig::MsiIrq(config),
self.cap.vector_masked(idx),
) {
error!("Failed updating vector: {:?}", e);
}
if self.cap.vector_masked(idx) {
if let Err(e) = self.interrupt_source_group.mask(idx as InterruptIndex) {
error!("Failed masking vector: {:?}", e);
}
} else if let Err(e) = self.interrupt_source_group.unmask(idx as InterruptIndex) {
error!("Failed unmasking vector: {:?}", e);
}
}
if !old_enabled {

View File

@ -132,7 +132,11 @@ impl MsixConfig {
};
self.interrupt_source_group
.update(idx as InterruptIndex, InterruptSourceConfig::MsiIrq(config))
.update(
idx as InterruptIndex,
InterruptSourceConfig::MsiIrq(config),
self.masked,
)
.map_err(Error::UpdateInterruptRoute)?;
self.interrupt_source_group
@ -171,21 +175,13 @@ impl MsixConfig {
devid: self.devid,
};
if let Err(e) = self
.interrupt_source_group
.update(idx as InterruptIndex, InterruptSourceConfig::MsiIrq(config))
{
if let Err(e) = self.interrupt_source_group.update(
idx as InterruptIndex,
InterruptSourceConfig::MsiIrq(config),
table_entry.masked(),
) {
error!("Failed updating vector: {:?}", e);
}
if table_entry.masked() {
if let Err(e) = self.interrupt_source_group.mask(idx as InterruptIndex) {
error!("Failed masking vector: {:?}", e);
}
} else if let Err(e) = self.interrupt_source_group.unmask(idx as InterruptIndex)
{
error!("Failed unmasking vector: {:?}", e);
}
}
} else if old_enabled || !old_masked {
debug!("MSI-X disabled for device 0x{:x}", self.devid);
@ -314,17 +310,10 @@ impl MsixConfig {
if let Err(e) = self.interrupt_source_group.update(
index as InterruptIndex,
InterruptSourceConfig::MsiIrq(config),
table_entry.masked(),
) {
error!("Failed updating vector: {:?}", e);
}
if table_entry.masked() {
if let Err(e) = self.interrupt_source_group.mask(index as InterruptIndex) {
error!("Failed masking vector: {:?}", e);
}
} else if let Err(e) = self.interrupt_source_group.unmask(index as InterruptIndex) {
error!("Failed unmasking vector: {:?}", e);
}
}
// After the MSI-X table entry has been updated, it is necessary to

View File

@ -178,19 +178,11 @@ pub trait InterruptSourceGroup: Send + Sync {
/// # Arguments
/// * index: sub-index into the group.
/// * config: configuration data for the interrupt source.
fn update(&self, index: InterruptIndex, config: InterruptSourceConfig) -> Result<()>;
/// Mask an interrupt from this interrupt source.
fn mask(&self, _index: InterruptIndex) -> Result<()> {
// Not all interrupt sources can be disabled.
// To accommodate this, we can have a no-op here.
Ok(())
}
/// Unmask an interrupt from this interrupt source.
fn unmask(&self, _index: InterruptIndex) -> Result<()> {
// Not all interrupt sources can be disabled.
// To accommodate this, we can have a no-op here.
Ok(())
}
/// * masked: if the interrupt is masked
fn update(
&self,
index: InterruptIndex,
config: InterruptSourceConfig,
masked: bool,
) -> Result<()>;
}

View File

@ -165,9 +165,20 @@ impl InterruptSourceGroup for MsiInterruptGroup<IrqRoutingEntry> {
None
}
fn update(&self, index: InterruptIndex, config: InterruptSourceConfig) -> Result<()> {
fn update(
&self,
index: InterruptIndex,
config: InterruptSourceConfig,
masked: bool,
) -> Result<()> {
if let Some(route) = self.irq_routes.get(&index) {
let entry = RoutingEntry::<_>::make_entry(&self.vm, route.gsi, &config)?;
let mut entry = RoutingEntry::<_>::make_entry(&self.vm, route.gsi, &config)?;
entry.masked = masked;
if masked {
route.disable(&self.vm)?;
} else {
route.enable(&self.vm)?;
}
let mut routes = self.gsi_msi_routes.lock().unwrap();
routes.insert(route.gsi, *entry);
return self.set_gsi_routes(&routes);
@ -178,48 +189,6 @@ impl InterruptSourceGroup for MsiInterruptGroup<IrqRoutingEntry> {
format!("update: Invalid interrupt index {}", index),
))
}
fn mask(&self, index: InterruptIndex) -> Result<()> {
if let Some(route) = self.irq_routes.get(&index) {
let mut routes = self.gsi_msi_routes.lock().unwrap();
if let Some(entry) = routes.get_mut(&route.gsi) {
entry.masked = true;
} else {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("mask: No existing route for interrupt index {}", index),
));
}
route.disable(&self.vm)?;
return self.set_gsi_routes(&routes);
}
Err(io::Error::new(
io::ErrorKind::Other,
format!("mask: Invalid interrupt index {}", index),
))
}
fn unmask(&self, index: InterruptIndex) -> Result<()> {
if let Some(route) = self.irq_routes.get(&index) {
let mut routes = self.gsi_msi_routes.lock().unwrap();
if let Some(entry) = routes.get_mut(&route.gsi) {
entry.masked = false;
} else {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("mask: No existing route for interrupt index {}", index),
));
}
route.enable(&self.vm)?;
return self.set_gsi_routes(&routes);
}
Err(io::Error::new(
io::ErrorKind::Other,
format!("unmask: Invalid interrupt index {}", index),
))
}
}
pub struct LegacyUserspaceInterruptGroup {
@ -247,7 +216,12 @@ impl InterruptSourceGroup for LegacyUserspaceInterruptGroup {
})
}
fn update(&self, _index: InterruptIndex, _config: InterruptSourceConfig) -> Result<()> {
fn update(
&self,
_index: InterruptIndex,
_config: InterruptSourceConfig,
_masked: bool,
) -> Result<()> {
Ok(())
}