All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] xen: add support for skipping the current instruction
@ 2014-09-09  2:22 Mihai Donțu
  2014-09-09  2:28 ` [PATCH 1/3] x86: add support for computing the instruction length Mihai Donțu
                   ` (3 more replies)
  0 siblings, 4 replies; 21+ messages in thread
From: Mihai Donțu @ 2014-09-09  2:22 UTC (permalink / raw)
  To: xen-devel

Hi,

Răzvan Cojocaru has posted a patch in July that added support for
computing the length of the instruction that generated the VMEXIT:

http://lists.xen.org/archives/html/xen-devel/2014-07/msg00314.html

which he then split into two in order to give himself more time to
think about Andrew's proposal to extend the existent x86 emulator. I
offered to take that off his hands as he was already working to get
several patches in.

The initial code was an almost verbatim copy from Linux, with a very
small change to make it compile within xen (replaced 'asm/string.h'
with 'xen/string.h').

I spent some time to determine what the code save would be if we were
to make use of existent xen functionality and my first impression is
that the increase in complexity of an already very complex machinery
(caused by both the nature of the architecture and by the design of the
emulator itself) would not make it worthwhile.

The starting point would be x86_emulate() which uses a carefully coded
switch() to walk through the opcode groups, but it only covers a subset
of those and, obviously, expects one to add not just instruction length
calculation (ie. next eip/rip) but also _actual_ emulation to which I
don't think anyone can commit given the architecture complexity (think
MMX, SSEn, AVXn etc). The opportunity for bugs makes this task rather
prohibitive.

Masami Hiramatsu, the author of the Linux code, most likely came to the
same realization and used a rather simple approach: created
x86-opcode-map.txt in which he simply lists the opcode classes in a
fairly human readable way. Then he uses an awk script to generate the
core of the machinery to which he added a couple of helper functions. I
decided to keep this part and see if I can replace some of the helpers,
but aside insn_fetch_bytes() which relies on previous calculations made
in x86_emulate(), I wasn't able to identify any other code-reuse
opportunities. Also, I don't yet have the courage to shuffle code
around in x86_emulate.c. :-)

In conclusion, I would opt to bring Masami's code in with very little
changes possible (other than coding style which can be handled by a
script) so that future updates can be easily ported to xen.

What follows are three patches:
  1. adds Masami's et al code (insn_get_length());
  2. adds a user in emulate.c;
  3. a clang-format script that can be used to do the bulk of the
  coding style work on the imported files (should someone else other
  than me were to do it).

The motivation behind the 'instruction skipping' idea is to allow
memory introspection technologies to instruct Xen to jump over
instructions that reside in memory areas of the guest that are marked
as NX in EPT (eg. heap/stack of user processes). In such situations,
maintaining the vCPU register state is not needed and, as a bonus,
expedites the termination of the in-guest process that attempted to
execute the code.

Thanks,

-- 
Mihai Donțu

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 1/3] x86: add support for computing the instruction length
  2014-09-09  2:22 [PATCH 0/3] xen: add support for skipping the current instruction Mihai Donțu
@ 2014-09-09  2:28 ` Mihai Donțu
  2014-09-09  8:47   ` Mihai Donțu
  2014-09-09  2:29 ` [PATCH 2/3] x86/hvm: implement hvm_get_insn_length() Mihai Donțu
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 21+ messages in thread
From: Mihai Donțu @ 2014-09-09  2:28 UTC (permalink / raw)
  To: xen-devel; +Cc: Mihai Donțu, keir, jbeulich

This patch adds support for computing the length of an instruction. The entire
logic relies on a set of opcode tables generated by gen-insn-attr-x86.awk from
x86-opcode-map.txt and a number of small helper functions. It originated in
Linux, where it was added by Masami Hiramatsu. Since it's an almost identical
copy, it's separated from the x86 emulator, simplifying future updates.

---
Changed since v1:
  * adjusted the coding style to match the rest of xen
  * moved the source files into x86/x86_emulate
  * replaced inat-tables.c with x86-opcode-map.txt and gen-insn-attr-x86.awk
    that are used to generate it

Signed-off-by: Mihai Donțu <mdontu@bitdefender.com>
---
 xen/arch/x86/Makefile                       |  11 +-
 xen/arch/x86/x86_emulate.c                  |   2 +
 xen/arch/x86/x86_emulate/inat.c             |  98 +++
 xen/arch/x86/x86_emulate/insn.c             | 624 ++++++++++++++++++
 xen/arch/x86/x86_emulate/x86-opcode-map.txt | 961 ++++++++++++++++++++++++++++
 xen/include/asm-x86/inat.h                  | 219 +++++++
 xen/include/asm-x86/inat_types.h            |  29 +
 xen/include/asm-x86/insn.h                  | 201 ++++++
 xen/tools/gen-insn-attr-x86.awk             | 386 +++++++++++
 9 files changed, 2529 insertions(+), 2 deletions(-)
 create mode 100644 xen/arch/x86/x86_emulate/inat.c
 create mode 100644 xen/arch/x86/x86_emulate/insn.c
 create mode 100644 xen/arch/x86/x86_emulate/x86-opcode-map.txt
 create mode 100644 xen/include/asm-x86/inat.h
 create mode 100644 xen/include/asm-x86/inat_types.h
 create mode 100644 xen/include/asm-x86/insn.h
 create mode 100644 xen/tools/gen-insn-attr-x86.awk

diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index c1e244d..63529d3 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -62,7 +62,11 @@ obj-y += xstate.o
 
 obj-$(crash_debug) += gdbstub.o
 
-x86_emulate.o: x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h
+inat_tables_script = $(BASEDIR)/tools/gen-insn-attr-x86.awk
+inat_tables_maps = $(BASEDIR)/arch/x86/x86_emulate/x86-opcode-map.txt
+
+x86_emulate.o: x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h \
+	x86_emulate/inat.c x86_emulate/insn.c x86_emulate/inat-tables.c
 
 efi-$(x86_64) := $(shell if [ ! -r $(BASEDIR)/include/xen/compile.h -o \
                                 -O $(BASEDIR)/include/xen/compile.h ]; then \
@@ -165,9 +169,12 @@ boot/mkelf32: boot/mkelf32.c
 efi/mkreloc: efi/mkreloc.c
 	$(HOSTCC) $(HOSTCFLAGS) -g -o $@ $<
 
+x86_emulate/inat-tables.c: $(inat_tables_script) $(inat_tables_maps)
+	awk -f $(inat_tables_script) $(inat_tables_maps) > $@ || rm -f $@
+
 .PHONY: clean
 clean::
 	rm -f asm-offsets.s *.lds boot/*.o boot/*~ boot/core boot/mkelf32
 	rm -f $(BASEDIR)/.xen-syms.[0-9]* boot/.*.d
 	rm -f $(BASEDIR)/.xen.efi.[0-9]* efi/*.o efi/.*.d efi/*.efi efi/disabled efi/mkreloc
-	rm -f boot/reloc.S boot/reloc.lnk boot/reloc.bin
+	rm -f boot/reloc.S boot/reloc.lnk boot/reloc.bin x86_emulate/inat-tables.c
diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c
index 79b4ab3..1d43bb1 100644
--- a/xen/arch/x86/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate.c
@@ -22,3 +22,5 @@
         cpu_has_amd_erratum(&current_cpu_data, AMD_ERRATUM_##nr)
 
 #include "x86_emulate/x86_emulate.c"
+#include "x86_emulate/inat.c"
+#include "x86_emulate/insn.c"
diff --git a/xen/arch/x86/x86_emulate/inat.c b/xen/arch/x86/x86_emulate/inat.c
new file mode 100644
index 0000000..e4251ba
--- /dev/null
+++ b/xen/arch/x86/x86_emulate/inat.c
@@ -0,0 +1,98 @@
+/*
+ * x86 instruction attribute tables
+ *
+ * Written by Masami Hiramatsu <mhiramat@redhat.com>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+#include <asm/insn.h>
+
+/* Attribute tables are generated from opcode map */
+#include "inat-tables.c"
+
+/* Attribute search APIs */
+insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode)
+{
+    return inat_primary_table[opcode];
+}
+
+int inat_get_last_prefix_id(insn_byte_t last_pfx)
+{
+    insn_attr_t lpfx_attr;
+
+    lpfx_attr = inat_get_opcode_attribute(last_pfx);
+    return inat_last_prefix_id(lpfx_attr);
+}
+
+insn_attr_t inat_get_escape_attribute(insn_byte_t opcode, int lpfx_id,
+                                      insn_attr_t esc_attr)
+{
+    const insn_attr_t *table;
+    int n;
+
+    n = inat_escape_id(esc_attr);
+
+    table = inat_escape_tables[n][0];
+    if ( !table )
+        return 0;
+    if ( inat_has_variant(table[opcode]) && lpfx_id )
+    {
+        table = inat_escape_tables[n][lpfx_id];
+        if ( !table )
+            return 0;
+    }
+    return table[opcode];
+}
+
+insn_attr_t inat_get_group_attribute(insn_byte_t modrm, int lpfx_id,
+                                     insn_attr_t grp_attr)
+{
+    const insn_attr_t *table;
+    int n;
+
+    n = inat_group_id(grp_attr);
+
+    table = inat_group_tables[n][0];
+    if ( !table )
+        return inat_group_common_attribute(grp_attr);
+    if ( inat_has_variant(table[X86_MODRM_REG(modrm)]) && lpfx_id )
+    {
+        table = inat_group_tables[n][lpfx_id];
+        if ( !table )
+            return inat_group_common_attribute(grp_attr);
+    }
+    return table[X86_MODRM_REG(modrm)] | inat_group_common_attribute(grp_attr);
+}
+
+insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, insn_byte_t vex_m,
+                                   insn_byte_t vex_p)
+{
+    const insn_attr_t *table;
+    if ( vex_m > X86_VEX_M_MAX || vex_p > INAT_LSTPFX_MAX )
+        return 0;
+    /* At first, this checks the master table */
+    table = inat_avx_tables[vex_m][0];
+    if ( !table )
+        return 0;
+    if ( !inat_is_group(table[opcode]) && vex_p )
+    {
+        /* If this is not a group, get attribute directly */
+        table = inat_avx_tables[vex_m][vex_p];
+        if ( !table )
+            return 0;
+    }
+    return table[opcode];
+}
diff --git a/xen/arch/x86/x86_emulate/insn.c b/xen/arch/x86/x86_emulate/insn.c
new file mode 100644
index 0000000..4d7416e
--- /dev/null
+++ b/xen/arch/x86/x86_emulate/insn.c
@@ -0,0 +1,624 @@
+/*
+ * x86 instruction analysis
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004, 2009
+ */
+
+#include <xen/string.h>
+#include <asm/inat.h>
+#include <asm/insn.h>
+
+/* Verify next sizeof(t) bytes can be on the same instruction */
+#define validate_next(t, insn, n) \
+    ((insn)->next_byte + sizeof(t) + n - (insn)->kaddr <= MAX_INSN_SIZE)
+
+#define __get_next(t, insn)           \
+    (                                 \
+        {                             \
+        t r = *(t *)insn->next_byte;  \
+        insn->next_byte += sizeof(t); \
+        r;                            \
+        })
+
+#define __peek_nbyte_next(t, insn, n)        \
+    (                                        \
+        {                                    \
+        t r = *(t *)((insn)->next_byte + n); \
+        r;                                   \
+        })
+
+#define get_next(t, insn)                         \
+    (                                             \
+        {                                         \
+        if ( unlikely(!validate_next(t, insn, 0)) ) \
+            goto err_out;                         \
+        __get_next(t, insn);                      \
+        })
+
+#define peek_nbyte_next(t, insn, n)               \
+    (                                             \
+        {                                         \
+        if ( unlikely(!validate_next(t, insn, n)) ) \
+            goto err_out;                         \
+        __peek_nbyte_next(t, insn, n);            \
+        })
+
+#define peek_next(t, insn) peek_nbyte_next(t, insn, 0)
+
+/**
+ * insn_init() - initialize struct insn
+ * @insn:	&struct insn to be initialized
+ * @kaddr:	address (in kernel memory) of instruction (or copy thereof)
+ * @x86_64:	!0 for 64-bit kernel or 64-bit app
+ */
+void insn_init(struct insn *insn, const void *kaddr, int x86_64)
+{
+    memset(insn, 0, sizeof(*insn));
+    insn->kaddr = kaddr;
+    insn->next_byte = kaddr;
+    insn->x86_64 = x86_64 ? 1 : 0;
+    insn->opnd_bytes = 4;
+    if ( x86_64 )
+        insn->addr_bytes = 8;
+    else
+        insn->addr_bytes = 4;
+}
+
+/**
+ * insn_get_prefixes - scan x86 instruction prefix bytes
+ * @insn:	&struct insn containing instruction
+ *
+ * Populates the @insn->prefixes bitmap, and updates @insn->next_byte
+ * to point to the (first) opcode.  No effect if @insn->prefixes.got
+ * is already set.
+ */
+void insn_get_prefixes(struct insn *insn)
+{
+    struct insn_field *prefixes = &insn->prefixes;
+    insn_attr_t attr;
+    insn_byte_t b, lb;
+    int i, nb;
+
+    if ( prefixes->got )
+        return;
+
+    nb = 0;
+    lb = 0;
+    b = peek_next(insn_byte_t, insn);
+    attr = inat_get_opcode_attribute(b);
+    while ( inat_is_legacy_prefix(attr) )
+    {
+        /* Skip if same prefix */
+        for (i = 0; i < nb; i++)
+            if ( prefixes->bytes[i] == b )
+                goto found;
+        if ( nb == 4 )
+            /* Invalid instruction */
+            break;
+        prefixes->bytes[nb++] = b;
+        if ( inat_is_address_size_prefix(attr) )
+        {
+            /* address size switches 2/4 or 4/8 */
+            if ( insn->x86_64 )
+                insn->addr_bytes ^= 12;
+            else
+                insn->addr_bytes ^= 6;
+        }
+        else if ( inat_is_operand_size_prefix(attr) )
+        {
+            /* oprand size switches 2/4 */
+            insn->opnd_bytes ^= 6;
+        }
+    found:
+        prefixes->nbytes++;
+        insn->next_byte++;
+        lb = b;
+        b = peek_next(insn_byte_t, insn);
+        attr = inat_get_opcode_attribute(b);
+    }
+    /* Set the last prefix */
+    if ( lb && lb != insn->prefixes.bytes[3] )
+    {
+        if ( unlikely(insn->prefixes.bytes[3]) )
+        {
+            /* Swap the last prefix */
+            b = insn->prefixes.bytes[3];
+            for (i = 0; i < nb; i++)
+                if ( prefixes->bytes[i] == lb )
+                    prefixes->bytes[i] = b;
+        }
+        insn->prefixes.bytes[3] = lb;
+    }
+
+    /* Decode REX prefix */
+    if ( insn->x86_64 )
+    {
+        b = peek_next(insn_byte_t, insn);
+        attr = inat_get_opcode_attribute(b);
+        if ( inat_is_rex_prefix(attr) )
+        {
+            insn->rex_prefix.value = b;
+            insn->rex_prefix.nbytes = 1;
+            insn->next_byte++;
+            if ( X86_REX_W(b) )
+                /* REX.W overrides opnd_size */
+                insn->opnd_bytes = 8;
+        }
+    }
+    insn->rex_prefix.got = 1;
+
+    /* Decode VEX prefix */
+    b = peek_next(insn_byte_t, insn);
+    attr = inat_get_opcode_attribute(b);
+    if ( inat_is_vex_prefix(attr) )
+    {
+        insn_byte_t b2 = peek_nbyte_next(insn_byte_t, insn, 1);
+        if ( !insn->x86_64 )
+        {
+            /*
+             * In 32-bits mode, if the [7:6] bits (mod bits of
+             * ModRM) on the second byte are not 11b, it is
+             * LDS or LES.
+             */
+            if ( X86_MODRM_MOD(b2) != 3 )
+                goto vex_end;
+        }
+        insn->vex_prefix.bytes[0] = b;
+        insn->vex_prefix.bytes[1] = b2;
+        if ( inat_is_vex3_prefix(attr) )
+        {
+            b2 = peek_nbyte_next(insn_byte_t, insn, 2);
+            insn->vex_prefix.bytes[2] = b2;
+            insn->vex_prefix.nbytes = 3;
+            insn->next_byte += 3;
+            if ( insn->x86_64 && X86_VEX_W(b2) )
+                /* VEX.W overrides opnd_size */
+                insn->opnd_bytes = 8;
+        }
+        else
+        {
+            insn->vex_prefix.nbytes = 2;
+            insn->next_byte += 2;
+        }
+    }
+vex_end:
+    insn->vex_prefix.got = 1;
+
+    prefixes->got = 1;
+
+err_out:
+    return;
+}
+
+/**
+ * insn_get_opcode - collect opcode(s)
+ * @insn:	&struct insn containing instruction
+ *
+ * Populates @insn->opcode, updates @insn->next_byte to point past the
+ * opcode byte(s), and set @insn->attr (except for groups).
+ * If necessary, first collects any preceding (prefix) bytes.
+ * Sets @insn->opcode.value = opcode1.  No effect if @insn->opcode.got
+ * is already 1.
+ */
+void insn_get_opcode(struct insn *insn)
+{
+    struct insn_field *opcode = &insn->opcode;
+    insn_byte_t op;
+    int pfx_id;
+    if ( opcode->got )
+        return;
+    if ( !insn->prefixes.got )
+        insn_get_prefixes(insn);
+
+    /* Get first opcode */
+    op = get_next(insn_byte_t, insn);
+    opcode->bytes[0] = op;
+    opcode->nbytes = 1;
+
+    /* Check if there is VEX prefix or not */
+    if ( insn_is_avx(insn) )
+    {
+        insn_byte_t m, p;
+        m = insn_vex_m_bits(insn);
+        p = insn_vex_p_bits(insn);
+        insn->attr = inat_get_avx_attribute(op, m, p);
+        if ( !inat_accept_vex(insn->attr) && !inat_is_group(insn->attr) )
+            insn->attr = 0; /* This instruction is bad */
+        goto end;           /* VEX has only 1 byte for opcode */
+    }
+
+    insn->attr = inat_get_opcode_attribute(op);
+    while ( inat_is_escape(insn->attr) )
+    {
+        /* Get escaped opcode */
+        op = get_next(insn_byte_t, insn);
+        opcode->bytes[opcode->nbytes++] = op;
+        pfx_id = insn_last_prefix_id(insn);
+        insn->attr = inat_get_escape_attribute(op, pfx_id, insn->attr);
+    }
+    if ( inat_must_vex(insn->attr) )
+        insn->attr = 0; /* This instruction is bad */
+end:
+    opcode->got = 1;
+
+err_out:
+    return;
+}
+
+/**
+ * insn_get_modrm - collect ModRM byte, if any
+ * @insn:	&struct insn containing instruction
+ *
+ * Populates @insn->modrm and updates @insn->next_byte to point past the
+ * ModRM byte, if any.  If necessary, first collects the preceding bytes
+ * (prefixes and opcode(s)).  No effect if @insn->modrm.got is already 1.
+ */
+void insn_get_modrm(struct insn *insn)
+{
+    struct insn_field *modrm = &insn->modrm;
+    insn_byte_t pfx_id, mod;
+    if ( modrm->got )
+        return;
+    if ( !insn->opcode.got )
+        insn_get_opcode(insn);
+
+    if ( inat_has_modrm(insn->attr) )
+    {
+        mod = get_next(insn_byte_t, insn);
+        modrm->value = mod;
+        modrm->nbytes = 1;
+        if ( inat_is_group(insn->attr) )
+        {
+            pfx_id = insn_last_prefix_id(insn);
+            insn->attr = inat_get_group_attribute(mod, pfx_id, insn->attr);
+            if ( insn_is_avx(insn) && !inat_accept_vex(insn->attr) )
+                insn->attr = 0; /* This is bad */
+        }
+    }
+
+    if ( insn->x86_64 && inat_is_force64(insn->attr) )
+        insn->opnd_bytes = 8;
+    modrm->got = 1;
+
+err_out:
+    return;
+}
+
+/**
+ * insn_rip_relative() - Does instruction use RIP-relative addressing mode?
+ * @insn:	&struct insn containing instruction
+ *
+ * If necessary, first collects the instruction up to and including the
+ * ModRM byte.  No effect if @insn->x86_64 is 0.
+ */
+int insn_rip_relative(struct insn *insn)
+{
+    struct insn_field *modrm = &insn->modrm;
+
+    if ( !insn->x86_64 )
+        return 0;
+    if ( !modrm->got )
+        insn_get_modrm(insn);
+    /*
+     * For rip-relative instructions, the mod field (top 2 bits)
+     * is zero and the r/m field (bottom 3 bits) is 0x5.
+     */
+    return (modrm->nbytes && (modrm->value & 0xc7) == 0x5);
+}
+
+/**
+ * insn_get_sib() - Get the SIB byte of instruction
+ * @insn:	&struct insn containing instruction
+ *
+ * If necessary, first collects the instruction up to and including the
+ * ModRM byte.
+ */
+void insn_get_sib(struct insn *insn)
+{
+    insn_byte_t modrm;
+
+    if ( insn->sib.got )
+        return;
+    if ( !insn->modrm.got )
+        insn_get_modrm(insn);
+    if ( insn->modrm.nbytes )
+    {
+        modrm = (insn_byte_t)insn->modrm.value;
+        if ( insn->addr_bytes != 2 && X86_MODRM_MOD(modrm ) != 3 &&
+            X86_MODRM_RM(modrm) == 4)
+        {
+            insn->sib.value = get_next(insn_byte_t, insn);
+            insn->sib.nbytes = 1;
+        }
+    }
+    insn->sib.got = 1;
+
+err_out:
+    return;
+}
+
+/**
+ * insn_get_displacement() - Get the displacement of instruction
+ * @insn:	&struct insn containing instruction
+ *
+ * If necessary, first collects the instruction up to and including the
+ * SIB byte.
+ * Displacement value is sign-expanded.
+ */
+void insn_get_displacement(struct insn *insn)
+{
+    insn_byte_t mod, rm, base;
+
+    if ( insn->displacement.got )
+        return;
+    if ( !insn->sib.got )
+        insn_get_sib(insn);
+    if ( insn->modrm.nbytes )
+    {
+        /*
+         * Interpreting the modrm byte:
+         * mod = 00 - no displacement fields (exceptions below)
+         * mod = 01 - 1-byte displacement field
+         * mod = 10 - displacement field is 4 bytes, or 2 bytes if
+         * 	address size = 2 (0x67 prefix in 32-bit mode)
+         * mod = 11 - no memory operand
+         *
+         * If address size = 2...
+         * mod = 00, r/m = 110 - displacement field is 2 bytes
+         *
+         * If address size != 2...
+         * mod != 11, r/m = 100 - SIB byte exists
+         * mod = 00, SIB base = 101 - displacement field is 4 bytes
+         * mod = 00, r/m = 101 - rip-relative addressing, displacement
+         * 	field is 4 bytes
+         */
+        mod = X86_MODRM_MOD(insn->modrm.value);
+        rm = X86_MODRM_RM(insn->modrm.value);
+        base = X86_SIB_BASE(insn->sib.value);
+        if ( mod == 3 )
+            goto out;
+        if ( mod == 1 )
+        {
+            insn->displacement.value = get_next(char, insn);
+            insn->displacement.nbytes = 1;
+        }
+        else if ( insn->addr_bytes == 2 )
+        {
+            if ( (mod == 0 && rm == 6) || mod == 2 )
+            {
+                insn->displacement.value = get_next(short, insn);
+                insn->displacement.nbytes = 2;
+            }
+        }
+        else
+        {
+            if ( (mod == 0 && rm == 5) || mod == 2 || (mod == 0 && base == 5) )
+            {
+                insn->displacement.value = get_next(int, insn);
+                insn->displacement.nbytes = 4;
+            }
+        }
+    }
+out:
+    insn->displacement.got = 1;
+
+err_out:
+    return;
+}
+
+/* Decode moffset16/32/64. Return 0 if failed */
+static int __get_moffset(struct insn *insn)
+{
+    switch ( insn->addr_bytes )
+    {
+    case 2:
+        insn->moffset1.value = get_next(short, insn);
+        insn->moffset1.nbytes = 2;
+        break;
+    case 4:
+        insn->moffset1.value = get_next(int, insn);
+        insn->moffset1.nbytes = 4;
+        break;
+    case 8:
+        insn->moffset1.value = get_next(int, insn);
+        insn->moffset1.nbytes = 4;
+        insn->moffset2.value = get_next(int, insn);
+        insn->moffset2.nbytes = 4;
+        break;
+    default: /* opnd_bytes must be modified manually */
+        goto err_out;
+    }
+    insn->moffset1.got = insn->moffset2.got = 1;
+
+    return 1;
+
+err_out:
+    return 0;
+}
+
+/* Decode imm v32(Iz). Return 0 if failed */
+static int __get_immv32(struct insn *insn)
+{
+    switch ( insn->opnd_bytes )
+    {
+    case 2:
+        insn->immediate.value = get_next(short, insn);
+        insn->immediate.nbytes = 2;
+        break;
+    case 4:
+    case 8:
+        insn->immediate.value = get_next(int, insn);
+        insn->immediate.nbytes = 4;
+        break;
+    default: /* opnd_bytes must be modified manually */
+        goto err_out;
+    }
+
+    return 1;
+
+err_out:
+    return 0;
+}
+
+/* Decode imm v64(Iv/Ov), Return 0 if failed */
+static int __get_immv(struct insn *insn)
+{
+    switch ( insn->opnd_bytes )
+    {
+    case 2:
+        insn->immediate1.value = get_next(short, insn);
+        insn->immediate1.nbytes = 2;
+        break;
+    case 4:
+        insn->immediate1.value = get_next(int, insn);
+        insn->immediate1.nbytes = 4;
+        break;
+    case 8:
+        insn->immediate1.value = get_next(int, insn);
+        insn->immediate1.nbytes = 4;
+        insn->immediate2.value = get_next(int, insn);
+        insn->immediate2.nbytes = 4;
+        break;
+    default: /* opnd_bytes must be modified manually */
+        goto err_out;
+    }
+    insn->immediate1.got = insn->immediate2.got = 1;
+
+    return 1;
+err_out:
+    return 0;
+}
+
+/* Decode ptr16:16/32(Ap) */
+static int __get_immptr(struct insn *insn)
+{
+    switch ( insn->opnd_bytes )
+    {
+    case 2:
+        insn->immediate1.value = get_next(short, insn);
+        insn->immediate1.nbytes = 2;
+        break;
+    case 4:
+        insn->immediate1.value = get_next(int, insn);
+        insn->immediate1.nbytes = 4;
+        break;
+    case 8:
+        /* ptr16:64 is not exist (no segment) */
+        return 0;
+    default: /* opnd_bytes must be modified manually */
+        goto err_out;
+    }
+    insn->immediate2.value = get_next(unsigned short, insn);
+    insn->immediate2.nbytes = 2;
+    insn->immediate1.got = insn->immediate2.got = 1;
+
+    return 1;
+err_out:
+    return 0;
+}
+
+/**
+ * insn_get_immediate() - Get the immediates of instruction
+ * @insn:	&struct insn containing instruction
+ *
+ * If necessary, first collects the instruction up to and including the
+ * displacement bytes.
+ * Basically, most of immediates are sign-expanded. Unsigned-value can be
+ * get by bit masking with ((1 << (nbytes * 8)) - 1)
+ */
+void insn_get_immediate(struct insn *insn)
+{
+    if ( insn->immediate.got )
+        return;
+    if ( !insn->displacement.got )
+        insn_get_displacement(insn);
+
+    if ( inat_has_moffset(insn->attr) )
+    {
+        if ( !__get_moffset(insn) )
+            goto err_out;
+        goto done;
+    }
+
+    if ( !inat_has_immediate(insn->attr) )
+        /* no immediates */
+        goto done;
+
+    switch ( inat_immediate_size(insn->attr) )
+    {
+    case INAT_IMM_BYTE:
+        insn->immediate.value = get_next(char, insn);
+        insn->immediate.nbytes = 1;
+        break;
+    case INAT_IMM_WORD:
+        insn->immediate.value = get_next(short, insn);
+        insn->immediate.nbytes = 2;
+        break;
+    case INAT_IMM_DWORD:
+        insn->immediate.value = get_next(int, insn);
+        insn->immediate.nbytes = 4;
+        break;
+    case INAT_IMM_QWORD:
+        insn->immediate1.value = get_next(int, insn);
+        insn->immediate1.nbytes = 4;
+        insn->immediate2.value = get_next(int, insn);
+        insn->immediate2.nbytes = 4;
+        break;
+    case INAT_IMM_PTR:
+        if ( !__get_immptr(insn) )
+            goto err_out;
+        break;
+    case INAT_IMM_VWORD32:
+        if ( !__get_immv32(insn) )
+            goto err_out;
+        break;
+    case INAT_IMM_VWORD:
+        if ( !__get_immv(insn) )
+            goto err_out;
+        break;
+    default:
+        /* Here, insn must have an immediate, but failed */
+        goto err_out;
+    }
+    if ( inat_has_second_immediate(insn->attr) )
+    {
+        insn->immediate2.value = get_next(char, insn);
+        insn->immediate2.nbytes = 1;
+    }
+done:
+    insn->immediate.got = 1;
+
+err_out:
+    return;
+}
+
+/**
+ * insn_get_length() - Get the length of instruction
+ * @insn:	&struct insn containing instruction
+ *
+ * If necessary, first collects the instruction up to and including the
+ * immediates bytes.
+ */
+void insn_get_length(struct insn *insn)
+{
+    if ( insn->length )
+        return;
+    if ( !insn->immediate.got )
+        insn_get_immediate(insn);
+    insn->length = (unsigned char)((unsigned long)insn->next_byte -
+                                   (unsigned long)insn->kaddr);
+}
diff --git a/xen/arch/x86/x86_emulate/x86-opcode-map.txt b/xen/arch/x86/x86_emulate/x86-opcode-map.txt
new file mode 100644
index 0000000..1a2be7c
--- /dev/null
+++ b/xen/arch/x86/x86_emulate/x86-opcode-map.txt
@@ -0,0 +1,961 @@
+# x86 Opcode Maps
+#
+# This is (mostly) based on following documentations.
+# - Intel(R) 64 and IA-32 Architectures Software Developer's Manual Vol.2C
+#   (#326018-047US, June 2013)
+#
+#<Opcode maps>
+# Table: table-name
+# Referrer: escaped-name
+# AVXcode: avx-code
+# opcode: mnemonic|GrpXXX [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...]
+# (or)
+# opcode: escape # escaped-name
+# EndTable
+#
+#<group maps>
+# GrpTable: GrpXXX
+# reg:  mnemonic [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...]
+# EndTable
+#
+# AVX Superscripts
+#  (v): this opcode requires VEX prefix.
+#  (v1): this opcode only supports 128bit VEX.
+#
+# Last Prefix Superscripts
+#  - (66): the last prefix is 0x66
+#  - (F3): the last prefix is 0xF3
+#  - (F2): the last prefix is 0xF2
+#  - (!F3) : the last prefix is not 0xF3 (including non-last prefix case)
+#  - (66&F2): Both 0x66 and 0xF2 prefixes are specified.
+
+Table: one byte opcode
+Referrer:
+AVXcode:
+# 0x00 - 0x0f
+00: ADD Eb,Gb
+01: ADD Ev,Gv
+02: ADD Gb,Eb
+03: ADD Gv,Ev
+04: ADD AL,Ib
+05: ADD rAX,Iz
+06: PUSH ES (i64)
+07: POP ES (i64)
+08: OR Eb,Gb
+09: OR Ev,Gv
+0a: OR Gb,Eb
+0b: OR Gv,Ev
+0c: OR AL,Ib
+0d: OR rAX,Iz
+0e: PUSH CS (i64)
+0f: escape # 2-byte escape
+# 0x10 - 0x1f
+10: ADC Eb,Gb
+11: ADC Ev,Gv
+12: ADC Gb,Eb
+13: ADC Gv,Ev
+14: ADC AL,Ib
+15: ADC rAX,Iz
+16: PUSH SS (i64)
+17: POP SS (i64)
+18: SBB Eb,Gb
+19: SBB Ev,Gv
+1a: SBB Gb,Eb
+1b: SBB Gv,Ev
+1c: SBB AL,Ib
+1d: SBB rAX,Iz
+1e: PUSH DS (i64)
+1f: POP DS (i64)
+# 0x20 - 0x2f
+20: AND Eb,Gb
+21: AND Ev,Gv
+22: AND Gb,Eb
+23: AND Gv,Ev
+24: AND AL,Ib
+25: AND rAx,Iz
+26: SEG=ES (Prefix)
+27: DAA (i64)
+28: SUB Eb,Gb
+29: SUB Ev,Gv
+2a: SUB Gb,Eb
+2b: SUB Gv,Ev
+2c: SUB AL,Ib
+2d: SUB rAX,Iz
+2e: SEG=CS (Prefix)
+2f: DAS (i64)
+# 0x30 - 0x3f
+30: XOR Eb,Gb
+31: XOR Ev,Gv
+32: XOR Gb,Eb
+33: XOR Gv,Ev
+34: XOR AL,Ib
+35: XOR rAX,Iz
+36: SEG=SS (Prefix)
+37: AAA (i64)
+38: CMP Eb,Gb
+39: CMP Ev,Gv
+3a: CMP Gb,Eb
+3b: CMP Gv,Ev
+3c: CMP AL,Ib
+3d: CMP rAX,Iz
+3e: SEG=DS (Prefix)
+3f: AAS (i64)
+# 0x40 - 0x4f
+40: INC eAX (i64) | REX (o64)
+41: INC eCX (i64) | REX.B (o64)
+42: INC eDX (i64) | REX.X (o64)
+43: INC eBX (i64) | REX.XB (o64)
+44: INC eSP (i64) | REX.R (o64)
+45: INC eBP (i64) | REX.RB (o64)
+46: INC eSI (i64) | REX.RX (o64)
+47: INC eDI (i64) | REX.RXB (o64)
+48: DEC eAX (i64) | REX.W (o64)
+49: DEC eCX (i64) | REX.WB (o64)
+4a: DEC eDX (i64) | REX.WX (o64)
+4b: DEC eBX (i64) | REX.WXB (o64)
+4c: DEC eSP (i64) | REX.WR (o64)
+4d: DEC eBP (i64) | REX.WRB (o64)
+4e: DEC eSI (i64) | REX.WRX (o64)
+4f: DEC eDI (i64) | REX.WRXB (o64)
+# 0x50 - 0x5f
+50: PUSH rAX/r8 (d64)
+51: PUSH rCX/r9 (d64)
+52: PUSH rDX/r10 (d64)
+53: PUSH rBX/r11 (d64)
+54: PUSH rSP/r12 (d64)
+55: PUSH rBP/r13 (d64)
+56: PUSH rSI/r14 (d64)
+57: PUSH rDI/r15 (d64)
+58: POP rAX/r8 (d64)
+59: POP rCX/r9 (d64)
+5a: POP rDX/r10 (d64)
+5b: POP rBX/r11 (d64)
+5c: POP rSP/r12 (d64)
+5d: POP rBP/r13 (d64)
+5e: POP rSI/r14 (d64)
+5f: POP rDI/r15 (d64)
+# 0x60 - 0x6f
+60: PUSHA/PUSHAD (i64)
+61: POPA/POPAD (i64)
+62: BOUND Gv,Ma (i64)
+63: ARPL Ew,Gw (i64) | MOVSXD Gv,Ev (o64)
+64: SEG=FS (Prefix)
+65: SEG=GS (Prefix)
+66: Operand-Size (Prefix)
+67: Address-Size (Prefix)
+68: PUSH Iz (d64)
+69: IMUL Gv,Ev,Iz
+6a: PUSH Ib (d64)
+6b: IMUL Gv,Ev,Ib
+6c: INS/INSB Yb,DX
+6d: INS/INSW/INSD Yz,DX
+6e: OUTS/OUTSB DX,Xb
+6f: OUTS/OUTSW/OUTSD DX,Xz
+# 0x70 - 0x7f
+70: JO Jb
+71: JNO Jb
+72: JB/JNAE/JC Jb
+73: JNB/JAE/JNC Jb
+74: JZ/JE Jb
+75: JNZ/JNE Jb
+76: JBE/JNA Jb
+77: JNBE/JA Jb
+78: JS Jb
+79: JNS Jb
+7a: JP/JPE Jb
+7b: JNP/JPO Jb
+7c: JL/JNGE Jb
+7d: JNL/JGE Jb
+7e: JLE/JNG Jb
+7f: JNLE/JG Jb
+# 0x80 - 0x8f
+80: Grp1 Eb,Ib (1A)
+81: Grp1 Ev,Iz (1A)
+82: Grp1 Eb,Ib (1A),(i64)
+83: Grp1 Ev,Ib (1A)
+84: TEST Eb,Gb
+85: TEST Ev,Gv
+86: XCHG Eb,Gb
+87: XCHG Ev,Gv
+88: MOV Eb,Gb
+89: MOV Ev,Gv
+8a: MOV Gb,Eb
+8b: MOV Gv,Ev
+8c: MOV Ev,Sw
+8d: LEA Gv,M
+8e: MOV Sw,Ew
+8f: Grp1A (1A) | POP Ev (d64)
+# 0x90 - 0x9f
+90: NOP | PAUSE (F3) | XCHG r8,rAX
+91: XCHG rCX/r9,rAX
+92: XCHG rDX/r10,rAX
+93: XCHG rBX/r11,rAX
+94: XCHG rSP/r12,rAX
+95: XCHG rBP/r13,rAX
+96: XCHG rSI/r14,rAX
+97: XCHG rDI/r15,rAX
+98: CBW/CWDE/CDQE
+99: CWD/CDQ/CQO
+9a: CALLF Ap (i64)
+9b: FWAIT/WAIT
+9c: PUSHF/D/Q Fv (d64)
+9d: POPF/D/Q Fv (d64)
+9e: SAHF
+9f: LAHF
+# 0xa0 - 0xaf
+a0: MOV AL,Ob
+a1: MOV rAX,Ov
+a2: MOV Ob,AL
+a3: MOV Ov,rAX
+a4: MOVS/B Yb,Xb
+a5: MOVS/W/D/Q Yv,Xv
+a6: CMPS/B Xb,Yb
+a7: CMPS/W/D Xv,Yv
+a8: TEST AL,Ib
+a9: TEST rAX,Iz
+aa: STOS/B Yb,AL
+ab: STOS/W/D/Q Yv,rAX
+ac: LODS/B AL,Xb
+ad: LODS/W/D/Q rAX,Xv
+ae: SCAS/B AL,Yb
+# Note: The May 2011 Intel manual shows Xv for the second parameter of the
+# next instruction but Yv is correct
+af: SCAS/W/D/Q rAX,Yv
+# 0xb0 - 0xbf
+b0: MOV AL/R8L,Ib
+b1: MOV CL/R9L,Ib
+b2: MOV DL/R10L,Ib
+b3: MOV BL/R11L,Ib
+b4: MOV AH/R12L,Ib
+b5: MOV CH/R13L,Ib
+b6: MOV DH/R14L,Ib
+b7: MOV BH/R15L,Ib
+b8: MOV rAX/r8,Iv
+b9: MOV rCX/r9,Iv
+ba: MOV rDX/r10,Iv
+bb: MOV rBX/r11,Iv
+bc: MOV rSP/r12,Iv
+bd: MOV rBP/r13,Iv
+be: MOV rSI/r14,Iv
+bf: MOV rDI/r15,Iv
+# 0xc0 - 0xcf
+c0: Grp2 Eb,Ib (1A)
+c1: Grp2 Ev,Ib (1A)
+c2: RETN Iw (f64)
+c3: RETN
+c4: LES Gz,Mp (i64) | VEX+2byte (Prefix)
+c5: LDS Gz,Mp (i64) | VEX+1byte (Prefix)
+c6: Grp11A Eb,Ib (1A)
+c7: Grp11B Ev,Iz (1A)
+c8: ENTER Iw,Ib
+c9: LEAVE (d64)
+ca: RETF Iw
+cb: RETF
+cc: INT3
+cd: INT Ib
+ce: INTO (i64)
+cf: IRET/D/Q
+# 0xd0 - 0xdf
+d0: Grp2 Eb,1 (1A)
+d1: Grp2 Ev,1 (1A)
+d2: Grp2 Eb,CL (1A)
+d3: Grp2 Ev,CL (1A)
+d4: AAM Ib (i64)
+d5: AAD Ib (i64)
+d6:
+d7: XLAT/XLATB
+d8: ESC
+d9: ESC
+da: ESC
+db: ESC
+dc: ESC
+dd: ESC
+de: ESC
+df: ESC
+# 0xe0 - 0xef
+e0: LOOPNE/LOOPNZ Jb (f64)
+e1: LOOPE/LOOPZ Jb (f64)
+e2: LOOP Jb (f64)
+e3: JrCXZ Jb (f64)
+e4: IN AL,Ib
+e5: IN eAX,Ib
+e6: OUT Ib,AL
+e7: OUT Ib,eAX
+e8: CALL Jz (f64)
+e9: JMP-near Jz (f64)
+ea: JMP-far Ap (i64)
+eb: JMP-short Jb (f64)
+ec: IN AL,DX
+ed: IN eAX,DX
+ee: OUT DX,AL
+ef: OUT DX,eAX
+# 0xf0 - 0xff
+f0: LOCK (Prefix)
+f1:
+f2: REPNE (Prefix) | XACQUIRE (Prefix)
+f3: REP/REPE (Prefix) | XRELEASE (Prefix)
+f4: HLT
+f5: CMC
+f6: Grp3_1 Eb (1A)
+f7: Grp3_2 Ev (1A)
+f8: CLC
+f9: STC
+fa: CLI
+fb: STI
+fc: CLD
+fd: STD
+fe: Grp4 (1A)
+ff: Grp5 (1A)
+EndTable
+
+Table: 2-byte opcode (0x0f)
+Referrer: 2-byte escape
+AVXcode: 1
+# 0x0f 0x00-0x0f
+00: Grp6 (1A)
+01: Grp7 (1A)
+02: LAR Gv,Ew
+03: LSL Gv,Ew
+04:
+05: SYSCALL (o64)
+06: CLTS
+07: SYSRET (o64)
+08: INVD
+09: WBINVD
+0a:
+0b: UD2 (1B)
+0c:
+# AMD's prefetch group. Intel supports prefetchw(/1) only.
+0d: GrpP
+0e: FEMMS
+# 3DNow! uses the last imm byte as opcode extension.
+0f: 3DNow! Pq,Qq,Ib
+# 0x0f 0x10-0x1f
+# NOTE: According to Intel SDM opcode map, vmovups and vmovupd has no operands
+# but it actually has operands. And also, vmovss and vmovsd only accept 128bit.
+# MOVSS/MOVSD has too many forms(3) on SDM. This map just shows a typical form.
+# Many AVX instructions lack v1 superscript, according to Intel AVX-Prgramming
+# Reference A.1
+10: vmovups Vps,Wps | vmovupd Vpd,Wpd (66) | vmovss Vx,Hx,Wss (F3),(v1) | vmovsd Vx,Hx,Wsd (F2),(v1)
+11: vmovups Wps,Vps | vmovupd Wpd,Vpd (66) | vmovss Wss,Hx,Vss (F3),(v1) | vmovsd Wsd,Hx,Vsd (F2),(v1)
+12: vmovlps Vq,Hq,Mq (v1) | vmovhlps Vq,Hq,Uq (v1) | vmovlpd Vq,Hq,Mq (66),(v1) | vmovsldup Vx,Wx (F3) | vmovddup Vx,Wx (F2)
+13: vmovlps Mq,Vq (v1) | vmovlpd Mq,Vq (66),(v1)
+14: vunpcklps Vx,Hx,Wx | vunpcklpd Vx,Hx,Wx (66)
+15: vunpckhps Vx,Hx,Wx | vunpckhpd Vx,Hx,Wx (66)
+16: vmovhps Vdq,Hq,Mq (v1) | vmovlhps Vdq,Hq,Uq (v1) | vmovhpd Vdq,Hq,Mq (66),(v1) | vmovshdup Vx,Wx (F3)
+17: vmovhps Mq,Vq (v1) | vmovhpd Mq,Vq (66),(v1)
+18: Grp16 (1A)
+19:
+1a: BNDCL Ev,Gv | BNDCU Ev,Gv | BNDMOV Gv,Ev | BNDLDX Gv,Ev,Gv
+1b: BNDCN Ev,Gv | BNDMOV Ev,Gv | BNDMK Gv,Ev | BNDSTX Ev,GV,Gv
+1c:
+1d:
+1e:
+1f: NOP Ev
+# 0x0f 0x20-0x2f
+20: MOV Rd,Cd
+21: MOV Rd,Dd
+22: MOV Cd,Rd
+23: MOV Dd,Rd
+24:
+25:
+26:
+27:
+28: vmovaps Vps,Wps | vmovapd Vpd,Wpd (66)
+29: vmovaps Wps,Vps | vmovapd Wpd,Vpd (66)
+2a: cvtpi2ps Vps,Qpi | cvtpi2pd Vpd,Qpi (66) | vcvtsi2ss Vss,Hss,Ey (F3),(v1) | vcvtsi2sd Vsd,Hsd,Ey (F2),(v1)
+2b: vmovntps Mps,Vps | vmovntpd Mpd,Vpd (66)
+2c: cvttps2pi Ppi,Wps | cvttpd2pi Ppi,Wpd (66) | vcvttss2si Gy,Wss (F3),(v1) | vcvttsd2si Gy,Wsd (F2),(v1)
+2d: cvtps2pi Ppi,Wps | cvtpd2pi Qpi,Wpd (66) | vcvtss2si Gy,Wss (F3),(v1) | vcvtsd2si Gy,Wsd (F2),(v1)
+2e: vucomiss Vss,Wss (v1) | vucomisd  Vsd,Wsd (66),(v1)
+2f: vcomiss Vss,Wss (v1) | vcomisd  Vsd,Wsd (66),(v1)
+# 0x0f 0x30-0x3f
+30: WRMSR
+31: RDTSC
+32: RDMSR
+33: RDPMC
+34: SYSENTER
+35: SYSEXIT
+36:
+37: GETSEC
+38: escape # 3-byte escape 1
+39:
+3a: escape # 3-byte escape 2
+3b:
+3c:
+3d:
+3e:
+3f:
+# 0x0f 0x40-0x4f
+40: CMOVO Gv,Ev
+41: CMOVNO Gv,Ev
+42: CMOVB/C/NAE Gv,Ev
+43: CMOVAE/NB/NC Gv,Ev
+44: CMOVE/Z Gv,Ev
+45: CMOVNE/NZ Gv,Ev
+46: CMOVBE/NA Gv,Ev
+47: CMOVA/NBE Gv,Ev
+48: CMOVS Gv,Ev
+49: CMOVNS Gv,Ev
+4a: CMOVP/PE Gv,Ev
+4b: CMOVNP/PO Gv,Ev
+4c: CMOVL/NGE Gv,Ev
+4d: CMOVNL/GE Gv,Ev
+4e: CMOVLE/NG Gv,Ev
+4f: CMOVNLE/G Gv,Ev
+# 0x0f 0x50-0x5f
+50: vmovmskps Gy,Ups | vmovmskpd Gy,Upd (66)
+51: vsqrtps Vps,Wps | vsqrtpd Vpd,Wpd (66) | vsqrtss Vss,Hss,Wss (F3),(v1) | vsqrtsd Vsd,Hsd,Wsd (F2),(v1)
+52: vrsqrtps Vps,Wps | vrsqrtss Vss,Hss,Wss (F3),(v1)
+53: vrcpps Vps,Wps | vrcpss Vss,Hss,Wss (F3),(v1)
+54: vandps Vps,Hps,Wps | vandpd Vpd,Hpd,Wpd (66)
+55: vandnps Vps,Hps,Wps | vandnpd Vpd,Hpd,Wpd (66)
+56: vorps Vps,Hps,Wps | vorpd Vpd,Hpd,Wpd (66)
+57: vxorps Vps,Hps,Wps | vxorpd Vpd,Hpd,Wpd (66)
+58: vaddps Vps,Hps,Wps | vaddpd Vpd,Hpd,Wpd (66) | vaddss Vss,Hss,Wss (F3),(v1) | vaddsd Vsd,Hsd,Wsd (F2),(v1)
+59: vmulps Vps,Hps,Wps | vmulpd Vpd,Hpd,Wpd (66) | vmulss Vss,Hss,Wss (F3),(v1) | vmulsd Vsd,Hsd,Wsd (F2),(v1)
+5a: vcvtps2pd Vpd,Wps | vcvtpd2ps Vps,Wpd (66) | vcvtss2sd Vsd,Hx,Wss (F3),(v1) | vcvtsd2ss Vss,Hx,Wsd (F2),(v1)
+5b: vcvtdq2ps Vps,Wdq | vcvtps2dq Vdq,Wps (66) | vcvttps2dq Vdq,Wps (F3)
+5c: vsubps Vps,Hps,Wps | vsubpd Vpd,Hpd,Wpd (66) | vsubss Vss,Hss,Wss (F3),(v1) | vsubsd Vsd,Hsd,Wsd (F2),(v1)
+5d: vminps Vps,Hps,Wps | vminpd Vpd,Hpd,Wpd (66) | vminss Vss,Hss,Wss (F3),(v1) | vminsd Vsd,Hsd,Wsd (F2),(v1)
+5e: vdivps Vps,Hps,Wps | vdivpd Vpd,Hpd,Wpd (66) | vdivss Vss,Hss,Wss (F3),(v1) | vdivsd Vsd,Hsd,Wsd (F2),(v1)
+5f: vmaxps Vps,Hps,Wps | vmaxpd Vpd,Hpd,Wpd (66) | vmaxss Vss,Hss,Wss (F3),(v1) | vmaxsd Vsd,Hsd,Wsd (F2),(v1)
+# 0x0f 0x60-0x6f
+60: punpcklbw Pq,Qd | vpunpcklbw Vx,Hx,Wx (66),(v1)
+61: punpcklwd Pq,Qd | vpunpcklwd Vx,Hx,Wx (66),(v1)
+62: punpckldq Pq,Qd | vpunpckldq Vx,Hx,Wx (66),(v1)
+63: packsswb Pq,Qq | vpacksswb Vx,Hx,Wx (66),(v1)
+64: pcmpgtb Pq,Qq | vpcmpgtb Vx,Hx,Wx (66),(v1)
+65: pcmpgtw Pq,Qq | vpcmpgtw Vx,Hx,Wx (66),(v1)
+66: pcmpgtd Pq,Qq | vpcmpgtd Vx,Hx,Wx (66),(v1)
+67: packuswb Pq,Qq | vpackuswb Vx,Hx,Wx (66),(v1)
+68: punpckhbw Pq,Qd | vpunpckhbw Vx,Hx,Wx (66),(v1)
+69: punpckhwd Pq,Qd | vpunpckhwd Vx,Hx,Wx (66),(v1)
+6a: punpckhdq Pq,Qd | vpunpckhdq Vx,Hx,Wx (66),(v1)
+6b: packssdw Pq,Qd | vpackssdw Vx,Hx,Wx (66),(v1)
+6c: vpunpcklqdq Vx,Hx,Wx (66),(v1)
+6d: vpunpckhqdq Vx,Hx,Wx (66),(v1)
+6e: movd/q Pd,Ey | vmovd/q Vy,Ey (66),(v1)
+6f: movq Pq,Qq | vmovdqa Vx,Wx (66) | vmovdqu Vx,Wx (F3)
+# 0x0f 0x70-0x7f
+70: pshufw Pq,Qq,Ib | vpshufd Vx,Wx,Ib (66),(v1) | vpshufhw Vx,Wx,Ib (F3),(v1) | vpshuflw Vx,Wx,Ib (F2),(v1)
+71: Grp12 (1A)
+72: Grp13 (1A)
+73: Grp14 (1A)
+74: pcmpeqb Pq,Qq | vpcmpeqb Vx,Hx,Wx (66),(v1)
+75: pcmpeqw Pq,Qq | vpcmpeqw Vx,Hx,Wx (66),(v1)
+76: pcmpeqd Pq,Qq | vpcmpeqd Vx,Hx,Wx (66),(v1)
+# Note: Remove (v), because vzeroall and vzeroupper becomes emms without VEX.
+77: emms | vzeroupper | vzeroall
+78: VMREAD Ey,Gy
+79: VMWRITE Gy,Ey
+7a:
+7b:
+7c: vhaddpd Vpd,Hpd,Wpd (66) | vhaddps Vps,Hps,Wps (F2)
+7d: vhsubpd Vpd,Hpd,Wpd (66) | vhsubps Vps,Hps,Wps (F2)
+7e: movd/q Ey,Pd | vmovd/q Ey,Vy (66),(v1) | vmovq Vq,Wq (F3),(v1)
+7f: movq Qq,Pq | vmovdqa Wx,Vx (66) | vmovdqu Wx,Vx (F3)
+# 0x0f 0x80-0x8f
+80: JO Jz (f64)
+81: JNO Jz (f64)
+82: JB/JC/JNAE Jz (f64)
+83: JAE/JNB/JNC Jz (f64)
+84: JE/JZ Jz (f64)
+85: JNE/JNZ Jz (f64)
+86: JBE/JNA Jz (f64)
+87: JA/JNBE Jz (f64)
+88: JS Jz (f64)
+89: JNS Jz (f64)
+8a: JP/JPE Jz (f64)
+8b: JNP/JPO Jz (f64)
+8c: JL/JNGE Jz (f64)
+8d: JNL/JGE Jz (f64)
+8e: JLE/JNG Jz (f64)
+8f: JNLE/JG Jz (f64)
+# 0x0f 0x90-0x9f
+90: SETO Eb
+91: SETNO Eb
+92: SETB/C/NAE Eb
+93: SETAE/NB/NC Eb
+94: SETE/Z Eb
+95: SETNE/NZ Eb
+96: SETBE/NA Eb
+97: SETA/NBE Eb
+98: SETS Eb
+99: SETNS Eb
+9a: SETP/PE Eb
+9b: SETNP/PO Eb
+9c: SETL/NGE Eb
+9d: SETNL/GE Eb
+9e: SETLE/NG Eb
+9f: SETNLE/G Eb
+# 0x0f 0xa0-0xaf
+a0: PUSH FS (d64)
+a1: POP FS (d64)
+a2: CPUID
+a3: BT Ev,Gv
+a4: SHLD Ev,Gv,Ib
+a5: SHLD Ev,Gv,CL
+a6: GrpPDLK
+a7: GrpRNG
+a8: PUSH GS (d64)
+a9: POP GS (d64)
+aa: RSM
+ab: BTS Ev,Gv
+ac: SHRD Ev,Gv,Ib
+ad: SHRD Ev,Gv,CL
+ae: Grp15 (1A),(1C)
+af: IMUL Gv,Ev
+# 0x0f 0xb0-0xbf
+b0: CMPXCHG Eb,Gb
+b1: CMPXCHG Ev,Gv
+b2: LSS Gv,Mp
+b3: BTR Ev,Gv
+b4: LFS Gv,Mp
+b5: LGS Gv,Mp
+b6: MOVZX Gv,Eb
+b7: MOVZX Gv,Ew
+b8: JMPE (!F3) | POPCNT Gv,Ev (F3)
+b9: Grp10 (1A)
+ba: Grp8 Ev,Ib (1A)
+bb: BTC Ev,Gv
+bc: BSF Gv,Ev (!F3) | TZCNT Gv,Ev (F3)
+bd: BSR Gv,Ev (!F3) | LZCNT Gv,Ev (F3)
+be: MOVSX Gv,Eb
+bf: MOVSX Gv,Ew
+# 0x0f 0xc0-0xcf
+c0: XADD Eb,Gb
+c1: XADD Ev,Gv
+c2: vcmpps Vps,Hps,Wps,Ib | vcmppd Vpd,Hpd,Wpd,Ib (66) | vcmpss Vss,Hss,Wss,Ib (F3),(v1) | vcmpsd Vsd,Hsd,Wsd,Ib (F2),(v1)
+c3: movnti My,Gy
+c4: pinsrw Pq,Ry/Mw,Ib | vpinsrw Vdq,Hdq,Ry/Mw,Ib (66),(v1)
+c5: pextrw Gd,Nq,Ib | vpextrw Gd,Udq,Ib (66),(v1)
+c6: vshufps Vps,Hps,Wps,Ib | vshufpd Vpd,Hpd,Wpd,Ib (66)
+c7: Grp9 (1A)
+c8: BSWAP RAX/EAX/R8/R8D
+c9: BSWAP RCX/ECX/R9/R9D
+ca: BSWAP RDX/EDX/R10/R10D
+cb: BSWAP RBX/EBX/R11/R11D
+cc: BSWAP RSP/ESP/R12/R12D
+cd: BSWAP RBP/EBP/R13/R13D
+ce: BSWAP RSI/ESI/R14/R14D
+cf: BSWAP RDI/EDI/R15/R15D
+# 0x0f 0xd0-0xdf
+d0: vaddsubpd Vpd,Hpd,Wpd (66) | vaddsubps Vps,Hps,Wps (F2)
+d1: psrlw Pq,Qq | vpsrlw Vx,Hx,Wx (66),(v1)
+d2: psrld Pq,Qq | vpsrld Vx,Hx,Wx (66),(v1)
+d3: psrlq Pq,Qq | vpsrlq Vx,Hx,Wx (66),(v1)
+d4: paddq Pq,Qq | vpaddq Vx,Hx,Wx (66),(v1)
+d5: pmullw Pq,Qq | vpmullw Vx,Hx,Wx (66),(v1)
+d6: vmovq Wq,Vq (66),(v1) | movq2dq Vdq,Nq (F3) | movdq2q Pq,Uq (F2)
+d7: pmovmskb Gd,Nq | vpmovmskb Gd,Ux (66),(v1)
+d8: psubusb Pq,Qq | vpsubusb Vx,Hx,Wx (66),(v1)
+d9: psubusw Pq,Qq | vpsubusw Vx,Hx,Wx (66),(v1)
+da: pminub Pq,Qq | vpminub Vx,Hx,Wx (66),(v1)
+db: pand Pq,Qq | vpand Vx,Hx,Wx (66),(v1)
+dc: paddusb Pq,Qq | vpaddusb Vx,Hx,Wx (66),(v1)
+dd: paddusw Pq,Qq | vpaddusw Vx,Hx,Wx (66),(v1)
+de: pmaxub Pq,Qq | vpmaxub Vx,Hx,Wx (66),(v1)
+df: pandn Pq,Qq | vpandn Vx,Hx,Wx (66),(v1)
+# 0x0f 0xe0-0xef
+e0: pavgb Pq,Qq | vpavgb Vx,Hx,Wx (66),(v1)
+e1: psraw Pq,Qq | vpsraw Vx,Hx,Wx (66),(v1)
+e2: psrad Pq,Qq | vpsrad Vx,Hx,Wx (66),(v1)
+e3: pavgw Pq,Qq | vpavgw Vx,Hx,Wx (66),(v1)
+e4: pmulhuw Pq,Qq | vpmulhuw Vx,Hx,Wx (66),(v1)
+e5: pmulhw Pq,Qq | vpmulhw Vx,Hx,Wx (66),(v1)
+e6: vcvttpd2dq Vx,Wpd (66) | vcvtdq2pd Vx,Wdq (F3) | vcvtpd2dq Vx,Wpd (F2)
+e7: movntq Mq,Pq | vmovntdq Mx,Vx (66)
+e8: psubsb Pq,Qq | vpsubsb Vx,Hx,Wx (66),(v1)
+e9: psubsw Pq,Qq | vpsubsw Vx,Hx,Wx (66),(v1)
+ea: pminsw Pq,Qq | vpminsw Vx,Hx,Wx (66),(v1)
+eb: por Pq,Qq | vpor Vx,Hx,Wx (66),(v1)
+ec: paddsb Pq,Qq | vpaddsb Vx,Hx,Wx (66),(v1)
+ed: paddsw Pq,Qq | vpaddsw Vx,Hx,Wx (66),(v1)
+ee: pmaxsw Pq,Qq | vpmaxsw Vx,Hx,Wx (66),(v1)
+ef: pxor Pq,Qq | vpxor Vx,Hx,Wx (66),(v1)
+# 0x0f 0xf0-0xff
+f0: vlddqu Vx,Mx (F2)
+f1: psllw Pq,Qq | vpsllw Vx,Hx,Wx (66),(v1)
+f2: pslld Pq,Qq | vpslld Vx,Hx,Wx (66),(v1)
+f3: psllq Pq,Qq | vpsllq Vx,Hx,Wx (66),(v1)
+f4: pmuludq Pq,Qq | vpmuludq Vx,Hx,Wx (66),(v1)
+f5: pmaddwd Pq,Qq | vpmaddwd Vx,Hx,Wx (66),(v1)
+f6: psadbw Pq,Qq | vpsadbw Vx,Hx,Wx (66),(v1)
+f7: maskmovq Pq,Nq | vmaskmovdqu Vx,Ux (66),(v1)
+f8: psubb Pq,Qq | vpsubb Vx,Hx,Wx (66),(v1)
+f9: psubw Pq,Qq | vpsubw Vx,Hx,Wx (66),(v1)
+fa: psubd Pq,Qq | vpsubd Vx,Hx,Wx (66),(v1)
+fb: psubq Pq,Qq | vpsubq Vx,Hx,Wx (66),(v1)
+fc: paddb Pq,Qq | vpaddb Vx,Hx,Wx (66),(v1)
+fd: paddw Pq,Qq | vpaddw Vx,Hx,Wx (66),(v1)
+fe: paddd Pq,Qq | vpaddd Vx,Hx,Wx (66),(v1)
+ff:
+EndTable
+
+Table: 3-byte opcode 1 (0x0f 0x38)
+Referrer: 3-byte escape 1
+AVXcode: 2
+# 0x0f 0x38 0x00-0x0f
+00: pshufb Pq,Qq | vpshufb Vx,Hx,Wx (66),(v1)
+01: phaddw Pq,Qq | vphaddw Vx,Hx,Wx (66),(v1)
+02: phaddd Pq,Qq | vphaddd Vx,Hx,Wx (66),(v1)
+03: phaddsw Pq,Qq | vphaddsw Vx,Hx,Wx (66),(v1)
+04: pmaddubsw Pq,Qq | vpmaddubsw Vx,Hx,Wx (66),(v1)
+05: phsubw Pq,Qq | vphsubw Vx,Hx,Wx (66),(v1)
+06: phsubd Pq,Qq | vphsubd Vx,Hx,Wx (66),(v1)
+07: phsubsw Pq,Qq | vphsubsw Vx,Hx,Wx (66),(v1)
+08: psignb Pq,Qq | vpsignb Vx,Hx,Wx (66),(v1)
+09: psignw Pq,Qq | vpsignw Vx,Hx,Wx (66),(v1)
+0a: psignd Pq,Qq | vpsignd Vx,Hx,Wx (66),(v1)
+0b: pmulhrsw Pq,Qq | vpmulhrsw Vx,Hx,Wx (66),(v1)
+0c: vpermilps Vx,Hx,Wx (66),(v)
+0d: vpermilpd Vx,Hx,Wx (66),(v)
+0e: vtestps Vx,Wx (66),(v)
+0f: vtestpd Vx,Wx (66),(v)
+# 0x0f 0x38 0x10-0x1f
+10: pblendvb Vdq,Wdq (66)
+11:
+12:
+13: vcvtph2ps Vx,Wx,Ib (66),(v)
+14: blendvps Vdq,Wdq (66)
+15: blendvpd Vdq,Wdq (66)
+16: vpermps Vqq,Hqq,Wqq (66),(v)
+17: vptest Vx,Wx (66)
+18: vbroadcastss Vx,Wd (66),(v)
+19: vbroadcastsd Vqq,Wq (66),(v)
+1a: vbroadcastf128 Vqq,Mdq (66),(v)
+1b:
+1c: pabsb Pq,Qq | vpabsb Vx,Wx (66),(v1)
+1d: pabsw Pq,Qq | vpabsw Vx,Wx (66),(v1)
+1e: pabsd Pq,Qq | vpabsd Vx,Wx (66),(v1)
+1f:
+# 0x0f 0x38 0x20-0x2f
+20: vpmovsxbw Vx,Ux/Mq (66),(v1)
+21: vpmovsxbd Vx,Ux/Md (66),(v1)
+22: vpmovsxbq Vx,Ux/Mw (66),(v1)
+23: vpmovsxwd Vx,Ux/Mq (66),(v1)
+24: vpmovsxwq Vx,Ux/Md (66),(v1)
+25: vpmovsxdq Vx,Ux/Mq (66),(v1)
+26:
+27:
+28: vpmuldq Vx,Hx,Wx (66),(v1)
+29: vpcmpeqq Vx,Hx,Wx (66),(v1)
+2a: vmovntdqa Vx,Mx (66),(v1)
+2b: vpackusdw Vx,Hx,Wx (66),(v1)
+2c: vmaskmovps Vx,Hx,Mx (66),(v)
+2d: vmaskmovpd Vx,Hx,Mx (66),(v)
+2e: vmaskmovps Mx,Hx,Vx (66),(v)
+2f: vmaskmovpd Mx,Hx,Vx (66),(v)
+# 0x0f 0x38 0x30-0x3f
+30: vpmovzxbw Vx,Ux/Mq (66),(v1)
+31: vpmovzxbd Vx,Ux/Md (66),(v1)
+32: vpmovzxbq Vx,Ux/Mw (66),(v1)
+33: vpmovzxwd Vx,Ux/Mq (66),(v1)
+34: vpmovzxwq Vx,Ux/Md (66),(v1)
+35: vpmovzxdq Vx,Ux/Mq (66),(v1)
+36: vpermd Vqq,Hqq,Wqq (66),(v)
+37: vpcmpgtq Vx,Hx,Wx (66),(v1)
+38: vpminsb Vx,Hx,Wx (66),(v1)
+39: vpminsd Vx,Hx,Wx (66),(v1)
+3a: vpminuw Vx,Hx,Wx (66),(v1)
+3b: vpminud Vx,Hx,Wx (66),(v1)
+3c: vpmaxsb Vx,Hx,Wx (66),(v1)
+3d: vpmaxsd Vx,Hx,Wx (66),(v1)
+3e: vpmaxuw Vx,Hx,Wx (66),(v1)
+3f: vpmaxud Vx,Hx,Wx (66),(v1)
+# 0x0f 0x38 0x40-0x8f
+40: vpmulld Vx,Hx,Wx (66),(v1)
+41: vphminposuw Vdq,Wdq (66),(v1)
+42:
+43:
+44:
+45: vpsrlvd/q Vx,Hx,Wx (66),(v)
+46: vpsravd Vx,Hx,Wx (66),(v)
+47: vpsllvd/q Vx,Hx,Wx (66),(v)
+# Skip 0x48-0x57
+58: vpbroadcastd Vx,Wx (66),(v)
+59: vpbroadcastq Vx,Wx (66),(v)
+5a: vbroadcasti128 Vqq,Mdq (66),(v)
+# Skip 0x5b-0x77
+78: vpbroadcastb Vx,Wx (66),(v)
+79: vpbroadcastw Vx,Wx (66),(v)
+# Skip 0x7a-0x7f
+80: INVEPT Gy,Mdq (66)
+81: INVPID Gy,Mdq (66)
+82: INVPCID Gy,Mdq (66)
+8c: vpmaskmovd/q Vx,Hx,Mx (66),(v)
+8e: vpmaskmovd/q Mx,Vx,Hx (66),(v)
+# 0x0f 0x38 0x90-0xbf (FMA)
+90: vgatherdd/q Vx,Hx,Wx (66),(v)
+91: vgatherqd/q Vx,Hx,Wx (66),(v)
+92: vgatherdps/d Vx,Hx,Wx (66),(v)
+93: vgatherqps/d Vx,Hx,Wx (66),(v)
+94:
+95:
+96: vfmaddsub132ps/d Vx,Hx,Wx (66),(v)
+97: vfmsubadd132ps/d Vx,Hx,Wx (66),(v)
+98: vfmadd132ps/d Vx,Hx,Wx (66),(v)
+99: vfmadd132ss/d Vx,Hx,Wx (66),(v),(v1)
+9a: vfmsub132ps/d Vx,Hx,Wx (66),(v)
+9b: vfmsub132ss/d Vx,Hx,Wx (66),(v),(v1)
+9c: vfnmadd132ps/d Vx,Hx,Wx (66),(v)
+9d: vfnmadd132ss/d Vx,Hx,Wx (66),(v),(v1)
+9e: vfnmsub132ps/d Vx,Hx,Wx (66),(v)
+9f: vfnmsub132ss/d Vx,Hx,Wx (66),(v),(v1)
+a6: vfmaddsub213ps/d Vx,Hx,Wx (66),(v)
+a7: vfmsubadd213ps/d Vx,Hx,Wx (66),(v)
+a8: vfmadd213ps/d Vx,Hx,Wx (66),(v)
+a9: vfmadd213ss/d Vx,Hx,Wx (66),(v),(v1)
+aa: vfmsub213ps/d Vx,Hx,Wx (66),(v)
+ab: vfmsub213ss/d Vx,Hx,Wx (66),(v),(v1)
+ac: vfnmadd213ps/d Vx,Hx,Wx (66),(v)
+ad: vfnmadd213ss/d Vx,Hx,Wx (66),(v),(v1)
+ae: vfnmsub213ps/d Vx,Hx,Wx (66),(v)
+af: vfnmsub213ss/d Vx,Hx,Wx (66),(v),(v1)
+b6: vfmaddsub231ps/d Vx,Hx,Wx (66),(v)
+b7: vfmsubadd231ps/d Vx,Hx,Wx (66),(v)
+b8: vfmadd231ps/d Vx,Hx,Wx (66),(v)
+b9: vfmadd231ss/d Vx,Hx,Wx (66),(v),(v1)
+ba: vfmsub231ps/d Vx,Hx,Wx (66),(v)
+bb: vfmsub231ss/d Vx,Hx,Wx (66),(v),(v1)
+bc: vfnmadd231ps/d Vx,Hx,Wx (66),(v)
+bd: vfnmadd231ss/d Vx,Hx,Wx (66),(v),(v1)
+be: vfnmsub231ps/d Vx,Hx,Wx (66),(v)
+bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1)
+# 0x0f 0x38 0xc0-0xff
+db: VAESIMC Vdq,Wdq (66),(v1)
+dc: VAESENC Vdq,Hdq,Wdq (66),(v1)
+dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1)
+de: VAESDEC Vdq,Hdq,Wdq (66),(v1)
+df: VAESDECLAST Vdq,Hdq,Wdq (66),(v1)
+f0: MOVBE Gy,My | MOVBE Gw,Mw (66) | CRC32 Gd,Eb (F2) | CRC32 Gd,Eb (66&F2)
+f1: MOVBE My,Gy | MOVBE Mw,Gw (66) | CRC32 Gd,Ey (F2) | CRC32 Gd,Ew (66&F2)
+f2: ANDN Gy,By,Ey (v)
+f3: Grp17 (1A)
+f5: BZHI Gy,Ey,By (v) | PEXT Gy,By,Ey (F3),(v) | PDEP Gy,By,Ey (F2),(v)
+f6: ADCX Gy,Ey (66) | ADOX Gy,Ey (F3) | MULX By,Gy,rDX,Ey (F2),(v)
+f7: BEXTR Gy,Ey,By (v) | SHLX Gy,Ey,By (66),(v) | SARX Gy,Ey,By (F3),(v) | SHRX Gy,Ey,By (F2),(v)
+EndTable
+
+Table: 3-byte opcode 2 (0x0f 0x3a)
+Referrer: 3-byte escape 2
+AVXcode: 3
+# 0x0f 0x3a 0x00-0xff
+00: vpermq Vqq,Wqq,Ib (66),(v)
+01: vpermpd Vqq,Wqq,Ib (66),(v)
+02: vpblendd Vx,Hx,Wx,Ib (66),(v)
+03:
+04: vpermilps Vx,Wx,Ib (66),(v)
+05: vpermilpd Vx,Wx,Ib (66),(v)
+06: vperm2f128 Vqq,Hqq,Wqq,Ib (66),(v)
+07:
+08: vroundps Vx,Wx,Ib (66)
+09: vroundpd Vx,Wx,Ib (66)
+0a: vroundss Vss,Wss,Ib (66),(v1)
+0b: vroundsd Vsd,Wsd,Ib (66),(v1)
+0c: vblendps Vx,Hx,Wx,Ib (66)
+0d: vblendpd Vx,Hx,Wx,Ib (66)
+0e: vpblendw Vx,Hx,Wx,Ib (66),(v1)
+0f: palignr Pq,Qq,Ib | vpalignr Vx,Hx,Wx,Ib (66),(v1)
+14: vpextrb Rd/Mb,Vdq,Ib (66),(v1)
+15: vpextrw Rd/Mw,Vdq,Ib (66),(v1)
+16: vpextrd/q Ey,Vdq,Ib (66),(v1)
+17: vextractps Ed,Vdq,Ib (66),(v1)
+18: vinsertf128 Vqq,Hqq,Wqq,Ib (66),(v)
+19: vextractf128 Wdq,Vqq,Ib (66),(v)
+1d: vcvtps2ph Wx,Vx,Ib (66),(v)
+20: vpinsrb Vdq,Hdq,Ry/Mb,Ib (66),(v1)
+21: vinsertps Vdq,Hdq,Udq/Md,Ib (66),(v1)
+22: vpinsrd/q Vdq,Hdq,Ey,Ib (66),(v1)
+38: vinserti128 Vqq,Hqq,Wqq,Ib (66),(v)
+39: vextracti128 Wdq,Vqq,Ib (66),(v)
+40: vdpps Vx,Hx,Wx,Ib (66)
+41: vdppd Vdq,Hdq,Wdq,Ib (66),(v1)
+42: vmpsadbw Vx,Hx,Wx,Ib (66),(v1)
+44: vpclmulqdq Vdq,Hdq,Wdq,Ib (66),(v1)
+46: vperm2i128 Vqq,Hqq,Wqq,Ib (66),(v)
+4a: vblendvps Vx,Hx,Wx,Lx (66),(v)
+4b: vblendvpd Vx,Hx,Wx,Lx (66),(v)
+4c: vpblendvb Vx,Hx,Wx,Lx (66),(v1)
+60: vpcmpestrm Vdq,Wdq,Ib (66),(v1)
+61: vpcmpestri Vdq,Wdq,Ib (66),(v1)
+62: vpcmpistrm Vdq,Wdq,Ib (66),(v1)
+63: vpcmpistri Vdq,Wdq,Ib (66),(v1)
+df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1)
+f0: RORX Gy,Ey,Ib (F2),(v)
+EndTable
+
+GrpTable: Grp1
+0: ADD
+1: OR
+2: ADC
+3: SBB
+4: AND
+5: SUB
+6: XOR
+7: CMP
+EndTable
+
+GrpTable: Grp1A
+0: POP
+EndTable
+
+GrpTable: Grp2
+0: ROL
+1: ROR
+2: RCL
+3: RCR
+4: SHL/SAL
+5: SHR
+6:
+7: SAR
+EndTable
+
+GrpTable: Grp3_1
+0: TEST Eb,Ib
+1:
+2: NOT Eb
+3: NEG Eb
+4: MUL AL,Eb
+5: IMUL AL,Eb
+6: DIV AL,Eb
+7: IDIV AL,Eb
+EndTable
+
+GrpTable: Grp3_2
+0: TEST Ev,Iz
+1:
+2: NOT Ev
+3: NEG Ev
+4: MUL rAX,Ev
+5: IMUL rAX,Ev
+6: DIV rAX,Ev
+7: IDIV rAX,Ev
+EndTable
+
+GrpTable: Grp4
+0: INC Eb
+1: DEC Eb
+EndTable
+
+GrpTable: Grp5
+0: INC Ev
+1: DEC Ev
+2: CALLN Ev (f64)
+3: CALLF Ep
+4: JMPN Ev (f64)
+5: JMPF Mp
+6: PUSH Ev (d64)
+7:
+EndTable
+
+GrpTable: Grp6
+0: SLDT Rv/Mw
+1: STR Rv/Mw
+2: LLDT Ew
+3: LTR Ew
+4: VERR Ew
+5: VERW Ew
+EndTable
+
+GrpTable: Grp7
+0: SGDT Ms | VMCALL (001),(11B) | VMLAUNCH (010),(11B) | VMRESUME (011),(11B) | VMXOFF (100),(11B)
+1: SIDT Ms | MONITOR (000),(11B) | MWAIT (001),(11B) | CLAC (010),(11B) | STAC (011),(11B)
+2: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | XEND (101)(11B) | XTEST (110)(11B)
+3: LIDT Ms
+4: SMSW Mw/Rv
+5:
+6: LMSW Ew
+7: INVLPG Mb | SWAPGS (o64),(000),(11B) | RDTSCP (001),(11B)
+EndTable
+
+GrpTable: Grp8
+4: BT
+5: BTS
+6: BTR
+7: BTC
+EndTable
+
+GrpTable: Grp9
+1: CMPXCHG8B/16B Mq/Mdq
+6: VMPTRLD Mq | VMCLEAR Mq (66) | VMXON Mq (F3) | RDRAND Rv (11B)
+7: VMPTRST Mq | VMPTRST Mq (F3) | RDSEED Rv (11B)
+EndTable
+
+GrpTable: Grp10
+EndTable
+
+# Grp11A and Grp11B are expressed as Grp11 in Intel SDM
+GrpTable: Grp11A
+0: MOV Eb,Ib
+7: XABORT Ib (000),(11B)
+EndTable
+
+GrpTable: Grp11B
+0: MOV Eb,Iz
+7: XBEGIN Jz (000),(11B)
+EndTable
+
+GrpTable: Grp12
+2: psrlw Nq,Ib (11B) | vpsrlw Hx,Ux,Ib (66),(11B),(v1)
+4: psraw Nq,Ib (11B) | vpsraw Hx,Ux,Ib (66),(11B),(v1)
+6: psllw Nq,Ib (11B) | vpsllw Hx,Ux,Ib (66),(11B),(v1)
+EndTable
+
+GrpTable: Grp13
+2: psrld Nq,Ib (11B) | vpsrld Hx,Ux,Ib (66),(11B),(v1)
+4: psrad Nq,Ib (11B) | vpsrad Hx,Ux,Ib (66),(11B),(v1)
+6: pslld Nq,Ib (11B) | vpslld Hx,Ux,Ib (66),(11B),(v1)
+EndTable
+
+GrpTable: Grp14
+2: psrlq Nq,Ib (11B) | vpsrlq Hx,Ux,Ib (66),(11B),(v1)
+3: vpsrldq Hx,Ux,Ib (66),(11B),(v1)
+6: psllq Nq,Ib (11B) | vpsllq Hx,Ux,Ib (66),(11B),(v1)
+7: vpslldq Hx,Ux,Ib (66),(11B),(v1)
+EndTable
+
+GrpTable: Grp15
+0: fxsave | RDFSBASE Ry (F3),(11B)
+1: fxstor | RDGSBASE Ry (F3),(11B)
+2: vldmxcsr Md (v1) | WRFSBASE Ry (F3),(11B)
+3: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B)
+4: XSAVE
+5: XRSTOR | lfence (11B)
+6: XSAVEOPT | mfence (11B)
+7: clflush | sfence (11B)
+EndTable
+
+GrpTable: Grp16
+0: prefetch NTA
+1: prefetch T0
+2: prefetch T1
+3: prefetch T2
+EndTable
+
+GrpTable: Grp17
+1: BLSR By,Ey (v)
+2: BLSMSK By,Ey (v)
+3: BLSI By,Ey (v)
+EndTable
+
+# AMD's Prefetch Group
+GrpTable: GrpP
+0: PREFETCH
+1: PREFETCHW
+EndTable
+
+GrpTable: GrpPDLK
+0: MONTMUL
+1: XSHA1
+2: XSHA2
+EndTable
+
+GrpTable: GrpRNG
+0: xstore-rng
+1: xcrypt-ecb
+2: xcrypt-cbc
+4: xcrypt-cfb
+5: xcrypt-ofb
+EndTable
diff --git a/xen/include/asm-x86/inat.h b/xen/include/asm-x86/inat.h
new file mode 100644
index 0000000..41b9066
--- /dev/null
+++ b/xen/include/asm-x86/inat.h
@@ -0,0 +1,219 @@
+#ifndef _ASM_X86_INAT_H
+#define _ASM_X86_INAT_H
+/*
+ * x86 instruction attributes
+ *
+ * Written by Masami Hiramatsu <mhiramat@redhat.com>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+#include <asm/inat_types.h>
+
+/*
+ * Internal bits. Don't use bitmasks directly, because these bits are
+ * unstable. You should use checking functions.
+ */
+
+#define INAT_OPCODE_TABLE_SIZE 256
+#define INAT_GROUP_TABLE_SIZE 8
+
+/* Legacy last prefixes */
+#define INAT_PFX_OPNDSZ 1 /* 0x66 */ /* LPFX1 */
+#define INAT_PFX_REPE 2 /* 0xF3 */   /* LPFX2 */
+#define INAT_PFX_REPNE 3 /* 0xF2 */  /* LPFX3 */
+/* Other Legacy prefixes */
+#define INAT_PFX_LOCK 4    /* 0xF0 */
+#define INAT_PFX_CS 5      /* 0x2E */
+#define INAT_PFX_DS 6      /* 0x3E */
+#define INAT_PFX_ES 7      /* 0x26 */
+#define INAT_PFX_FS 8      /* 0x64 */
+#define INAT_PFX_GS 9      /* 0x65 */
+#define INAT_PFX_SS 10     /* 0x36 */
+#define INAT_PFX_ADDRSZ 11 /* 0x67 */
+/* x86-64 REX prefix */
+#define INAT_PFX_REX 12 /* 0x4X */
+/* AVX VEX prefixes */
+#define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */
+#define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */
+
+#define INAT_LSTPFX_MAX 3
+#define INAT_LGCPFX_MAX 11
+
+/* Immediate size */
+#define INAT_IMM_BYTE 1
+#define INAT_IMM_WORD 2
+#define INAT_IMM_DWORD 3
+#define INAT_IMM_QWORD 4
+#define INAT_IMM_PTR 5
+#define INAT_IMM_VWORD32 6
+#define INAT_IMM_VWORD 7
+
+/* Legacy prefix */
+#define INAT_PFX_OFFS 0
+#define INAT_PFX_BITS 4
+#define INAT_PFX_MAX ((1 << INAT_PFX_BITS) - 1)
+#define INAT_PFX_MASK (INAT_PFX_MAX << INAT_PFX_OFFS)
+/* Escape opcodes */
+#define INAT_ESC_OFFS (INAT_PFX_OFFS + INAT_PFX_BITS)
+#define INAT_ESC_BITS 2
+#define INAT_ESC_MAX ((1 << INAT_ESC_BITS) - 1)
+#define INAT_ESC_MASK (INAT_ESC_MAX << INAT_ESC_OFFS)
+/* Group opcodes (1-16) */
+#define INAT_GRP_OFFS (INAT_ESC_OFFS + INAT_ESC_BITS)
+#define INAT_GRP_BITS 5
+#define INAT_GRP_MAX ((1 << INAT_GRP_BITS) - 1)
+#define INAT_GRP_MASK (INAT_GRP_MAX << INAT_GRP_OFFS)
+/* Immediates */
+#define INAT_IMM_OFFS (INAT_GRP_OFFS + INAT_GRP_BITS)
+#define INAT_IMM_BITS 3
+#define INAT_IMM_MASK (((1 << INAT_IMM_BITS) - 1) << INAT_IMM_OFFS)
+/* Flags */
+#define INAT_FLAG_OFFS (INAT_IMM_OFFS + INAT_IMM_BITS)
+#define INAT_MODRM (1 << (INAT_FLAG_OFFS))
+#define INAT_FORCE64 (1 << (INAT_FLAG_OFFS + 1))
+#define INAT_SCNDIMM (1 << (INAT_FLAG_OFFS + 2))
+#define INAT_MOFFSET (1 << (INAT_FLAG_OFFS + 3))
+#define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4))
+#define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5))
+#define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6))
+/* Attribute making macros for attribute tables */
+#define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS)
+#define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS)
+#define INAT_MAKE_GROUP(grp) ((grp << INAT_GRP_OFFS) | INAT_MODRM)
+#define INAT_MAKE_IMM(imm) (imm << INAT_IMM_OFFS)
+
+/* Attribute search APIs */
+extern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode);
+extern int inat_get_last_prefix_id(insn_byte_t last_pfx);
+extern insn_attr_t inat_get_escape_attribute(insn_byte_t opcode, int lpfx_id,
+                                             insn_attr_t esc_attr);
+extern insn_attr_t inat_get_group_attribute(insn_byte_t modrm, int lpfx_id,
+                                            insn_attr_t esc_attr);
+extern insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, insn_byte_t vex_m,
+                                          insn_byte_t vex_pp);
+
+/* Attribute checking functions */
+static inline int inat_is_legacy_prefix(insn_attr_t attr)
+{
+    attr &= INAT_PFX_MASK;
+    return attr && attr <= INAT_LGCPFX_MAX;
+}
+
+static inline int inat_is_address_size_prefix(insn_attr_t attr)
+{
+    return (attr & INAT_PFX_MASK) == INAT_PFX_ADDRSZ;
+}
+
+static inline int inat_is_operand_size_prefix(insn_attr_t attr)
+{
+    return (attr & INAT_PFX_MASK) == INAT_PFX_OPNDSZ;
+}
+
+static inline int inat_is_rex_prefix(insn_attr_t attr)
+{
+    return (attr & INAT_PFX_MASK) == INAT_PFX_REX;
+}
+
+static inline int inat_last_prefix_id(insn_attr_t attr)
+{
+    if ( (attr & INAT_PFX_MASK) > INAT_LSTPFX_MAX )
+        return 0;
+    else
+        return attr & INAT_PFX_MASK;
+}
+
+static inline int inat_is_vex_prefix(insn_attr_t attr)
+{
+    attr &= INAT_PFX_MASK;
+    return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3;
+}
+
+static inline int inat_is_vex3_prefix(insn_attr_t attr)
+{
+    return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3;
+}
+
+static inline int inat_is_escape(insn_attr_t attr)
+{
+    return attr & INAT_ESC_MASK;
+}
+
+static inline int inat_escape_id(insn_attr_t attr)
+{
+    return (attr & INAT_ESC_MASK) >> INAT_ESC_OFFS;
+}
+
+static inline int inat_is_group(insn_attr_t attr)
+{
+    return attr & INAT_GRP_MASK;
+}
+
+static inline int inat_group_id(insn_attr_t attr)
+{
+    return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS;
+}
+
+static inline int inat_group_common_attribute(insn_attr_t attr)
+{
+    return attr & ~INAT_GRP_MASK;
+}
+
+static inline int inat_has_immediate(insn_attr_t attr)
+{
+    return attr & INAT_IMM_MASK;
+}
+
+static inline int inat_immediate_size(insn_attr_t attr)
+{
+    return (attr & INAT_IMM_MASK) >> INAT_IMM_OFFS;
+}
+
+static inline int inat_has_modrm(insn_attr_t attr)
+{
+    return attr & INAT_MODRM;
+}
+
+static inline int inat_is_force64(insn_attr_t attr)
+{
+    return attr & INAT_FORCE64;
+}
+
+static inline int inat_has_second_immediate(insn_attr_t attr)
+{
+    return attr & INAT_SCNDIMM;
+}
+
+static inline int inat_has_moffset(insn_attr_t attr)
+{
+    return attr & INAT_MOFFSET;
+}
+
+static inline int inat_has_variant(insn_attr_t attr)
+{
+    return attr & INAT_VARIANT;
+}
+
+static inline int inat_accept_vex(insn_attr_t attr)
+{
+    return attr & INAT_VEXOK;
+}
+
+static inline int inat_must_vex(insn_attr_t attr)
+{
+    return attr & INAT_VEXONLY;
+}
+
+#endif /* _ASM_X86_INAT_H */
diff --git a/xen/include/asm-x86/inat_types.h b/xen/include/asm-x86/inat_types.h
new file mode 100644
index 0000000..662ac14
--- /dev/null
+++ b/xen/include/asm-x86/inat_types.h
@@ -0,0 +1,29 @@
+#ifndef _ASM_X86_INAT_TYPES_H
+#define _ASM_X86_INAT_TYPES_H
+/*
+ * x86 instruction attributes
+ *
+ * Written by Masami Hiramatsu <mhiramat@redhat.com>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+/* Instruction attributes */
+typedef unsigned int insn_attr_t;
+typedef unsigned char insn_byte_t;
+typedef signed int insn_value_t;
+
+#endif /* _ASM_X86_INAT_TYPES_H */
diff --git a/xen/include/asm-x86/insn.h b/xen/include/asm-x86/insn.h
new file mode 100644
index 0000000..739773a
--- /dev/null
+++ b/xen/include/asm-x86/insn.h
@@ -0,0 +1,201 @@
+#ifndef _ASM_X86_INSN_H
+#define _ASM_X86_INSN_H
+/*
+ * x86 instruction analysis
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2009
+ */
+
+/* insn_attr_t is defined in inat.h */
+#include <asm/inat.h>
+
+struct insn_field
+{
+    union {
+        insn_value_t value;
+        insn_byte_t bytes[4];
+    };
+    /* !0 if we've run insn_get_xxx() for this field */
+    unsigned char got;
+    unsigned char nbytes;
+};
+
+struct insn
+{
+    struct insn_field prefixes; /*
+                                 * Prefixes
+                                 * prefixes.bytes[3]: last prefix
+                                 */
+    struct insn_field rex_prefix; /* REX prefix */
+    struct insn_field vex_prefix; /* VEX prefix */
+    struct insn_field opcode;     /*
+                                   * opcode.bytes[0]: opcode1
+                                   * opcode.bytes[1]: opcode2
+                                   * opcode.bytes[2]: opcode3
+                                   */
+    struct insn_field modrm;
+    struct insn_field sib;
+    struct insn_field displacement;
+    union {
+        struct insn_field immediate;
+        struct insn_field moffset1;   /* for 64bit MOV */
+        struct insn_field immediate1; /* for 64bit imm or off16/32 */
+    };
+    union {
+        struct insn_field moffset2;   /* for 64bit MOV */
+        struct insn_field immediate2; /* for 64bit imm or seg16 */
+    };
+
+    insn_attr_t attr;
+    unsigned char opnd_bytes;
+    unsigned char addr_bytes;
+    unsigned char length;
+    unsigned char x86_64;
+
+    const insn_byte_t *kaddr; /* kernel address of insn to analyze */
+    const insn_byte_t *next_byte;
+};
+
+#define MAX_INSN_SIZE 16
+
+#define X86_MODRM_MOD(modrm) (((modrm) & 0xc0) >> 6)
+#define X86_MODRM_REG(modrm) (((modrm) & 0x38) >> 3)
+#define X86_MODRM_RM(modrm) ((modrm) & 0x07)
+
+#define X86_SIB_SCALE(sib) (((sib) & 0xc0) >> 6)
+#define X86_SIB_INDEX(sib) (((sib) & 0x38) >> 3)
+#define X86_SIB_BASE(sib) ((sib) & 0x07)
+
+#define X86_REX_W(rex) ((rex) & 8)
+#define X86_REX_R(rex) ((rex) & 4)
+#define X86_REX_X(rex) ((rex) & 2)
+#define X86_REX_B(rex) ((rex) & 1)
+
+/* VEX bit flags  */
+#define X86_VEX_W(vex) ((vex) & 0x80) /* VEX3 Byte2 */
+#define X86_VEX_R(vex) ((vex) & 0x80) /* VEX2/3 Byte1 */
+#define X86_VEX_X(vex) ((vex) & 0x40) /* VEX3 Byte1 */
+#define X86_VEX_B(vex) ((vex) & 0x20) /* VEX3 Byte1 */
+#define X86_VEX_L(vex) ((vex) & 0x04) /* VEX3 Byte2, VEX2 Byte1 */
+/* VEX bit fields */
+#define X86_VEX3_M(vex) ((vex) & 0x1f)       /* VEX3 Byte1 */
+#define X86_VEX2_M 1                         /* VEX2.M always 1 */
+#define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */
+#define X86_VEX_P(vex) ((vex) & 0x03)        /* VEX3 Byte2, VEX2 Byte1 */
+#define X86_VEX_M_MAX 0x1f                   /* VEX3.M Maximum value */
+
+extern void insn_init(struct insn *insn, const void *kaddr, int x86_64);
+extern void insn_get_prefixes(struct insn *insn);
+extern void insn_get_opcode(struct insn *insn);
+extern void insn_get_modrm(struct insn *insn);
+extern void insn_get_sib(struct insn *insn);
+extern void insn_get_displacement(struct insn *insn);
+extern void insn_get_immediate(struct insn *insn);
+extern void insn_get_length(struct insn *insn);
+
+/* Attribute will be determined after getting ModRM (for opcode groups) */
+static inline void insn_get_attribute(struct insn *insn)
+{
+    insn_get_modrm(insn);
+}
+
+/* Instruction uses RIP-relative addressing */
+extern int insn_rip_relative(struct insn *insn);
+
+/* Init insn for kernel text */
+static inline void kernel_insn_init(struct insn *insn, const void *kaddr)
+{
+#ifdef CONFIG_X86_64
+    insn_init(insn, kaddr, 1);
+#else /* CONFIG_X86_32 */
+    insn_init(insn, kaddr, 0);
+#endif
+}
+
+static inline int insn_is_avx(struct insn *insn)
+{
+    if ( !insn->prefixes.got )
+        insn_get_prefixes(insn);
+    return (insn->vex_prefix.value != 0);
+}
+
+/* Ensure this instruction is decoded completely */
+static inline int insn_complete(struct insn *insn)
+{
+    return insn->opcode.got && insn->modrm.got && insn->sib.got &&
+           insn->displacement.got && insn->immediate.got;
+}
+
+static inline insn_byte_t insn_vex_m_bits(struct insn *insn)
+{
+    if ( insn->vex_prefix.nbytes == 2 ) /* 2 bytes VEX */
+        return X86_VEX2_M;
+    else
+        return X86_VEX3_M(insn->vex_prefix.bytes[1]);
+}
+
+static inline insn_byte_t insn_vex_p_bits(struct insn *insn)
+{
+    if ( insn->vex_prefix.nbytes == 2 ) /* 2 bytes VEX */
+        return X86_VEX_P(insn->vex_prefix.bytes[1]);
+    else
+        return X86_VEX_P(insn->vex_prefix.bytes[2]);
+}
+
+/* Get the last prefix id from last prefix or VEX prefix */
+static inline int insn_last_prefix_id(struct insn *insn)
+{
+    if ( insn_is_avx(insn) )
+        return insn_vex_p_bits(insn); /* VEX_p is a SIMD prefix id */
+
+    if ( insn->prefixes.bytes[3] )
+        return inat_get_last_prefix_id(insn->prefixes.bytes[3]);
+
+    return 0;
+}
+
+/* Offset of each field from kaddr */
+static inline int insn_offset_rex_prefix(struct insn *insn)
+{
+    return insn->prefixes.nbytes;
+}
+static inline int insn_offset_vex_prefix(struct insn *insn)
+{
+    return insn_offset_rex_prefix(insn) + insn->rex_prefix.nbytes;
+}
+static inline int insn_offset_opcode(struct insn *insn)
+{
+    return insn_offset_vex_prefix(insn) + insn->vex_prefix.nbytes;
+}
+static inline int insn_offset_modrm(struct insn *insn)
+{
+    return insn_offset_opcode(insn) + insn->opcode.nbytes;
+}
+static inline int insn_offset_sib(struct insn *insn)
+{
+    return insn_offset_modrm(insn) + insn->modrm.nbytes;
+}
+static inline int insn_offset_displacement(struct insn *insn)
+{
+    return insn_offset_sib(insn) + insn->sib.nbytes;
+}
+static inline int insn_offset_immediate(struct insn *insn)
+{
+    return insn_offset_displacement(insn) + insn->displacement.nbytes;
+}
+
+#endif /* _ASM_X86_INSN_H */
diff --git a/xen/tools/gen-insn-attr-x86.awk b/xen/tools/gen-insn-attr-x86.awk
new file mode 100644
index 0000000..bbb8f40
--- /dev/null
+++ b/xen/tools/gen-insn-attr-x86.awk
@@ -0,0 +1,386 @@
+#!/bin/awk -f
+# gen-insn-attr-x86.awk: Instruction attribute table generator
+# Written by Masami Hiramatsu <mhiramat@redhat.com>
+#
+# Usage: awk -f gen-insn-attr-x86.awk x86-opcode-map.txt > inat-tables.c
+
+# Awk implementation sanity check
+function check_awk_implement() {
+	if (sprintf("%x", 0) != "0")
+		return "Your awk has a printf-format problem."
+	return ""
+}
+
+# Clear working vars
+function clear_vars() {
+	delete table
+	delete lptable2
+	delete lptable1
+	delete lptable3
+	eid = -1 # escape id
+	gid = -1 # group id
+	aid = -1 # AVX id
+	tname = ""
+}
+
+BEGIN {
+	# Implementation error checking
+	awkchecked = check_awk_implement()
+	if (awkchecked != "") {
+		print "Error: " awkchecked > "/dev/stderr"
+		print "Please try to use gawk." > "/dev/stderr"
+		exit 1
+	}
+
+	# Setup generating tables
+	print "/* x86 opcode map generated from x86-opcode-map.txt */"
+	print "/* Do not change this code. */\n"
+	ggid = 1
+	geid = 1
+	gaid = 0
+	delete etable
+	delete gtable
+	delete atable
+
+	opnd_expr = "^[A-Za-z/]"
+	ext_expr = "^\\("
+	sep_expr = "^\\|$"
+	group_expr = "^Grp[0-9A-Za-z]+"
+
+	imm_expr = "^[IJAOL][a-z]"
+	imm_flag["Ib"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
+	imm_flag["Jb"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
+	imm_flag["Iw"] = "INAT_MAKE_IMM(INAT_IMM_WORD)"
+	imm_flag["Id"] = "INAT_MAKE_IMM(INAT_IMM_DWORD)"
+	imm_flag["Iq"] = "INAT_MAKE_IMM(INAT_IMM_QWORD)"
+	imm_flag["Ap"] = "INAT_MAKE_IMM(INAT_IMM_PTR)"
+	imm_flag["Iz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
+	imm_flag["Jz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
+	imm_flag["Iv"] = "INAT_MAKE_IMM(INAT_IMM_VWORD)"
+	imm_flag["Ob"] = "INAT_MOFFSET"
+	imm_flag["Ov"] = "INAT_MOFFSET"
+	imm_flag["Lx"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
+
+	modrm_expr = "^([CDEGMNPQRSUVW/][a-z]+|NTA|T[012])"
+	force64_expr = "\\([df]64\\)"
+	rex_expr = "^REX(\\.[XRWB]+)*"
+	fpu_expr = "^ESC" # TODO
+
+	lprefix1_expr = "\\((66|!F3)\\)"
+	lprefix2_expr = "\\(F3\\)"
+	lprefix3_expr = "\\((F2|!F3|66\\&F2)\\)"
+	lprefix_expr = "\\((66|F2|F3)\\)"
+	max_lprefix = 4
+
+	# All opcodes starting with lower-case 'v' or with (v1) superscript
+	# accepts VEX prefix
+	vexok_opcode_expr = "^v.*"
+	vexok_expr = "\\(v1\\)"
+	# All opcodes with (v) superscript supports *only* VEX prefix
+	vexonly_expr = "\\(v\\)"
+
+	prefix_expr = "\\(Prefix\\)"
+	prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ"
+	prefix_num["REPNE"] = "INAT_PFX_REPNE"
+	prefix_num["REP/REPE"] = "INAT_PFX_REPE"
+	prefix_num["XACQUIRE"] = "INAT_PFX_REPNE"
+	prefix_num["XRELEASE"] = "INAT_PFX_REPE"
+	prefix_num["LOCK"] = "INAT_PFX_LOCK"
+	prefix_num["SEG=CS"] = "INAT_PFX_CS"
+	prefix_num["SEG=DS"] = "INAT_PFX_DS"
+	prefix_num["SEG=ES"] = "INAT_PFX_ES"
+	prefix_num["SEG=FS"] = "INAT_PFX_FS"
+	prefix_num["SEG=GS"] = "INAT_PFX_GS"
+	prefix_num["SEG=SS"] = "INAT_PFX_SS"
+	prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ"
+	prefix_num["VEX+1byte"] = "INAT_PFX_VEX2"
+	prefix_num["VEX+2byte"] = "INAT_PFX_VEX3"
+
+	clear_vars()
+}
+
+function semantic_error(msg) {
+	print "Semantic error at " NR ": " msg > "/dev/stderr"
+	exit 1
+}
+
+function debug(msg) {
+	print "DEBUG: " msg
+}
+
+function array_size(arr,   i,c) {
+	c = 0
+	for (i in arr)
+		c++
+	return c
+}
+
+/^Table:/ {
+	print "/* " $0 " */"
+	if (tname != "")
+		semantic_error("Hit Table: before EndTable:.");
+}
+
+/^Referrer:/ {
+	if (NF != 1) {
+		# escape opcode table
+		ref = ""
+		for (i = 2; i <= NF; i++)
+			ref = ref $i
+		eid = escape[ref]
+		tname = sprintf("inat_escape_table_%d", eid)
+	}
+}
+
+/^AVXcode:/ {
+	if (NF != 1) {
+		# AVX/escape opcode table
+		aid = $2
+		if (gaid <= aid)
+			gaid = aid + 1
+		if (tname == "")	# AVX only opcode table
+			tname = sprintf("inat_avx_table_%d", $2)
+	}
+	if (aid == -1 && eid == -1)	# primary opcode table
+		tname = "inat_primary_table"
+}
+
+/^GrpTable:/ {
+	print "/* " $0 " */"
+	if (!($2 in group))
+		semantic_error("No group: " $2 )
+	gid = group[$2]
+	tname = "inat_group_table_" gid
+}
+
+function print_table(tbl,name,fmt,n)
+{
+	print "const insn_attr_t " name " = {"
+	for (i = 0; i < n; i++) {
+		id = sprintf(fmt, i)
+		if (tbl[id])
+			print "    [" id "] = " tbl[id] ","
+	}
+	print "};"
+}
+
+/^EndTable/ {
+	if (gid != -1) {
+		# print group tables
+		if (array_size(table) != 0) {
+			print_table(table, tname "[INAT_GROUP_TABLE_SIZE]",
+				    "0x%x", 8)
+			gtable[gid,0] = tname
+		}
+		if (array_size(lptable1) != 0) {
+			print_table(lptable1, tname "_1[INAT_GROUP_TABLE_SIZE]",
+				    "0x%x", 8)
+			gtable[gid,1] = tname "_1"
+		}
+		if (array_size(lptable2) != 0) {
+			print_table(lptable2, tname "_2[INAT_GROUP_TABLE_SIZE]",
+				    "0x%x", 8)
+			gtable[gid,2] = tname "_2"
+		}
+		if (array_size(lptable3) != 0) {
+			print_table(lptable3, tname "_3[INAT_GROUP_TABLE_SIZE]",
+				    "0x%x", 8)
+			gtable[gid,3] = tname "_3"
+		}
+	} else {
+		# print primary/escaped tables
+		if (array_size(table) != 0) {
+			print_table(table, tname "[INAT_OPCODE_TABLE_SIZE]",
+				    "0x%02x", 256)
+			etable[eid,0] = tname
+			if (aid >= 0)
+				atable[aid,0] = tname
+		}
+		if (array_size(lptable1) != 0) {
+			print_table(lptable1,tname "_1[INAT_OPCODE_TABLE_SIZE]",
+				    "0x%02x", 256)
+			etable[eid,1] = tname "_1"
+			if (aid >= 0)
+				atable[aid,1] = tname "_1"
+		}
+		if (array_size(lptable2) != 0) {
+			print_table(lptable2,tname "_2[INAT_OPCODE_TABLE_SIZE]",
+				    "0x%02x", 256)
+			etable[eid,2] = tname "_2"
+			if (aid >= 0)
+				atable[aid,2] = tname "_2"
+		}
+		if (array_size(lptable3) != 0) {
+			print_table(lptable3,tname "_3[INAT_OPCODE_TABLE_SIZE]",
+				    "0x%02x", 256)
+			etable[eid,3] = tname "_3"
+			if (aid >= 0)
+				atable[aid,3] = tname "_3"
+		}
+	}
+	print ""
+	clear_vars()
+}
+
+function add_flags(old,new) {
+	if (old && new)
+		return old " | " new
+	else if (old)
+		return old
+	else
+		return new
+}
+
+# convert operands to flags.
+function convert_operands(count,opnd,       i,j,imm,mod)
+{
+	imm = null
+	mod = null
+	for (j = 1; j <= count; j++) {
+		i = opnd[j]
+		if (match(i, imm_expr) == 1) {
+			if (!imm_flag[i])
+				semantic_error("Unknown imm opnd: " i)
+			if (imm) {
+				if (i != "Ib")
+					semantic_error("Second IMM error")
+				imm = add_flags(imm, "INAT_SCNDIMM")
+			} else
+				imm = imm_flag[i]
+		} else if (match(i, modrm_expr))
+			mod = "INAT_MODRM"
+	}
+	return add_flags(imm, mod)
+}
+
+/^[0-9a-f]+\:/ {
+	if (NR == 1)
+		next
+	# get index
+	idx = "0x" substr($1, 1, index($1,":") - 1)
+	if (idx in table)
+		semantic_error("Redefine " idx " in " tname)
+
+	# check if escaped opcode
+	if ("escape" == $2) {
+		if ($3 != "#")
+			semantic_error("No escaped name")
+		ref = ""
+		for (i = 4; i <= NF; i++)
+			ref = ref $i
+		if (ref in escape)
+			semantic_error("Redefine escape (" ref ")")
+		escape[ref] = geid
+		geid++
+		table[idx] = "INAT_MAKE_ESCAPE(" escape[ref] ")"
+		next
+	}
+
+	variant = null
+	# converts
+	i = 2
+	while (i <= NF) {
+		opcode = $(i++)
+		delete opnds
+		ext = null
+		flags = null
+		opnd = null
+		# parse one opcode
+		if (match($i, opnd_expr)) {
+			opnd = $i
+			count = split($(i++), opnds, ",")
+			flags = convert_operands(count, opnds)
+		}
+		if (match($i, ext_expr))
+			ext = $(i++)
+		if (match($i, sep_expr))
+			i++
+		else if (i < NF)
+			semantic_error($i " is not a separator")
+
+		# check if group opcode
+		if (match(opcode, group_expr)) {
+			if (!(opcode in group)) {
+				group[opcode] = ggid
+				ggid++
+			}
+			flags = add_flags(flags, "INAT_MAKE_GROUP(" group[opcode] ")")
+		}
+		# check force(or default) 64bit
+		if (match(ext, force64_expr))
+			flags = add_flags(flags, "INAT_FORCE64")
+
+		# check REX prefix
+		if (match(opcode, rex_expr))
+			flags = add_flags(flags, "INAT_MAKE_PREFIX(INAT_PFX_REX)")
+
+		# check coprocessor escape : TODO
+		if (match(opcode, fpu_expr))
+			flags = add_flags(flags, "INAT_MODRM")
+
+		# check VEX codes
+		if (match(ext, vexonly_expr))
+			flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY")
+		else if (match(ext, vexok_expr) || match(opcode, vexok_opcode_expr))
+			flags = add_flags(flags, "INAT_VEXOK")
+
+		# check prefixes
+		if (match(ext, prefix_expr)) {
+			if (!prefix_num[opcode])
+				semantic_error("Unknown prefix: " opcode)
+			flags = add_flags(flags, "INAT_MAKE_PREFIX(" prefix_num[opcode] ")")
+		}
+		if (length(flags) == 0)
+			continue
+		# check if last prefix
+		if (match(ext, lprefix1_expr)) {
+			lptable1[idx] = add_flags(lptable1[idx],flags)
+			variant = "INAT_VARIANT"
+		}
+		if (match(ext, lprefix2_expr)) {
+			lptable2[idx] = add_flags(lptable2[idx],flags)
+			variant = "INAT_VARIANT"
+		}
+		if (match(ext, lprefix3_expr)) {
+			lptable3[idx] = add_flags(lptable3[idx],flags)
+			variant = "INAT_VARIANT"
+		}
+		if (!match(ext, lprefix_expr)){
+			table[idx] = add_flags(table[idx],flags)
+		}
+	}
+	if (variant)
+		table[idx] = add_flags(table[idx],variant)
+}
+
+END {
+	if (awkchecked != "")
+		exit 1
+	# print escape opcode map's array
+	print "/* Escape opcode map array */"
+	print "static const insn_attr_t * const inat_escape_tables[INAT_ESC_MAX + 1]" \
+	      "[INAT_LSTPFX_MAX + 1] = {"
+	for (i = 0; i < geid; i++)
+		for (j = 0; j < max_lprefix; j++)
+			if (etable[i,j])
+				print "    ["i"]["j"] = "etable[i,j]","
+	print "};\n"
+	# print group opcode map's array
+	print "/* Group opcode map array */"
+	print "static const insn_attr_t * const inat_group_tables[INAT_GRP_MAX + 1]"\
+	      "[INAT_LSTPFX_MAX + 1] = {"
+	for (i = 0; i < ggid; i++)
+		for (j = 0; j < max_lprefix; j++)
+			if (gtable[i,j])
+				print "    ["i"]["j"] = "gtable[i,j]","
+	print "};\n"
+	# print AVX opcode map's array
+	print "/* AVX opcode map array */"
+	print "static const insn_attr_t * const inat_avx_tables[X86_VEX_M_MAX + 1]"\
+	      "[INAT_LSTPFX_MAX + 1] = {"
+	for (i = 0; i < gaid; i++)
+		for (j = 0; j < max_lprefix; j++)
+			if (atable[i,j])
+				print "    ["i"]["j"] = "atable[i,j]","
+	print "};"
+}
-- 
1.9.1


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

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 2/3] x86/hvm: implement hvm_get_insn_length()
  2014-09-09  2:22 [PATCH 0/3] xen: add support for skipping the current instruction Mihai Donțu
  2014-09-09  2:28 ` [PATCH 1/3] x86: add support for computing the instruction length Mihai Donțu
