From: Peter Xu <peterx@redhat.com>
To: qemu-devel@nongnu.org
Cc: mst@redhat.com, pbonzini@redhat.com, marcel@redhat.com,
peterx@redhat.com
Subject: [Qemu-devel] [PATCH] pci-testdev: enhance to support new testcases
Date: Thu, 22 Sep 2016 14:15:08 +0800 [thread overview]
Message-ID: <1474524908-18716-1-git-send-email-peterx@redhat.com> (raw)
pci-testdev is used mostly in kvm-unit-test for some eventfd tests.
However I see it a good framework for other tests as well (e.g., the
IOMMU unit test in the future). So enhanced it to support more
testcases.
The original memory handlers and protocol are strict and not easy to
change (we need to keep the old behavior of pci-testdev). So I added a
new parameter for the device, and memory ops will be dynamically handled
depending on what testcase it is configured. To specify a new test case
for pci-testdev, we use:
-device pci-testdev,testcase=XXX
The default will be "eventfd", which is the original behavior for
pci-testdev. In the future, we can just add new testcase for pci-testdev
to achieve different goals.
Signed-off-by: Peter Xu <peterx@redhat.com>
---
This is kind-of a RFC since I am not sure whether this is a good way.
I did run the default kvm-unit-test cases on x86 to make sure it
didn't break anything. In case this is not good, I didn't write any
further test cases (e.g., emulate device DMAR/IR operations) yet. If
we like the idea, I can move on.
Please kindly review. Thanks.
hw/misc/pci-testdev.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 76 insertions(+), 4 deletions(-)
diff --git a/hw/misc/pci-testdev.c b/hw/misc/pci-testdev.c
index 7d59902..b25d673 100644
--- a/hw/misc/pci-testdev.c
+++ b/hw/misc/pci-testdev.c
@@ -22,6 +22,19 @@
#include "hw/pci/pci.h"
#include "qemu/event_notifier.h"
#include "sysemu/kvm.h"
+#include "qemu/error-report.h"
+
+/* Type: 0 for MMIO write, 1 for PIO write. */
+typedef void (*pci_testdev_write_op)(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size, int type);
+typedef uint64_t (*pci_testdev_read_op)(void *opaque, hwaddr addr,
+ unsigned size);
+
+struct testcase {
+ const char *name;
+ pci_testdev_write_op write_op;
+ pci_testdev_read_op read_op;
+};
typedef struct PCITestDevHdr {
uint8_t test;
@@ -85,6 +98,8 @@ typedef struct PCITestDevState {
MemoryRegion portio;
IOTest *tests;
int current;
+ char *testcase_name;
+ struct testcase *testcase;
} PCITestDevState;
#define TYPE_PCI_TEST_DEV "pci-testdev"
@@ -200,22 +215,58 @@ pci_testdev_read(void *opaque, hwaddr addr, unsigned size)
return buf[addr];
}
+/*
+ * To add a new test, we need to implement both write_op and read_op,
+ * and add a new "struct testcase" into the global pci_testcases[].
+ */
+struct testcase pci_testcases[] = {
+ {"eventfd", pci_testdev_write, pci_testdev_read},
+ {NULL, NULL, NULL},
+};
+
+#define FOREACH_TEST_CASE(n) for (n = &pci_testcases[0]; n->name; n++)
+
+static struct testcase *
+pci_testdev_find_testcase(char *name)
+{
+ struct testcase *test;
+
+ FOREACH_TEST_CASE(test) {
+ if (!strcmp(test->name, name)) {
+ return test;
+ }
+ }
+ return NULL;
+}
+
+static uint64_t
+pci_testdev_common_read(void *opaque, hwaddr addr, unsigned size)
+{
+ PCITestDevState *d = opaque;
+ pci_testdev_read_op read_op = d->testcase->read_op;
+ return read_op(opaque, addr, size);
+}
+
static void
pci_testdev_mmio_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
- pci_testdev_write(opaque, addr, val, size, 0);
+ PCITestDevState *d = opaque;
+ pci_testdev_write_op write_op = d->testcase->write_op;
+ write_op(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);
+ PCITestDevState *d = opaque;
+ pci_testdev_write_op write_op = d->testcase->write_op;
+ write_op(opaque, addr, val, size, 1);
}
static const MemoryRegionOps pci_testdev_mmio_ops = {
- .read = pci_testdev_read,
+ .read = pci_testdev_common_read,
.write = pci_testdev_mmio_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.impl = {
@@ -225,7 +276,7 @@ static const MemoryRegionOps pci_testdev_mmio_ops = {
};
static const MemoryRegionOps pci_testdev_pio_ops = {
- .read = pci_testdev_read,
+ .read = pci_testdev_common_read,
.write = pci_testdev_pio_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.impl = {
@@ -281,6 +332,21 @@ static void pci_testdev_realize(PCIDevice *pci_dev, Error **errp)
assert(r >= 0);
test->hasnotifier = true;
}
+
+ if (!d->testcase_name) {
+ d->testcase_name = (char *)"eventfd";
+ }
+
+ d->testcase = pci_testdev_find_testcase(d->testcase_name);
+ if (!d->testcase) {
+ struct testcase *test;
+ error_report("Invalid test case. Currently support: {");
+ FOREACH_TEST_CASE(test) {
+ error_report("\t\"%s\", ", test->name);
+ }
+ error_report("}");
+ exit(1);
+ }
}
static void
@@ -305,6 +371,11 @@ static void qdev_pci_testdev_reset(DeviceState *dev)
pci_testdev_reset(d);
}
+static Property pci_testdev_properties[] = {
+ DEFINE_PROP_STRING("testcase", PCITestDevState, testcase_name),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
static void pci_testdev_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -319,6 +390,7 @@ static void pci_testdev_class_init(ObjectClass *klass, void *data)
dc->desc = "PCI Test Device";
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
dc->reset = qdev_pci_testdev_reset;
+ dc->props = pci_testdev_properties;
}
static const TypeInfo pci_testdev_info = {
--
2.7.4
next reply other threads:[~2016-09-22 6:15 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-09-22 6:15 Peter Xu [this message]
2016-09-22 11:18 ` [Qemu-devel] [PATCH] pci-testdev: enhance to support new testcases Andrew Jones
2016-09-23 3:37 ` Peter Xu
2016-09-22 18:23 ` Michael S. Tsirkin
2016-09-27 6:37 ` Peter Xu
2016-09-27 8:38 ` Peter Xu
2016-09-27 10:13 ` Paolo Bonzini
2016-09-28 3:04 ` Peter Xu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1474524908-18716-1-git-send-email-peterx@redhat.com \
--to=peterx@redhat.com \
--cc=marcel@redhat.com \
--cc=mst@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).