* [Qemu-devel] [PATCH v2 4/6] pci: add pci test device
2013-04-04 10:39 [Qemu-devel] [PATCH v2 0/6] kvm: pci PORT IO MMIO and PV MMIO speed tests Michael S. Tsirkin
@ 2013-04-04 10:40 ` Michael S. Tsirkin
2013-04-04 10:40 ` [Qemu-devel] [PATCH v2 1/6] kvm: remove unused APIs Michael S. Tsirkin
` (4 subsequent siblings)
5 siblings, 0 replies; 15+ messages in thread
From: Michael S. Tsirkin @ 2013-04-04 10:40 UTC (permalink / raw)
To: qemu-devel, kvm, pbonzini, gleb, mtosatti
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>
---
docs/specs/pci-testdev.txt | 26 ++++
hw/Makefile.objs | 1 +
hw/pci-testdev.c | 306 +++++++++++++++++++++++++++++++++++++++++++++
hw/pci/pci.h | 1 +
4 files changed, 334 insertions(+)
create mode 100644 docs/specs/pci-testdev.txt
create mode 100644 hw/pci-testdev.c
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/Makefile.objs b/hw/Makefile.objs
index eb7eb31..b4e3b1d 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -12,6 +12,7 @@ common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
common-obj-$(CONFIG_VIRTIO) += virtio-bus.o
common-obj-y += fw_cfg.o
common-obj-$(CONFIG_PCI) += pci_bridge_dev.o
+common-obj-$(CONFIG_PCI) += pci-testdev.o
common-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
common-obj-$(CONFIG_PCI) += i82801b11.o
common-obj-y += watchdog.o
diff --git a/hw/pci-testdev.c b/hw/pci-testdev.c
new file mode 100644
index 0000000..9486624
--- /dev/null
+++ b/hw/pci-testdev.c
@@ -0,0 +1,306 @@
+#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/hw/pci/pci.h b/hw/pci/pci.h
index 774369c..d81198c 100644
--- a/hw/pci/pci.h
+++ b/hw/pci/pci.h
@@ -84,6 +84,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] 15+ messages in thread
* [Qemu-devel] [PATCH v2 1/6] kvm: remove unused APIs
2013-04-04 10:39 [Qemu-devel] [PATCH v2 0/6] kvm: pci PORT IO MMIO and PV MMIO speed tests Michael S. Tsirkin
2013-04-04 10:40 ` [Qemu-devel] [PATCH v2 4/6] pci: add pci test device Michael S. Tsirkin
@ 2013-04-04 10:40 ` Michael S. Tsirkin
2013-04-04 10:40 ` [Qemu-devel] [PATCH v2 2/6] kvm: support any size for pio eventfd Michael S. Tsirkin
` (3 subsequent siblings)
5 siblings, 0 replies; 15+ messages in thread
From: Michael S. Tsirkin @ 2013-04-04 10:40 UTC (permalink / raw)
To: qemu-devel, kvm, pbonzini, gleb, mtosatti
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] 15+ messages in thread
* [Qemu-devel] [PATCH v2 2/6] kvm: support any size for pio eventfd
2013-04-04 10:39 [Qemu-devel] [PATCH v2 0/6] kvm: pci PORT IO MMIO and PV MMIO speed tests Michael S. Tsirkin
2013-04-04 10:40 ` [Qemu-devel] [PATCH v2 4/6] pci: add pci test device Michael S. Tsirkin
2013-04-04 10:40 ` [Qemu-devel] [PATCH v2 1/6] kvm: remove unused APIs Michael S. Tsirkin
@ 2013-04-04 10:40 ` Michael S. Tsirkin
2013-04-04 10:40 ` [Qemu-devel] [PATCH v2 3/6] kvm: support non datamatch ioeventfd Michael S. Tsirkin
` (2 subsequent siblings)
5 siblings, 0 replies; 15+ messages in thread
From: Michael S. Tsirkin @ 2013-04-04 10:40 UTC (permalink / raw)
To: qemu-devel, kvm, pbonzini, gleb, mtosatti
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] 15+ messages in thread
* [Qemu-devel] [PATCH v2 3/6] kvm: support non datamatch ioeventfd
2013-04-04 10:39 [Qemu-devel] [PATCH v2 0/6] kvm: pci PORT IO MMIO and PV MMIO speed tests Michael S. Tsirkin
` (2 preceding siblings ...)
2013-04-04 10:40 ` [Qemu-devel] [PATCH v2 2/6] kvm: support any size for pio eventfd Michael S. Tsirkin
@ 2013-04-04 10:40 ` Michael S. Tsirkin
2013-04-04 10:40 ` [Qemu-devel] [PATCH v2 6/6] pci-testdev: add pv mmio test Michael S. Tsirkin
2013-04-04 10:40 ` [Qemu-devel] [PATCH v2 5/6] kvm: add PV MMIO Michael S. Tsirkin
5 siblings, 0 replies; 15+ messages in thread
From: Michael S. Tsirkin @ 2013-04-04 10:40 UTC (permalink / raw)
To: qemu-devel, kvm, pbonzini, gleb, mtosatti
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] 15+ messages in thread
* [Qemu-devel] [PATCH v2 6/6] pci-testdev: add pv mmio test
2013-04-04 10:39 [Qemu-devel] [PATCH v2 0/6] kvm: pci PORT IO MMIO and PV MMIO speed tests Michael S. Tsirkin
` (3 preceding siblings ...)
2013-04-04 10:40 ` [Qemu-devel] [PATCH v2 3/6] kvm: support non datamatch ioeventfd Michael S. Tsirkin
@ 2013-04-04 10:40 ` Michael S. Tsirkin
2013-04-04 10:40 ` [Qemu-devel] [PATCH v2 5/6] kvm: add PV MMIO Michael S. Tsirkin
5 siblings, 0 replies; 15+ messages in thread
From: Michael S. Tsirkin @ 2013-04-04 10:40 UTC (permalink / raw)
To: qemu-devel, kvm, pbonzini, gleb, mtosatti
Add ability to test the speed of PV MMIO.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
hw/pci-testdev.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/hw/pci-testdev.c b/hw/pci-testdev.c
index f0ebf99..9a50631 100644
--- a/hw/pci-testdev.c
+++ b/hw/pci-testdev.c
@@ -19,6 +19,7 @@ typedef struct IOTest {
EventNotifier notifier;
bool hasnotifier;
unsigned size;
+ bool pv;
bool match_data;
PCITestDevHdr *hdr;
unsigned bufsize;
@@ -33,7 +34,8 @@ typedef struct IOTest {
static const char *iotest_test[] = {
"no-eventfd",
"wildcard-eventfd",
- "datamatch-eventfd"
+ "datamatch-eventfd",
+ "pv-eventfd"
};
static const char *iotest_type[] = {
@@ -80,7 +82,7 @@ static int pci_testdev_start(IOTest *test)
memory_region_add_eventfd(test->mr,
le32_to_cpu(test->hdr->offset),
test->size,
- false,
+ test->pv,
test->match_data,
test->hdr->data,
&test->notifier);
@@ -95,7 +97,7 @@ static void pci_testdev_stop(IOTest *test)
memory_region_del_eventfd(test->mr,
le32_to_cpu(test->hdr->offset),
test->size,
- false,
+ test->pv,
test->match_data,
test->hdr->data,
&test->notifier);
@@ -237,7 +239,8 @@ static int pci_testdev_init(PCIDevice *pci_dev)
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->pv = !strcmp(IOTEST_TEST(i), "pv-eventfd");
+ test->match_data = !strcmp(IOTEST_TEST(i), "datamatch-eventfd");
test->hdr->test = i;
test->hdr->data = test->match_data ? IOTEST_DATAMATCH : IOTEST_NOMATCH;
test->hdr->width = IOTEST_ACCESS_WIDTH;
--
MST
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v2 5/6] kvm: add PV MMIO
2013-04-04 10:39 [Qemu-devel] [PATCH v2 0/6] kvm: pci PORT IO MMIO and PV MMIO speed tests Michael S. Tsirkin
` (4 preceding siblings ...)
2013-04-04 10:40 ` [Qemu-devel] [PATCH v2 6/6] pci-testdev: add pv mmio test Michael S. Tsirkin
@ 2013-04-04 10:40 ` Michael S. Tsirkin
2013-04-04 12:46 ` Paolo Bonzini
2013-04-04 12:50 ` Peter Maydell
5 siblings, 2 replies; 15+ messages in thread
From: Michael S. Tsirkin @ 2013-04-04 10:40 UTC (permalink / raw)
To: qemu-devel, kvm, pbonzini, gleb, mtosatti
Add an option for users to specify PV eventfd
listeners, and utilize KVM's PV MMIO underneath.
Upodate all callers.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
hw/dataplane/hostmem.c | 1 +
hw/ivshmem.c | 2 ++
hw/pci-testdev.c | 2 ++
hw/vhost.c | 4 ++--
hw/virtio-pci.c | 4 ++--
include/exec/memory.h | 10 ++++++++++
kvm-all.c | 15 ++++++++++++---
| 8 ++++++++
memory.c | 9 +++++++--
9 files changed, 46 insertions(+), 9 deletions(-)
diff --git a/hw/dataplane/hostmem.c b/hw/dataplane/hostmem.c
index 380537e..41d43e7 100644
--- a/hw/dataplane/hostmem.c
+++ b/hw/dataplane/hostmem.c
@@ -126,6 +126,7 @@ static void hostmem_listener_section_dummy(MemoryListener *listener,
static void hostmem_listener_eventfd_dummy(MemoryListener *listener,
MemoryRegionSection *section,
+ bool pv,
bool match_data, uint64_t data,
EventNotifier *e)
{
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index 68a2cf2..28e5978 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -352,6 +352,7 @@ static void ivshmem_add_eventfd(IVShmemState *s, int posn, int i)
memory_region_add_eventfd(&s->ivshmem_mmio,
DOORBELL,
4,
+ false,
true,
(posn << 16) | i,
&s->peers[posn].eventfds[i]);
@@ -362,6 +363,7 @@ static void ivshmem_del_eventfd(IVShmemState *s, int posn, int i)
memory_region_del_eventfd(&s->ivshmem_mmio,
DOORBELL,
4,
+ false,
true,
(posn << 16) | i,
&s->peers[posn].eventfds[i]);
diff --git a/hw/pci-testdev.c b/hw/pci-testdev.c
index 9486624..f0ebf99 100644
--- a/hw/pci-testdev.c
+++ b/hw/pci-testdev.c
@@ -80,6 +80,7 @@ static int pci_testdev_start(IOTest *test)
memory_region_add_eventfd(test->mr,
le32_to_cpu(test->hdr->offset),
test->size,
+ false,
test->match_data,
test->hdr->data,
&test->notifier);
@@ -94,6 +95,7 @@ static void pci_testdev_stop(IOTest *test)
memory_region_del_eventfd(test->mr,
le32_to_cpu(test->hdr->offset),
test->size,
+ false,
test->match_data,
test->hdr->data,
&test->notifier);
diff --git a/hw/vhost.c b/hw/vhost.c
index 4d6aee3..9ad7101 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -750,13 +750,13 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
}
static void vhost_eventfd_add(MemoryListener *listener,
- MemoryRegionSection *section,
+ MemoryRegionSection *section, bool pv,
bool match_data, uint64_t data, EventNotifier *e)
{
}
static void vhost_eventfd_del(MemoryListener *listener,
- MemoryRegionSection *section,
+ MemoryRegionSection *section, bool pv,
bool match_data, uint64_t data, EventNotifier *e)
{
}
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 19965e5..f9ff994 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -189,10 +189,10 @@ static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
}
virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
memory_region_add_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
- true, n, notifier);
+ false, true, n, notifier);
} else {
memory_region_del_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
- true, n, notifier);
+ false, true, n, notifier);
virtio_queue_set_host_notifier_fd_handler(vq, false, false);
event_notifier_cleanup(notifier);
}
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 2322732..3612004 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -215,8 +215,10 @@ struct MemoryListener {
void (*log_global_start)(MemoryListener *listener);
void (*log_global_stop)(MemoryListener *listener);
void (*eventfd_add)(MemoryListener *listener, MemoryRegionSection *section,
+ bool pv,
bool match_data, uint64_t data, EventNotifier *e);
void (*eventfd_del)(MemoryListener *listener, MemoryRegionSection *section,
+ bool pv,
bool match_data, uint64_t data, EventNotifier *e);
void (*coalesced_mmio_add)(MemoryListener *listener, MemoryRegionSection *section,
hwaddr addr, hwaddr len);
@@ -594,6 +596,9 @@ void memory_region_clear_flush_coalesced(MemoryRegion *mr);
* @mr: the memory region being updated.
* @addr: the address within @mr that is to be monitored
* @size: the size of the access to trigger the eventfd
+ * @pv: set if Guest can promise us that all accesses touching this address
+ * are writes of specified length, starting at the specified address.
+ * If not - it's a Guest bug. Might give faster access.
* @match_data: whether to match against @data, instead of just @addr
* @data: the data to match against the guest write
* @fd: the eventfd to be triggered when @addr, @size, and @data all match.
@@ -601,6 +606,7 @@ void memory_region_clear_flush_coalesced(MemoryRegion *mr);
void memory_region_add_eventfd(MemoryRegion *mr,
hwaddr addr,
unsigned size,
+ bool pv,
bool match_data,
uint64_t data,
EventNotifier *e);
@@ -614,6 +620,9 @@ void memory_region_add_eventfd(MemoryRegion *mr,
* @mr: the memory region being updated.
* @addr: the address within @mr that is to be monitored
* @size: the size of the access to trigger the eventfd
+ * @pv: set if Guest can promise us that all accesses touching this address
+ * are writes of specified length, starting at the specified address.
+ * If not - it's a Guest bug. Might give faster access.
* @match_data: whether to match against @data, instead of just @addr
* @data: the data to match against the guest write
* @fd: the eventfd to be triggered when @addr, @size, and @data all match.
@@ -621,6 +630,7 @@ void memory_region_add_eventfd(MemoryRegion *mr,
void memory_region_del_eventfd(MemoryRegion *mr,
hwaddr addr,
unsigned size,
+ bool pv,
bool match_data,
uint64_t data,
EventNotifier *e);
diff --git a/kvm-all.c b/kvm-all.c
index ce823f9..59835ca 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -500,7 +500,7 @@ 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,
+static int kvm_set_ioeventfd_mmio(int fd, uint32_t addr, uint32_t val, bool pv,
bool assign, uint32_t size, bool datamatch)
{
int ret;
@@ -518,6 +518,11 @@ static int kvm_set_ioeventfd_mmio(int fd, uint32_t addr, uint32_t val,
if (datamatch) {
iofd.flags |= KVM_IOEVENTFD_FLAG_DATAMATCH;
+ /* Kernel doesn't support data match with PV MMIO. */
+ pv = false;
+ }
+ if (pv) {
+ iofd.flags |= KVM_IOEVENTFD_FLAG_PV_MMIO;
}
if (!assign) {
iofd.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
@@ -802,6 +807,7 @@ static void kvm_log_global_stop(struct MemoryListener *listener)
static void kvm_mem_ioeventfd_add(MemoryListener *listener,
MemoryRegionSection *section,
+ bool pv,
bool match_data, uint64_t data,
EventNotifier *e)
{
@@ -809,7 +815,7 @@ static void kvm_mem_ioeventfd_add(MemoryListener *listener,
int r;
r = kvm_set_ioeventfd_mmio(fd, section->offset_within_address_space,
- data, true, section->size, match_data);
+ data, pv, true, section->size, match_data);
if (r < 0) {
abort();
}
@@ -817,6 +823,7 @@ static void kvm_mem_ioeventfd_add(MemoryListener *listener,
static void kvm_mem_ioeventfd_del(MemoryListener *listener,
MemoryRegionSection *section,
+ bool pv,
bool match_data, uint64_t data,
EventNotifier *e)
{
@@ -824,7 +831,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, match_data);
+ data, pv, false, section->size, match_data);
if (r < 0) {
abort();
}
@@ -832,6 +839,7 @@ static void kvm_mem_ioeventfd_del(MemoryListener *listener,
static void kvm_io_ioeventfd_add(MemoryListener *listener,
MemoryRegionSection *section,
+ bool pv,
bool match_data, uint64_t data,
EventNotifier *e)
{
@@ -847,6 +855,7 @@ static void kvm_io_ioeventfd_add(MemoryListener *listener,
static void kvm_io_ioeventfd_del(MemoryListener *listener,
MemoryRegionSection *section,
+ bool pv,
bool match_data, uint64_t data,
EventNotifier *e)
--git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index caca979..871cc0a 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -449,11 +449,19 @@ enum {
kvm_ioeventfd_flag_nr_datamatch,
kvm_ioeventfd_flag_nr_pio,
kvm_ioeventfd_flag_nr_deassign,
+ kvm_ioeventfd_flag_nr_pv_mmio,
kvm_ioeventfd_flag_nr_max,
};
#define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch)
#define KVM_IOEVENTFD_FLAG_PIO (1 << kvm_ioeventfd_flag_nr_pio)
+/*
+ * PV_MMIO - Guest can promise us that all accesses touching this address
+ * are writes of specified length, starting at the specified address.
+ * If not - it's a Guest bug.
+ * Can not be used together with either PIO or DATAMATCH.
+ */
+#define KVM_IOEVENTFD_FLAG_PV_MMIO (1 << kvm_ioeventfd_flag_nr_pv_mmio)
#define KVM_IOEVENTFD_FLAG_DEASSIGN (1 << kvm_ioeventfd_flag_nr_deassign)
#define KVM_IOEVENTFD_VALID_FLAG_MASK ((1 << kvm_ioeventfd_flag_nr_max) - 1)
diff --git a/memory.c b/memory.c
index 92a2196..5a64b3c 100644
--- a/memory.c
+++ b/memory.c
@@ -162,6 +162,7 @@ struct CoalescedMemoryRange {
struct MemoryRegionIoeventfd {
AddrRange addr;
+ bool pv;
bool match_data;
uint64_t data;
EventNotifier *e;
@@ -600,7 +601,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
.offset_within_address_space = int128_get64(fd->addr.start),
.size = int128_get64(fd->addr.size),
};
- MEMORY_LISTENER_CALL(eventfd_del, Forward, §ion,
+ MEMORY_LISTENER_CALL(eventfd_del, Forward, §ion, fd->pv,
fd->match_data, fd->data, fd->e);
++iold;
} else if (inew < fds_new_nb
@@ -613,7 +614,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
.offset_within_address_space = int128_get64(fd->addr.start),
.size = int128_get64(fd->addr.size),
};
- MEMORY_LISTENER_CALL(eventfd_add, Reverse, §ion,
+ MEMORY_LISTENER_CALL(eventfd_add, Reverse, §ion, fd->pv,
fd->match_data, fd->data, fd->e);
++inew;
} else {
@@ -1243,6 +1244,7 @@ void memory_region_clear_flush_coalesced(MemoryRegion *mr)
void memory_region_add_eventfd(MemoryRegion *mr,
hwaddr addr,
unsigned size,
+ bool pv,
bool match_data,
uint64_t data,
EventNotifier *e)
@@ -1250,6 +1252,7 @@ void memory_region_add_eventfd(MemoryRegion *mr,
MemoryRegionIoeventfd mrfd = {
.addr.start = int128_make64(addr),
.addr.size = int128_make64(size),
+ .pv = pv,
.match_data = match_data,
.data = data,
.e = e,
@@ -1276,6 +1279,7 @@ void memory_region_add_eventfd(MemoryRegion *mr,
void memory_region_del_eventfd(MemoryRegion *mr,
hwaddr addr,
unsigned size,
+ bool pv,
bool match_data,
uint64_t data,
EventNotifier *e)
@@ -1283,6 +1287,7 @@ void memory_region_del_eventfd(MemoryRegion *mr,
MemoryRegionIoeventfd mrfd = {
.addr.start = int128_make64(addr),
.addr.size = int128_make64(size),
+ .pv = pv,
.match_data = match_data,
.data = data,
.e = e,
--
MST
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v2 5/6] kvm: add PV MMIO
2013-04-04 10:40 ` [Qemu-devel] [PATCH v2 5/6] kvm: add PV MMIO Michael S. Tsirkin
@ 2013-04-04 12:46 ` Paolo Bonzini
2013-04-04 13:10 ` Michael S. Tsirkin
2013-04-04 12:50 ` Peter Maydell
1 sibling, 1 reply; 15+ messages in thread
From: Paolo Bonzini @ 2013-04-04 12:46 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: gleb, mtosatti, qemu-devel, kvm, Avi Kivity
Il 04/04/2013 12:40, Michael S. Tsirkin ha scritto:
> Add an option for users to specify PV eventfd
> listeners, and utilize KVM's PV MMIO underneath.
> Upodate all callers.
I would like Avi to comment on this, because I think this is not the
"memory-API approved" way of doing things. You need KVM to define its
own AddressSpace, and make KVM's listener use
memory_region_to_address_space to figure out if it is for PV MMIO.
To handle accesses from TCG, the PV AddressSpace can simply have just an
alias to the actual MemoryRegion where the doorbell is.
Paolo
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
> hw/dataplane/hostmem.c | 1 +
> hw/ivshmem.c | 2 ++
> hw/pci-testdev.c | 2 ++
> hw/vhost.c | 4 ++--
> hw/virtio-pci.c | 4 ++--
> include/exec/memory.h | 10 ++++++++++
> kvm-all.c | 15 ++++++++++++---
> linux-headers/linux/kvm.h | 8 ++++++++
> memory.c | 9 +++++++--
> 9 files changed, 46 insertions(+), 9 deletions(-)
>
> diff --git a/hw/dataplane/hostmem.c b/hw/dataplane/hostmem.c
> index 380537e..41d43e7 100644
> --- a/hw/dataplane/hostmem.c
> +++ b/hw/dataplane/hostmem.c
> @@ -126,6 +126,7 @@ static void hostmem_listener_section_dummy(MemoryListener *listener,
>
> static void hostmem_listener_eventfd_dummy(MemoryListener *listener,
> MemoryRegionSection *section,
> + bool pv,
> bool match_data, uint64_t data,
> EventNotifier *e)
> {
> diff --git a/hw/ivshmem.c b/hw/ivshmem.c
> index 68a2cf2..28e5978 100644
> --- a/hw/ivshmem.c
> +++ b/hw/ivshmem.c
> @@ -352,6 +352,7 @@ static void ivshmem_add_eventfd(IVShmemState *s, int posn, int i)
> memory_region_add_eventfd(&s->ivshmem_mmio,
> DOORBELL,
> 4,
> + false,
> true,
> (posn << 16) | i,
> &s->peers[posn].eventfds[i]);
> @@ -362,6 +363,7 @@ static void ivshmem_del_eventfd(IVShmemState *s, int posn, int i)
> memory_region_del_eventfd(&s->ivshmem_mmio,
> DOORBELL,
> 4,
> + false,
> true,
> (posn << 16) | i,
> &s->peers[posn].eventfds[i]);
> diff --git a/hw/pci-testdev.c b/hw/pci-testdev.c
> index 9486624..f0ebf99 100644
> --- a/hw/pci-testdev.c
> +++ b/hw/pci-testdev.c
> @@ -80,6 +80,7 @@ static int pci_testdev_start(IOTest *test)
> memory_region_add_eventfd(test->mr,
> le32_to_cpu(test->hdr->offset),
> test->size,
> + false,
> test->match_data,
> test->hdr->data,
> &test->notifier);
> @@ -94,6 +95,7 @@ static void pci_testdev_stop(IOTest *test)
> memory_region_del_eventfd(test->mr,
> le32_to_cpu(test->hdr->offset),
> test->size,
> + false,
> test->match_data,
> test->hdr->data,
> &test->notifier);
> diff --git a/hw/vhost.c b/hw/vhost.c
> index 4d6aee3..9ad7101 100644
> --- a/hw/vhost.c
> +++ b/hw/vhost.c
> @@ -750,13 +750,13 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
> }
>
> static void vhost_eventfd_add(MemoryListener *listener,
> - MemoryRegionSection *section,
> + MemoryRegionSection *section, bool pv,
> bool match_data, uint64_t data, EventNotifier *e)
> {
> }
>
> static void vhost_eventfd_del(MemoryListener *listener,
> - MemoryRegionSection *section,
> + MemoryRegionSection *section, bool pv,
> bool match_data, uint64_t data, EventNotifier *e)
> {
> }
> diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
> index 19965e5..f9ff994 100644
> --- a/hw/virtio-pci.c
> +++ b/hw/virtio-pci.c
> @@ -189,10 +189,10 @@ static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
> }
> virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
> memory_region_add_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
> - true, n, notifier);
> + false, true, n, notifier);
> } else {
> memory_region_del_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
> - true, n, notifier);
> + false, true, n, notifier);
> virtio_queue_set_host_notifier_fd_handler(vq, false, false);
> event_notifier_cleanup(notifier);
> }
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 2322732..3612004 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -215,8 +215,10 @@ struct MemoryListener {
> void (*log_global_start)(MemoryListener *listener);
> void (*log_global_stop)(MemoryListener *listener);
> void (*eventfd_add)(MemoryListener *listener, MemoryRegionSection *section,
> + bool pv,
> bool match_data, uint64_t data, EventNotifier *e);
> void (*eventfd_del)(MemoryListener *listener, MemoryRegionSection *section,
> + bool pv,
> bool match_data, uint64_t data, EventNotifier *e);
> void (*coalesced_mmio_add)(MemoryListener *listener, MemoryRegionSection *section,
> hwaddr addr, hwaddr len);
> @@ -594,6 +596,9 @@ void memory_region_clear_flush_coalesced(MemoryRegion *mr);
> * @mr: the memory region being updated.
> * @addr: the address within @mr that is to be monitored
> * @size: the size of the access to trigger the eventfd
> + * @pv: set if Guest can promise us that all accesses touching this address
> + * are writes of specified length, starting at the specified address.
> + * If not - it's a Guest bug. Might give faster access.
> * @match_data: whether to match against @data, instead of just @addr
> * @data: the data to match against the guest write
> * @fd: the eventfd to be triggered when @addr, @size, and @data all match.
> @@ -601,6 +606,7 @@ void memory_region_clear_flush_coalesced(MemoryRegion *mr);
> void memory_region_add_eventfd(MemoryRegion *mr,
> hwaddr addr,
> unsigned size,
> + bool pv,
> bool match_data,
> uint64_t data,
> EventNotifier *e);
> @@ -614,6 +620,9 @@ void memory_region_add_eventfd(MemoryRegion *mr,
> * @mr: the memory region being updated.
> * @addr: the address within @mr that is to be monitored
> * @size: the size of the access to trigger the eventfd
> + * @pv: set if Guest can promise us that all accesses touching this address
> + * are writes of specified length, starting at the specified address.
> + * If not - it's a Guest bug. Might give faster access.
> * @match_data: whether to match against @data, instead of just @addr
> * @data: the data to match against the guest write
> * @fd: the eventfd to be triggered when @addr, @size, and @data all match.
> @@ -621,6 +630,7 @@ void memory_region_add_eventfd(MemoryRegion *mr,
> void memory_region_del_eventfd(MemoryRegion *mr,
> hwaddr addr,
> unsigned size,
> + bool pv,
> bool match_data,
> uint64_t data,
> EventNotifier *e);
> diff --git a/kvm-all.c b/kvm-all.c
> index ce823f9..59835ca 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -500,7 +500,7 @@ 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,
> +static int kvm_set_ioeventfd_mmio(int fd, uint32_t addr, uint32_t val, bool pv,
> bool assign, uint32_t size, bool datamatch)
> {
> int ret;
> @@ -518,6 +518,11 @@ static int kvm_set_ioeventfd_mmio(int fd, uint32_t addr, uint32_t val,
>
> if (datamatch) {
> iofd.flags |= KVM_IOEVENTFD_FLAG_DATAMATCH;
> + /* Kernel doesn't support data match with PV MMIO. */
> + pv = false;
> + }
> + if (pv) {
> + iofd.flags |= KVM_IOEVENTFD_FLAG_PV_MMIO;
> }
> if (!assign) {
> iofd.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
> @@ -802,6 +807,7 @@ static void kvm_log_global_stop(struct MemoryListener *listener)
>
> static void kvm_mem_ioeventfd_add(MemoryListener *listener,
> MemoryRegionSection *section,
> + bool pv,
> bool match_data, uint64_t data,
> EventNotifier *e)
> {
> @@ -809,7 +815,7 @@ static void kvm_mem_ioeventfd_add(MemoryListener *listener,
> int r;
>
> r = kvm_set_ioeventfd_mmio(fd, section->offset_within_address_space,
> - data, true, section->size, match_data);
> + data, pv, true, section->size, match_data);
> if (r < 0) {
> abort();
> }
> @@ -817,6 +823,7 @@ static void kvm_mem_ioeventfd_add(MemoryListener *listener,
>
> static void kvm_mem_ioeventfd_del(MemoryListener *listener,
> MemoryRegionSection *section,
> + bool pv,
> bool match_data, uint64_t data,
> EventNotifier *e)
> {
> @@ -824,7 +831,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, match_data);
> + data, pv, false, section->size, match_data);
> if (r < 0) {
> abort();
> }
> @@ -832,6 +839,7 @@ static void kvm_mem_ioeventfd_del(MemoryListener *listener,
>
> static void kvm_io_ioeventfd_add(MemoryListener *listener,
> MemoryRegionSection *section,
> + bool pv,
> bool match_data, uint64_t data,
> EventNotifier *e)
> {
> @@ -847,6 +855,7 @@ static void kvm_io_ioeventfd_add(MemoryListener *listener,
>
> static void kvm_io_ioeventfd_del(MemoryListener *listener,
> MemoryRegionSection *section,
> + bool pv,
> bool match_data, uint64_t data,
> EventNotifier *e)
>
> diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
> index caca979..871cc0a 100644
> --- a/linux-headers/linux/kvm.h
> +++ b/linux-headers/linux/kvm.h
> @@ -449,11 +449,19 @@ enum {
> kvm_ioeventfd_flag_nr_datamatch,
> kvm_ioeventfd_flag_nr_pio,
> kvm_ioeventfd_flag_nr_deassign,
> + kvm_ioeventfd_flag_nr_pv_mmio,
> kvm_ioeventfd_flag_nr_max,
> };
>
> #define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch)
> #define KVM_IOEVENTFD_FLAG_PIO (1 << kvm_ioeventfd_flag_nr_pio)
> +/*
> + * PV_MMIO - Guest can promise us that all accesses touching this address
> + * are writes of specified length, starting at the specified address.
> + * If not - it's a Guest bug.
> + * Can not be used together with either PIO or DATAMATCH.
> + */
> +#define KVM_IOEVENTFD_FLAG_PV_MMIO (1 << kvm_ioeventfd_flag_nr_pv_mmio)
> #define KVM_IOEVENTFD_FLAG_DEASSIGN (1 << kvm_ioeventfd_flag_nr_deassign)
>
> #define KVM_IOEVENTFD_VALID_FLAG_MASK ((1 << kvm_ioeventfd_flag_nr_max) - 1)
> diff --git a/memory.c b/memory.c
> index 92a2196..5a64b3c 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -162,6 +162,7 @@ struct CoalescedMemoryRange {
>
> struct MemoryRegionIoeventfd {
> AddrRange addr;
> + bool pv;
> bool match_data;
> uint64_t data;
> EventNotifier *e;
> @@ -600,7 +601,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
> .offset_within_address_space = int128_get64(fd->addr.start),
> .size = int128_get64(fd->addr.size),
> };
> - MEMORY_LISTENER_CALL(eventfd_del, Forward, §ion,
> + MEMORY_LISTENER_CALL(eventfd_del, Forward, §ion, fd->pv,
> fd->match_data, fd->data, fd->e);
> ++iold;
> } else if (inew < fds_new_nb
> @@ -613,7 +614,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
> .offset_within_address_space = int128_get64(fd->addr.start),
> .size = int128_get64(fd->addr.size),
> };
> - MEMORY_LISTENER_CALL(eventfd_add, Reverse, §ion,
> + MEMORY_LISTENER_CALL(eventfd_add, Reverse, §ion, fd->pv,
> fd->match_data, fd->data, fd->e);
> ++inew;
> } else {
> @@ -1243,6 +1244,7 @@ void memory_region_clear_flush_coalesced(MemoryRegion *mr)
> void memory_region_add_eventfd(MemoryRegion *mr,
> hwaddr addr,
> unsigned size,
> + bool pv,
> bool match_data,
> uint64_t data,
> EventNotifier *e)
> @@ -1250,6 +1252,7 @@ void memory_region_add_eventfd(MemoryRegion *mr,
> MemoryRegionIoeventfd mrfd = {
> .addr.start = int128_make64(addr),
> .addr.size = int128_make64(size),
> + .pv = pv,
> .match_data = match_data,
> .data = data,
> .e = e,
> @@ -1276,6 +1279,7 @@ void memory_region_add_eventfd(MemoryRegion *mr,
> void memory_region_del_eventfd(MemoryRegion *mr,
> hwaddr addr,
> unsigned size,
> + bool pv,
> bool match_data,
> uint64_t data,
> EventNotifier *e)
> @@ -1283,6 +1287,7 @@ void memory_region_del_eventfd(MemoryRegion *mr,
> MemoryRegionIoeventfd mrfd = {
> .addr.start = int128_make64(addr),
> .addr.size = int128_make64(size),
> + .pv = pv,
> .match_data = match_data,
> .data = data,
> .e = e,
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v2 5/6] kvm: add PV MMIO
2013-04-04 12:46 ` Paolo Bonzini
@ 2013-04-04 13:10 ` Michael S. Tsirkin
2013-04-04 14:56 ` Paolo Bonzini
0 siblings, 1 reply; 15+ messages in thread
From: Michael S. Tsirkin @ 2013-04-04 13:10 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: gleb, mtosatti, qemu-devel, kvm, Avi Kivity
On Thu, Apr 04, 2013 at 02:46:11PM +0200, Paolo Bonzini wrote:
> Il 04/04/2013 12:40, Michael S. Tsirkin ha scritto:
> > Add an option for users to specify PV eventfd
> > listeners, and utilize KVM's PV MMIO underneath.
> > Upodate all callers.
>
> I would like Avi to comment on this, because I think this is not the
> "memory-API approved" way of doing things. You need KVM to define its
> own AddressSpace, and make KVM's listener use
> memory_region_to_address_space to figure out if it is for PV MMIO.
>
> To handle accesses from TCG, the PV AddressSpace can simply have just an
> alias to the actual MemoryRegion where the doorbell is.
>
> Paolo
This is not really different from other eventfd flags like datamatch.
Separate address space is not appropriate here.
This is regular memory space, KVM eventfd simply has a flag that says
"guest is well behaved so please make eventfd go faster".
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > ---
> > hw/dataplane/hostmem.c | 1 +
> > hw/ivshmem.c | 2 ++
> > hw/pci-testdev.c | 2 ++
> > hw/vhost.c | 4 ++--
> > hw/virtio-pci.c | 4 ++--
> > include/exec/memory.h | 10 ++++++++++
> > kvm-all.c | 15 ++++++++++++---
> > linux-headers/linux/kvm.h | 8 ++++++++
> > memory.c | 9 +++++++--
> > 9 files changed, 46 insertions(+), 9 deletions(-)
> >
> > diff --git a/hw/dataplane/hostmem.c b/hw/dataplane/hostmem.c
> > index 380537e..41d43e7 100644
> > --- a/hw/dataplane/hostmem.c
> > +++ b/hw/dataplane/hostmem.c
> > @@ -126,6 +126,7 @@ static void hostmem_listener_section_dummy(MemoryListener *listener,
> >
> > static void hostmem_listener_eventfd_dummy(MemoryListener *listener,
> > MemoryRegionSection *section,
> > + bool pv,
> > bool match_data, uint64_t data,
> > EventNotifier *e)
> > {
> > diff --git a/hw/ivshmem.c b/hw/ivshmem.c
> > index 68a2cf2..28e5978 100644
> > --- a/hw/ivshmem.c
> > +++ b/hw/ivshmem.c
> > @@ -352,6 +352,7 @@ static void ivshmem_add_eventfd(IVShmemState *s, int posn, int i)
> > memory_region_add_eventfd(&s->ivshmem_mmio,
> > DOORBELL,
> > 4,
> > + false,
> > true,
> > (posn << 16) | i,
> > &s->peers[posn].eventfds[i]);
> > @@ -362,6 +363,7 @@ static void ivshmem_del_eventfd(IVShmemState *s, int posn, int i)
> > memory_region_del_eventfd(&s->ivshmem_mmio,
> > DOORBELL,
> > 4,
> > + false,
> > true,
> > (posn << 16) | i,
> > &s->peers[posn].eventfds[i]);
> > diff --git a/hw/pci-testdev.c b/hw/pci-testdev.c
> > index 9486624..f0ebf99 100644
> > --- a/hw/pci-testdev.c
> > +++ b/hw/pci-testdev.c
> > @@ -80,6 +80,7 @@ static int pci_testdev_start(IOTest *test)
> > memory_region_add_eventfd(test->mr,
> > le32_to_cpu(test->hdr->offset),
> > test->size,
> > + false,
> > test->match_data,
> > test->hdr->data,
> > &test->notifier);
> > @@ -94,6 +95,7 @@ static void pci_testdev_stop(IOTest *test)
> > memory_region_del_eventfd(test->mr,
> > le32_to_cpu(test->hdr->offset),
> > test->size,
> > + false,
> > test->match_data,
> > test->hdr->data,
> > &test->notifier);
> > diff --git a/hw/vhost.c b/hw/vhost.c
> > index 4d6aee3..9ad7101 100644
> > --- a/hw/vhost.c
> > +++ b/hw/vhost.c
> > @@ -750,13 +750,13 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
> > }
> >
> > static void vhost_eventfd_add(MemoryListener *listener,
> > - MemoryRegionSection *section,
> > + MemoryRegionSection *section, bool pv,
> > bool match_data, uint64_t data, EventNotifier *e)
> > {
> > }
> >
> > static void vhost_eventfd_del(MemoryListener *listener,
> > - MemoryRegionSection *section,
> > + MemoryRegionSection *section, bool pv,
> > bool match_data, uint64_t data, EventNotifier *e)
> > {
> > }
> > diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
> > index 19965e5..f9ff994 100644
> > --- a/hw/virtio-pci.c
> > +++ b/hw/virtio-pci.c
> > @@ -189,10 +189,10 @@ static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
> > }
> > virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
> > memory_region_add_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
> > - true, n, notifier);
> > + false, true, n, notifier);
> > } else {
> > memory_region_del_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
> > - true, n, notifier);
> > + false, true, n, notifier);
> > virtio_queue_set_host_notifier_fd_handler(vq, false, false);
> > event_notifier_cleanup(notifier);
> > }
> > diff --git a/include/exec/memory.h b/include/exec/memory.h
> > index 2322732..3612004 100644
> > --- a/include/exec/memory.h
> > +++ b/include/exec/memory.h
> > @@ -215,8 +215,10 @@ struct MemoryListener {
> > void (*log_global_start)(MemoryListener *listener);
> > void (*log_global_stop)(MemoryListener *listener);
> > void (*eventfd_add)(MemoryListener *listener, MemoryRegionSection *section,
> > + bool pv,
> > bool match_data, uint64_t data, EventNotifier *e);
> > void (*eventfd_del)(MemoryListener *listener, MemoryRegionSection *section,
> > + bool pv,
> > bool match_data, uint64_t data, EventNotifier *e);
> > void (*coalesced_mmio_add)(MemoryListener *listener, MemoryRegionSection *section,
> > hwaddr addr, hwaddr len);
> > @@ -594,6 +596,9 @@ void memory_region_clear_flush_coalesced(MemoryRegion *mr);
> > * @mr: the memory region being updated.
> > * @addr: the address within @mr that is to be monitored
> > * @size: the size of the access to trigger the eventfd
> > + * @pv: set if Guest can promise us that all accesses touching this address
> > + * are writes of specified length, starting at the specified address.
> > + * If not - it's a Guest bug. Might give faster access.
> > * @match_data: whether to match against @data, instead of just @addr
> > * @data: the data to match against the guest write
> > * @fd: the eventfd to be triggered when @addr, @size, and @data all match.
> > @@ -601,6 +606,7 @@ void memory_region_clear_flush_coalesced(MemoryRegion *mr);
> > void memory_region_add_eventfd(MemoryRegion *mr,
> > hwaddr addr,
> > unsigned size,
> > + bool pv,
> > bool match_data,
> > uint64_t data,
> > EventNotifier *e);
> > @@ -614,6 +620,9 @@ void memory_region_add_eventfd(MemoryRegion *mr,
> > * @mr: the memory region being updated.
> > * @addr: the address within @mr that is to be monitored
> > * @size: the size of the access to trigger the eventfd
> > + * @pv: set if Guest can promise us that all accesses touching this address
> > + * are writes of specified length, starting at the specified address.
> > + * If not - it's a Guest bug. Might give faster access.
> > * @match_data: whether to match against @data, instead of just @addr
> > * @data: the data to match against the guest write
> > * @fd: the eventfd to be triggered when @addr, @size, and @data all match.
> > @@ -621,6 +630,7 @@ void memory_region_add_eventfd(MemoryRegion *mr,
> > void memory_region_del_eventfd(MemoryRegion *mr,
> > hwaddr addr,
> > unsigned size,
> > + bool pv,
> > bool match_data,
> > uint64_t data,
> > EventNotifier *e);
> > diff --git a/kvm-all.c b/kvm-all.c
> > index ce823f9..59835ca 100644
> > --- a/kvm-all.c
> > +++ b/kvm-all.c
> > @@ -500,7 +500,7 @@ 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,
> > +static int kvm_set_ioeventfd_mmio(int fd, uint32_t addr, uint32_t val, bool pv,
> > bool assign, uint32_t size, bool datamatch)
> > {
> > int ret;
> > @@ -518,6 +518,11 @@ static int kvm_set_ioeventfd_mmio(int fd, uint32_t addr, uint32_t val,
> >
> > if (datamatch) {
> > iofd.flags |= KVM_IOEVENTFD_FLAG_DATAMATCH;
> > + /* Kernel doesn't support data match with PV MMIO. */
> > + pv = false;
> > + }
> > + if (pv) {
> > + iofd.flags |= KVM_IOEVENTFD_FLAG_PV_MMIO;
> > }
> > if (!assign) {
> > iofd.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
> > @@ -802,6 +807,7 @@ static void kvm_log_global_stop(struct MemoryListener *listener)
> >
> > static void kvm_mem_ioeventfd_add(MemoryListener *listener,
> > MemoryRegionSection *section,
> > + bool pv,
> > bool match_data, uint64_t data,
> > EventNotifier *e)
> > {
> > @@ -809,7 +815,7 @@ static void kvm_mem_ioeventfd_add(MemoryListener *listener,
> > int r;
> >
> > r = kvm_set_ioeventfd_mmio(fd, section->offset_within_address_space,
> > - data, true, section->size, match_data);
> > + data, pv, true, section->size, match_data);
> > if (r < 0) {
> > abort();
> > }
> > @@ -817,6 +823,7 @@ static void kvm_mem_ioeventfd_add(MemoryListener *listener,
> >
> > static void kvm_mem_ioeventfd_del(MemoryListener *listener,
> > MemoryRegionSection *section,
> > + bool pv,
> > bool match_data, uint64_t data,
> > EventNotifier *e)
> > {
> > @@ -824,7 +831,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, match_data);
> > + data, pv, false, section->size, match_data);
> > if (r < 0) {
> > abort();
> > }
> > @@ -832,6 +839,7 @@ static void kvm_mem_ioeventfd_del(MemoryListener *listener,
> >
> > static void kvm_io_ioeventfd_add(MemoryListener *listener,
> > MemoryRegionSection *section,
> > + bool pv,
> > bool match_data, uint64_t data,
> > EventNotifier *e)
> > {
> > @@ -847,6 +855,7 @@ static void kvm_io_ioeventfd_add(MemoryListener *listener,
> >
> > static void kvm_io_ioeventfd_del(MemoryListener *listener,
> > MemoryRegionSection *section,
> > + bool pv,
> > bool match_data, uint64_t data,
> > EventNotifier *e)
> >
> > diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
> > index caca979..871cc0a 100644
> > --- a/linux-headers/linux/kvm.h
> > +++ b/linux-headers/linux/kvm.h
> > @@ -449,11 +449,19 @@ enum {
> > kvm_ioeventfd_flag_nr_datamatch,
> > kvm_ioeventfd_flag_nr_pio,
> > kvm_ioeventfd_flag_nr_deassign,
> > + kvm_ioeventfd_flag_nr_pv_mmio,
> > kvm_ioeventfd_flag_nr_max,
> > };
> >
> > #define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch)
> > #define KVM_IOEVENTFD_FLAG_PIO (1 << kvm_ioeventfd_flag_nr_pio)
> > +/*
> > + * PV_MMIO - Guest can promise us that all accesses touching this address
> > + * are writes of specified length, starting at the specified address.
> > + * If not - it's a Guest bug.
> > + * Can not be used together with either PIO or DATAMATCH.
> > + */
> > +#define KVM_IOEVENTFD_FLAG_PV_MMIO (1 << kvm_ioeventfd_flag_nr_pv_mmio)
> > #define KVM_IOEVENTFD_FLAG_DEASSIGN (1 << kvm_ioeventfd_flag_nr_deassign)
> >
> > #define KVM_IOEVENTFD_VALID_FLAG_MASK ((1 << kvm_ioeventfd_flag_nr_max) - 1)
> > diff --git a/memory.c b/memory.c
> > index 92a2196..5a64b3c 100644
> > --- a/memory.c
> > +++ b/memory.c
> > @@ -162,6 +162,7 @@ struct CoalescedMemoryRange {
> >
> > struct MemoryRegionIoeventfd {
> > AddrRange addr;
> > + bool pv;
> > bool match_data;
> > uint64_t data;
> > EventNotifier *e;
> > @@ -600,7 +601,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
> > .offset_within_address_space = int128_get64(fd->addr.start),
> > .size = int128_get64(fd->addr.size),
> > };
> > - MEMORY_LISTENER_CALL(eventfd_del, Forward, §ion,
> > + MEMORY_LISTENER_CALL(eventfd_del, Forward, §ion, fd->pv,
> > fd->match_data, fd->data, fd->e);
> > ++iold;
> > } else if (inew < fds_new_nb
> > @@ -613,7 +614,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
> > .offset_within_address_space = int128_get64(fd->addr.start),
> > .size = int128_get64(fd->addr.size),
> > };
> > - MEMORY_LISTENER_CALL(eventfd_add, Reverse, §ion,
> > + MEMORY_LISTENER_CALL(eventfd_add, Reverse, §ion, fd->pv,
> > fd->match_data, fd->data, fd->e);
> > ++inew;
> > } else {
> > @@ -1243,6 +1244,7 @@ void memory_region_clear_flush_coalesced(MemoryRegion *mr)
> > void memory_region_add_eventfd(MemoryRegion *mr,
> > hwaddr addr,
> > unsigned size,
> > + bool pv,
> > bool match_data,
> > uint64_t data,
> > EventNotifier *e)
> > @@ -1250,6 +1252,7 @@ void memory_region_add_eventfd(MemoryRegion *mr,
> > MemoryRegionIoeventfd mrfd = {
> > .addr.start = int128_make64(addr),
> > .addr.size = int128_make64(size),
> > + .pv = pv,
> > .match_data = match_data,
> > .data = data,
> > .e = e,
> > @@ -1276,6 +1279,7 @@ void memory_region_add_eventfd(MemoryRegion *mr,
> > void memory_region_del_eventfd(MemoryRegion *mr,
> > hwaddr addr,
> > unsigned size,
> > + bool pv,
> > bool match_data,
> > uint64_t data,
> > EventNotifier *e)
> > @@ -1283,6 +1287,7 @@ void memory_region_del_eventfd(MemoryRegion *mr,
> > MemoryRegionIoeventfd mrfd = {
> > .addr.start = int128_make64(addr),
> > .addr.size = int128_make64(size),
> > + .pv = pv,
> > .match_data = match_data,
> > .data = data,
> > .e = e,
> >
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v2 5/6] kvm: add PV MMIO
2013-04-04 13:10 ` Michael S. Tsirkin
@ 2013-04-04 14:56 ` Paolo Bonzini
2013-04-04 14:38 ` Michael S. Tsirkin
0 siblings, 1 reply; 15+ messages in thread
From: Paolo Bonzini @ 2013-04-04 14:56 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: gleb, mtosatti, qemu-devel, kvm, Avi Kivity
Il 04/04/2013 15:10, Michael S. Tsirkin ha scritto:
> > I would like Avi to comment on this, because I think this is not the
> > "memory-API approved" way of doing things. You need KVM to define its
> > own AddressSpace, and make KVM's listener use
> > memory_region_to_address_space to figure out if it is for PV MMIO.
> >
> > To handle accesses from TCG, the PV AddressSpace can simply have just an
> > alias to the actual MemoryRegion where the doorbell is.
>
> This is not really different from other eventfd flags like datamatch.
> Separate address space is not appropriate here.
> This is regular memory space, KVM eventfd simply has a flag that says
> "guest is well behaved so please make eventfd go faster".
Having a separate address space would match what you do in the kernel
though.
I just don't like functions with a dozen arguments... Can you just make
datamatch and pv a single flags argument, as is the case with the KVM API?
Paolo
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v2 5/6] kvm: add PV MMIO
2013-04-04 14:56 ` Paolo Bonzini
@ 2013-04-04 14:38 ` Michael S. Tsirkin
0 siblings, 0 replies; 15+ messages in thread
From: Michael S. Tsirkin @ 2013-04-04 14:38 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: gleb, mtosatti, qemu-devel, kvm, Avi Kivity
On Thu, Apr 04, 2013 at 04:56:11PM +0200, Paolo Bonzini wrote:
> Il 04/04/2013 15:10, Michael S. Tsirkin ha scritto:
> > > I would like Avi to comment on this, because I think this is not the
> > > "memory-API approved" way of doing things. You need KVM to define its
> > > own AddressSpace, and make KVM's listener use
> > > memory_region_to_address_space to figure out if it is for PV MMIO.
> > >
> > > To handle accesses from TCG, the PV AddressSpace can simply have just an
> > > alias to the actual MemoryRegion where the doorbell is.
> >
> > This is not really different from other eventfd flags like datamatch.
> > Separate address space is not appropriate here.
> > This is regular memory space, KVM eventfd simply has a flag that says
> > "guest is well behaved so please make eventfd go faster".
>
> Having a separate address space would match what you do in the kernel
> though.
Not really, in kernel the device is as usual on the MMIO
bus. The pv_mmio_bus is an extra datastructure to enable lookups where
length is not known in an efficient way. Userspace does not need to know
about these details.
> I just don't like functions with a dozen arguments... Can you just make
> datamatch and pv a single flags argument, as is the case with the KVM API?
>
> Paolo
Extra parameters are detected by compiler :)
I don't really care, anyone else objects to changing
datamatch to a flags argument?
Please let me know to avoid changing it back and forth.
--
MST
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v2 5/6] kvm: add PV MMIO
2013-04-04 10:40 ` [Qemu-devel] [PATCH v2 5/6] kvm: add PV MMIO Michael S. Tsirkin
2013-04-04 12:46 ` Paolo Bonzini
@ 2013-04-04 12:50 ` Peter Maydell
2013-04-04 13:11 ` Michael S. Tsirkin
1 sibling, 1 reply; 15+ messages in thread
From: Peter Maydell @ 2013-04-04 12:50 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: pbonzini, gleb, mtosatti, qemu-devel, kvm
On 4 April 2013 11:40, Michael S. Tsirkin <mst@redhat.com> wrote:
> Add an option for users to specify PV eventfd
> listeners, and utilize KVM's PV MMIO underneath.
> Upodate all callers.
>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
> hw/dataplane/hostmem.c | 1 +
> hw/ivshmem.c | 2 ++
> hw/pci-testdev.c | 2 ++
> hw/vhost.c | 4 ++--
> hw/virtio-pci.c | 4 ++--
> include/exec/memory.h | 10 ++++++++++
> kvm-all.c | 15 ++++++++++++---
> linux-headers/linux/kvm.h | 8 ++++++++
> memory.c | 9 +++++++--
Can we keep linux-headers updates in separate patches, please
(with commit messages saying what kernel commit/version the
sync is with)?
thanks
-- PMM
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v2 5/6] kvm: add PV MMIO
2013-04-04 12:50 ` Peter Maydell
@ 2013-04-04 13:11 ` Michael S. Tsirkin
2013-04-04 14:23 ` Peter Maydell
0 siblings, 1 reply; 15+ messages in thread
From: Michael S. Tsirkin @ 2013-04-04 13:11 UTC (permalink / raw)
To: Peter Maydell; +Cc: pbonzini, gleb, mtosatti, qemu-devel, kvm
On Thu, Apr 04, 2013 at 01:50:36PM +0100, Peter Maydell wrote:
> On 4 April 2013 11:40, Michael S. Tsirkin <mst@redhat.com> wrote:
> > Add an option for users to specify PV eventfd
> > listeners, and utilize KVM's PV MMIO underneath.
> > Upodate all callers.
> >
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > ---
> > hw/dataplane/hostmem.c | 1 +
> > hw/ivshmem.c | 2 ++
> > hw/pci-testdev.c | 2 ++
> > hw/vhost.c | 4 ++--
> > hw/virtio-pci.c | 4 ++--
> > include/exec/memory.h | 10 ++++++++++
> > kvm-all.c | 15 ++++++++++++---
> > linux-headers/linux/kvm.h | 8 ++++++++
> > memory.c | 9 +++++++--
>
> Can we keep linux-headers updates in separate patches, please
> (with commit messages saying what kernel commit/version the
> sync is with)?
>
> thanks
> -- PMM
OK, first it needs to get into linux though :).
--
MST
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v2 5/6] kvm: add PV MMIO
2013-04-04 13:11 ` Michael S. Tsirkin
@ 2013-04-04 14:23 ` Peter Maydell
2013-04-04 13:34 ` Michael S. Tsirkin
0 siblings, 1 reply; 15+ messages in thread
From: Peter Maydell @ 2013-04-04 14:23 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: pbonzini, gleb, mtosatti, qemu-devel, kvm
On 4 April 2013 14:11, Michael S. Tsirkin <mst@redhat.com> wrote:
> On Thu, Apr 04, 2013 at 01:50:36PM +0100, Peter Maydell wrote:
>> Can we keep linux-headers updates in separate patches, please
>> (with commit messages saying what kernel commit/version the
>> sync is with)?
> OK, first it needs to get into linux though :).
In that case you need an RFC tag on your patches :-)
-- PMM
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v2 5/6] kvm: add PV MMIO
2013-04-04 14:23 ` Peter Maydell
@ 2013-04-04 13:34 ` Michael S. Tsirkin
0 siblings, 0 replies; 15+ messages in thread
From: Michael S. Tsirkin @ 2013-04-04 13:34 UTC (permalink / raw)
To: Peter Maydell; +Cc: pbonzini, gleb, mtosatti, qemu-devel, kvm
On Thu, Apr 04, 2013 at 03:23:43PM +0100, Peter Maydell wrote:
> On 4 April 2013 14:11, Michael S. Tsirkin <mst@redhat.com> wrote:
> > On Thu, Apr 04, 2013 at 01:50:36PM +0100, Peter Maydell wrote:
> >> Can we keep linux-headers updates in separate patches, please
> >> (with commit messages saying what kernel commit/version the
> >> sync is with)?
>
> > OK, first it needs to get into linux though :).
>
> In that case you need an RFC tag on your patches :-)
>
> -- PMM
The cover letter said patches 5 and 6 are RFC,
but patches 1-4 are ready and should go in I think.
--
MST
^ permalink raw reply [flat|nested] 15+ messages in thread