From patchwork Mon Jul 10 10:39:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 9832673 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 D5BA060350 for ; Mon, 10 Jul 2017 10:41:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 017B52841C for ; Mon, 10 Jul 2017 10:41:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E7A962843C; Mon, 10 Jul 2017 10:41:39 +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=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED 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 408522841C for ; Mon, 10 Jul 2017 10:41:38 +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 1dUW5z-0001NS-F4; Mon, 10 Jul 2017 10:39:15 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dUW5x-0001NM-Gr for xen-devel@lists.xenproject.org; Mon, 10 Jul 2017 10:39:13 +0000 Received: from [85.158.137.68] by server-6.bemta-3.messagelabs.com id 42/10-02181-05953695; Mon, 10 Jul 2017 10:39:12 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrOIsWRWlGSWpSXmKPExsXS6fjDS9c/Mjn S4MFzS4vvWyYzOTB6HP5whSWAMYo1My8pvyKBNePd1o1MBT90Kpoun2ZuYLyo2MXIySEkkCex t2U+E4jNK2An0XIWwpYQMJQ4vfAmC4jNIqAqMXn5NmYQm01AXaLt2XbWLkYODhEBA4lzR5NAT GYBfYlt61hATGGBQIlb39MghttJbF18mR0kzCsgKPF3hzBImBkofOXObdYJjNyzEDKzkGQgbC 2Jh79usUDY2hLLFr5mngW2Slpi+T8OiLC5RHvrMzQlILaTxMyza1kWMHKsYtQoTi0qSy3SNTL USyrKTM8oyU3MzNE1NDDWy00tLk5MT81JTCrWS87P3cQIDMh6BgbGHYw9e/0OMUpyMCmJ8kp6 J0cK8SXlp1RmJBZnxBeV5qQWH2KU4eBQkuBdHgGUEyxKTU+tSMvMAcYGTFqCg0dJhNfIByjNW 1yQmFucmQ6ROsVoybFh9fovTBwdPRuA5KsJ/78xCbHk5eelSonzzgKZJwDSkFGaBzcOFr+XGG WlhHkZGRgYhHgKUotyM0tQ5V8xinMwKgnzrggBmsKTmVcCt/UV0EFMQAex1SWAHFSSiJCSamB knKy2qeChVTOHgdCLiidPQw8q/vlxR0jolMCO7cxyuvseHbou1K2s6/T4NVcM/6tbwvO7Etbu 3XDi+OsH/8OfpbL/0Vh6aVauw+qql8kGlS6fvYMehVZP4M79uHvBlfsP/DaUHln2eMWelfc+3 Vh55Pai3yyPHp/fs0chpqLhyIpZu5XEw7bF1CuxFGckGmoxFxUnAgBUv9uS2gIAAA== X-Env-Sender: JBeulich@suse.com X-Msg-Ref: server-11.tower-31.messagelabs.com!1499683150!73825821!1 X-Originating-IP: [137.65.248.74] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 9.4.25; banners=-,-,- X-VirusChecked: Checked Received: (qmail 20598 invoked from network); 10 Jul 2017 10:39:11 -0000 Received: from prv-mh.provo.novell.com (HELO prv-mh.provo.novell.com) (137.65.248.74) by server-11.tower-31.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 10 Jul 2017 10:39:11 -0000 Received: from INET-PRV-MTA by prv-mh.provo.novell.com with Novell_GroupWise; Mon, 10 Jul 2017 04:39:09 -0600 Message-Id: <59637569020000780016A34F@prv-mh.provo.novell.com> X-Mailer: Novell GroupWise Internet Agent 14.2.2 Date: Mon, 10 Jul 2017 04:39:05 -0600 From: "Jan Beulich" To: "xen-devel" References: <59637569020000780016A34F@prv-mh.provo.novell.com> Mime-Version: 1.0 Cc: Andrew Cooper Subject: [Xen-devel] [PATCH v3] x86/HVM: don't #GP/#SS on wrapping virt->linear translations 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-Virus-Scanned: ClamAV using ClamSMTP Real hardware wraps silently in most cases, so we should behave the same. Also split real and VM86 mode handling, as the latter really ought to have limit checks applied. Signed-off-by: Jan Beulich --- v3: Restore 32-bit wrap check for AMD. v2: Extend to non-64-bit modes. Reduce 64-bit check to a single is_canonical_address() invocation. x86/HVM: don't #GP/#SS on wrapping virt->linear translations Real hardware wraps silently in most cases, so we should behave the same. Also split real and VM86 mode handling, as the latter really ought to have limit checks applied. Signed-off-by: Jan Beulich --- v3: Restore 32-bit wrap check for AMD. v2: Extend to non-64-bit modes. Reduce 64-bit check to a single is_canonical_address() invocation. --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -2416,16 +2416,21 @@ bool_t hvm_virtual_to_linear_addr( */ ASSERT(seg < x86_seg_none); - if ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) || - (guest_cpu_user_regs()->eflags & X86_EFLAGS_VM) ) + if ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) ) { /* - * REAL/VM86 MODE: Don't bother with segment access checks. + * REAL MODE: Don't bother with segment access checks. * Certain of them are not done in native real mode anyway. */ addr = (uint32_t)(addr + reg->base); - last_byte = (uint32_t)addr + bytes - !!bytes; - if ( last_byte < addr ) + } + else if ( (guest_cpu_user_regs()->eflags & X86_EFLAGS_VM) && + is_x86_user_segment(seg) ) + { + /* VM86 MODE: Fixed 64k limits on all user segments. */ + addr = (uint32_t)(addr + reg->base); + last_byte = (uint32_t)offset + bytes - !!bytes; + if ( max(offset, last_byte) >> 16 ) goto out; } else if ( hvm_long_mode_active(curr) && @@ -2447,8 +2452,7 @@ bool_t hvm_virtual_to_linear_addr( addr += reg->base; last_byte = addr + bytes - !!bytes; - if ( !is_canonical_address(addr) || last_byte < addr || - !is_canonical_address(last_byte) ) + if ( !is_canonical_address((long)addr < 0 ? addr : last_byte) ) goto out; } else @@ -2498,8 +2502,11 @@ bool_t hvm_virtual_to_linear_addr( if ( (offset <= reg->limit) || (last_byte < offset) ) goto out; } - else if ( (last_byte > reg->limit) || (last_byte < offset) ) - goto out; /* last byte is beyond limit or wraps 0xFFFFFFFF */ + else if ( last_byte > reg->limit ) + goto out; /* last byte is beyond limit */ + else if ( last_byte < offset && + curr->domain->arch.cpuid->x86_vendor == X86_VENDOR_AMD ) + goto out; /* access wraps */ } /* All checks ok. */ --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -2416,16 +2416,21 @@ bool_t hvm_virtual_to_linear_addr( */ ASSERT(seg < x86_seg_none); - if ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) || - (guest_cpu_user_regs()->eflags & X86_EFLAGS_VM) ) + if ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) ) { /* - * REAL/VM86 MODE: Don't bother with segment access checks. + * REAL MODE: Don't bother with segment access checks. * Certain of them are not done in native real mode anyway. */ addr = (uint32_t)(addr + reg->base); - last_byte = (uint32_t)addr + bytes - !!bytes; - if ( last_byte < addr ) + } + else if ( (guest_cpu_user_regs()->eflags & X86_EFLAGS_VM) && + is_x86_user_segment(seg) ) + { + /* VM86 MODE: Fixed 64k limits on all user segments. */ + addr = (uint32_t)(addr + reg->base); + last_byte = (uint32_t)offset + bytes - !!bytes; + if ( max(offset, last_byte) >> 16 ) goto out; } else if ( hvm_long_mode_active(curr) && @@ -2447,8 +2452,7 @@ bool_t hvm_virtual_to_linear_addr( addr += reg->base; last_byte = addr + bytes - !!bytes; - if ( !is_canonical_address(addr) || last_byte < addr || - !is_canonical_address(last_byte) ) + if ( !is_canonical_address((long)addr < 0 ? addr : last_byte) ) goto out; } else @@ -2498,8 +2502,11 @@ bool_t hvm_virtual_to_linear_addr( if ( (offset <= reg->limit) || (last_byte < offset) ) goto out; } - else if ( (last_byte > reg->limit) || (last_byte < offset) ) - goto out; /* last byte is beyond limit or wraps 0xFFFFFFFF */ + else if ( last_byte > reg->limit ) + goto out; /* last byte is beyond limit */ + else if ( last_byte < offset && + curr->domain->arch.cpuid->x86_vendor == X86_VENDOR_AMD ) + goto out; /* access wraps */ } /* All checks ok. */