From patchwork Thu Sep 8 13:42:56 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 9321411 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 3224160752 for ; Thu, 8 Sep 2016 13:45:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2027E2980E for ; Thu, 8 Sep 2016 13:45:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 10E1F2988B; Thu, 8 Sep 2016 13:45:40 +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 6DF682980E for ; Thu, 8 Sep 2016 13:45:39 +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 1bhzbb-0004r7-4e; Thu, 08 Sep 2016 13:43:03 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bhzbZ-0004qo-6N for xen-devel@lists.xenproject.org; Thu, 08 Sep 2016 13:43:01 +0000 Received: from [85.158.137.68] by server-4.bemta-3.messagelabs.com id 0C/4B-15788-4EA61D75; Thu, 08 Sep 2016 13:43:00 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrGIsWRWlGSWpSXmKPExsXS6fjDS/dx1sV wg+VTZCy+b5nM5MDocfjDFZYAxijWzLyk/IoE1ox1e9ewFnzxrdjyoYulgfGCaRcjJ4eQQJ7E w+372UBsXgE7iSfdrUwgtoSAocTT99eB4hwcLAKqEg0z5EHCbALqEm3PtrOChEUEDCTOHU0CM ZkF9CW2rWMBMYUFtCT+H+aFmG0nsWTBYRYQm1PAXmLKkieMICW8AoISf3cIg4SZgUoaL39nm8 DIMwshMwtJBsLWknj46xYLhK0tsWzha+ZZYGulJZb/44AIG0s0fz3MjKoEYszXoxtYFzByrGL UKE4tKkst0jU01EsqykzPKMlNzMzRNTQw1stNLS5OTE/NSUwq1kvOz93ECAxTBiDYwbj6t9Mh RkkOJiVRXp/iC+FCfEn5KZUZicUZ8UWlOanFhxg1ODgEtu1afYFRiiUvPy9VSYL3SubFcCHBo tT01Iq0zBxgJMGUSnDwKInwngZJ8xYXJOYWZ6ZDpE4xKkqJ8y4BSQiAJDJK8+DaYNF7iVFWSp iXEegoIZ6C1KLczBJU+VeM4hyMSsK8O0Gm8GTmlcBNfwW0mAlosdCp8yCLSxIRUlINjG273eM WtFt1aOyYwLbwj/tOre/l8W7Bp/30mOYufO2Qv+X65fusAopC6yVcObtd9KbxvDwTf9fph7C3 +HH/M3vyVsrPiak2+70x2KyY5/9MpwUqAWZbNSJDdRQV+v1CLH1WXqm8YK12W8Ngxq/zJ5M2P j26mOeKTEsWi8VmqZWqoiJ5O/5kKLEUZyQaajEXFScCAF81emzZAgAA X-Env-Sender: JBeulich@suse.com X-Msg-Ref: server-11.tower-31.messagelabs.com!1473342177!33387620!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 19241 invoked from network); 8 Sep 2016 13:42:59 -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; 8 Sep 2016 13:42:59 -0000 Received: from INET-PRV-MTA by prv-mh.provo.novell.com with Novell_GroupWise; Thu, 08 Sep 2016 07:42:56 -0600 Message-Id: <57D18700020000780010D264@prv-mh.provo.novell.com> X-Mailer: Novell GroupWise Internet Agent 14.2.1 Date: Thu, 08 Sep 2016 07:42:56 -0600 From: "Jan Beulich" To: "xen-devel" References: <57D18589020000780010D251@prv-mh.provo.novell.com> In-Reply-To: <57D18589020000780010D251@prv-mh.provo.novell.com> Mime-Version: 1.0 Cc: Andrew Cooper Subject: [Xen-devel] [PATCH 1/5] x86emul: support UMIP 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 To make this complete, also add support for SLDT and STR. Note that by just looking at the guest CR4 bit, this is independent of actually making available the UMIP feature to guests. Signed-off-by: Jan Beulich x86emul: support UMIP To make this complete, also add support for SLDT and STR. Note that by just looking at the guest CR4 bit, this is independent of actually making available the UMIP feature to guests. Signed-off-by: Jan Beulich --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -182,7 +182,7 @@ static const opcode_desc_t opcode_table[ static const opcode_desc_t twobyte_table[256] = { /* 0x00 - 0x07 */ - SrcMem16|ModRM, ImplicitOps|ModRM, ModRM, ModRM, + ModRM, ImplicitOps|ModRM, ModRM, ModRM, 0, ImplicitOps, ImplicitOps, ImplicitOps, /* 0x08 - 0x0F */ ImplicitOps, ImplicitOps, 0, ImplicitOps, @@ -421,6 +421,7 @@ typedef union { /* Control register flags. */ #define CR0_PE (1<<0) #define CR4_TSD (1<<2) +#define CR4_UMIP (1<<11) /* EFLAGS bit definitions. */ #define EFLG_VIP (1<<20) @@ -1484,6 +1485,17 @@ static bool is_aligned(enum x86_segment return !((reg.base + offs) & (size - 1)); } +static bool is_umip(struct x86_emulate_ctxt *ctxt, + const struct x86_emulate_ops *ops) +{ + unsigned long cr4; + + /* Intentionally not using mode_ring0() here to avoid its fail_if(). */ + return get_cpl(ctxt, ops) > 0 && + ops->read_cr && ops->read_cr(4, &cr4, ctxt) == X86EMUL_OKAY && + (cr4 & CR4_UMIP); +} + /* Inject a software interrupt/exception, emulating if needed. */ static int inject_swint(enum x86_swint_type type, uint8_t vector, uint8_t insn_len, @@ -2051,10 +2063,20 @@ x86_decode( break; case ext_0f: - case ext_0f3a: - case ext_8f08: - case ext_8f09: - case ext_8f0a: + switch ( b ) + { + case 0x00: /* Grp6 */ + switch ( modrm_reg & 6 ) + { + case 0: + d |= DstMem | SrcImplicit | Mov; + break; + case 2: case 4: + d |= SrcMem16; + break; + } + break; + } break; case ext_0f38: @@ -2070,6 +2092,12 @@ x86_decode( } break; + case ext_0f3a: + case ext_8f08: + case ext_8f09: + case ext_8f0a: + break; + default: ASSERT_UNREACHABLE(); } @@ -4177,14 +4205,31 @@ x86_emulate( } break; - case X86EMUL_OPC(0x0f, 0x00): /* Grp6 */ - fail_if((modrm_reg & 6) != 2); + case X86EMUL_OPC(0x0f, 0x00): /* Grp6 */ { + enum x86_segment seg = (modrm_reg & 1) ? x86_seg_tr : x86_seg_ldtr; + + fail_if(modrm_reg & 4); generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1); - generate_exception_if(!mode_ring0(), EXC_GP, 0); - if ( (rc = load_seg((modrm_reg & 1) ? x86_seg_tr : x86_seg_ldtr, - src.val, 0, NULL, ctxt, ops)) != 0 ) - goto done; + if ( modrm_reg & 2 ) + { + generate_exception_if(!mode_ring0(), EXC_GP, 0); + if ( (rc = load_seg(seg, src.val, 0, NULL, ctxt, ops)) != 0 ) + goto done; + } + else + { + struct segment_register reg; + + generate_exception_if(is_umip(ctxt, ops), EXC_GP, 0); + fail_if(!ops->read_segment); + if ( (rc = ops->read_segment(seg, ®, ctxt)) != 0 ) + goto done; + dst.val = reg.sel; + if ( dst.type == OP_MEM ) + dst.bytes = 2; + } break; + } case X86EMUL_OPC(0x0f, 0x01): /* Grp7 */ { struct segment_register reg; @@ -4282,6 +4327,7 @@ x86_emulate( case 0: /* sgdt */ case 1: /* sidt */ generate_exception_if(ea.type != OP_MEM, EXC_UD, -1); + generate_exception_if(is_umip(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, @@ -4316,6 +4362,7 @@ x86_emulate( goto done; break; case 4: /* smsw */ + generate_exception_if(is_umip(ctxt, ops), EXC_GP, 0); ea.bytes = (ea.type == OP_MEM) ? 2 : op_bytes; dst = ea; fail_if(ops->read_cr == NULL); --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -182,7 +182,7 @@ static const opcode_desc_t opcode_table[ static const opcode_desc_t twobyte_table[256] = { /* 0x00 - 0x07 */ - SrcMem16|ModRM, ImplicitOps|ModRM, ModRM, ModRM, + ModRM, ImplicitOps|ModRM, ModRM, ModRM, 0, ImplicitOps, ImplicitOps, ImplicitOps, /* 0x08 - 0x0F */ ImplicitOps, ImplicitOps, 0, ImplicitOps, @@ -421,6 +421,7 @@ typedef union { /* Control register flags. */ #define CR0_PE (1<<0) #define CR4_TSD (1<<2) +#define CR4_UMIP (1<<11) /* EFLAGS bit definitions. */ #define EFLG_VIP (1<<20) @@ -1484,6 +1485,17 @@ static bool is_aligned(enum x86_segment return !((reg.base + offs) & (size - 1)); } +static bool is_umip(struct x86_emulate_ctxt *ctxt, + const struct x86_emulate_ops *ops) +{ + unsigned long cr4; + + /* Intentionally not using mode_ring0() here to avoid its fail_if(). */ + return get_cpl(ctxt, ops) > 0 && + ops->read_cr && ops->read_cr(4, &cr4, ctxt) == X86EMUL_OKAY && + (cr4 & CR4_UMIP); +} + /* Inject a software interrupt/exception, emulating if needed. */ static int inject_swint(enum x86_swint_type type, uint8_t vector, uint8_t insn_len, @@ -2051,10 +2063,20 @@ x86_decode( break; case ext_0f: - case ext_0f3a: - case ext_8f08: - case ext_8f09: - case ext_8f0a: + switch ( b ) + { + case 0x00: /* Grp6 */ + switch ( modrm_reg & 6 ) + { + case 0: + d |= DstMem | SrcImplicit | Mov; + break; + case 2: case 4: + d |= SrcMem16; + break; + } + break; + } break; case ext_0f38: @@ -2070,6 +2092,12 @@ x86_decode( } break; + case ext_0f3a: + case ext_8f08: + case ext_8f09: + case ext_8f0a: + break; + default: ASSERT_UNREACHABLE(); } @@ -4177,14 +4205,31 @@ x86_emulate( } break; - case X86EMUL_OPC(0x0f, 0x00): /* Grp6 */ - fail_if((modrm_reg & 6) != 2); + case X86EMUL_OPC(0x0f, 0x00): /* Grp6 */ { + enum x86_segment seg = (modrm_reg & 1) ? x86_seg_tr : x86_seg_ldtr; + + fail_if(modrm_reg & 4); generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1); - generate_exception_if(!mode_ring0(), EXC_GP, 0); - if ( (rc = load_seg((modrm_reg & 1) ? x86_seg_tr : x86_seg_ldtr, - src.val, 0, NULL, ctxt, ops)) != 0 ) - goto done; + if ( modrm_reg & 2 ) + { + generate_exception_if(!mode_ring0(), EXC_GP, 0); + if ( (rc = load_seg(seg, src.val, 0, NULL, ctxt, ops)) != 0 ) + goto done; + } + else + { + struct segment_register reg; + + generate_exception_if(is_umip(ctxt, ops), EXC_GP, 0); + fail_if(!ops->read_segment); + if ( (rc = ops->read_segment(seg, ®, ctxt)) != 0 ) + goto done; + dst.val = reg.sel; + if ( dst.type == OP_MEM ) + dst.bytes = 2; + } break; + } case X86EMUL_OPC(0x0f, 0x01): /* Grp7 */ { struct segment_register reg; @@ -4282,6 +4327,7 @@ x86_emulate( case 0: /* sgdt */ case 1: /* sidt */ generate_exception_if(ea.type != OP_MEM, EXC_UD, -1); + generate_exception_if(is_umip(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, @@ -4316,6 +4362,7 @@ x86_emulate( goto done; break; case 4: /* smsw */ + generate_exception_if(is_umip(ctxt, ops), EXC_GP, 0); ea.bytes = (ea.type == OP_MEM) ? 2 : op_bytes; dst = ea; fail_if(ops->read_cr == NULL);