# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 37e9c9cd6c14a26fa396a0439f91e16a820d4e34
# Parent 2b95125015a59eeb086b3748f9415ac440133b4d
Clean up and fix hypercall macros in XenLinux: we must assume that
all register parameters are clobbered on return. Furthermore,
multicall arrays are clobbered on return from a multicall (only the
result field can be trusted!).
These restrictions are enforced by debug builds of Xen in the
following ways:
1. On completion of a multicall, the call array is overwritten
with garbage before writing in the result fields.
2. On completion of a hypercall, all parameter registers are
overwritten with garbage.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
diff -r 2b95125015a5 -r 37e9c9cd6c14
linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
--- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Fri Aug 26
13:06:49 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Fri Aug 26
17:42:34 2005
@@ -63,16 +63,19 @@
"popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
: "=a" (ret) : "0" (&hypercall) : "memory" );
#elif defined (__x86_64__)
- __asm__ __volatile__ (
- "movq %5,%%r10; movq %6,%%r8;" TRAP_INSTR
- : "=a" (ret)
- : "a" ((unsigned long)hypercall.op),
- "D" ((unsigned long)hypercall.arg[0]),
- "S" ((unsigned long)hypercall.arg[1]),
- "d" ((unsigned long)hypercall.arg[2]),
- "g" ((unsigned long)hypercall.arg[3]),
- "g" ((unsigned long)hypercall.arg[4])
- : "r11","rcx","r8","r10","memory");
+ {
+ long ign1, ign2, ign3;
+ __asm__ __volatile__ (
+ "movq %5,%%r10; movq %6,%%r8;" TRAP_INSTR
+ : "=a" (ret), "=D" (ign1), "=S" (ign2), "=d" (ign3)
+ : "0" ((unsigned long)hypercall.op),
+ "1" ((unsigned long)hypercall.arg[0]),
+ "2" ((unsigned long)hypercall.arg[1]),
+ "3" ((unsigned long)hypercall.arg[2]),
+ "g" ((unsigned long)hypercall.arg[3]),
+ "g" ((unsigned long)hypercall.arg[4])
+ : "r11","rcx","r8","r10","memory");
+ }
#endif
}
break;
diff -r 2b95125015a5 -r 37e9c9cd6c14
linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h Fri Aug 26
13:06:49 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h Fri Aug 26
17:42:34 2005
@@ -29,551 +29,362 @@
#ifndef __HYPERCALL_H__
#define __HYPERCALL_H__
+
#include <asm-xen/xen-public/xen.h>
-/*
- * Assembler stubs for hyper-calls.
- */
+#define _hypercall0(type, name) \
+({ \
+ long __res; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res) \
+ : "0" (__HYPERVISOR_##name) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall1(type, name, a1) \
+({ \
+ long __res, __ign1; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res), "=b" (__ign1) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall2(type, name, a1, a2) \
+({ \
+ long __res, __ign1, __ign2; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
+ "2" ((long)(a2)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall3(type, name, a1, a2, a3) \
+({ \
+ long __res, __ign1, __ign2, __ign3; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
+ "=d" (__ign3) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
+ "2" ((long)(a2)), "3" ((long)(a3)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall4(type, name, a1, a2, a3, a4) \
+({ \
+ long __res, __ign1, __ign2, __ign3, __ign4; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
+ "=d" (__ign3), "=S" (__ign4) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
+ "2" ((long)(a2)), "3" ((long)(a3)), \
+ "4" ((long)(a4)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
+({ \
+ long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
+ "=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
+ "2" ((long)(a2)), "3" ((long)(a3)), \
+ "4" ((long)(a4)), "5" ((long)(a5)) \
+ : "memory" ); \
+ (type)__res; \
+})
static inline int
HYPERVISOR_set_trap_table(
- trap_info_t *table)
-{
- int ret;
- unsigned long ignore;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ignore)
- : "0" (__HYPERVISOR_set_trap_table), "1" (table)
- : "memory" );
-
- return ret;
+ trap_info_t *table)
+{
+ return _hypercall1(int, set_trap_table, table);
}
static inline int
HYPERVISOR_mmu_update(
- mmu_update_t *req, int count, int *success_count, domid_t domid)
-{
- int ret;
- unsigned long ign1, ign2, ign3, ign4;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
- : "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count),
- "3" (success_count), "4" (domid)
- : "memory" );
-
- return ret;
+ mmu_update_t *req, int count, int *success_count, domid_t domid)
+{
+ return _hypercall4(int, mmu_update, req, count, success_count, domid);
}
static inline int
HYPERVISOR_mmuext_op(
- struct mmuext_op *op, int count, int *success_count, domid_t domid)
-{
- int ret;
- unsigned long ign1, ign2, ign3, ign4;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
- : "0" (__HYPERVISOR_mmuext_op), "1" (op), "2" (count),
- "3" (success_count), "4" (domid)
- : "memory" );
-
- return ret;
+ struct mmuext_op *op, int count, int *success_count, domid_t domid)
+{
+ return _hypercall4(int, mmuext_op, op, count, success_count, domid);
}
static inline int
HYPERVISOR_set_gdt(
- unsigned long *frame_list, int entries)
-{
- int ret;
- unsigned long ign1, ign2;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2)
- : "0" (__HYPERVISOR_set_gdt), "1" (frame_list), "2" (entries)
- : "memory" );
-
-
- return ret;
+ unsigned long *frame_list, int entries)
+{
+ return _hypercall2(int, set_gdt, frame_list, entries);
}
static inline int
HYPERVISOR_stack_switch(
- unsigned long ss, unsigned long esp)
-{
- int ret;
- unsigned long ign1, ign2;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2)
- : "0" (__HYPERVISOR_stack_switch), "1" (ss), "2" (esp)
- : "memory" );
-
- return ret;
+ unsigned long ss, unsigned long esp)
+{
+ return _hypercall2(int, stack_switch, ss, esp);
}
static inline int
HYPERVISOR_set_callbacks(
- unsigned long event_selector, unsigned long event_address,
- unsigned long failsafe_selector, unsigned long failsafe_address)
-{
- int ret;
- unsigned long ign1, ign2, ign3, ign4;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
- : "0" (__HYPERVISOR_set_callbacks), "1" (event_selector),
- "2" (event_address), "3" (failsafe_selector), "4" (failsafe_address)
- : "memory" );
-
- return ret;
+ unsigned long event_selector, unsigned long event_address,
+ unsigned long failsafe_selector, unsigned long failsafe_address)
+{
+ return _hypercall4(int, set_callbacks,
+ event_selector, event_address,
+ failsafe_selector, failsafe_address);
}
static inline int
HYPERVISOR_fpu_taskswitch(
- int set)
-{
- int ret;
- unsigned long ign;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign)
- : "0" (__HYPERVISOR_fpu_taskswitch), "1" (set)
- : "memory" );
-
- return ret;
+ int set)
+{
+ return _hypercall1(int, fpu_taskswitch, set);
}
static inline int
HYPERVISOR_yield(
- void)
-{
- int ret;
- unsigned long ign;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign)
- : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_yield)
- : "memory", "ecx" );
-
- return ret;
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_yield, 0);
}
static inline int
HYPERVISOR_block(
- void)
-{
- int ret;
- unsigned long ign1;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1)
- : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_block)
- : "memory", "ecx" );
-
- return ret;
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_block, 0);
}
static inline int
HYPERVISOR_shutdown(
- void)
-{
- int ret;
- unsigned long ign1;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1)
- : "0" (__HYPERVISOR_sched_op),
- "1" (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift))
- : "memory", "ecx" );
-
- return ret;
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+ (SHUTDOWN_poweroff << SCHEDOP_reasonshift), 0);
}
static inline int
HYPERVISOR_reboot(
- void)
-{
- int ret;
- unsigned long ign1;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1)
- : "0" (__HYPERVISOR_sched_op),
- "1" (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift))
- : "memory", "ecx" );
-
- return ret;
-}
-
-static inline int
-HYPERVISOR_suspend(
- unsigned long srec)
-{
- int ret;
- unsigned long ign1, ign2;
-
- /* NB. On suspend, control software expects a suspend record in %esi. */
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=S" (ign2)
- : "0" (__HYPERVISOR_sched_op),
- "b" (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)),
- "S" (srec) : "memory", "ecx");
-
- return ret;
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+ (SHUTDOWN_reboot << SCHEDOP_reasonshift), 0);
}
static inline int
HYPERVISOR_crash(
- void)
-{
- int ret;
- unsigned long ign1;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1)
- : "0" (__HYPERVISOR_sched_op),
- "1" (SCHEDOP_shutdown | (SHUTDOWN_crash << SCHEDOP_reasonshift))
- : "memory", "ecx" );
-
- return ret;
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+ (SHUTDOWN_crash << SCHEDOP_reasonshift), 0);
}
static inline long
HYPERVISOR_set_timer_op(
- u64 timeout)
-{
- int ret;
- unsigned long timeout_hi = (unsigned long)(timeout>>32);
- unsigned long timeout_lo = (unsigned long)timeout;
- unsigned long ign1, ign2;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2)
- : "0" (__HYPERVISOR_set_timer_op), "b" (timeout_lo), "c" (timeout_hi)
- : "memory");
-
- return ret;
+ u64 timeout)
+{
+ unsigned long timeout_hi = (unsigned long)(timeout>>32);
+ unsigned long timeout_lo = (unsigned long)timeout;
+ return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
}
static inline int
HYPERVISOR_dom0_op(
- dom0_op_t *dom0_op)
-{
- int ret;
- unsigned long ign1;
-
- dom0_op->interface_version = DOM0_INTERFACE_VERSION;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1)
- : "0" (__HYPERVISOR_dom0_op), "1" (dom0_op)
- : "memory");
-
- return ret;
+ dom0_op_t *dom0_op)
+{
+ dom0_op->interface_version = DOM0_INTERFACE_VERSION;
+ return _hypercall1(int, dom0_op, dom0_op);
}
static inline int
HYPERVISOR_set_debugreg(
- int reg, unsigned long value)
-{
- int ret;
- unsigned long ign1, ign2;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2)
- : "0" (__HYPERVISOR_set_debugreg), "1" (reg), "2" (value)
- : "memory" );
-
- return ret;
+ int reg, unsigned long value)
+{
+ return _hypercall2(int, set_debugreg, reg, value);
}
static inline unsigned long
HYPERVISOR_get_debugreg(
- int reg)
-{
- unsigned long ret;
- unsigned long ign;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign)
- : "0" (__HYPERVISOR_get_debugreg), "1" (reg)
- : "memory" );
-
- return ret;
+ int reg)
+{
+ return _hypercall1(unsigned long, get_debugreg, reg);
}
static inline int
HYPERVISOR_update_descriptor(
- u64 ma, u64 desc)
-{
- int ret;
- unsigned long ign1, ign2, ign3, ign4;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
- : "0" (__HYPERVISOR_update_descriptor),
- "1" ((unsigned long)ma), "2" ((unsigned long)(ma>>32)),
- "3" ((unsigned long)desc), "4" ((unsigned long)(desc>>32))
- : "memory" );
-
- return ret;
+ u64 ma, u64 desc)
+{
+ return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
}
static inline int
HYPERVISOR_dom_mem_op(
- unsigned int op, unsigned long *extent_list,
- unsigned long nr_extents, unsigned int extent_order)
-{
- int ret;
- unsigned long ign1, ign2, ign3, ign4, ign5;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4),
- "=D" (ign5)
- : "0" (__HYPERVISOR_dom_mem_op), "1" (op), "2" (extent_list),
- "3" (nr_extents), "4" (extent_order), "5" (DOMID_SELF)
- : "memory" );
-
- return ret;
+ unsigned int op, unsigned long *extent_list,
+ unsigned long nr_extents, unsigned int extent_order)
+{
+ return _hypercall5(int, dom_mem_op, op, extent_list,
+ nr_extents, extent_order, DOMID_SELF);
}
static inline int
HYPERVISOR_multicall(
- void *call_list, int nr_calls)
-{
- int ret;
- unsigned long ign1, ign2;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2)
- : "0" (__HYPERVISOR_multicall), "1" (call_list), "2" (nr_calls)
- : "memory" );
-
- return ret;
+ void *call_list, int nr_calls)
+{
+ return _hypercall2(int, multicall, call_list, nr_calls);
}
static inline int
HYPERVISOR_update_va_mapping(
- unsigned long va, pte_t new_val, unsigned long flags)
-{
- int ret;
- unsigned long ign1, ign2, ign3, ign4;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
- : "0" (__HYPERVISOR_update_va_mapping),
- "1" (va), "2" ((new_val).pte_low),
+ unsigned long va, pte_t new_val, unsigned long flags)
+{
+ unsigned long pte_hi = 0;
#ifdef CONFIG_X86_PAE
- "3" ((new_val).pte_high),
-#else
- "3" (0),
+ pte_hi = new_val.pte_high;
#endif
- "4" (flags)
- : "memory" );
-
- return ret;
+ return _hypercall4(int, update_va_mapping, va,
+ new_val.pte_low, pte_hi, flags);
}
static inline int
HYPERVISOR_event_channel_op(
- void *op)
-{
- int ret;
- unsigned long ignore;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ignore)
- : "0" (__HYPERVISOR_event_channel_op), "1" (op)
- : "memory" );
-
- return ret;
+ void *op)
+{
+ return _hypercall1(int, event_channel_op, op);
}
static inline int
HYPERVISOR_xen_version(
- int cmd)
-{
- int ret;
- unsigned long ignore;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ignore)
- : "0" (__HYPERVISOR_xen_version), "1" (cmd)
- : "memory" );
-
- return ret;
+ int cmd)
+{
+ return _hypercall1(int, xen_version, cmd);
}
static inline int
HYPERVISOR_console_io(
- int cmd, int count, char *str)
-{
- int ret;
- unsigned long ign1, ign2, ign3;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
- : "0" (__HYPERVISOR_console_io), "1" (cmd), "2" (count), "3" (str)
- : "memory" );
-
- return ret;
+ int cmd, int count, char *str)
+{
+ return _hypercall3(int, console_io, cmd, count, str);
}
static inline int
HYPERVISOR_physdev_op(
- void *physdev_op)
-{
- int ret;
- unsigned long ign;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign)
- : "0" (__HYPERVISOR_physdev_op), "1" (physdev_op)
- : "memory" );
-
- return ret;
+ void *physdev_op)
+{
+ return _hypercall1(int, physdev_op, physdev_op);
}
static inline int
HYPERVISOR_grant_table_op(
- unsigned int cmd, void *uop, unsigned int count)
-{
- int ret;
- unsigned long ign1, ign2, ign3;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
- : "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (uop), "3" (count)
- : "memory" );
-
- return ret;
+ unsigned int cmd, void *uop, unsigned int count)
+{
+ return _hypercall3(int, grant_table_op, cmd, uop, count);
}
static inline int
HYPERVISOR_update_va_mapping_otherdomain(
- unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
-{
- int ret;
- unsigned long ign1, ign2, ign3, ign4, ign5;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3),
- "=S" (ign4), "=D" (ign5)
- : "0" (__HYPERVISOR_update_va_mapping_otherdomain),
- "1" (va), "2" ((new_val).pte_low),
+ unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
+{
+ unsigned long pte_hi = 0;
#ifdef CONFIG_X86_PAE
- "3" ((new_val).pte_high),
-#else
- "3" (0),
+ pte_hi = new_val.pte_high;
#endif
- "4" (flags), "5" (domid) :
- "memory" );
-
- return ret;
+ return _hypercall5(int, update_va_mapping_otherdomain, va,
+ new_val.pte_low, pte_hi, flags, domid);
}
static inline int
HYPERVISOR_vm_assist(
- unsigned int cmd, unsigned int type)
-{
- int ret;
- unsigned long ign1, ign2;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2)
- : "0" (__HYPERVISOR_vm_assist), "1" (cmd), "2" (type)
- : "memory" );
-
- return ret;
+ unsigned int cmd, unsigned int type)
+{
+ return _hypercall2(int, vm_assist, cmd, type);
}
static inline int
HYPERVISOR_boot_vcpu(
- unsigned long vcpu, vcpu_guest_context_t *ctxt)
-{
- int ret;
- unsigned long ign1, ign2;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2)
- : "0" (__HYPERVISOR_boot_vcpu), "1" (vcpu), "2" (ctxt)
- : "memory");
-
- return ret;
+ unsigned long vcpu, vcpu_guest_context_t *ctxt)
+{
+ return _hypercall2(int, boot_vcpu, vcpu, ctxt);
+}
+
+static inline int
+HYPERVISOR_vcpu_up(
+ int vcpu)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_vcpu_up |
+ (vcpu << SCHEDOP_vcpushift), 0);
+}
+
+static inline int
+HYPERVISOR_vcpu_pickle(
+ int vcpu, vcpu_guest_context_t *ctxt)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_vcpu_pickle |
+ (vcpu << SCHEDOP_vcpushift), ctxt);
+}
+
+static inline int
+HYPERVISOR_suspend(
+ unsigned long srec)
+{
+ int ret;
+ unsigned long ign1, ign2;
+
+ /* On suspend, control software expects a suspend record in %esi. */
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=S" (ign2)
+ : "0" (__HYPERVISOR_sched_op),
+ "1" (SCHEDOP_shutdown | (SHUTDOWN_suspend <<
+ SCHEDOP_reasonshift)),
+ "2" (srec) : "memory", "ecx");
+
+ return ret;
}
static inline int
HYPERVISOR_vcpu_down(
- int vcpu)
-{
- int ret;
- unsigned long ign1;
- /* Yes, I really do want to clobber edx here: when we resume a
- vcpu after unpickling a multi-processor domain, it returns
- here, but clobbers all of the call clobbered registers. */
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1)
- : "0" (__HYPERVISOR_sched_op),
- "1" (SCHEDOP_vcpu_down | (vcpu << SCHEDOP_vcpushift))
- : "memory", "ecx", "edx" );
-
- return ret;
-}
-
-static inline int
-HYPERVISOR_vcpu_up(
- int vcpu)
-{
- int ret;
- unsigned long ign1;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1)
- : "0" (__HYPERVISOR_sched_op),
- "1" (SCHEDOP_vcpu_up | (vcpu << SCHEDOP_vcpushift))
- : "memory", "ecx" );
-
- return ret;
-}
-
-static inline int
-HYPERVISOR_vcpu_pickle(
- int vcpu, vcpu_guest_context_t *ctxt)
-{
- int ret;
- unsigned long ign1, ign2;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2)
- : "0" (__HYPERVISOR_sched_op),
- "1" (SCHEDOP_vcpu_pickle | (vcpu << SCHEDOP_vcpushift)),
- "2" (ctxt)
- : "memory" );
-
- return ret;
+ int vcpu)
+{
+ int ret;
+ unsigned long ign1;
+ /* Yes, I really do want to clobber edx here: when we resume a
+ vcpu after unpickling a multi-processor domain, it returns
+ here, but clobbers all of the call clobbered registers. */
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1)
+ : "0" (__HYPERVISOR_sched_op),
+ "1" (SCHEDOP_vcpu_down | (vcpu << SCHEDOP_vcpushift))
+ : "memory", "ecx", "edx" );
+ return ret;
}
#endif /* __HYPERCALL_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r 2b95125015a5 -r 37e9c9cd6c14
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h Fri Aug
26 13:06:49 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h Fri Aug
26 17:42:34 2005
@@ -4,6 +4,10 @@
* Linux-specific hypervisor handling.
*
* Copyright (c) 2002-2004, K A Fraser
+ *
+ * 64-bit updates:
+ * Benjamin Liu <benjamin.liu@xxxxxxxxx>
+ * Jun Nakajima <jun.nakajima@xxxxxxxxx>
*
* This file may be distributed separately from the Linux kernel, or
* incorporated into other software packages, subject to the following license:
@@ -26,497 +30,331 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
-/*
- * Benjamin Liu <benjamin.liu@xxxxxxxxx>
- * Jun Nakajima <jun.nakajima@xxxxxxxxx>
- * Ported to x86-64.
- *
- */
#ifndef __HYPERCALL_H__
#define __HYPERCALL_H__
+
#include <asm-xen/xen-public/xen.h>
#define __syscall_clobber "r11","rcx","memory"
-/*
- * Assembler stubs for hyper-calls.
- */
+#define _hypercall0(type, name) \
+({ \
+ long __res; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res) \
+ : "0" (__HYPERVISOR_##name) \
+ : __syscall_clobber ); \
+ (type)__res; \
+})
+
+#define _hypercall1(type, name, a1) \
+({ \
+ long __res, __ign1; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res), "=D" (__ign1) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)) \
+ : __syscall_clobber ); \
+ (type)__res; \
+})
+
+#define _hypercall2(type, name, a1, a2) \
+({ \
+ long __res, __ign1, __ign2; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res), "=D" (__ign1), "=S" (__ign2) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
+ "2" ((long)(a2)) \
+ : __syscall_clobber ); \
+ (type)__res; \
+})
+
+#define _hypercall3(type, name, a1, a2, a3) \
+({ \
+ long __res, __ign1, __ign2, __ign3; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \
+ "=d" (__ign3) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
+ "2" ((long)(a2)), "3" ((long)(a3)) \
+ : __syscall_clobber ); \
+ (type)__res; \
+})
+
+#define _hypercall4(type, name, a1, a2, a3, a4) \
+({ \
+ long __res, __ign1, __ign2, __ign3; \
+ asm volatile ( \
+ "movq %8,%%r10; " TRAP_INSTR \
+ : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \
+ "=d" (__ign3) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
+ "2" ((long)(a2)), "3" ((long)(a3)), \
+ "g" ((long)(a4)) \
+ : __syscall_clobber, "r10" ); \
+ (type)__res; \
+})
+
+#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
+({ \
+ long __res, __ign1, __ign2, __ign3; \
+ asm volatile ( \
+ "movq %8,%%r10; movq %9,%%r8; " TRAP_INSTR \
+ : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \
+ "=d" (__ign3) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
+ "2" ((long)(a2)), "3" ((long)(a3)), \
+ "g" ((long)(a4)), "g" ((long)(a5)) \
+ : __syscall_clobber, "r10", "r8" ); \
+ (type)__res; \
+})
+
static inline int
HYPERVISOR_set_trap_table(
- trap_info_t *table)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_set_trap_table), "D" (table)
- : __syscall_clobber );
-
- return ret;
+ trap_info_t *table)
+{
+ return _hypercall1(int, set_trap_table, table);
}
static inline int
HYPERVISOR_mmu_update(
- mmu_update_t *req, int count, int *success_count, domid_t domid)
-{
- int ret;
-
- __asm__ __volatile__ (
- "movq %5, %%r10;" TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_mmu_update), "D" (req), "S"
((long)count),
- "d" (success_count), "g" ((unsigned long)domid)
- : __syscall_clobber, "r10" );
-
- return ret;
+ mmu_update_t *req, int count, int *success_count, domid_t domid)
+{
+ return _hypercall4(int, mmu_update, req, count, success_count, domid);
}
static inline int
HYPERVISOR_mmuext_op(
- struct mmuext_op *op, int count, int *success_count, domid_t domid)
-{
- int ret;
-
- __asm__ __volatile__ (
- "movq %5, %%r10;" TRAP_INSTR
- : "=a" (ret)
- : "0" (__HYPERVISOR_mmuext_op), "D" (op), "S" ((long)count),
- "d" (success_count), "g" ((unsigned long)domid)
- : __syscall_clobber, "r10" );
-
- return ret;
+ struct mmuext_op *op, int count, int *success_count, domid_t domid)
+{
+ return _hypercall4(int, mmuext_op, op, count, success_count, domid);
}
static inline int
HYPERVISOR_set_gdt(
- unsigned long *frame_list, int entries)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_set_gdt), "D" (frame_list), "S"
((long)entries)
- : __syscall_clobber );
-
-
- return ret;
-}
+ unsigned long *frame_list, int entries)
+{
+ return _hypercall2(int, set_gdt, frame_list, entries);
+}
+
static inline int
HYPERVISOR_stack_switch(
- unsigned long ss, unsigned long esp)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_stack_switch), "D" (ss), "S" (esp)
- : __syscall_clobber );
-
- return ret;
+ unsigned long ss, unsigned long esp)
+{
+ return _hypercall2(int, stack_switch, ss, esp);
}
static inline int
HYPERVISOR_set_callbacks(
- unsigned long event_address, unsigned long failsafe_address,
- unsigned long syscall_address)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_set_callbacks), "D" (event_address),
- "S" (failsafe_address), "d" (syscall_address)
- : __syscall_clobber );
-
- return ret;
+ unsigned long event_address, unsigned long failsafe_address,
+ unsigned long syscall_address)
+{
+ return _hypercall3(int, set_callbacks,
+ event_address, failsafe_address, syscall_address);
}
static inline int
HYPERVISOR_fpu_taskswitch(
- int set)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" ((unsigned long)__HYPERVISOR_fpu_taskswitch),
- "D" ((unsigned long) set) : __syscall_clobber );
-
- return ret;
+ int set)
+{
+ return _hypercall1(int, fpu_taskswitch, set);
}
static inline int
HYPERVISOR_yield(
- void)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_sched_op), "D" ((unsigned
long)SCHEDOP_yield)
- : __syscall_clobber );
-
- return ret;
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_yield, 0);
}
static inline int
HYPERVISOR_block(
- void)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_sched_op), "D" ((unsigned
long)SCHEDOP_block)
- : __syscall_clobber );
-
- return ret;
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_block, 0);
}
static inline int
HYPERVISOR_shutdown(
- void)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_sched_op),
- "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_poweroff <<
SCHEDOP_reasonshift)))
- : __syscall_clobber );
-
- return ret;
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+ (SHUTDOWN_poweroff << SCHEDOP_reasonshift), 0);
}
static inline int
HYPERVISOR_reboot(
- void)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_sched_op),
- "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_reboot <<
SCHEDOP_reasonshift)))
- : __syscall_clobber );
-
- return ret;
-}
-
-static inline int
-HYPERVISOR_suspend(
- unsigned long srec)
-{
- int ret;
-
- /* NB. On suspend, control software expects a suspend record in %esi. */
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_sched_op),
- "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_suspend <<
SCHEDOP_reasonshift))),
- "S" (srec)
- : __syscall_clobber );
-
- return ret;
-}
-
-/*
- * We can have the timeout value in a single argument for the hypercall, but
- * that will break the common code.
- */
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+ (SHUTDOWN_reboot << SCHEDOP_reasonshift), 0);
+}
+
static inline long
HYPERVISOR_set_timer_op(
- u64 timeout)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_set_timer_op),
- "D" (timeout)
- : __syscall_clobber );
-
- return ret;
+ u64 timeout)
+{
+ return _hypercall1(long, set_timer_op, timeout);
}
static inline int
HYPERVISOR_dom0_op(
- dom0_op_t *dom0_op)
-{
- int ret;
-
- dom0_op->interface_version = DOM0_INTERFACE_VERSION;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_dom0_op), "D" (dom0_op)
- : __syscall_clobber );
-
- return ret;
+ dom0_op_t *dom0_op)
+{
+ dom0_op->interface_version = DOM0_INTERFACE_VERSION;
+ return _hypercall1(int, dom0_op, dom0_op);
}
static inline int
HYPERVISOR_set_debugreg(
- int reg, unsigned long value)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_set_debugreg), "D" ((unsigned
long)reg), "S" (value)
- : __syscall_clobber );
-
- return ret;
+ int reg, unsigned long value)
+{
+ return _hypercall2(int, set_debugreg, reg, value);
}
static inline unsigned long
HYPERVISOR_get_debugreg(
- int reg)
-{
- unsigned long ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_get_debugreg), "D" ((unsigned
long)reg)
- : __syscall_clobber );
-
- return ret;
+ int reg)
+{
+ return _hypercall1(unsigned long, get_debugreg, reg);
}
static inline int
HYPERVISOR_update_descriptor(
- unsigned long ma, unsigned long word)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_update_descriptor), "D" (ma),
- "S" (word)
- : __syscall_clobber );
-
- return ret;
+ unsigned long ma, unsigned long word)
+{
+ return _hypercall2(int, update_descriptor, ma, word);
}
static inline int
HYPERVISOR_dom_mem_op(
- unsigned int op, unsigned long *extent_list,
- unsigned long nr_extents, unsigned int extent_order)
-{
- int ret;
-
- __asm__ __volatile__ (
- "movq %5,%%r10; movq %6,%%r8;" TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_dom_mem_op), "D" ((unsigned
long)op), "S" (extent_list),
- "d" (nr_extents), "g" ((unsigned long) extent_order), "g" ((unsigned
long) DOMID_SELF)
- : __syscall_clobber,"r8","r10");
-
- return ret;
+ unsigned int op, unsigned long *extent_list,
+ unsigned long nr_extents, unsigned int extent_order)
+{
+ return _hypercall5(int, dom_mem_op, op, extent_list,
+ nr_extents, extent_order, DOMID_SELF);
}
static inline int
HYPERVISOR_multicall(
- void *call_list, int nr_calls)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_multicall), "D" (call_list), "S"
((unsigned long)nr_calls)
- : __syscall_clobber);
-
- return ret;
+ void *call_list, int nr_calls)
+{
+ return _hypercall2(int, multicall, call_list, nr_calls);
}
static inline int
HYPERVISOR_update_va_mapping(
- unsigned long page_nr, pte_t new_val, unsigned long flags)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_update_va_mapping),
- "D" (page_nr), "S" (new_val.pte), "d" (flags)
- : __syscall_clobber);
-
- return ret;
+ unsigned long va, pte_t new_val, unsigned long flags)
+{
+ return _hypercall3(int, update_va_mapping, va, new_val.pte, flags);
}
static inline int
HYPERVISOR_event_channel_op(
- void *op)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_event_channel_op), "D" (op)
- : __syscall_clobber);
-
- return ret;
+ void *op)
+{
+ return _hypercall1(int, event_channel_op, op);
}
static inline int
HYPERVISOR_xen_version(
- int cmd)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_xen_version), "D" ((unsigned
long)cmd)
- : __syscall_clobber);
-
- return ret;
+ int cmd)
+{
+ return _hypercall1(int, xen_version, cmd);
}
static inline int
HYPERVISOR_console_io(
- int cmd, int count, char *str)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_console_io), "D" ((unsigned
long)cmd), "S" ((unsigned long)count), "d" (str)
- : __syscall_clobber);
-
- return ret;
+ int cmd, int count, char *str)
+{
+ return _hypercall3(int, console_io, cmd, count, str);
}
static inline int
HYPERVISOR_physdev_op(
- void *physdev_op)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_physdev_op), "D" (physdev_op)
- : __syscall_clobber);
-
- return ret;
+ void *physdev_op)
+{
+ return _hypercall1(int, physdev_op, physdev_op);
}
static inline int
HYPERVISOR_grant_table_op(
- unsigned int cmd, void *uop, unsigned int count)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_grant_table_op), "D" ((unsigned
long)cmd), "S" ((unsigned long)uop), "d" (count)
- : __syscall_clobber);
-
- return ret;
+ unsigned int cmd, void *uop, unsigned int count)
+{
+ return _hypercall3(int, grant_table_op, cmd, uop, count);
}
static inline int
HYPERVISOR_update_va_mapping_otherdomain(
- unsigned long page_nr, pte_t new_val, unsigned long flags, domid_t domid)
-{
- int ret;
-
- __asm__ __volatile__ (
- "movq %5, %%r10;" TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_update_va_mapping_otherdomain),
- "D" (page_nr), "S" (new_val.pte), "d" (flags), "g" ((unsigned
long)domid)
- : __syscall_clobber,"r10");
-
- return ret;
+ unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
+{
+ return _hypercall4(int, update_va_mapping_otherdomain, va,
+ new_val.pte, flags, domid);
}
static inline int
HYPERVISOR_vm_assist(
- unsigned int cmd, unsigned int type)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_vm_assist), "D" ((unsigned
long)cmd), "S" ((unsigned long)type)
- : __syscall_clobber);
-
- return ret;
+ unsigned int cmd, unsigned int type)
+{
+ return _hypercall2(int, vm_assist, cmd, type);
+}
+
+static inline int
+HYPERVISOR_boot_vcpu(
+ unsigned long vcpu, vcpu_guest_context_t *ctxt)
+{
+ return _hypercall2(int, boot_vcpu, vcpu, ctxt);
+}
+
+static inline int
+HYPERVISOR_vcpu_up(
+ int vcpu)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_vcpu_up |
+ (vcpu << SCHEDOP_vcpushift), 0);
+}
+
+static inline int
+HYPERVISOR_vcpu_pickle(
+ int vcpu, vcpu_guest_context_t *ctxt)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_vcpu_pickle |
+ (vcpu << SCHEDOP_vcpushift), ctxt);
}
static inline int
HYPERVISOR_switch_to_user(void)
{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" ((unsigned long)__HYPERVISOR_switch_to_user) :
__syscall_clobber );
-
- return ret;
-}
-
-static inline int
-HYPERVISOR_boot_vcpu(
- unsigned long vcpu, vcpu_guest_context_t *ctxt)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" (__HYPERVISOR_boot_vcpu), "D" (vcpu), "S" (ctxt)
- : __syscall_clobber);
-
- return ret;
+ return _hypercall0(int, switch_to_user);
}
static inline int
HYPERVISOR_set_segment_base(
- int reg, unsigned long value)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_set_segment_base), "D" ((unsigned
long)reg), "S" (value)
- : __syscall_clobber );
-
- return ret;
-}
-
-static inline int
-HYPERVISOR_vcpu_pickle(
- int vcpu, vcpu_guest_context_t *ctxt)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_sched_op),
- "D" ((unsigned long)SCHEDOP_vcpu_pickle | (vcpu << SCHEDOP_vcpushift)),
- "S" ((unsigned long)ctxt)
- : __syscall_clobber );
-
- return ret;
+ int reg, unsigned long value)
+{
+ return _hypercall2(int, set_segment_base, reg, value);
+}
+
+static inline int
+HYPERVISOR_suspend(
+ unsigned long srec)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+ (SHUTDOWN_suspend << SCHEDOP_reasonshift), srec);
}
#endif /* __HYPERCALL_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r 2b95125015a5 -r 37e9c9cd6c14 xen/arch/x86/x86_32/asm-offsets.c
--- a/xen/arch/x86/x86_32/asm-offsets.c Fri Aug 26 13:06:49 2005
+++ b/xen/arch/x86/x86_32/asm-offsets.c Fri Aug 26 17:42:34 2005
@@ -71,6 +71,9 @@
OFFSET(VCPUINFO_upcall_mask, vcpu_info_t, evtchn_upcall_mask);
BLANK();
+ DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info));
+ BLANK();
+
OFFSET(TRAPBOUNCE_error_code, struct trap_bounce, error_code);
OFFSET(TRAPBOUNCE_cr2, struct trap_bounce, cr2);
OFFSET(TRAPBOUNCE_flags, struct trap_bounce, flags);
diff -r 2b95125015a5 -r 37e9c9cd6c14 xen/arch/x86/x86_32/entry.S
--- a/xen/arch/x86/x86_32/entry.S Fri Aug 26 13:06:49 2005
+++ b/xen/arch/x86/x86_32/entry.S Fri Aug 26 17:42:34 2005
@@ -60,6 +60,11 @@
#include <asm/apicdef.h>
#include <asm/page.h>
#include <public/xen.h>
+
+#define GET_GUEST_REGS(reg) \
+ movl $~(STACK_SIZE-1),reg; \
+ andl %esp,reg; \
+ orl $(STACK_SIZE-CPUINFO_sizeof),reg;
#define GET_CURRENT(reg) \
movl $STACK_SIZE-4, reg; \
@@ -273,7 +278,41 @@
GET_CURRENT(%ebx)
andl $(NR_hypercalls-1),%eax
PERFC_INCR(PERFC_hypercalls, %eax)
+#ifndef NDEBUG
+ /* Deliberately corrupt parameter regs not used by this hypercall. */
+ pushl %eax
+ pushl UREGS_eip+4(%esp)
+ pushl 28(%esp) # EBP
+ pushl 28(%esp) # EDI
+ pushl 28(%esp) # ESI
+ pushl 28(%esp) # EDX
+ pushl 28(%esp) # ECX
+ pushl 28(%esp) # EBX
+ movzb hypercall_args_table(,%eax,1),%ecx
+ leal (%esp,%ecx,4),%edi
+ subl $6,%ecx
+ negl %ecx
+ movl %eax,%esi
+ movl $0xDEADBEEF,%eax
+ rep stosl
+ movl %esi,%eax
+#endif
call *hypercall_table(,%eax,4)
+#ifndef NDEBUG
+ /* Deliberately corrupt parameter regs used by this hypercall. */
+ addl $24,%esp # Shadow parameters
+ popl %ecx # Shadow EIP
+ cmpl %ecx,UREGS_eip(%esp)
+ popl %ecx # Shadow hypercall index
+ jne skip_clobber # If EIP has changed then don't clobber
+ movzb hypercall_args_table(,%ecx,1),%ecx
+ movl %esp,%edi
+ movl %eax,%esi
+ movl $0xDEADBEEF,%eax
+ rep stosl
+ movl %esi,%eax
+skip_clobber:
+#endif
movl %eax,UREGS_eax(%esp) # save the return value
test_all_events:
@@ -674,12 +713,14 @@
do_arch_sched_op:
# Ensure we return success even if we return via schedule_tail()
xorl %eax,%eax
- movl %eax,UREGS_eax+4(%esp)
+ GET_GUEST_REGS(%ecx)
+ movl %eax,UREGS_eax(%ecx)
jmp do_sched_op
do_switch_vm86:
- # Discard the return address
- addl $4,%esp
+ # Reset the stack pointer
+ GET_GUEST_REGS(%ecx)
+ movl %ecx,%esp
# GS:ESI == Ring-1 stack activation
movl UREGS_esp(%esp),%esi
@@ -768,3 +809,36 @@
.rept NR_hypercalls-((.-hypercall_table)/4)
.long do_ni_hypercall
.endr
+
+ENTRY(hypercall_args_table)
+ .byte 1 /* do_set_trap_table */ /* 0 */
+ .byte 4 /* do_mmu_update */
+ .byte 2 /* do_set_gdt */
+ .byte 2 /* do_stack_switch */
+ .byte 4 /* do_set_callbacks */
+ .byte 1 /* do_fpu_taskswitch */ /* 5 */
+ .byte 2 /* do_arch_sched_op */
+ .byte 1 /* do_dom0_op */
+ .byte 2 /* do_set_debugreg */
+ .byte 1 /* do_get_debugreg */
+ .byte 4 /* do_update_descriptor */ /* 10 */
+ .byte 0 /* do_ni_hypercall */
+ .byte 5 /* do_dom_mem_op */
+ .byte 2 /* do_multicall */
+ .byte 4 /* do_update_va_mapping */
+ .byte 2 /* do_set_timer_op */ /* 15 */
+ .byte 1 /* do_event_channel_op */
+ .byte 1 /* do_xen_version */
+ .byte 3 /* do_console_io */
+ .byte 1 /* do_physdev_op */
+ .byte 3 /* do_grant_table_op */ /* 20 */
+ .byte 2 /* do_vm_assist */
+ .byte 5 /* do_update_va_mapping_otherdomain */
+ .byte 0 /* do_switch_vm86 */
+ .byte 2 /* do_boot_vcpu */
+ .byte 0 /* do_ni_hypercall */ /* 25 */
+ .byte 4 /* do_mmuext_op */
+ .byte 1 /* do_acm_op */
+ .rept NR_hypercalls-(.-hypercall_args_table)
+ .byte 0 /* do_ni_hypercall */
+ .endr
diff -r 2b95125015a5 -r 37e9c9cd6c14 xen/arch/x86/x86_64/asm-offsets.c
--- a/xen/arch/x86/x86_64/asm-offsets.c Fri Aug 26 13:06:49 2005
+++ b/xen/arch/x86/x86_64/asm-offsets.c Fri Aug 26 17:42:34 2005
@@ -71,6 +71,9 @@
OFFSET(VCPUINFO_upcall_mask, vcpu_info_t, evtchn_upcall_mask);
BLANK();
+ DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info));
+ BLANK();
+
OFFSET(TRAPBOUNCE_error_code, struct trap_bounce, error_code);
OFFSET(TRAPBOUNCE_cr2, struct trap_bounce, cr2);
OFFSET(TRAPBOUNCE_flags, struct trap_bounce, flags);
diff -r 2b95125015a5 -r 37e9c9cd6c14 xen/arch/x86/x86_64/entry.S
--- a/xen/arch/x86/x86_64/entry.S Fri Aug 26 13:06:49 2005
+++ b/xen/arch/x86/x86_64/entry.S Fri Aug 26 17:42:34 2005
@@ -11,6 +11,11 @@
#include <asm/apicdef.h>
#include <asm/page.h>
#include <public/xen.h>
+
+#define GET_GUEST_REGS(reg) \
+ movq $~(STACK_SIZE-1),reg; \
+ andq %rsp,reg; \
+ orq $(STACK_SIZE-CPUINFO_sizeof),reg;
#define GET_CURRENT(reg) \
movq $STACK_SIZE-8, reg; \
@@ -120,10 +125,42 @@
/*hypercall:*/
movq %r10,%rcx
andq $(NR_hypercalls-1),%rax
+#ifndef NDEBUG
+ /* Deliberately corrupt parameter regs not used by this hypercall. */
+ pushq %rdi; pushq %rsi; pushq %rdx; pushq %rcx; pushq %r8 ; pushq %r9
+ leaq hypercall_args_table(%rip),%r10
+ movq $6,%rcx
+ sub (%r10,%rax,1),%cl
+ movq %rsp,%rdi
+ movl $0xDEADBEEF,%eax
+ rep stosq
+ popq %r9 ; popq %r8 ; popq %rcx; popq %rdx; popq %rsi; popq %rdi
+ movq UREGS_rax(%rsp),%rax
+ andq $(NR_hypercalls-1),%rax
+ pushq %rax
+ pushq UREGS_rip+8(%rsp)
+#endif
leaq hypercall_table(%rip),%r10
PERFC_INCR(PERFC_hypercalls, %rax)
callq *(%r10,%rax,8)
- movq %rax,UREGS_rax(%rsp) # save the return value
+#ifndef NDEBUG
+ /* Deliberately corrupt parameter regs used by this hypercall. */
+ popq %r10 # Shadow RIP
+ cmpq %r10,UREGS_rip(%rsp)
+ popq %rcx # Shadow hypercall index
+ jne skip_clobber /* If RIP has changed then don't clobber. */
+ leaq hypercall_args_table(%rip),%r10
+ movb (%r10,%rcx,1),%cl
+ movl $0xDEADBEEF,%r10d
+ cmpb $1,%cl; jb skip_clobber; movq %r10,UREGS_rdi(%rsp)
+ cmpb $2,%cl; jb skip_clobber; movq %r10,UREGS_rsi(%rsp)
+ cmpb $3,%cl; jb skip_clobber; movq %r10,UREGS_rdx(%rsp)
+ cmpb $4,%cl; jb skip_clobber; movq %r10,UREGS_r10(%rsp)
+ cmpb $5,%cl; jb skip_clobber; movq %r10,UREGS_r8(%rsp)
+ cmpb $6,%cl; jb skip_clobber; movq %r10,UREGS_r9(%rsp)
+skip_clobber:
+#endif
+ movq %rax,UREGS_rax(%rsp) # save the return value
/* %rbx: struct vcpu */
test_all_events:
@@ -538,7 +575,8 @@
do_arch_sched_op:
# Ensure we return success even if we return via schedule_tail()
xorl %eax,%eax
- movq %rax,UREGS_rax+8(%rsp)
+ GET_GUEST_REGS(%r10)
+ movq %rax,UREGS_rax(%r10)
jmp do_sched_op
.data
@@ -597,3 +635,36 @@
.rept NR_hypercalls-((.-hypercall_table)/4)
.quad do_ni_hypercall
.endr
+
+ENTRY(hypercall_args_table)
+ .byte 1 /* do_set_trap_table */ /* 0 */
+ .byte 4 /* do_mmu_update */
+ .byte 2 /* do_set_gdt */
+ .byte 2 /* do_stack_switch */
+ .byte 3 /* do_set_callbacks */
+ .byte 1 /* do_fpu_taskswitch */ /* 5 */
+ .byte 2 /* do_arch_sched_op */
+ .byte 1 /* do_dom0_op */
+ .byte 2 /* do_set_debugreg */
+ .byte 1 /* do_get_debugreg */
+ .byte 2 /* do_update_descriptor */ /* 10 */
+ .byte 0 /* do_ni_hypercall */
+ .byte 5 /* do_dom_mem_op */
+ .byte 2 /* do_multicall */
+ .byte 3 /* do_update_va_mapping */
+ .byte 1 /* do_set_timer_op */ /* 15 */
+ .byte 1 /* do_event_channel_op */
+ .byte 1 /* do_xen_version */
+ .byte 3 /* do_console_io */
+ .byte 1 /* do_physdev_op */
+ .byte 3 /* do_grant_table_op */ /* 20 */
+ .byte 2 /* do_vm_assist */
+ .byte 4 /* do_update_va_mapping_otherdomain */
+ .byte 0 /* do_switch_to_user */
+ .byte 2 /* do_boot_vcpu */
+ .byte 2 /* do_set_segment_base */ /* 25 */
+ .byte 4 /* do_mmuext_op */
+ .byte 1 /* do_acm_op */
+ .rept NR_hypercalls-(.-hypercall_args_table)
+ .byte 0 /* do_ni_hypercall */
+ .endr
diff -r 2b95125015a5 -r 37e9c9cd6c14 xen/common/multicall.c
--- a/xen/common/multicall.c Fri Aug 26 13:06:49 2005
+++ b/xen/common/multicall.c Fri Aug 26 17:42:34 2005
@@ -45,6 +45,18 @@
do_multicall_call(&mcs->call);
+#ifndef NDEBUG
+ {
+ /*
+ * Deliberately corrupt the contents of the multicall structure.
+ * The caller must depend only on the 'result' field on return.
+ */
+ multicall_entry_t corrupt;
+ memset(&corrupt, 0xAA, sizeof(corrupt));
+ (void)__copy_to_user(&call_list[i], &corrupt, sizeof(corrupt));
+ }
+#endif
+
if ( unlikely(__put_user(mcs->call.result, &call_list[i].result)) )
{
DPRINTK("Error writing result back to multicall block.\n");
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|