aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Smetanin <asmetanin@virtuozzo.com>2015-11-30 11:22:20 -0500
committerPaolo Bonzini <pbonzini@redhat.com>2015-12-16 12:49:44 -0500
commit765eaa0f70eaa274ec8b815d8c210c20cf7b6dbc (patch)
tree5eda792ac2977dd37b16b8a6268acd0abc14ea11
parent93bf4172481c4b2a8544c83a687946252563edd0 (diff)
kvm/x86: Hyper-V SynIC message slot pending clearing at SINT ack
The SynIC message protocol mandates that the message slot is claimed by atomically setting message type to something other than HVMSG_NONE. If another message is to be delivered while the slot is still busy, message pending flag is asserted to indicate to the guest that the hypervisor wants to be notified when the slot is released. To make sure the protocol works regardless of where the message sources are (kernel or userspace), clear the pending flag on SINT ACK notification, and let the message sources compete for the slot again. 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: "K. Y. Srinivasan" <kys@microsoft.com> CC: Haiyang Zhang <haiyangz@microsoft.com> CC: Vitaly Kuznetsov <vkuznets@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>
-rw-r--r--arch/x86/kvm/hyperv.c31
-rw-r--r--include/linux/kvm_host.h2
2 files changed, 33 insertions, 0 deletions
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 99589268fe5d..6412b6b504b5 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -27,6 +27,7 @@
27#include "hyperv.h" 27#include "hyperv.h"
28 28
29#include <linux/kvm_host.h> 29#include <linux/kvm_host.h>
30#include <linux/highmem.h>
30#include <asm/apicdef.h> 31#include <asm/apicdef.h>
31#include <trace/events/kvm.h> 32#include <trace/events/kvm.h>
32 33
@@ -116,13 +117,43 @@ static struct kvm_vcpu_hv_synic *synic_get(struct kvm *kvm, u32 vcpu_id)
116 return (synic->active) ? synic : NULL; 117 return (synic->active) ? synic : NULL;
117} 118}
118 119
120static void synic_clear_sint_msg_pending(struct kvm_vcpu_hv_synic *synic,
121 u32 sint)
122{
123 struct kvm_vcpu *vcpu = synic_to_vcpu(synic);
124 struct page *page;
125 gpa_t gpa;
126 struct hv_message *msg;
127 struct hv_message_page *msg_page;
128
129 gpa = synic->msg_page & PAGE_MASK;
130 page = kvm_vcpu_gfn_to_page(vcpu, gpa >> PAGE_SHIFT);
131 if (is_error_page(page)) {
132 vcpu_err(vcpu, "Hyper-V SynIC can't get msg page, gpa 0x%llx\n",
133 gpa);
134 return;
135 }
136 msg_page = kmap_atomic(page);
137
138 msg = &msg_page->sint_message[sint];
139 msg->header.message_flags.msg_pending = 0;
140
141 kunmap_atomic(msg_page);
142 kvm_release_page_dirty(page);
143 kvm_vcpu_mark_page_dirty(vcpu, gpa >> PAGE_SHIFT);
144}
145
119static void kvm_hv_notify_acked_sint(struct kvm_vcpu *vcpu, u32 sint) 146static void kvm_hv_notify_acked_sint(struct kvm_vcpu *vcpu, u32 sint)
120{ 147{
121 struct kvm *kvm = vcpu->kvm; 148 struct kvm *kvm = vcpu->kvm;
149 struct kvm_vcpu_hv_synic *synic = vcpu_to_synic(vcpu);
122 int gsi, idx; 150 int gsi, idx;
123 151
124 vcpu_debug(vcpu, "Hyper-V SynIC acked sint %d\n", sint); 152 vcpu_debug(vcpu, "Hyper-V SynIC acked sint %d\n", sint);
125 153
154 if (synic->msg_page & HV_SYNIC_SIMP_ENABLE)
155 synic_clear_sint_msg_pending(synic, sint);
156
126 idx = srcu_read_lock(&kvm->irq_srcu); 157 idx = srcu_read_lock(&kvm->irq_srcu);
127 gsi = atomic_read(&vcpu_to_synic(vcpu)->sint_to_gsi[sint]); 158 gsi = atomic_read(&vcpu_to_synic(vcpu)->sint_to_gsi[sint]);
128 if (gsi != -1) 159 if (gsi != -1)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 590c46e672df..f44c24b81b17 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -450,6 +450,8 @@ struct kvm {
450 450
451#define vcpu_debug(vcpu, fmt, ...) \ 451#define vcpu_debug(vcpu, fmt, ...) \
452 kvm_debug("vcpu%i " fmt, (vcpu)->vcpu_id, ## __VA_ARGS__) 452 kvm_debug("vcpu%i " fmt, (vcpu)->vcpu_id, ## __VA_ARGS__)
453#define vcpu_err(vcpu, fmt, ...) \
454 kvm_err("vcpu%i " fmt, (vcpu)->vcpu_id, ## __VA_ARGS__)
453 455
454static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i) 456static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i)
455{ 457{