[kvm-unit-tests PATCH 7/7] s390x: virtio data transfer

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



We use a test device, "PONG" to transfer chunks of data of different
size and alignment and compare a checksum calculated before the sending
with the VIRTIO device checksum response.

Signed-off-by: Pierre Morel <pmorel@xxxxxxxxxxxxx>
---
 s390x/virtio_pong.c | 107 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/s390x/virtio_pong.c b/s390x/virtio_pong.c
index 1e050a4d..94d6acdc 100644
--- a/s390x/virtio_pong.c
+++ b/s390x/virtio_pong.c
@@ -39,6 +39,112 @@ static struct virtio_ccw_device *vcdev;
 static struct virtqueue *out_vq;
 static struct virtqueue *in_vq;
 
+static bool virtio_read(struct virtqueue *q, char **buf, unsigned int *len)
+{
+	int ret;
+	char *p;
+
+	ret = virtqueue_add_inbuf(q, *buf, *len);
+	if (ret < 0)
+		return false;
+
+	disable_io_irq();
+	virtqueue_kick(q);
+	wait_for_interrupt(PSW_MASK_IO);
+
+	do {
+		p = virtqueue_get_buf(q, len);
+	} while (!p);
+
+	*buf = (void *)p;
+
+	return true;
+}
+
+static bool virtio_write(struct virtqueue *q, char *buf, unsigned int len)
+{
+	int ret;
+
+	ret = virtqueue_add_outbuf(q, buf, len);
+	if (ret < 0)
+		return false;
+
+	virtqueue_kick(q);
+	while (!virtqueue_get_buf(q, &len))
+		;
+
+	return true;
+}
+
+static unsigned int simple_checksum(char *buf, unsigned int len)
+{
+	unsigned int sum = 0;
+
+	while (len--) {
+		sum += *buf * *buf + 7 * *buf + 3;
+		buf++;
+	}
+
+	return sum;
+}
+
+static void pong_write(char *buf, unsigned int len)
+{
+	unsigned int cksum;
+	unsigned int cksum_ret;
+	char *ret_ptr = (char *)&cksum_ret;
+
+	cksum = simple_checksum(buf, len);
+	report(virtio_write(out_vq, buf, len), "Sending data: %08x", cksum);
+
+	len = sizeof(cksum_ret);
+	report(virtio_read(in_vq, &ret_ptr, &len),
+	       "Receiving checksum: %08x", cksum_ret);
+
+	report(cksum == cksum_ret, "Verifying checksum");
+}
+
+static struct {
+	const char *name;
+	int size;
+	int offset;
+} chunks[] = {
+	{ "Small buffer", 3, 0 },
+	{ "Page aligned", 4096, 0 },
+	{ "Large page aligned", 0x00100000, 0 },
+	{ "Page unaligned", 4096, 0x107 },
+	{ "Random data", 5119, 0x107 },
+	{ NULL, 0, 0 }
+};
+
+static void test_pong_data(void)
+{
+	char *buf;
+	char *p;
+	int len;
+	int i;
+
+	if (vcdev->state != VCDEV_INIT) {
+		report_skip("Device non initialized");
+		return;
+	}
+
+	for (i = 0; chunks[i].name; i++) {
+		report_prefix_push(chunks[i].name);
+
+		len = chunks[i].size + chunks[i].offset;
+		buf = alloc_io_mem(len, 0);
+
+		p = buf + chunks[i].offset;
+		memset(p, 0xA5, chunks[i].size);
+		pong_write(p, chunks[i].size);
+
+		free_io_mem(buf, len);
+
+		report_prefix_pop();
+	}
+}
+
 static void test_find_vqs(void)
 {
 	struct virtio_device *vdev = &vcdev->vdev;
@@ -186,6 +292,7 @@ static struct {
 	{ "CCW Bus", test_virtio_ccw_bus },
 	{ "CCW Device", test_virtio_device_init },
 	{ "Queues setup", test_find_vqs },
+	{ "Data transfer", test_pong_data },
 	{ NULL, NULL }
 };
 
-- 
2.25.1




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux