hyperv: make HvSintRoute reference-counted
[qemu/ar7.git] / hw / misc / hyperv_testdev.c
blobdbf4e7e4ab25c7c71077d59eb2fb76e9e46c8709
1 /*
2 * QEMU KVM Hyper-V test device to support Hyper-V kvm-unit-tests
4 * Copyright (C) 2015 Andrey Smetanin <asmetanin@virtuozzo.com>
6 * Authors:
7 * Andrey Smetanin <asmetanin@virtuozzo.com>
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
14 #include "qemu/osdep.h"
15 #include "qemu/queue.h"
16 #include "hw/qdev.h"
17 #include "hw/isa/isa.h"
18 #include "target/i386/hyperv.h"
20 typedef struct TestSintRoute {
21 QLIST_ENTRY(TestSintRoute) le;
22 uint8_t vp_index;
23 uint8_t sint;
24 HvSintRoute *sint_route;
25 } TestSintRoute;
27 struct HypervTestDev {
28 ISADevice parent_obj;
29 MemoryRegion sint_control;
30 QLIST_HEAD(, TestSintRoute) sint_routes;
32 typedef struct HypervTestDev HypervTestDev;
34 #define TYPE_HYPERV_TEST_DEV "hyperv-testdev"
35 #define HYPERV_TEST_DEV(obj) \
36 OBJECT_CHECK(HypervTestDev, (obj), TYPE_HYPERV_TEST_DEV)
38 enum {
39 HV_TEST_DEV_SINT_ROUTE_CREATE = 1,
40 HV_TEST_DEV_SINT_ROUTE_DESTROY,
41 HV_TEST_DEV_SINT_ROUTE_SET_SINT
44 static void sint_route_create(HypervTestDev *dev,
45 uint8_t vp_index, uint8_t sint)
47 TestSintRoute *sint_route;
49 sint_route = g_new0(TestSintRoute, 1);
50 assert(sint_route);
52 sint_route->vp_index = vp_index;
53 sint_route->sint = sint;
55 sint_route->sint_route = hyperv_sint_route_new(vp_index, sint, NULL, NULL);
56 assert(sint_route->sint_route);
58 QLIST_INSERT_HEAD(&dev->sint_routes, sint_route, le);
61 static TestSintRoute *sint_route_find(HypervTestDev *dev,
62 uint8_t vp_index, uint8_t sint)
64 TestSintRoute *sint_route;
66 QLIST_FOREACH(sint_route, &dev->sint_routes, le) {
67 if (sint_route->vp_index == vp_index && sint_route->sint == sint) {
68 return sint_route;
71 assert(false);
72 return NULL;
75 static void sint_route_destroy(HypervTestDev *dev,
76 uint8_t vp_index, uint8_t sint)
78 TestSintRoute *sint_route;
80 sint_route = sint_route_find(dev, vp_index, sint);
81 QLIST_REMOVE(sint_route, le);
82 hyperv_sint_route_unref(sint_route->sint_route);
83 g_free(sint_route);
86 static void sint_route_set_sint(HypervTestDev *dev,
87 uint8_t vp_index, uint8_t sint)
89 TestSintRoute *sint_route;
91 sint_route = sint_route_find(dev, vp_index, sint);
93 kvm_hv_sint_route_set_sint(sint_route->sint_route);
96 static uint64_t hv_test_dev_read(void *opaque, hwaddr addr, unsigned size)
98 return 0;
101 static void hv_test_dev_write(void *opaque, hwaddr addr, uint64_t data,
102 uint32_t len)
104 HypervTestDev *dev = HYPERV_TEST_DEV(opaque);
105 uint8_t sint = data & 0xFF;
106 uint8_t vp_index = (data >> 8ULL) & 0xFF;
107 uint8_t ctl = (data >> 16ULL) & 0xFF;
109 switch (ctl) {
110 case HV_TEST_DEV_SINT_ROUTE_CREATE:
111 sint_route_create(dev, vp_index, sint);
112 break;
113 case HV_TEST_DEV_SINT_ROUTE_DESTROY:
114 sint_route_destroy(dev, vp_index, sint);
115 break;
116 case HV_TEST_DEV_SINT_ROUTE_SET_SINT:
117 sint_route_set_sint(dev, vp_index, sint);
118 break;
119 default:
120 break;
124 static const MemoryRegionOps synic_test_sint_ops = {
125 .read = hv_test_dev_read,
126 .write = hv_test_dev_write,
127 .valid.min_access_size = 4,
128 .valid.max_access_size = 4,
129 .endianness = DEVICE_LITTLE_ENDIAN,
132 static void hv_test_dev_realizefn(DeviceState *d, Error **errp)
134 ISADevice *isa = ISA_DEVICE(d);
135 HypervTestDev *dev = HYPERV_TEST_DEV(d);
136 MemoryRegion *io = isa_address_space_io(isa);
138 QLIST_INIT(&dev->sint_routes);
139 memory_region_init_io(&dev->sint_control, OBJECT(dev),
140 &synic_test_sint_ops, dev,
141 "hyperv-testdev-ctl", 4);
142 memory_region_add_subregion(io, 0x3000, &dev->sint_control);
145 static void hv_test_dev_class_init(ObjectClass *klass, void *data)
147 DeviceClass *dc = DEVICE_CLASS(klass);
149 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
150 dc->realize = hv_test_dev_realizefn;
153 static const TypeInfo hv_test_dev_info = {
154 .name = TYPE_HYPERV_TEST_DEV,
155 .parent = TYPE_ISA_DEVICE,
156 .instance_size = sizeof(HypervTestDev),
157 .class_init = hv_test_dev_class_init,
160 static void hv_test_dev_register_types(void)
162 type_register_static(&hv_test_dev_info);
164 type_init(hv_test_dev_register_types);