2 * QEMU KVM Hyper-V test device to support Hyper-V kvm-unit-tests
4 * Copyright (C) 2015 Andrey Smetanin <asmetanin@virtuozzo.com>
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 <linux/kvm.h>
19 #include "hw/isa/isa.h"
20 #include "sysemu/kvm.h"
21 #include "target/i386/hyperv.h"
24 typedef struct TestSintRoute
{
25 QLIST_ENTRY(TestSintRoute
) le
;
28 HvSintRoute
*sint_route
;
31 struct HypervTestDev
{
33 MemoryRegion sint_control
;
34 QLIST_HEAD(, TestSintRoute
) sint_routes
;
36 typedef struct HypervTestDev HypervTestDev
;
38 #define TYPE_HYPERV_TEST_DEV "hyperv-testdev"
39 #define HYPERV_TEST_DEV(obj) \
40 OBJECT_CHECK(HypervTestDev, (obj), TYPE_HYPERV_TEST_DEV)
43 HV_TEST_DEV_SINT_ROUTE_CREATE
= 1,
44 HV_TEST_DEV_SINT_ROUTE_DESTROY
,
45 HV_TEST_DEV_SINT_ROUTE_SET_SINT
48 static void sint_route_create(HypervTestDev
*dev
,
49 uint8_t vp_index
, uint8_t sint
)
51 TestSintRoute
*sint_route
;
53 sint_route
= g_new0(TestSintRoute
, 1);
56 sint_route
->vp_index
= vp_index
;
57 sint_route
->sint
= sint
;
59 sint_route
->sint_route
= kvm_hv_sint_route_create(vp_index
, sint
, NULL
);
60 assert(sint_route
->sint_route
);
62 QLIST_INSERT_HEAD(&dev
->sint_routes
, sint_route
, le
);
65 static TestSintRoute
*sint_route_find(HypervTestDev
*dev
,
66 uint8_t vp_index
, uint8_t sint
)
68 TestSintRoute
*sint_route
;
70 QLIST_FOREACH(sint_route
, &dev
->sint_routes
, le
) {
71 if (sint_route
->vp_index
== vp_index
&& sint_route
->sint
== sint
) {
79 static void sint_route_destroy(HypervTestDev
*dev
,
80 uint8_t vp_index
, uint8_t sint
)
82 TestSintRoute
*sint_route
;
84 sint_route
= sint_route_find(dev
, vp_index
, sint
);
85 QLIST_REMOVE(sint_route
, le
);
86 kvm_hv_sint_route_destroy(sint_route
->sint_route
);
90 static void sint_route_set_sint(HypervTestDev
*dev
,
91 uint8_t vp_index
, uint8_t sint
)
93 TestSintRoute
*sint_route
;
95 sint_route
= sint_route_find(dev
, vp_index
, sint
);
97 kvm_hv_sint_route_set_sint(sint_route
->sint_route
);
100 static uint64_t hv_test_dev_read(void *opaque
, hwaddr addr
, unsigned size
)
105 static void hv_test_dev_write(void *opaque
, hwaddr addr
, uint64_t data
,
108 HypervTestDev
*dev
= HYPERV_TEST_DEV(opaque
);
109 uint8_t sint
= data
& 0xFF;
110 uint8_t vp_index
= (data
>> 8ULL) & 0xFF;
111 uint8_t ctl
= (data
>> 16ULL) & 0xFF;
114 case HV_TEST_DEV_SINT_ROUTE_CREATE
:
115 sint_route_create(dev
, vp_index
, sint
);
117 case HV_TEST_DEV_SINT_ROUTE_DESTROY
:
118 sint_route_destroy(dev
, vp_index
, sint
);
120 case HV_TEST_DEV_SINT_ROUTE_SET_SINT
:
121 sint_route_set_sint(dev
, vp_index
, sint
);
128 static const MemoryRegionOps synic_test_sint_ops
= {
129 .read
= hv_test_dev_read
,
130 .write
= hv_test_dev_write
,
131 .valid
.min_access_size
= 4,
132 .valid
.max_access_size
= 4,
133 .endianness
= DEVICE_LITTLE_ENDIAN
,
136 static void hv_test_dev_realizefn(DeviceState
*d
, Error
**errp
)
138 ISADevice
*isa
= ISA_DEVICE(d
);
139 HypervTestDev
*dev
= HYPERV_TEST_DEV(d
);
140 MemoryRegion
*io
= isa_address_space_io(isa
);
142 QLIST_INIT(&dev
->sint_routes
);
143 memory_region_init_io(&dev
->sint_control
, OBJECT(dev
),
144 &synic_test_sint_ops
, dev
,
145 "hyperv-testdev-ctl", 4);
146 memory_region_add_subregion(io
, 0x3000, &dev
->sint_control
);
149 static void hv_test_dev_class_init(ObjectClass
*klass
, void *data
)
151 DeviceClass
*dc
= DEVICE_CLASS(klass
);
153 set_bit(DEVICE_CATEGORY_MISC
, dc
->categories
);
154 dc
->realize
= hv_test_dev_realizefn
;
157 static const TypeInfo hv_test_dev_info
= {
158 .name
= TYPE_HYPERV_TEST_DEV
,
159 .parent
= TYPE_ISA_DEVICE
,
160 .instance_size
= sizeof(HypervTestDev
),
161 .class_init
= hv_test_dev_class_init
,
164 static void hv_test_dev_register_types(void)
166 type_register_static(&hv_test_dev_info
);
168 type_init(hv_test_dev_register_types
);