Skip to content

Commit

Permalink
hyperv: add synic event flag signaling
Browse files Browse the repository at this point in the history
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 <rkagan@virtuozzo.com>
Message-Id: <20180921082217.29481-7-rkagan@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
  • Loading branch information
rvka authored and bonzini committed Oct 19, 2018
1 parent 4cbaf3c commit f5642f8
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 0 deletions.
32 changes: 32 additions & 0 deletions hw/hyperv/hyperv.c
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
{
Expand Down
4 changes: 4 additions & 0 deletions include/hw/hyperv/hyperv.h
Expand Up @@ -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)
{
Expand Down

0 comments on commit f5642f8

Please sign in to comment.