mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-10 07:10:27 +00:00
kvm/x86: Hyper-V kvm exit
A new vcpu exit is introduced to notify the userspace of the changes in Hyper-V SynIC configuration triggered by guest writing to the corresponding MSRs. Changes v4: * exit into userspace only if guest writes into SynIC MSR's Changes v3: * added KVM_EXIT_HYPERV types and structs notes into docs Signed-off-by: Andrey Smetanin <asmetanin@virtuozzo.com> Reviewed-by: Roman Kagan <rkagan@virtuozzo.com> Signed-off-by: Denis V. Lunev <den@openvz.org> CC: Gleb Natapov <gleb@kernel.org> CC: Paolo Bonzini <pbonzini@redhat.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:
parent
5c919412fe
commit
db3975717a
@ -3337,6 +3337,28 @@ the userspace IOAPIC should process the EOI and retrigger the interrupt if
|
||||
it is still asserted. Vector is the LAPIC interrupt vector for which the
|
||||
EOI was received.
|
||||
|
||||
struct kvm_hyperv_exit {
|
||||
#define KVM_EXIT_HYPERV_SYNIC 1
|
||||
__u32 type;
|
||||
union {
|
||||
struct {
|
||||
__u32 msr;
|
||||
__u64 control;
|
||||
__u64 evt_page;
|
||||
__u64 msg_page;
|
||||
} synic;
|
||||
} u;
|
||||
};
|
||||
/* KVM_EXIT_HYPERV */
|
||||
struct kvm_hyperv_exit hyperv;
|
||||
Indicates that the VCPU exits into userspace to process some tasks
|
||||
related to Hyper-V emulation.
|
||||
Valid values for 'type' are:
|
||||
KVM_EXIT_HYPERV_SYNIC -- synchronously notify user-space about
|
||||
Hyper-V SynIC state change. Notification is used to remap SynIC
|
||||
event/message pages and to enable/disable SynIC messages/events processing
|
||||
in userspace.
|
||||
|
||||
/* Fix the size of the union. */
|
||||
char padding[256];
|
||||
};
|
||||
|
@ -393,6 +393,7 @@ struct kvm_vcpu_hv {
|
||||
u64 hv_vapic;
|
||||
s64 runtime_offset;
|
||||
struct kvm_vcpu_hv_synic synic;
|
||||
struct kvm_hyperv_exit exit;
|
||||
};
|
||||
|
||||
struct kvm_vcpu_arch {
|
||||
|
@ -130,6 +130,20 @@ static void kvm_hv_notify_acked_sint(struct kvm_vcpu *vcpu, u32 sint)
|
||||
srcu_read_unlock(&kvm->irq_srcu, idx);
|
||||
}
|
||||
|
||||
static void synic_exit(struct kvm_vcpu_hv_synic *synic, u32 msr)
|
||||
{
|
||||
struct kvm_vcpu *vcpu = synic_to_vcpu(synic);
|
||||
struct kvm_vcpu_hv *hv_vcpu = &vcpu->arch.hyperv;
|
||||
|
||||
hv_vcpu->exit.type = KVM_EXIT_HYPERV_SYNIC;
|
||||
hv_vcpu->exit.u.synic.msr = msr;
|
||||
hv_vcpu->exit.u.synic.control = synic->control;
|
||||
hv_vcpu->exit.u.synic.evt_page = synic->evt_page;
|
||||
hv_vcpu->exit.u.synic.msg_page = synic->msg_page;
|
||||
|
||||
kvm_make_request(KVM_REQ_HV_EXIT, vcpu);
|
||||
}
|
||||
|
||||
static int synic_set_msr(struct kvm_vcpu_hv_synic *synic,
|
||||
u32 msr, u64 data, bool host)
|
||||
{
|
||||
@ -145,6 +159,8 @@ static int synic_set_msr(struct kvm_vcpu_hv_synic *synic,
|
||||
switch (msr) {
|
||||
case HV_X64_MSR_SCONTROL:
|
||||
synic->control = data;
|
||||
if (!host)
|
||||
synic_exit(synic, msr);
|
||||
break;
|
||||
case HV_X64_MSR_SVERSION:
|
||||
if (!host) {
|
||||
@ -161,6 +177,8 @@ static int synic_set_msr(struct kvm_vcpu_hv_synic *synic,
|
||||
break;
|
||||
}
|
||||
synic->evt_page = data;
|
||||
if (!host)
|
||||
synic_exit(synic, msr);
|
||||
break;
|
||||
case HV_X64_MSR_SIMP:
|
||||
if (data & HV_SYNIC_SIMP_ENABLE)
|
||||
@ -170,6 +188,8 @@ static int synic_set_msr(struct kvm_vcpu_hv_synic *synic,
|
||||
break;
|
||||
}
|
||||
synic->msg_page = data;
|
||||
if (!host)
|
||||
synic_exit(synic, msr);
|
||||
break;
|
||||
case HV_X64_MSR_EOM: {
|
||||
int i;
|
||||
|
@ -6482,6 +6482,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
|
||||
r = 0;
|
||||
goto out;
|
||||
}
|
||||
if (kvm_check_request(KVM_REQ_HV_EXIT, vcpu)) {
|
||||
vcpu->run->exit_reason = KVM_EXIT_HYPERV;
|
||||
vcpu->run->hyperv = vcpu->arch.hyperv.exit;
|
||||
r = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -143,6 +143,7 @@ static inline bool is_error_page(struct page *page)
|
||||
#define KVM_REQ_HV_CRASH 27
|
||||
#define KVM_REQ_IOAPIC_EOI_EXIT 28
|
||||
#define KVM_REQ_HV_RESET 29
|
||||
#define KVM_REQ_HV_EXIT 30
|
||||
|
||||
#define KVM_USERSPACE_IRQ_SOURCE_ID 0
|
||||
#define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1
|
||||
|
@ -154,6 +154,20 @@ struct kvm_s390_skeys {
|
||||
__u32 flags;
|
||||
__u32 reserved[9];
|
||||
};
|
||||
|
||||
struct kvm_hyperv_exit {
|
||||
#define KVM_EXIT_HYPERV_SYNIC 1
|
||||
__u32 type;
|
||||
union {
|
||||
struct {
|
||||
__u32 msr;
|
||||
__u64 control;
|
||||
__u64 evt_page;
|
||||
__u64 msg_page;
|
||||
} synic;
|
||||
} u;
|
||||
};
|
||||
|
||||
#define KVM_S390_GET_SKEYS_NONE 1
|
||||
#define KVM_S390_SKEYS_MAX 1048576
|
||||
|
||||
@ -184,6 +198,7 @@ struct kvm_s390_skeys {
|
||||
#define KVM_EXIT_SYSTEM_EVENT 24
|
||||
#define KVM_EXIT_S390_STSI 25
|
||||
#define KVM_EXIT_IOAPIC_EOI 26
|
||||
#define KVM_EXIT_HYPERV 27
|
||||
|
||||
/* For KVM_EXIT_INTERNAL_ERROR */
|
||||
/* Emulate instruction failed. */
|
||||
@ -338,6 +353,8 @@ struct kvm_run {
|
||||
struct {
|
||||
__u8 vector;
|
||||
} eoi;
|
||||
/* KVM_EXIT_HYPERV */
|
||||
struct kvm_hyperv_exit hyperv;
|
||||
/* Fix the size of the union. */
|
||||
char padding[256];
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user