[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v4 01/27] x86: factor out common PV emulation code



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@xxxxxxxxxx>
---
 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@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.