From patchwork Thu Sep 19 13:22:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 11152375 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0A2B176 for ; Thu, 19 Sep 2019 13:23:50 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E2AA1217D6 for ; Thu, 19 Sep 2019 13:23:49 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E2AA1217D6 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iAwNw-0007hF-CX; Thu, 19 Sep 2019 13:22:12 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iAwNv-0007gy-Bs for xen-devel@lists.xenproject.org; Thu, 19 Sep 2019 13:22:11 +0000 X-Inumbo-ID: 7bbfc724-dae0-11e9-b299-bc764e2007e4 Received: from mx1.suse.de (unknown [195.135.220.15]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 7bbfc724-dae0-11e9-b299-bc764e2007e4; Thu, 19 Sep 2019 13:22:10 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 456C1AF1D; Thu, 19 Sep 2019 13:22:09 +0000 (UTC) From: Jan Beulich To: "xen-devel@lists.xenproject.org" References: Message-ID: <06a35251-013f-d215-d70c-70a4c98ac86e@suse.com> Date: Thu, 19 Sep 2019 15:22:17 +0200 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.9.0 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US Subject: [Xen-devel] [PATCH v6 2/8] AMD/IOMMU: make phantom functions share interrupt remapping tables X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Andrew Cooper , Suravee Suthikulpanit Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Rather than duplicating entries in amd_iommu_msi_msg_update_ire(), share the tables. This mainly requires some care while freeing them, to avoid freeing memory blocks twice. Signed-off-by: Jan Beulich Acked-by: Andrew Cooper Reviewed-by: Paul Durrant --- v5: New. --- xen/drivers/passthrough/amd/iommu_init.c | 43 +++++++++++++++--------- xen/drivers/passthrough/amd/iommu_intr.c | 45 +++++++++++++------------- xen/drivers/passthrough/amd/pci_amd_iommu.c | 2 - xen/include/asm-x86/amd-iommu.h | 2 - xen/include/asm-x86/hvm/svm/amd-iommu-proto.h | 2 - 5 files changed, 53 insertions(+), 41 deletions(-) --- a/xen/drivers/passthrough/amd/iommu_init.c +++ b/xen/drivers/passthrough/amd/iommu_init.c @@ -1111,7 +1111,7 @@ static void __init amd_iommu_init_cleanu amd_iommu_free_intremap_table(list_first_entry(&amd_iommu_head, struct amd_iommu, list), - NULL); + NULL, 0); /* free amd iommu list */ list_for_each_entry_safe ( iommu, next, &amd_iommu_head, list ) @@ -1176,7 +1176,7 @@ int iterate_ivrs_mappings(int (*handler) } int iterate_ivrs_entries(int (*handler)(const struct amd_iommu *, - struct ivrs_mappings *)) + struct ivrs_mappings *, uint16_t bdf)) { u16 seg = 0; int rc = 0; @@ -1193,7 +1193,7 @@ int iterate_ivrs_entries(int (*handler)( const struct amd_iommu *iommu = map[bdf].iommu; if ( iommu && map[bdf].dte_requestor_id == bdf ) - rc = handler(iommu, &map[bdf]); + rc = handler(iommu, &map[bdf], bdf); } } while ( !rc && ++seg ); @@ -1286,20 +1286,29 @@ static int __init amd_iommu_setup_device if ( pdev ) { - unsigned int req_id = bdf; - - do { - ivrs_mappings[req_id].intremap_table = - amd_iommu_alloc_intremap_table( - ivrs_mappings[bdf].iommu, - &ivrs_mappings[req_id].intremap_inuse); - if ( !ivrs_mappings[req_id].intremap_table ) - return -ENOMEM; - - if ( !pdev->phantom_stride ) - break; - req_id += pdev->phantom_stride; - } while ( PCI_SLOT(req_id) == pdev->sbdf.dev ); + ivrs_mappings[bdf].intremap_table = + amd_iommu_alloc_intremap_table( + ivrs_mappings[bdf].iommu, + &ivrs_mappings[bdf].intremap_inuse); + if ( !ivrs_mappings[bdf].intremap_table ) + return -ENOMEM; + + if ( pdev->phantom_stride ) + { + unsigned int req_id = bdf; + + for ( ; ; ) + { + req_id += pdev->phantom_stride; + if ( PCI_SLOT(req_id) != pdev->sbdf.dev ) + break; + + ivrs_mappings[req_id].intremap_table = + ivrs_mappings[bdf].intremap_table; + ivrs_mappings[req_id].intremap_inuse = + ivrs_mappings[bdf].intremap_inuse; + } + } } amd_iommu_set_intremap_table( --- a/xen/drivers/passthrough/amd/iommu_intr.c +++ b/xen/drivers/passthrough/amd/iommu_intr.c @@ -711,33 +711,20 @@ int amd_iommu_msi_msg_update_ire( if ( msi_desc->remap_index >= 0 && !msg ) { - do { - update_intremap_entry_from_msi_msg(iommu, bdf, nr, - &msi_desc->remap_index, - NULL, NULL); - if ( !pdev || !pdev->phantom_stride ) - break; - bdf += pdev->phantom_stride; - } while ( PCI_SLOT(bdf) == PCI_SLOT(pdev->devfn) ); + update_intremap_entry_from_msi_msg(iommu, bdf, nr, + &msi_desc->remap_index, + NULL, NULL); for ( i = 0; i < nr; ++i ) msi_desc[i].remap_index = -1; - if ( pdev ) - bdf = PCI_BDF2(pdev->bus, pdev->devfn); } if ( !msg ) return 0; - do { - rc = update_intremap_entry_from_msi_msg(iommu, bdf, nr, - &msi_desc->remap_index, - msg, &data); - if ( rc || !pdev || !pdev->phantom_stride ) - break; - bdf += pdev->phantom_stride; - } while ( PCI_SLOT(bdf) == PCI_SLOT(pdev->devfn) ); - + rc = update_intremap_entry_from_msi_msg(iommu, bdf, nr, + &msi_desc->remap_index, + msg, &data); if ( !rc ) { for ( i = 1; i < nr; ++i ) @@ -790,12 +777,27 @@ void amd_iommu_read_msi_from_ire( } int amd_iommu_free_intremap_table( - const struct amd_iommu *iommu, struct ivrs_mappings *ivrs_mapping) + const struct amd_iommu *iommu, struct ivrs_mappings *ivrs_mapping, + uint16_t bdf) { void **tblp; if ( ivrs_mapping ) { + unsigned int i; + + /* + * PCI device phantom functions use the same tables as their "base" + * function: Look ahead to zap the pointers. + */ + for ( i = 1; PCI_FUNC(bdf + i) && bdf + i < ivrs_bdf_entries; ++i ) + if ( ivrs_mapping[i].intremap_table == + ivrs_mapping->intremap_table ) + { + ivrs_mapping[i].intremap_table = NULL; + ivrs_mapping[i].intremap_inuse = NULL; + } + XFREE(ivrs_mapping->intremap_inuse); tblp = &ivrs_mapping->intremap_table; } @@ -934,7 +936,8 @@ static void dump_intremap_table(const st } static int dump_intremap_mapping(const struct amd_iommu *iommu, - struct ivrs_mappings *ivrs_mapping) + struct ivrs_mappings *ivrs_mapping, + uint16_t unused) { unsigned long flags; --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c @@ -519,7 +519,7 @@ static int amd_iommu_remove_device(u8 de if ( amd_iommu_perdev_intremap && ivrs_mappings[bdf].dte_requestor_id == bdf && ivrs_mappings[bdf].intremap_table ) - amd_iommu_free_intremap_table(iommu, &ivrs_mappings[bdf]); + amd_iommu_free_intremap_table(iommu, &ivrs_mappings[bdf], bdf); return 0; } --- a/xen/include/asm-x86/amd-iommu.h +++ b/xen/include/asm-x86/amd-iommu.h @@ -131,7 +131,7 @@ extern u8 ivhd_type; struct ivrs_mappings *get_ivrs_mappings(u16 seg); int iterate_ivrs_mappings(int (*)(u16 seg, struct ivrs_mappings *)); int iterate_ivrs_entries(int (*)(const struct amd_iommu *, - struct ivrs_mappings *)); + struct ivrs_mappings *, uint16_t)); /* iommu tables in guest space */ struct mmio_reg { --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h @@ -101,7 +101,7 @@ int amd_iommu_setup_ioapic_remapping(voi void *amd_iommu_alloc_intremap_table( const struct amd_iommu *, unsigned long **); int amd_iommu_free_intremap_table( - const struct amd_iommu *, struct ivrs_mappings *); + const struct amd_iommu *, struct ivrs_mappings *, uint16_t); void amd_iommu_ioapic_update_ire( unsigned int apic, unsigned int reg, unsigned int value); unsigned int amd_iommu_read_ioapic_from_ire(