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: Andrey Smetanin <asmetanin@virtuozzo.com> Reviewed-by: Roman 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: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Родитель
b2fdc2570a
Коммит
83326e43f2
|
@ -3339,6 +3339,7 @@ EOI was received.
|
|||
|
||||
struct kvm_hyperv_exit {
|
||||
#define KVM_EXIT_HYPERV_SYNIC 1
|
||||
#define KVM_EXIT_HYPERV_HCALL 2
|
||||
__u32 type;
|
||||
union {
|
||||
struct {
|
||||
|
@ -3347,6 +3348,11 @@ EOI was received.
|
|||
__u64 evt_page;
|
||||
__u64 msg_page;
|
||||
} synic;
|
||||
struct {
|
||||
__u64 input;
|
||||
__u64 result;
|
||||
__u64 params[2];
|
||||
} hcall;
|
||||
} u;
|
||||
};
|
||||
/* KVM_EXIT_HYPERV */
|
||||
|
|
|
@ -1043,6 +1043,27 @@ bool kvm_hv_hypercall_enabled(struct kvm *kvm)
|
|||
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)
|
||||
{
|
||||
u64 param, ingpa, outgpa, ret;
|
||||
|
@ -1093,6 +1114,16 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
|
|||
case HVCALL_NOTIFY_LONG_SPIN_WAIT:
|
||||
kvm_vcpu_on_spin(vcpu);
|
||||
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:
|
||||
res = HV_STATUS_INVALID_HYPERCALL_CODE;
|
||||
break;
|
||||
|
@ -1100,12 +1131,6 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
|
|||
|
||||
set_result:
|
||||
ret = res | (((u64)rep_done & 0xfff) << 32);
|
||||
if (longmode) {
|
||||
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);
|
||||
}
|
||||
|
||||
kvm_hv_hypercall_set_result(vcpu, ret);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -157,6 +157,7 @@ struct kvm_s390_skeys {
|
|||
|
||||
struct kvm_hyperv_exit {
|
||||
#define KVM_EXIT_HYPERV_SYNIC 1
|
||||
#define KVM_EXIT_HYPERV_HCALL 2
|
||||
__u32 type;
|
||||
union {
|
||||
struct {
|
||||
|
@ -165,6 +166,11 @@ struct kvm_hyperv_exit {
|
|||
__u64 evt_page;
|
||||
__u64 msg_page;
|
||||
} synic;
|
||||
struct {
|
||||
__u64 input;
|
||||
__u64 result;
|
||||
__u64 params[2];
|
||||
} hcall;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче