From patchwork Fri Sep 30 13:16:36 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 9358247 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 BFB59600C8 for ; Fri, 30 Sep 2016 13:19:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AA10E2A01B for ; Fri, 30 Sep 2016 13:19:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9EB592A020; Fri, 30 Sep 2016 13:19:00 +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 0DBA92A01B for ; Fri, 30 Sep 2016 13:18:59 +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 1bpxgA-00050R-9L; Fri, 30 Sep 2016 13:16:42 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bpxg9-00050J-Kq for xen-devel@lists.xenproject.org; Fri, 30 Sep 2016 13:16:41 +0000 Received: from [85.158.137.68] by server-12.bemta-3.messagelabs.com id DF/D3-09160-8B56EE75; Fri, 30 Sep 2016 13:16:40 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrJIsWRWlGSWpSXmKPExsXS6fjDS3d76rt wg5ubTCy+b5nM5MDocfjDFZYAxijWzLyk/IoE1oxjb6+xFfw+w1jReu4sawPjry7GLkZODiGB PIl3J66yg9i8AnYS759dZwOxJQQMJZ6+h7BZBFQl2g9NBrPZBNQl2p5tZ+1i5OAQETCQOHc0C cRkFtCX2LaOBaRCWMBNYtmit2wQ0+0k/tz7xwpicwrYS+y7eIEJpJxXQFDi7w5hkDAzUEnLgb NsExh5ZiFkZiHJQNhaEg9/3WKBsLUlli18zTwLbK+0xPJ/HBBhe4mffzezoSoBsb0kPvx/zLi AkWMVo3pxalFZapGumV5SUWZ6RkluYmaOrqGBsV5uanFxYnpqTmJSsV5yfu4mRmCw1jMwMO5g vNLmfIhRkoNJSZRX9ujbcCG+pPyUyozE4oz4otKc1OJDjBocHAITzs6dziTFkpefl6okwSuS8 i5cSLAoNT21Ii0zBxhPMKUSHDxKIrzuIGne4oLE3OLMdIjUKUZFKXFeUZCEAEgiozQPrg0Ww5 cYZaWEeRkZGBiEeApSi3IzS1DlXzGKczAqCfPygEzhycwrgZv+CmgxE9Di/KNvQBaXJCKkpBo Y9+8vFgx2zfTduU5xzyHHXzt+3H91ff6zj88+L+v5lhhSWMiYG1yxyPqBxOKlx5nU+xdyzG1y 3Xw9fNtDsQ/fJjv7ef2JDZry8YzkrSibVqX/lZeni5cZn3zx8aXUNEGtR31nFxTbMc4xrC8wb /782OnOoQ2H5FrfLn7VuuHrfPf6WXJf++0y2JVYijMSDbWYi4oTAZxX3YLcAgAA X-Env-Sender: JBeulich@suse.com X-Msg-Ref: server-13.tower-31.messagelabs.com!1475241397!63155545!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.84; banners=-,-,- X-VirusChecked: Checked Received: (qmail 59870 invoked from network); 30 Sep 2016 13:16:39 -0000 Received: from prv-mh.provo.novell.com (HELO prv-mh.provo.novell.com) (137.65.248.74) by server-13.tower-31.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 30 Sep 2016 13:16:39 -0000 Received: from INET-PRV-MTA by prv-mh.provo.novell.com with Novell_GroupWise; Fri, 30 Sep 2016 07:16:37 -0600 Message-Id: <57EE81D4020000780011443F@prv-mh.provo.novell.com> X-Mailer: Novell GroupWise Internet Agent 14.2.1 Date: Fri, 30 Sep 2016 07:16:36 -0600 From: "Jan Beulich" To: "xen-devel" References: <57EE80D6020000780011442C@prv-mh.provo.novell.com> In-Reply-To: <57EE80D6020000780011442C@prv-mh.provo.novell.com> Mime-Version: 1.0 Cc: Andrew Cooper Subject: [Xen-devel] [PATCH v2 2/4] x86emul: consolidate segment register handling 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 Use a single set of variables throughout the huge switch() statement, allowing to funnel SLDT/STR into the mov-from-sreg code path. Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper --- v2: s/store_seg/store_selector/g. Re-base. x86emul: consolidate segment register handling Use a single set of variables throughout the huge switch() statement, allowing to funnel SLDT/STR into the mov-from-sreg code path. Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper --- v2: s/store_seg/store_selector/g. Re-base. --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -2505,7 +2505,8 @@ x86_emulate( switch ( ctxt->opcode ) { - struct segment_register cs; + enum x86_segment seg; + struct segment_register cs, sreg; case 0x00 ... 0x05: add: /* add */ emulate_2op_SrcV("add", src, dst, _regs.eflags); @@ -2541,22 +2542,20 @@ x86_emulate( dst.type = OP_NONE; break; - case 0x06: /* push %%es */ { - struct segment_register reg; + case 0x06: /* push %%es */ src.val = x86_seg_es; push_seg: generate_exception_if(mode_64bit() && !ext, EXC_UD, -1); fail_if(ops->read_segment == NULL); - if ( (rc = ops->read_segment(src.val, ®, ctxt)) != 0 ) + if ( (rc = ops->read_segment(src.val, &sreg, ctxt)) != 0 ) goto done; /* 64-bit mode: PUSH defaults to a 64-bit operand. */ if ( mode_64bit() && (op_bytes == 4) ) op_bytes = 8; if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes), - ®.sel, op_bytes, ctxt)) != 0 ) + &sreg.sel, op_bytes, ctxt)) != 0 ) goto done; break; - } case 0x07: /* pop %%es */ src.val = x86_seg_es; @@ -2872,21 +2871,20 @@ x86_emulate( dst.val = src.val; break; - case 0x8c: /* mov Sreg,r/m */ { - struct segment_register reg; - enum x86_segment seg = decode_segment(modrm_reg); + case 0x8c: /* mov Sreg,r/m */ + seg = decode_segment(modrm_reg); generate_exception_if(seg == decode_segment_failed, EXC_UD, -1); + store_selector: fail_if(ops->read_segment == NULL); - if ( (rc = ops->read_segment(seg, ®, ctxt)) != 0 ) + if ( (rc = ops->read_segment(seg, &sreg, ctxt)) != 0 ) goto done; - dst.val = reg.sel; + dst.val = sreg.sel; if ( dst.type == OP_MEM ) dst.bytes = 2; break; - } - case 0x8e: /* mov r/m,Sreg */ { - enum x86_segment seg = decode_segment(modrm_reg); + case 0x8e: /* mov r/m,Sreg */ + seg = decode_segment(modrm_reg); generate_exception_if(seg == decode_segment_failed, EXC_UD, -1); generate_exception_if(seg == x86_seg_cs, EXC_UD, -1); if ( (rc = load_seg(seg, src.val, 0, NULL, ctxt, ops)) != 0 ) @@ -2895,7 +2893,6 @@ x86_emulate( ctxt->retire.flags.mov_ss = 1; dst.type = OP_NONE; break; - } case 0x8d: /* lea */ generate_exception_if(ea.type != OP_MEM, EXC_UD, -1); @@ -2952,17 +2949,15 @@ x86_emulate( } break; - case 0x9a: /* call (far, absolute) */ { - struct segment_register reg; - + case 0x9a: /* call (far, absolute) */ ASSERT(!mode_64bit()); fail_if(ops->read_segment == NULL); - if ( (rc = ops->read_segment(x86_seg_cs, ®, ctxt)) || + if ( (rc = ops->read_segment(x86_seg_cs, &sreg, ctxt)) || (rc = load_seg(x86_seg_cs, imm2, 0, &cs, ctxt, ops)) || (validate_far_branch(&cs, imm1), rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes), - ®.sel, op_bytes, ctxt)) || + &sreg.sel, op_bytes, ctxt)) || (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes), &_regs.eip, op_bytes, ctxt)) || (rc = ops->write_segment(x86_seg_cs, &cs, ctxt)) ) @@ -2970,7 +2965,6 @@ x86_emulate( _regs.eip = imm1; break; - } case 0x9b: /* wait/fwait */ emulate_fpu_insn("fwait"); @@ -4179,13 +4173,12 @@ x86_emulate( if ( (modrm_reg & 7) == 3 ) /* call */ { - struct segment_register reg; fail_if(ops->read_segment == NULL); - if ( (rc = ops->read_segment(x86_seg_cs, ®, ctxt)) || + if ( (rc = ops->read_segment(x86_seg_cs, &sreg, ctxt)) || (rc = load_seg(x86_seg_cs, sel, 0, &cs, ctxt, ops)) || (validate_far_branch(&cs, src.val), rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes), - ®.sel, op_bytes, ctxt)) || + &sreg.sel, op_bytes, ctxt)) || (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes), &_regs.eip, op_bytes, ctxt)) || (rc = ops->write_segment(x86_seg_cs, &cs, ctxt)) ) @@ -4207,23 +4200,13 @@ x86_emulate( break; case X86EMUL_OPC(0x0f, 0x00): /* Grp6 */ - { - enum x86_segment seg = (modrm_reg & 1) ? x86_seg_tr : x86_seg_ldtr; - + seg = (modrm_reg & 1) ? x86_seg_tr : x86_seg_ldtr; generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1); switch ( modrm_reg & 6 ) { - struct segment_register sreg; - case 0: /* sldt / str */ generate_exception_if(umip_active(ctxt, ops), EXC_GP, 0); - fail_if(!ops->read_segment); - if ( (rc = ops->read_segment(seg, &sreg, ctxt)) != 0 ) - goto done; - dst.val = sreg.sel; - if ( dst.type == OP_MEM ) - dst.bytes = 2; - break; + goto store_selector; case 2: /* lldt / ltr */ generate_exception_if(!mode_ring0(), EXC_GP, 0); if ( (rc = load_seg(seg, src.val, 0, NULL, ctxt, ops)) != 0 ) @@ -4234,10 +4217,8 @@ x86_emulate( break; } break; - } case X86EMUL_OPC(0x0f, 0x01): /* Grp7 */ { - struct segment_register reg; unsigned long base, limit, cr0, cr0w; switch( modrm ) @@ -4326,6 +4307,8 @@ x86_emulate( } } + seg = (modrm_reg & 1) ? x86_seg_idtr : x86_seg_gdtr; + switch ( modrm_reg & 7 ) { case 0: /* sgdt */ @@ -4333,16 +4316,14 @@ x86_emulate( generate_exception_if(ea.type != OP_MEM, EXC_UD, -1); generate_exception_if(umip_active(ctxt, ops), EXC_GP, 0); fail_if(ops->read_segment == NULL); - if ( (rc = ops->read_segment((modrm_reg & 1) ? - x86_seg_idtr : x86_seg_gdtr, - ®, ctxt)) ) + if ( (rc = ops->read_segment(seg, &sreg, ctxt)) ) goto done; if ( op_bytes == 2 ) - reg.base &= 0xffffff; + sreg.base &= 0xffffff; if ( (rc = ops->write(ea.mem.seg, ea.mem.off+0, - ®.limit, 2, ctxt)) || + &sreg.limit, 2, ctxt)) || (rc = ops->write(ea.mem.seg, ea.mem.off+2, - ®.base, mode_64bit() ? 8 : 4, ctxt)) ) + &sreg.base, mode_64bit() ? 8 : 4, ctxt)) ) goto done; break; case 2: /* lgdt */ @@ -4350,19 +4331,17 @@ x86_emulate( generate_exception_if(!mode_ring0(), EXC_GP, 0); generate_exception_if(ea.type != OP_MEM, EXC_UD, -1); fail_if(ops->write_segment == NULL); - memset(®, 0, sizeof(reg)); + memset(&sreg, 0, sizeof(sreg)); if ( (rc = read_ulong(ea.mem.seg, ea.mem.off+0, &limit, 2, ctxt, ops)) || (rc = read_ulong(ea.mem.seg, ea.mem.off+2, &base, mode_64bit() ? 8 : 4, ctxt, ops)) ) goto done; - reg.base = base; - reg.limit = limit; + sreg.base = base; + sreg.limit = limit; if ( op_bytes == 2 ) - reg.base &= 0xffffff; - if ( (rc = ops->write_segment((modrm_reg & 1) ? - x86_seg_idtr : x86_seg_gdtr, - ®, ctxt)) ) + sreg.base &= 0xffffff; + if ( (rc = ops->write_segment(seg, &sreg, ctxt)) ) goto done; break; case 4: /* smsw */ @@ -4405,7 +4384,6 @@ x86_emulate( case X86EMUL_OPC(0x0f, 0x05): /* syscall */ { uint64_t msr_content; - struct segment_register cs, ss; generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1); @@ -4419,11 +4397,11 @@ x86_emulate( goto done; cs.sel = (msr_content >> 32) & ~3; /* SELECTOR_RPL_MASK */ - ss.sel = cs.sel + 8; + sreg.sel = cs.sel + 8; - cs.base = ss.base = 0; /* flat segment */ - cs.limit = ss.limit = ~0u; /* 4GB limit */ - ss.attr.bytes = 0xc93; /* G+DB+P+S+Data */ + cs.base = sreg.base = 0; /* flat segment */ + cs.limit = sreg.limit = ~0u; /* 4GB limit */ + sreg.attr.bytes = 0xc93; /* G+DB+P+S+Data */ #ifdef __x86_64__ rc = in_longmode(ctxt, ops); @@ -4457,7 +4435,7 @@ x86_emulate( fail_if(ops->write_segment == NULL); if ( (rc = ops->write_segment(x86_seg_cs, &cs, ctxt)) || - (rc = ops->write_segment(x86_seg_ss, &ss, ctxt)) ) + (rc = ops->write_segment(x86_seg_ss, &sreg, ctxt)) ) goto done; break; @@ -4676,7 +4654,6 @@ x86_emulate( case X86EMUL_OPC(0x0f, 0x34): /* sysenter */ { uint64_t msr_content; - struct segment_register cs, ss; int lm; generate_exception_if(mode_ring0(), EXC_GP, 0); @@ -4701,14 +4678,14 @@ x86_emulate( cs.attr.bytes = lm ? 0xa9b /* L+DB+P+S+Code */ : 0xc9b; /* G+DB+P+S+Code */ - ss.sel = cs.sel + 8; - ss.base = 0; /* flat segment */ - ss.limit = ~0u; /* 4GB limit */ - ss.attr.bytes = 0xc93; /* G+DB+P+S+Data */ + sreg.sel = cs.sel + 8; + sreg.base = 0; /* flat segment */ + sreg.limit = ~0u; /* 4GB limit */ + sreg.attr.bytes = 0xc93; /* G+DB+P+S+Data */ fail_if(ops->write_segment == NULL); if ( (rc = ops->write_segment(x86_seg_cs, &cs, ctxt)) != 0 || - (rc = ops->write_segment(x86_seg_ss, &ss, ctxt)) != 0 ) + (rc = ops->write_segment(x86_seg_ss, &sreg, ctxt)) != 0 ) goto done; if ( (rc = ops->read_msr(MSR_SYSENTER_EIP, &msr_content, ctxt)) != 0 ) @@ -4724,7 +4701,6 @@ x86_emulate( case X86EMUL_OPC(0x0f, 0x35): /* sysexit */ { uint64_t msr_content; - struct segment_register cs, ss; bool_t user64 = !!(rex_prefix & REX_W); generate_exception_if(!mode_ring0(), EXC_GP, 0); @@ -4746,14 +4722,14 @@ x86_emulate( cs.attr.bytes = user64 ? 0xafb /* L+DB+P+DPL3+S+Code */ : 0xcfb; /* G+DB+P+DPL3+S+Code */ - ss.sel = cs.sel + 8; - ss.base = 0; /* flat segment */ - ss.limit = ~0u; /* 4GB limit */ - ss.attr.bytes = 0xcf3; /* G+DB+P+DPL3+S+Data */ + sreg.sel = cs.sel + 8; + sreg.base = 0; /* flat segment */ + sreg.limit = ~0u; /* 4GB limit */ + sreg.attr.bytes = 0xcf3; /* G+DB+P+DPL3+S+Data */ fail_if(ops->write_segment == NULL); if ( (rc = ops->write_segment(x86_seg_cs, &cs, ctxt)) != 0 || - (rc = ops->write_segment(x86_seg_ss, &ss, ctxt)) != 0 ) + (rc = ops->write_segment(x86_seg_ss, &sreg, ctxt)) != 0 ) goto done; _regs.eip = user64 ? _regs.edx : (uint32_t)_regs.edx; --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -2505,7 +2505,8 @@ x86_emulate( switch ( ctxt->opcode ) { - struct segment_register cs; + enum x86_segment seg; + struct segment_register cs, sreg; case 0x00 ... 0x05: add: /* add */ emulate_2op_SrcV("add", src, dst, _regs.eflags); @@ -2541,22 +2542,20 @@ x86_emulate( dst.type = OP_NONE; break; - case 0x06: /* push %%es */ { - struct segment_register reg; + case 0x06: /* push %%es */ src.val = x86_seg_es; push_seg: generate_exception_if(mode_64bit() && !ext, EXC_UD, -1); fail_if(ops->read_segment == NULL); - if ( (rc = ops->read_segment(src.val, ®, ctxt)) != 0 ) + if ( (rc = ops->read_segment(src.val, &sreg, ctxt)) != 0 ) goto done; /* 64-bit mode: PUSH defaults to a 64-bit operand. */ if ( mode_64bit() && (op_bytes == 4) ) op_bytes = 8; if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes), - ®.sel, op_bytes, ctxt)) != 0 ) + &sreg.sel, op_bytes, ctxt)) != 0 ) goto done; break; - } case 0x07: /* pop %%es */ src.val = x86_seg_es; @@ -2872,21 +2871,20 @@ x86_emulate( dst.val = src.val; break; - case 0x8c: /* mov Sreg,r/m */ { - struct segment_register reg; - enum x86_segment seg = decode_segment(modrm_reg); + case 0x8c: /* mov Sreg,r/m */ + seg = decode_segment(modrm_reg); generate_exception_if(seg == decode_segment_failed, EXC_UD, -1); + store_selector: fail_if(ops->read_segment == NULL); - if ( (rc = ops->read_segment(seg, ®, ctxt)) != 0 ) + if ( (rc = ops->read_segment(seg, &sreg, ctxt)) != 0 ) goto done; - dst.val = reg.sel; + dst.val = sreg.sel; if ( dst.type == OP_MEM ) dst.bytes = 2; break; - } - case 0x8e: /* mov r/m,Sreg */ { - enum x86_segment seg = decode_segment(modrm_reg); + case 0x8e: /* mov r/m,Sreg */ + seg = decode_segment(modrm_reg); generate_exception_if(seg == decode_segment_failed, EXC_UD, -1); generate_exception_if(seg == x86_seg_cs, EXC_UD, -1); if ( (rc = load_seg(seg, src.val, 0, NULL, ctxt, ops)) != 0 ) @@ -2895,7 +2893,6 @@ x86_emulate( ctxt->retire.flags.mov_ss = 1; dst.type = OP_NONE; break; - } case 0x8d: /* lea */ generate_exception_if(ea.type != OP_MEM, EXC_UD, -1); @@ -2952,17 +2949,15 @@ x86_emulate( } break; - case 0x9a: /* call (far, absolute) */ { - struct segment_register reg; - + case 0x9a: /* call (far, absolute) */ ASSERT(!mode_64bit()); fail_if(ops->read_segment == NULL); - if ( (rc = ops->read_segment(x86_seg_cs, ®, ctxt)) || + if ( (rc = ops->read_segment(x86_seg_cs, &sreg, ctxt)) || (rc = load_seg(x86_seg_cs, imm2, 0, &cs, ctxt, ops)) || (validate_far_branch(&cs, imm1), rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes), - ®.sel, op_bytes, ctxt)) || + &sreg.sel, op_bytes, ctxt)) || (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes), &_regs.eip, op_bytes, ctxt)) || (rc = ops->write_segment(x86_seg_cs, &cs, ctxt)) ) @@ -2970,7 +2965,6 @@ x86_emulate( _regs.eip = imm1; break; - } case 0x9b: /* wait/fwait */ emulate_fpu_insn("fwait"); @@ -4179,13 +4173,12 @@ x86_emulate( if ( (modrm_reg & 7) == 3 ) /* call */ { - struct segment_register reg; fail_if(ops->read_segment == NULL); - if ( (rc = ops->read_segment(x86_seg_cs, ®, ctxt)) || + if ( (rc = ops->read_segment(x86_seg_cs, &sreg, ctxt)) || (rc = load_seg(x86_seg_cs, sel, 0, &cs, ctxt, ops)) || (validate_far_branch(&cs, src.val), rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes), - ®.sel, op_bytes, ctxt)) || + &sreg.sel, op_bytes, ctxt)) || (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes), &_regs.eip, op_bytes, ctxt)) || (rc = ops->write_segment(x86_seg_cs, &cs, ctxt)) ) @@ -4207,23 +4200,13 @@ x86_emulate( break; case X86EMUL_OPC(0x0f, 0x00): /* Grp6 */ - { - enum x86_segment seg = (modrm_reg & 1) ? x86_seg_tr : x86_seg_ldtr; - + seg = (modrm_reg & 1) ? x86_seg_tr : x86_seg_ldtr; generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1); switch ( modrm_reg & 6 ) { - struct segment_register sreg; - case 0: /* sldt / str */ generate_exception_if(umip_active(ctxt, ops), EXC_GP, 0); - fail_if(!ops->read_segment); - if ( (rc = ops->read_segment(seg, &sreg, ctxt)) != 0 ) - goto done; - dst.val = sreg.sel; - if ( dst.type == OP_MEM ) - dst.bytes = 2; - break; + goto store_selector; case 2: /* lldt / ltr */ generate_exception_if(!mode_ring0(), EXC_GP, 0); if ( (rc = load_seg(seg, src.val, 0, NULL, ctxt, ops)) != 0 ) @@ -4234,10 +4217,8 @@ x86_emulate( break; } break; - } case X86EMUL_OPC(0x0f, 0x01): /* Grp7 */ { - struct segment_register reg; unsigned long base, limit, cr0, cr0w; switch( modrm ) @@ -4326,6 +4307,8 @@ x86_emulate( } } + seg = (modrm_reg & 1) ? x86_seg_idtr : x86_seg_gdtr; + switch ( modrm_reg & 7 ) { case 0: /* sgdt */ @@ -4333,16 +4316,14 @@ x86_emulate( generate_exception_if(ea.type != OP_MEM, EXC_UD, -1); generate_exception_if(umip_active(ctxt, ops), EXC_GP, 0); fail_if(ops->read_segment == NULL); - if ( (rc = ops->read_segment((modrm_reg & 1) ? - x86_seg_idtr : x86_seg_gdtr, - ®, ctxt)) ) + if ( (rc = ops->read_segment(seg, &sreg, ctxt)) ) goto done; if ( op_bytes == 2 ) - reg.base &= 0xffffff; + sreg.base &= 0xffffff; if ( (rc = ops->write(ea.mem.seg, ea.mem.off+0, - ®.limit, 2, ctxt)) || + &sreg.limit, 2, ctxt)) || (rc = ops->write(ea.mem.seg, ea.mem.off+2, - ®.base, mode_64bit() ? 8 : 4, ctxt)) ) + &sreg.base, mode_64bit() ? 8 : 4, ctxt)) ) goto done; break; case 2: /* lgdt */ @@ -4350,19 +4331,17 @@ x86_emulate( generate_exception_if(!mode_ring0(), EXC_GP, 0); generate_exception_if(ea.type != OP_MEM, EXC_UD, -1); fail_if(ops->write_segment == NULL); - memset(®, 0, sizeof(reg)); + memset(&sreg, 0, sizeof(sreg)); if ( (rc = read_ulong(ea.mem.seg, ea.mem.off+0, &limit, 2, ctxt, ops)) || (rc = read_ulong(ea.mem.seg, ea.mem.off+2, &base, mode_64bit() ? 8 : 4, ctxt, ops)) ) goto done; - reg.base = base; - reg.limit = limit; + sreg.base = base; + sreg.limit = limit; if ( op_bytes == 2 ) - reg.base &= 0xffffff; - if ( (rc = ops->write_segment((modrm_reg & 1) ? - x86_seg_idtr : x86_seg_gdtr, - ®, ctxt)) ) + sreg.base &= 0xffffff; + if ( (rc = ops->write_segment(seg, &sreg, ctxt)) ) goto done; break; case 4: /* smsw */ @@ -4405,7 +4384,6 @@ x86_emulate( case X86EMUL_OPC(0x0f, 0x05): /* syscall */ { uint64_t msr_content; - struct segment_register cs, ss; generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1); @@ -4419,11 +4397,11 @@ x86_emulate( goto done; cs.sel = (msr_content >> 32) & ~3; /* SELECTOR_RPL_MASK */ - ss.sel = cs.sel + 8; + sreg.sel = cs.sel + 8; - cs.base = ss.base = 0; /* flat segment */ - cs.limit = ss.limit = ~0u; /* 4GB limit */ - ss.attr.bytes = 0xc93; /* G+DB+P+S+Data */ + cs.base = sreg.base = 0; /* flat segment */ + cs.limit = sreg.limit = ~0u; /* 4GB limit */ + sreg.attr.bytes = 0xc93; /* G+DB+P+S+Data */ #ifdef __x86_64__ rc = in_longmode(ctxt, ops); @@ -4457,7 +4435,7 @@ x86_emulate( fail_if(ops->write_segment == NULL); if ( (rc = ops->write_segment(x86_seg_cs, &cs, ctxt)) || - (rc = ops->write_segment(x86_seg_ss, &ss, ctxt)) ) + (rc = ops->write_segment(x86_seg_ss, &sreg, ctxt)) ) goto done; break; @@ -4676,7 +4654,6 @@ x86_emulate( case X86EMUL_OPC(0x0f, 0x34): /* sysenter */ { uint64_t msr_content; - struct segment_register cs, ss; int lm; generate_exception_if(mode_ring0(), EXC_GP, 0); @@ -4701,14 +4678,14 @@ x86_emulate( cs.attr.bytes = lm ? 0xa9b /* L+DB+P+S+Code */ : 0xc9b; /* G+DB+P+S+Code */ - ss.sel = cs.sel + 8; - ss.base = 0; /* flat segment */ - ss.limit = ~0u; /* 4GB limit */ - ss.attr.bytes = 0xc93; /* G+DB+P+S+Data */ + sreg.sel = cs.sel + 8; + sreg.base = 0; /* flat segment */ + sreg.limit = ~0u; /* 4GB limit */ + sreg.attr.bytes = 0xc93; /* G+DB+P+S+Data */ fail_if(ops->write_segment == NULL); if ( (rc = ops->write_segment(x86_seg_cs, &cs, ctxt)) != 0 || - (rc = ops->write_segment(x86_seg_ss, &ss, ctxt)) != 0 ) + (rc = ops->write_segment(x86_seg_ss, &sreg, ctxt)) != 0 ) goto done; if ( (rc = ops->read_msr(MSR_SYSENTER_EIP, &msr_content, ctxt)) != 0 ) @@ -4724,7 +4701,6 @@ x86_emulate( case X86EMUL_OPC(0x0f, 0x35): /* sysexit */ { uint64_t msr_content; - struct segment_register cs, ss; bool_t user64 = !!(rex_prefix & REX_W); generate_exception_if(!mode_ring0(), EXC_GP, 0); @@ -4746,14 +4722,14 @@ x86_emulate( cs.attr.bytes = user64 ? 0xafb /* L+DB+P+DPL3+S+Code */ : 0xcfb; /* G+DB+P+DPL3+S+Code */ - ss.sel = cs.sel + 8; - ss.base = 0; /* flat segment */ - ss.limit = ~0u; /* 4GB limit */ - ss.attr.bytes = 0xcf3; /* G+DB+P+DPL3+S+Data */ + sreg.sel = cs.sel + 8; + sreg.base = 0; /* flat segment */ + sreg.limit = ~0u; /* 4GB limit */ + sreg.attr.bytes = 0xcf3; /* G+DB+P+DPL3+S+Data */ fail_if(ops->write_segment == NULL); if ( (rc = ops->write_segment(x86_seg_cs, &cs, ctxt)) != 0 || - (rc = ops->write_segment(x86_seg_ss, &ss, ctxt)) != 0 ) + (rc = ops->write_segment(x86_seg_ss, &sreg, ctxt)) != 0 ) goto done; _regs.eip = user64 ? _regs.edx : (uint32_t)_regs.edx;