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"
17 #include "hw/isa/isa.h"
18 #include "target/i386/hyperv.h"
20 typedef struct TestSintRoute
{
21 QLIST_ENTRY(TestSintRoute
) le
;
24 HvSintRoute
*sint_route
;
27 struct HypervTestDev
{
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)
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);
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
) {
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
);
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
)
101 static void hv_test_dev_write(void *opaque
, hwaddr addr
, uint64_t data
,
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;
110 case HV_TEST_DEV_SINT_ROUTE_CREATE
:
111 sint_route_create(dev
, vp_index
, sint
);
113 case HV_TEST_DEV_SINT_ROUTE_DESTROY
:
114 sint_route_destroy(dev
, vp_index
, sint
);
116 case HV_TEST_DEV_SINT_ROUTE_SET_SINT
:
117 sint_route_set_sint(dev
, vp_index
, sint
);
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
);