Commit 83326e43 authored by Andrey Smetanin's avatar Andrey Smetanin Committed by Paolo Bonzini

kvm/x86: Hyper-V VMBus hypercall userspace exit

The patch implements KVM_EXIT_HYPERV userspace exit
functionality for Hyper-V VMBus hypercalls:
HV_X64_HCALL_POST_MESSAGE, HV_X64_HCALL_SIGNAL_EVENT.

Changes v3:
* use vcpu->arch.complete_userspace_io to setup hypercall
result

Changes v2:
* use KVM_EXIT_HYPERV for hypercalls
Signed-off-by: default avatarAndrey Smetanin <asmetanin@virtuozzo.com>
Reviewed-by: default avatarRoman Kagan <rkagan@virtuozzo.com>
CC: Gleb Natapov <gleb@kernel.org>
CC: Paolo Bonzini <pbonzini@redhat.com>
CC: Joerg Roedel <joro@8bytes.org>
CC: "K. Y. Srinivasan" <kys@microsoft.com>
CC: Haiyang Zhang <haiyangz@microsoft.com>
CC: Roman Kagan <rkagan@virtuozzo.com>
CC: Denis V. Lunev <den@openvz.org>
CC: qemu-devel@nongnu.org
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent b2fdc257
...@@ -3339,6 +3339,7 @@ EOI was received. ...@@ -3339,6 +3339,7 @@ EOI was received.
struct kvm_hyperv_exit { struct kvm_hyperv_exit {
#define KVM_EXIT_HYPERV_SYNIC 1 #define KVM_EXIT_HYPERV_SYNIC 1
#define KVM_EXIT_HYPERV_HCALL 2
__u32 type; __u32 type;
union { union {
struct { struct {
...@@ -3347,6 +3348,11 @@ EOI was received. ...@@ -3347,6 +3348,11 @@ EOI was received.
__u64 evt_page; __u64 evt_page;
__u64 msg_page; __u64 msg_page;
} synic; } synic;
struct {
__u64 input;
__u64 result;
__u64 params[2];
} hcall;
} u; } u;
}; };
/* KVM_EXIT_HYPERV */ /* KVM_EXIT_HYPERV */
......
...@@ -1043,6 +1043,27 @@ bool kvm_hv_hypercall_enabled(struct kvm *kvm) ...@@ -1043,6 +1043,27 @@ bool kvm_hv_hypercall_enabled(struct kvm *kvm)
return kvm->arch.hyperv.hv_hypercall & HV_X64_MSR_HYPERCALL_ENABLE; return kvm->arch.hyperv.hv_hypercall & HV_X64_MSR_HYPERCALL_ENABLE;
} }
static void kvm_hv_hypercall_set_result(struct kvm_vcpu *vcpu, u64 result)
{
bool longmode;
longmode = is_64_bit_mode(vcpu);
if (longmode)
kvm_register_write(vcpu, VCPU_REGS_RAX, result);
else {
kvm_register_write(vcpu, VCPU_REGS_RDX, result >> 32);
kvm_register_write(vcpu, VCPU_REGS_RAX, result & 0xffffffff);
}
}
static int kvm_hv_hypercall_complete_userspace(struct kvm_vcpu *vcpu)
{
struct kvm_run *run = vcpu->run;
kvm_hv_hypercall_set_result(vcpu, run->hyperv.u.hcall.result);
return 1;
}
int kvm_hv_hypercall(struct kvm_vcpu *vcpu) int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
{ {
u64 param, ingpa, outgpa, ret; u64 param, ingpa, outgpa, ret;
...@@ -1093,6 +1114,16 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) ...@@ -1093,6 +1114,16 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
case HVCALL_NOTIFY_LONG_SPIN_WAIT: case HVCALL_NOTIFY_LONG_SPIN_WAIT:
kvm_vcpu_on_spin(vcpu); kvm_vcpu_on_spin(vcpu);
break; break;
case HVCALL_POST_MESSAGE:
case HVCALL_SIGNAL_EVENT:
vcpu->run->exit_reason = KVM_EXIT_HYPERV;
vcpu->run->hyperv.type = KVM_EXIT_HYPERV_HCALL;
vcpu->run->hyperv.u.hcall.input = param;
vcpu->run->hyperv.u.hcall.params[0] = ingpa;
vcpu->run->hyperv.u.hcall.params[1] = outgpa;
vcpu->arch.complete_userspace_io =
kvm_hv_hypercall_complete_userspace;
return 0;
default: default:
res = HV_STATUS_INVALID_HYPERCALL_CODE; res = HV_STATUS_INVALID_HYPERCALL_CODE;
break; break;
...@@ -1100,12 +1131,6 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) ...@@ -1100,12 +1131,6 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
set_result: set_result:
ret = res | (((u64)rep_done & 0xfff) << 32); ret = res | (((u64)rep_done & 0xfff) << 32);
if (longmode) { kvm_hv_hypercall_set_result(vcpu, ret);
kvm_register_write(vcpu, VCPU_REGS_RAX, ret);
} else {
kvm_register_write(vcpu, VCPU_REGS_RDX, ret >> 32);
kvm_register_write(vcpu, VCPU_REGS_RAX, ret & 0xffffffff);
}
return 1; return 1;
} }
...@@ -157,6 +157,7 @@ struct kvm_s390_skeys { ...@@ -157,6 +157,7 @@ struct kvm_s390_skeys {
struct kvm_hyperv_exit { struct kvm_hyperv_exit {
#define KVM_EXIT_HYPERV_SYNIC 1 #define KVM_EXIT_HYPERV_SYNIC 1
#define KVM_EXIT_HYPERV_HCALL 2
__u32 type; __u32 type;
union { union {
struct { struct {
...@@ -165,6 +166,11 @@ struct kvm_hyperv_exit { ...@@ -165,6 +166,11 @@ struct kvm_hyperv_exit {
__u64 evt_page; __u64 evt_page;
__u64 msg_page; __u64 msg_page;
} synic; } synic;
struct {
__u64 input;
__u64 result;
__u64 params[2];
} hcall;
} u; } u;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment