hyperv: add synic event flag signaling
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>
This commit is contained in:
parent
4cbaf3c133
commit
f5642f8b45
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user