Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP7:Update
xen.30332
608676f2-VT-d-register-based-invalidation-optio...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 608676f2-VT-d-register-based-invalidation-optional.patch of Package xen.30332
# Commit 6773b1a7584a75a486e9774541ad5bd84c9aa5ee # Date 2021-04-26 10:16:50 +0200 # Author Chao Gao <chao.gao@intel.com> # Committer Jan Beulich <jbeulich@suse.com> VT-d: Don't assume register-based invalidation is always supported According to Intel VT-d SPEC rev3.3 Section 6.5, Register-based Invalidation isn't supported by Intel VT-d version 6 and beyond. This hardware change impacts following two scenarios: admin can disable queued invalidation via 'qinval' cmdline and use register-based interface; VT-d switches to register-based invalidation when queued invalidation needs to be disabled, for example, during disabling x2apic or during system suspension or after enabling queued invalidation fails. To deal with this hardware change, if register-based invalidation isn't supported, queued invalidation cannot be disabled through Xen cmdline; and if queued invalidation has to be disabled temporarily in some scenarios, VT-d won't switch to register-based interface but use some dummy functions to catch errors in case there is any invalidation request issued when queued invalidation is disabled. Signed-off-by: Chao Gao <chao.gao@intel.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> --- a/docs/misc/xen-command-line.pandoc +++ b/docs/misc/xen-command-line.pandoc @@ -1328,7 +1328,9 @@ The following options are specific to In * The `qinval` boolean controls the Queued Invalidation sub-feature, and is active by default on compatible hardware. Queued Invalidation is a feature in second-generation IOMMUs and is a functional prerequisite for - Interrupt Remapping. + Interrupt Remapping. Note that Xen disregards this setting for Intel VT-d + version 6 and greater as Registered-Based Invalidation isn't supported + by them. * The `igfx` boolean is active by default, and controls whether the IOMMU in front of an Intel Graphics Device is enabled or not. --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -1232,6 +1232,14 @@ int __init iommu_alloc(struct acpi_drhd_ iommu->cap = dmar_readq(iommu->reg, DMAR_CAP_REG); iommu->ecap = dmar_readq(iommu->reg, DMAR_ECAP_REG); + iommu->version = dmar_readl(iommu->reg, DMAR_VER_REG); + + if ( !iommu_qinval && !has_register_based_invalidation(iommu) ) + { + printk(XENLOG_WARNING VTDPREFIX "IOMMU %d: cannot disable Queued Invalidation\n", + iommu->index); + iommu_qinval = true; + } if ( iommu_verbose ) { @@ -2197,6 +2205,10 @@ static int __must_check init_vtd_hw(void */ if ( enable_qinval(iommu) != 0 ) { + /* Ensure register-based invalidation is available */ + if ( !has_register_based_invalidation(iommu) ) + return -EIO; + flush = iommu_get_flush(iommu); flush->context = vtd_flush_context_reg; flush->iotlb = vtd_flush_iotlb_reg; @@ -2288,6 +2300,7 @@ int __init intel_vtd_setup(void) struct acpi_drhd_unit *drhd; struct iommu *iommu; int ret; + bool reg_inval_supported = true; if ( list_empty(&acpi_drhd_units) ) { @@ -2311,8 +2324,8 @@ int __init intel_vtd_setup(void) iommu_ops = intel_iommu_ops; /* We enable the following features only if they are supported by all VT-d - * engines: Snoop Control, DMA passthrough, Queued Invalidation, Interrupt - * Remapping, and Posted Interrupt + * engines: Snoop Control, DMA passthrough, Register-based Invalidation, + * Queued Invalidation, Interrupt Remapping, and Posted Interrupt. */ for_each_drhd_unit ( drhd ) { @@ -2337,6 +2350,9 @@ int __init intel_vtd_setup(void) if ( iommu_qinval && !ecap_queued_inval(iommu->ecap) ) iommu_qinval = 0; + if ( !has_register_based_invalidation(iommu) ) + reg_inval_supported = false; + if ( iommu_intremap && !ecap_intr_remap(iommu->ecap) ) iommu_intremap = 0; @@ -2361,6 +2377,13 @@ int __init intel_vtd_setup(void) softirq_tasklet_init(&vtd_fault_tasklet, do_iommu_page_fault, 0); + if ( !iommu_qinval && !reg_inval_supported ) + { + dprintk(XENLOG_ERR VTDPREFIX, "No available invalidation interface\n"); + ret = -ENODEV; + goto error; + } + if ( !iommu_qinval && iommu_intremap ) { iommu_intremap = 0; --- a/xen/drivers/passthrough/vtd/iommu.h +++ b/xen/drivers/passthrough/vtd/iommu.h @@ -547,6 +547,7 @@ struct iommu { struct list_head ats_devices; unsigned long *domid_bitmap; /* domain id bitmap */ u16 *domid_map; /* domain id mapping array */ + uint32_t version; }; static inline struct qi_ctrl *iommu_qi_ctrl(struct iommu *iommu) @@ -571,4 +572,10 @@ static inline struct iommu_flush *iommu_ dprintk(XENLOG_WARNING VTDPREFIX, fmt, ## args); \ } while(0) +/* Register-based invalidation isn't supported by VT-d version 6 and beyond. */ +static inline bool has_register_based_invalidation(const struct iommu *vtd) +{ + return VER_MAJOR(vtd->version) < 6; +} + #endif --- a/xen/drivers/passthrough/vtd/qinval.c +++ b/xen/drivers/passthrough/vtd/qinval.c @@ -455,6 +455,23 @@ int enable_qinval(struct iommu *iommu) return 0; } +static int vtd_flush_context_noop(void *iommu, uint16_t did, + uint16_t source_id, uint8_t function_mask, + uint64_t type, bool flush_non_present_entry) +{ + WARN(); + return -EIO; +} + +static int vtd_flush_iotlb_noop(void *iommu, uint16_t did, + uint64_t addr, unsigned int size_order, + uint64_t type, bool flush_non_present_entry, + bool flush_dev_iotlb) +{ + WARN(); + return -EIO; +} + void disable_qinval(struct iommu *iommu) { u32 sts; @@ -478,6 +495,18 @@ out: spin_unlock_irqrestore(&iommu->register_lock, flags); flush = iommu_get_flush(iommu); - flush->context = vtd_flush_context_reg; - flush->iotlb = vtd_flush_iotlb_reg; + /* + * Assign callbacks to noop to catch errors if register-based invalidation + * isn't supported. + */ + if ( has_register_based_invalidation(iommu) ) + { + flush->context = vtd_flush_context_reg; + flush->iotlb = vtd_flush_iotlb_reg; + } + else + { + flush->context = vtd_flush_context_noop; + flush->iotlb = vtd_flush_iotlb_noop; + } }
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