From b8038beeeba1d14e3c843ba4de0f281c4595344c Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 21 Apr 2008 10:33:40 +0100 Subject: [PATCH] iommu: Consolidate iommu enablement logic. Now there is only one command-line parameter for disabling IOV/VTD: "iommu"/"no-iommu". Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/svm/intr.c | 2 +- xen/arch/x86/hvm/vmx/intr.c | 2 +- xen/drivers/passthrough/amd/pci_amd_iommu.c | 107 +++++++----------- xen/drivers/passthrough/iommu.c | 20 +++- xen/drivers/passthrough/vtd/dmar.c | 21 ++-- xen/drivers/passthrough/vtd/iommu.c | 11 +- xen/drivers/passthrough/vtd/utils.c | 2 +- xen/include/asm-x86/amd-iommu.h | 1 - xen/include/asm-x86/hvm/svm/amd-iommu-proto.h | 5 - xen/include/xen/iommu.h | 3 +- 10 files changed, 76 insertions(+), 98 deletions(-) diff --git a/xen/arch/x86/hvm/svm/intr.c b/xen/arch/x86/hvm/svm/intr.c index 17a9c3bc7b..4b3dcd33ad 100644 --- a/xen/arch/x86/hvm/svm/intr.c +++ b/xen/arch/x86/hvm/svm/intr.c @@ -102,7 +102,7 @@ static void svm_dirq_assist(struct vcpu *v) struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci; struct dev_intx_gsi_link *digl; - if ( !amd_iommu_enabled || (v->vcpu_id != 0) || (hvm_irq_dpci == NULL) ) + if ( !iommu_enabled || (v->vcpu_id != 0) || (hvm_irq_dpci == NULL) ) return; for ( irq = find_first_bit(hvm_irq_dpci->dirq_mask, NR_IRQS); diff --git a/xen/arch/x86/hvm/vmx/intr.c b/xen/arch/x86/hvm/vmx/intr.c index a212310d75..dc47430a63 100644 --- a/xen/arch/x86/hvm/vmx/intr.c +++ b/xen/arch/x86/hvm/vmx/intr.c @@ -111,7 +111,7 @@ static void vmx_dirq_assist(struct vcpu *v) struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci; struct dev_intx_gsi_link *digl; - if ( !vtd_enabled || (v->vcpu_id != 0) || (hvm_irq_dpci == NULL) ) + if ( !iommu_enabled || (v->vcpu_id != 0) || (hvm_irq_dpci == NULL) ) return; for ( irq = find_first_bit(hvm_irq_dpci->dirq_mask, NR_IRQS); diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c index 08d46e37e7..ab2b86e20d 100644 --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c @@ -30,16 +30,10 @@ struct list_head amd_iommu_head; long amd_iommu_poll_comp_wait = COMPLETION_WAIT_DEFAULT_POLLING_COUNT; static long amd_iommu_cmd_buffer_entries = IOMMU_CMD_BUFFER_DEFAULT_ENTRIES; static long amd_iommu_event_log_entries = IOMMU_EVENT_LOG_DEFAULT_ENTRIES; -int nr_amd_iommus = 0; +int nr_amd_iommus; -unsigned short ivrs_bdf_entries = 0; -struct ivrs_mappings *ivrs_mappings = NULL; - -/* will set if amd-iommu HW is found */ -int amd_iommu_enabled = 0; - -static int enable_amd_iommu = 0; -boolean_param("enable_amd_iov", enable_amd_iommu); +unsigned short ivrs_bdf_entries; +struct ivrs_mappings *ivrs_mappings; static void deallocate_domain_page_tables(struct hvm_iommu *hd) { @@ -78,24 +72,6 @@ static void __init deallocate_iommu_resources(struct amd_iommu *iommu) deallocate_iommu_table_struct(&iommu->event_log); } -static void __init detect_cleanup(void) -{ - struct amd_iommu *iommu, *next; - - list_for_each_entry_safe ( iommu, next, &amd_iommu_head, list ) - { - list_del(&iommu->list); - deallocate_iommu_resources(iommu); - xfree(iommu); - } - - if ( ivrs_mappings ) - { - xfree(ivrs_mappings); - ivrs_mappings = NULL; - } -} - static int __init allocate_iommu_table_struct(struct table_struct *table, const char *name) { @@ -246,8 +222,6 @@ static int __init amd_iommu_init(void) nr_amd_iommus++; } - amd_iommu_enabled = 1; - return 0; error_out: @@ -277,7 +251,7 @@ struct amd_iommu *find_iommu_for_device(int bus, int devfn) return NULL; } -void amd_iommu_setup_domain_device( +static void amd_iommu_setup_domain_device( struct domain *domain, struct amd_iommu *iommu, int bdf) { void *dte; @@ -316,7 +290,7 @@ void amd_iommu_setup_domain_device( } } -void __init amd_iommu_setup_dom0_devices(void) +static void __init amd_iommu_setup_dom0_devices(void) { struct hvm_iommu *hd = domain_hvm_iommu(dom0); struct amd_iommu *iommu; @@ -358,13 +332,7 @@ int amd_iov_detect(void) { unsigned long i; int last_bus; - struct amd_iommu *iommu; - - if ( !enable_amd_iommu ) - { - printk("AMD_IOV: Disabled.\n"); - return 0; - } + struct amd_iommu *iommu, *next; INIT_LIST_HEAD(&amd_iommu_head); @@ -377,29 +345,26 @@ int amd_iov_detect(void) if ( !iommu_found() ) { printk("AMD_IOV: IOMMU not found!\n"); - return 0; + goto error_out; } - else + + /* allocate 'ivrs mappings' table */ + /* note: the table has entries to accomodate all IOMMUs */ + last_bus = 0; + for_each_amd_iommu ( iommu ) + if ( iommu->last_downstream_bus > last_bus ) + last_bus = iommu->last_downstream_bus; + + ivrs_bdf_entries = (last_bus + 1) * + IOMMU_DEV_TABLE_ENTRIES_PER_BUS; + ivrs_mappings = xmalloc_array( struct ivrs_mappings, ivrs_bdf_entries); + if ( ivrs_mappings == NULL ) { - /* allocate 'ivrs mappings' table */ - /* note: the table has entries to accomodate all IOMMUs */ - last_bus = 0; - for_each_amd_iommu ( iommu ) - if ( iommu->last_downstream_bus > last_bus ) - last_bus = iommu->last_downstream_bus; - - ivrs_bdf_entries = (last_bus + 1) * - IOMMU_DEV_TABLE_ENTRIES_PER_BUS; - ivrs_mappings = xmalloc_array( struct ivrs_mappings, ivrs_bdf_entries); - - if ( !ivrs_mappings ) - { - amd_iov_error("Error allocating IVRS DevMappings table\n"); - goto error_out; - } - memset(ivrs_mappings, 0, - ivrs_bdf_entries * sizeof(struct ivrs_mappings)); + amd_iov_error("Error allocating IVRS DevMappings table\n"); + goto error_out; } + memset(ivrs_mappings, 0, + ivrs_bdf_entries * sizeof(struct ivrs_mappings)); if ( amd_iommu_init() != 0 ) { @@ -418,9 +383,20 @@ int amd_iov_detect(void) return 0; error_out: - detect_cleanup(); - return -ENODEV; + list_for_each_entry_safe ( iommu, next, &amd_iommu_head, list ) + { + list_del(&iommu->list); + deallocate_iommu_resources(iommu); + xfree(iommu); + } + + if ( ivrs_mappings ) + { + xfree(ivrs_mappings); + ivrs_mappings = NULL; + } + return -ENODEV; } static int allocate_domain_resources(struct hvm_iommu *hd) @@ -464,7 +440,7 @@ static int get_paging_mode(unsigned long entries) return level; } -int amd_iommu_domain_init(struct domain *domain) +static int amd_iommu_domain_init(struct domain *domain) { struct hvm_iommu *hd = domain_hvm_iommu(domain); @@ -561,7 +537,7 @@ static int reassign_device( struct domain *source, struct domain *target, return 0; } -int amd_iommu_assign_device(struct domain *d, u8 bus, u8 devfn) +static int amd_iommu_assign_device(struct domain *d, u8 bus, u8 devfn) { int bdf = (bus << 8) | devfn; int req_id = ivrs_mappings[bdf].dte_requestor_id; @@ -647,16 +623,13 @@ static void deallocate_iommu_page_tables(struct domain *d) hd ->root_table = NULL; } -void amd_iommu_domain_destroy(struct domain *d) +static void amd_iommu_domain_destroy(struct domain *d) { - if ( !amd_iommu_enabled ) - return; - deallocate_iommu_page_tables(d); release_domain_devices(d); } -void amd_iommu_return_device( +static void amd_iommu_return_device( struct domain *s, struct domain *t, u8 bus, u8 devfn) { pdev_flr(bus, devfn); diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c index 51a6e20b44..9fbd41a584 100644 --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -21,6 +21,9 @@ extern struct iommu_ops amd_iommu_ops; int intel_vtd_setup(void); int amd_iov_detect(void); +int iommu_enabled = 1; +boolean_param("iommu", iommu_enabled); + int iommu_domain_init(struct domain *domain) { struct hvm_iommu *hd = domain_hvm_iommu(domain); @@ -139,13 +142,24 @@ void deassign_device(struct domain *d, u8 bus, u8 devfn) int iommu_setup(void) { + int rc = -ENODEV; + + if ( !iommu_enabled ) + goto out; + switch ( boot_cpu_data.x86_vendor ) { case X86_VENDOR_INTEL: - return intel_vtd_setup(); + rc = intel_vtd_setup(); + break; case X86_VENDOR_AMD: - return amd_iov_detect(); + rc = amd_iov_detect(); + break; } - return 0; + iommu_enabled = (rc == 0); + + out: + printk("I/O virtualisation %sabled\n", iommu_enabled ? "en" : "dis"); + return rc; } diff --git a/xen/drivers/passthrough/vtd/dmar.c b/xen/drivers/passthrough/vtd/dmar.c index 9498914044..6ba260b37e 100644 --- a/xen/drivers/passthrough/vtd/dmar.c +++ b/xen/drivers/passthrough/vtd/dmar.c @@ -30,8 +30,7 @@ #include "dmar.h" #include "../pci_regs.h" -int vtd_enabled; -boolean_param("vtd", vtd_enabled); +int vtd_enabled = 1; #undef PREFIX #define PREFIX VTDPREFIX "ACPI DMAR:" @@ -604,22 +603,24 @@ int acpi_dmar_init(void) { int rc; - if ( !vtd_enabled ) - return -ENODEV; + rc = -ENODEV; + if ( !iommu_enabled ) + goto fail; if ( (rc = vtd_hw_check()) != 0 ) - return rc; + goto fail; acpi_table_parse(ACPI_DMAR, acpi_parse_dmar); + rc = -ENODEV; if ( list_empty(&acpi_drhd_units) ) - { - dprintk(XENLOG_ERR VTDPREFIX, "No DMAR devices found\n"); - vtd_enabled = 0; - return -ENODEV; - } + goto fail; printk("Intel VT-d has been enabled\n"); return 0; + + fail: + vtd_enabled = 0; + return -ENODEV; } diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index d7498e4d35..9396959dc1 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -1111,7 +1111,7 @@ static void free_iommu(struct iommu *iommu) agaw = 64; \ agaw; }) -int intel_iommu_domain_init(struct domain *domain) +static int intel_iommu_domain_init(struct domain *domain) { struct hvm_iommu *hd = domain_hvm_iommu(domain); struct iommu *iommu = NULL; @@ -1120,9 +1120,6 @@ int intel_iommu_domain_init(struct domain *domain) unsigned long sagaw; struct acpi_drhd_unit *drhd; - if ( !vtd_enabled || list_empty(&acpi_drhd_units) ) - return 0; - for_each_drhd_unit ( drhd ) iommu = drhd->iommu ? : iommu_alloc(drhd); @@ -1911,7 +1908,7 @@ int intel_vtd_setup(void) unsigned long i; if ( !vtd_enabled ) - return 0; + return -ENODEV; spin_lock_init(&domid_bitmap_lock); INIT_LIST_HEAD(&hd->pdev_list); @@ -1946,13 +1943,13 @@ int intel_vtd_setup(void) return 0; error: - printk("iommu_setup() failed\n"); for_each_drhd_unit ( drhd ) { iommu = drhd->iommu; free_iommu(iommu); } - return -EIO; + vtd_enabled = 0; + return -ENOMEM; } /* diff --git a/xen/drivers/passthrough/vtd/utils.c b/xen/drivers/passthrough/vtd/utils.c index 3c33a2c300..47c6b7b83c 100644 --- a/xen/drivers/passthrough/vtd/utils.c +++ b/xen/drivers/passthrough/vtd/utils.c @@ -60,10 +60,10 @@ int vtd_hw_check(void) dprintk(XENLOG_WARNING VTDPREFIX, "*** vendor = %x device = %x revision = %x\n", vendor, device, revision); - vtd_enabled = 0; return -ENODEV; } } + return 0; } diff --git a/xen/include/asm-x86/amd-iommu.h b/xen/include/asm-x86/amd-iommu.h index f896088f8d..8acfb55189 100644 --- a/xen/include/asm-x86/amd-iommu.h +++ b/xen/include/asm-x86/amd-iommu.h @@ -28,7 +28,6 @@ #define iommu_found() (!list_empty(&amd_iommu_head)) -extern int amd_iommu_enabled; extern struct list_head amd_iommu_head; extern int __init amd_iov_detect(void); diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h index 646ab7047e..0886776cea 100644 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h @@ -84,11 +84,6 @@ void invalidate_dev_table_entry(struct amd_iommu *iommu, int send_iommu_command(struct amd_iommu *iommu, u32 cmd[]); void flush_command_buffer(struct amd_iommu *iommu); -/* iommu domain funtions */ -int amd_iommu_domain_init(struct domain *domain); -void amd_iommu_setup_domain_device(struct domain *domain, - struct amd_iommu *iommu, int bdf); - /* find iommu for bdf */ struct amd_iommu *find_iommu_for_device(int bus, int devfn); diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h index bde167694e..7ad55190fa 100644 --- a/xen/include/xen/iommu.h +++ b/xen/include/xen/iommu.h @@ -27,9 +27,8 @@ #include extern int vtd_enabled; -extern int amd_iommu_enabled; +extern int iommu_enabled; -#define iommu_enabled ( amd_iommu_enabled || vtd_enabled ) #define domain_hvm_iommu(d) (&d->arch.hvm_domain.hvm_iommu) #define domain_vmx_iommu(d) (&d->arch.hvm_domain.hvm_iommu.vmx_iommu) -- 2.39.5