From patchwork Thu Apr 28 14:52:53 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 8971451 Return-Path: X-Original-To: patchwork-xen-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 04909BF29F for ; Thu, 28 Apr 2016 14:55:12 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id F39512017E for ; Thu, 28 Apr 2016 14:55:10 +0000 (UTC) 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.kernel.org (Postfix) with ESMTPS id CF22D2015A for ; Thu, 28 Apr 2016 14:55:09 +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 1avnJI-0003NF-8S; Thu, 28 Apr 2016 14:52:56 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1avnJH-0003N7-3R for xen-devel@lists.xenproject.org; Thu, 28 Apr 2016 14:52:55 +0000 Received: from [85.158.137.68] by server-5.bemta-3.messagelabs.com id A7/54-03651-6C322275; Thu, 28 Apr 2016 14:52:54 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrMIsWRWlGSWpSXmKPExsXS6fjDS/eoslK 4wfZecYvvWyYzOTB6HP5whSWAMYo1My8pvyKBNeNY2yPWgvdOFYtvpDQwLtPvYuTkEBLIk9i0 ZQI7iM0rYCex+eYXFhBbQsBQYt/8VWwgNouAqsSxjZMZQWw2AXWJtmfbWbsYOThEBAwkzh1NA gkzC9RIzGqfB1YiLGAs0TnnNAtICa+AoMTfHcIQJXYS/79cZZnAyDULITMLSQbC1pJ4+OsWlK 0tsWzha2aQcmYBaYnl/zggwk4SD/YeZEZVAmL7Sizv6mFawMixilG9OLWoLLVI11IvqSgzPaM kNzEzR9fQwFgvN7W4ODE9NScxqVgvOT93EyMw8OoZGBh3ML7+6XSIUZKDSUmUt+uQYrgQX1J+ SmVGYnFGfFFpTmrxIUYZDg4lCd65SkrhQoJFqempFWmZOcAYgElLcPAoifA2g6R5iwsSc4sz0 yFSpxgVpcR5DUASAiCJjNI8uDZY3F1ilJUS5mVkYGAQ4ilILcrNLEGVf8UozsGoJMzbCTKFJz OvBG76K6DFTECLBTYpgiwuSURISTUwtqm+LlwfVepvv03Kr/uK5H0vVs8N2q2v5KLrZ+y+OyN 5n86+q/MiOxaZ9W/anMU0892zhSme5ztD7c3CHvp7iYX1Mv1Mn/HJc4K+PWeitesKRxOHDslW Jadmvb8R+9uaGE28k5iUJyy3Ycp2PBRfsnExi0DZfLky6yccC8VWHIub1jj7lakSS3FGoqEWc 1FxIgCfcOwMtgIAAA== X-Env-Sender: JBeulich@suse.com X-Msg-Ref: server-14.tower-31.messagelabs.com!1461855171!37501239!1 X-Originating-IP: [137.65.248.74] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 8.34; banners=-,-,- X-VirusChecked: Checked Received: (qmail 43551 invoked from network); 28 Apr 2016 14:52:53 -0000 Received: from prv-mh.provo.novell.com (HELO prv-mh.provo.novell.com) (137.65.248.74) by server-14.tower-31.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 28 Apr 2016 14:52:53 -0000 Received: from INET-PRV-MTA by prv-mh.provo.novell.com with Novell_GroupWise; Thu, 28 Apr 2016 08:52:50 -0600 Message-Id: <57223FE502000078000E6E8D@prv-mh.provo.novell.com> X-Mailer: Novell GroupWise Internet Agent 14.2.0 Date: Thu, 28 Apr 2016 08:52:53 -0600 From: "Jan Beulich" To: "xen-devel" Mime-Version: 1.0 Cc: Andrew Cooper , Paul Durrant , Wei Liu Subject: [Xen-devel] [PATCH v2] x86/vMSI-X: also snoop REP MOVS 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: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP ... as at least certain versions of Windows use such to update the MSI-X table. However, to not overly complicate the logic for now - only EFLAGS.DF=0 is being handled, - only updates not crossing MSI-X table entry boundaries are handled. Signed-off-by: Jan Beulich Reviewed-by: Paul Durrant --- v2: Comment conditional being added to msixtbl_range(). x86/vMSI-X: also snoop REP MOVS ... as at least certain versions of Windows use such to update the MSI-X table. However, to not overly complicate the logic for now - only EFLAGS.DF=0 is being handled, - only updates not crossing MSI-X table entry boundaries are handled. Signed-off-by: Jan Beulich --- v2: Comment conditional being added to msixtbl_range(). --- a/xen/arch/x86/hvm/vmsi.c +++ b/xen/arch/x86/hvm/vmsi.c @@ -351,9 +351,10 @@ static int msixtbl_range(struct vcpu *v, ASSERT(r->type == IOREQ_TYPE_COPY); if ( r->dir == IOREQ_WRITE ) { + unsigned int size = r->size; + if ( !r->data_is_ptr ) { - unsigned int size = r->size; uint64_t data = r->data; if ( size == 8 ) @@ -366,7 +367,29 @@ static int msixtbl_range(struct vcpu *v, ((addr & (PCI_MSIX_ENTRY_SIZE - 1)) == PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET) && !(data & PCI_MSIX_VECTOR_BITMASK) ) + { v->arch.hvm_vcpu.hvm_io.msix_snoop_address = addr; + v->arch.hvm_vcpu.hvm_io.msix_snoop_gpa = 0; + } + } + else if ( (size == 4 || size == 8) && + /* Only support forward REP MOVS for now. */ + !r->df && + /* + * Only fully support accesses to a single table entry for + * now (if multiple ones get written to in one go, only the + * final one gets dealt with). + */ + r->count && r->count <= PCI_MSIX_ENTRY_SIZE / size && + !((addr + (size * r->count)) & (PCI_MSIX_ENTRY_SIZE - 1)) ) + { + BUILD_BUG_ON((PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET + 4) & + (PCI_MSIX_ENTRY_SIZE - 1)); + + v->arch.hvm_vcpu.hvm_io.msix_snoop_address = + addr + size * r->count - 4; + v->arch.hvm_vcpu.hvm_io.msix_snoop_gpa = + r->data + size * r->count - 4; } } @@ -471,6 +494,7 @@ out: for_each_vcpu ( d, v ) { if ( (v->pause_flags & VPF_blocked_in_xen) && + !v->arch.hvm_vcpu.hvm_io.msix_snoop_gpa && v->arch.hvm_vcpu.hvm_io.msix_snoop_address == (gtable + msi_desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + @@ -561,9 +585,29 @@ void msixtbl_pt_cleanup(struct domain *d void msix_write_completion(struct vcpu *v) { unsigned long ctrl_address = v->arch.hvm_vcpu.hvm_io.msix_unmask_address; + unsigned long snoop_addr = v->arch.hvm_vcpu.hvm_io.msix_snoop_address; v->arch.hvm_vcpu.hvm_io.msix_snoop_address = 0; + if ( !ctrl_address && snoop_addr && + v->arch.hvm_vcpu.hvm_io.msix_snoop_gpa ) + { + const struct msi_desc *desc; + uint32_t data; + + rcu_read_lock(&msixtbl_rcu_lock); + desc = msixtbl_addr_to_desc(msixtbl_find_entry(v, snoop_addr), + snoop_addr); + rcu_read_unlock(&msixtbl_rcu_lock); + + if ( desc && + hvm_copy_from_guest_phys(&data, + v->arch.hvm_vcpu.hvm_io.msix_snoop_gpa, + sizeof(data)) == HVMCOPY_okay && + !(data & PCI_MSIX_VECTOR_BITMASK) ) + ctrl_address = snoop_addr; + } + if ( !ctrl_address ) return; --- a/xen/include/asm-x86/hvm/vcpu.h +++ b/xen/include/asm-x86/hvm/vcpu.h @@ -86,6 +86,7 @@ struct hvm_vcpu_io { unsigned long msix_unmask_address; unsigned long msix_snoop_address; + unsigned long msix_snoop_gpa; const struct g2m_ioport *g2m_ioport; }; --- a/xen/arch/x86/hvm/vmsi.c +++ b/xen/arch/x86/hvm/vmsi.c @@ -351,9 +351,10 @@ static int msixtbl_range(struct vcpu *v, ASSERT(r->type == IOREQ_TYPE_COPY); if ( r->dir == IOREQ_WRITE ) { + unsigned int size = r->size; + if ( !r->data_is_ptr ) { - unsigned int size = r->size; uint64_t data = r->data; if ( size == 8 ) @@ -366,7 +367,29 @@ static int msixtbl_range(struct vcpu *v, ((addr & (PCI_MSIX_ENTRY_SIZE - 1)) == PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET) && !(data & PCI_MSIX_VECTOR_BITMASK) ) + { v->arch.hvm_vcpu.hvm_io.msix_snoop_address = addr; + v->arch.hvm_vcpu.hvm_io.msix_snoop_gpa = 0; + } + } + else if ( (size == 4 || size == 8) && + /* Only support forward REP MOVS for now. */ + !r->df && + /* + * Only fully support accesses to a single table entry for + * now (if multiple ones get written to in one go, only the + * final one gets dealt with). + */ + r->count && r->count <= PCI_MSIX_ENTRY_SIZE / size && + !((addr + (size * r->count)) & (PCI_MSIX_ENTRY_SIZE - 1)) ) + { + BUILD_BUG_ON((PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET + 4) & + (PCI_MSIX_ENTRY_SIZE - 1)); + + v->arch.hvm_vcpu.hvm_io.msix_snoop_address = + addr + size * r->count - 4; + v->arch.hvm_vcpu.hvm_io.msix_snoop_gpa = + r->data + size * r->count - 4; } } @@ -471,6 +494,7 @@ out: for_each_vcpu ( d, v ) { if ( (v->pause_flags & VPF_blocked_in_xen) && + !v->arch.hvm_vcpu.hvm_io.msix_snoop_gpa && v->arch.hvm_vcpu.hvm_io.msix_snoop_address == (gtable + msi_desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + @@ -561,9 +585,29 @@ void msixtbl_pt_cleanup(struct domain *d void msix_write_completion(struct vcpu *v) { unsigned long ctrl_address = v->arch.hvm_vcpu.hvm_io.msix_unmask_address; + unsigned long snoop_addr = v->arch.hvm_vcpu.hvm_io.msix_snoop_address; v->arch.hvm_vcpu.hvm_io.msix_snoop_address = 0; + if ( !ctrl_address && snoop_addr && + v->arch.hvm_vcpu.hvm_io.msix_snoop_gpa ) + { + const struct msi_desc *desc; + uint32_t data; + + rcu_read_lock(&msixtbl_rcu_lock); + desc = msixtbl_addr_to_desc(msixtbl_find_entry(v, snoop_addr), + snoop_addr); + rcu_read_unlock(&msixtbl_rcu_lock); + + if ( desc && + hvm_copy_from_guest_phys(&data, + v->arch.hvm_vcpu.hvm_io.msix_snoop_gpa, + sizeof(data)) == HVMCOPY_okay && + !(data & PCI_MSIX_VECTOR_BITMASK) ) + ctrl_address = snoop_addr; + } + if ( !ctrl_address ) return; --- a/xen/include/asm-x86/hvm/vcpu.h +++ b/xen/include/asm-x86/hvm/vcpu.h @@ -86,6 +86,7 @@ struct hvm_vcpu_io { unsigned long msix_unmask_address; unsigned long msix_snoop_address; + unsigned long msix_snoop_gpa; const struct g2m_ioport *g2m_ioport; };