* [Qemu-devel] [PULL 0/4] pci: add pci test device
@ 2013-04-18 8:00 Michael S. Tsirkin
2013-04-18 8:00 ` [Qemu-devel] [PATCH 1/4] kvm: remove unused APIs Michael S. Tsirkin
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Michael S. Tsirkin @ 2013-04-18 8:00 UTC (permalink / raw)
To: qemu-devel, Anthony Liguori; +Cc: mst
The following changes since commit e2ec3f976803b360c70d9ae2ba13852fa5d11665:
qjson: to_json() case QTYPE_QSTRING is buggy, rewrite (2013-04-13 19:40:25 +0000)
are available in the git repository at:
git://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git tags/for_anthony
for you to fetch changes up to 22773d6066a7f01a95f78c270edf9dbd2e755ac3:
pci: add pci test device (2013-04-16 01:41:53 +0300)
----------------------------------------------------------------
pci: add pci test device
This adds a new device that we can use for testing PCI PIO and MMIO, with and
without ioeventfd in different configurations. FAST_MMIO will be added if/when
kvm supports it. Also included are minor cleanups in kvm APIs that it needs.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
----------------------------------------------------------------
Michael S. Tsirkin (4):
kvm: remove unused APIs
kvm: support any size for pio eventfd
kvm: support non datamatch ioeventfd
pci: add pci test device
default-configs/pci.mak | 1 +
docs/specs/pci-testdev.txt | 26 ++++
hw/misc/Makefile.objs | 1 +
hw/misc/pci-testdev.c | 325 +++++++++++++++++++++++++++++++++++++++++++++
include/hw/pci/pci.h | 1 +
include/sysemu/kvm.h | 4 -
kvm-all.c | 133 ++++++++++---------
kvm-stub.c | 10 --
8 files changed, 422 insertions(+), 79 deletions(-)
create mode 100644 docs/specs/pci-testdev.txt
create mode 100644 hw/misc/pci-testdev.c
Michael S. Tsirkin (4):
kvm: remove unused APIs
kvm: support any size for pio eventfd
kvm: support non datamatch ioeventfd
pci: add pci test device
default-configs/pci.mak | 1 +
docs/specs/pci-testdev.txt | 26 ++++
hw/misc/Makefile.objs | 1 +
hw/misc/pci-testdev.c | 325 +++++++++++++++++++++++++++++++++++++++++++++
include/hw/pci/pci.h | 1 +
include/sysemu/kvm.h | 4 -
kvm-all.c | 133 ++++++++++---------
kvm-stub.c | 10 --
8 files changed, 422 insertions(+), 79 deletions(-)
create mode 100644 docs/specs/pci-testdev.txt
create mode 100644 hw/misc/pci-testdev.c
--
MST
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 1/4] kvm: remove unused APIs
2013-04-18 8:00 [Qemu-devel] [PULL 0/4] pci: add pci test device Michael S. Tsirkin
@ 2013-04-18 8:00 ` Michael S. Tsirkin
2013-04-18 8:00 ` [Qemu-devel] [PATCH 2/4] kvm: support any size for pio eventfd Michael S. Tsirkin
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Michael S. Tsirkin @ 2013-04-18 8:00 UTC (permalink / raw)
To: qemu-devel, Anthony Liguori; +Cc: mst
There are only used internally now, move them
out of header and out of stub.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/sysemu/kvm.h | 4 --
kvm-all.c | 107 ++++++++++++++++++++++++++-------------------------
kvm-stub.c | 10 -----
3 files changed, 54 insertions(+), 67 deletions(-)
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index f2d97b5..4a65d9f 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -283,10 +283,6 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
#endif
#endif
-int kvm_set_ioeventfd_mmio(int fd, uint32_t adr, uint32_t val, bool assign,
- uint32_t size);
-
-int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign);
int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg);
diff --git a/kvm-all.c b/kvm-all.c
index 9b433d3..ca9775d 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -500,6 +500,60 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
return ret;
}
+static int kvm_set_ioeventfd_mmio(int fd, uint32_t addr, uint32_t val, bool assign,
+ uint32_t size)
+{
+ int ret;
+ struct kvm_ioeventfd iofd;
+
+ iofd.datamatch = val;
+ iofd.addr = addr;
+ iofd.len = size;
+ iofd.flags = KVM_IOEVENTFD_FLAG_DATAMATCH;
+ iofd.fd = fd;
+
+ if (!kvm_enabled()) {
+ return -ENOSYS;
+ }
+
+ if (!assign) {
+ iofd.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
+ }
+
+ ret = kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &iofd);
+
+ if (ret < 0) {
+ return -errno;
+ }
+
+ return 0;
+}
+
+static int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val,
+ bool assign)
+{
+ struct kvm_ioeventfd kick = {
+ .datamatch = val,
+ .addr = addr,
+ .len = 2,
+ .flags = KVM_IOEVENTFD_FLAG_DATAMATCH | KVM_IOEVENTFD_FLAG_PIO,
+ .fd = fd,
+ };
+ int r;
+ if (!kvm_enabled()) {
+ return -ENOSYS;
+ }
+ if (!assign) {
+ kick.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
+ }
+ r = kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &kick);
+ if (r < 0) {
+ return r;
+ }
+ return 0;
+}
+
+
static int kvm_check_many_ioeventfds(void)
{
/* Userspace can use ioeventfd for io notification. This requires a host
@@ -1971,59 +2025,6 @@ int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset)
return r;
}
-
-int kvm_set_ioeventfd_mmio(int fd, uint32_t addr, uint32_t val, bool assign,
- uint32_t size)
-{
- int ret;
- struct kvm_ioeventfd iofd;
-
- iofd.datamatch = val;
- iofd.addr = addr;
- iofd.len = size;
- iofd.flags = KVM_IOEVENTFD_FLAG_DATAMATCH;
- iofd.fd = fd;
-
- if (!kvm_enabled()) {
- return -ENOSYS;
- }
-
- if (!assign) {
- iofd.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
- }
-
- ret = kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &iofd);
-
- if (ret < 0) {
- return -errno;
- }
-
- return 0;
-}
-
-int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
-{
- struct kvm_ioeventfd kick = {
- .datamatch = val,
- .addr = addr,
- .len = 2,
- .flags = KVM_IOEVENTFD_FLAG_DATAMATCH | KVM_IOEVENTFD_FLAG_PIO,
- .fd = fd,
- };
- int r;
- if (!kvm_enabled()) {
- return -ENOSYS;
- }
- if (!assign) {
- kick.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
- }
- r = kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &kick);
- if (r < 0) {
- return r;
- }
- return 0;
-}
-
int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr)
{
return kvm_arch_on_sigbus_vcpu(cpu, code, addr);
diff --git a/kvm-stub.c b/kvm-stub.c
index 760aadc..ef1f201 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -102,16 +102,6 @@ int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset)
}
#endif
-int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
-{
- return -ENOSYS;
-}
-
-int kvm_set_ioeventfd_mmio(int fd, uint32_t adr, uint32_t val, bool assign, uint32_t len)
-{
- return -ENOSYS;
-}
-
int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr)
{
return 1;
--
MST
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 2/4] kvm: support any size for pio eventfd
2013-04-18 8:00 [Qemu-devel] [PULL 0/4] pci: add pci test device Michael S. Tsirkin
2013-04-18 8:00 ` [Qemu-devel] [PATCH 1/4] kvm: remove unused APIs Michael S. Tsirkin
@ 2013-04-18 8:00 ` Michael S. Tsirkin
2013-04-18 8:00 ` [Qemu-devel] [PATCH 3/4] kvm: support non datamatch ioeventfd Michael S. Tsirkin
2013-04-18 8:00 ` [Qemu-devel] [PATCH 4/4] pci: add pci test device Michael S. Tsirkin
3 siblings, 0 replies; 5+ messages in thread
From: Michael S. Tsirkin @ 2013-04-18 8:00 UTC (permalink / raw)
To: qemu-devel, Anthony Liguori; +Cc: mst
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
kvm-all.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/kvm-all.c b/kvm-all.c
index ca9775d..589e37c 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -500,8 +500,8 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
return ret;
}
-static int kvm_set_ioeventfd_mmio(int fd, uint32_t addr, uint32_t val, bool assign,
- uint32_t size)
+static int kvm_set_ioeventfd_mmio(int fd, uint32_t addr, uint32_t val,
+ bool assign, uint32_t size)
{
int ret;
struct kvm_ioeventfd iofd;
@@ -529,13 +529,13 @@ static int kvm_set_ioeventfd_mmio(int fd, uint32_t addr, uint32_t val, bool assi
return 0;
}
-static int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val,
- bool assign)
+static int kvm_set_ioeventfd_pio(int fd, uint16_t addr, uint16_t val,
+ bool assign, uint32_t size)
{
struct kvm_ioeventfd kick = {
.datamatch = val,
.addr = addr,
- .len = 2,
+ .len = size,
.flags = KVM_IOEVENTFD_FLAG_DATAMATCH | KVM_IOEVENTFD_FLAG_PIO,
.fd = fd,
};
@@ -571,7 +571,7 @@ static int kvm_check_many_ioeventfds(void)
if (ioeventfds[i] < 0) {
break;
}
- ret = kvm_set_ioeventfd_pio_word(ioeventfds[i], 0, i, true);
+ ret = kvm_set_ioeventfd_pio(ioeventfds[i], 0, i, true, 2);
if (ret < 0) {
close(ioeventfds[i]);
break;
@@ -582,7 +582,7 @@ static int kvm_check_many_ioeventfds(void)
ret = i == ARRAY_SIZE(ioeventfds);
while (i-- > 0) {
- kvm_set_ioeventfd_pio_word(ioeventfds[i], 0, i, false);
+ kvm_set_ioeventfd_pio(ioeventfds[i], 0, i, false, 2);
close(ioeventfds[i]);
}
return ret;
@@ -834,10 +834,10 @@ static void kvm_io_ioeventfd_add(MemoryListener *listener,
int fd = event_notifier_get_fd(e);
int r;
- assert(match_data && section->size == 2);
+ assert(match_data && section->size <= 8);
- r = kvm_set_ioeventfd_pio_word(fd, section->offset_within_address_space,
- data, true);
+ r = kvm_set_ioeventfd_pio(fd, section->offset_within_address_space,
+ data, true, section->size);
if (r < 0) {
abort();
}
@@ -852,8 +852,8 @@ static void kvm_io_ioeventfd_del(MemoryListener *listener,
int fd = event_notifier_get_fd(e);
int r;
- r = kvm_set_ioeventfd_pio_word(fd, section->offset_within_address_space,
- data, false);
+ r = kvm_set_ioeventfd_pio(fd, section->offset_within_address_space,
+ data, false, section->size);
if (r < 0) {
abort();
}
--
MST
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 3/4] kvm: support non datamatch ioeventfd
2013-04-18 8:00 [Qemu-devel] [PULL 0/4] pci: add pci test device Michael S. Tsirkin
2013-04-18 8:00 ` [Qemu-devel] [PATCH 1/4] kvm: remove unused APIs Michael S. Tsirkin
2013-04-18 8:00 ` [Qemu-devel] [PATCH 2/4] kvm: support any size for pio eventfd Michael S. Tsirkin
@ 2013-04-18 8:00 ` Michael S. Tsirkin
2013-04-18 8:00 ` [Qemu-devel] [PATCH 4/4] pci: add pci test device Michael S. Tsirkin
3 siblings, 0 replies; 5+ messages in thread
From: Michael S. Tsirkin @ 2013-04-18 8:00 UTC (permalink / raw)
To: qemu-devel, Anthony Liguori; +Cc: mst
Adding restrictions just adds code.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
kvm-all.c | 34 ++++++++++++++++++----------------
1 file changed, 18 insertions(+), 16 deletions(-)
diff --git a/kvm-all.c b/kvm-all.c
index 589e37c..ce823f9 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -501,21 +501,24 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
}
static int kvm_set_ioeventfd_mmio(int fd, uint32_t addr, uint32_t val,
- bool assign, uint32_t size)
+ bool assign, uint32_t size, bool datamatch)
{
int ret;
struct kvm_ioeventfd iofd;
- iofd.datamatch = val;
+ iofd.datamatch = datamatch ? val : 0;
iofd.addr = addr;
iofd.len = size;
- iofd.flags = KVM_IOEVENTFD_FLAG_DATAMATCH;
+ iofd.flags = 0;
iofd.fd = fd;
if (!kvm_enabled()) {
return -ENOSYS;
}
+ if (datamatch) {
+ iofd.flags |= KVM_IOEVENTFD_FLAG_DATAMATCH;
+ }
if (!assign) {
iofd.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
}
@@ -530,19 +533,22 @@ static int kvm_set_ioeventfd_mmio(int fd, uint32_t addr, uint32_t val,
}
static int kvm_set_ioeventfd_pio(int fd, uint16_t addr, uint16_t val,
- bool assign, uint32_t size)
+ bool assign, uint32_t size, bool datamatch)
{
struct kvm_ioeventfd kick = {
- .datamatch = val,
+ .datamatch = datamatch ? val : 0,
.addr = addr,
+ .flags = KVM_IOEVENTFD_FLAG_PIO,
.len = size,
- .flags = KVM_IOEVENTFD_FLAG_DATAMATCH | KVM_IOEVENTFD_FLAG_PIO,
.fd = fd,
};
int r;
if (!kvm_enabled()) {
return -ENOSYS;
}
+ if (datamatch) {
+ kick.flags |= KVM_IOEVENTFD_FLAG_DATAMATCH;
+ }
if (!assign) {
kick.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
}
@@ -571,7 +577,7 @@ static int kvm_check_many_ioeventfds(void)
if (ioeventfds[i] < 0) {
break;
}
- ret = kvm_set_ioeventfd_pio(ioeventfds[i], 0, i, true, 2);
+ ret = kvm_set_ioeventfd_pio(ioeventfds[i], 0, i, true, 2, true);
if (ret < 0) {
close(ioeventfds[i]);
break;
@@ -582,7 +588,7 @@ static int kvm_check_many_ioeventfds(void)
ret = i == ARRAY_SIZE(ioeventfds);
while (i-- > 0) {
- kvm_set_ioeventfd_pio(ioeventfds[i], 0, i, false, 2);
+ kvm_set_ioeventfd_pio(ioeventfds[i], 0, i, false, 2, true);
close(ioeventfds[i]);
}
return ret;
@@ -802,10 +808,8 @@ static void kvm_mem_ioeventfd_add(MemoryListener *listener,
int fd = event_notifier_get_fd(e);
int r;
- assert(match_data && section->size <= 8);
-
r = kvm_set_ioeventfd_mmio(fd, section->offset_within_address_space,
- data, true, section->size);
+ data, true, section->size, match_data);
if (r < 0) {
abort();
}
@@ -820,7 +824,7 @@ static void kvm_mem_ioeventfd_del(MemoryListener *listener,
int r;
r = kvm_set_ioeventfd_mmio(fd, section->offset_within_address_space,
- data, false, section->size);
+ data, false, section->size, match_data);
if (r < 0) {
abort();
}
@@ -834,10 +838,8 @@ static void kvm_io_ioeventfd_add(MemoryListener *listener,
int fd = event_notifier_get_fd(e);
int r;
- assert(match_data && section->size <= 8);
-
r = kvm_set_ioeventfd_pio(fd, section->offset_within_address_space,
- data, true, section->size);
+ data, true, section->size, match_data);
if (r < 0) {
abort();
}
@@ -853,7 +855,7 @@ static void kvm_io_ioeventfd_del(MemoryListener *listener,
int r;
r = kvm_set_ioeventfd_pio(fd, section->offset_within_address_space,
- data, false, section->size);
+ data, false, section->size, match_data);
if (r < 0) {
abort();
}
--
MST
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 4/4] pci: add pci test device
2013-04-18 8:00 [Qemu-devel] [PULL 0/4] pci: add pci test device Michael S. Tsirkin
` (2 preceding siblings ...)
2013-04-18 8:00 ` [Qemu-devel] [PATCH 3/4] kvm: support non datamatch ioeventfd Michael S. Tsirkin
@ 2013-04-18 8:00 ` Michael S. Tsirkin
3 siblings, 0 replies; 5+ messages in thread
From: Michael S. Tsirkin @ 2013-04-18 8:00 UTC (permalink / raw)
To: qemu-devel, Anthony Liguori; +Cc: mst
This device is used for kvm unit tests,
currently it supports testing performance of ioeventfd.
Using updated kvm unittest, here's an example output:
mmio-no-eventfd:pci-mem 8796
mmio-wildcard-eventfd:pci-mem 3609
mmio-datamatch-eventfd:pci-mem 3685
portio-no-eventfd:pci-io 5287
portio-wildcard-eventfd:pci-io 1762
portio-datamatch-eventfd:pci-io 1777
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
default-configs/pci.mak | 1 +
docs/specs/pci-testdev.txt | 26 ++++
hw/misc/Makefile.objs | 1 +
hw/misc/pci-testdev.c | 325 +++++++++++++++++++++++++++++++++++++++++++++
include/hw/pci/pci.h | 1 +
5 files changed, 354 insertions(+)
create mode 100644 docs/specs/pci-testdev.txt
create mode 100644 hw/misc/pci-testdev.c
diff --git a/default-configs/pci.mak b/default-configs/pci.mak
index f5f100e..b608f31 100644
--- a/default-configs/pci.mak
+++ b/default-configs/pci.mak
@@ -24,3 +24,4 @@ CONFIG_SERIAL=y
CONFIG_SERIAL_PCI=y
CONFIG_IPACK=y
CONFIG_WDT_IB6300ESB=y
+CONFIG_PCI_TESTDEV=y
diff --git a/docs/specs/pci-testdev.txt b/docs/specs/pci-testdev.txt
new file mode 100644
index 0000000..128ae22
--- /dev/null
+++ b/docs/specs/pci-testdev.txt
@@ -0,0 +1,26 @@
+pci-test is a device used for testing low level IO
+
+device implements up to two BARs: BAR0 and BAR1.
+Each BAR can be memory or IO. Guests must detect
+BAR type and act accordingly.
+
+Each BAR size is up to 4K bytes.
+Each BAR starts with the following header:
+
+typedef struct PCITestDevHdr {
+ uint8_t test; <- write-only, starts a given test number
+ uint8_t width_type; <- read-only, type and width of access for a given test.
+ 1,2,4 for byte,word or long write.
+ any other value if test not supported on this BAR
+ uint8_t pad0[2];
+ uint32_t offset; <- read-only, offset in this BAR for a given test
+ uint32_t data; <- read-only, data to use for a given test
+ uint32_t count; <- for debugging. number of writes detected.
+ uint8_t name[]; <- for debugging. 0-terminated ASCII string.
+} PCITestDevHdr;
+
+All registers are little endian.
+
+device is expected to always implement tests 0 to N on each BAR, and to add new
+tests with higher numbers. In this way a guest can scan test numbers until it
+detects an access type that it does not support on this BAR, then stop.
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 03699c3..11b18a4 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -4,6 +4,7 @@ common-obj-$(CONFIG_TMP105) += tmp105.o
common-obj-$(CONFIG_ISA_DEBUG) += debugexit.o
common-obj-$(CONFIG_SGA) += sga.o
common-obj-$(CONFIG_ISA_TESTDEV) += pc-testdev.o
+common-obj-$(CONFIG_PCI_TESTDEV) += pci-testdev.o
obj-$(CONFIG_VMPORT) += vmport.o
diff --git a/hw/misc/pci-testdev.c b/hw/misc/pci-testdev.c
new file mode 100644
index 0000000..71ce5a3
--- /dev/null
+++ b/hw/misc/pci-testdev.c
@@ -0,0 +1,325 @@
+/*
+ * QEMU PCI test device
+ *
+ * Copyright (c) 2012 Red Hat Inc.
+ * Author: Michael S. Tsirkin <mst@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "qemu/event_notifier.h"
+#include "qemu/osdep.h"
+
+typedef struct PCITestDevHdr {
+ uint8_t test;
+ uint8_t width;
+ uint8_t pad0[2];
+ uint32_t offset;
+ uint8_t data;
+ uint8_t pad1[3];
+ uint32_t count;
+ uint8_t name[];
+} PCITestDevHdr;
+
+typedef struct IOTest {
+ MemoryRegion *mr;
+ EventNotifier notifier;
+ bool hasnotifier;
+ unsigned size;
+ bool match_data;
+ PCITestDevHdr *hdr;
+ unsigned bufsize;
+} IOTest;
+
+#define IOTEST_DATAMATCH 0xFA
+#define IOTEST_NOMATCH 0xCE
+
+#define IOTEST_IOSIZE 128
+#define IOTEST_MEMSIZE 2048
+
+static const char *iotest_test[] = {
+ "no-eventfd",
+ "wildcard-eventfd",
+ "datamatch-eventfd"
+};
+
+static const char *iotest_type[] = {
+ "mmio",
+ "portio"
+};
+
+#define IOTEST_TEST(i) (iotest_test[((i) % ARRAY_SIZE(iotest_test))])
+#define IOTEST_TYPE(i) (iotest_type[((i) / ARRAY_SIZE(iotest_test))])
+#define IOTEST_MAX_TEST (ARRAY_SIZE(iotest_test))
+#define IOTEST_MAX_TYPE (ARRAY_SIZE(iotest_type))
+#define IOTEST_MAX (IOTEST_MAX_TEST * IOTEST_MAX_TYPE)
+
+enum {
+ IOTEST_ACCESS_NAME,
+ IOTEST_ACCESS_DATA,
+ IOTEST_ACCESS_MAX,
+};
+
+#define IOTEST_ACCESS_TYPE uint8_t
+#define IOTEST_ACCESS_WIDTH (sizeof(uint8_t))
+
+typedef struct PCITestDevState {
+ PCIDevice dev;
+ MemoryRegion mmio;
+ MemoryRegion portio;
+ IOTest *tests;
+ int current;
+} PCITestDevState;
+
+#define IOTEST_IS_MEM(i) (strcmp(IOTEST_TYPE(i), "portio"))
+#define IOTEST_REGION(d, i) (IOTEST_IS_MEM(i) ? &(d)->mmio : &(d)->portio)
+#define IOTEST_SIZE(i) (IOTEST_IS_MEM(i) ? IOTEST_MEMSIZE : IOTEST_IOSIZE)
+#define IOTEST_PCI_BAR(i) (IOTEST_IS_MEM(i) ? PCI_BASE_ADDRESS_SPACE_MEMORY : \
+ PCI_BASE_ADDRESS_SPACE_IO)
+
+static int pci_testdev_start(IOTest *test)
+{
+ test->hdr->count = 0;
+ if (!test->hasnotifier) {
+ return 0;
+ }
+ event_notifier_test_and_clear(&test->notifier);
+ memory_region_add_eventfd(test->mr,
+ le32_to_cpu(test->hdr->offset),
+ test->size,
+ test->match_data,
+ test->hdr->data,
+ &test->notifier);
+ return 0;
+}
+
+static void pci_testdev_stop(IOTest *test)
+{
+ if (!test->hasnotifier) {
+ return;
+ }
+ memory_region_del_eventfd(test->mr,
+ le32_to_cpu(test->hdr->offset),
+ test->size,
+ test->match_data,
+ test->hdr->data,
+ &test->notifier);
+}
+
+static void
+pci_testdev_reset(PCITestDevState *d)
+{
+ if (d->current == -1) {
+ return;
+ }
+ pci_testdev_stop(&d->tests[d->current]);
+ d->current = -1;
+}
+
+static void pci_testdev_inc(IOTest *test, unsigned inc)
+{
+ uint32_t c = le32_to_cpu(test->hdr->count);
+ test->hdr->count = cpu_to_le32(c + inc);
+}
+
+static void
+pci_testdev_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size, int type)
+{
+ PCITestDevState *d = opaque;
+ IOTest *test;
+ int t, r;
+
+ if (addr == offsetof(PCITestDevHdr, test)) {
+ pci_testdev_reset(d);
+ if (val >= IOTEST_MAX_TEST) {
+ return;
+ }
+ t = type * IOTEST_MAX_TEST + val;
+ r = pci_testdev_start(&d->tests[t]);
+ if (r < 0) {
+ return;
+ }
+ d->current = t;
+ return;
+ }
+ if (d->current < 0) {
+ return;
+ }
+ test = &d->tests[d->current];
+ if (addr != le32_to_cpu(test->hdr->offset)) {
+ return;
+ }
+ if (test->match_data && test->size != size) {
+ return;
+ }
+ if (test->match_data && val != test->hdr->data) {
+ return;
+ }
+ pci_testdev_inc(test, 1);
+}
+
+static uint64_t
+pci_testdev_read(void *opaque, hwaddr addr, unsigned size)
+{
+ PCITestDevState *d = opaque;
+ const char *buf;
+ IOTest *test;
+ if (d->current < 0) {
+ return 0;
+ }
+ test = &d->tests[d->current];
+ buf = (const char *)test->hdr;
+ if (addr + size >= test->bufsize) {
+ return 0;
+ }
+ if (test->hasnotifier) {
+ event_notifier_test_and_clear(&test->notifier);
+ }
+ return buf[addr];
+}
+
+static void
+pci_testdev_mmio_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ pci_testdev_write(opaque, addr, val, size, 0);
+}
+
+static void
+pci_testdev_pio_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ pci_testdev_write(opaque, addr, val, size, 1);
+}
+
+static const MemoryRegionOps pci_testdev_mmio_ops = {
+ .read = pci_testdev_read,
+ .write = pci_testdev_mmio_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+};
+
+static const MemoryRegionOps pci_testdev_pio_ops = {
+ .read = pci_testdev_read,
+ .write = pci_testdev_pio_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+};
+
+static int pci_testdev_init(PCIDevice *pci_dev)
+{
+ PCITestDevState *d = DO_UPCAST(PCITestDevState, dev, pci_dev);
+ uint8_t *pci_conf;
+ char *name;
+ int r, i;
+
+ pci_conf = d->dev.config;
+
+ pci_conf[PCI_INTERRUPT_PIN] = 0; /* no interrupt pin */
+
+ memory_region_init_io(&d->mmio, &pci_testdev_mmio_ops, d,
+ "pci-testdev-mmio", IOTEST_MEMSIZE * 2);
+ memory_region_init_io(&d->portio, &pci_testdev_pio_ops, d,
+ "pci-testdev-portio", IOTEST_IOSIZE * 2);
+ pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
+ pci_register_bar(&d->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->portio);
+
+ d->current = -1;
+ d->tests = g_malloc0(IOTEST_MAX * sizeof *d->tests);
+ for (i = 0; i < IOTEST_MAX; ++i) {
+ IOTest *test = &d->tests[i];
+ name = g_strdup_printf("%s-%s", IOTEST_TYPE(i), IOTEST_TEST(i));
+ test->bufsize = sizeof(PCITestDevHdr) + strlen(name) + 1;
+ test->hdr = g_malloc0(test->bufsize);
+ memcpy(test->hdr->name, name, strlen(name) + 1);
+ g_free(name);
+ test->hdr->offset = cpu_to_le32(IOTEST_SIZE(i) + i * IOTEST_ACCESS_WIDTH);
+ test->size = IOTEST_ACCESS_WIDTH;
+ test->match_data = strcmp(IOTEST_TEST(i), "wildcard-eventfd");
+ test->hdr->test = i;
+ test->hdr->data = test->match_data ? IOTEST_DATAMATCH : IOTEST_NOMATCH;
+ test->hdr->width = IOTEST_ACCESS_WIDTH;
+ test->mr = IOTEST_REGION(d, i);
+ if (!strcmp(IOTEST_TEST(i), "no-eventfd")) {
+ test->hasnotifier = false;
+ continue;
+ }
+ r = event_notifier_init(&test->notifier, 0);
+ assert(r >= 0);
+ test->hasnotifier = true;
+ }
+
+ return 0;
+}
+
+static void
+pci_testdev_uninit(PCIDevice *dev)
+{
+ PCITestDevState *d = DO_UPCAST(PCITestDevState, dev, dev);
+ int i;
+
+ pci_testdev_reset(d);
+ for (i = 0; i < IOTEST_MAX; ++i) {
+ if (d->tests[i].hasnotifier) {
+ event_notifier_cleanup(&d->tests[i].notifier);
+ }
+ g_free(d->tests[i].hdr);
+ }
+ g_free(d->tests);
+ memory_region_destroy(&d->mmio);
+ memory_region_destroy(&d->portio);
+}
+
+static void qdev_pci_testdev_reset(DeviceState *dev)
+{
+ PCITestDevState *d = DO_UPCAST(PCITestDevState, dev.qdev, dev);
+ pci_testdev_reset(d);
+}
+
+static void pci_testdev_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = pci_testdev_init;
+ k->exit = pci_testdev_uninit;
+ k->vendor_id = PCI_VENDOR_ID_REDHAT;
+ k->device_id = PCI_DEVICE_ID_REDHAT_TEST;
+ k->revision = 0x00;
+ k->class_id = PCI_CLASS_OTHERS;
+ dc->desc = "PCI Test Device";
+ dc->reset = qdev_pci_testdev_reset;
+}
+
+static const TypeInfo pci_testdev_info = {
+ .name = "pci-testdev",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCITestDevState),
+ .class_init = pci_testdev_class_init,
+};
+
+static void pci_testdev_register_types(void)
+{
+ type_register_static(&pci_testdev_info);
+}
+
+type_init(pci_testdev_register_types)
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 05315c0..7053d5b 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -85,6 +85,7 @@
#define PCI_DEVICE_ID_REDHAT_SERIAL 0x0002
#define PCI_DEVICE_ID_REDHAT_SERIAL2 0x0003
#define PCI_DEVICE_ID_REDHAT_SERIAL4 0x0004
+#define PCI_DEVICE_ID_REDHAT_TEST 0x0005
#define PCI_DEVICE_ID_REDHAT_QXL 0x0100
#define FMT_PCIBUS PRIx64
--
MST
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-04-18 8:59 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-18 8:00 [Qemu-devel] [PULL 0/4] pci: add pci test device Michael S. Tsirkin
2013-04-18 8:00 ` [Qemu-devel] [PATCH 1/4] kvm: remove unused APIs Michael S. Tsirkin
2013-04-18 8:00 ` [Qemu-devel] [PATCH 2/4] kvm: support any size for pio eventfd Michael S. Tsirkin
2013-04-18 8:00 ` [Qemu-devel] [PATCH 3/4] kvm: support non datamatch ioeventfd Michael S. Tsirkin
2013-04-18 8:00 ` [Qemu-devel] [PATCH 4/4] pci: add pci test device Michael S. Tsirkin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.