aboutsummaryrefslogtreecommitdiff
path: root/hw/hyperv
diff options
context:
space:
mode:
authorRoman Kagan <rkagan@virtuozzo.com>2018-09-21 11:22:09 +0300
committerPaolo Bonzini <pbonzini@redhat.com>2018-10-19 13:44:14 +0200
commit606c34bfd57a0ecda67b395bea022bb307a5384e (patch)
tree448b94dd535847b0cd358a13332e46085d563c6f /hw/hyperv
parent729ce7e1b6b6e035012544f51878d1ef5864bf39 (diff)
hyperv: qom-ify SynIC
Make Hyper-V SynIC a device which is attached as a child to a CPU. For now it only makes SynIC visibile in the qom hierarchy, and maintains its internal fields in sync with the respecitve msrs of the parent cpu (the fields will be used in followup patches). Signed-off-by: Roman Kagan <rkagan@virtuozzo.com> Message-Id: <20180921082217.29481-3-rkagan@virtuozzo.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw/hyperv')
-rw-r--r--hw/hyperv/hyperv.c101
1 files changed, 99 insertions, 2 deletions
diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c
index 97db87561e..3d6f044282 100644
--- a/hw/hyperv/hyperv.c
+++ b/hw/hyperv/hyperv.c
@@ -9,12 +9,103 @@
#include "qemu/osdep.h"
#include "qemu/main-loop.h"
+#include "qapi/error.h"
#include "sysemu/kvm.h"
#include "hw/hyperv/hyperv.h"
+typedef struct SynICState {
+ DeviceState parent_obj;
+
+ CPUState *cs;
+
+ bool enabled;
+ hwaddr msg_page_addr;
+ hwaddr event_page_addr;
+} SynICState;
+
+#define TYPE_SYNIC "hyperv-synic"
+#define SYNIC(obj) OBJECT_CHECK(SynICState, (obj), TYPE_SYNIC)
+
+static SynICState *get_synic(CPUState *cs)
+{
+ return SYNIC(object_resolve_path_component(OBJECT(cs), "synic"));
+}
+
+static void synic_update(SynICState *synic, bool enable,
+ hwaddr msg_page_addr, hwaddr event_page_addr)
+{
+
+ synic->enabled = enable;
+ synic->msg_page_addr = msg_page_addr;
+ synic->event_page_addr = event_page_addr;
+}
+
+void hyperv_synic_update(CPUState *cs, bool enable,
+ hwaddr msg_page_addr, hwaddr event_page_addr)
+{
+ SynICState *synic = get_synic(cs);
+
+ if (!synic) {
+ return;
+ }
+
+ synic_update(synic, enable, msg_page_addr, event_page_addr);
+}
+
+static void synic_realize(DeviceState *dev, Error **errp)
+{
+}
+
+static void synic_reset(DeviceState *dev)
+{
+ SynICState *synic = SYNIC(dev);
+ synic_update(synic, false, 0, 0);
+}
+
+static void synic_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = synic_realize;
+ dc->reset = synic_reset;
+ dc->user_creatable = false;
+}
+
+void hyperv_synic_add(CPUState *cs)
+{
+ Object *obj;
+ SynICState *synic;
+
+ obj = object_new(TYPE_SYNIC);
+ synic = SYNIC(obj);
+ synic->cs = cs;
+ object_property_add_child(OBJECT(cs), "synic", obj, &error_abort);
+ object_unref(obj);
+ object_property_set_bool(obj, true, "realized", &error_abort);
+}
+
+void hyperv_synic_reset(CPUState *cs)
+{
+ device_reset(DEVICE(get_synic(cs)));
+}
+
+static const TypeInfo synic_type_info = {
+ .name = TYPE_SYNIC,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(SynICState),
+ .class_init = synic_class_init,
+};
+
+static void synic_register_types(void)
+{
+ type_register_static(&synic_type_info);
+}
+
+type_init(synic_register_types)
+
struct HvSintRoute {
uint32_t sint;
- CPUState *cs;
+ SynICState *synic;
int gsi;
EventNotifier sint_set_notifier;
EventNotifier sint_ack_notifier;
@@ -46,12 +137,18 @@ HvSintRoute *hyperv_sint_route_new(uint32_t vp_index, uint32_t sint,
EventNotifier *ack_notifier;
int r, gsi;
CPUState *cs;
+ SynICState *synic;
cs = hyperv_find_vcpu(vp_index);
if (!cs) {
return NULL;
}
+ synic = get_synic(cs);
+ if (!synic) {
+ return NULL;
+ }
+
sint_route = g_new0(HvSintRoute, 1);
r = event_notifier_init(&sint_route->sint_set_notifier, false);
if (r) {
@@ -82,7 +179,7 @@ HvSintRoute *hyperv_sint_route_new(uint32_t vp_index, uint32_t sint,
sint_route->gsi = gsi;
sint_route->sint_ack_clb = sint_ack_clb;
sint_route->sint_ack_clb_data = sint_ack_clb_data;
- sint_route->cs = cs;
+ sint_route->synic = synic;
sint_route->sint = sint;
sint_route->refcount = 1;