From patchwork Thu Jun 8 17:11:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wei Liu X-Patchwork-Id: 9776079 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 8EAA960350 for ; Thu, 8 Jun 2017 17:14:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 744F127165 for ; Thu, 8 Jun 2017 17:14:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 68E9028508; Thu, 8 Jun 2017 17:14:32 +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 A7EAC28438 for ; Thu, 8 Jun 2017 17:14:31 +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 1dJ0yj-0004sC-0y; Thu, 08 Jun 2017 17:12:13 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dJ0yh-0004r3-JC for xen-devel@lists.xenproject.org; Thu, 08 Jun 2017 17:12:11 +0000 Received: from [85.158.137.68] by server-7.bemta-3.messagelabs.com id F6/E3-02196-A6589395; Thu, 08 Jun 2017 17:12:10 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupnkeJIrShJLcpLzFFi42JxWrohUjer1TL SYP1MdovvWyYzOTB6HP5whSWAMYo1My8pvyKBNWPH/scsBb2xFW0TDzA3MM5z6GLk5JAQ8Jd4 sn0fK4jNJqAs8bOzlw3EFhHQk2g68JwRxGYWyJPo/PiRvYuRg0NYwEni2dJCkDCLgIrE73VtY CW8AhYSnWdOMkKMlJfY1XYRbCSngKXEks/TmUFahYBqencmgISFBBQkOqYfY4JoFZQ4OfMJC8 QmCYmDL14wT2DknYUkNQtJagEj0ypGjeLUorLUIl1Dc72kosz0jJLcxMwcXUMDY73c1OLixPT UnMSkYr3k/NxNjMDAYQCCHYwvT3seYpTkYFIS5VUEBpQQX1J+SmVGYnFGfFFpTmrxIUYZDg4l Cd7PzUA5waLU9NSKtMwcYAjDpCU4eJREeNc2AKV5iwsSc4sz0yFSpxh1ORb0bPjCJMSSl5+XK iXOewZkhgBIUUZpHtwIWDxdYpSVEuZlBDpKiKcgtSg3swRV/hWjOAejkjBvcgvQFJ7MvBK4Ta +AjmACOmLJOwuQI0oSEVJSDYy1V7ZNY0rZIPcgedObH9tsty1jZFhbtWHW/W1hUjqPZG873Tk lf/Vpta/k86Kgg+f9OTbPZXik5+FyUfmuIMOr+9f/mvw/81410dfRZftJW+GjcnK3ec321kze uXHH4Y/vA4okBVSNG/SXFzyrmim2qC6Ym/NpxOQD+Zf/Z0vnK72e8u/DL66lSizFGYmGWsxFx YkAtid1pKICAAA= X-Env-Sender: prvs=3259bf657=wei.liu2@citrix.com X-Msg-Ref: server-6.tower-31.messagelabs.com!1496941927!66198067!2 X-Originating-IP: [66.165.176.89] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n, received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 9.4.19; banners=-,-,- X-VirusChecked: Checked Received: (qmail 28662 invoked from network); 8 Jun 2017 17:12:09 -0000 Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89) by server-6.tower-31.messagelabs.com with RC4-SHA encrypted SMTP; 8 Jun 2017 17:12:09 -0000 X-IronPort-AV: E=Sophos;i="5.39,315,1493683200"; d="scan'208";a="427128896" From: Wei Liu To: Xen-devel Date: Thu, 8 Jun 2017 18:11:37 +0100 Message-ID: <20170608171203.20416-2-wei.liu2@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170608171203.20416-1-wei.liu2@citrix.com> References: <20170608171203.20416-1-wei.liu2@citrix.com> MIME-Version: 1.0 Cc: Andrew Cooper , Wei Liu , Jan Beulich Subject: [Xen-devel] [PATCH v4 01/27] x86: factor out common PV emulation code 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 We're going to split PV emulation code into several files. This patch extracts the functions needed by them into a dedicated file. The functions are now prefixed with "pv_emul_" and exported via a local header file. While at it, change bool_t to bool. Signed-off-by: Wei Liu Acked-by: Jan Beulich --- xen/arch/x86/pv/Makefile | 1 + xen/arch/x86/pv/emulate.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++ xen/arch/x86/pv/emulate.h | 10 +++++ xen/arch/x86/traps.c | 95 ++++++++------------------------------------- 4 files changed, 126 insertions(+), 78 deletions(-) create mode 100644 xen/arch/x86/pv/emulate.c create mode 100644 xen/arch/x86/pv/emulate.h diff --git a/xen/arch/x86/pv/Makefile b/xen/arch/x86/pv/Makefile index 489a9f59cb..564202cbb7 100644 --- a/xen/arch/x86/pv/Makefile +++ b/xen/arch/x86/pv/Makefile @@ -3,3 +3,4 @@ obj-y += traps.o obj-bin-y += dom0_build.init.o obj-y += domain.o +obj-y += emulate.o diff --git a/xen/arch/x86/pv/emulate.c b/xen/arch/x86/pv/emulate.c new file mode 100644 index 0000000000..5750c7699b --- /dev/null +++ b/xen/arch/x86/pv/emulate.c @@ -0,0 +1,98 @@ +/****************************************************************************** + * arch/x86/pv/emulate.c + * + * Common PV emulation code + * + * Modifications to Linux original are copyright (c) 2002-2004, K A Fraser + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see . + */ + +#include + +#include + +#include "emulate.h" + +int pv_emul_read_descriptor(unsigned int sel, const struct vcpu *v, + unsigned long *base, unsigned long *limit, + unsigned int *ar, bool insn_fetch) +{ + struct desc_struct desc; + + if ( sel < 4) + desc.b = desc.a = 0; + else if ( __get_user(desc, + (const struct desc_struct *)(!(sel & 4) + ? GDT_VIRT_START(v) + : LDT_VIRT_START(v)) + + (sel >> 3)) ) + return 0; + if ( !insn_fetch ) + desc.b &= ~_SEGMENT_L; + + *ar = desc.b & 0x00f0ff00; + if ( !(desc.b & _SEGMENT_L) ) + { + *base = ((desc.a >> 16) + ((desc.b & 0xff) << 16) + + (desc.b & 0xff000000)); + *limit = (desc.a & 0xffff) | (desc.b & 0x000f0000); + if ( desc.b & _SEGMENT_G ) + *limit = ((*limit + 1) << 12) - 1; +#ifndef NDEBUG + if ( sel > 3 ) + { + unsigned int a, l; + unsigned char valid; + + asm volatile ( + "larl %2,%0 ; setz %1" + : "=r" (a), "=qm" (valid) : "rm" (sel)); + BUG_ON(valid && ((a & 0x00f0ff00) != *ar)); + asm volatile ( + "lsll %2,%0 ; setz %1" + : "=r" (l), "=qm" (valid) : "rm" (sel)); + BUG_ON(valid && (l != *limit)); + } +#endif + } + else + { + *base = 0UL; + *limit = ~0UL; + } + + return 1; +} + +void pv_emul_instruction_done(struct cpu_user_regs *regs, unsigned long rip) +{ + regs->rip = rip; + regs->eflags &= ~X86_EFLAGS_RF; + if ( regs->eflags & X86_EFLAGS_TF ) + { + current->arch.debugreg[6] |= DR_STEP | DR_STATUS_RESERVED_ONE; + pv_inject_hw_exception(TRAP_debug, X86_EVENT_NO_EC); + } +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/arch/x86/pv/emulate.h b/xen/arch/x86/pv/emulate.h new file mode 100644 index 0000000000..b2b1192d48 --- /dev/null +++ b/xen/arch/x86/pv/emulate.h @@ -0,0 +1,10 @@ +#ifndef __PV_EMULATE_H__ +#define __PV_EMULATE_H__ + +int pv_emul_read_descriptor(unsigned int sel, const struct vcpu *v, + unsigned long *base, unsigned long *limit, + unsigned int *ar, bool insn_fetch); + +void pv_emul_instruction_done(struct cpu_user_regs *regs, unsigned long rip); + +#endif /* __PV_EMULATE_H__ */ diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 52e740f11f..dcc48f9860 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -78,6 +78,8 @@ #include #include +#include "pv/emulate.h" + /* * opt_nmi: one of 'ignore', 'dom0', or 'fatal'. * fatal: Xen prints diagnostic message and then hangs. @@ -694,17 +696,6 @@ void pv_inject_event(const struct x86_event *event) } } -static void instruction_done(struct cpu_user_regs *regs, unsigned long rip) -{ - regs->rip = rip; - regs->eflags &= ~X86_EFLAGS_RF; - if ( regs->eflags & X86_EFLAGS_TF ) - { - current->arch.debugreg[6] |= DR_STEP | DR_STATUS_RESERVED_ONE; - pv_inject_hw_exception(TRAP_debug, X86_EVENT_NO_EC); - } -} - static unsigned int check_guest_io_breakpoint(struct vcpu *v, unsigned int port, unsigned int len) { @@ -1027,7 +1018,7 @@ static int emulate_invalid_rdtscp(struct cpu_user_regs *regs) return 0; eip += sizeof(opcode); pv_soft_rdtsc(v, regs, 1); - instruction_done(regs, eip); + pv_emul_instruction_done(regs, eip); return EXCRET_fault_fixed; } @@ -1075,7 +1066,7 @@ static int emulate_forced_invalid_op(struct cpu_user_regs *regs) regs->rcx = res.c; regs->rdx = res.d; - instruction_done(regs, eip); + pv_emul_instruction_done(regs, eip); trace_trap_one_addr(TRC_PV_FORCED_INVALID_OP, regs->rip); @@ -1623,60 +1614,6 @@ long do_fpu_taskswitch(int set) return 0; } -static int read_descriptor(unsigned int sel, - const struct vcpu *v, - unsigned long *base, - unsigned long *limit, - unsigned int *ar, - bool_t insn_fetch) -{ - struct desc_struct desc; - - if ( sel < 4) - desc.b = desc.a = 0; - else if ( __get_user(desc, - (const struct desc_struct *)(!(sel & 4) - ? GDT_VIRT_START(v) - : LDT_VIRT_START(v)) - + (sel >> 3)) ) - return 0; - if ( !insn_fetch ) - desc.b &= ~_SEGMENT_L; - - *ar = desc.b & 0x00f0ff00; - if ( !(desc.b & _SEGMENT_L) ) - { - *base = ((desc.a >> 16) + ((desc.b & 0xff) << 16) + - (desc.b & 0xff000000)); - *limit = (desc.a & 0xffff) | (desc.b & 0x000f0000); - if ( desc.b & _SEGMENT_G ) - *limit = ((*limit + 1) << 12) - 1; -#ifndef NDEBUG - if ( sel > 3 ) - { - unsigned int a, l; - unsigned char valid; - - asm volatile ( - "larl %2,%0 ; setz %1" - : "=r" (a), "=qm" (valid) : "rm" (sel)); - BUG_ON(valid && ((a & 0x00f0ff00) != *ar)); - asm volatile ( - "lsll %2,%0 ; setz %1" - : "=r" (l), "=qm" (valid) : "rm" (sel)); - BUG_ON(valid && (l != *limit)); - } -#endif - } - else - { - *base = 0UL; - *limit = ~0UL; - } - - return 1; -} - static int read_gate_descriptor(unsigned int gate_sel, const struct vcpu *v, unsigned int *sel, @@ -1841,7 +1778,8 @@ static int priv_op_read_segment(enum x86_segment seg, default: return X86EMUL_UNHANDLEABLE; } - if ( !read_descriptor(sel, current, ®->base, &limit, &ar, 0) ) + if ( !pv_emul_read_descriptor(sel, current, ®->base, + &limit, &ar, 0) ) return X86EMUL_UNHANDLEABLE; reg->limit = limit; @@ -2987,8 +2925,8 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) int rc; unsigned int eflags, ar; - if ( !read_descriptor(regs->cs, curr, &ctxt.cs.base, &ctxt.cs.limit, - &ar, 1) || + if ( !pv_emul_read_descriptor(regs->cs, curr, &ctxt.cs.base, + &ctxt.cs.limit, &ar, 1) || !(ar & _SEGMENT_S) || !(ar & _SEGMENT_P) || !(ar & _SEGMENT_CODE) ) @@ -3110,7 +3048,7 @@ static int gate_op_read( unsigned int ar; ASSERT(!goc->insn_fetch); - if ( !read_descriptor(sel, current, &addr, &limit, &ar, 0) || + if ( !pv_emul_read_descriptor(sel, current, &addr, &limit, &ar, 0) || !(ar & _SEGMENT_S) || !(ar & _SEGMENT_P) || ((ar & _SEGMENT_CODE) && !(ar & _SEGMENT_WR)) ) @@ -3170,8 +3108,8 @@ static void emulate_gate_op(struct cpu_user_regs *regs) * Decode instruction (and perhaps operand) to determine RPL, * whether this is a jump or a call, and the call return offset. */ - if ( !read_descriptor(regs->cs, v, &ctxt.cs.base, &ctxt.cs.limit, - &ar, 0) || + if ( !pv_emul_read_descriptor(regs->cs, v, &ctxt.cs.base, &ctxt.cs.limit, + &ar, 0) || !(ar & _SEGMENT_S) || !(ar & _SEGMENT_P) || !(ar & _SEGMENT_CODE) ) @@ -3243,7 +3181,7 @@ static void emulate_gate_op(struct cpu_user_regs *regs) return; } - if ( !read_descriptor(sel, v, &base, &limit, &ar, 0) || + if ( !pv_emul_read_descriptor(sel, v, &base, &limit, &ar, 0) || !(ar & _SEGMENT_S) || !(ar & _SEGMENT_CODE) || (!jump || (ar & _SEGMENT_EC) ? @@ -3293,7 +3231,7 @@ static void emulate_gate_op(struct cpu_user_regs *regs) esp = v->arch.pv_vcpu.kernel_sp; ss = v->arch.pv_vcpu.kernel_ss; if ( (ss & 3) != (sel & 3) || - !read_descriptor(ss, v, &base, &limit, &ar, 0) || + !pv_emul_read_descriptor(ss, v, &base, &limit, &ar, 0) || ((ar >> 13) & 3) != (sel & 3) || !(ar & _SEGMENT_S) || (ar & _SEGMENT_CODE) || @@ -3320,7 +3258,8 @@ static void emulate_gate_op(struct cpu_user_regs *regs) { const unsigned int *ustkp; - if ( !read_descriptor(regs->ss, v, &base, &limit, &ar, 0) || + if ( !pv_emul_read_descriptor(regs->ss, v, &base, + &limit, &ar, 0) || ((ar >> 13) & 3) != (regs->cs & 3) || !(ar & _SEGMENT_S) || (ar & _SEGMENT_CODE) || @@ -3354,7 +3293,7 @@ static void emulate_gate_op(struct cpu_user_regs *regs) sel |= (regs->cs & 3); esp = regs->rsp; ss = regs->ss; - if ( !read_descriptor(ss, v, &base, &limit, &ar, 0) || + if ( !pv_emul_read_descriptor(ss, v, &base, &limit, &ar, 0) || ((ar >> 13) & 3) != (sel & 3) ) { pv_inject_hw_exception(TRAP_gp_fault, regs->error_code); @@ -3382,7 +3321,7 @@ static void emulate_gate_op(struct cpu_user_regs *regs) sel |= (regs->cs & 3); regs->cs = sel; - instruction_done(regs, off); + pv_emul_instruction_done(regs, off); } void do_general_protection(struct cpu_user_regs *regs)