regs->pc -= 4; /* re-execute 'hvc #XEN_HYPERCALL_TAG' */
}
+void arch_hypercall_tasklet_result(struct vcpu *v, long res)
+{
+ struct cpu_user_regs *regs = &v->arch.cpu_info->guest_cpu_user_regs;
+
+ HYPERCALL_RESULT_REG(regs) = res;
+}
+
static bool check_multicall_32bit_clean(struct multicall_entry *multi)
{
int i;
#undef NEXT_ARG
+void arch_hypercall_tasklet_result(struct vcpu *v, long res)
+{
+ struct cpu_user_regs *regs = &v->arch.user_regs;
+
+ regs->rax = res;
+}
+
int hypercall_xlat_continuation(unsigned int *id, unsigned int nr,
unsigned int mask, ...)
{
{
struct migrate_info *info = (struct migrate_info *)_info;
struct vcpu *v = info->vcpu;
+ long res = -EINVAL;
/* Wait for vcpu to sleep so that we can access its register state. */
vcpu_sleep_sync(v);
this_cpu(continue_info) = info;
- return_reg(v) = (info->cpu == smp_processor_id())
- ? info->func(info->data) : -EINVAL;
+
+ if ( likely(info->cpu == smp_processor_id()) )
+ res = info->func(info->data);
+
+ arch_hypercall_tasklet_result(v, res);
+
this_cpu(continue_info) = NULL;
if ( info->nest-- == 0 )
return (diff == 0);
}
-#define return_reg(v) ((v)->arch.cpu_info->guest_cpu_user_regs.r0)
-
register_t get_user_reg(struct cpu_user_regs *regs, int reg);
void set_user_reg(struct cpu_user_regs *regs, int reg, register_t val);
(diff == 0); \
})
-#define return_reg(v) ((v)->arch.user_regs.rax)
-
#endif /* __X86_REGS_H__ */
int continue_hypercall_on_cpu(
unsigned int cpu, long (*func)(void *data), void *data);
+/*
+ * Companion to continue_hypercall_on_cpu(), to feed func()'s result back into
+ * vcpu regsiter state.
+ */
+void arch_hypercall_tasklet_result(struct vcpu *v, long res);
+
extern unsigned int xen_processor_pmbits;
extern bool_t opt_dom0_vcpus_pin;