mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-02 11:35:46 +00:00
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:
parent
6a099257e8
commit
ed87e42e6f
@ -76,6 +76,7 @@ impl InterruptController for Gic {
|
|||||||
.update(
|
.update(
|
||||||
i as InterruptIndex,
|
i as InterruptIndex,
|
||||||
InterruptSourceConfig::LegacyIrq(config),
|
InterruptSourceConfig::LegacyIrq(config),
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.map_err(Error::EnableInterrupt)?;
|
.map_err(Error::EnableInterrupt)?;
|
||||||
}
|
}
|
||||||
|
@ -367,19 +367,13 @@ impl Ioapic {
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.interrupt_source_group
|
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)?;
|
.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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -356,6 +356,7 @@ mod tests {
|
|||||||
&self,
|
&self,
|
||||||
_index: InterruptIndex,
|
_index: InterruptIndex,
|
||||||
_config: InterruptSourceConfig,
|
_config: InterruptSourceConfig,
|
||||||
|
_masked: bool,
|
||||||
) -> result::Result<(), std::io::Error> {
|
) -> result::Result<(), std::io::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -430,6 +430,7 @@ mod tests {
|
|||||||
&self,
|
&self,
|
||||||
_index: InterruptIndex,
|
_index: InterruptIndex,
|
||||||
_config: InterruptSourceConfig,
|
_config: InterruptSourceConfig,
|
||||||
|
_masked: bool,
|
||||||
) -> result::Result<(), std::io::Error> {
|
) -> result::Result<(), std::io::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -339,6 +339,7 @@ mod tests {
|
|||||||
&self,
|
&self,
|
||||||
_index: InterruptIndex,
|
_index: InterruptIndex,
|
||||||
_config: InterruptSourceConfig,
|
_config: InterruptSourceConfig,
|
||||||
|
_masked: bool,
|
||||||
) -> result::Result<(), std::io::Error> {
|
) -> result::Result<(), std::io::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -450,6 +450,7 @@ mod tests {
|
|||||||
&self,
|
&self,
|
||||||
_index: InterruptIndex,
|
_index: InterruptIndex,
|
||||||
_config: InterruptSourceConfig,
|
_config: InterruptSourceConfig,
|
||||||
|
_masked: bool,
|
||||||
) -> result::Result<(), std::io::Error> {
|
) -> result::Result<(), std::io::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -201,20 +201,13 @@ impl MsiConfig {
|
|||||||
devid: 0,
|
devid: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = self
|
if let Err(e) = self.interrupt_source_group.update(
|
||||||
.interrupt_source_group
|
idx as InterruptIndex,
|
||||||
.update(idx as InterruptIndex, InterruptSourceConfig::MsiIrq(config))
|
InterruptSourceConfig::MsiIrq(config),
|
||||||
{
|
self.cap.vector_masked(idx),
|
||||||
|
) {
|
||||||
error!("Failed updating vector: {:?}", e);
|
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 {
|
if !old_enabled {
|
||||||
|
@ -132,7 +132,11 @@ impl MsixConfig {
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.interrupt_source_group
|
self.interrupt_source_group
|
||||||
.update(idx as InterruptIndex, InterruptSourceConfig::MsiIrq(config))
|
.update(
|
||||||
|
idx as InterruptIndex,
|
||||||
|
InterruptSourceConfig::MsiIrq(config),
|
||||||
|
self.masked,
|
||||||
|
)
|
||||||
.map_err(Error::UpdateInterruptRoute)?;
|
.map_err(Error::UpdateInterruptRoute)?;
|
||||||
|
|
||||||
self.interrupt_source_group
|
self.interrupt_source_group
|
||||||
@ -171,21 +175,13 @@ impl MsixConfig {
|
|||||||
devid: self.devid,
|
devid: self.devid,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = self
|
if let Err(e) = self.interrupt_source_group.update(
|
||||||
.interrupt_source_group
|
idx as InterruptIndex,
|
||||||
.update(idx as InterruptIndex, InterruptSourceConfig::MsiIrq(config))
|
InterruptSourceConfig::MsiIrq(config),
|
||||||
{
|
table_entry.masked(),
|
||||||
|
) {
|
||||||
error!("Failed updating vector: {:?}", e);
|
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 {
|
} else if old_enabled || !old_masked {
|
||||||
debug!("MSI-X disabled for device 0x{:x}", self.devid);
|
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(
|
if let Err(e) = self.interrupt_source_group.update(
|
||||||
index as InterruptIndex,
|
index as InterruptIndex,
|
||||||
InterruptSourceConfig::MsiIrq(config),
|
InterruptSourceConfig::MsiIrq(config),
|
||||||
|
table_entry.masked(),
|
||||||
) {
|
) {
|
||||||
error!("Failed updating vector: {:?}", e);
|
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
|
// After the MSI-X table entry has been updated, it is necessary to
|
||||||
|
@ -178,19 +178,11 @@ pub trait InterruptSourceGroup: Send + Sync {
|
|||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * index: sub-index into the group.
|
/// * index: sub-index into the group.
|
||||||
/// * config: configuration data for the interrupt source.
|
/// * config: configuration data for the interrupt source.
|
||||||
fn update(&self, index: InterruptIndex, config: InterruptSourceConfig) -> Result<()>;
|
/// * masked: if the interrupt is masked
|
||||||
|
fn update(
|
||||||
/// Mask an interrupt from this interrupt source.
|
&self,
|
||||||
fn mask(&self, _index: InterruptIndex) -> Result<()> {
|
index: InterruptIndex,
|
||||||
// Not all interrupt sources can be disabled.
|
config: InterruptSourceConfig,
|
||||||
// To accommodate this, we can have a no-op here.
|
masked: bool,
|
||||||
Ok(())
|
) -> Result<()>;
|
||||||
}
|
|
||||||
|
|
||||||
/// 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(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -165,9 +165,20 @@ impl InterruptSourceGroup for MsiInterruptGroup<IrqRoutingEntry> {
|
|||||||
None
|
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) {
|
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();
|
let mut routes = self.gsi_msi_routes.lock().unwrap();
|
||||||
routes.insert(route.gsi, *entry);
|
routes.insert(route.gsi, *entry);
|
||||||
return self.set_gsi_routes(&routes);
|
return self.set_gsi_routes(&routes);
|
||||||
@ -178,48 +189,6 @@ impl InterruptSourceGroup for MsiInterruptGroup<IrqRoutingEntry> {
|
|||||||
format!("update: Invalid interrupt index {}", index),
|
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 {
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user