Enable compatibility mode operation for HYPERVISOR_multicall.
authorEmmanuel Ackaouy <ack@xensource.com>
Fri, 5 Jan 2007 17:34:34 +0000 (17:34 +0000)
committerEmmanuel Ackaouy <ack@xensource.com>
Fri, 5 Jan 2007 17:34:34 +0000 (17:34 +0000)
Signed-off-by: Jan Beulich <jbeulich@novell.com>
xen/arch/x86/x86_64/asm-offsets.c
xen/arch/x86/x86_64/compat/entry.S
xen/common/compat/Makefile
xen/common/compat/multicall.c [new file with mode: 0644]
xen/common/multicall.c
xen/include/asm-x86/multicall.h
xen/include/xen/multicall.h

index 7a86371630b5c7b0f7c0aa734a0fba31db3f2c5f..001a781235391852d5c68a1558121ac0373f0e25 100644 (file)
@@ -135,5 +135,17 @@ void __dummy__(void)
     OFFSET(MULTICALL_result, struct multicall_entry, result);
     BLANK();
 
+#ifdef CONFIG_COMPAT
+    OFFSET(COMPAT_MULTICALL_op, struct compat_multicall_entry, op);
+    OFFSET(COMPAT_MULTICALL_arg0, struct compat_multicall_entry, args[0]);
+    OFFSET(COMPAT_MULTICALL_arg1, struct compat_multicall_entry, args[1]);
+    OFFSET(COMPAT_MULTICALL_arg2, struct compat_multicall_entry, args[2]);
+    OFFSET(COMPAT_MULTICALL_arg3, struct compat_multicall_entry, args[3]);
+    OFFSET(COMPAT_MULTICALL_arg4, struct compat_multicall_entry, args[4]);
+    OFFSET(COMPAT_MULTICALL_arg5, struct compat_multicall_entry, args[5]);
+    OFFSET(COMPAT_MULTICALL_result, struct compat_multicall_entry, result);
+    BLANK();
+#endif
+
     DEFINE(IRQSTAT_shift, LOG_2(sizeof(irq_cpustat_t)));
 }
index 47cd1e3864fec059cd2437ce312b0d081649008d..fa62fe416044f346d8d87f89e0bcd5f05bfca2a9 100644 (file)
@@ -279,7 +279,6 @@ CFIX14:
 .section .rodata, "a", @progbits
 
 #define compat_platform_op domain_crash_synchronous
-#define compat_multicall domain_crash_synchronous
 #define compat_set_timer_op domain_crash_synchronous
 #define compat_grant_table_op domain_crash_synchronous
 #define compat_acm_op domain_crash_synchronous
index 9a54a43c500221dc591b5fc9a0aa68d11ee033e1..dfab7bc77cf62f4eadea950434c5c19bd806ae1d 100644 (file)
@@ -1,7 +1,9 @@
 obj-y += domain.o
 obj-y += kernel.o
 obj-y += memory.o
+obj-y += multicall.o
 obj-y += xlat.o
 
 # extra dependencies
 kernel.o:      ../kernel.c
+multicall.o:   ../multicall.c
diff --git a/xen/common/compat/multicall.c b/xen/common/compat/multicall.c
new file mode 100644 (file)
index 0000000..17b12d6
--- /dev/null
@@ -0,0 +1,31 @@
+/******************************************************************************
+ * multicall.c
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/multicall.h>
+
+#define COMPAT
+typedef int ret_t;
+#undef do_multicall_call
+
+DEFINE_XEN_GUEST_HANDLE(multicall_entry_compat_t);
+#define multicall_entry      compat_multicall_entry
+#define multicall_entry_t    multicall_entry_compat_t
+#define do_multicall_call    compat_multicall_call
+#define call                 compat_call
+#define do_multicall(l, n)   compat_multicall(_##l, n)
+#define _XEN_GUEST_HANDLE(t) XEN_GUEST_HANDLE(t)
+
+#include "../multicall.c"
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
index 499e6bd62cbf5d093339e6bd6c5b0c280351fc98..1a43838ca09eef3ac59eeaf0bc07bb8bbbe9253f 100644 (file)
 #include <asm/current.h>
 #include <asm/hardirq.h>
 
+#ifndef COMPAT
 DEFINE_PER_CPU(struct mc_state, mc_state);
+typedef long ret_t;
+#endif
 
-long
+ret_t
 do_multicall(
     XEN_GUEST_HANDLE(multicall_entry_t) call_list, unsigned int nr_calls)
 {
index 1ce7866c3eb581cf3ced42793b13e2f021cb0aa0..8414dca055119114a94f7f9e8190e23d0a53b25d 100644 (file)
               "r8",  "r9",  "r10", "r11" );                  \
     } while ( 0 )
 
+#define compat_multicall_call(_call)                              \
+    do {                                                          \
+        __asm__ __volatile__ (                                    \
+            "    movl  "STR(COMPAT_MULTICALL_op)"(%0),%%eax; "    \
+            "    leaq  compat_hypercall_table(%%rip),%%rdi; "     \
+            "    cmpl  $("STR(NR_hypercalls)"),%%eax; "           \
+            "    jae   2f; "                                      \
+            "    movq  (%%rdi,%%rax,8),%%rax; "                   \
+            "    movl  "STR(COMPAT_MULTICALL_arg0)"(%0),%%edi; "  \
+            "    movl  "STR(COMPAT_MULTICALL_arg1)"(%0),%%esi; "  \
+            "    movl  "STR(COMPAT_MULTICALL_arg2)"(%0),%%edx; "  \
+            "    movl  "STR(COMPAT_MULTICALL_arg3)"(%0),%%ecx; "  \
+            "    movl  "STR(COMPAT_MULTICALL_arg4)"(%0),%%r8d; "  \
+            "    callq *%%rax; "                                  \
+            "1:  movl  %%eax,"STR(COMPAT_MULTICALL_result)"(%0)\n"\
+            ".section .fixup,\"ax\"\n"                            \
+            "2:  movl  $-"STR(ENOSYS)",%%eax\n"                   \
+            "    jmp   1b\n"                                      \
+            ".previous\n"                                         \
+            : : "b" (_call)                                       \
+              /* all the caller-saves registers */                \
+            : "rax", "rcx", "rdx", "rsi", "rdi",                  \
+              "r8",  "r9",  "r10", "r11" );                       \
+    } while ( 0 )
+
 #else
 
 #define do_multicall_call(_call)                             \
index 5d8b4db1ca933eb6b44684e22ba13aa392786256..34cdb4664f739ffe9c0d456f838a03872277161a 100644 (file)
@@ -7,6 +7,9 @@
 
 #include <xen/percpu.h>
 #include <asm/multicall.h>
+#ifdef CONFIG_COMPAT
+#include <compat/xen.h>
+#endif
 
 #define _MCSF_in_multicall   0
 #define _MCSF_call_preempted 1
 #define MCSF_call_preempted  (1<<_MCSF_call_preempted)
 struct mc_state {
     unsigned long flags;
-    struct multicall_entry call;
+    union {
+        struct multicall_entry call;
+#ifdef CONFIG_COMPAT
+        struct compat_multicall_entry compat_call;
+#endif
+    };
 };
 
 DECLARE_PER_CPU(struct mc_state, mc_state);