On 11/4/2024 5:55 PM, Huang, Kai wrote:
[...]
int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
{
- unsigned long nr, a0, a1, a2, a3, ret;
- int op_64_bit;
- int cpl;
+ int r;
if (kvm_xen_hypercall_enabled(vcpu->kvm))
return kvm_xen_hypercall(vcpu);
@@ -10102,23 +10105,12 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
if (kvm_hv_hypercall_enabled(vcpu))
return kvm_hv_hypercall(vcpu);
- nr = kvm_rax_read(vcpu);
- a0 = kvm_rbx_read(vcpu);
- a1 = kvm_rcx_read(vcpu);
- a2 = kvm_rdx_read(vcpu);
- a3 = kvm_rsi_read(vcpu);
- op_64_bit = is_64_bit_hypercall(vcpu);
- cpl = kvm_x86_call(get_cpl)(vcpu);
-
- ret = __kvm_emulate_hypercall(vcpu, nr, a0, a1, a2, a3, op_64_bit, cpl);
- if (nr == KVM_HC_MAP_GPA_RANGE && !ret)
- /* MAP_GPA tosses the request to the user space. */
+ r = __kvm_emulate_hypercall(vcpu, rax, rbx, rcx, rdx, rsi,
+ is_64_bit_hypercall(vcpu),
+ kvm_x86_call(get_cpl)(vcpu), RAX);
Now, the register for return code of the hypercall can be specified.
But in ____kvm_emulate_hypercall(), the complete_userspace_io callback
is hardcoded to complete_hypercall_exit(), which always set return code
to RAX.
We can allow the caller to pass in the cui callback, or assign different
version according to the input 'ret_reg'. So that different callers can use
different cui callbacks. E.g., TDX needs to set return code to R10 in cui
callback.
How about:
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index dba78f22ab27..0fba98685f42 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -2226,13 +2226,15 @@ static inline void kvm_clear_apicv_inhibit(struct kvm *kvm,
int ____kvm_emulate_hypercall(struct kvm_vcpu *vcpu, unsigned long nr,
unsigned long a0, unsigned long a1,
unsigned long a2, unsigned long a3,
- int op_64_bit, int cpl, int ret_reg);
+ int op_64_bit, int cpl, int ret_reg,
+ int (*cui)(struct kvm_vcpu *vcpu));
Does below (incremental diff based on Sean's) work?
Yes, it can work.
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 734dac079453..5131af97968d 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10075,7 +10075,6 @@ int ____kvm_emulate_hypercall(struct kvm_vcpu *vcpu,
unsigned long nr,
vcpu->run->hypercall.flags |=
KVM_EXIT_HYPERCALL_LONG_MODE;
WARN_ON_ONCE(vcpu->run->hypercall.flags &
KVM_EXIT_HYPERCALL_MBZ);
- vcpu->arch.complete_userspace_io = complete_hypercall_exit;
/* stat is incremented on completion. */
return 0;
}
@@ -10108,8 +10107,11 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
r = __kvm_emulate_hypercall(vcpu, rax, rbx, rcx, rdx, rsi,
is_64_bit_hypercall(vcpu),
kvm_x86_call(get_cpl)(vcpu), RAX);
- if (r <= 0)
+ if (r <= 0) {
+ if (!r)
+ vcpu->arch.complete_userspace_io =
complete_hypercall_exit;
return 0;
+ }
return kvm_skip_emulated_instruction(vcpu);
}