xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Wei Liu <wei.liu2@citrix.com>
To: Xen-devel <xen-devel@lists.xenproject.org>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>,
	Wei Liu <wei.liu2@citrix.com>, Jan Beulich <JBeulich@suse.com>
Subject: [PATCH v4 01/27] x86: factor out common PV emulation code
Date: Thu, 8 Jun 2017 18:11:37 +0100	[thread overview]
Message-ID: <20170608171203.20416-2-wei.liu2@citrix.com> (raw)
In-Reply-To: <20170608171203.20416-1-wei.liu2@citrix.com>

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 <wei.liu2@citrix.com>
---
 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/guest_access.h>
+
+#include <asm/debugreg.h>
+
+#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 <asm/cpuid.h>
 #include <xsm/xsm.h>
 
+#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, &reg->base, &limit, &ar, 0) )
+        if ( !pv_emul_read_descriptor(sel, current, &reg->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)
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

  reply	other threads:[~2017-06-08 17:12 UTC|newest]

Thread overview: 72+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-08 17:11 [PATCH v4 00/27] x86: refactor trap handling code Wei Liu
2017-06-08 17:11 ` Wei Liu [this message]
2017-06-20 16:00   ` [PATCH v4 01/27] x86: factor out common PV emulation code Jan Beulich
2017-06-08 17:11 ` [PATCH v4 02/27] x86: move PV privileged instruction " Wei Liu
2017-06-20 16:03   ` Jan Beulich
2017-06-08 17:11 ` [PATCH v4 03/27] x86: move PV gate op " Wei Liu
2017-06-20 16:05   ` Jan Beulich
2017-06-08 17:11 ` [PATCH v4 04/27] x86: move PV invalid " Wei Liu
2017-06-20 16:21   ` Jan Beulich
2017-06-20 16:25     ` Wei Liu
2017-06-21  6:15       ` Jan Beulich
2017-06-21  8:57         ` Wei Liu
2017-06-21  9:09           ` Jan Beulich
2017-06-21  9:14             ` Wei Liu
2017-06-21  9:26               ` Jan Beulich
2017-06-21  9:29                 ` Wei Liu
2017-06-08 17:11 ` [PATCH v4 05/27] x86/traps: remove now unused inclusion of emulate.h Wei Liu
2017-06-20 16:21   ` Jan Beulich
2017-06-08 17:11 ` [PATCH v4 06/27] x86: clean up PV emulation code Wei Liu
2017-06-23 10:56   ` Andrew Cooper
2017-06-08 17:11 ` [PATCH v4 07/27] x86: move do_set_trap_table to pv/traps.c Wei Liu
2017-06-23 11:00   ` Andrew Cooper
2017-06-23 13:59     ` Wei Liu
2017-06-23 13:59       ` Andrew Cooper
2017-06-08 17:11 ` [PATCH v4 08/27] x86: move some misc PV hypercalls to misc-hypercalls.c Wei Liu
2017-06-23 11:02   ` Andrew Cooper
2017-06-08 17:11 ` [PATCH v4 09/27] x86/traps: move pv_inject_event to pv/traps.c Wei Liu
2017-06-23 11:04   ` Andrew Cooper
2017-06-08 17:11 ` [PATCH v4 10/27] x86/traps: move set_guest_{machine, nmi}_trapbounce Wei Liu
2017-06-23 11:05   ` Andrew Cooper
2017-06-08 17:11 ` [PATCH v4 11/27] x86:/traps: move {un, }register_guest_nmi_callback Wei Liu
2017-06-23 11:38   ` Andrew Cooper
2017-06-23 12:19     ` Andrew Cooper
2017-06-08 17:11 ` [PATCH v4 12/27] x86/traps: move guest_has_trap_callback to pv/traps.c Wei Liu
2017-06-23 12:01   ` Andrew Cooper
2017-06-08 17:11 ` [PATCH v4 13/27] x86: move toggle_guest_mode to pv/domain.c Wei Liu
2017-06-23 12:10   ` Andrew Cooper
2017-06-08 17:11 ` [PATCH v4 14/27] x86: move do_iret to pv/iret.c Wei Liu
2017-06-23 12:12   ` Andrew Cooper
2017-06-23 14:17     ` Wei Liu
2017-06-23 14:17       ` Andrew Cooper
2017-06-08 17:11 ` [PATCH v4 15/27] x86: move callback_op code to pv/callback.c Wei Liu
2017-06-08 17:11 ` [PATCH v4 16/27] x86/traps: factor out pv_trap_init Wei Liu
2017-06-23 12:31   ` Andrew Cooper
2017-06-23 13:55     ` Wei Liu
2017-06-08 17:11 ` [PATCH v4 17/27] x86/traps: move some PV specific functions and struct to pv/traps.c Wei Liu
2017-06-23 12:36   ` Andrew Cooper
2017-06-08 17:11 ` [PATCH v4 18/27] x86/traps: move init_int80_direct_trap " Wei Liu
2017-06-23 12:37   ` Andrew Cooper
2017-06-08 17:11 ` [PATCH v4 19/27] x86: move hypercall_page_initialise_ring3_kernel to pv/hypercall.c Wei Liu
2017-06-23 12:41   ` Andrew Cooper
2017-06-23 14:49     ` Wei Liu
2017-06-23 14:53       ` Andrew Cooper
2017-06-08 17:11 ` [PATCH v4 20/27] x86: move hypercall_page_initialise_ring1_kernel Wei Liu
2017-06-23 12:41   ` Andrew Cooper
2017-06-23 13:56     ` Wei Liu
2017-06-23 13:56       ` Andrew Cooper
2017-06-08 17:11 ` [PATCH v4 21/27] x86: move compat_set_trap_table along side the non-compat variant Wei Liu
2017-06-23 12:43   ` Andrew Cooper
2017-06-08 17:11 ` [PATCH v4 22/27] x86: move compat_iret along side its " Wei Liu
2017-06-23 12:44   ` Andrew Cooper
2017-06-08 17:11 ` [PATCH v4 23/27] x86: move the compat callback ops next to the " Wei Liu
2017-06-23 13:40   ` Jan Beulich
2017-06-08 17:12 ` [PATCH v4 24/27] x86: move compat_show_guest_statck near its " Wei Liu
2017-06-23 12:47   ` Andrew Cooper
2017-06-08 17:12 ` [PATCH v4 25/27] x86: remove the now empty x86_64/compat/traps.c Wei Liu
2017-06-23 12:47   ` Andrew Cooper
2017-06-08 17:12 ` [PATCH v4 26/27] x86: fix coding a style issue in asm-x86/traps.h Wei Liu
2017-06-23 12:48   ` Andrew Cooper
2017-06-08 17:12 ` [PATCH v4 27/27] x86: clean up traps.c Wei Liu
2017-06-23 12:50   ` Andrew Cooper
2017-06-23 13:45     ` Jan Beulich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170608171203.20416-2-wei.liu2@citrix.com \
    --to=wei.liu2@citrix.com \
    --cc=JBeulich@suse.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).