4 * Copyright (c) 2012 Red Hat Inc.
5 * Author: Michael S. Tsirkin <mst@redhat.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
22 #include "hw/pci/pci.h"
23 #include "hw/qdev-properties.h"
24 #include "qemu/event_notifier.h"
25 #include "qemu/module.h"
26 #include "sysemu/kvm.h"
27 #include "qom/object.h"
29 typedef struct PCITestDevHdr
{
40 typedef struct IOTest
{
42 EventNotifier notifier
;
50 #define IOTEST_DATAMATCH 0xFA
51 #define IOTEST_NOMATCH 0xCE
53 #define IOTEST_IOSIZE 128
54 #define IOTEST_MEMSIZE 2048
56 static const char *iotest_test
[] = {
62 static const char *iotest_type
[] = {
67 #define IOTEST_TEST(i) (iotest_test[((i) % ARRAY_SIZE(iotest_test))])
68 #define IOTEST_TYPE(i) (iotest_type[((i) / ARRAY_SIZE(iotest_test))])
69 #define IOTEST_MAX_TEST (ARRAY_SIZE(iotest_test))
70 #define IOTEST_MAX_TYPE (ARRAY_SIZE(iotest_type))
71 #define IOTEST_MAX (IOTEST_MAX_TEST * IOTEST_MAX_TYPE)
79 #define IOTEST_ACCESS_TYPE uint8_t
80 #define IOTEST_ACCESS_WIDTH (sizeof(uint8_t))
82 struct PCITestDevState
{
95 typedef struct PCITestDevState PCITestDevState
;
97 #define TYPE_PCI_TEST_DEV "pci-testdev"
99 DECLARE_INSTANCE_CHECKER(PCITestDevState
, PCI_TEST_DEV
,
102 #define IOTEST_IS_MEM(i) (strcmp(IOTEST_TYPE(i), "portio"))
103 #define IOTEST_REGION(d, i) (IOTEST_IS_MEM(i) ? &(d)->mmio : &(d)->portio)
104 #define IOTEST_SIZE(i) (IOTEST_IS_MEM(i) ? IOTEST_MEMSIZE : IOTEST_IOSIZE)
105 #define IOTEST_PCI_BAR(i) (IOTEST_IS_MEM(i) ? PCI_BASE_ADDRESS_SPACE_MEMORY : \
106 PCI_BASE_ADDRESS_SPACE_IO)
108 static int pci_testdev_start(IOTest
*test
)
110 test
->hdr
->count
= 0;
111 if (!test
->hasnotifier
) {
114 event_notifier_test_and_clear(&test
->notifier
);
115 memory_region_add_eventfd(test
->mr
,
116 le32_to_cpu(test
->hdr
->offset
),
124 static void pci_testdev_stop(IOTest
*test
)
126 if (!test
->hasnotifier
) {
129 memory_region_del_eventfd(test
->mr
,
130 le32_to_cpu(test
->hdr
->offset
),
138 pci_testdev_reset(PCITestDevState
*d
)
140 if (d
->current
== -1) {
143 pci_testdev_stop(&d
->tests
[d
->current
]);
147 static void pci_testdev_inc(IOTest
*test
, unsigned inc
)
149 uint32_t c
= le32_to_cpu(test
->hdr
->count
);
150 test
->hdr
->count
= cpu_to_le32(c
+ inc
);
154 pci_testdev_write(void *opaque
, hwaddr addr
, uint64_t val
,
155 unsigned size
, int type
)
157 PCITestDevState
*d
= opaque
;
161 if (addr
== offsetof(PCITestDevHdr
, test
)) {
162 pci_testdev_reset(d
);
163 if (val
>= IOTEST_MAX_TEST
) {
166 t
= type
* IOTEST_MAX_TEST
+ val
;
167 r
= pci_testdev_start(&d
->tests
[t
]);
174 if (d
->current
< 0) {
177 test
= &d
->tests
[d
->current
];
178 if (addr
!= le32_to_cpu(test
->hdr
->offset
)) {
181 if (test
->match_data
&& test
->size
!= size
) {
184 if (test
->match_data
&& val
!= test
->hdr
->data
) {
187 pci_testdev_inc(test
, 1);
191 pci_testdev_read(void *opaque
, hwaddr addr
, unsigned size
)
193 PCITestDevState
*d
= opaque
;
196 if (d
->current
< 0) {
199 test
= &d
->tests
[d
->current
];
200 buf
= (const char *)test
->hdr
;
201 if (addr
+ size
>= test
->bufsize
) {
204 if (test
->hasnotifier
) {
205 event_notifier_test_and_clear(&test
->notifier
);
211 pci_testdev_mmio_write(void *opaque
, hwaddr addr
, uint64_t val
,
214 pci_testdev_write(opaque
, addr
, val
, size
, 0);
218 pci_testdev_pio_write(void *opaque
, hwaddr addr
, uint64_t val
,
221 pci_testdev_write(opaque
, addr
, val
, size
, 1);
224 static const MemoryRegionOps pci_testdev_mmio_ops
= {
225 .read
= pci_testdev_read
,
226 .write
= pci_testdev_mmio_write
,
227 .endianness
= DEVICE_LITTLE_ENDIAN
,
229 .min_access_size
= 1,
230 .max_access_size
= 1,
234 static const MemoryRegionOps pci_testdev_pio_ops
= {
235 .read
= pci_testdev_read
,
236 .write
= pci_testdev_pio_write
,
237 .endianness
= DEVICE_LITTLE_ENDIAN
,
239 .min_access_size
= 1,
240 .max_access_size
= 1,
244 static void pci_testdev_realize(PCIDevice
*pci_dev
, Error
**errp
)
246 PCITestDevState
*d
= PCI_TEST_DEV(pci_dev
);
250 bool fastmmio
= kvm_ioeventfd_any_length_enabled();
252 pci_conf
= pci_dev
->config
;
254 pci_conf
[PCI_INTERRUPT_PIN
] = 0; /* no interrupt pin */
256 memory_region_init_io(&d
->mmio
, OBJECT(d
), &pci_testdev_mmio_ops
, d
,
257 "pci-testdev-mmio", IOTEST_MEMSIZE
* 2);
258 memory_region_init_io(&d
->portio
, OBJECT(d
), &pci_testdev_pio_ops
, d
,
259 "pci-testdev-portio", IOTEST_IOSIZE
* 2);
260 pci_register_bar(pci_dev
, 0, PCI_BASE_ADDRESS_SPACE_MEMORY
, &d
->mmio
);
261 pci_register_bar(pci_dev
, 1, PCI_BASE_ADDRESS_SPACE_IO
, &d
->portio
);
263 if (d
->membar_size
) {
264 memory_region_init(&d
->membar
, OBJECT(d
), "pci-testdev-membar",
266 pci_register_bar(pci_dev
, 2,
267 PCI_BASE_ADDRESS_SPACE_MEMORY
|
268 PCI_BASE_ADDRESS_MEM_PREFETCH
|
269 PCI_BASE_ADDRESS_MEM_TYPE_64
,
274 d
->tests
= g_malloc0(IOTEST_MAX
* sizeof *d
->tests
);
275 for (i
= 0; i
< IOTEST_MAX
; ++i
) {
276 IOTest
*test
= &d
->tests
[i
];
277 name
= g_strdup_printf("%s-%s", IOTEST_TYPE(i
), IOTEST_TEST(i
));
278 test
->bufsize
= sizeof(PCITestDevHdr
) + strlen(name
) + 1;
279 test
->hdr
= g_malloc0(test
->bufsize
);
280 memcpy(test
->hdr
->name
, name
, strlen(name
) + 1);
282 test
->hdr
->offset
= cpu_to_le32(IOTEST_SIZE(i
) + i
* IOTEST_ACCESS_WIDTH
);
283 test
->match_data
= strcmp(IOTEST_TEST(i
), "wildcard-eventfd");
284 if (fastmmio
&& IOTEST_IS_MEM(i
) && !test
->match_data
) {
287 test
->size
= IOTEST_ACCESS_WIDTH
;
290 test
->hdr
->data
= test
->match_data
? IOTEST_DATAMATCH
: IOTEST_NOMATCH
;
291 test
->hdr
->width
= IOTEST_ACCESS_WIDTH
;
292 test
->mr
= IOTEST_REGION(d
, i
);
293 if (!strcmp(IOTEST_TEST(i
), "no-eventfd")) {
294 test
->hasnotifier
= false;
297 r
= event_notifier_init(&test
->notifier
, 0);
299 test
->hasnotifier
= true;
304 pci_testdev_uninit(PCIDevice
*dev
)
306 PCITestDevState
*d
= PCI_TEST_DEV(dev
);
309 pci_testdev_reset(d
);
310 for (i
= 0; i
< IOTEST_MAX
; ++i
) {
311 if (d
->tests
[i
].hasnotifier
) {
312 event_notifier_cleanup(&d
->tests
[i
].notifier
);
314 g_free(d
->tests
[i
].hdr
);
319 static void qdev_pci_testdev_reset(DeviceState
*dev
)
321 PCITestDevState
*d
= PCI_TEST_DEV(dev
);
322 pci_testdev_reset(d
);
325 static Property pci_testdev_properties
[] = {
326 DEFINE_PROP_SIZE("membar", PCITestDevState
, membar_size
, 0),
327 DEFINE_PROP_END_OF_LIST(),
330 static void pci_testdev_class_init(ObjectClass
*klass
, void *data
)
332 DeviceClass
*dc
= DEVICE_CLASS(klass
);
333 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
335 k
->realize
= pci_testdev_realize
;
336 k
->exit
= pci_testdev_uninit
;
337 k
->vendor_id
= PCI_VENDOR_ID_REDHAT
;
338 k
->device_id
= PCI_DEVICE_ID_REDHAT_TEST
;
340 k
->class_id
= PCI_CLASS_OTHERS
;
341 dc
->desc
= "PCI Test Device";
342 set_bit(DEVICE_CATEGORY_MISC
, dc
->categories
);
343 dc
->reset
= qdev_pci_testdev_reset
;
344 device_class_set_props(dc
, pci_testdev_properties
);
347 static const TypeInfo pci_testdev_info
= {
348 .name
= TYPE_PCI_TEST_DEV
,
349 .parent
= TYPE_PCI_DEVICE
,
350 .instance_size
= sizeof(PCITestDevState
),
351 .class_init
= pci_testdev_class_init
,
352 .interfaces
= (InterfaceInfo
[]) {
353 { INTERFACE_CONVENTIONAL_PCI_DEVICE
},
358 static void pci_testdev_register_types(void)
360 type_register_static(&pci_testdev_info
);
363 type_init(pci_testdev_register_types
)