|
@@ -99,6 +99,43 @@ static inline __u64 generate_guest_id(__u64 d_info1, __u64 kernel_version,
|
|
|
return guest_id;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+/* Free the message slot and signal end-of-message if required */
|
|
|
+static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * On crash we're reading some other CPU's message page and we need
|
|
|
+ * to be careful: this other CPU may already had cleared the header
|
|
|
+ * and the host may already had delivered some other message there.
|
|
|
+ * In case we blindly write msg->header.message_type we're going
|
|
|
+ * to lose it. We can still lose a message of the same type but
|
|
|
+ * we count on the fact that there can only be one
|
|
|
+ * CHANNELMSG_UNLOAD_RESPONSE and we don't care about other messages
|
|
|
+ * on crash.
|
|
|
+ */
|
|
|
+ if (cmpxchg(&msg->header.message_type, old_msg_type,
|
|
|
+ HVMSG_NONE) != old_msg_type)
|
|
|
+ return;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Make sure the write to MessageType (ie set to
|
|
|
+ * HVMSG_NONE) happens before we read the
|
|
|
+ * MessagePending and EOMing. Otherwise, the EOMing
|
|
|
+ * will not deliver any more messages since there is
|
|
|
+ * no empty slot
|
|
|
+ */
|
|
|
+ mb();
|
|
|
+
|
|
|
+ if (msg->header.message_flags.msg_pending) {
|
|
|
+ /*
|
|
|
+ * This will cause message queue rescan to
|
|
|
+ * possibly deliver another msg from the
|
|
|
+ * hypervisor
|
|
|
+ */
|
|
|
+ wrmsrl(HV_X64_MSR_EOM, 0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void hyperv_callback_vector(void);
|
|
|
#ifdef CONFIG_TRACING
|
|
|
#define trace_hyperv_callback_vector hyperv_callback_vector
|