From patchwork Wed Mar 15 05:11:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chao Gao X-Patchwork-Id: 9625483 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 91E7B60424 for ; Wed, 15 Mar 2017 12:16:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 870B628609 for ; Wed, 15 Mar 2017 12:16:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7A23728616; Wed, 15 Mar 2017 12:16:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.5 required=2.0 tests=BAYES_00, DATE_IN_PAST_06_12, DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 8F8BD28615 for ; Wed, 15 Mar 2017 12:16:48 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1co7oQ-00049c-Lt; Wed, 15 Mar 2017 12:13:54 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1co7oP-00049V-Lq for xen-devel@lists.xen.org; Wed, 15 Mar 2017 12:13:53 +0000 Received: from [85.158.139.211] by server-5.bemta-5.messagelabs.com id 09/06-29481-10039C85; Wed, 15 Mar 2017 12:13:53 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrBLMWRWlGSWpSXmKPExsXS1tbhqMtgcDL CYPFHWYslHxezODB6HN39mymAMYo1My8pvyKBNWPZqZeMBZfdKu7e3sPYwHjJrIuRi4NF4BaT xPoTL1lBHCGBaYwS11oPADmcHBICvBJHls2AsgMk+m4cBbI5gIrKJdYckQEJswkoS1z82ssGY osISEtc+3yZEWQOs8BTJol3276wgNQLC6RKdL9LAKlhEVCVeLFuLguIzSvgKPHs8Bmo8QoSUx 6+ZwYp5xRwktjwtg4kLARUsmvvDNYJjHwLGBlWMaoXpxaVpRbpGuolFWWmZ5TkJmbm6BoamOr lphYXJ6an5iQmFesl5+duYgSGSD0DA+MOxqZe50OMkhxMSqK8KoInIoT4kvJTKjMSizPii0pz UosPMcpwcChJ8D49BJQTLEpNT61Iy8wBBitMWoKDR0mEtwgkzVtckJhbnJkOkTrFqCglzpsFk hAASWSU5sG1wSLkEqOslDAvIwMDgxBPQWpRbmYJqvwrRnEORiVh3mqQKTyZeSVw018BLWYCWp z48wjI4pJEhJRUA6N6uIdd2eGk5n0MDq3vzngo7nb1WXhOzGvF8nMiMa2tDhyRn9M/LKz4+/K 396V4GUdnTSHtxObw7xFnFvhaXbr7lmNS+h3NWS8ntJT0RxV5zX0tGxtvWMZwf21S3zM/GyHJ K+mnb81Qt15QtKqntdX5nd3FbTeVQvyLlCeGaWQcivp3sSfKUYmlOCPRUIu5qDgRAL4chtmLA gAA X-Env-Sender: chao.gao@intel.com X-Msg-Ref: server-13.tower-206.messagelabs.com!1489580028!74059212!2 X-Originating-IP: [134.134.136.65] X-SpamReason: No, hits=0.8 required=7.0 tests=DATE_IN_PAST_06_12 X-StarScan-Received: X-StarScan-Version: 9.2.3; banners=-,-,- X-VirusChecked: Checked Received: (qmail 12155 invoked from network); 15 Mar 2017 12:13:51 -0000 Received: from mga03.intel.com (HELO mga03.intel.com) (134.134.136.65) by server-13.tower-206.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 15 Mar 2017 12:13:51 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=intel.com; i=@intel.com; q=dns/txt; s=intel; t=1489580031; x=1521116031; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=Q6qQ/dU8T0MwxcnbSGZXiJS46pY4KDV3TriMvjKqyVw=; b=J+p6UAb25aHFvBHp5YiULjnNw2vPQemx5mFA4E4TcpHhDO2HgZruSR2C 0/60h4fybk1VFamQfj6PPcq1vAFt9Q==; Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 Mar 2017 05:13:51 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos; i="5.36,168,1486454400"; d="scan'208"; a="1108706693" Received: from skl-2s3.sh.intel.com ([10.239.48.35]) by orsmga001.jf.intel.com with ESMTP; 15 Mar 2017 05:13:49 -0700 From: Chao Gao To: xen-devel@lists.xen.org Date: Wed, 15 Mar 2017 13:11:17 +0800 Message-Id: <1489554682-6126-2-git-send-email-chao.gao@intel.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1489554682-6126-1-git-send-email-chao.gao@intel.com> References: <1489554682-6126-1-git-send-email-chao.gao@intel.com> Cc: Kevin Tian , Feng Wu , Jun Nakajima , George Dunlap , Andrew Cooper , Dario Faggioli , Jan Beulich , Chao Gao Subject: [Xen-devel] [PATCH v10 1/6] VT-d: Introduce new fields in msi_desc to track binding with guest interrupt X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Currently, msi_msg_to_remap_entry is buggy when the live IRTE is in posted format. Straightforwardly, we can let caller specify which format of IRTE they want update to. But the problem is current callers are not aware of the binding with guest interrupt. Making all callers be aware of the binding with guest interrupt will cause a far more complicated change. Also some callings happen in interrupt context where they can't acquire d->event_lock to read struct hvm_pirq_dpci. This patch introduces two new fields in msi_desc to track binding with a guest interrupt such that msi_msg_to_remap_entry() can get the binding and update IRTE accordingly. After that change, pi_update_irte() can utilize msi_msg_to_remap_entry() to update IRTE to posted format. Signed-off-by: Feng Wu Signed-off-by: Chao Gao --- v10: - Newly added. xen/arch/x86/msi.c | 1 + xen/drivers/passthrough/vtd/intremap.c | 148 +++++++-------------------------- xen/include/asm-x86/msi.h | 2 + 3 files changed, 34 insertions(+), 117 deletions(-) diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c index a868007..3374cd4 100644 --- a/xen/arch/x86/msi.c +++ b/xen/arch/x86/msi.c @@ -578,6 +578,7 @@ static struct msi_desc *alloc_msi_entry(unsigned int nr) entry[nr].dev = NULL; entry[nr].irq = -1; entry[nr].remap_index = -1; + entry[nr].pi_desc = NULL; } return entry; diff --git a/xen/drivers/passthrough/vtd/intremap.c b/xen/drivers/passthrough/vtd/intremap.c index bfd468b..6202ece 100644 --- a/xen/drivers/passthrough/vtd/intremap.c +++ b/xen/drivers/passthrough/vtd/intremap.c @@ -552,11 +552,12 @@ static int msi_msg_to_remap_entry( struct msi_desc *msi_desc, struct msi_msg *msg) { struct iremap_entry *iremap_entry = NULL, *iremap_entries; - struct iremap_entry new_ire; + struct iremap_entry new_ire = {{0}}; struct msi_msg_remap_entry *remap_rte; unsigned int index, i, nr = 1; unsigned long flags; struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu); + const struct pi_desc *pi_desc = msi_desc->pi_desc; if ( msi_desc->msi_attrib.type == PCI_CAP_ID_MSI ) nr = msi_desc->msi.nvec; @@ -595,33 +596,35 @@ static int msi_msg_to_remap_entry( GET_IREMAP_ENTRY(ir_ctrl->iremap_maddr, index, iremap_entries, iremap_entry); - memcpy(&new_ire, iremap_entry, sizeof(struct iremap_entry)); - - /* Set interrupt remapping table entry */ - new_ire.remap.fpd = 0; - new_ire.remap.dm = (msg->address_lo >> MSI_ADDR_DESTMODE_SHIFT) & 0x1; - new_ire.remap.tm = (msg->data >> MSI_DATA_TRIGGER_SHIFT) & 0x1; - new_ire.remap.dlm = (msg->data >> MSI_DATA_DELIVERY_MODE_SHIFT) & 0x1; - /* Hardware require RH = 1 for LPR delivery mode */ - new_ire.remap.rh = (new_ire.remap.dlm == dest_LowestPrio); - new_ire.remap.avail = 0; - new_ire.remap.res_1 = 0; - new_ire.remap.vector = (msg->data >> MSI_DATA_VECTOR_SHIFT) & - MSI_DATA_VECTOR_MASK; - new_ire.remap.res_2 = 0; - if ( x2apic_enabled ) - new_ire.remap.dst = msg->dest32; + if ( !pi_desc ) + { + new_ire.remap.dm = msg->address_lo >> MSI_ADDR_DESTMODE_SHIFT; + new_ire.remap.tm = msg->data >> MSI_DATA_TRIGGER_SHIFT; + new_ire.remap.dlm = msg->data >> MSI_DATA_DELIVERY_MODE_SHIFT; + /* Hardware require RH = 1 for LPR delivery mode */ + new_ire.remap.rh = (new_ire.remap.dlm == dest_LowestPrio); + new_ire.remap.vector = (msg->data >> MSI_DATA_VECTOR_SHIFT) & + MSI_DATA_VECTOR_MASK; + if ( x2apic_enabled ) + new_ire.remap.dst = msg->dest32; + else + new_ire.remap.dst = + MASK_EXTR(msg->address_lo, MSI_ADDR_DEST_ID_MASK) << 8; + new_ire.remap.p = 1; + } else - new_ire.remap.dst = ((msg->address_lo >> MSI_ADDR_DEST_ID_SHIFT) - & 0xff) << 8; + { + new_ire.post.im = 1; + new_ire.post.vector = msi_desc->gvec; + new_ire.post.pda_l = virt_to_maddr(pi_desc) >> (32 - PDA_LOW_BIT); + new_ire.post.pda_h = virt_to_maddr(pi_desc) >> 32; + new_ire.post.p = 1; + } if ( pdev ) set_msi_source_id(pdev, &new_ire); else set_hpet_source_id(msi_desc->hpet_id, &new_ire); - new_ire.remap.res_3 = 0; - new_ire.remap.res_4 = 0; - new_ire.remap.p = 1; /* finally, set present bit */ /* now construct new MSI/MSI-X rte entry */ remap_rte = (struct msi_msg_remap_entry *)msg; @@ -902,42 +905,6 @@ void iommu_disable_x2apic_IR(void) disable_qinval(drhd->iommu); } -static void setup_posted_irte( - struct iremap_entry *new_ire, const struct iremap_entry *old_ire, - const struct pi_desc *pi_desc, const uint8_t gvec) -{ - memset(new_ire, 0, sizeof(*new_ire)); - - /* - * 'im' filed decides whether the irte is in posted format (with value 1) - * or remapped format (with value 0), if the old irte is in remapped format, - * we copy things from remapped part in 'struct iremap_entry', otherwise, - * we copy from posted part. - */ - if ( !old_ire->remap.im ) - { - new_ire->post.p = old_ire->remap.p; - new_ire->post.fpd = old_ire->remap.fpd; - new_ire->post.sid = old_ire->remap.sid; - new_ire->post.sq = old_ire->remap.sq; - new_ire->post.svt = old_ire->remap.svt; - } - else - { - new_ire->post.p = old_ire->post.p; - new_ire->post.fpd = old_ire->post.fpd; - new_ire->post.sid = old_ire->post.sid; - new_ire->post.sq = old_ire->post.sq; - new_ire->post.svt = old_ire->post.svt; - new_ire->post.urg = old_ire->post.urg; - } - - new_ire->post.im = 1; - new_ire->post.vector = gvec; - new_ire->post.pda_l = virt_to_maddr(pi_desc) >> (32 - PDA_LOW_BIT); - new_ire->post.pda_h = virt_to_maddr(pi_desc) >> 32; -} - /* * This function is used to update the IRTE for posted-interrupt * when guest changes MSI/MSI-X information. @@ -946,17 +913,9 @@ int pi_update_irte(const struct vcpu *v, const struct pirq *pirq, const uint8_t gvec) { struct irq_desc *desc; - const struct msi_desc *msi_desc; - int remap_index; - int rc = 0; - const struct pci_dev *pci_dev; - const struct acpi_drhd_unit *drhd; - struct iommu *iommu; - struct ir_ctrl *ir_ctrl; - struct iremap_entry *iremap_entries = NULL, *p = NULL; - struct iremap_entry new_ire, old_ire; + struct msi_desc *msi_desc; const struct pi_desc *pi_desc = &v->arch.hvm_vmx.pi_desc; - __uint128_t ret; + int rc; desc = pirq_spin_lock_irq_desc(pirq, NULL); if ( !desc ) @@ -968,59 +927,14 @@ int pi_update_irte(const struct vcpu *v, const struct pirq *pirq, rc = -ENODEV; goto unlock_out; } - - pci_dev = msi_desc->dev; - if ( !pci_dev ) - { - rc = -ENODEV; - goto unlock_out; - } - - remap_index = msi_desc->remap_index; + msi_desc->pi_desc = pi_desc; + msi_desc->gvec = gvec; spin_unlock_irq(&desc->lock); ASSERT(pcidevs_locked()); - - /* - * FIXME: For performance reasons we should store the 'iommu' pointer in - * 'struct msi_desc' in some other place, so we don't need to waste - * time searching it here. - */ - drhd = acpi_find_matched_drhd_unit(pci_dev); - if ( !drhd ) - return -ENODEV; - - iommu = drhd->iommu; - ir_ctrl = iommu_ir_ctrl(iommu); - if ( !ir_ctrl ) - return -ENODEV; - - spin_lock_irq(&ir_ctrl->iremap_lock); - - GET_IREMAP_ENTRY(ir_ctrl->iremap_maddr, remap_index, iremap_entries, p); - - old_ire = *p; - - /* Setup/Update interrupt remapping table entry. */ - setup_posted_irte(&new_ire, &old_ire, pi_desc, gvec); - ret = cmpxchg16b(p, &old_ire, &new_ire); - - /* - * In the above, we use cmpxchg16 to atomically update the 128-bit IRTE, - * and the hardware cannot update the IRTE behind us, so the return value - * of cmpxchg16 should be the same as old_ire. This ASSERT validate it. - */ - ASSERT(ret == old_ire.val); - - iommu_flush_cache_entry(p, sizeof(*p)); - iommu_flush_iec_index(iommu, 0, remap_index); - - unmap_vtd_domain_page(iremap_entries); - - spin_unlock_irq(&ir_ctrl->iremap_lock); - - return 0; + rc = iommu_update_ire_from_msi(msi_desc, &msi_desc->msg); + return rc; unlock_out: spin_unlock_irq(&desc->lock); diff --git a/xen/include/asm-x86/msi.h b/xen/include/asm-x86/msi.h index 9c02945..3286692 100644 --- a/xen/include/asm-x86/msi.h +++ b/xen/include/asm-x86/msi.h @@ -118,6 +118,8 @@ struct msi_desc { struct msi_msg msg; /* Last set MSI message */ int remap_index; /* index in interrupt remapping table */ + const void *pi_desc; /* PDA, indicates msi is delivered via VT-d PI */ + uint8_t gvec; /* guest vector. valid when pi_desc isn't NULL */ }; /*