Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP5:Update
xen.21123
xsa373-5.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File xsa373-5.patch of Package xen.21123
AMD/IOMMU: drop command completion timeout First and foremost - such timeouts were not signaled to callers, making them believe they're fine to e.g. free previously unmapped pages. Mirror VT-d's behavior: A fixed number of loop iterations is not a suitable way to detect timeouts in an environment (CPU and bus speeds) independent manner anyway. Furthermore, leaving an in-progress operation pending when it appears to take too long is problematic: If a command completed later, the signaling of its completion may instead be understood to signal a subsequently started command's completion. Log excessively long processing times (with a progressive threshold) to have some indication of problems in this area. Allow callers to specify a non-default timeout bias for this logging, using the same values as VT-d does, which in particular means a (by default) much larger value for device IO TLB invalidation. This is part of XSA-373. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Paul Durrant <paul@xen.org> --- a/xen/drivers/passthrough/amd/iommu_cmd.c +++ b/xen/drivers/passthrough/amd/iommu_cmd.c @@ -57,8 +57,9 @@ static void send_iommu_command(struct am static void flush_command_buffer(struct amd_iommu *iommu) { - u32 cmd[4], status; - int loop_count, comp_wait; + uint32_t cmd[4]; + s_time_t start, timeout; + static unsigned int __read_mostly threshold = 1; /* RW1C 'ComWaitInt' in status register */ writel(IOMMU_STATUS_COMP_WAIT_INT_MASK, @@ -74,24 +75,29 @@ static void flush_command_buffer(struct IOMMU_COMP_WAIT_I_FLAG_SHIFT, &cmd[0]); send_iommu_command(iommu, cmd); - /* Make loop_count long enough for polling completion wait bit */ - loop_count = 1000; - do { - status = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); - comp_wait = get_field_from_reg_u32(status, - IOMMU_STATUS_COMP_WAIT_INT_MASK, - IOMMU_STATUS_COMP_WAIT_INT_SHIFT); - --loop_count; - } while ( !comp_wait && loop_count ); - - if ( comp_wait ) + start = NOW(); + timeout = start + 100 * MILLISECS(threshold); + while ( !(readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET) & + IOMMU_STATUS_COMP_WAIT_INT_MASK) ) { - /* RW1C 'ComWaitInt' in status register */ - writel(IOMMU_STATUS_COMP_WAIT_INT_MASK, - iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); - return; + if ( timeout && NOW() > timeout ) + { + threshold |= threshold << 1; + printk(XENLOG_WARNING + "AMD IOMMU %04x:%02x:%02x.%u: completion wait taking too long\n", + iommu->seg, PCI_BUS(iommu->bdf), + PCI_SLOT(iommu->bdf), PCI_FUNC(iommu->bdf)); + timeout = 0; + } + cpu_relax(); } - AMD_IOMMU_DEBUG("Warning: ComWaitInt bit did not assert!\n"); + + if ( !timeout ) + printk(XENLOG_WARNING + "AMD IOMMU %04x:%02x:%02x.%u: completion wait took %lums\n", + iommu->seg, PCI_BUS(iommu->bdf), + PCI_SLOT(iommu->bdf), PCI_FUNC(iommu->bdf), + (NOW() - start) / 10000000); } /* Build low level iommu command messages */
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor