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

[Xen-changelog] [xen staging] x86emul: vendor specific direct branch behavior in 64-bit mode



commit 6329109cf352e164e0c227fe119b64bf7d38de38
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Thu Mar 26 12:32:07 2020 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Thu Mar 26 12:32:07 2020 +0100

    x86emul: vendor specific direct branch behavior in 64-bit mode
    
    Intel CPUs ignore operand size overrides here, while AMD ones don't.
    
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
 tools/tests/x86_emulator/test_x86_emulator.c | 68 ++++++++++++++++++++++++++++
 xen/arch/x86/x86_emulate/x86_emulate.c       |  8 +++-
 2 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/tools/tests/x86_emulator/test_x86_emulator.c 
b/tools/tests/x86_emulator/test_x86_emulator.c
index f28dae14e3..2d39bd05db 100644
--- a/tools/tests/x86_emulator/test_x86_emulator.c
+++ b/tools/tests/x86_emulator/test_x86_emulator.c
@@ -757,6 +757,62 @@ static const struct {
         .opc_len = { 4, 4 },
         .stkoff = { 2 + 16, 8 + 16 },
         .disp = { STKVAL_DISP - MMAP_ADDR, STKVAL_DISP },
+    }, {
+        .descr = "jmpw .+16",
+        .opcode = { 0x66, 0xeb, 0x10 },
+        .opc_len = { 3, 3 },
+        .disp = { 3 + 16 - MMAP_ADDR, 3 + 16 },
+    }, {
+        .descr = "jmpw .+128",
+        .opcode = { 0x66, 0xe9, 0x80, 0x00, 0x00, 0x00 },
+        .opc_len = { 4, 6 },
+        .disp = { 4 + 128 - MMAP_ADDR, 6 + 128 },
+    }, {
+        .descr = "callw .+16",
+        .opcode = { 0x66, 0xe8, 0x10, 0x00, 0x00, 0x00 },
+        .opc_len = { 4, 6 },
+        .stkoff = { -2, -8 },
+        .disp = { 4 + 16 - MMAP_ADDR, 6 + 16 },
+    }, {
+        .descr = "jzw .+16",
+        .opcode = { 0x66, 0x74, 0x10 },
+        .opc_len = { 3, 3 },
+        .disp = { 3, 3 },
+    }, {
+        .descr = "jzw .+128",
+        .opcode = { 0x66, 0x0f, 0x84, 0x80, 0x00, 0x00, 0x00 },
+        .opc_len = { 5, 7 },
+        .disp = { 5, 7 },
+    }, {
+        .descr = "jnzw .+16",
+        .opcode = { 0x66, 0x75, 0x10 },
+        .opc_len = { 3, 3 },
+        .disp = { 3 + 16 - MMAP_ADDR, 3 + 16 },
+    }, {
+        .descr = "jnzw .+128",
+        .opcode = { 0x66, 0x0f, 0x85, 0x80, 0x00, 0x00, 0x00 },
+        .opc_len = { 5, 7 },
+        .disp = { 5 + 128 - MMAP_ADDR, 7 + 128 },
+    }, {
+        .descr = "loopqw .+16 (RCX>1)",
+        .opcode = { 0x66, 0xe0, 0x10 },
+        .opc_len = { 3, 3 },
+        .disp = { 3 + 16 - MMAP_ADDR, 3 + 16 },
+    }, {
+        .descr = "looplw .+16 (ECX=1)",
+        .opcode = { 0x66, 0x67, 0xe0, 0x10 },
+        .opc_len = { 4, 4 },
+        .disp = { 4, 4 },
+    }, {
+        .descr = "jrcxzw .+16 (RCX>0)",
+        .opcode = { 0x66, 0xe3, 0x10 },
+        .opc_len = { 3, 3 },
+        .disp = { 3, 3 },
+    }, {
+        .descr = "jecxzw .+16 (ECX=0)",
+        .opcode = { 0x66, 0x67, 0xe3, 0x10 },
+        .opc_len = { 4, 4 },
+        .disp = { 4 + 16 - MMAP_ADDR, 4 + 16 },
     },
 };
 #endif
@@ -1361,6 +1417,7 @@ int main(int argc, char **argv)
         const char *vendor = cp.x86_vendor == X86_VENDOR_INTEL ? "Intel" : 
"AMD";
         uint64_t *stk = (void *)res + MMAP_SZ - 16;
 
+        regs.rcx = 2;
         for ( i = 0; i < ARRAY_SIZE(vendor_tests); ++i )
         {
             printf("%-*s",
@@ -1370,6 +1427,7 @@ int main(int argc, char **argv)
             regs.eflags = EFLAGS_ALWAYS_SET;
             regs.rip    = (unsigned long)instr;
             regs.rsp    = (unsigned long)stk;
+            regs.rcx   |= 0x8765432100000000UL;
             stk[0]      = regs.rip + STKVAL_DISP;
             rc = x86_emulate(&ctxt, &emulops);
             if ( (rc != X86EMUL_OKAY) ||
@@ -1379,6 +1437,16 @@ int main(int argc, char **argv)
                                ?: vendor_tests[i].opc_len[v])) ||
                  (regs.rsp != (unsigned long)stk + vendor_tests[i].stkoff[v]) )
                 goto fail;
+            /* For now only call insns push something onto the stack. */
+            if ( regs.rsp < (unsigned long)stk )
+            {
+                unsigned long opc_end = (unsigned long)instr +
+                                        vendor_tests[i].opc_len[v];
+
+                if ( memcmp(&opc_end, (void *)regs.rsp,
+                            min((unsigned long)stk - regs.rsp, 8UL)) )
+                    goto fail;
+            }
             printf("okay\n");
         }
 
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c 
b/xen/arch/x86/x86_emulate/x86_emulate.c
index c00f56a32a..49c21585c2 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -1273,7 +1273,7 @@ do {                                                      
              \
 #define jmp_rel(rel)                                                    \
 do {                                                                    \
     unsigned long ip = _regs.r(ip) + (int)(rel);                        \
-    if ( op_bytes == 2 )                                                \
+    if ( op_bytes == 2 && (amd_like(ctxt) || !mode_64bit()) )           \
         ip = (uint16_t)ip;                                              \
     else if ( !mode_64bit() )                                           \
         ip = (uint32_t)ip;                                              \
@@ -3391,7 +3391,13 @@ x86_decode(
 
     case SrcImm:
         if ( !(d & ByteOp) )
+        {
+            if ( mode_64bit() && !amd_like(ctxt) &&
+                 ((ext == ext_none && (b | 1) == 0xe9) /* call / jmp */ ||
+                  (ext == ext_0f && (b | 0xf) == 0x8f) /* jcc */ ) )
+                op_bytes = 4;
             bytes = op_bytes != 8 ? op_bytes : 4;
+        }
         else
         {
     case SrcImmByte:
--
generated by git-patchbot for /home/xen/git/xen.git#staging

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

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