#include "qemu/osdep.h"
#include "qemu/main-loop.h"
+#include "qemu/module.h"
#include "qapi/error.h"
#include "exec/address-spaces.h"
#include "sysemu/kvm.h"
#include "qemu/bitops.h"
#include "qemu/error-report.h"
+#include "qemu/lockable.h"
#include "qemu/queue.h"
#include "qemu/rcu.h"
#include "qemu/rcu_queue.h"
#include "hw/hyperv/hyperv.h"
+#include "qom/object.h"
-typedef struct SynICState {
+struct SynICState {
DeviceState parent_obj;
CPUState *cs;
MemoryRegion event_page_mr;
struct hyperv_message_page *msg_page;
struct hyperv_event_flags_page *event_page;
-} SynICState;
+};
#define TYPE_SYNIC "hyperv-synic"
-#define SYNIC(obj) OBJECT_CHECK(SynICState, (obj), TYPE_SYNIC)
+OBJECT_DECLARE_SIMPLE_TYPE(SynICState, SYNIC)
+
+static bool synic_enabled;
+
+bool hyperv_is_synic_enabled(void)
+{
+ return synic_enabled;
+}
static SynICState *get_synic(CPUState *cs)
{
obj = object_new(TYPE_SYNIC);
synic = SYNIC(obj);
synic->cs = cs;
- object_property_add_child(OBJECT(cs), "synic", obj, &error_abort);
+ object_property_add_child(OBJECT(cs), "synic", obj);
object_unref(obj);
- object_property_set_bool(obj, true, "realized", &error_abort);
+ qdev_realize(DEVICE(obj), NULL, &error_abort);
+ synic_enabled = true;
}
void hyperv_synic_reset(CPUState *cs)
{
- device_reset(DEVICE(get_synic(cs)));
+ SynICState *synic = get_synic(cs);
+
+ if (synic) {
+ device_legacy_reset(DEVICE(synic));
+ }
}
static const TypeInfo synic_type_info = {
int ret;
MsgHandler *mh;
- qemu_mutex_lock(&handlers_mutex);
+ QEMU_LOCK_GUARD(&handlers_mutex);
QLIST_FOREACH(mh, &msg_handlers, link) {
if (mh->conn_id == conn_id) {
if (handler) {
g_free_rcu(mh, rcu);
ret = 0;
}
- goto unlock;
+ return ret;
}
}
} else {
ret = -ENOENT;
}
-unlock:
- qemu_mutex_unlock(&handlers_mutex);
+
return ret;
}
}
ret = HV_STATUS_INVALID_CONNECTION_ID;
- rcu_read_lock();
- QLIST_FOREACH_RCU(mh, &msg_handlers, link) {
- if (mh->conn_id == (msg->connection_id & HV_CONNECTION_ID_MASK)) {
- ret = mh->handler(msg, mh->data);
- break;
+ WITH_RCU_READ_LOCK_GUARD() {
+ QLIST_FOREACH_RCU(mh, &msg_handlers, link) {
+ if (mh->conn_id == (msg->connection_id & HV_CONNECTION_ID_MASK)) {
+ ret = mh->handler(msg, mh->data);
+ break;
+ }
}
}
- rcu_read_unlock();
unmap:
cpu_physical_memory_unmap(msg, len, 0, 0);
int ret;
EventFlagHandler *handler;
- qemu_mutex_lock(&handlers_mutex);
+ QEMU_LOCK_GUARD(&handlers_mutex);
QLIST_FOREACH(handler, &event_flag_handlers, link) {
if (handler->conn_id == conn_id) {
if (notifier) {
g_free_rcu(handler, rcu);
ret = 0;
}
- goto unlock;
+ return ret;
}
}
} else {
ret = -ENOENT;
}
-unlock:
- qemu_mutex_unlock(&handlers_mutex);
+
return ret;
}
uint16_t hyperv_hcall_signal_event(uint64_t param, bool fast)
{
- uint16_t ret;
EventFlagHandler *handler;
if (unlikely(!fast)) {
return HV_STATUS_INVALID_HYPERCALL_INPUT;
}
- ret = HV_STATUS_INVALID_CONNECTION_ID;
- rcu_read_lock();
+ RCU_READ_LOCK_GUARD();
QLIST_FOREACH_RCU(handler, &event_flag_handlers, link) {
if (handler->conn_id == param) {
event_notifier_set(handler->notifier);
- ret = 0;
- break;
+ return 0;
}
}
- rcu_read_unlock();
- return ret;
+ return HV_STATUS_INVALID_CONNECTION_ID;
}