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
- {
- if ( is_pv_vcpu(current) )
- regs->rip += 2; /* skip re-execute 'syscall' / 'int $xx' */
- else
- current->arch.hvm_vcpu.hcall_preempted = 0;
- }
+ current->hcall_preempted = false;
}
unsigned long hypercall_create_continuation(
regs->rax = op;
- /* Ensure the hypercall trap instruction is re-executed. */
- if ( is_pv_vcpu(curr) )
- regs->rip -= 2; /* re-execute 'syscall' / 'int $xx' */
- else
- curr->arch.hvm_vcpu.hcall_preempted = 1;
+ curr->hcall_preempted = true;
if ( is_pv_vcpu(curr) ?
!is_pv_32bit_vcpu(curr) :
return HVM_HCALL_completed;
}
- curr->arch.hvm_vcpu.hcall_preempted = 0;
+ curr->hcall_preempted = false;
if ( mode == 8 )
{
curr->arch.hvm_vcpu.hcall_64bit = 0;
#ifndef NDEBUG
- if ( !curr->arch.hvm_vcpu.hcall_preempted )
+ if ( !curr->hcall_preempted )
{
/* Deliberately corrupt parameter regs used by this hypercall. */
switch ( hypercall_args_table[eax].native )
ebp);
#ifndef NDEBUG
- if ( !curr->arch.hvm_vcpu.hcall_preempted )
+ if ( !curr->hcall_preempted )
{
/* Deliberately corrupt parameter regs used by this hypercall. */
switch ( hypercall_args_table[eax].compat )
HVM_DBG_LOG(DBG_LEVEL_HCALL, "hcall%lu -> %lx", eax, regs->rax);
- if ( curr->arch.hvm_vcpu.hcall_preempted )
+ if ( curr->hcall_preempted )
return HVM_HCALL_preempted;
if ( unlikely(currd->arch.hvm_domain.qemu_mapcache_invalidate) &&
void pv_hypercall(struct cpu_user_regs *regs)
{
struct vcpu *curr = current;
-#ifndef NDEBUG
- unsigned long old_rip = regs->rip;
-#endif
unsigned long eax;
ASSERT(guest_kernel_mode(curr, regs));
return;
}
+ curr->hcall_preempted = false;
+
if ( !is_pv_32bit_vcpu(curr) )
{
unsigned long rdi = regs->rdi;
regs->rax = pv_hypercall_table[eax].native(rdi, rsi, rdx, r10, r8, r9);
#ifndef NDEBUG
- if ( regs->rip == old_rip )
+ if ( !curr->hcall_preempted )
{
/* Deliberately corrupt parameter regs used by this hypercall. */
switch ( hypercall_args_table[eax].native )
regs->_eax = pv_hypercall_table[eax].compat(ebx, ecx, edx, esi, edi, ebp);
#ifndef NDEBUG
- if ( regs->rip == old_rip )
+ if ( !curr->hcall_preempted )
{
/* Deliberately corrupt parameter regs used by this hypercall. */
switch ( hypercall_args_table[eax].compat )
#endif
}
+ /*
+ * PV guests use SYSCALL or INT $0x82 to make a hypercall, both of which
+ * have trap semantics. If the hypercall has been preempted, rewind the
+ * instruction pointer to reexecute the instruction.
+ */
+ if ( curr->hcall_preempted )
+ regs->rip -= 2;
+
perfc_incr(hypercalls);
}
bool debug_state_latch;
bool single_step;
- bool hcall_preempted;
bool hcall_64bit;
struct hvm_vcpu_asid n1asid;
/* VCPU need affinity restored */
bool affinity_broken;
+ /* A hypercall has been preempted. */
+ bool hcall_preempted;
+
/*
* > 0: a single port is being polled;