qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 06/10] hyperv: add synic event flag signaling


From: Roman Kagan
Subject: [Qemu-devel] [PATCH 06/10] hyperv: add synic event flag signaling
Date: Fri, 21 Sep 2018 11:22:13 +0300

Add infrastructure to signal SynIC event flags by atomically setting the
corresponding bit in the event flags page and firing a SINT if
necessary.

Signed-off-by: Roman Kagan <address@hidden>
---
 include/hw/hyperv/hyperv.h |  4 ++++
 hw/hyperv/hyperv.c         | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/include/hw/hyperv/hyperv.h b/include/hw/hyperv/hyperv.h
index 82d561fc88..757c85eb8f 100644
--- a/include/hw/hyperv/hyperv.h
+++ b/include/hw/hyperv/hyperv.h
@@ -34,6 +34,10 @@ int hyperv_sint_route_set_sint(HvSintRoute *sint_route);
  * with the @sint_route; until then no more messages are accepted.
  */
 int hyperv_post_msg(HvSintRoute *sint_route, struct hyperv_message *msg);
+/*
+ * Set event flag @eventno, and signal the SINT if the flag has changed.
+ */
+int hyperv_set_event_flag(HvSintRoute *sint_route, unsigned eventno);
 
 static inline uint32_t hyperv_vp_index(CPUState *cs)
 {
diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c
index 21217631dc..0b28e7922c 100644
--- a/hw/hyperv/hyperv.c
+++ b/hw/hyperv/hyperv.c
@@ -12,6 +12,7 @@
 #include "qapi/error.h"
 #include "exec/address-spaces.h"
 #include "sysemu/kvm.h"
+#include "qemu/bitops.h"
 #include "hw/hyperv/hyperv.h"
 
 typedef struct SynICState {
@@ -310,6 +311,37 @@ static void sint_ack_handler(EventNotifier *notifier)
     aio_bh_schedule_oneshot(qemu_get_aio_context(), sint_msg_bh, sint_route);
 }
 
+/*
+ * Set given event flag for a given sint on a given vcpu, and signal the sint.
+ */
+int hyperv_set_event_flag(HvSintRoute *sint_route, unsigned eventno)
+{
+    int ret;
+    SynICState *synic = sint_route->synic;
+    unsigned long *flags, set_mask;
+    unsigned set_idx;
+
+    if (eventno > HV_EVENT_FLAGS_COUNT) {
+        return -EINVAL;
+    }
+    if (!synic->enabled || !synic->event_page_addr) {
+        return -ENXIO;
+    }
+
+    set_idx = BIT_WORD(eventno);
+    set_mask = BIT_MASK(eventno);
+    flags = synic->event_page->slot[sint_route->sint].flags;
+
+    if ((atomic_fetch_or(&flags[set_idx], set_mask) & set_mask) != set_mask) {
+        memory_region_set_dirty(&synic->event_page_mr, 0,
+                                sizeof(*synic->event_page));
+        ret = hyperv_sint_route_set_sint(sint_route);
+    } else {
+        ret = 0;
+    }
+    return ret;
+}
+
 HvSintRoute *hyperv_sint_route_new(uint32_t vp_index, uint32_t sint,
                                    HvSintMsgCb cb, void *cb_data)
 {
-- 
2.17.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]