Skip to content

Commit d9eb86a

Browse files
sean-jcbonzini
authored andcommitted
KVM: x86: Always complete hypercall via function callback
Finish "emulation" of KVM hypercalls by function callback, even when the hypercall is handled entirely within KVM, i.e. doesn't require an exit to userspace, and refactor __kvm_emulate_hypercall()'s return value to *only* communicate whether or not KVM should exit to userspace or resume the guest. (Ab)Use vcpu->run->hypercall.ret to propagate the return value to the callback, purely to avoid having to add a trampoline for every completion callback. Using the function return value for KVM's control flow eliminates the multiplexed return value, where '0' for KVM_HC_MAP_GPA_RANGE (and only that hypercall) means "exit to userspace". Note, the unnecessary extra indirect call and thus potential retpoline will be eliminated in the near future by converting the intermediate layer to a macro. Suggested-by: Binbin Wu <[email protected]> Suggested-by: Kai Huang <[email protected]> Signed-off-by: Sean Christopherson <[email protected]> Reviewed-by: Kai Huang <[email protected]> Message-ID: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 05a518b commit d9eb86a

File tree

2 files changed

+17
-21
lines changed

2 files changed

+17
-21
lines changed

arch/x86/kvm/x86.c

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9982,10 +9982,11 @@ static int complete_hypercall_exit(struct kvm_vcpu *vcpu)
99829982
return kvm_skip_emulated_instruction(vcpu);
99839983
}
99849984

9985-
unsigned long __kvm_emulate_hypercall(struct kvm_vcpu *vcpu, unsigned long nr,
9986-
unsigned long a0, unsigned long a1,
9987-
unsigned long a2, unsigned long a3,
9988-
int op_64_bit, int cpl)
9985+
int __kvm_emulate_hypercall(struct kvm_vcpu *vcpu, unsigned long nr,
9986+
unsigned long a0, unsigned long a1,
9987+
unsigned long a2, unsigned long a3,
9988+
int op_64_bit, int cpl,
9989+
int (*complete_hypercall)(struct kvm_vcpu *))
99899990
{
99909991
unsigned long ret;
99919992

@@ -10068,7 +10069,7 @@ unsigned long __kvm_emulate_hypercall(struct kvm_vcpu *vcpu, unsigned long nr,
1006810069
vcpu->run->hypercall.flags |= KVM_EXIT_HYPERCALL_LONG_MODE;
1006910070

1007010071
WARN_ON_ONCE(vcpu->run->hypercall.flags & KVM_EXIT_HYPERCALL_MBZ);
10071-
vcpu->arch.complete_userspace_io = complete_hypercall_exit;
10072+
vcpu->arch.complete_userspace_io = complete_hypercall;
1007210073
return 0;
1007310074
}
1007410075
default:
@@ -10077,13 +10078,14 @@ unsigned long __kvm_emulate_hypercall(struct kvm_vcpu *vcpu, unsigned long nr,
1007710078
}
1007810079

1007910080
out:
10080-
return ret;
10081+
vcpu->run->hypercall.ret = ret;
10082+
return complete_hypercall(vcpu);
1008110083
}
1008210084
EXPORT_SYMBOL_GPL(__kvm_emulate_hypercall);
1008310085

1008410086
int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
1008510087
{
10086-
unsigned long nr, a0, a1, a2, a3, ret;
10088+
unsigned long nr, a0, a1, a2, a3;
1008710089
int op_64_bit;
1008810090
int cpl;
1008910091

@@ -10101,16 +10103,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
1010110103
op_64_bit = is_64_bit_hypercall(vcpu);
1010210104
cpl = kvm_x86_call(get_cpl)(vcpu);
1010310105

10104-
ret = __kvm_emulate_hypercall(vcpu, nr, a0, a1, a2, a3, op_64_bit, cpl);
10105-
if (nr == KVM_HC_MAP_GPA_RANGE && !ret)
10106-
/* MAP_GPA tosses the request to the user space. */
10107-
return 0;
10108-
10109-
if (!op_64_bit)
10110-
ret = (u32)ret;
10111-
kvm_rax_write(vcpu, ret);
10112-
10113-
return kvm_skip_emulated_instruction(vcpu);
10106+
return __kvm_emulate_hypercall(vcpu, nr, a0, a1, a2, a3, op_64_bit, cpl,
10107+
complete_hypercall_exit);
1011410108
}
1011510109
EXPORT_SYMBOL_GPL(kvm_emulate_hypercall);
1011610110

arch/x86/kvm/x86.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -617,10 +617,12 @@ static inline bool user_exit_on_hypercall(struct kvm *kvm, unsigned long hc_nr)
617617
return kvm->arch.hypercall_exit_enabled & BIT(hc_nr);
618618
}
619619

620-
unsigned long __kvm_emulate_hypercall(struct kvm_vcpu *vcpu, unsigned long nr,
621-
unsigned long a0, unsigned long a1,
622-
unsigned long a2, unsigned long a3,
623-
int op_64_bit, int cpl);
620+
int __kvm_emulate_hypercall(struct kvm_vcpu *vcpu, unsigned long nr,
621+
unsigned long a0, unsigned long a1,
622+
unsigned long a2, unsigned long a3,
623+
int op_64_bit, int cpl,
624+
int (*complete_hypercall)(struct kvm_vcpu *));
625+
624626
int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
625627

626628
#endif

0 commit comments

Comments
 (0)