]> xenbits.xensource.com Git - people/royger/xen.git/commitdiff
x86/PV: avoid indirect call/thunk in I/O emulation
authorJan Beulich <jbeulich@suse.com>
Mon, 19 Feb 2018 12:59:37 +0000 (13:59 +0100)
committerJan Beulich <jbeulich@suse.com>
Mon, 19 Feb 2018 12:59:37 +0000 (13:59 +0100)
The stub is within reach from the .text section, so there's no point
using an indirect call here. This has the added benefit of there no
longer being two sufficiently different approaches, breaking one of
which people may not even notice.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citix.com>
xen/arch/x86/pv/emul-priv-op.c

index 21ecfc8e761dd412994628506a5b6c66d0ab85d6..17aaf97f103aa8ae245a8355733ce943053a892b 100644 (file)
@@ -73,55 +73,42 @@ void (*pv_post_outb_hook)(unsigned int port, u8 value);
 
 typedef void io_emul_stub_t(struct cpu_user_regs *);
 
-void __x86_indirect_thunk_rcx(void);
-
 static io_emul_stub_t *io_emul_stub_setup(struct priv_op_ctxt *ctxt, u8 opcode,
                                           unsigned int port, unsigned int bytes)
 {
     struct stubs *this_stubs = &this_cpu(stubs);
     unsigned long stub_va = this_stubs->addr + STUB_BUF_SIZE / 2;
+    long disp;
     bool use_quirk_stub = false;
 
     if ( !ctxt->io_emul_stub )
         ctxt->io_emul_stub =
             map_domain_page(_mfn(this_stubs->mfn)) + (stub_va & ~PAGE_MASK);
 
-    /* movq $host_to_guest_gpr_switch,%rcx */
-    ctxt->io_emul_stub[0] = 0x48;
-    ctxt->io_emul_stub[1] = 0xb9;
-    *(void **)&ctxt->io_emul_stub[2] = (void *)host_to_guest_gpr_switch;
-
-#ifdef CONFIG_INDIRECT_THUNK
-    /* callq __x86_indirect_thunk_rcx */
-    ctxt->io_emul_stub[10] = 0xe8;
-    *(int32_t *)&ctxt->io_emul_stub[11] =
-        (long)__x86_indirect_thunk_rcx - (stub_va + 11 + 4);
-#else
-    /* callq *%rcx */
-    ctxt->io_emul_stub[10] = 0xff;
-    ctxt->io_emul_stub[11] = 0xd1;
-    /* TODO: untangle ideal_nops from init/livepatch Kconfig options. */
-    memcpy(&ctxt->io_emul_stub[12], "\x0f\x1f\x00", 3); /* P6_NOP3 */
-#endif
+    /* call host_to_guest_gpr_switch */
+    ctxt->io_emul_stub[0] = 0xe8;
+    disp = (long)host_to_guest_gpr_switch - (stub_va + 5);
+    BUG_ON((int32_t)disp != disp);
+    *(int32_t *)&ctxt->io_emul_stub[1] = disp;
 
     if ( unlikely(ioemul_handle_quirk) )
-        use_quirk_stub = ioemul_handle_quirk(opcode, &ctxt->io_emul_stub[15],
+        use_quirk_stub = ioemul_handle_quirk(opcode, &ctxt->io_emul_stub[5],
                                              ctxt->ctxt.regs);
 
     if ( !use_quirk_stub )
     {
         /* data16 or nop */
-        ctxt->io_emul_stub[15] = (bytes != 2) ? 0x90 : 0x66;
+        ctxt->io_emul_stub[5] = (bytes != 2) ? 0x90 : 0x66;
         /* <io-access opcode> */
-        ctxt->io_emul_stub[16] = opcode;
+        ctxt->io_emul_stub[6] = opcode;
         /* imm8 or nop */
-        ctxt->io_emul_stub[17] = !(opcode & 8) ? port : 0x90;
+        ctxt->io_emul_stub[7] = !(opcode & 8) ? port : 0x90;
         /* ret (jumps to guest_to_host_gpr_switch) */
-        ctxt->io_emul_stub[18] = 0xc3;
+        ctxt->io_emul_stub[8] = 0xc3;
     }
 
-    BUILD_BUG_ON(STUB_BUF_SIZE / 2 < MAX(19, /* Default emul stub */
-                                         15 + IOEMUL_QUIRK_STUB_BYTES));
+    BUILD_BUG_ON(STUB_BUF_SIZE / 2 < MAX(9, /* Default emul stub */
+                                         5 + IOEMUL_QUIRK_STUB_BYTES));
 
     /* Handy function-typed pointer to the stub. */
     return (void *)stub_va;