void hypercall_cancel_continuation(void)
{
- struct cpu_user_regs *regs = guest_cpu_user_regs();
struct mc_state *mcs = ¤t->mc_state;
if ( mcs->flags & MCSF_in_multicall )
- {
__clear_bit(_MCSF_call_preempted, &mcs->flags);
- }
else
- {
- regs->pc += 4; /* undo re-execute 'hvc #XEN_HYPERCALL_TAG' */
- }
+ current->hcall_preempted = false;
}
unsigned long hypercall_create_continuation(
{
regs = guest_cpu_user_regs();
- /* Ensure the hypercall trap instruction is re-executed. */
- regs->pc -= 4; /* re-execute 'hvc #XEN_HYPERCALL_TAG' */
+ current->hcall_preempted = true;
#ifdef CONFIG_ARM_64
if ( !is_32bit_domain(current->domain) )
unsigned long iss)
{
arm_hypercall_fn_t call = NULL;
-#ifndef NDEBUG
- register_t orig_pc = regs->pc;
-#endif
BUILD_BUG_ON(NR_hypercalls < ARRAY_SIZE(arm_hypercall_table) );
return;
}
+ current->hcall_preempted = false;
+
perfc_incra(hypercalls, *nr);
call = arm_hypercall_table[*nr].fn;
if ( call == NULL )
HYPERCALL_RESULT_REG(regs) = call(HYPERCALL_ARGS(regs));
#ifndef NDEBUG
- /*
- * Clobber argument registers only if pc is unchanged, otherwise
- * this is a hypercall continuation.
- */
- if ( orig_pc == regs->pc )
+ if ( !current->hcall_preempted )
{
+ /* Deliberately corrupt parameter regs used by this hypercall. */
switch ( arm_hypercall_table[*nr].nr_args ) {
case 5: HYPERCALL_ARG5(regs) = 0xDEADBEEF;
case 4: HYPERCALL_ARG4(regs) = 0xDEADBEEF;
*nr = 0xDEADBEEF;
}
#endif
+
+ /* Ensure the hypercall trap instruction is re-executed. */
+ if ( current->hcall_preempted )
+ regs->pc -= 4; /* re-execute 'hvc #XEN_HYPERCALL_TAG' */
}
static bool check_multicall_32bit_clean(struct multicall_entry *multi)