@ 2014-09-09  2:29 ` Mihai Donțu
  2014-09-09  2:32 ` [PATCH 3/3] xen/tools: script for automatically adjusting the coding style to xen style Mihai Donțu
  2014-09-09  9:47 ` [PATCH 0/3] xen: add support for skipping the current instruction Jan Beulich
  3 siblings, 0 replies; 21+ messages in thread
From: Mihai Donțu @ 2014-09-09  2:29 UTC (permalink / raw)
  To: xen-devel; +Cc: Mihai Donțu, keir, jbeulich

Add a helper function that can be used to compute the length of the current
instruction (the one that generated a VMEXIT). This can be called by memory
introspection technologies to jump over instructions that were classified
as malicious.

Signed-off-by: Mihai Donțu <mdontu@bitdefender.com>
---
 xen/arch/x86/hvm/emulate.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index 6ab06e0..8f5357d 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -21,6 +21,7 @@
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/trace.h>
 #include <asm/hvm/support.h>
+#include <asm/insn.h>
 
 static void hvmtrace_io_assist(int is_mmio, ioreq_t *p)
 {
@@ -1410,6 +1411,50 @@ void hvm_mem_event_emulate_one(bool_t nowrite, unsigned int trapnr,
     hvm_emulate_writeback(&ctx);
 }
 
+int hvm_get_insn_length(
+    struct hvm_emulate_ctxt *hvmemul_ctxt)
+{
+    struct cpu_user_regs *regs = hvmemul_ctxt->ctxt.regs;
+    struct vcpu *curr = current;
+    uint32_t pfec = PFEC_page_present;
+    unsigned long addr;
+    struct insn insn;
+
+    if ( hvm_long_mode_enabled(curr) &&
+         hvmemul_ctxt->seg_reg[x86_seg_cs].attr.fields.l )
+        hvmemul_ctxt->ctxt.addr_size = hvmemul_ctxt->ctxt.sp_size = 64;
+    else
+    {
+        hvmemul_ctxt->ctxt.addr_size =
+            hvmemul_ctxt->seg_reg[x86_seg_cs].attr.fields.db ? 32 : 16;
+        hvmemul_ctxt->ctxt.sp_size =
+            hvmemul_ctxt->seg_reg[x86_seg_ss].attr.fields.db ? 32 : 16;
+    }
+
+    if ( hvmemul_ctxt->seg_reg[x86_seg_ss].attr.fields.dpl == 3 )
+        pfec |= PFEC_user_mode;
+
+    hvmemul_ctxt->insn_buf_eip = regs->eip;
+    hvmemul_ctxt->insn_buf_bytes =
+        hvm_get_insn_bytes(curr, hvmemul_ctxt->insn_buf)
+        ? :
+        (hvm_virtual_to_linear_addr(
+            x86_seg_cs, &hvmemul_ctxt->seg_reg[x86_seg_cs],
+            regs->eip, sizeof(hvmemul_ctxt->insn_buf),
+            hvm_access_insn_fetch, hvmemul_ctxt->ctxt.addr_size, &addr) &&
+        !hvm_fetch_from_guest_virt_nofault(
+            hvmemul_ctxt->insn_buf, addr,
+            sizeof(hvmemul_ctxt->insn_buf), pfec))
+    ? sizeof(hvmemul_ctxt->insn_buf) : 0;
+
+    hvmemul_ctxt->exn_pending = 0;
+
+    insn_init(&insn, hvmemul_ctxt->insn_buf, hvm_long_mode_enabled(curr));
+    insn_get_length(&insn);
+
+    return insn.length;
+}
+
 void hvm_emulate_prepare(
     struct hvm_emulate_ctxt *hvmemul_ctxt,
     struct cpu_user_regs *regs)
-- 
1.9.1


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

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 3/3] xen/tools: script for automatically adjusting the coding style to xen style
  2014-09-09  2:22 [PATCH 0/3] xen: add support for skipping the current instruction Mihai Donțu
  2014-09-09  2:28 ` [PATCH 1/3] x86: add support for computing the instruction length Mihai Donțu
  2014-09-09  2:29 ` [PATCH 2/3] x86/hvm: implement hvm_get_insn_length() Mihai Donțu
@ 2014-09-09  2:32 ` Mihai Donțu
  2014-09-09 14:50   ` Ian Campbell
  2014-09-10 14:21   ` Don Slutz
  2014-09-09  9:47 ` [PATCH 0/3] xen: add support for skipping the current instruction Jan Beulich
  3 siblings, 2 replies; 21+ messages in thread
From: Mihai Donțu @ 2014-09-09  2:32 UTC (permalink / raw)
  To: xen-devel; +Cc: Mihai Donțu

This is a clang-format wrapper script that can be used to do the bulk of the
coding style work on a foreign source file. It is not yet complete, but it's
sufficient for 98% of the cases.

Signed-off-by: Mihai Donțu <mdontu@bitdefender.com>
---
 xen/tools/xen-indent | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)
 create mode 100755 xen/tools/xen-indent

diff --git a/xen/tools/xen-indent b/xen/tools/xen-indent
new file mode 100755
index 0000000..6be507c
--- /dev/null
+++ b/xen/tools/xen-indent
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+CLANG_FORMAT=`which clang-format 2>/dev/null`
+
+if [ "x$CLANG_FORMAT" = "x" ]; then
+	printf "Error: \`clang-format' is not installed. It is usually part of clang (3.4 and newer)\n" >&2
+	exit 1
+fi
+
+if [ "x$1" = "x" ]; then
+	printf "Usage: $0 <file[s]>\n"
+	exit 2
+fi
+
+for i in $@; do
+	DN=`dirname "$i"`
+	cat >"$DN/.clang-format" <<EOF
+---
+AccessModifierOffset:                           -8
+IndentWidth:                                    4
+TabWidth:                                       4
+ConstructorInitializerIndentWidth:              4
+AlignEscapedNewlinesLeft:                       true
+AlignTrailingComments:                          true
+AllowAllParametersOfDeclarationOnNextLine:      true
+AllowShortIfStatementsOnASingleLine:            false
+AllowShortLoopsOnASingleLine:                   false
+AllowShortFunctionsOnASingleLine:               false
+AlwaysBreakTemplateDeclarations:                false
+AlwaysBreakBeforeMultilineStrings:              false
+BreakBeforeBinaryOperators:                     false
+BreakBeforeTernaryOperators:                    true
+BreakConstructorInitializersBeforeComma:        false
+BinPackParameters:                              true
+ColumnLimit:                                    80
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+DerivePointerBinding:                           false
+ExperimentalAutoDetectBinPacking:               false
+IndentCaseLabels:                               false
+MaxEmptyLinesToKeep:                            1
+NamespaceIndentation:                           All
+ObjCSpaceBeforeProtocolList:                    true
+PenaltyBreakBeforeFirstCallParameter:           19
+PenaltyBreakComment:                            60
+PenaltyBreakString:                             1000
+PenaltyBreakFirstLessLess:                      120
+PenaltyExcessCharacter:                         1000000
+PenaltyReturnTypeOnItsOwnLine:                  60
+PointerBindsToType:                             false
+SpacesBeforeTrailingComments:                   1
+Cpp11BracedListStyle:                           false
+Standard:                                       Cpp11
+UseTab:                                         Never
+BreakBeforeBraces:                              Allman
+IndentFunctionDeclarationAfterType:             false
+SpaceBeforeParens:                              ControlStatements
+SpacesInParentheses:                            false
+SpacesInAngles:                                 false
+SpaceInEmptyParentheses:                        false
+SpacesInCStyleCastParentheses:                  false
+SpaceAfterControlStatementKeyword:              true
+SpaceBeforeAssignmentOperators:                 true
+ContinuationIndentWidth:                        4
+EOF
+	ERR=0
+	$CLANG_FORMAT "$i" >"${i}.clang-tmp" || ERR=1
+	rm -f "$DN/.clang-format"
+	if [ $ERR -ne 0 ]; then
+		rm -f "${i}.clang-tmp"
+		exit 3
+	fi
+	sed 's#if\s*(\(.*\))#if ( \1 )#m' "${i}.clang-tmp" >"${i}.clang-tmp.1"
+	sed 's#switch\s*(\(.*\))#switch ( \1 )#m' "${i}.clang-tmp.1" >"${i}.clang-tmp.2"
+	sed 's#while\s*(\(.*\))#while ( \1 )#m' "${i}.clang-tmp.2" >"${i}.clang-tmp.3"
+	mv -f "${i}.clang-tmp.3" "${i}"
+	rm -f "${i}.clang-tmp" "${i}.clang-tmp.1" "${i}.clang-tmp.2"
+done
-- 
1.9.1


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

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/3] x86: add support for computing the instruction length
  2014-09-09  2:28 ` [PATCH 1/3] x86: add support for computing the instruction length Mihai Donțu
@ 2014-09-09  8:47   ` Mihai Donțu
  2014-09-09  9:44     ` Mihai Donțu
  0 siblings, 1 reply; 21+ messages in thread
From: Mihai Donțu @ 2014-09-09  8:47 UTC (permalink / raw)
  To: xen-devel; +Cc: keir, Razvan Cojocaru, jbeulich

On Tuesday 09 September 2014 05:28:02 Mihai Donțu wrote:
> This patch adds support for computing the length of an instruction. The entire
> logic relies on a set of opcode tables generated by gen-insn-attr-x86.awk from
> x86-opcode-map.txt and a number of small helper functions. It originated in
> Linux, where it was added by Masami Hiramatsu. Since it's an almost identical
> copy, it's separated from the x86 emulator, simplifying future updates.
> 
> ---
> Changed since v1:
>   * adjusted the coding style to match the rest of xen
>   * moved the source files into x86/x86_emulate
>   * replaced inat-tables.c with x86-opcode-map.txt and gen-insn-attr-x86.awk
>     that are used to generate it
> 
> Signed-off-by: Mihai Donțu <mdontu@bitdefender.com>

There are a couple of design issues with this code which Jan pointed
out and which I overlooked. I'm sorry, it was not intentional. I'll do
my best to address them in a following email.

>  xen/arch/x86/Makefile                       |  11 +-
>  xen/arch/x86/x86_emulate.c                  |   2 +
>  xen/arch/x86/x86_emulate/inat.c             |  98 +++
>  xen/arch/x86/x86_emulate/insn.c             | 624 ++++++++++++++++++
>  xen/arch/x86/x86_emulate/x86-opcode-map.txt | 961 ++++++++++++++++++++++++++++
>  xen/include/asm-x86/inat.h                  | 219 +++++++
>  xen/include/asm-x86/inat_types.h            |  29 +
>  xen/include/asm-x86/insn.h                  | 201 ++++++
>  xen/tools/gen-insn-attr-x86.awk             | 386 +++++++++++
>  9 files changed, 2529 insertions(+), 2 deletions(-)
>  create mode 100644 xen/arch/x86/x86_emulate/inat.c
>  create mode 100644 xen/arch/x86/x86_emulate/insn.c
>  create mode 100644 xen/arch/x86/x86_emulate/x86-opcode-map.txt
>  create mode 100644 xen/include/asm-x86/inat.h
>  create mode 100644 xen/include/asm-x86/inat_types.h
>  create mode 100644 xen/include/asm-x86/insn.h
>  create mode 100644 xen/tools/gen-insn-attr-x86.awk
> 
> diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
> index c1e244d..63529d3 100644
> --- a/xen/arch/x86/Makefile
> +++ b/xen/arch/x86/Makefile
> @@ -62,7 +62,11 @@ obj-y += xstate.o
>  
>  obj-$(crash_debug) += gdbstub.o
>  
> -x86_emulate.o: x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h
> +inat_tables_script = $(BASEDIR)/tools/gen-insn-attr-x86.awk
> +inat_tables_maps = $(BASEDIR)/arch/x86/x86_emulate/x86-opcode-map.txt
> +
> +x86_emulate.o: x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h \
> +	x86_emulate/inat.c x86_emulate/insn.c x86_emulate/inat-tables.c
>  
>  efi-$(x86_64) := $(shell if [ ! -r $(BASEDIR)/include/xen/compile.h -o \
>                                  -O $(BASEDIR)/include/xen/compile.h ]; then \
> @@ -165,9 +169,12 @@ boot/mkelf32: boot/mkelf32.c
>  efi/mkreloc: efi/mkreloc.c
>  	$(HOSTCC) $(HOSTCFLAGS) -g -o $@ $<
>  
> +x86_emulate/inat-tables.c: $(inat_tables_script) $(inat_tables_maps)
> +	awk -f $(inat_tables_script) $(inat_tables_maps) > $@ || rm -f $@
> +
>  .PHONY: clean
>  clean::
>  	rm -f asm-offsets.s *.lds boot/*.o boot/*~ boot/core boot/mkelf32
>  	rm -f $(BASEDIR)/.xen-syms.[0-9]* boot/.*.d
>  	rm -f $(BASEDIR)/.xen.efi.[0-9]* efi/*.o efi/.*.d efi/*.efi efi/disabled efi/mkreloc
> -	rm -f boot/reloc.S boot/reloc.lnk boot/reloc.bin
> +	rm -f boot/reloc.S boot/reloc.lnk boot/reloc.bin x86_emulate/inat-tables.c
> diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c
> index 79b4ab3..1d43bb1 100644
> --- a/xen/arch/x86/x86_emulate.c
> +++ b/xen/arch/x86/x86_emulate.c
> @@ -22,3 +22,5 @@
>          cpu_has_amd_erratum(&current_cpu_data, AMD_ERRATUM_##nr)
>  
>  #include "x86_emulate/x86_emulate.c"
> +#include "x86_emulate/inat.c"
> +#include "x86_emulate/insn.c"
> diff --git a/xen/arch/x86/x86_emulate/inat.c b/xen/arch/x86/x86_emulate/inat.c
> new file mode 100644
> index 0000000..e4251ba
> --- /dev/null
> +++ b/xen/arch/x86/x86_emulate/inat.c
> @@ -0,0 +1,98 @@
> +/*
> + * x86 instruction attribute tables
> + *
> + * Written by Masami Hiramatsu <mhiramat@redhat.com>
> + *
> + * 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, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + *
> + */
> +#include <asm/insn.h>
> +
> +/* Attribute tables are generated from opcode map */
> +#include "inat-tables.c"
> +
> +/* Attribute search APIs */
> +insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode)
> +{
> +    return inat_primary_table[opcode];
> +}
> +
> +int inat_get_last_prefix_id(insn_byte_t last_pfx)
> +{
> +    insn_attr_t lpfx_attr;
> +
> +    lpfx_attr = inat_get_opcode_attribute(last_pfx);
> +    return inat_last_prefix_id(lpfx_attr);
> +}
> +
> +insn_attr_t inat_get_escape_attribute(insn_byte_t opcode, int lpfx_id,
> +                                      insn_attr_t esc_attr)
> +{
> +    const insn_attr_t *table;
> +    int n;
> +
> +    n = inat_escape_id(esc_attr);
> +
> +    table = inat_escape_tables[n][0];
> +    if ( !table )
> +        return 0;
> +    if ( inat_has_variant(table[opcode]) && lpfx_id )
> +    {
> +        table = inat_escape_tables[n][lpfx_id];
> +        if ( !table )
> +            return 0;
> +    }
> +    return table[opcode];
> +}
> +
> +insn_attr_t inat_get_group_attribute(insn_byte_t modrm, int lpfx_id,
> +                                     insn_attr_t grp_attr)
> +{
> +    const insn_attr_t *table;
> +    int n;
> +
> +    n = inat_group_id(grp_attr);
> +
> +    table = inat_group_tables[n][0];
> +    if ( !table )
> +        return inat_group_common_attribute(grp_attr);
> +    if ( inat_has_variant(table[X86_MODRM_REG(modrm)]) && lpfx_id )
> +    {
> +        table = inat_group_tables[n][lpfx_id];
> +        if ( !table )
> +            return inat_group_common_attribute(grp_attr);
> +    }
> +    return table[X86_MODRM_REG(modrm)] | inat_group_common_attribute(grp_attr);
> +}
> +
> +insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, insn_byte_t vex_m,
> +                                   insn_byte_t vex_p)
> +{
> +    const insn_attr_t *table;
> +    if ( vex_m > X86_VEX_M_MAX || vex_p > INAT_LSTPFX_MAX )
> +        return 0;
> +    /* At first, this checks the master table */
> +    table = inat_avx_tables[vex_m][0];
> +    if ( !table )
> +        return 0;
> +    if ( !inat_is_group(table[opcode]) && vex_p )
> +    {
> +        /* If this is not a group, get attribute directly */
> +        table = inat_avx_tables[vex_m][vex_p];
> +        if ( !table )
> +            return 0;
> +    }
> +    return table[opcode];
> +}
> diff --git a/xen/arch/x86/x86_emulate/insn.c b/xen/arch/x86/x86_emulate/insn.c
> new file mode 100644
> index 0000000..4d7416e
> --- /dev/null
> +++ b/xen/arch/x86/x86_emulate/insn.c
> @@ -0,0 +1,624 @@
> +/*
> + * x86 instruction analysis
> + *
> + * 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, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + *
> + * Copyright (C) IBM Corporation, 2002, 2004, 2009
> + */
> +
> +#include <xen/string.h>
> +#include <asm/inat.h>
> +#include <asm/insn.h>
> +
> +/* Verify next sizeof(t) bytes can be on the same instruction */
> +#define validate_next(t, insn, n) \
> +    ((insn)->next_byte + sizeof(t) + n - (insn)->kaddr <= MAX_INSN_SIZE)
> +
> +#define __get_next(t, insn)           \
> +    (                                 \
> +        {                             \
> +        t r = *(t *)insn->next_byte;  \
> +        insn->next_byte += sizeof(t); \
> +        r;                            \
> +        })
> +
> +#define __peek_nbyte_next(t, insn, n)        \
> +    (                                        \
> +        {                                    \
> +        t r = *(t *)((insn)->next_byte + n); \
> +        r;                                   \
> +        })
> +
> +#define get_next(t, insn)                         \
> +    (                                             \
> +        {                                         \
> +        if ( unlikely(!validate_next(t, insn, 0)) ) \
> +            goto err_out;                         \
> +        __get_next(t, insn);                      \
> +        })
> +
> +#define peek_nbyte_next(t, insn, n)               \
> +    (                                             \
> +        {                                         \
> +        if ( unlikely(!validate_next(t, insn, n)) ) \
> +            goto err_out;                         \
> +        __peek_nbyte_next(t, insn, n);            \
> +        })
> +
> +#define peek_next(t, insn) peek_nbyte_next(t, insn, 0)
> +
> +/**
> + * insn_init() - initialize struct insn
> + * @insn:	&struct insn to be initialized
> + * @kaddr:	address (in kernel memory) of instruction (or copy thereof)
> + * @x86_64:	!0 for 64-bit kernel or 64-bit app
> + */
> +void insn_init(struct insn *insn, const void *kaddr, int x86_64)
> +{
> +    memset(insn, 0, sizeof(*insn));
> +    insn->kaddr = kaddr;
> +    insn->next_byte = kaddr;
> +    insn->x86_64 = x86_64 ? 1 : 0;
> +    insn->opnd_bytes = 4;
> +    if ( x86_64 )
> +        insn->addr_bytes = 8;
> +    else
> +        insn->addr_bytes = 4;
> +}
> +
> +/**
> + * insn_get_prefixes - scan x86 instruction prefix bytes
> + * @insn:	&struct insn containing instruction
> + *
> + * Populates the @insn->prefixes bitmap, and updates @insn->next_byte
> + * to point to the (first) opcode.  No effect if @insn->prefixes.got
> + * is already set.
> + */
> +void insn_get_prefixes(struct insn *insn)
> +{
> +    struct insn_field *prefixes = &insn->prefixes;
> +    insn_attr_t attr;
> +    insn_byte_t b, lb;
> +    int i, nb;
> +
> +    if ( prefixes->got )
> +        return;
> +
> +    nb = 0;
> +    lb = 0;
> +    b = peek_next(insn_byte_t, insn);
> +    attr = inat_get_opcode_attribute(b);
> +    while ( inat_is_legacy_prefix(attr) )
> +    {
> +        /* Skip if same prefix */
> +        for (i = 0; i < nb; i++)
> +            if ( prefixes->bytes[i] == b )
> +                goto found;
> +        if ( nb == 4 )
> +            /* Invalid instruction */
> +            break;
> +        prefixes->bytes[nb++] = b;
> +        if ( inat_is_address_size_prefix(attr) )
> +        {
> +            /* address size switches 2/4 or 4/8 */
> +            if ( insn->x86_64 )
> +                insn->addr_bytes ^= 12;
> +            else
> +                insn->addr_bytes ^= 6;
> +        }
> +        else if ( inat_is_operand_size_prefix(attr) )
> +        {
> +            /* oprand size switches 2/4 */
> +            insn->opnd_bytes ^= 6;
> +        }
> +    found:
> +        prefixes->nbytes++;
> +        insn->next_byte++;
> +        lb = b;
> +        b = peek_next(insn_byte_t, insn);
> +        attr = inat_get_opcode_attribute(b);
> +    }
> +    /* Set the last prefix */
> +    if ( lb && lb != insn->prefixes.bytes[3] )
> +    {
> +        if ( unlikely(insn->prefixes.bytes[3]) )
> +        {
> +            /* Swap the last prefix */
> +            b = insn->prefixes.bytes[3];
> +            for (i = 0; i < nb; i++)
> +                if ( prefixes->bytes[i] == lb )
> +                    prefixes->bytes[i] = b;
> +        }
> +        insn->prefixes.bytes[3] = lb;
> +    }
> +
> +    /* Decode REX prefix */
> +    if ( insn->x86_64 )
> +    {
> +        b = peek_next(insn_byte_t, insn);
> +        attr = inat_get_opcode_attribute(b);
> +        if ( inat_is_rex_prefix(attr) )
> +        {
> +            insn->rex_prefix.value = b;
> +            insn->rex_prefix.nbytes = 1;
> +            insn->next_byte++;
> +            if ( X86_REX_W(b) )
> +                /* REX.W overrides opnd_size */
> +                insn->opnd_bytes = 8;
> +        }
> +    }
> +    insn->rex_prefix.got = 1;
> +
> +    /* Decode VEX prefix */
> +    b = peek_next(insn_byte_t, insn);
> +    attr = inat_get_opcode_attribute(b);
> +    if ( inat_is_vex_prefix(attr) )
> +    {
> +        insn_byte_t b2 = peek_nbyte_next(insn_byte_t, insn, 1);
> +        if ( !insn->x86_64 )
> +        {
> +            /*
> +             * In 32-bits mode, if the [7:6] bits (mod bits of
> +             * ModRM) on the second byte are not 11b, it is
> +             * LDS or LES.
> +             */
> +            if ( X86_MODRM_MOD(b2) != 3 )
> +                goto vex_end;
> +        }
> +        insn->vex_prefix.bytes[0] = b;
> +        insn->vex_prefix.bytes[1] = b2;
> +        if ( inat_is_vex3_prefix(attr) )
> +        {
> +            b2 = peek_nbyte_next(insn_byte_t, insn, 2);
> +            insn->vex_prefix.bytes[2] = b2;
> +            insn->vex_prefix.nbytes = 3;
> +            insn->next_byte += 3;
> +            if ( insn->x86_64 && X86_VEX_W(b2) )
> +                /* VEX.W overrides opnd_size */
> +                insn->opnd_bytes = 8;
> +        }
> +        else
> +        {
> +            insn->vex_prefix.nbytes = 2;
> +            insn->next_byte += 2;
> +        }
> +    }
> +vex_end:
> +    insn->vex_prefix.got = 1;
> +
> +    prefixes->got = 1;
> +
> +err_out:
> +    return;
> +}
> +
> +/**
> + * insn_get_opcode - collect opcode(s)
> + * @insn:	&struct insn containing instruction
> + *
> + * Populates @insn->opcode, updates @insn->next_byte to point past the
> + * opcode byte(s), and set @insn->attr (except for groups).
> + * If necessary, first collects any preceding (prefix) bytes.
> + * Sets @insn->opcode.value = opcode1.  No effect if @insn->opcode.got
> + * is already 1.
> + */
> +void insn_get_opcode(struct insn *insn)
> +{
> +    struct insn_field *opcode = &insn->opcode;
> +    insn_byte_t op;
> +    int pfx_id;
> +    if ( opcode->got )
> +        return;
> +    if ( !insn->prefixes.got )
> +        insn_get_prefixes(insn);
> +
> +    /* Get first opcode */
> +    op = get_next(insn_byte_t, insn);
> +    opcode->bytes[0] = op;
> +    opcode->nbytes = 1;
> +
> +    /* Check if there is VEX prefix or not */
> +    if ( insn_is_avx(insn) )
> +    {
> +        insn_byte_t m, p;
> +        m = insn_vex_m_bits(insn);
> +        p = insn_vex_p_bits(insn);
> +        insn->attr = inat_get_avx_attribute(op, m, p);
> +        if ( !inat_accept_vex(insn->attr) && !inat_is_group(insn->attr) )
> +            insn->attr = 0; /* This instruction is bad */
> +        goto end;           /* VEX has only 1 byte for opcode */
> +    }
> +
> +    insn->attr = inat_get_opcode_attribute(op);
> +    while ( inat_is_escape(insn->attr) )
> +    {
> +        /* Get escaped opcode */
> +        op = get_next(insn_byte_t, insn);
> +        opcode->bytes[opcode->nbytes++] = op;
> +        pfx_id = insn_last_prefix_id(insn);
> +        insn->attr = inat_get_escape_attribute(op, pfx_id, insn->attr);
> +    }
> +    if ( inat_must_vex(insn->attr) )
> +        insn->attr = 0; /* This instruction is bad */
> +end:
> +    opcode->got = 1;
> +
> +err_out:
> +    return;
> +}
> +
> +/**
> + * insn_get_modrm - collect ModRM byte, if any
> + * @insn:	&struct insn containing instruction
> + *
> + * Populates @insn->modrm and updates @insn->next_byte to point past the
> + * ModRM byte, if any.  If necessary, first collects the preceding bytes
> + * (prefixes and opcode(s)).  No effect if @insn->modrm.got is already 1.
> + */
> +void insn_get_modrm(struct insn *insn)
> +{
> +    struct insn_field *modrm = &insn->modrm;
> +    insn_byte_t pfx_id, mod;
> +    if ( modrm->got )
> +        return;
> +    if ( !insn->opcode.got )
> +        insn_get_opcode(insn);
> +
> +    if ( inat_has_modrm(insn->attr) )
> +    {
> +        mod = get_next(insn_byte_t, insn);
> +        modrm->value = mod;
> +        modrm->nbytes = 1;
> +        if ( inat_is_group(insn->attr) )
> +        {
> +            pfx_id = insn_last_prefix_id(insn);
> +            insn->attr = inat_get_group_attribute(mod, pfx_id, insn->attr);
> +            if ( insn_is_avx(insn) && !inat_accept_vex(insn->attr) )
> +                insn->attr = 0; /* This is bad */
> +        }
> +    }
> +
> +    if ( insn->x86_64 && inat_is_force64(insn->attr) )
> +        insn->opnd_bytes = 8;
> +    modrm->got = 1;
> +
> +err_out:
> +    return;
> +}
> +
> +/**
> + * insn_rip_relative() - Does instruction use RIP-relative addressing mode?
> + * @insn:	&struct insn containing instruction
> + *
> + * If necessary, first collects the instruction up to and including the
> + * ModRM byte.  No effect if @insn->x86_64 is 0.
> + */
> +int insn_rip_relative(struct insn *insn)
> +{
> +    struct insn_field *modrm = &insn->modrm;
> +
> +    if ( !insn->x86_64 )
> +        return 0;
> +    if ( !modrm->got )
> +        insn_get_modrm(insn);
> +    /*
> +     * For rip-relative instructions, the mod field (top 2 bits)
> +     * is zero and the r/m field (bottom 3 bits) is 0x5.
> +     */
> +    return (modrm->nbytes && (modrm->value & 0xc7) == 0x5);
> +}
> +
> +/**
> + * insn_get_sib() - Get the SIB byte of instruction
> + * @insn:	&struct insn containing instruction
> + *
> + * If necessary, first collects the instruction up to and including the
> + * ModRM byte.
> + */
> +void insn_get_sib(struct insn *insn)
> +{
> +    insn_byte_t modrm;
> +
> +    if ( insn->sib.got )
> +        return;
> +    if ( !insn->modrm.got )
> +        insn_get_modrm(insn);
> +    if ( insn->modrm.nbytes )
> +    {
> +        modrm = (insn_byte_t)insn->modrm.value;
> +        if ( insn->addr_bytes != 2 && X86_MODRM_MOD(modrm ) != 3 &&
> +            X86_MODRM_RM(modrm) == 4)
> +        {
> +            insn->sib.value = get_next(insn_byte_t, insn);
> +            insn->sib.nbytes = 1;
> +        }
> +    }
> +    insn->sib.got = 1;
> +
> +err_out:
> +    return;
> +}
> +
> +/**
> + * insn_get_displacement() - Get the displacement of instruction
> + * @insn:	&struct insn containing instruction
> + *
> + * If necessary, first collects the instruction up to and including the
> + * SIB byte.
> + * Displacement value is sign-expanded.
> + */
> +void insn_get_displacement(struct insn *insn)
> +{
> +    insn_byte_t mod, rm, base;
> +
> +    if ( insn->displacement.got )
> +        return;
> +    if ( !insn->sib.got )
> +        insn_get_sib(insn);
> +    if ( insn->modrm.nbytes )
> +    {
> +        /*
> +         * Interpreting the modrm byte:
> +         * mod = 00 - no displacement fields (exceptions below)
> +         * mod = 01 - 1-byte displacement field
> +         * mod = 10 - displacement field is 4 bytes, or 2 bytes if
> +         * 	address size = 2 (0x67 prefix in 32-bit mode)
> +         * mod = 11 - no memory operand
> +         *
> +         * If address size = 2...
> +         * mod = 00, r/m = 110 - displacement field is 2 bytes
> +         *
> +         * If address size != 2...
> +         * mod != 11, r/m = 100 - SIB byte exists
> +         * mod = 00, SIB base = 101 - displacement field is 4 bytes
> +         * mod = 00, r/m = 101 - rip-relative addressing, displacement
> +         * 	field is 4 bytes
> +         */
> +        mod = X86_MODRM_MOD(insn->modrm.value);
> +        rm = X86_MODRM_RM(insn->modrm.value);
> +        base = X86_SIB_BASE(insn->sib.value);
> +        if ( mod == 3 )
> +            goto out;
> +        if ( mod == 1 )
> +        {
> +            insn->displacement.value = get_next(char, insn);
> +            insn->displacement.nbytes = 1;
> +        }
> +        else if ( insn->addr_bytes == 2 )
> +        {
> +            if ( (mod == 0 && rm == 6) || mod == 2 )
> +            {
> +                insn->displacement.value = get_next(short, insn);
> +                insn->displacement.nbytes = 2;
> +            }
> +        }
> +        else
> +        {
> +            if ( (mod == 0 && rm == 5) || mod == 2 || (mod == 0 && base == 5) )
> +            {
> +                insn->displacement.value = get_next(int, insn);
> +                insn->displacement.nbytes = 4;
> +            }
> +        }
> +    }
> +out:
> +    insn->displacement.got = 1;
> +
> +err_out:
> +    return;
> +}
> +
> +/* Decode moffset16/32/64. Return 0 if failed */
> +static int __get_moffset(struct insn *insn)
> +{
> +    switch ( insn->addr_bytes )
> +    {
> +    case 2:
> +        insn->moffset1.value = get_next(short, insn);
> +        insn->moffset1.nbytes = 2;
> +        break;
> +    case 4:
> +        insn->moffset1.value = get_next(int, insn);
> +        insn->moffset1.nbytes = 4;
> +        break;
> +    case 8:
> +        insn->moffset1.value = get_next(int, insn);
> +        insn->moffset1.nbytes = 4;
> +        insn->moffset2.value = get_next(int, insn);
> +        insn->moffset2.nbytes = 4;
> +        break;
> +    default: /* opnd_bytes must be modified manually */
> +        goto err_out;
> +    }
> +    insn->moffset1.got = insn->moffset2.got = 1;
> +
> +    return 1;
> +
> +err_out:
> +    return 0;
> +}
> +
> +/* Decode imm v32(Iz). Return 0 if failed */
> +static int __get_immv32(struct insn *insn)
> +{
> +    switch ( insn->opnd_bytes )
> +    {
> +    case 2:
> +        insn->immediate.value = get_next(short, insn);
> +        insn->immediate.nbytes = 2;
> +        break;
> +    case 4:
> +    case 8:
> +        insn->immediate.value = get_next(int, insn);
> +        insn->immediate.nbytes = 4;
> +        break;
> +    default: /* opnd_bytes must be modified manually */
> +        goto err_out;
> +    }
> +
> +    return 1;
> +
> +err_out:
> +    return 0;
> +}
> +
> +/* Decode imm v64(Iv/Ov), Return 0 if failed */
> +static int __get_immv(struct insn *insn)
> +{
> +    switch ( insn->opnd_bytes )
> +    {
> +    case 2:
> +        insn->immediate1.value = get_next(short, insn);
> +        insn->immediate1.nbytes = 2;
> +        break;
> +    case 4:
> +        insn->immediate1.value = get_next(int, insn);
> +        insn->immediate1.nbytes = 4;
> +        break;
> +    case 8:
> +        insn->immediate1.value = get_next(int, insn);
> +        insn->immediate1.nbytes = 4;
> +        insn->immediate2.value = get_next(int, insn);
> +        insn->immediate2.nbytes = 4;
> +        break;
> +    default: /* opnd_bytes must be modified manually */
> +        goto err_out;
> +    }
> +    insn->immediate1.got = insn->immediate2.got = 1;
> +
> +    return 1;
> +err_out:
> +    return 0;
> +}
> +
> +/* Decode ptr16:16/32(Ap) */
> +static int __get_immptr(struct insn *insn)
> +{
> +    switch ( insn->opnd_bytes )
> +    {
> +    case 2:
> +        insn->immediate1.value = get_next(short, insn);
> +        insn->immediate1.nbytes = 2;
> +        break;
> +    case 4:
> +        insn->immediate1.value = get_next(int, insn);
> +        insn->immediate1.nbytes = 4;
> +        break;
> +    case 8:
> +        /* ptr16:64 is not exist (no segment) */
> +        return 0;
> +    default: /* opnd_bytes must be modified manually */
> +        goto err_out;
> +    }
> +    insn->immediate2.value = get_next(unsigned short, insn);
> +    insn->immediate2.nbytes = 2;
> +    insn->immediate1.got = insn->immediate2.got = 1;
> +
> +    return 1;
> +err_out:
> +    return 0;
> +}
> +
> +/**
> + * insn_get_immediate() - Get the immediates of instruction
> + * @insn:	&struct insn containing instruction
> + *
> + * If necessary, first collects the instruction up to and including the
> + * displacement bytes.
> + * Basically, most of immediates are sign-expanded. Unsigned-value can be
> + * get by bit masking with ((1 << (nbytes * 8)) - 1)
> + */
> +void insn_get_immediate(struct insn *insn)
> +{
> +    if ( insn->immediate.got )
> +        return;
> +    if ( !insn->displacement.got )
> +        insn_get_displacement(insn);
> +
> +    if ( inat_has_moffset(insn->attr) )
> +    {
> +        if ( !__get_moffset(insn) )
> +            goto err_out;
> +        goto done;
> +    }
> +
> +    if ( !inat_has_immediate(insn->attr) )
> +        /* no immediates */
> +        goto done;
> +
> +    switch ( inat_immediate_size(insn->attr) )
> +    {
> +    case INAT_IMM_BYTE:
> +        insn->immediate.value = get_next(char, insn);
> +        insn->immediate.nbytes = 1;
> +        break;
> +    case INAT_IMM_WORD:
> +        insn->immediate.value = get_next(short, insn);
> +        insn->immediate.nbytes = 2;
> +        break;
> +    case INAT_IMM_DWORD:
> +        insn->immediate.value = get_next(int, insn);
> +        insn->immediate.nbytes = 4;
> +        break;
> +    case INAT_IMM_QWORD:
> +        insn->immediate1.value = get_next(int, insn);
> +        insn->immediate1.nbytes = 4;
> +        insn->immediate2.value = get_next(int, insn);
> +        insn->immediate2.nbytes = 4;
> +        break;
> +    case INAT_IMM_PTR:
> +        if ( !__get_immptr(insn) )
> +            goto err_out;
> +        break;
> +    case INAT_IMM_VWORD32:
> +        if ( !__get_immv32(insn) )
> +            goto err_out;
> +        break;
> +    case INAT_IMM_VWORD:
> +        if ( !__get_immv(insn) )
> +            goto err_out;
> +        break;
> +    default:
> +        /* Here, insn must have an immediate, but failed */
> +        goto err_out;
> +    }
> +    if ( inat_has_second_immediate(insn->attr) )
> +    {
> +        insn->immediate2.value = get_next(char, insn);
> +        insn->immediate2.nbytes = 1;
> +    }
> +done:
> +    insn->immediate.got = 1;
> +
> +err_out:
> +    return;
> +}
> +
> +/**
> + * insn_get_length() - Get the length of instruction
> + * @insn:	&struct insn containing instruction
> + *
> + * If necessary, first collects the instruction up to and including the
> + * immediates bytes.
> + */
> +void insn_get_length(struct insn *insn)
> +{
> +    if ( insn->length )
> +        return;
> +    if ( !insn->immediate.got )
> +        insn_get_immediate(insn);
> +    insn->length = (unsigned char)((unsigned long)insn->next_byte -
> +                                   (unsigned long)insn->kaddr);
> +}
> diff --git a/xen/arch/x86/x86_emulate/x86-opcode-map.txt b/xen/arch/x86/x86_emulate/x86-opcode-map.txt
> new file mode 100644
> index 0000000..1a2be7c
> --- /dev/null
> +++ b/xen/arch/x86/x86_emulate/x86-opcode-map.txt
> @@ -0,0 +1,961 @@
> +# x86 Opcode Maps
> +#
> +# This is (mostly) based on following documentations.
> +# - Intel(R) 64 and IA-32 Architectures Software Developer's Manual Vol.2C
> +#   (#326018-047US, June 2013)
> +#
> +#<Opcode maps>
> +# Table: table-name
> +# Referrer: escaped-name
> +# AVXcode: avx-code
> +# opcode: mnemonic|GrpXXX [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...]
> +# (or)
> +# opcode: escape # escaped-name
> +# EndTable
> +#
> +#<group maps>
> +# GrpTable: GrpXXX
> +# reg:  mnemonic [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...]
> +# EndTable
> +#
> +# AVX Superscripts
> +#  (v): this opcode requires VEX prefix.
> +#  (v1): this opcode only supports 128bit VEX.
> +#
> +# Last Prefix Superscripts
> +#  - (66): the last prefix is 0x66
> +#  - (F3): the last prefix is 0xF3
> +#  - (F2): the last prefix is 0xF2
> +#  - (!F3) : the last prefix is not 0xF3 (including non-last prefix case)
> +#  - (66&F2): Both 0x66 and 0xF2 prefixes are specified.
> +
> +Table: one byte opcode
> +Referrer:
> +AVXcode:
> +# 0x00 - 0x0f
> +00: ADD Eb,Gb
> +01: ADD Ev,Gv
> +02: ADD Gb,Eb
> +03: ADD Gv,Ev
> +04: ADD AL,Ib
> +05: ADD rAX,Iz
> +06: PUSH ES (i64)
> +07: POP ES (i64)
> +08: OR Eb,Gb
> +09: OR Ev,Gv
> +0a: OR Gb,Eb
> +0b: OR Gv,Ev
> +0c: OR AL,Ib
> +0d: OR rAX,Iz
> +0e: PUSH CS (i64)
> +0f: escape # 2-byte escape
> +# 0x10 - 0x1f
> +10: ADC Eb,Gb
> +11: ADC Ev,Gv
> +12: ADC Gb,Eb
> +13: ADC Gv,Ev
> +14: ADC AL,Ib
> +15: ADC rAX,Iz
> +16: PUSH SS (i64)
> +17: POP SS (i64)
> +18: SBB Eb,Gb
> +19: SBB Ev,Gv
> +1a: SBB Gb,Eb
> +1b: SBB Gv,Ev
> +1c: SBB AL,Ib
> +1d: SBB rAX,Iz
> +1e: PUSH DS (i64)
> +1f: POP DS (i64)
> +# 0x20 - 0x2f
> +20: AND Eb,Gb
> +21: AND Ev,Gv
> +22: AND Gb,Eb
> +23: AND Gv,Ev
> +24: AND AL,Ib
> +25: AND rAx,Iz
> +26: SEG=ES (Prefix)
> +27: DAA (i64)
> +28: SUB Eb,Gb
> +29: SUB Ev,Gv
> +2a: SUB Gb,Eb
> +2b: SUB Gv,Ev
> +2c: SUB AL,Ib
> +2d: SUB rAX,Iz
> +2e: SEG=CS (Prefix)
> +2f: DAS (i64)
> +# 0x30 - 0x3f
> +30: XOR Eb,Gb
> +31: XOR Ev,Gv
> +32: XOR Gb,Eb
> +33: XOR Gv,Ev
> +34: XOR AL,Ib
> +35: XOR rAX,Iz
> +36: SEG=SS (Prefix)
> +37: AAA (i64)
> +38: CMP Eb,Gb
> +39: CMP Ev,Gv
> +3a: CMP Gb,Eb
> +3b: CMP Gv,Ev
> +3c: CMP AL,Ib
> +3d: CMP rAX,Iz
> +3e: SEG=DS (Prefix)
> +3f: AAS (i64)
> +# 0x40 - 0x4f
> +40: INC eAX (i64) | REX (o64)
> +41: INC eCX (i64) | REX.B (o64)
> +42: INC eDX (i64) | REX.X (o64)
> +43: INC eBX (i64) | REX.XB (o64)
> +44: INC eSP (i64) | REX.R (o64)
> +45: INC eBP (i64) | REX.RB (o64)
> +46: INC eSI (i64) | REX.RX (o64)
> +47: INC eDI (i64) | REX.RXB (o64)
> +48: DEC eAX (i64) | REX.W (o64)
> +49: DEC eCX (i64) | REX.WB (o64)
> +4a: DEC eDX (i64) | REX.WX (o64)
> +4b: DEC eBX (i64) | REX.WXB (o64)
> +4c: DEC eSP (i64) | REX.WR (o64)
> +4d: DEC eBP (i64) | REX.WRB (o64)
> +4e: DEC eSI (i64) | REX.WRX (o64)
> +4f: DEC eDI (i64) | REX.WRXB (o64)
> +# 0x50 - 0x5f
> +50: PUSH rAX/r8 (d64)
> +51: PUSH rCX/r9 (d64)
> +52: PUSH rDX/r10 (d64)
> +53: PUSH rBX/r11 (d64)
> +54: PUSH rSP/r12 (d64)
> +55: PUSH rBP/r13 (d64)
> +56: PUSH rSI/r14 (d64)
> +57: PUSH rDI/r15 (d64)
> +58: POP rAX/r8 (d64)
> +59: POP rCX/r9 (d64)
> +5a: POP rDX/r10 (d64)
> +5b: POP rBX/r11 (d64)
> +5c: POP rSP/r12 (d64)
> +5d: POP rBP/r13 (d64)
> +5e: POP rSI/r14 (d64)
> +5f: POP rDI/r15 (d64)
> +# 0x60 - 0x6f
> +60: PUSHA/PUSHAD (i64)
> +61: POPA/POPAD (i64)
> +62: BOUND Gv,Ma (i64)
> +63: ARPL Ew,Gw (i64) | MOVSXD Gv,Ev (o64)
> +64: SEG=FS (Prefix)
> +65: SEG=GS (Prefix)
> +66: Operand-Size (Prefix)
> +67: Address-Size (Prefix)
> +68: PUSH Iz (d64)
> +69: IMUL Gv,Ev,Iz
> +6a: PUSH Ib (d64)
> +6b: IMUL Gv,Ev,Ib
> +6c: INS/INSB Yb,DX
> +6d: INS/INSW/INSD Yz,DX
> +6e: OUTS/OUTSB DX,Xb
> +6f: OUTS/OUTSW/OUTSD DX,Xz
> +# 0x70 - 0x7f
> +70: JO Jb
> +71: JNO Jb
> +72: JB/JNAE/JC Jb
> +73: JNB/JAE/JNC Jb
> +74: JZ/JE Jb
> +75: JNZ/JNE Jb
> +76: JBE/JNA Jb
> +77: JNBE/JA Jb
> +78: JS Jb
> +79: JNS Jb
> +7a: JP/JPE Jb
> +7b: JNP/JPO Jb
> +7c: JL/JNGE Jb
> +7d: JNL/JGE Jb
> +7e: JLE/JNG Jb
> +7f: JNLE/JG Jb
> +# 0x80 - 0x8f
> +80: Grp1 Eb,Ib (1A)
> +81: Grp1 Ev,Iz (1A)
> +82: Grp1 Eb,Ib (1A),(i64)
> +83: Grp1 Ev,Ib (1A)
> +84: TEST Eb,Gb
> +85: TEST Ev,Gv
> +86: XCHG Eb,Gb
> +87: XCHG Ev,Gv
> +88: MOV Eb,Gb
> +89: MOV Ev,Gv
> +8a: MOV Gb,Eb
> +8b: MOV Gv,Ev
> +8c: MOV Ev,Sw
> +8d: LEA Gv,M
> +8e: MOV Sw,Ew
> +8f: Grp1A (1A) | POP Ev (d64)
> +# 0x90 - 0x9f
> +90: NOP | PAUSE (F3) | XCHG r8,rAX
> +91: XCHG rCX/r9,rAX
> +92: XCHG rDX/r10,rAX
> +93: XCHG rBX/r11,rAX
> +94: XCHG rSP/r12,rAX
> +95: XCHG rBP/r13,rAX
> +96: XCHG rSI/r14,rAX
> +97: XCHG rDI/r15,rAX
> +98: CBW/CWDE/CDQE
> +99: CWD/CDQ/CQO
> +9a: CALLF Ap (i64)
> +9b: FWAIT/WAIT
> +9c: PUSHF/D/Q Fv (d64)
> +9d: POPF/D/Q Fv (d64)
> +9e: SAHF
> +9f: LAHF
> +# 0xa0 - 0xaf
> +a0: MOV AL,Ob
> +a1: MOV rAX,Ov
> +a2: MOV Ob,AL
> +a3: MOV Ov,rAX
> +a4: MOVS/B Yb,Xb
> +a5: MOVS/W/D/Q Yv,Xv
> +a6: CMPS/B Xb,Yb
> +a7: CMPS/W/D Xv,Yv
> +a8: TEST AL,Ib
> +a9: TEST rAX,Iz
> +aa: STOS/B Yb,AL
> +ab: STOS/W/D/Q Yv,rAX
> +ac: LODS/B AL,Xb
> +ad: LODS/W/D/Q rAX,Xv
> +ae: SCAS/B AL,Yb
> +# Note: The May 2011 Intel manual shows Xv for the second parameter of the
> +# next instruction but Yv is correct
> +af: SCAS/W/D/Q rAX,Yv
> +# 0xb0 - 0xbf
> +b0: MOV AL/R8L,Ib
> +b1: MOV CL/R9L,Ib
> +b2: MOV DL/R10L,Ib
> +b3: MOV BL/R11L,Ib
> +b4: MOV AH/R12L,Ib
> +b5: MOV CH/R13L,Ib
> +b6: MOV DH/R14L,Ib
> +b7: MOV BH/R15L,Ib
> +b8: MOV rAX/r8,Iv
> +b9: MOV rCX/r9,Iv
> +ba: MOV rDX/r10,Iv
> +bb: MOV rBX/r11,Iv
> +bc: MOV rSP/r12,Iv
> +bd: MOV rBP/r13,Iv
> +be: MOV rSI/r14,Iv
> +bf: MOV rDI/r15,Iv
> +# 0xc0 - 0xcf
> +c0: Grp2 Eb,Ib (1A)
> +c1: Grp2 Ev,Ib (1A)
> +c2: RETN Iw (f64)
> +c3: RETN
> +c4: LES Gz,Mp (i64) | VEX+2byte (Prefix)
> +c5: LDS Gz,Mp (i64) | VEX+1byte (Prefix)
> +c6: Grp11A Eb,Ib (1A)
> +c7: Grp11B Ev,Iz (1A)
> +c8: ENTER Iw,Ib
> +c9: LEAVE (d64)
> +ca: RETF Iw
> +cb: RETF
> +cc: INT3
> +cd: INT Ib
> +ce: INTO (i64)
> +cf: IRET/D/Q
> +# 0xd0 - 0xdf
> +d0: Grp2 Eb,1 (1A)
> +d1: Grp2 Ev,1 (1A)
> +d2: Grp2 Eb,CL (1A)
> +d3: Grp2 Ev,CL (1A)
> +d4: AAM Ib (i64)
> +d5: AAD Ib (i64)
> +d6:
> +d7: XLAT/XLATB
> +d8: ESC
> +d9: ESC
> +da: ESC
> +db: ESC
> +dc: ESC
> +dd: ESC
> +de: ESC
> +df: ESC
> +# 0xe0 - 0xef
> +e0: LOOPNE/LOOPNZ Jb (f64)
> +e1: LOOPE/LOOPZ Jb (f64)
> +e2: LOOP Jb (f64)
> +e3: JrCXZ Jb (f64)
> +e4: IN AL,Ib
> +e5: IN eAX,Ib
> +e6: OUT Ib,AL
> +e7: OUT Ib,eAX
> +e8: CALL Jz (f64)
> +e9: JMP-near Jz (f64)
> +ea: JMP-far Ap (i64)
> +eb: JMP-short Jb (f64)
> +ec: IN AL,DX
> +ed: IN eAX,DX
> +ee: OUT DX,AL
> +ef: OUT DX,eAX
> +# 0xf0 - 0xff
> +f0: LOCK (Prefix)
> +f1:
> +f2: REPNE (Prefix) | XACQUIRE (Prefix)
> +f3: REP/REPE (Prefix) | XRELEASE (Prefix)
> +f4: HLT
> +f5: CMC
> +f6: Grp3_1 Eb (1A)
> +f7: Grp3_2 Ev (1A)
> +f8: CLC
> +f9: STC
> +fa: CLI
> +fb: STI
> +fc: CLD
> +fd: STD
> +fe: Grp4 (1A)
> +ff: Grp5 (1A)
> +EndTable
> +
> +Table: 2-byte opcode (0x0f)
> +Referrer: 2-byte escape
> +AVXcode: 1
> +# 0x0f 0x00-0x0f
> +00: Grp6 (1A)
> +01: Grp7 (1A)
> +02: LAR Gv,Ew
> +03: LSL Gv,Ew
> +04:
> +05: SYSCALL (o64)
> +06: CLTS
> +07: SYSRET (o64)
> +08: INVD
> +09: WBINVD
> +0a:
> +0b: UD2 (1B)
> +0c:
> +# AMD's prefetch group. Intel supports prefetchw(/1) only.
> +0d: GrpP
> +0e: FEMMS
> +# 3DNow! uses the last imm byte as opcode extension.
> +0f: 3DNow! Pq,Qq,Ib
> +# 0x0f 0x10-0x1f
> +# NOTE: According to Intel SDM opcode map, vmovups and vmovupd has no operands
> +# but it actually has operands. And also, vmovss and vmovsd only accept 128bit.
> +# MOVSS/MOVSD has too many forms(3) on SDM. This map just shows a typical form.
> +# Many AVX instructions lack v1 superscript, according to Intel AVX-Prgramming
> +# Reference A.1
> +10: vmovups Vps,Wps | vmovupd Vpd,Wpd (66) | vmovss Vx,Hx,Wss (F3),(v1) | vmovsd Vx,Hx,Wsd (F2),(v1)
> +11: vmovups Wps,Vps | vmovupd Wpd,Vpd (66) | vmovss Wss,Hx,Vss (F3),(v1) | vmovsd Wsd,Hx,Vsd (F2),(v1)
> +12: vmovlps Vq,Hq,Mq (v1) | vmovhlps Vq,Hq,Uq (v1) | vmovlpd Vq,Hq,Mq (66),(v1) | vmovsldup Vx,Wx (F3) | vmovddup Vx,Wx (F2)
> +13: vmovlps Mq,Vq (v1) | vmovlpd Mq,Vq (66),(v1)
> +14: vunpcklps Vx,Hx,Wx | vunpcklpd Vx,Hx,Wx (66)
> +15: vunpckhps Vx,Hx,Wx | vunpckhpd Vx,Hx,Wx (66)
> +16: vmovhps Vdq,Hq,Mq (v1) | vmovlhps Vdq,Hq,Uq (v1) | vmovhpd Vdq,Hq,Mq (66),(v1) | vmovshdup Vx,Wx (F3)
> +17: vmovhps Mq,Vq (v1) | vmovhpd Mq,Vq (66),(v1)
> +18: Grp16 (1A)
> +19:
> +1a: BNDCL Ev,Gv | BNDCU Ev,Gv | BNDMOV Gv,Ev | BNDLDX Gv,Ev,Gv
> +1b: BNDCN Ev,Gv | BNDMOV Ev,Gv | BNDMK Gv,Ev | BNDSTX Ev,GV,Gv
> +1c:
> +1d:
> +1e:
> +1f: NOP Ev
> +# 0x0f 0x20-0x2f
> +20: MOV Rd,Cd
> +21: MOV Rd,Dd
> +22: MOV Cd,Rd
> +23: MOV Dd,Rd
> +24:
> +25:
> +26:
> +27:
> +28: vmovaps Vps,Wps | vmovapd Vpd,Wpd (66)
> +29: vmovaps Wps,Vps | vmovapd Wpd,Vpd (66)
> +2a: cvtpi2ps Vps,Qpi | cvtpi2pd Vpd,Qpi (66) | vcvtsi2ss Vss,Hss,Ey (F3),(v1) | vcvtsi2sd Vsd,Hsd,Ey (F2),(v1)
> +2b: vmovntps Mps,Vps | vmovntpd Mpd,Vpd (66)
> +2c: cvttps2pi Ppi,Wps | cvttpd2pi Ppi,Wpd (66) | vcvttss2si Gy,Wss (F3),(v1) | vcvttsd2si Gy,Wsd (F2),(v1)
> +2d: cvtps2pi Ppi,Wps | cvtpd2pi Qpi,Wpd (66) | vcvtss2si Gy,Wss (F3),(v1) | vcvtsd2si Gy,Wsd (F2),(v1)
> +2e: vucomiss Vss,Wss (v1) | vucomisd  Vsd,Wsd (66),(v1)
> +2f: vcomiss Vss,Wss (v1) | vcomisd  Vsd,Wsd (66),(v1)
> +# 0x0f 0x30-0x3f
> +30: WRMSR
> +31: RDTSC
> +32: RDMSR
> +33: RDPMC
> +34: SYSENTER
> +35: SYSEXIT
> +36:
> +37: GETSEC
> +38: escape # 3-byte escape 1
> +39:
> +3a: escape # 3-byte escape 2
> +3b:
> +3c:
> +3d:
> +3e:
> +3f:
> +# 0x0f 0x40-0x4f
> +40: CMOVO Gv,Ev
> +41: CMOVNO Gv,Ev
> +42: CMOVB/C/NAE Gv,Ev
> +43: CMOVAE/NB/NC Gv,Ev
> +44: CMOVE/Z Gv,Ev
> +45: CMOVNE/NZ Gv,Ev
> +46: CMOVBE/NA Gv,Ev
> +47: CMOVA/NBE Gv,Ev
> +48: CMOVS Gv,Ev
> +49: CMOVNS Gv,Ev
> +4a: CMOVP/PE Gv,Ev
> +4b: CMOVNP/PO Gv,Ev
> +4c: CMOVL/NGE Gv,Ev
> +4d: CMOVNL/GE Gv,Ev
> +4e: CMOVLE/NG Gv,Ev
> +4f: CMOVNLE/G Gv,Ev
> +# 0x0f 0x50-0x5f
> +50: vmovmskps Gy,Ups | vmovmskpd Gy,Upd (66)
> +51: vsqrtps Vps,Wps | vsqrtpd Vpd,Wpd (66) | vsqrtss Vss,Hss,Wss (F3),(v1) | vsqrtsd Vsd,Hsd,Wsd (F2),(v1)
> +52: vrsqrtps Vps,Wps | vrsqrtss Vss,Hss,Wss (F3),(v1)
> +53: vrcpps Vps,Wps | vrcpss Vss,Hss,Wss (F3),(v1)
> +54: vandps Vps,Hps,Wps | vandpd Vpd,Hpd,Wpd (66)
> +55: vandnps Vps,Hps,Wps | vandnpd Vpd,Hpd,Wpd (66)
> +56: vorps Vps,Hps,Wps | vorpd Vpd,Hpd,Wpd (66)
> +57: vxorps Vps,Hps,Wps | vxorpd Vpd,Hpd,Wpd (66)
> +58: vaddps Vps,Hps,Wps | vaddpd Vpd,Hpd,Wpd (66) | vaddss Vss,Hss,Wss (F3),(v1) | vaddsd Vsd,Hsd,Wsd (F2),(v1)
> +59: vmulps Vps,Hps,Wps | vmulpd Vpd,Hpd,Wpd (66) | vmulss Vss,Hss,Wss (F3),(v1) | vmulsd Vsd,Hsd,Wsd (F2),(v1)
> +5a: vcvtps2pd Vpd,Wps | vcvtpd2ps Vps,Wpd (66) | vcvtss2sd Vsd,Hx,Wss (F3),(v1) | vcvtsd2ss Vss,Hx,Wsd (F2),(v1)
> +5b: vcvtdq2ps Vps,Wdq | vcvtps2dq Vdq,Wps (66) | vcvttps2dq Vdq,Wps (F3)
> +5c: vsubps Vps,Hps,Wps | vsubpd Vpd,Hpd,Wpd (66) | vsubss Vss,Hss,Wss (F3),(v1) | vsubsd Vsd,Hsd,Wsd (F2),(v1)
> +5d: vminps Vps,Hps,Wps | vminpd Vpd,Hpd,Wpd (66) | vminss Vss,Hss,Wss (F3),(v1) | vminsd Vsd,Hsd,Wsd (F2),(v1)
> +5e: vdivps Vps,Hps,Wps | vdivpd Vpd,Hpd,Wpd (66) | vdivss Vss,Hss,Wss (F3),(v1) | vdivsd Vsd,Hsd,Wsd (F2),(v1)
> +5f: vmaxps Vps,Hps,Wps | vmaxpd Vpd,Hpd,Wpd (66) | vmaxss Vss,Hss,Wss (F3),(v1) | vmaxsd Vsd,Hsd,Wsd (F2),(v1)
> +# 0x0f 0x60-0x6f
> +60: punpcklbw Pq,Qd | vpunpcklbw Vx,Hx,Wx (66),(v1)
> +61: punpcklwd Pq,Qd | vpunpcklwd Vx,Hx,Wx (66),(v1)
> +62: punpckldq Pq,Qd | vpunpckldq Vx,Hx,Wx (66),(v1)
> +63: packsswb Pq,Qq | vpacksswb Vx,Hx,Wx (66),(v1)
> +64: pcmpgtb Pq,Qq | vpcmpgtb Vx,Hx,Wx (66),(v1)
> +65: pcmpgtw Pq,Qq | vpcmpgtw Vx,Hx,Wx (66),(v1)
> +66: pcmpgtd Pq,Qq | vpcmpgtd Vx,Hx,Wx (66),(v1)
> +67: packuswb Pq,Qq | vpackuswb Vx,Hx,Wx (66),(v1)
> +68: punpckhbw Pq,Qd | vpunpckhbw Vx,Hx,Wx (66),(v1)
> +69: punpckhwd Pq,Qd | vpunpckhwd Vx,Hx,Wx (66),(v1)
> +6a: punpckhdq Pq,Qd | vpunpckhdq Vx,Hx,Wx (66),(v1)
> +6b: packssdw Pq,Qd | vpackssdw Vx,Hx,Wx (66),(v1)
> +6c: vpunpcklqdq Vx,Hx,Wx (66),(v1)
> +6d: vpunpckhqdq Vx,Hx,Wx (66),(v1)
> +6e: movd/q Pd,Ey | vmovd/q Vy,Ey (66),(v1)
> +6f: movq Pq,Qq | vmovdqa Vx,Wx (66) | vmovdqu Vx,Wx (F3)
> +# 0x0f 0x70-0x7f
> +70: pshufw Pq,Qq,Ib | vpshufd Vx,Wx,Ib (66),(v1) | vpshufhw Vx,Wx,Ib (F3),(v1) | vpshuflw Vx,Wx,Ib (F2),(v1)
> +71: Grp12 (1A)
> +72: Grp13 (1A)
> +73: Grp14 (1A)
> +74: pcmpeqb Pq,Qq | vpcmpeqb Vx,Hx,Wx (66),(v1)
> +75: pcmpeqw Pq,Qq | vpcmpeqw Vx,Hx,Wx (66),(v1)
> +76: pcmpeqd Pq,Qq | vpcmpeqd Vx,Hx,Wx (66),(v1)
> +# Note: Remove (v), because vzeroall and vzeroupper becomes emms without VEX.
> +77: emms | vzeroupper | vzeroall
> +78: VMREAD Ey,Gy
> +79: VMWRITE Gy,Ey
> +7a:
> +7b:
> +7c: vhaddpd Vpd,Hpd,Wpd (66) | vhaddps Vps,Hps,Wps (F2)
> +7d: vhsubpd Vpd,Hpd,Wpd (66) | vhsubps Vps,Hps,Wps (F2)
> +7e: movd/q Ey,Pd | vmovd/q Ey,Vy (66),(v1) | vmovq Vq,Wq (F3),(v1)
> +7f: movq Qq,Pq | vmovdqa Wx,Vx (66) | vmovdqu Wx,Vx (F3)
> +# 0x0f 0x80-0x8f
> +80: JO Jz (f64)
> +81: JNO Jz (f64)
> +82: JB/JC/JNAE Jz (f64)
> +83: JAE/JNB/JNC Jz (f64)
> +84: JE/JZ Jz (f64)
> +85: JNE/JNZ Jz (f64)
> +86: JBE/JNA Jz (f64)
> +87: JA/JNBE Jz (f64)
> +88: JS Jz (f64)
> +89: JNS Jz (f64)
> +8a: JP/JPE Jz (f64)
> +8b: JNP/JPO Jz (f64)
> +8c: JL/JNGE Jz (f64)
> +8d: JNL/JGE Jz (f64)
> +8e: JLE/JNG Jz (f64)
> +8f: JNLE/JG Jz (f64)
> +# 0x0f 0x90-0x9f
> +90: SETO Eb
> +91: SETNO Eb
> +92: SETB/C/NAE Eb
> +93: SETAE/NB/NC Eb
> +94: SETE/Z Eb
> +95: SETNE/NZ Eb
> +96: SETBE/NA Eb
> +97: SETA/NBE Eb
> +98: SETS Eb
> +99: SETNS Eb
> +9a: SETP/PE Eb
> +9b: SETNP/PO Eb
> +9c: SETL/NGE Eb
> +9d: SETNL/GE Eb
> +9e: SETLE/NG Eb
> +9f: SETNLE/G Eb
> +# 0x0f 0xa0-0xaf
> +a0: PUSH FS (d64)
> +a1: POP FS (d64)
> +a2: CPUID
> +a3: BT Ev,Gv
> +a4: SHLD Ev,Gv,Ib
> +a5: SHLD Ev,Gv,CL
> +a6: GrpPDLK
> +a7: GrpRNG
> +a8: PUSH GS (d64)
> +a9: POP GS (d64)
> +aa: RSM
> +ab: BTS Ev,Gv
> +ac: SHRD Ev,Gv,Ib
> +ad: SHRD Ev,Gv,CL
> +ae: Grp15 (1A),(1C)
> +af: IMUL Gv,Ev
> +# 0x0f 0xb0-0xbf
> +b0: CMPXCHG Eb,Gb
> +b1: CMPXCHG Ev,Gv
> +b2: LSS Gv,Mp
> +b3: BTR Ev,Gv
> +b4: LFS Gv,Mp
> +b5: LGS Gv,Mp
> +b6: MOVZX Gv,Eb
> +b7: MOVZX Gv,Ew
> +b8: JMPE (!F3) | POPCNT Gv,Ev (F3)
> +b9: Grp10 (1A)
> +ba: Grp8 Ev,Ib (1A)
> +bb: BTC Ev,Gv
> +bc: BSF Gv,Ev (!F3) | TZCNT Gv,Ev (F3)
> +bd: BSR Gv,Ev (!F3) | LZCNT Gv,Ev (F3)
> +be: MOVSX Gv,Eb
> +bf: MOVSX Gv,Ew
> +# 0x0f 0xc0-0xcf
> +c0: XADD Eb,Gb
> +c1: XADD Ev,Gv
> +c2: vcmpps Vps,Hps,Wps,Ib | vcmppd Vpd,Hpd,Wpd,Ib (66) | vcmpss Vss,Hss,Wss,Ib (F3),(v1) | vcmpsd Vsd,Hsd,Wsd,Ib (F2),(v1)
> +c3: movnti My,Gy
> +c4: pinsrw Pq,Ry/Mw,Ib | vpinsrw Vdq,Hdq,Ry/Mw,Ib (66),(v1)
> +c5: pextrw Gd,Nq,Ib | vpextrw Gd,Udq,Ib (66),(v1)
> +c6: vshufps Vps,Hps,Wps,Ib | vshufpd Vpd,Hpd,Wpd,Ib (66)
> +c7: Grp9 (1A)
> +c8: BSWAP RAX/EAX/R8/R8D
> +c9: BSWAP RCX/ECX/R9/R9D
> +ca: BSWAP RDX/EDX/R10/R10D
> +cb: BSWAP RBX/EBX/R11/R11D
> +cc: BSWAP RSP/ESP/R12/R12D
> +cd: BSWAP RBP/EBP/R13/R13D
> +ce: BSWAP RSI/ESI/R14/R14D
> +cf: BSWAP RDI/EDI/R15/R15D
> +# 0x0f 0xd0-0xdf
> +d0: vaddsubpd Vpd,Hpd,Wpd (66) | vaddsubps Vps,Hps,Wps (F2)
> +d1: psrlw Pq,Qq | vpsrlw Vx,Hx,Wx (66),(v1)
> +d2: psrld Pq,Qq | vpsrld Vx,Hx,Wx (66),(v1)
> +d3: psrlq Pq,Qq | vpsrlq Vx,Hx,Wx (66),(v1)
> +d4: paddq Pq,Qq | vpaddq Vx,Hx,Wx (66),(v1)
> +d5: pmullw Pq,Qq | vpmullw Vx,Hx,Wx (66),(v1)
> +d6: vmovq Wq,Vq (66),(v1) | movq2dq Vdq,Nq (F3) | movdq2q Pq,Uq (F2)
> +d7: pmovmskb Gd,Nq | vpmovmskb Gd,Ux (66),(v1)
> +d8: psubusb Pq,Qq | vpsubusb Vx,Hx,Wx (66),(v1)
> +d9: psubusw Pq,Qq | vpsubusw Vx,Hx,Wx (66),(v1)
> +da: pminub Pq,Qq | vpminub Vx,Hx,Wx (66),(v1)
> +db: pand Pq,Qq | vpand Vx,Hx,Wx (66),(v1)
> +dc: paddusb Pq,Qq | vpaddusb Vx,Hx,Wx (66),(v1)
> +dd: paddusw Pq,Qq | vpaddusw Vx,Hx,Wx (66),(v1)
> +de: pmaxub Pq,Qq | vpmaxub Vx,Hx,Wx (66),(v1)
> +df: pandn Pq,Qq | vpandn Vx,Hx,Wx (66),(v1)
> +# 0x0f 0xe0-0xef
> +e0: pavgb Pq,Qq | vpavgb Vx,Hx,Wx (66),(v1)
> +e1: psraw Pq,Qq | vpsraw Vx,Hx,Wx (66),(v1)
> +e2: psrad Pq,Qq | vpsrad Vx,Hx,Wx (66),(v1)
> +e3: pavgw Pq,Qq | vpavgw Vx,Hx,Wx (66),(v1)
> +e4: pmulhuw Pq,Qq | vpmulhuw Vx,Hx,Wx (66),(v1)
> +e5: pmulhw Pq,Qq | vpmulhw Vx,Hx,Wx (66),(v1)
> +e6: vcvttpd2dq Vx,Wpd (66) | vcvtdq2pd Vx,Wdq (F3) | vcvtpd2dq Vx,Wpd (F2)
> +e7: movntq Mq,Pq | vmovntdq Mx,Vx (66)
> +e8: psubsb Pq,Qq | vpsubsb Vx,Hx,Wx (66),(v1)
> +e9: psubsw Pq,Qq | vpsubsw Vx,Hx,Wx (66),(v1)
> +ea: pminsw Pq,Qq | vpminsw Vx,Hx,Wx (66),(v1)
> +eb: por Pq,Qq | vpor Vx,Hx,Wx (66),(v1)
> +ec: paddsb Pq,Qq | vpaddsb Vx,Hx,Wx (66),(v1)
> +ed: paddsw Pq,Qq | vpaddsw Vx,Hx,Wx (66),(v1)
> +ee: pmaxsw Pq,Qq | vpmaxsw Vx,Hx,Wx (66),(v1)
> +ef: pxor Pq,Qq | vpxor Vx,Hx,Wx (66),(v1)
> +# 0x0f 0xf0-0xff
> +f0: vlddqu Vx,Mx (F2)
> +f1: psllw Pq,Qq | vpsllw Vx,Hx,Wx (66),(v1)
> +f2: pslld Pq,Qq | vpslld Vx,Hx,Wx (66),(v1)
> +f3: psllq Pq,Qq | vpsllq Vx,Hx,Wx (66),(v1)
> +f4: pmuludq Pq,Qq | vpmuludq Vx,Hx,Wx (66),(v1)
> +f5: pmaddwd Pq,Qq | vpmaddwd Vx,Hx,Wx (66),(v1)
> +f6: psadbw Pq,Qq | vpsadbw Vx,Hx,Wx (66),(v1)
> +f7: maskmovq Pq,Nq | vmaskmovdqu Vx,Ux (66),(v1)
> +f8: psubb Pq,Qq | vpsubb Vx,Hx,Wx (66),(v1)
> +f9: psubw Pq,Qq | vpsubw Vx,Hx,Wx (66),(v1)
> +fa: psubd Pq,Qq | vpsubd Vx,Hx,Wx (66),(v1)
> +fb: psubq Pq,Qq | vpsubq Vx,Hx,Wx (66),(v1)
> +fc: paddb Pq,Qq | vpaddb Vx,Hx,Wx (66),(v1)
> +fd: paddw Pq,Qq | vpaddw Vx,Hx,Wx (66),(v1)
> +fe: paddd Pq,Qq | vpaddd Vx,Hx,Wx (66),(v1)
> +ff:
> +EndTable
> +
> +Table: 3-byte opcode 1 (0x0f 0x38)
> +Referrer: 3-byte escape 1
> +AVXcode: 2
> +# 0x0f 0x38 0x00-0x0f
> +00: pshufb Pq,Qq | vpshufb Vx,Hx,Wx (66),(v1)
> +01: phaddw Pq,Qq | vphaddw Vx,Hx,Wx (66),(v1)
> +02: phaddd Pq,Qq | vphaddd Vx,Hx,Wx (66),(v1)
> +03: phaddsw Pq,Qq | vphaddsw Vx,Hx,Wx (66),(v1)
> +04: pmaddubsw Pq,Qq | vpmaddubsw Vx,Hx,Wx (66),(v1)
> +05: phsubw Pq,Qq | vphsubw Vx,Hx,Wx (66),(v1)
> +06: phsubd Pq,Qq | vphsubd Vx,Hx,Wx (66),(v1)
> +07: phsubsw Pq,Qq | vphsubsw Vx,Hx,Wx (66),(v1)
> +08: psignb Pq,Qq | vpsignb Vx,Hx,Wx (66),(v1)
> +09: psignw Pq,Qq | vpsignw Vx,Hx,Wx (66),(v1)
> +0a: psignd Pq,Qq | vpsignd Vx,Hx,Wx (66),(v1)
> +0b: pmulhrsw Pq,Qq | vpmulhrsw Vx,Hx,Wx (66),(v1)
> +0c: vpermilps Vx,Hx,Wx (66),(v)
> +0d: vpermilpd Vx,Hx,Wx (66),(v)
> +0e: vtestps Vx,Wx (66),(v)
> +0f: vtestpd Vx,Wx (66),(v)
> +# 0x0f 0x38 0x10-0x1f
> +10: pblendvb Vdq,Wdq (66)
> +11:
> +12:
> +13: vcvtph2ps Vx,Wx,Ib (66),(v)
> +14: blendvps Vdq,Wdq (66)
> +15: blendvpd Vdq,Wdq (66)
> +16: vpermps Vqq,Hqq,Wqq (66),(v)
> +17: vptest Vx,Wx (66)
> +18: vbroadcastss Vx,Wd (66),(v)
> +19: vbroadcastsd Vqq,Wq (66),(v)
> +1a: vbroadcastf128 Vqq,Mdq (66),(v)
> +1b:
> +1c: pabsb Pq,Qq | vpabsb Vx,Wx (66),(v1)
> +1d: pabsw Pq,Qq | vpabsw Vx,Wx (66),(v1)
> +1e: pabsd Pq,Qq | vpabsd Vx,Wx (66),(v1)
> +1f:
> +# 0x0f 0x38 0x20-0x2f
> +20: vpmovsxbw Vx,Ux/Mq (66),(v1)
> +21: vpmovsxbd Vx,Ux/Md (66),(v1)
> +22: vpmovsxbq Vx,Ux/Mw (66),(v1)
> +23: vpmovsxwd Vx,Ux/Mq (66),(v1)
> +24: vpmovsxwq Vx,Ux/Md (66),(v1)
> +25: vpmovsxdq Vx,Ux/Mq (66),(v1)
> +26:
> +27:
> +28: vpmuldq Vx,Hx,Wx (66),(v1)
> +29: vpcmpeqq Vx,Hx,Wx (66),(v1)
> +2a: vmovntdqa Vx,Mx (66),(v1)
> +2b: vpackusdw Vx,Hx,Wx (66),(v1)
> +2c: vmaskmovps Vx,Hx,Mx (66),(v)
> +2d: vmaskmovpd Vx,Hx,Mx (66),(v)
> +2e: vmaskmovps Mx,Hx,Vx (66),(v)
> +2f: vmaskmovpd Mx,Hx,Vx (66),(v)
> +# 0x0f 0x38 0x30-0x3f
> +30: vpmovzxbw Vx,Ux/Mq (66),(v1)
> +31: vpmovzxbd Vx,Ux/Md (66),(v1)
> +32: vpmovzxbq Vx,Ux/Mw (66),(v1)
> +33: vpmovzxwd Vx,Ux/Mq (66),(v1)
> +34: vpmovzxwq Vx,Ux/Md (66),(v1)
> +35: vpmovzxdq Vx,Ux/Mq (66),(v1)
> +36: vpermd Vqq,Hqq,Wqq (66),(v)
> +37: vpcmpgtq Vx,Hx,Wx (66),(v1)
> +38: vpminsb Vx,Hx,Wx (66),(v1)
> +39: vpminsd Vx,Hx,Wx (66),(v1)
> +3a: vpminuw Vx,Hx,Wx (66),(v1)
> +3b: vpminud Vx,Hx,Wx (66),(v1)
> +3c: vpmaxsb Vx,Hx,Wx (66),(v1)
> +3d: vpmaxsd Vx,Hx,Wx (66),(v1)
> +3e: vpmaxuw Vx,Hx,Wx (66),(v1)
> +3f: vpmaxud Vx,Hx,Wx (66),(v1)
> +# 0x0f 0x38 0x40-0x8f
> +40: vpmulld Vx,Hx,Wx (66),(v1)
> +41: vphminposuw Vdq,Wdq (66),(v1)
> +42:
> +43:
> +44:
> +45: vpsrlvd/q Vx,Hx,Wx (66),(v)
> +46: vpsravd Vx,Hx,Wx (66),(v)
> +47: vpsllvd/q Vx,Hx,Wx (66),(v)
> +# Skip 0x48-0x57
> +58: vpbroadcastd Vx,Wx (66),(v)
> +59: vpbroadcastq Vx,Wx (66),(v)
> +5a: vbroadcasti128 Vqq,Mdq (66),(v)
> +# Skip 0x5b-0x77
> +78: vpbroadcastb Vx,Wx (66),(v)
> +79: vpbroadcastw Vx,Wx (66),(v)
> +# Skip 0x7a-0x7f
> +80: INVEPT Gy,Mdq (66)
> +81: INVPID Gy,Mdq (66)
> +82: INVPCID Gy,Mdq (66)
> +8c: vpmaskmovd/q Vx,Hx,Mx (66),(v)
> +8e: vpmaskmovd/q Mx,Vx,Hx (66),(v)
> +# 0x0f 0x38 0x90-0xbf (FMA)
> +90: vgatherdd/q Vx,Hx,Wx (66),(v)
> +91: vgatherqd/q Vx,Hx,Wx (66),(v)
> +92: vgatherdps/d Vx,Hx,Wx (66),(v)
> +93: vgatherqps/d Vx,Hx,Wx (66),(v)
> +94:
> +95:
> +96: vfmaddsub132ps/d Vx,Hx,Wx (66),(v)
> +97: vfmsubadd132ps/d Vx,Hx,Wx (66),(v)
> +98: vfmadd132ps/d Vx,Hx,Wx (66),(v)
> +99: vfmadd132ss/d Vx,Hx,Wx (66),(v),(v1)
> +9a: vfmsub132ps/d Vx,Hx,Wx (66),(v)
> +9b: vfmsub132ss/d Vx,Hx,Wx (66),(v),(v1)
> +9c: vfnmadd132ps/d Vx,Hx,Wx (66),(v)
> +9d: vfnmadd132ss/d Vx,Hx,Wx (66),(v),(v1)
> +9e: vfnmsub132ps/d Vx,Hx,Wx (66),(v)
> +9f: vfnmsub132ss/d Vx,Hx,Wx (66),(v),(v1)
> +a6: vfmaddsub213ps/d Vx,Hx,Wx (66),(v)
> +a7: vfmsubadd213ps/d Vx,Hx,Wx (66),(v)
> +a8: vfmadd213ps/d Vx,Hx,Wx (66),(v)
> +a9: vfmadd213ss/d Vx,Hx,Wx (66),(v),(v1)
> +aa: vfmsub213ps/d Vx,Hx,Wx (66),(v)
> +ab: vfmsub213ss/d Vx,Hx,Wx (66),(v),(v1)
> +ac: vfnmadd213ps/d Vx,Hx,Wx (66),(v)
> +ad: vfnmadd213ss/d Vx,Hx,Wx (66),(v),(v1)
> +ae: vfnmsub213ps/d Vx,Hx,Wx (66),(v)
> +af: vfnmsub213ss/d Vx,Hx,Wx (66),(v),(v1)
> +b6: vfmaddsub231ps/d Vx,Hx,Wx (66),(v)
> +b7: vfmsubadd231ps/d Vx,Hx,Wx (66),(v)
> +b8: vfmadd231ps/d Vx,Hx,Wx (66),(v)
> +b9: vfmadd231ss/d Vx,Hx,Wx (66),(v),(v1)
> +ba: vfmsub231ps/d Vx,Hx,Wx (66),(v)
> +bb: vfmsub231ss/d Vx,Hx,Wx (66),(v),(v1)
> +bc: vfnmadd231ps/d Vx,Hx,Wx (66),(v)
> +bd: vfnmadd231ss/d Vx,Hx,Wx (66),(v),(v1)
> +be: vfnmsub231ps/d Vx,Hx,Wx (66),(v)
> +bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1)
> +# 0x0f 0x38 0xc0-0xff
> +db: VAESIMC Vdq,Wdq (66),(v1)
> +dc: VAESENC Vdq,Hdq,Wdq (66),(v1)
> +dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1)
> +de: VAESDEC Vdq,Hdq,Wdq (66),(v1)
> +df: VAESDECLAST Vdq,Hdq,Wdq (66),(v1)
> +f0: MOVBE Gy,My | MOVBE Gw,Mw (66) | CRC32 Gd,Eb (F2) | CRC32 Gd,Eb (66&F2)
> +f1: MOVBE My,Gy | MOVBE Mw,Gw (66) | CRC32 Gd,Ey (F2) | CRC32 Gd,Ew (66&F2)
> +f2: ANDN Gy,By,Ey (v)
> +f3: Grp17 (1A)
> +f5: BZHI Gy,Ey,By (v) | PEXT Gy,By,Ey (F3),(v) | PDEP Gy,By,Ey (F2),(v)
> +f6: ADCX Gy,Ey (66) | ADOX Gy,Ey (F3) | MULX By,Gy,rDX,Ey (F2),(v)
> +f7: BEXTR Gy,Ey,By (v) | SHLX Gy,Ey,By (66),(v) | SARX Gy,Ey,By (F3),(v) | SHRX Gy,Ey,By (F2),(v)
> +EndTable
> +
> +Table: 3-byte opcode 2 (0x0f 0x3a)
> +Referrer: 3-byte escape 2
> +AVXcode: 3
> +# 0x0f 0x3a 0x00-0xff
> +00: vpermq Vqq,Wqq,Ib (66),(v)
> +01: vpermpd Vqq,Wqq,Ib (66),(v)
> +02: vpblendd Vx,Hx,Wx,Ib (66),(v)
> +03:
> +04: vpermilps Vx,Wx,Ib (66),(v)
> +05: vpermilpd Vx,Wx,Ib (66),(v)
> +06: vperm2f128 Vqq,Hqq,Wqq,Ib (66),(v)
> +07:
> +08: vroundps Vx,Wx,Ib (66)
> +09: vroundpd Vx,Wx,Ib (66)
> +0a: vroundss Vss,Wss,Ib (66),(v1)
> +0b: vroundsd Vsd,Wsd,Ib (66),(v1)
> +0c: vblendps Vx,Hx,Wx,Ib (66)
> +0d: vblendpd Vx,Hx,Wx,Ib (66)
> +0e: vpblendw Vx,Hx,Wx,Ib (66),(v1)
> +0f: palignr Pq,Qq,Ib | vpalignr Vx,Hx,Wx,Ib (66),(v1)
> +14: vpextrb Rd/Mb,Vdq,Ib (66),(v1)
> +15: vpextrw Rd/Mw,Vdq,Ib (66),(v1)
> +16: vpextrd/q Ey,Vdq,Ib (66),(v1)
> +17: vextractps Ed,Vdq,Ib (66),(v1)
> +18: vinsertf128 Vqq,Hqq,Wqq,Ib (66),(v)
> +19: vextractf128 Wdq,Vqq,Ib (66),(v)
> +1d: vcvtps2ph Wx,Vx,Ib (66),(v)
> +20: vpinsrb Vdq,Hdq,Ry/Mb,Ib (66),(v1)
> +21: vinsertps Vdq,Hdq,Udq/Md,Ib (66),(v1)
> +22: vpinsrd/q Vdq,Hdq,Ey,Ib (66),(v1)
> +38: vinserti128 Vqq,Hqq,Wqq,Ib (66),(v)
> +39: vextracti128 Wdq,Vqq,Ib (66),(v)
> +40: vdpps Vx,Hx,Wx,Ib (66)
> +41: vdppd Vdq,Hdq,Wdq,Ib (66),(v1)
> +42: vmpsadbw Vx,Hx,Wx,Ib (66),(v1)
> +44: vpclmulqdq Vdq,Hdq,Wdq,Ib (66),(v1)
> +46: vperm2i128 Vqq,Hqq,Wqq,Ib (66),(v)
> +4a: vblendvps Vx,Hx,Wx,Lx (66),(v)
> +4b: vblendvpd Vx,Hx,Wx,Lx (66),(v)
> +4c: vpblendvb Vx,Hx,Wx,Lx (66),(v1)
> +60: vpcmpestrm Vdq,Wdq,Ib (66),(v1)
> +61: vpcmpestri Vdq,Wdq,Ib (66),(v1)
> +62: vpcmpistrm Vdq,Wdq,Ib (66),(v1)
> +63: vpcmpistri Vdq,Wdq,Ib (66),(v1)
> +df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1)
> +f0: RORX Gy,Ey,Ib (F2),(v)
> +EndTable
> +
> +GrpTable: Grp1
> +0: ADD
> +1: OR
> +2: ADC
> +3: SBB
> +4: AND
> +5: SUB
> +6: XOR
> +7: CMP
> +EndTable
> +
> +GrpTable: Grp1A
> +0: POP
> +EndTable
> +
> +GrpTable: Grp2
> +0: ROL
> +1: ROR
> +2: RCL
> +3: RCR
> +4: SHL/SAL
> +5: SHR
> +6:
> +7: SAR
> +EndTable
> +
> +GrpTable: Grp3_1
> +0: TEST Eb,Ib
> +1:
> +2: NOT Eb
> +3: NEG Eb
> +4: MUL AL,Eb
> +5: IMUL AL,Eb
> +6: DIV AL,Eb
> +7: IDIV AL,Eb
> +EndTable
> +
> +GrpTable: Grp3_2
> +0: TEST Ev,Iz
> +1:
> +2: NOT Ev
> +3: NEG Ev
> +4: MUL rAX,Ev
> +5: IMUL rAX,Ev
> +6: DIV rAX,Ev
> +7: IDIV rAX,Ev
> +EndTable
> +
> +GrpTable: Grp4
> +0: INC Eb
> +1: DEC Eb
> +EndTable
> +
> +GrpTable: Grp5
> +0: INC Ev
> +1: DEC Ev
> +2: CALLN Ev (f64)
> +3: CALLF Ep
> +4: JMPN Ev (f64)
> +5: JMPF Mp
> +6: PUSH Ev (d64)
> +7:
> +EndTable
> +
> +GrpTable: Grp6
> +0: SLDT Rv/Mw
> +1: STR Rv/Mw
> +2: LLDT Ew
> +3: LTR Ew
> +4: VERR Ew
> +5: VERW Ew
> +EndTable
> +
> +GrpTable: Grp7
> +0: SGDT Ms | VMCALL (001),(11B) | VMLAUNCH (010),(11B) | VMRESUME (011),(11B) | VMXOFF (100),(11B)
> +1: SIDT Ms | MONITOR (000),(11B) | MWAIT (001),(11B) | CLAC (010),(11B) | STAC (011),(11B)
> +2: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | XEND (101)(11B) | XTEST (110)(11B)
> +3: LIDT Ms
> +4: SMSW Mw/Rv
> +5:
> +6: LMSW Ew
> +7: INVLPG Mb | SWAPGS (o64),(000),(11B) | RDTSCP (001),(11B)
> +EndTable
> +
> +GrpTable: Grp8
> +4: BT
> +5: BTS
> +6: BTR
> +7: BTC
> +EndTable
> +
> +GrpTable: Grp9
> +1: CMPXCHG8B/16B Mq/Mdq
> +6: VMPTRLD Mq | VMCLEAR Mq (66) | VMXON Mq (F3) | RDRAND Rv (11B)
> +7: VMPTRST Mq | VMPTRST Mq (F3) | RDSEED Rv (11B)
> +EndTable
> +
> +GrpTable: Grp10
> +EndTable
> +
> +# Grp11A and Grp11B are expressed as Grp11 in Intel SDM
> +GrpTable: Grp11A
> +0: MOV Eb,Ib
> +7: XABORT Ib (000),(11B)
> +EndTable
> +
> +GrpTable: Grp11B
> +0: MOV Eb,Iz
> +7: XBEGIN Jz (000),(11B)
> +EndTable
> +
> +GrpTable: Grp12
> +2: psrlw Nq,Ib (11B) | vpsrlw Hx,Ux,Ib (66),(11B),(v1)
> +4: psraw Nq,Ib (11B) | vpsraw Hx,Ux,Ib (66),(11B),(v1)
> +6: psllw Nq,Ib (11B) | vpsllw Hx,Ux,Ib (66),(11B),(v1)
> +EndTable
> +
> +GrpTable: Grp13
> +2: psrld Nq,Ib (11B) | vpsrld Hx,Ux,Ib (66),(11B),(v1)
> +4: psrad Nq,Ib (11B) | vpsrad Hx,Ux,Ib (66),(11B),(v1)
> +6: pslld Nq,Ib (11B) | vpslld Hx,Ux,Ib (66),(11B),(v1)
> +EndTable
> +
> +GrpTable: Grp14
> +2: psrlq Nq,Ib (11B) | vpsrlq Hx,Ux,Ib (66),(11B),(v1)
> +3: vpsrldq Hx,Ux,Ib (66),(11B),(v1)
> +6: psllq Nq,Ib (11B) | vpsllq Hx,Ux,Ib (66),(11B),(v1)
> +7: vpslldq Hx,Ux,Ib (66),(11B),(v1)
> +EndTable
> +
> +GrpTable: Grp15
> +0: fxsave | RDFSBASE Ry (F3),(11B)
> +1: fxstor | RDGSBASE Ry (F3),(11B)
> +2: vldmxcsr Md (v1) | WRFSBASE Ry (F3),(11B)
> +3: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B)
> +4: XSAVE
> +5: XRSTOR | lfence (11B)
> +6: XSAVEOPT | mfence (11B)
> +7: clflush | sfence (11B)
> +EndTable
> +
> +GrpTable: Grp16
> +0: prefetch NTA
> +1: prefetch T0
> +2: prefetch T1
> +3: prefetch T2
> +EndTable
> +
> +GrpTable: Grp17
> +1: BLSR By,Ey (v)
> +2: BLSMSK By,Ey (v)
> +3: BLSI By,Ey (v)
> +EndTable
> +
> +# AMD's Prefetch Group
> +GrpTable: GrpP
> +0: PREFETCH
> +1: PREFETCHW
> +EndTable
> +
> +GrpTable: GrpPDLK
> +0: MONTMUL
> +1: XSHA1
> +2: XSHA2
> +EndTable
> +
> +GrpTable: GrpRNG
> +0: xstore-rng
> +1: xcrypt-ecb
> +2: xcrypt-cbc
> +4: xcrypt-cfb
> +5: xcrypt-ofb
> +EndTable
> diff --git a/xen/include/asm-x86/inat.h b/xen/include/asm-x86/inat.h
> new file mode 100644
> index 0000000..41b9066
> --- /dev/null
> +++ b/xen/include/asm-x86/inat.h
> @@ -0,0 +1,219 @@
> +#ifndef _ASM_X86_INAT_H
> +#define _ASM_X86_INAT_H
> +/*
> + * x86 instruction attributes
> + *
> + * Written by Masami Hiramatsu <mhiramat@redhat.com>
> + *
> + * 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, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + *
> + */
> +#include <asm/inat_types.h>
> +
> +/*
> + * Internal bits. Don't use bitmasks directly, because these bits are
> + * unstable. You should use checking functions.
> + */
> +
> +#define INAT_OPCODE_TABLE_SIZE 256
> +#define INAT_GROUP_TABLE_SIZE 8
> +
> +/* Legacy last prefixes */
> +#define INAT_PFX_OPNDSZ 1 /* 0x66 */ /* LPFX1 */
> +#define INAT_PFX_REPE 2 /* 0xF3 */   /* LPFX2 */
> +#define INAT_PFX_REPNE 3 /* 0xF2 */  /* LPFX3 */
> +/* Other Legacy prefixes */
> +#define INAT_PFX_LOCK 4    /* 0xF0 */
> +#define INAT_PFX_CS 5      /* 0x2E */
> +#define INAT_PFX_DS 6      /* 0x3E */
> +#define INAT_PFX_ES 7      /* 0x26 */
> +#define INAT_PFX_FS 8      /* 0x64 */
> +#define INAT_PFX_GS 9      /* 0x65 */
> +#define INAT_PFX_SS 10     /* 0x36 */
> +#define INAT_PFX_ADDRSZ 11 /* 0x67 */
> +/* x86-64 REX prefix */
> +#define INAT_PFX_REX 12 /* 0x4X */
> +/* AVX VEX prefixes */
> +#define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */
> +#define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */
> +
> +#define INAT_LSTPFX_MAX 3
> +#define INAT_LGCPFX_MAX 11
> +
> +/* Immediate size */
> +#define INAT_IMM_BYTE 1
> +#define INAT_IMM_WORD 2
> +#define INAT_IMM_DWORD 3
> +#define INAT_IMM_QWORD 4
> +#define INAT_IMM_PTR 5
> +#define INAT_IMM_VWORD32 6
> +#define INAT_IMM_VWORD 7
> +
> +/* Legacy prefix */
> +#define INAT_PFX_OFFS 0
> +#define INAT_PFX_BITS 4
> +#define INAT_PFX_MAX ((1 << INAT_PFX_BITS) - 1)
> +#define INAT_PFX_MASK (INAT_PFX_MAX << INAT_PFX_OFFS)
> +/* Escape opcodes */
> +#define INAT_ESC_OFFS (INAT_PFX_OFFS + INAT_PFX_BITS)
> +#define INAT_ESC_BITS 2
> +#define INAT_ESC_MAX ((1 << INAT_ESC_BITS) - 1)
> +#define INAT_ESC_MASK (INAT_ESC_MAX << INAT_ESC_OFFS)
> +/* Group opcodes (1-16) */
> +#define INAT_GRP_OFFS (INAT_ESC_OFFS + INAT_ESC_BITS)
> +#define INAT_GRP_BITS 5
> +#define INAT_GRP_MAX ((1 << INAT_GRP_BITS) - 1)
> +#define INAT_GRP_MASK (INAT_GRP_MAX << INAT_GRP_OFFS)
> +/* Immediates */
> +#define INAT_IMM_OFFS (INAT_GRP_OFFS + INAT_GRP_BITS)
> +#define INAT_IMM_BITS 3
> +#define INAT_IMM_MASK (((1 << INAT_IMM_BITS) - 1) << INAT_IMM_OFFS)
> +/* Flags */
> +#define INAT_FLAG_OFFS (INAT_IMM_OFFS + INAT_IMM_BITS)
> +#define INAT_MODRM (1 << (INAT_FLAG_OFFS))
> +#define INAT_FORCE64 (1 << (INAT_FLAG_OFFS + 1))
> +#define INAT_SCNDIMM (1 << (INAT_FLAG_OFFS + 2))
> +#define INAT_MOFFSET (1 << (INAT_FLAG_OFFS + 3))
> +#define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4))
> +#define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5))
> +#define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6))
> +/* Attribute making macros for attribute tables */
> +#define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS)
> +#define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS)
> +#define INAT_MAKE_GROUP(grp) ((grp << INAT_GRP_OFFS) | INAT_MODRM)
> +#define INAT_MAKE_IMM(imm) (imm << INAT_IMM_OFFS)
> +
> +/* Attribute search APIs */
> +extern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode);
> +extern int inat_get_last_prefix_id(insn_byte_t last_pfx);
> +extern insn_attr_t inat_get_escape_attribute(insn_byte_t opcode, int lpfx_id,
> +                                             insn_attr_t esc_attr);
> +extern insn_attr_t inat_get_group_attribute(insn_byte_t modrm, int lpfx_id,
> +                                            insn_attr_t esc_attr);
> +extern insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, insn_byte_t vex_m,
> +                                          insn_byte_t vex_pp);
> +
> +/* Attribute checking functions */
> +static inline int inat_is_legacy_prefix(insn_attr_t attr)
> +{
> +    attr &= INAT_PFX_MASK;
> +    return attr && attr <= INAT_LGCPFX_MAX;
> +}
> +
> +static inline int inat_is_address_size_prefix(insn_attr_t attr)
> +{
> +    return (attr & INAT_PFX_MASK) == INAT_PFX_ADDRSZ;
> +}
> +
> +static inline int inat_is_operand_size_prefix(insn_attr_t attr)
> +{
> +    return (attr & INAT_PFX_MASK) == INAT_PFX_OPNDSZ;
> +}
> +
> +static inline int inat_is_rex_prefix(insn_attr_t attr)
> +{
> +    return (attr & INAT_PFX_MASK) == INAT_PFX_REX;
> +}
> +
> +static inline int inat_last_prefix_id(insn_attr_t attr)
> +{
> +    if ( (attr & INAT_PFX_MASK) > INAT_LSTPFX_MAX )
> +        return 0;
> +    else
> +        return attr & INAT_PFX_MASK;
> +}
> +
> +static inline int inat_is_vex_prefix(insn_attr_t attr)
> +{
> +    attr &= INAT_PFX_MASK;
> +    return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3;
> +}
> +
> +static inline int inat_is_vex3_prefix(insn_attr_t attr)
> +{
> +    return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3;
> +}
> +
> +static inline int inat_is_escape(insn_attr_t attr)
> +{
> +    return attr & INAT_ESC_MASK;
> +}
> +
> +static inline int inat_escape_id(insn_attr_t attr)
> +{
> +    return (attr & INAT_ESC_MASK) >> INAT_ESC_OFFS;
> +}
> +
> +static inline int inat_is_group(insn_attr_t attr)
> +{
> +    return attr & INAT_GRP_MASK;
> +}
> +
> +static inline int inat_group_id(insn_attr_t attr)
> +{
> +    return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS;
> +}
> +
> +static inline int inat_group_common_attribute(insn_attr_t attr)
> +{
> +    return attr & ~INAT_GRP_MASK;
> +}
> +
> +static inline int inat_has_immediate(insn_attr_t attr)
> +{
> +    return attr & INAT_IMM_MASK;
> +}
> +
> +static inline int inat_immediate_size(insn_attr_t attr)
> +{
> +    return (attr & INAT_IMM_MASK) >> INAT_IMM_OFFS;
> +}
> +
> +static inline int inat_has_modrm(insn_attr_t attr)
> +{
> +    return attr & INAT_MODRM;
> +}
> +
> +static inline int inat_is_force64(insn_attr_t attr)
> +{
> +    return attr & INAT_FORCE64;
> +}
> +
> +static inline int inat_has_second_immediate(insn_attr_t attr)
> +{
> +    return attr & INAT_SCNDIMM;
> +}
> +
> +static inline int inat_has_moffset(insn_attr_t attr)
> +{
> +    return attr & INAT_MOFFSET;
> +}
> +
> +static inline int inat_has_variant(insn_attr_t attr)
> +{
> +    return attr & INAT_VARIANT;
> +}
> +
> +static inline int inat_accept_vex(insn_attr_t attr)
> +{
> +    return attr & INAT_VEXOK;
> +}
> +
> +static inline int inat_must_vex(insn_attr_t attr)
> +{
> +    return attr & INAT_VEXONLY;
> +}
> +
> +#endif /* _ASM_X86_INAT_H */
> diff --git a/xen/include/asm-x86/inat_types.h b/xen/include/asm-x86/inat_types.h
> new file mode 100644
> index 0000000..662ac14
> --- /dev/null
> +++ b/xen/include/asm-x86/inat_types.h
> @@ -0,0 +1,29 @@
> +#ifndef _ASM_X86_INAT_TYPES_H
> +#define _ASM_X86_INAT_TYPES_H
> +/*
> + * x86 instruction attributes
> + *
> + * Written by Masami Hiramatsu <mhiramat@redhat.com>
> + *
> + * 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, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + *
> + */
> +
> +/* Instruction attributes */
> +typedef unsigned int insn_attr_t;
> +typedef unsigned char insn_byte_t;
> +typedef signed int insn_value_t;
> +
> +#endif /* _ASM_X86_INAT_TYPES_H */
> diff --git a/xen/include/asm-x86/insn.h b/xen/include/asm-x86/insn.h
> new file mode 100644
> index 0000000..739773a
> --- /dev/null
> +++ b/xen/include/asm-x86/insn.h
> @@ -0,0 +1,201 @@
> +#ifndef _ASM_X86_INSN_H
> +#define _ASM_X86_INSN_H
> +/*
> + * x86 instruction analysis
> + *
> + * 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, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + *
> + * Copyright (C) IBM Corporation, 2009
> + */
> +
> +/* insn_attr_t is defined in inat.h */
> +#include <asm/inat.h>
> +
> +struct insn_field
> +{
> +    union {
> +        insn_value_t value;
> +        insn_byte_t bytes[4];
> +    };
> +    /* !0 if we've run insn_get_xxx() for this field */
> +    unsigned char got;
> +    unsigned char nbytes;
> +};
> +
> +struct insn
> +{
> +    struct insn_field prefixes; /*
> +                                 * Prefixes
> +                                 * prefixes.bytes[3]: last prefix
> +                                 */
> +    struct insn_field rex_prefix; /* REX prefix */
> +    struct insn_field vex_prefix; /* VEX prefix */
> +    struct insn_field opcode;     /*
> +                                   * opcode.bytes[0]: opcode1
> +                                   * opcode.bytes[1]: opcode2
> +                                   * opcode.bytes[2]: opcode3
> +                                   */
> +    struct insn_field modrm;
> +    struct insn_field sib;
> +    struct insn_field displacement;
> +    union {
> +        struct insn_field immediate;
> +        struct insn_field moffset1;   /* for 64bit MOV */
> +        struct insn_field immediate1; /* for 64bit imm or off16/32 */
> +    };
> +    union {
> +        struct insn_field moffset2;   /* for 64bit MOV */
> +        struct insn_field immediate2; /* for 64bit imm or seg16 */
> +    };
> +
> +    insn_attr_t attr;
> +    unsigned char opnd_bytes;
> +    unsigned char addr_bytes;
> +    unsigned char length;
> +    unsigned char x86_64;
> +
> +    const insn_byte_t *kaddr; /* kernel address of insn to analyze */
> +    const insn_byte_t *next_byte;
> +};
> +
> +#define MAX_INSN_SIZE 16
> +
> +#define X86_MODRM_MOD(modrm) (((modrm) & 0xc0) >> 6)
> +#define X86_MODRM_REG(modrm) (((modrm) & 0x38) >> 3)
> +#define X86_MODRM_RM(modrm) ((modrm) & 0x07)
> +
> +#define X86_SIB_SCALE(sib) (((sib) & 0xc0) >> 6)
> +#define X86_SIB_INDEX(sib) (((sib) & 0x38) >> 3)
> +#define X86_SIB_BASE(sib) ((sib) & 0x07)
> +
> +#define X86_REX_W(rex) ((rex) & 8)
> +#define X86_REX_R(rex) ((rex) & 4)
> +#define X86_REX_X(rex) ((rex) & 2)
> +#define X86_REX_B(rex) ((rex) & 1)
> +
> +/* VEX bit flags  */
> +#define X86_VEX_W(vex) ((vex) & 0x80) /* VEX3 Byte2 */
> +#define X86_VEX_R(vex) ((vex) & 0x80) /* VEX2/3 Byte1 */
> +#define X86_VEX_X(vex) ((vex) & 0x40) /* VEX3 Byte1 */
> +#define X86_VEX_B(vex) ((vex) & 0x20) /* VEX3 Byte1 */
> +#define X86_VEX_L(vex) ((vex) & 0x04) /* VEX3 Byte2, VEX2 Byte1 */
> +/* VEX bit fields */
> +#define X86_VEX3_M(vex) ((vex) & 0x1f)       /* VEX3 Byte1 */
> +#define X86_VEX2_M 1                         /* VEX2.M always 1 */
> +#define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */
> +#define X86_VEX_P(vex) ((vex) & 0x03)        /* VEX3 Byte2, VEX2 Byte1 */
> +#define X86_VEX_M_MAX 0x1f                   /* VEX3.M Maximum value */
> +
> +extern void insn_init(struct insn *insn, const void *kaddr, int x86_64);
> +extern void insn_get_prefixes(struct insn *insn);
> +extern void insn_get_opcode(struct insn *insn);
> +extern void insn_get_modrm(struct insn *insn);
> +extern void insn_get_sib(struct insn *insn);
> +extern void insn_get_displacement(struct insn *insn);
> +extern void insn_get_immediate(struct insn *insn);
> +extern void insn_get_length(struct insn *insn);
> +
> +/* Attribute will be determined after getting ModRM (for opcode groups) */
> +static inline void insn_get_attribute(struct insn *insn)
> +{
> +    insn_get_modrm(insn);
> +}
> +
> +/* Instruction uses RIP-relative addressing */
> +extern int insn_rip_relative(struct insn *insn);
> +
> +/* Init insn for kernel text */
> +static inline void kernel_insn_init(struct insn *insn, const void *kaddr)
> +{
> +#ifdef CONFIG_X86_64
> +    insn_init(insn, kaddr, 1);
> +#else /* CONFIG_X86_32 */
> +    insn_init(insn, kaddr, 0);
> +#endif
> +}
> +
> +static inline int insn_is_avx(struct insn *insn)
> +{
> +    if ( !insn->prefixes.got )
> +        insn_get_prefixes(insn);
> +    return (insn->vex_prefix.value != 0);
> +}
> +
> +/* Ensure this instruction is decoded completely */
> +static inline int insn_complete(struct insn *insn)
> +{
> +    return insn->opcode.got && insn->modrm.got && insn->sib.got &&
> +           insn->displacement.got && insn->immediate.got;
> +}
> +
> +static inline insn_byte_t insn_vex_m_bits(struct insn *insn)
> +{
> +    if ( insn->vex_prefix.nbytes == 2 ) /* 2 bytes VEX */
> +        return X86_VEX2_M;
> +    else
> +        return X86_VEX3_M(insn->vex_prefix.bytes[1]);
> +}
> +
> +static inline insn_byte_t insn_vex_p_bits(struct insn *insn)
> +{
> +    if ( insn->vex_prefix.nbytes == 2 ) /* 2 bytes VEX */
> +        return X86_VEX_P(insn->vex_prefix.bytes[1]);
> +    else
> +        return X86_VEX_P(insn->vex_prefix.bytes[2]);
> +}
> +
> +/* Get the last prefix id from last prefix or VEX prefix */
> +static inline int insn_last_prefix_id(struct insn *insn)
> +{
> +    if ( insn_is_avx(insn) )
> +        return insn_vex_p_bits(insn); /* VEX_p is a SIMD prefix id */
> +
> +    if ( insn->prefixes.bytes[3] )
> +        return inat_get_last_prefix_id(insn->prefixes.bytes[3]);
> +
> +    return 0;
> +}
> +
> +/* Offset of each field from kaddr */
> +static inline int insn_offset_rex_prefix(struct insn *insn)
> +{
> +    return insn->prefixes.nbytes;
> +}
> +static inline int insn_offset_vex_prefix(struct insn *insn)
> +{
> +    return insn_offset_rex_prefix(insn) + insn->rex_prefix.nbytes;
> +}
> +static inline int insn_offset_opcode(struct insn *insn)
> +{
> +    return insn_offset_vex_prefix(insn) + insn->vex_prefix.nbytes;
> +}
> +static inline int insn_offset_modrm(struct insn *insn)
> +{
> +    return insn_offset_opcode(insn) + insn->opcode.nbytes;
> +}
> +static inline int insn_offset_sib(struct insn *insn)
> +{
> +    return insn_offset_modrm(insn) + insn->modrm.nbytes;
> +}
> +static inline int insn_offset_displacement(struct insn *insn)
> +{
> +    return insn_offset_sib(insn) + insn->sib.nbytes;
> +}
> +static inline int insn_offset_immediate(struct insn *insn)
> +{
> +    return insn_offset_displacement(insn) + insn->displacement.nbytes;
> +}
> +
> +#endif /* _ASM_X86_INSN_H */
> diff --git a/xen/tools/gen-insn-attr-x86.awk b/xen/tools/gen-insn-attr-x86.awk
> new file mode 100644
> index 0000000..bbb8f40
> --- /dev/null
> +++ b/xen/tools/gen-insn-attr-x86.awk
> @@ -0,0 +1,386 @@
> +#!/bin/awk -f
> +# gen-insn-attr-x86.awk: Instruction attribute table generator
> +# Written by Masami Hiramatsu <mhiramat@redhat.com>
> +#
> +# Usage: awk -f gen-insn-attr-x86.awk x86-opcode-map.txt > inat-tables.c
> +
> +# Awk implementation sanity check
> +function check_awk_implement() {
> +	if (sprintf("%x", 0) != "0")
> +		return "Your awk has a printf-format problem."
> +	return ""
> +}
> +
> +# Clear working vars
> +function clear_vars() {
> +	delete table
> +	delete lptable2
> +	delete lptable1
> +	delete lptable3
> +	eid = -1 # escape id
> +	gid = -1 # group id
> +	aid = -1 # AVX id
> +	tname = ""
> +}
> +
> +BEGIN {
> +	# Implementation error checking
> +	awkchecked = check_awk_implement()
> +	if (awkchecked != "") {
> +		print "Error: " awkchecked > "/dev/stderr"
> +		print "Please try to use gawk." > "/dev/stderr"
> +		exit 1
> +	}
> +
> +	# Setup generating tables
> +	print "/* x86 opcode map generated from x86-opcode-map.txt */"
> +	print "/* Do not change this code. */\n"
> +	ggid = 1
> +	geid = 1
> +	gaid = 0
> +	delete etable
> +	delete gtable
> +	delete atable
> +
> +	opnd_expr = "^[A-Za-z/]"
> +	ext_expr = "^\\("
> +	sep_expr = "^\\|$"
> +	group_expr = "^Grp[0-9A-Za-z]+"
> +
> +	imm_expr = "^[IJAOL][a-z]"
> +	imm_flag["Ib"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
> +	imm_flag["Jb"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
> +	imm_flag["Iw"] = "INAT_MAKE_IMM(INAT_IMM_WORD)"
> +	imm_flag["Id"] = "INAT_MAKE_IMM(INAT_IMM_DWORD)"
> +	imm_flag["Iq"] = "INAT_MAKE_IMM(INAT_IMM_QWORD)"
> +	imm_flag["Ap"] = "INAT_MAKE_IMM(INAT_IMM_PTR)"
> +	imm_flag["Iz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
> +	imm_flag["Jz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
> +	imm_flag["Iv"] = "INAT_MAKE_IMM(INAT_IMM_VWORD)"
> +	imm_flag["Ob"] = "INAT_MOFFSET"
> +	imm_flag["Ov"] = "INAT_MOFFSET"
> +	imm_flag["Lx"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
> +
> +	modrm_expr = "^([CDEGMNPQRSUVW/][a-z]+|NTA|T[012])"
> +	force64_expr = "\\([df]64\\)"
> +	rex_expr = "^REX(\\.[XRWB]+)*"
> +	fpu_expr = "^ESC" # TODO
> +
> +	lprefix1_expr = "\\((66|!F3)\\)"
> +	lprefix2_expr = "\\(F3\\)"
> +	lprefix3_expr = "\\((F2|!F3|66\\&F2)\\)"
> +	lprefix_expr = "\\((66|F2|F3)\\)"
> +	max_lprefix = 4
> +
> +	# All opcodes starting with lower-case 'v' or with (v1) superscript
> +	# accepts VEX prefix
> +	vexok_opcode_expr = "^v.*"
> +	vexok_expr = "\\(v1\\)"
> +	# All opcodes with (v) superscript supports *only* VEX prefix
> +	vexonly_expr = "\\(v\\)"
> +
> +	prefix_expr = "\\(Prefix\\)"
> +	prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ"
> +	prefix_num["REPNE"] = "INAT_PFX_REPNE"
> +	prefix_num["REP/REPE"] = "INAT_PFX_REPE"
> +	prefix_num["XACQUIRE"] = "INAT_PFX_REPNE"
> +	prefix_num["XRELEASE"] = "INAT_PFX_REPE"
> +	prefix_num["LOCK"] = "INAT_PFX_LOCK"
> +	prefix_num["SEG=CS"] = "INAT_PFX_CS"
> +	prefix_num["SEG=DS"] = "INAT_PFX_DS"
> +	prefix_num["SEG=ES"] = "INAT_PFX_ES"
> +	prefix_num["SEG=FS"] = "INAT_PFX_FS"
> +	prefix_num["SEG=GS"] = "INAT_PFX_GS"
> +	prefix_num["SEG=SS"] = "INAT_PFX_SS"
> +	prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ"
> +	prefix_num["VEX+1byte"] = "INAT_PFX_VEX2"
> +	prefix_num["VEX+2byte"] = "INAT_PFX_VEX3"
> +
> +	clear_vars()
> +}
> +
> +function semantic_error(msg) {
> +	print "Semantic error at " NR ": " msg > "/dev/stderr"
> +	exit 1
> +}
> +
> +function debug(msg) {
> +	print "DEBUG: " msg
> +}
> +
> +function array_size(arr,   i,c) {
> +	c = 0
> +	for (i in arr)
> +		c++
> +	return c
> +}
> +
> +/^Table:/ {
> +	print "/* " $0 " */"
> +	if (tname != "")
> +		semantic_error("Hit Table: before EndTable:.");
> +}
> +
> +/^Referrer:/ {
> +	if (NF != 1) {
> +		# escape opcode table
> +		ref = ""
> +		for (i = 2; i <= NF; i++)
> +			ref = ref $i
> +		eid = escape[ref]
> +		tname = sprintf("inat_escape_table_%d", eid)
> +	}
> +}
> +
> +/^AVXcode:/ {
> +	if (NF != 1) {
> +		# AVX/escape opcode table
> +		aid = $2
> +		if (gaid <= aid)
> +			gaid = aid + 1
> +		if (tname == "")	# AVX only opcode table
> +			tname = sprintf("inat_avx_table_%d", $2)
> +	}
> +	if (aid == -1 && eid == -1)	# primary opcode table
> +		tname = "inat_primary_table"
> +}
> +
> +/^GrpTable:/ {
> +	print "/* " $0 " */"
> +	if (!($2 in group))
> +		semantic_error("No group: " $2 )
> +	gid = group[$2]
> +	tname = "inat_group_table_" gid
> +}
> +
> +function print_table(tbl,name,fmt,n)
> +{
> +	print "const insn_attr_t " name " = {"
> +	for (i = 0; i < n; i++) {
> +		id = sprintf(fmt, i)
> +		if (tbl[id])
> +			print "    [" id "] = " tbl[id] ","
> +	}
> +	print "};"
> +}
> +
> +/^EndTable/ {
> +	if (gid != -1) {
> +		# print group tables
> +		if (array_size(table) != 0) {
> +			print_table(table, tname "[INAT_GROUP_TABLE_SIZE]",
> +				    "0x%x", 8)
> +			gtable[gid,0] = tname
> +		}
> +		if (array_size(lptable1) != 0) {
> +			print_table(lptable1, tname "_1[INAT_GROUP_TABLE_SIZE]",
> +				    "0x%x", 8)
> +			gtable[gid,1] = tname "_1"
> +		}
> +		if (array_size(lptable2) != 0) {
> +			print_table(lptable2, tname "_2[INAT_GROUP_TABLE_SIZE]",
> +				    "0x%x", 8)
> +			gtable[gid,2] = tname "_2"
> +		}
> +		if (array_size(lptable3) != 0) {
> +			print_table(lptable3, tname "_3[INAT_GROUP_TABLE_SIZE]",
> +				    "0x%x", 8)
> +			gtable[gid,3] = tname "_3"
> +		}
> +	} else {
> +		# print primary/escaped tables
> +		if (array_size(table) != 0) {
> +			print_table(table, tname "[INAT_OPCODE_TABLE_SIZE]",
> +				    "0x%02x", 256)
> +			etable[eid,0] = tname
> +			if (aid >= 0)
> +				atable[aid,0] = tname
> +		}
> +		if (array_size(lptable1) != 0) {
> +			print_table(lptable1,tname "_1[INAT_OPCODE_TABLE_SIZE]",
> +				    "0x%02x", 256)
> +			etable[eid,1] = tname "_1"
> +			if (aid >= 0)
> +				atable[aid,1] = tname "_1"
> +		}
> +		if (array_size(lptable2) != 0) {
> +			print_table(lptable2,tname "_2[INAT_OPCODE_TABLE_SIZE]",
> +				    "0x%02x", 256)
> +			etable[eid,2] = tname "_2"
> +			if (aid >= 0)
> +				atable[aid,2] = tname "_2"
> +		}
> +		if (array_size(lptable3) != 0) {
> +			print_table(lptable3,tname "_3[INAT_OPCODE_TABLE_SIZE]",
> +				    "0x%02x", 256)
> +			etable[eid,3] = tname "_3"
> +			if (aid >= 0)
> +				atable[aid,3] = tname "_3"
> +		}
> +	}
> +	print ""
> +	clear_vars()
> +}
> +
> +function add_flags(old,new) {
> +	if (old && new)
> +		return old " | " new
> +	else if (old)
> +		return old
> +	else
> +		return new
> +}
> +
> +# convert operands to flags.
> +function convert_operands(count,opnd,       i,j,imm,mod)
> +{
> +	imm = null
> +	mod = null
> +	for (j = 1; j <= count; j++) {
> +		i = opnd[j]
> +		if (match(i, imm_expr) == 1) {
> +			if (!imm_flag[i])
> +				semantic_error("Unknown imm opnd: " i)
> +			if (imm) {
> +				if (i != "Ib")
> +					semantic_error("Second IMM error")
> +				imm = add_flags(imm, "INAT_SCNDIMM")
> +			} else
> +				imm = imm_flag[i]
> +		} else if (match(i, modrm_expr))
> +			mod = "INAT_MODRM"
> +	}
> +	return add_flags(imm, mod)
> +}
> +
> +/^[0-9a-f]+\:/ {
> +	if (NR == 1)
> +		next
> +	# get index
> +	idx = "0x" substr($1, 1, index($1,":") - 1)
> +	if (idx in table)
> +		semantic_error("Redefine " idx " in " tname)
> +
> +	# check if escaped opcode
> +	if ("escape" == $2) {
> +		if ($3 != "#")
> +			semantic_error("No escaped name")
> +		ref = ""
> +		for (i = 4; i <= NF; i++)
> +			ref = ref $i
> +		if (ref in escape)
> +			semantic_error("Redefine escape (" ref ")")
> +		escape[ref] = geid
> +		geid++
> +		table[idx] = "INAT_MAKE_ESCAPE(" escape[ref] ")"
> +		next
> +	}
> +
> +	variant = null
> +	# converts
> +	i = 2
> +	while (i <= NF) {
> +		opcode = $(i++)
> +		delete opnds
> +		ext = null
> +		flags = null
> +		opnd = null
> +		# parse one opcode
> +		if (match($i, opnd_expr)) {
> +			opnd = $i
> +			count = split($(i++), opnds, ",")
> +			flags = convert_operands(count, opnds)
> +		}
> +		if (match($i, ext_expr))
> +			ext = $(i++)
> +		if (match($i, sep_expr))
> +			i++
> +		else if (i < NF)
> +			semantic_error($i " is not a separator")
> +
> +		# check if group opcode
> +		if (match(opcode, group_expr)) {
> +			if (!(opcode in group)) {
> +				group[opcode] = ggid
> +				ggid++
> +			}
> +			flags = add_flags(flags, "INAT_MAKE_GROUP(" group[opcode] ")")
> +		}
> +		# check force(or default) 64bit
> +		if (match(ext, force64_expr))
> +			flags = add_flags(flags, "INAT_FORCE64")
> +
> +		# check REX prefix
> +		if (match(opcode, rex_expr))
> +			flags = add_flags(flags, "INAT_MAKE_PREFIX(INAT_PFX_REX)")
> +
> +		# check coprocessor escape : TODO
> +		if (match(opcode, fpu_expr))
> +			flags = add_flags(flags, "INAT_MODRM")
> +
> +		# check VEX codes
> +		if (match(ext, vexonly_expr))
> +			flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY")
> +		else if (match(ext, vexok_expr) || match(opcode, vexok_opcode_expr))
> +			flags = add_flags(flags, "INAT_VEXOK")
> +
> +		# check prefixes
> +		if (match(ext, prefix_expr)) {
> +			if (!prefix_num[opcode])
> +				semantic_error("Unknown prefix: " opcode)
> +			flags = add_flags(flags, "INAT_MAKE_PREFIX(" prefix_num[opcode] ")")
> +		}
> +		if (length(flags) == 0)
> +			continue
> +		# check if last prefix
> +		if (match(ext, lprefix1_expr)) {
> +			lptable1[idx] = add_flags(lptable1[idx],flags)
> +			variant = "INAT_VARIANT"
> +		}
> +		if (match(ext, lprefix2_expr)) {
> +			lptable2[idx] = add_flags(lptable2[idx],flags)
> +			variant = "INAT_VARIANT"
> +		}
> +		if (match(ext, lprefix3_expr)) {
> +			lptable3[idx] = add_flags(lptable3[idx],flags)
> +			variant = "INAT_VARIANT"
> +		}
> +		if (!match(ext, lprefix_expr)){
> +			table[idx] = add_flags(table[idx],flags)
> +		}
> +	}
> +	if (variant)
> +		table[idx] = add_flags(table[idx],variant)
> +}
> +
> +END {
> +	if (awkchecked != "")
> +		exit 1
> +	# print escape opcode map's array
> +	print "/* Escape opcode map array */"
> +	print "static const insn_attr_t * const inat_escape_tables[INAT_ESC_MAX + 1]" \
> +	      "[INAT_LSTPFX_MAX + 1] = {"
> +	for (i = 0; i < geid; i++)
> +		for (j = 0; j < max_lprefix; j++)
> +			if (etable[i,j])
> +				print "    ["i"]["j"] = "etable[i,j]","
> +	print "};\n"
> +	# print group opcode map's array
> +	print "/* Group opcode map array */"
> +	print "static const insn_attr_t * const inat_group_tables[INAT_GRP_MAX + 1]"\
> +	      "[INAT_LSTPFX_MAX + 1] = {"
> +	for (i = 0; i < ggid; i++)
> +		for (j = 0; j < max_lprefix; j++)
> +			if (gtable[i,j])
> +				print "    ["i"]["j"] = "gtable[i,j]","
> +	print "};\n"
> +	# print AVX opcode map's array
> +	print "/* AVX opcode map array */"
> +	print "static const insn_attr_t * const inat_avx_tables[X86_VEX_M_MAX + 1]"\
> +	      "[INAT_LSTPFX_MAX + 1] = {"
> +	for (i = 0; i < gaid; i++)
> +		for (j = 0; j < max_lprefix; j++)
> +			if (atable[i,j])
> +				print "    ["i"]["j"] = "atable[i,j]","
> +	print "};"
> +}

-- 
Mihai Donțu

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/3] x86: add support for computing the instruction length
  2014-09-09  8:47   ` Mihai Donțu
@ 2014-09-09  9:44     ` Mihai Donțu
  2014-09-09 10:13       ` Masami Hiramatsu
  0 siblings, 1 reply; 21+ messages in thread
From: Mihai Donțu @ 2014-09-09  9:44 UTC (permalink / raw)
  To: Masami Hiramatsu; +Cc: xen-devel, keir, jbeulich, Razvan Cojocaru

On Tue, 9 Sep 2014 11:47:05 +0300 Mihai Donțu wrote:
> On Tuesday 09 September 2014 05:28:02 Mihai Donțu wrote:
> > This patch adds support for computing the length of an instruction. The entire
> > logic relies on a set of opcode tables generated by gen-insn-attr-x86.awk from
> > x86-opcode-map.txt and a number of small helper functions. It originated in
> > Linux, where it was added by Masami Hiramatsu. Since it's an almost identical
> > copy, it's separated from the x86 emulator, simplifying future updates.
> > 
> > ---
> > Changed since v1:
> >   * adjusted the coding style to match the rest of xen
> >   * moved the source files into x86/x86_emulate
> >   * replaced inat-tables.c with x86-opcode-map.txt and gen-insn-attr-x86.awk
> >     that are used to generate it
> > 
> > Signed-off-by: Mihai Donțu <mdontu@bitdefender.com>
> 
> There are a couple of design issues with this code which Jan pointed
> out and which I overlooked. I'm sorry, it was not intentional. I'll do
> my best to address them in a following email.

I'd like to give it a try at saving some time by asking the author
behind the Linux code what is his opinion on this.

Masami, I'm trying to bring to xen the code you wrote for Linux a while
back and which uses an opcode map, a script and some helper functions
(insn.c, inat.c) to compute an instruction's length. Jan has made some
observations which I believe would be of interest to the kernel
developers as well. Please see:

http://lists.xenproject.org/archives/html/xen-devel/2014-07/msg00375.html

While valid, would they affect the overall goal of insn_get_length() or
is that function tuned for a specific use case? I can't yet tell for
sure if we can get away with it.

Thanks,

-- 
Mihai Donțu

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 0/3] xen: add support for skipping the current instruction
  2014-09-09  2:22 [PATCH 0/3] xen: add support for skipping the current instruction Mihai Donțu
                   ` (2 preceding siblings ...)
  2014-09-09  2:32 ` [PATCH 3/3] xen/tools: script for automatically adjusting the coding style to xen style Mihai Donțu
@ 2014-09-09  9:47 ` Jan Beulich
  2014-09-09 17:00   ` Mihai Donțu
  3 siblings, 1 reply; 21+ messages in thread
From: Jan Beulich @ 2014-09-09  9:47 UTC (permalink / raw)
  To: Mihai Donțu; +Cc: xen-devel

>>> On 09.09.14 at 04:22, <mdontu@bitdefender.com> wrote:
> Răzvan Cojocaru has posted a patch in July that added support for
> computing the length of the instruction that generated the VMEXIT:
> 
> http://lists.xen.org/archives/html/xen-devel/2014-07/msg00314.html 
> 
> which he then split into two in order to give himself more time to
> think about Andrew's proposal to extend the existent x86 emulator. I
> offered to take that off his hands as he was already working to get
> several patches in.
> 
> The initial code was an almost verbatim copy from Linux, with a very
> small change to make it compile within xen (replaced 'asm/string.h'
> with 'xen/string.h').
> 
> I spent some time to determine what the code save would be if we were
> to make use of existent xen functionality and my first impression is
> that the increase in complexity of an already very complex machinery
> (caused by both the nature of the architecture and by the design of the
> emulator itself) would not make it worthwhile.
> 
> The starting point would be x86_emulate() which uses a carefully coded
> switch() to walk through the opcode groups, but it only covers a subset
> of those and, obviously, expects one to add not just instruction length
> calculation (ie. next eip/rip) but also _actual_ emulation to which I
> don't think anyone can commit given the architecture complexity (think
> MMX, SSEn, AVXn etc). The opportunity for bugs makes this task rather
> prohibitive.

I disagree, for two reasons: First, there's no reason to implement full
emulation for everything as long as there's a way for the caller to
know whether actual emulation (rather than just instruction boundary
determination) did happen. And second, as recently also pointed out
by Andrew, making full emulation (including very recent additions like
AVX-512) a goal would likely be of more than just theoretical value
(allowing emergency migration of guests to less capable hosts without
prior CPU feature leveling). Plus - as long as those newer extensions
could be emulated in ways similar by how the FPU instructions get
dealt with, I think the scope for bugs can be meaningfully reduced.

> Masami Hiramatsu, the author of the Linux code, most likely came to the
> same realization and used a rather simple approach: created
> x86-opcode-map.txt in which he simply lists the opcode classes in a
> fairly human readable way. Then he uses an awk script to generate the
> core of the machinery to which he added a couple of helper functions. I
> decided to keep this part and see if I can replace some of the helpers,
> but aside insn_fetch_bytes() which relies on previous calculations made
> in x86_emulate(), I wasn't able to identify any other code-reuse
> opportunities. Also, I don't yet have the courage to shuffle code
> around in x86_emulate.c. :-)
> 
> In conclusion, I would opt to bring Masami's code in with very little
> changes possible (other than coding style which can be handled by a
> script) so that future updates can be easily ported to xen.
> 
> What follows are three patches:
>   1. adds Masami's et al code (insn_get_length());
>   2. adds a user in emulate.c;
>   3. a clang-format script that can be used to do the bulk of the
>   coding style work on the imported files (should someone else other
>   than me were to do it).
> 
> The motivation behind the 'instruction skipping' idea is to allow
> memory introspection technologies to instruct Xen to jump over
> instructions that reside in memory areas of the guest that are marked
> as NX in EPT (eg. heap/stack of user processes). In such situations,
> maintaining the vCPU register state is not needed and, as a bonus,
> expedites the termination of the in-guest process that attempted to
> execute the code.

Leaving open why terminating the in-guest process requires advancing
its IP then, if all other register updates are unnecessary. A huge chunk
of source code like this needs - I think - a little more of a rationale than
some exotic, only partially explained use case.

Jan

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/3] x86: add support for computing the instruction length
  2014-09-09  9:44     ` Mihai Donțu
@ 2014-09-09 10:13       ` Masami Hiramatsu
  2014-09-09 15:46         ` Mihai Donțu
  0 siblings, 1 reply; 21+ messages in thread
From: Masami Hiramatsu @ 2014-09-09 10:13 UTC (permalink / raw)
  To: Mihai Donțu; +Cc: xen-devel, keir, jbeulich, Razvan Cojocaru

Hello,

(2014/09/09 18:44), Mihai Donțu wrote:
> On Tue, 9 Sep 2014 11:47:05 +0300 Mihai Donțu wrote:
>> On Tuesday 09 September 2014 05:28:02 Mihai Donțu wrote:
>>> This patch adds support for computing the length of an instruction. The entire
>>> logic relies on a set of opcode tables generated by gen-insn-attr-x86.awk from
>>> x86-opcode-map.txt and a number of small helper functions. It originated in
>>> Linux, where it was added by Masami Hiramatsu. Since it's an almost identical
>>> copy, it's separated from the x86 emulator, simplifying future updates.
>>>
>>> ---
>>> Changed since v1:
>>>   * adjusted the coding style to match the rest of xen
>>>   * moved the source files into x86/x86_emulate
>>>   * replaced inat-tables.c with x86-opcode-map.txt and gen-insn-attr-x86.awk
>>>     that are used to generate it
>>>
>>> Signed-off-by: Mihai Donțu <mdontu@bitdefender.com>
>>
>> There are a couple of design issues with this code which Jan pointed
>> out and which I overlooked. I'm sorry, it was not intentional. I'll do
>> my best to address them in a following email.
> 
> I'd like to give it a try at saving some time by asking the author
> behind the Linux code what is his opinion on this.
> 
> Masami, I'm trying to bring to xen the code you wrote for Linux a while
> back and which uses an opcode map, a script and some helper functions
> (insn.c, inat.c) to compute an instruction's length. Jan has made some
> observations which I believe would be of interest to the kernel
> developers as well. Please see:
> 
> http://lists.xenproject.org/archives/html/xen-devel/2014-07/msg00375.html

Ah, thanks for the comments!

> 
> While valid, would they affect the overall goal of insn_get_length() or
> is that function tuned for a specific use case? I can't yet tell for
> sure if we can get away with it.

Actually, in the Linux kernel, currently we use this just for decoding the
length and searching branches. Thus, strict decoding is not needed (moreover,
I have a request to optimize it only for that purpose for speeding up).
But I think it is better to integrate several different decoders in kernel too.
So your comments are very useful for me! :)

Thank you!

> 
> Thanks,
> 


-- 
Masami HIRAMATSU
Software Platform Research Dept. Linux Technology Research Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: masami.hiramatsu.pt@hitachi.com



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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 3/3] xen/tools: script for automatically adjusting the coding style to xen style
  2014-09-09  2:32 ` [PATCH 3/3] xen/tools: script for automatically adjusting the coding style to xen style Mihai Donțu
@ 2014-09-09 14:50   ` Ian Campbell
  2014-09-09 15:00     ` Andrew Cooper
                       ` (2 more replies)
  2014-09-10 14:21   ` Don Slutz
  1 sibling, 3 replies; 21+ messages in thread
From: Ian Campbell @ 2014-09-09 14:50 UTC (permalink / raw)
  To: Mihai Donțu; +Cc: Tim Deegan, xen-devel, keir, Jan Beulich, Don Slutz

On Tue, 2014-09-09 at 05:32 +0300, Mihai Donțu wrote:
> This is a clang-format wrapper script that can be used to do the bulk of the
> coding style work on a foreign source file. It is not yet complete, but it's
> sufficient for 98% of the cases.

I think a lot of people would like to have something along these lines
available. Don also proposed something recently, see [0]. Not sure what
the hypervisor maintainers opinion is though, I've CCd a few for input.

I've no prior experience with either clang-format or astyle so I don't
know which is better, but I do like that clang-format doesn't need a
second pass in emacs (despite being an emacs user).

Ian.

[0] http://lists.xen.org/archives/html/xen-devel/2014-09/msg00918.html

> 
> Signed-off-by: Mihai Donțu <mdontu@bitdefender.com>
> ---
>  xen/tools/xen-indent | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 77 insertions(+)
>  create mode 100755 xen/tools/xen-indent
> 
> diff --git a/xen/tools/xen-indent b/xen/tools/xen-indent
> new file mode 100755
> index 0000000..6be507c
> --- /dev/null
> +++ b/xen/tools/xen-indent
> @@ -0,0 +1,77 @@
> +#!/bin/sh
> +
> +CLANG_FORMAT=`which clang-format 2>/dev/null`
> +
> +if [ "x$CLANG_FORMAT" = "x" ]; then
> +	printf "Error: \`clang-format' is not installed. It is usually part of clang (3.4 and newer)\n" >&2
> +	exit 1
> +fi
> +
> +if [ "x$1" = "x" ]; then
> +	printf "Usage: $0 <file[s]>\n"
> +	exit 2
> +fi
> +
> +for i in $@; do
> +	DN=`dirname "$i"`
> +	cat >"$DN/.clang-format" <<EOF
> +---
> +AccessModifierOffset:                           -8
> +IndentWidth:                                    4
> +TabWidth:                                       4
> +ConstructorInitializerIndentWidth:              4
> +AlignEscapedNewlinesLeft:                       true
> +AlignTrailingComments:                          true
> +AllowAllParametersOfDeclarationOnNextLine:      true
> +AllowShortIfStatementsOnASingleLine:            false
> +AllowShortLoopsOnASingleLine:                   false
> +AllowShortFunctionsOnASingleLine:               false
> +AlwaysBreakTemplateDeclarations:                false
> +AlwaysBreakBeforeMultilineStrings:              false
> +BreakBeforeBinaryOperators:                     false
> +BreakBeforeTernaryOperators:                    true
> +BreakConstructorInitializersBeforeComma:        false
> +BinPackParameters:                              true
> +ColumnLimit:                                    80
> +ConstructorInitializerAllOnOneLineOrOnePerLine: false
> +DerivePointerBinding:                           false
> +ExperimentalAutoDetectBinPacking:               false
> +IndentCaseLabels:                               false
> +MaxEmptyLinesToKeep:                            1
> +NamespaceIndentation:                           All
> +ObjCSpaceBeforeProtocolList:                    true
> +PenaltyBreakBeforeFirstCallParameter:           19
> +PenaltyBreakComment:                            60
> +PenaltyBreakString:                             1000
> +PenaltyBreakFirstLessLess:                      120
> +PenaltyExcessCharacter:                         1000000
> +PenaltyReturnTypeOnItsOwnLine:                  60
> +PointerBindsToType:                             false
> +SpacesBeforeTrailingComments:                   1
> +Cpp11BracedListStyle:                           false
> +Standard:                                       Cpp11
> +UseTab:                                         Never
> +BreakBeforeBraces:                              Allman
> +IndentFunctionDeclarationAfterType:             false
> +SpaceBeforeParens:                              ControlStatements
> +SpacesInParentheses:                            false
> +SpacesInAngles:                                 false
> +SpaceInEmptyParentheses:                        false
> +SpacesInCStyleCastParentheses:                  false
> +SpaceAfterControlStatementKeyword:              true
> +SpaceBeforeAssignmentOperators:                 true
> +ContinuationIndentWidth:                        4
> +EOF
> +	ERR=0
> +	$CLANG_FORMAT "$i" >"${i}.clang-tmp" || ERR=1
> +	rm -f "$DN/.clang-format"
> +	if [ $ERR -ne 0 ]; then
> +		rm -f "${i}.clang-tmp"
> +		exit 3
> +	fi
> +	sed 's#if\s*(\(.*\))#if ( \1 )#m' "${i}.clang-tmp" >"${i}.clang-tmp.1"
> +	sed 's#switch\s*(\(.*\))#switch ( \1 )#m' "${i}.clang-tmp.1" >"${i}.clang-tmp.2"
> +	sed 's#while\s*(\(.*\))#while ( \1 )#m' "${i}.clang-tmp.2" >"${i}.clang-tmp.3"
> +	mv -f "${i}.clang-tmp.3" "${i}"
> +	rm -f "${i}.clang-tmp" "${i}.clang-tmp.1" "${i}.clang-tmp.2"
> +done



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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 3/3] xen/tools: script for automatically adjusting the coding style to xen style
  2014-09-09 14:50   ` Ian Campbell
@ 2014-09-09 15:00     ` Andrew Cooper
  2014-09-09 19:52     ` Tim Deegan
  2014-09-10 10:59     ` Don Slutz
  2 siblings, 0 replies; 21+ messages in thread
From: Andrew Cooper @ 2014-09-09 15:00 UTC (permalink / raw)
  To: Ian Campbell, Mihai Donțu
  Cc: keir, xen-devel, Tim Deegan, Don Slutz, Jan Beulich

On 09/09/14 15:50, Ian Campbell wrote:
> On Tue, 2014-09-09 at 05:32 +0300, Mihai Donțu wrote:
>> This is a clang-format wrapper script that can be used to do the bulk of the
>> coding style work on a foreign source file. It is not yet complete, but it's
>> sufficient for 98% of the cases.
> I think a lot of people would like to have something along these lines
> available. Don also proposed something recently, see [0]. Not sure what
> the hypervisor maintainers opinion is though, I've CCd a few for input.
>
> I've no prior experience with either clang-format or astyle so I don't
> know which is better, but I do like that clang-format doesn't need a
> second pass in emacs (despite being an emacs user).
>
> Ian.
>
> [0] http://lists.xen.org/archives/html/xen-devel/2014-09/msg00918.html

I have no experience with either, but +1 for the principle.  It would
vastly ease certain reviews with a single reference to how to correctly
format for Xen style.

The problem with Xen itself is working out which files have Linux style,
which have Xen style and which are currently a mix of the two, and which
are neither.

The problem could possibly be solved by a grepable tag in the emacs
style block?

~Andrew


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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/3] x86: add support for computing the instruction length
  2014-09-09 10:13       ` Masami Hiramatsu
@ 2014-09-09 15:46         ` Mihai Donțu
  2014-09-09 16:01           ` Mihai Donțu
  0 siblings, 1 reply; 21+ messages in thread
From: Mihai Donțu @ 2014-09-09 15:46 UTC (permalink / raw)
  To: Masami Hiramatsu; +Cc: xen-devel, keir, jbeulich, Razvan Cojocaru

On Tuesday 09 September 2014 19:13:26 Masami Hiramatsu wrote:
> Hello,
> 
> (2014/09/09 18:44), Mihai Donțu wrote:
> > On Tue, 9 Sep 2014 11:47:05 +0300 Mihai Donțu wrote:
> >> On Tuesday 09 September 2014 05:28:02 Mihai Donțu wrote:
> >>> This patch adds support for computing the length of an instruction. The entire
> >>> logic relies on a set of opcode tables generated by gen-insn-attr-x86.awk from
> >>> x86-opcode-map.txt and a number of small helper functions. It originated in
> >>> Linux, where it was added by Masami Hiramatsu. Since it's an almost identical
> >>> copy, it's separated from the x86 emulator, simplifying future updates.
> >>>
> >>> ---
> >>> Changed since v1:
> >>>   * adjusted the coding style to match the rest of xen
> >>>   * moved the source files into x86/x86_emulate
> >>>   * replaced inat-tables.c with x86-opcode-map.txt and gen-insn-attr-x86.awk
> >>>     that are used to generate it
> >>>
> >>> Signed-off-by: Mihai Donțu <mdontu@bitdefender.com>
> >>
> >> There are a couple of design issues with this code which Jan pointed
> >> out and which I overlooked. I'm sorry, it was not intentional. I'll do
> >> my best to address them in a following email.
> > 
> > I'd like to give it a try at saving some time by asking the author
> > behind the Linux code what is his opinion on this.
> > 
> > Masami, I'm trying to bring to xen the code you wrote for Linux a while
> > back and which uses an opcode map, a script and some helper functions
> > (insn.c, inat.c) to compute an instruction's length. Jan has made some
> > observations which I believe would be of interest to the kernel
> > developers as well. Please see:
> > 
> > http://lists.xenproject.org/archives/html/xen-devel/2014-07/msg00375.html
> 
> Ah, thanks for the comments!
> 
> > 
> > While valid, would they affect the overall goal of insn_get_length() or
> > is that function tuned for a specific use case? I can't yet tell for
> > sure if we can get away with it.
> 
> Actually, in the Linux kernel, currently we use this just for decoding the
> length and searching branches. Thus, strict decoding is not needed (moreover,
> I have a request to optimize it only for that purpose for speeding up).
> But I think it is better to integrate several different decoders in kernel too.
> So your comments are very useful for me! :)

Thank you Masami, that's the exact same use case we plan for it too: to
solely compute the instruction length. This, I hope, dispels any
concerns regarding its functionality and whether it does what it's
supposed to do correctly.

-- 
Mihai Donțu

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/3] x86: add support for computing the instruction length
  2014-09-09 15:46         ` Mihai Donțu
@ 2014-09-09 16:01           ` Mihai Donțu
  2014-09-09 16:25             ` Jan Beulich
  0 siblings, 1 reply; 21+ messages in thread
From: Mihai Donțu @ 2014-09-09 16:01 UTC (permalink / raw)
  To: xen-devel; +Cc: keir, jbeulich, Razvan Cojocaru

On Tuesday 09 September 2014 18:46:30 Mihai Donțu wrote:
> On Tuesday 09 September 2014 19:13:26 Masami Hiramatsu wrote:
> > Hello,
> > 
> > (2014/09/09 18:44), Mihai Donțu wrote:
> > > On Tue, 9 Sep 2014 11:47:05 +0300 Mihai Donțu wrote:
> > >> On Tuesday 09 September 2014 05:28:02 Mihai Donțu wrote:
> > >>> This patch adds support for computing the length of an instruction. The entire
> > >>> logic relies on a set of opcode tables generated by gen-insn-attr-x86.awk from
> > >>> x86-opcode-map.txt and a number of small helper functions. It originated in
> > >>> Linux, where it was added by Masami Hiramatsu. Since it's an almost identical
> > >>> copy, it's separated from the x86 emulator, simplifying future updates.
> > >>>
> > >>> ---
> > >>> Changed since v1:
> > >>>   * adjusted the coding style to match the rest of xen
> > >>>   * moved the source files into x86/x86_emulate
> > >>>   * replaced inat-tables.c with x86-opcode-map.txt and gen-insn-attr-x86.awk
> > >>>     that are used to generate it
> > >>>
> > >>> Signed-off-by: Mihai Donțu <mdontu@bitdefender.com>
> > >>
> > >> There are a couple of design issues with this code which Jan pointed
> > >> out and which I overlooked. I'm sorry, it was not intentional. I'll do
> > >> my best to address them in a following email.
> > > 
> > > I'd like to give it a try at saving some time by asking the author
> > > behind the Linux code what is his opinion on this.
> > > 
> > > Masami, I'm trying to bring to xen the code you wrote for Linux a while
> > > back and which uses an opcode map, a script and some helper functions
> > > (insn.c, inat.c) to compute an instruction's length. Jan has made some
> > > observations which I believe would be of interest to the kernel
> > > developers as well. Please see:
> > > 
> > > http://lists.xenproject.org/archives/html/xen-devel/2014-07/msg00375.html
> > 
> > Ah, thanks for the comments!
> > 
> > > 
> > > While valid, would they affect the overall goal of insn_get_length() or
> > > is that function tuned for a specific use case? I can't yet tell for
> > > sure if we can get away with it.
> > 
> > Actually, in the Linux kernel, currently we use this just for decoding the
> > length and searching branches. Thus, strict decoding is not needed (moreover,
> > I have a request to optimize it only for that purpose for speeding up).
> > But I think it is better to integrate several different decoders in kernel too.
> > So your comments are very useful for me! :)
> 
> Thank you Masami, that's the exact same use case we plan for it too: to
> solely compute the instruction length. This, I hope, dispels any
> concerns regarding its functionality and whether it does what it's
> supposed to do correctly.

I've opted to send a new mail so I can remove Masami from CC, as he's
probably not interested in the rest of the conversation.

Right now we have two patches which work around x86/emulator
limitations:

 * one computes the instruction length;
 * the other uses single stepping to jump over unsupported instructions;

Adding support for the complete x86(_64) instruction set to the
existent emulator in Xen would make those two unneeded and while I
would like to try my hand at it, I'm not sure the effort would be pay
off. Not to mention that I would very much like to _somehow_ catch the
4.5 deadline. I wonder if it's possible to do this in iterations: take
this (or a decent derivation of it) in, while Răzvan and I work on doing
a better work for 4.6. Am I pushing it? :-)

-- 
Mihai Donțu

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/3] x86: add support for computing the instruction length
  2014-09-09 16:01           ` Mihai Donțu
@ 2014-09-09 16:25             ` Jan Beulich
  2014-09-09 17:14               ` Andrew Cooper
                                 ` (2 more replies)
  0 siblings, 3 replies; 21+ messages in thread
From: Jan Beulich @ 2014-09-09 16:25 UTC (permalink / raw)
  To: Mihai Donțu; +Cc: xen-devel, keir, Razvan Cojocaru

>>> On 09.09.14 at 18:01, <mdontu@bitdefender.com> wrote:
> I've opted to send a new mail so I can remove Masami from CC, as he's
> probably not interested in the rest of the conversation.
> 
> Right now we have two patches which work around x86/emulator
> limitations:
> 
>  * one computes the instruction length;
>  * the other uses single stepping to jump over unsupported instructions;
> 
> Adding support for the complete x86(_64) instruction set to the
> existent emulator in Xen would make those two unneeded and while I
> would like to try my hand at it, I'm not sure the effort would be pay
> off. Not to mention that I would very much like to _somehow_ catch the
> 4.5 deadline. I wonder if it's possible to do this in iterations: take
> this (or a decent derivation of it) in, while Răzvan and I work on doing
> a better work for 4.6. Am I pushing it? :-)

Personally I don't think this makes sense to push for 4.5, but in the
end it'll be Konrad's call. We already have enough other half-way
reviewed patch series that need finalizing, so I don't think this series
(which was posted just once many weeks ago) is a candidate.
Furthermore I'm rather unconvinced of this being code useful to
other than just your product. And finally, we had (with other
submitters) some bad experience in the past taking what they
promised they would clean up later.

Jan

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 0/3] xen: add support for skipping the current instruction
  2014-09-09  9:47 ` [PATCH 0/3] xen: add support for skipping the current instruction Jan Beulich
@ 2014-09-09 17:00   ` Mihai Donțu
  2014-09-09 18:58     ` Tamas K Lengyel
  0 siblings, 1 reply; 21+ messages in thread
From: Mihai Donțu @ 2014-09-09 17:00 UTC (permalink / raw)
  To: Jan Beulich; +Cc: xen-devel

On Tuesday 09 September 2014 10:47:43 Jan Beulich wrote:
> >>> On 09.09.14 at 04:22, <mdontu@bitdefender.com> wrote:
> > Răzvan Cojocaru has posted a patch in July that added support for
> > computing the length of the instruction that generated the VMEXIT:
> > 
> > http://lists.xen.org/archives/html/xen-devel/2014-07/msg00314.html 
> > 
> > which he then split into two in order to give himself more time to
> > think about Andrew's proposal to extend the existent x86 emulator. I
> > offered to take that off his hands as he was already working to get
> > several patches in.
> > 
> > The initial code was an almost verbatim copy from Linux, with a very
> > small change to make it compile within xen (replaced 'asm/string.h'
> > with 'xen/string.h').
> > 
> > I spent some time to determine what the code save would be if we were
> > to make use of existent xen functionality and my first impression is
> > that the increase in complexity of an already very complex machinery
> > (caused by both the nature of the architecture and by the design of the
> > emulator itself) would not make it worthwhile.
> > 
> > The starting point would be x86_emulate() which uses a carefully coded
> > switch() to walk through the opcode groups, but it only covers a subset
> > of those and, obviously, expects one to add not just instruction length
> > calculation (ie. next eip/rip) but also _actual_ emulation to which I
> > don't think anyone can commit given the architecture complexity (think
> > MMX, SSEn, AVXn etc). The opportunity for bugs makes this task rather
> > prohibitive.
> 
> I disagree, for two reasons: First, there's no reason to implement full
> emulation for everything as long as there's a way for the caller to
> know whether actual emulation (rather than just instruction boundary
> determination) did happen. And second, as recently also pointed out
> by Andrew, making full emulation (including very recent additions like
> AVX-512) a goal would likely be of more than just theoretical value
> (allowing emergency migration of guests to less capable hosts without
> prior CPU feature leveling). Plus - as long as those newer extensions
> could be emulated in ways similar by how the FPU instructions get
> dealt with, I think the scope for bugs can be meaningfully reduced.

I'm looking at emulate_fpu_insn(). Took me a bit to understand the
trick behind it: it doesn't do full emulation just advances the %rip.
Mmm.

> > Masami Hiramatsu, the author of the Linux code, most likely came to the
> > same realization and used a rather simple approach: created
> > x86-opcode-map.txt in which he simply lists the opcode classes in a
> > fairly human readable way. Then he uses an awk script to generate the
> > core of the machinery to which he added a couple of helper functions. I
> > decided to keep this part and see if I can replace some of the helpers,
> > but aside insn_fetch_bytes() which relies on previous calculations made
> > in x86_emulate(), I wasn't able to identify any other code-reuse
> > opportunities. Also, I don't yet have the courage to shuffle code
> > around in x86_emulate.c. :-)
> > 
> > In conclusion, I would opt to bring Masami's code in with very little
> > changes possible (other than coding style which can be handled by a
> > script) so that future updates can be easily ported to xen.
> > 
> > What follows are three patches:
> >   1. adds Masami's et al code (insn_get_length());
> >   2. adds a user in emulate.c;
> >   3. a clang-format script that can be used to do the bulk of the
> >   coding style work on the imported files (should someone else other
> >   than me were to do it).
> > 
> > The motivation behind the 'instruction skipping' idea is to allow
> > memory introspection technologies to instruct Xen to jump over
> > instructions that reside in memory areas of the guest that are marked
> > as NX in EPT (eg. heap/stack of user processes). In such situations,
> > maintaining the vCPU register state is not needed and, as a bonus,
> > expedites the termination of the in-guest process that attempted to
> > execute the code.
> 
> Leaving open why terminating the in-guest process requires advancing
> its IP then, if all other register updates are unnecessary. A huge chunk
> of source code like this needs - I think - a little more of a rationale than
> some exotic, only partially explained use case.

Essentially, instruction skipping is an alternative to
'emulate-no-write'. All it offers is a speed boost, which is noticeable
when, for example, the emulator is walking a piece of code located into
an NX-marked memory area (stack, for example). With emulation, it takes
a long time for an application which has been exploited to terminate
(some types of malware try in a forever-loop to write to the memory
areas they target).

Now, given the tight schedule for 4.5 feature merges of which both
you and Ian talked, I think I'm going to hold this patch for now. It is
not an essential part of memory introspection, but rather an
improvement and it can wait a bit longer.

Thanks,

-- 
Mihai Donțu

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/3] x86: add support for computing the instruction length
  2014-09-09 16:25             ` Jan Beulich
@ 2014-09-09 17:14               ` Andrew Cooper
  2014-09-09 17:27               ` Mihai Donțu
  2014-09-09 17:57               ` Konrad Rzeszutek Wilk
  2 siblings, 0 replies; 21+ messages in thread
From: Andrew Cooper @ 2014-09-09 17:14 UTC (permalink / raw)
  To: Mihai Donțu; +Cc: xen-devel, keir, Razvan Cojocaru, Jan Beulich

On 09/09/14 17:25, Jan Beulich wrote:
>>>> On 09.09.14 at 18:01, <mdontu@bitdefender.com> wrote:
>> I've opted to send a new mail so I can remove Masami from CC, as he's
>> probably not interested in the rest of the conversation.
>>
>> Right now we have two patches which work around x86/emulator
>> limitations:
>>
>>  * one computes the instruction length;
>>  * the other uses single stepping to jump over unsupported instructions;
>>
>> Adding support for the complete x86(_64) instruction set to the
>> existent emulator in Xen would make those two unneeded and while I
>> would like to try my hand at it, I'm not sure the effort would be pay
>> off. Not to mention that I would very much like to _somehow_ catch the
>> 4.5 deadline. I wonder if it's possible to do this in iterations: take
>> this (or a decent derivation of it) in, while Răzvan and I work on doing
>> a better work for 4.6. Am I pushing it? :-)
> Personally I don't think this makes sense to push for 4.5, but in the
> end it'll be Konrad's call. We already have enough other half-way
> reviewed patch series that need finalizing, so I don't think this series
> (which was posted just once many weeks ago) is a candidate.
> Furthermore I'm rather unconvinced of this being code useful to
> other than just your product. And finally, we had (with other
> submitters) some bad experience in the past taking what they
> promised they would clean up later.

I would agree that pushing for 4.5 is unlikely to happen.  I would
suggest that your efforts would be be better spent getting a high
quality series for 4.6 sorted.

As for the instruction length itself, that could be sorted in a more
generic way.

One issue with the current x86_emulate() is that it mixes instruction
decode with instruction emulation.  The AMD SVM code already has a
partial instruction length checker for certain cases where hardware
support is lacking.

It seems plausible to split instruction decode and instruction emulate
into two distinct steps.  This would allow easier unit testing of each
step (always a good thing), and for the instruction decode to be used
independently of emulation.

~Andrew


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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/3] x86: add support for computing the instruction length
  2014-09-09 16:25             ` Jan Beulich
  2014-09-09 17:14               ` Andrew Cooper
@ 2014-09-09 17:27               ` Mihai Donțu
  2014-09-09 17:57               ` Konrad Rzeszutek Wilk
  2 siblings, 0 replies; 21+ messages in thread
From: Mihai Donțu @ 2014-09-09 17:27 UTC (permalink / raw)
  To: Jan Beulich; +Cc: xen-devel, keir, Razvan Cojocaru

On Tuesday 09 September 2014 17:25:58 Jan Beulich wrote:
> >>> On 09.09.14 at 18:01, <mdontu@bitdefender.com> wrote:
> > I've opted to send a new mail so I can remove Masami from CC, as he's
> > probably not interested in the rest of the conversation.
> > 
> > Right now we have two patches which work around x86/emulator
> > limitations:
> > 
> >  * one computes the instruction length;
> >  * the other uses single stepping to jump over unsupported instructions;
> > 
> > Adding support for the complete x86(_64) instruction set to the
> > existent emulator in Xen would make those two unneeded and while I
> > would like to try my hand at it, I'm not sure the effort would be pay
> > off. Not to mention that I would very much like to _somehow_ catch the
> > 4.5 deadline. I wonder if it's possible to do this in iterations: take
> > this (or a decent derivation of it) in, while Răzvan and I work on doing
> > a better work for 4.6. Am I pushing it? :-)
> 
> Personally I don't think this makes sense to push for 4.5, but in the
> end it'll be Konrad's call. We already have enough other half-way
> reviewed patch series that need finalizing, so I don't think this series
> (which was posted just once many weeks ago) is a candidate.
> Furthermore I'm rather unconvinced of this being code useful to
> other than just your product.

I don't know how to dispel this belief, which I think comes from the
fact that currently we appear to be the only security vendor to open
source at least a part of our work on using hypervisors as a security
tool (at least in this fashion). Our end goal is to create a generic
interface which anyone can use to do what we are proposing and put the
effort into building a technology on top of it so that we can say for
certain what such an interface should offer. If either my or Răzvan's
suggestions/needs look specific, it's only because no one else outside
Bitdefender spoke out (and I know of a few who are silently following
this thread).

> And finally, we had (with other submitters) some bad experience in the
> past taking what they promised they would clean up later.

Fair enough.

-- 
Mihai Donțu

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/3] x86: add support for computing the instruction length
  2014-09-09 16:25             ` Jan Beulich
  2014-09-09 17:14               ` Andrew Cooper
  2014-09-09 17:27               ` Mihai Donțu
@ 2014-09-09 17:57               ` Konrad Rzeszutek Wilk
  2 siblings, 0 replies; 21+ messages in thread
From: Konrad Rzeszutek Wilk @ 2014-09-09 17:57 UTC (permalink / raw)
  To: Jan Beulich; +Cc: xen-devel, Mihai Donțu, keir, Razvan Cojocaru

On Tue, Sep 09, 2014 at 05:25:58PM +0100, Jan Beulich wrote:
> >>> On 09.09.14 at 18:01, <mdontu@bitdefender.com> wrote:
> > I've opted to send a new mail so I can remove Masami from CC, as he's
> > probably not interested in the rest of the conversation.
> > 
> > Right now we have two patches which work around x86/emulator
> > limitations:
> > 
> >  * one computes the instruction length;
> >  * the other uses single stepping to jump over unsupported instructions;
> > 
> > Adding support for the complete x86(_64) instruction set to the
> > existent emulator in Xen would make those two unneeded and while I
> > would like to try my hand at it, I'm not sure the effort would be pay
> > off. Not to mention that I would very much like to _somehow_ catch the
> > 4.5 deadline. I wonder if it's possible to do this in iterations: take
> > this (or a decent derivation of it) in, while Răzvan and I work on doing
> > a better work for 4.6. Am I pushing it? :-)
> 
> Personally I don't think this makes sense to push for 4.5, but in the
> end it'll be Konrad's call. We already have enough other half-way

I think that this particular feature - that is - add extra emulation
(or skipping over certain operations) for new opcodes - should be
deferred to Xen 4.6. The reasons are:

 - It is a complex piece of code and there are so many outstanding 
   patches to review and not enough brains to look at all of them.

 - It will take a couple of iterations to get to a high-quality
   that is required and the time to get all of that done within
   the feature window is mighty hard.

 - Spending the next week working 18hrs to get it in and potentially
   missing the deadline - is really frustrating - and I think it
   would be better if this was implemented with a couple of nice
   non-stressfull months instead of days.

> reviewed patch series that need finalizing, so I don't think this series
> (which was posted just once many weeks ago) is a candidate.
> Furthermore I'm rather unconvinced of this being code useful to
> other than just your product. And finally, we had (with other
> submitters) some bad experience in the past taking what they
> promised they would clean up later.
> 
> Jan
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 0/3] xen: add support for skipping the current instruction
  2014-09-09 17:00   ` Mihai Donțu
@ 2014-09-09 18:58     ` Tamas K Lengyel
  0 siblings, 0 replies; 21+ messages in thread
From: Tamas K Lengyel @ 2014-09-09 18:58 UTC (permalink / raw)
  To: Mihai Donțu; +Cc: xen-devel, Jan Beulich


[-- Attachment #1.1: Type: text/plain, Size: 1351 bytes --]

> Leaving open why terminating the in-guest process requires advancing
> > its IP then, if all other register updates are unnecessary. A huge chunk
> > of source code like this needs - I think - a little more of a rationale
> than
> > some exotic, only partially explained use case.
>
> Essentially, instruction skipping is an alternative to
> 'emulate-no-write'. All it offers is a speed boost, which is noticeable
> when, for example, the emulator is walking a piece of code located into
> an NX-marked memory area (stack, for example). With emulation, it takes
> a long time for an application which has been exploited to terminate
> (some types of malware try in a forever-loop to write to the memory
> areas they target).
>

I wonder what the point is in skipping over the code of some code malware
has put on the stack? Wouldn't it likely just end up crashing afterwards
anyway? If your goal is to terminate the offending application, you could
just simply point the process' RIP to a known invalid location to cause an
immediate crash.. If you need to terminate the process cleanly, then you
could use some OS specific knowledge to redirect the execution of the
process, like update RIP to ExitProcess on Windows for example. Of course,
depending on the threat model that may not be acceptable (ExitProcess may
be hooked as well, etc.).

Tamas

[-- Attachment #1.2: Type: text/html, Size: 1720 bytes --]

[-- Attachment #2: Type: text/plain, Size: 126 bytes --]

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 3/3] xen/tools: script for automatically adjusting the coding style to xen style
  2014-09-09 14:50   ` Ian Campbell
  2014-09-09 15:00     ` Andrew Cooper
@ 2014-09-09 19:52     ` Tim Deegan
  2014-09-10 10:59     ` Don Slutz
  2 siblings, 0 replies; 21+ messages in thread
From: Tim Deegan @ 2014-09-09 19:52 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Mihai Don??u, xen-devel, keir, Jan Beulich, Don Slutz

At 15:50 +0100 on 09 Sep (1410274207), Ian Campbell wrote:
> On Tue, 2014-09-09 at 05:32 +0300, Mihai Don??u wrote:
> > This is a clang-format wrapper script that can be used to do the bulk of the
> > coding style work on a foreign source file. It is not yet complete, but it's
> > sufficient for 98% of the cases.
> 
> I think a lot of people would like to have something along these lines
> available. Don also proposed something recently, see [0]. Not sure what
> the hypervisor maintainers opinion is though, I've CCd a few for input.
> 
> I've no prior experience with either clang-format or astyle so I don't
> know which is better, but I do like that clang-format doesn't need a
> second pass in emacs (despite being an emacs user).

Yes please to any tool like this.  As long as it's even vaguely
usable, AFAIC whoever's wililng to put in the time to make the script
gets to pick the tool. :)

Tim.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 3/3] xen/tools: script for automatically adjusting the coding style to xen style
  2014-09-09 14:50   ` Ian Campbell
  2014-09-09 15:00     ` Andrew Cooper
  2014-09-09 19:52     ` Tim Deegan
@ 2014-09-10 10:59     ` Don Slutz
  2 siblings, 0 replies; 21+ messages in thread
From: Don Slutz @ 2014-09-10 10:59 UTC (permalink / raw)
  To: Ian Campbell
  Cc: xen-devel, keir, Mihai Donțu, Tim Deegan, Don Slutz, Jan Beulich

On 09/09/14 10:50, Ian Campbell wrote:
> On Tue, 2014-09-09 at 05:32 +0300, Mihai Donțu wrote:
>> This is a clang-format wrapper script that can be used to do the bulk of the
>> coding style work on a foreign source file. It is not yet complete, but it's
>> sufficient for 98% of the cases.
> I think a lot of people would like to have something along these lines
> available. Don also proposed something recently, see [0]. Not sure what
> the hypervisor maintainers opinion is though, I've CCd a few for input.
>
> I've no prior experience with either clang-format or astyle so I don't
> know which is better, but I do like that clang-format doesn't need a
> second pass in emacs (despite being an emacs user).
>
> Ian.
>
> [0] http://lists.xen.org/archives/html/xen-devel/2014-09/msg00918.html
>

I am not able to just use it:


[root@localhost xen]# xen/tools/xen-indent xen/arch/x86/numa.c
YAML:39:49: error: unknown key 'SpaceBeforeParens'
SpaceBeforeParens:                              ControlStatements
                                                 ^~~~~~~~~~~~~~~~~
Error reading /root/xen/xen/arch/x86/.clang-format: Invalid argument
Can't find usable .clang-format, using LLVM style

Also clang_format is not available in older distros.

    -Don Slutz

>> Signed-off-by: Mihai Donțu <mdontu@bitdefender.com>
>> ---
>>   xen/tools/xen-indent | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 77 insertions(+)
>>   create mode 100755 xen/tools/xen-indent
>>
>> diff --git a/xen/tools/xen-indent b/xen/tools/xen-indent
>> new file mode 100755
>> index 0000000..6be507c
>> --- /dev/null
>> +++ b/xen/tools/xen-indent
>> @@ -0,0 +1,77 @@
>> +#!/bin/sh
>> +
>> +CLANG_FORMAT=`which clang-format 2>/dev/null`
>> +
>> +if [ "x$CLANG_FORMAT" = "x" ]; then
>> +	printf "Error: \`clang-format' is not installed. It is usually part of clang (3.4 and newer)\n" >&2
>> +	exit 1
>> +fi
>> +
>> +if [ "x$1" = "x" ]; then
>> +	printf "Usage: $0 <file[s]>\n"
>> +	exit 2
>> +fi
>> +
>> +for i in $@; do
>> +	DN=`dirname "$i"`
>> +	cat >"$DN/.clang-format" <<EOF
>> +---
>> +AccessModifierOffset:                           -8
>> +IndentWidth:                                    4
>> +TabWidth:                                       4
>> +ConstructorInitializerIndentWidth:              4
>> +AlignEscapedNewlinesLeft:                       true
>> +AlignTrailingComments:                          true
>> +AllowAllParametersOfDeclarationOnNextLine:      true
>> +AllowShortIfStatementsOnASingleLine:            false
>> +AllowShortLoopsOnASingleLine:                   false
>> +AllowShortFunctionsOnASingleLine:               false
>> +AlwaysBreakTemplateDeclarations:                false
>> +AlwaysBreakBeforeMultilineStrings:              false
>> +BreakBeforeBinaryOperators:                     false
>> +BreakBeforeTernaryOperators:                    true
>> +BreakConstructorInitializersBeforeComma:        false
>> +BinPackParameters:                              true
>> +ColumnLimit:                                    80
>> +ConstructorInitializerAllOnOneLineOrOnePerLine: false
>> +DerivePointerBinding:                           false
>> +ExperimentalAutoDetectBinPacking:               false
>> +IndentCaseLabels:                               false
>> +MaxEmptyLinesToKeep:                            1
>> +NamespaceIndentation:                           All
>> +ObjCSpaceBeforeProtocolList:                    true
>> +PenaltyBreakBeforeFirstCallParameter:           19
>> +PenaltyBreakComment:                            60
>> +PenaltyBreakString:                             1000
>> +PenaltyBreakFirstLessLess:                      120
>> +PenaltyExcessCharacter:                         1000000
>> +PenaltyReturnTypeOnItsOwnLine:                  60
>> +PointerBindsToType:                             false
>> +SpacesBeforeTrailingComments:                   1
>> +Cpp11BracedListStyle:                           false
>> +Standard:                                       Cpp11
>> +UseTab:                                         Never
>> +BreakBeforeBraces:                              Allman
>> +IndentFunctionDeclarationAfterType:             false
>> +SpaceBeforeParens:                              ControlStatements
>> +SpacesInParentheses:                            false
>> +SpacesInAngles:                                 false
>> +SpaceInEmptyParentheses:                        false
>> +SpacesInCStyleCastParentheses:                  false
>> +SpaceAfterControlStatementKeyword:              true
>> +SpaceBeforeAssignmentOperators:                 true
>> +ContinuationIndentWidth:                        4
>> +EOF
>> +	ERR=0
>> +	$CLANG_FORMAT "$i" >"${i}.clang-tmp" || ERR=1
>> +	rm -f "$DN/.clang-format"
>> +	if [ $ERR -ne 0 ]; then
>> +		rm -f "${i}.clang-tmp"
>> +		exit 3
>> +	fi
>> +	sed 's#if\s*(\(.*\))#if ( \1 )#m' "${i}.clang-tmp" >"${i}.clang-tmp.1"
>> +	sed 's#switch\s*(\(.*\))#switch ( \1 )#m' "${i}.clang-tmp.1" >"${i}.clang-tmp.2"
>> +	sed 's#while\s*(\(.*\))#while ( \1 )#m' "${i}.clang-tmp.2" >"${i}.clang-tmp.3"
>> +	mv -f "${i}.clang-tmp.3" "${i}"
>> +	rm -f "${i}.clang-tmp" "${i}.clang-tmp.1" "${i}.clang-tmp.2"
>> +done
>


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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 3/3] xen/tools: script for automatically adjusting the coding style to xen style
  2014-09-09  2:32 ` [PATCH 3/3] xen/tools: script for automatically adjusting the coding style to xen style Mihai Donțu
  2014-09-09 14:50   ` Ian Campbell
@ 2014-09-10 14:21   ` Don Slutz
  1 sibling, 0 replies; 21+ messages in thread
From: Don Slutz @ 2014-09-10 14:21 UTC (permalink / raw)
  To: Mihai Donțu, xen-devel


On 09/08/14 22:32, Mihai Donțu wrote:
> This is a clang-format wrapper script that can be used to do the bulk of the
> coding style work on a foreign source file. It is not yet complete, but it's
> sufficient for 98% of the cases.
>
> Signed-off-by: Mihai Donțu <mdontu@bitdefender.com>
> ---
>   xen/tools/xen-indent | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 77 insertions(+)
>   create mode 100755 xen/tools/xen-indent
>
> diff --git a/xen/tools/xen-indent b/xen/tools/xen-indent
> new file mode 100755
> index 0000000..6be507c
> --- /dev/null
> +++ b/xen/tools/xen-indent
> @@ -0,0 +1,77 @@
> +#!/bin/sh
> +
> +CLANG_FORMAT=`which clang-format 2>/dev/null`
> +
> +if [ "x$CLANG_FORMAT" = "x" ]; then
> +	printf "Error: \`clang-format' is not installed. It is usually part of clang (3.4 and newer)\n" >&2
> +	exit 1
> +fi
> +
> +if [ "x$1" = "x" ]; then
> +	printf "Usage: $0 <file[s]>\n"
> +	exit 2
> +fi
> +
> +for i in $@; do
> +	DN=`dirname "$i"`
> +	cat >"$DN/.clang-format" <<EOF
> +---
> +AccessModifierOffset:                           -8
> +IndentWidth:                                    4
> +TabWidth:                                       4
> +ConstructorInitializerIndentWidth:              4
> +AlignEscapedNewlinesLeft:                       true
> +AlignTrailingComments:                          true
> +AllowAllParametersOfDeclarationOnNextLine:      true
> +AllowShortIfStatementsOnASingleLine:            false
> +AllowShortLoopsOnASingleLine:                   false
> +AllowShortFunctionsOnASingleLine:               false
> +AlwaysBreakTemplateDeclarations:                false
> +AlwaysBreakBeforeMultilineStrings:              false
> +BreakBeforeBinaryOperators:                     false
> +BreakBeforeTernaryOperators:                    true
> +BreakConstructorInitializersBeforeComma:        false
> +BinPackParameters:                              true
> +ColumnLimit:                                    80
> +ConstructorInitializerAllOnOneLineOrOnePerLine: false
> +DerivePointerBinding:                           false
> +ExperimentalAutoDetectBinPacking:               false
> +IndentCaseLabels:                               false
> +MaxEmptyLinesToKeep:                            1
> +NamespaceIndentation:                           All
> +ObjCSpaceBeforeProtocolList:                    true
> +PenaltyBreakBeforeFirstCallParameter:           19
> +PenaltyBreakComment:                            60
> +PenaltyBreakString:                             1000
> +PenaltyBreakFirstLessLess:                      120
> +PenaltyExcessCharacter:                         1000000
> +PenaltyReturnTypeOnItsOwnLine:                  60
> +PointerBindsToType:                             false
> +SpacesBeforeTrailingComments:                   1
> +Cpp11BracedListStyle:                           false
> +Standard:                                       Cpp11
> +UseTab:                                         Never
> +BreakBeforeBraces:                              Allman
> +IndentFunctionDeclarationAfterType:             false
> +SpaceBeforeParens:                              ControlStatements
> +SpacesInParentheses:                            false
> +SpacesInAngles:                                 false
> +SpaceInEmptyParentheses:                        false
> +SpacesInCStyleCastParentheses:                  false
> +SpaceAfterControlStatementKeyword:              true
> +SpaceBeforeAssignmentOperators:                 true
> +ContinuationIndentWidth:                        4
> +EOF
> +	ERR=0
> +	$CLANG_FORMAT "$i" >"${i}.clang-tmp" || ERR=1
> +	rm -f "$DN/.clang-format"
> +	if [ $ERR -ne 0 ]; then
> +		rm -f "${i}.clang-tmp"
> +		exit 3
> +	fi
> +	sed 's#if\s*(\(.*\))#if ( \1 )#m' "${i}.clang-tmp" >"${i}.clang-tmp.1"
> +	sed 's#switch\s*(\(.*\))#switch ( \1 )#m' "${i}.clang-tmp.1" >"${i}.clang-tmp.2"
> +	sed 's#while\s*(\(.*\))#while ( \1 )#m' "${i}.clang-tmp.2" >"${i}.clang-tmp.3"

This is missing "for".  And last I knew sed does not handle multiple lines.

And what about the "do {" exception?

     -Don Slutz

> +	mv -f "${i}.clang-tmp.3" "${i}"
> +	rm -f "${i}.clang-tmp" "${i}.clang-tmp.1" "${i}.clang-tmp.2"
> +done


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

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2014-09-10 14:21 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-09  2:22 [PATCH 0/3] xen: add support for skipping the current instruction Mihai Donțu
2014-09-09  2:28 ` [PATCH 1/3] x86: add support for computing the instruction length Mihai Donțu
2014-09-09  8:47   ` Mihai Donțu
2014-09-09  9:44     ` Mihai Donțu
2014-09-09 10:13       ` Masami Hiramatsu
2014-09-09 15:46         ` Mihai Donțu
2014-09-09 16:01           ` Mihai Donțu
2014-09-09 16:25             ` Jan Beulich
2014-09-09 17:14               ` Andrew Cooper
2014-09-09 17:27               ` Mihai Donțu
2014-09-09 17:57               ` Konrad Rzeszutek Wilk
2014-09-09  2:29 ` [PATCH 2/3] x86/hvm: implement hvm_get_insn_length() Mihai Donțu
2014-09-09  2:32 ` [PATCH 3/3] xen/tools: script for automatically adjusting the coding style to xen style Mihai Donțu
2014-09-09 14:50   ` Ian Campbell
2014-09-09 15:00     ` Andrew Cooper
2014-09-09 19:52     ` Tim Deegan
2014-09-10 10:59     ` Don Slutz
2014-09-10 14:21   ` Don Slutz
2014-09-09  9:47 ` [PATCH 0/3] xen: add support for skipping the current instruction Jan Beulich
2014-09-09 17:00   ` Mihai Donțu
2014-09-09 18:58     ` Tamas K Lengyel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.