From patchwork Tue Dec 6 13:39:11 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 9462603 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 5C2CE60236 for ; Tue, 6 Dec 2016 13:41:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 49098283E2 for ; Tue, 6 Dec 2016 13:41:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3D6BE283E6; Tue, 6 Dec 2016 13:41:19 +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 72210283E2 for ; Tue, 6 Dec 2016 13:41:18 +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 1cEFxm-0003sm-Kn; Tue, 06 Dec 2016 13:39:18 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cEFxl-0003sM-Aq for xen-devel@lists.xenproject.org; Tue, 06 Dec 2016 13:39:17 +0000 Received: from [85.158.143.35] by server-9.bemta-6.messagelabs.com id 4C/85-28694-48FB6485; Tue, 06 Dec 2016 13:39:16 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrJIsWRWlGSWpSXmKPExsXS6fjDS7d5v1u EwcNfZhbft0xmcmD0OPzhCksAYxRrZl5SfkUCa0bXnocsBUsjKuY/3sLawLjLrIuRk0NIIE/i cf8l1i5GDg5eATuJxhN6IGEJAUOJp++vs4HYLAKqEtuX3GYBsdkE1CXanm0HKxcRMJA4dzQJx GQW0JfYtg6sQlggQWL36mWsEMPtJF5e+MkEYnMK2Ev03d0MtUhQ4u8OYYhOO4l/S5knMPLMQk jMQkjMAmplFtCSePjrFguErS2xbOFrZogSaYnl/zggwuYST0+eZUdVAmI7SSyf2siygJFjFaN GcWpRWWqRrqGRXlJRZnpGSW5iZo6uoYGZXm5qcXFiempOYlKxXnJ+7iZGYJAyAMEOxssbAw4x SnIwKYnyqli6RQjxJeWnVGYkFmfEF5XmpBYfYpTh4FCS4I3aB5QTLEpNT61Iy8wBxgtMWoKDR 0mEN3IvUJq3uCAxtzgzHSJ1ilFRSpy3EqRPACSRUZoH1waL0UuMslLCvIxAhwjxFKQW5WaWoM q/YhTnYFQS5s0EmcKTmVcCN/0V0GImoMUnjjuDLC5JREhJNTDmbNwxeYVY3IUlvFGVvdEsn7p 3cfkuLEspVFzmED43z+LVL/ede28dOPvgxq5N2Z3b5R4cMuaYzRTafcXM9nUFd9FH/5MHnjGc yzMxWci9fNpDn4Lg6+fOfv0a8npF+AOnSRtvrF4mw7E3cHK3zJus9decbPV/uCiw//i/+arid YElq3asuvK1QomlOCPRUIu5qDgRANCWVg/MAgAA X-Env-Sender: JBeulich@suse.com X-Msg-Ref: server-4.tower-21.messagelabs.com!1481031553!40756449!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.0.16; banners=-,-,- X-VirusChecked: Checked Received: (qmail 3043 invoked from network); 6 Dec 2016 13:39:15 -0000 Received: from prv-mh.provo.novell.com (HELO prv-mh.provo.novell.com) (137.65.248.74) by server-4.tower-21.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 6 Dec 2016 13:39:15 -0000 Received: from INET-PRV-MTA by prv-mh.provo.novell.com with Novell_GroupWise; Tue, 06 Dec 2016 06:39:13 -0700 Message-Id: <5846CD8F0200007800125B5F@prv-mh.provo.novell.com> X-Mailer: Novell GroupWise Internet Agent 14.2.1 Date: Tue, 06 Dec 2016 06:39:11 -0700 From: "Jan Beulich" To: "xen-devel" References: <5846CBD80200007800125B49@prv-mh.provo.novell.com> In-Reply-To: <5846CBD80200007800125B49@prv-mh.provo.novell.com> Mime-Version: 1.0 Cc: Andrew Cooper Subject: [Xen-devel] [PATCH 2/2] x86emul: correct 64-bit mode repeated string insn handling with zero count 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 When a 32-bit address override is in effect these zero-extend all registers which would also get updated in case of non-zero repeat count. Signed-off-by: Jan Beulich x86emul: correct 64-bit mode repeated string insn handling with zero count When a 32-bit address override is in effect these zero-extend all registers which would also get updated in case of non-zero repeat count. Signed-off-by: Jan Beulich --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -933,15 +933,24 @@ static inline void put_loop_count( int_regs->ecx = ad_bytes == 4 ? (uint32_t)count : count; } -#define get_rep_prefix() ({ \ +#define get_rep_prefix(using_si, using_di) ({ \ unsigned long max_reps = 1; \ if ( rep_prefix() ) \ max_reps = get_loop_count(&_regs, ad_bytes); \ if ( max_reps == 0 ) \ { \ - /* Skip the instruction if no repetitions are required. */ \ - dst.type = OP_NONE; \ - goto writeback; \ + /* \ + * Skip the instruction if no repetitions are required, but \ + * zero extend involved registers first when using 32-bit \ + * addressing in 64-bit mode. \ + */ \ + if ( mode_64bit() && ad_bytes == 4 ) \ + { \ + _regs.ecx = 0; \ + if ( using_si ) _regs.esi = (uint32_t)_regs.esi; \ + if ( using_di ) _regs.edi = (uint32_t)_regs.edi; \ + } \ + goto no_writeback; \ } \ max_reps; \ }) @@ -2908,7 +2917,7 @@ x86_emulate( goto imul; case 0x6c ... 0x6d: /* ins %dx,%es:%edi */ { - unsigned long nr_reps = get_rep_prefix(); + unsigned long nr_reps = get_rep_prefix(false, true); unsigned int port = (uint16_t)_regs.edx; dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes; dst.mem.seg = x86_seg_es; @@ -2935,7 +2944,7 @@ x86_emulate( } case 0x6e ... 0x6f: /* outs %esi,%dx */ { - unsigned long nr_reps = get_rep_prefix(); + unsigned long nr_reps = get_rep_prefix(true, false); unsigned int port = (uint16_t)_regs.edx; dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes; ea.mem.off = truncate_ea_and_reps(_regs.esi, nr_reps, dst.bytes); @@ -3167,7 +3176,8 @@ x86_emulate( break; case 0xa4 ... 0xa5: /* movs */ { - unsigned long nr_reps = get_rep_prefix(); + unsigned long nr_reps = get_rep_prefix(true, true); + dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.mem.seg = x86_seg_es; dst.mem.off = truncate_ea_and_reps(_regs.edi, nr_reps, dst.bytes); @@ -3197,7 +3207,8 @@ x86_emulate( case 0xa6 ... 0xa7: /* cmps */ { unsigned long next_eip = _regs.eip; - get_rep_prefix(); + + get_rep_prefix(true, true); src.bytes = dst.bytes = (d & ByteOp) ? 1 : op_bytes; if ( (rc = read_ulong(ea.mem.seg, truncate_ea(_regs.esi), &dst.val, dst.bytes, ctxt, ops)) || @@ -3218,7 +3229,8 @@ x86_emulate( } case 0xaa ... 0xab: /* stos */ { - unsigned long nr_reps = get_rep_prefix(); + unsigned long nr_reps = get_rep_prefix(false, true); + dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.mem.seg = x86_seg_es; dst.mem.off = truncate_ea(_regs.edi); @@ -3241,8 +3253,8 @@ x86_emulate( break; } - case 0xac ... 0xad: /* lods */ { - /* unsigned long max_reps = */get_rep_prefix(); + case 0xac ... 0xad: /* lods */ + get_rep_prefix(true, false); dst.type = OP_REG; dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.reg = (unsigned long *)&_regs.eax; @@ -3253,11 +3265,11 @@ x86_emulate( _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); put_rep_prefix(1); break; - } case 0xae ... 0xaf: /* scas */ { unsigned long next_eip = _regs.eip; - get_rep_prefix(); + + get_rep_prefix(false, true); src.bytes = dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.val = _regs.eax; if ( (rc = read_ulong(x86_seg_es, truncate_ea(_regs.edi), @@ -5424,7 +5436,6 @@ x86_emulate( goto cannot_emulate; } - writeback: switch ( dst.type ) { case OP_REG: Reviewed-by: Andrew Cooper . However, --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -933,15 +933,24 @@ static inline void put_loop_count( int_regs->ecx = ad_bytes == 4 ? (uint32_t)count : count; } -#define get_rep_prefix() ({ \ +#define get_rep_prefix(using_si, using_di) ({ \ unsigned long max_reps = 1; \ if ( rep_prefix() ) \ max_reps = get_loop_count(&_regs, ad_bytes); \ if ( max_reps == 0 ) \ { \ - /* Skip the instruction if no repetitions are required. */ \ - dst.type = OP_NONE; \ - goto writeback; \ + /* \ + * Skip the instruction if no repetitions are required, but \ + * zero extend involved registers first when using 32-bit \ + * addressing in 64-bit mode. \ + */ \ + if ( mode_64bit() && ad_bytes == 4 ) \ + { \ + _regs.ecx = 0; \ + if ( using_si ) _regs.esi = (uint32_t)_regs.esi; \ + if ( using_di ) _regs.edi = (uint32_t)_regs.edi; \ + } \ + goto no_writeback; \ } \ max_reps; \ }) @@ -2908,7 +2917,7 @@ x86_emulate( goto imul; case 0x6c ... 0x6d: /* ins %dx,%es:%edi */ { - unsigned long nr_reps = get_rep_prefix(); + unsigned long nr_reps = get_rep_prefix(false, true); unsigned int port = (uint16_t)_regs.edx; dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes; dst.mem.seg = x86_seg_es; @@ -2935,7 +2944,7 @@ x86_emulate( } case 0x6e ... 0x6f: /* outs %esi,%dx */ { - unsigned long nr_reps = get_rep_prefix(); + unsigned long nr_reps = get_rep_prefix(true, false); unsigned int port = (uint16_t)_regs.edx; dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes; ea.mem.off = truncate_ea_and_reps(_regs.esi, nr_reps, dst.bytes); @@ -3167,7 +3176,8 @@ x86_emulate( break; case 0xa4 ... 0xa5: /* movs */ { - unsigned long nr_reps = get_rep_prefix(); + unsigned long nr_reps = get_rep_prefix(true, true); + dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.mem.seg = x86_seg_es; dst.mem.off = truncate_ea_and_reps(_regs.edi, nr_reps, dst.bytes); @@ -3197,7 +3207,8 @@ x86_emulate( case 0xa6 ... 0xa7: /* cmps */ { unsigned long next_eip = _regs.eip; - get_rep_prefix(); + + get_rep_prefix(true, true); src.bytes = dst.bytes = (d & ByteOp) ? 1 : op_bytes; if ( (rc = read_ulong(ea.mem.seg, truncate_ea(_regs.esi), &dst.val, dst.bytes, ctxt, ops)) || @@ -3218,7 +3229,8 @@ x86_emulate( } case 0xaa ... 0xab: /* stos */ { - unsigned long nr_reps = get_rep_prefix(); + unsigned long nr_reps = get_rep_prefix(false, true); + dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.mem.seg = x86_seg_es; dst.mem.off = truncate_ea(_regs.edi); @@ -3241,8 +3253,8 @@ x86_emulate( break; } - case 0xac ... 0xad: /* lods */ { - /* unsigned long max_reps = */get_rep_prefix(); + case 0xac ... 0xad: /* lods */ + get_rep_prefix(true, false); dst.type = OP_REG; dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.reg = (unsigned long *)&_regs.eax; @@ -3253,11 +3265,11 @@ x86_emulate( _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); put_rep_prefix(1); break; - } case 0xae ... 0xaf: /* scas */ { unsigned long next_eip = _regs.eip; - get_rep_prefix(); + + get_rep_prefix(false, true); src.bytes = dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.val = _regs.eax; if ( (rc = read_ulong(x86_seg_es, truncate_ea(_regs.edi), @@ -5424,7 +5436,6 @@ x86_emulate( goto cannot_emulate; } - writeback: switch ( dst.type ) { case OP_REG: