Re: [kvm-unit-tests PATCH v6 11/12] pci: Add pci-testdev PCI bus test device

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

 



On Fri, Jul 29, 2016 at 02:01:05PM +0200, Alexander Gordeev wrote:
> Cc: Thomas Huth <thuth@xxxxxxxxxx>
> Cc: Andrew Jones <drjones@xxxxxxxxxx>
> Signed-off-by: Alexander Gordeev <agordeev@xxxxxxxxxx>
> ---
>  lib/pci-testdev.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/pci.h         |   7 ++
>  2 files changed, 199 insertions(+)
>  create mode 100644 lib/pci-testdev.c

Reviewed-by: Andrew Jones <drjones@xxxxxxxxxx>

Also a series-wide comment below though.

> 
> diff --git a/lib/pci-testdev.c b/lib/pci-testdev.c
> new file mode 100644
> index 000000000000..ad482d3291c7
> --- /dev/null
> +++ b/lib/pci-testdev.c
> @@ -0,0 +1,192 @@
> +/*
> + * QEMU "pci-testdev" PCI test device
> + *
> + * Copyright (C) 2016, Red Hat Inc, Alexander Gordeev <agordeev@xxxxxxxxxx>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#include "pci.h"
> +#include "asm/io.h"
> +
> +struct pci_testdev_ops {
> +	u8 (*io_readb)(const volatile void *addr);
> +	u16 (*io_readw)(const volatile void *addr);
> +	u32 (*io_readl)(const volatile void *addr);
> +	void (*io_writeb)(u8 value, volatile void *addr);
> +	void (*io_writew)(u16 value, volatile void *addr);
> +	void (*io_writel)(u32 value, volatile void *addr);
> +};
> +
> +static u8 pio_readb(const volatile void *addr)
> +{
> +	return inb((unsigned long)addr);
> +}
> +
> +static u16 pio_readw(const volatile void *addr)
> +{
> +	return inw((unsigned long)addr);
> +}
> +
> +static u32 pio_readl(const volatile void *addr)
> +{
> +	return inl((unsigned long)addr);
> +}
> +
> +static void pio_writeb(u8 value, volatile void *addr)
> +{
> +	outb(value, (unsigned long)addr);
> +}
> +
> +static void pio_writew(u16 value, volatile void *addr)
> +{
> +	outw(value, (unsigned long)addr);
> +}
> +
> +static void pio_writel(u32 value, volatile void *addr)
> +{
> +	outl(value, (unsigned long)addr);
> +}
> +
> +static struct pci_testdev_ops pci_testdev_io_ops = {
> +	.io_readb	= pio_readb,
> +	.io_readw	= pio_readw,
> +	.io_readl	= pio_readl,
> +	.io_writeb	= pio_writeb,
> +	.io_writew	= pio_writew,
> +	.io_writel	= pio_writel
> +};
> +
> +static u8 mmio_readb(const volatile void *addr)
> +{
> +	return *(const volatile u8 __force *)addr;
> +}
> +
> +static u16 mmio_readw(const volatile void *addr)
> +{
> +	return *(const volatile u16 __force *)addr;
> +}
> +
> +static u32 mmio_readl(const volatile void *addr)
> +{
> +	return *(const volatile u32 __force *)addr;
> +}
> +
> +static void mmio_writeb(u8 value, volatile void *addr)
> +{
> +	*(volatile u8 __force *)addr = value;
> +}
> +
> +static void mmio_writew(u16 value, volatile void *addr)
> +{
> +	*(volatile u16 __force *)addr = value;
> +}
> +
> +static void mmio_writel(u32 value, volatile void *addr)
> +{
> +	*(volatile u32 __force *)addr = value;
> +}
> +
> +static struct pci_testdev_ops pci_testdev_mem_ops = {
> +	.io_readb	= mmio_readb,
> +	.io_readw	= mmio_readw,
> +	.io_readl	= mmio_readl,
> +	.io_writeb	= mmio_writeb,
> +	.io_writew	= mmio_writew,
> +	.io_writel	= mmio_writel
> +};
> +
> +static bool pci_testdev_one(struct pci_test_dev_hdr *test,
> +			    int test_nr,
> +			    struct pci_testdev_ops *ops)
> +{
> +	u8 width;
> +	u32 count, sig, off;
> +	const int nr_writes = 16;
> +	int i;
> +
> +	ops->io_writeb(test_nr, &test->test);
> +	count = ops->io_readl(&test->count);
> +	if (count != 0)
> +		return false;
> +
> +	width = ops->io_readb(&test->width);
> +	if (width != 1 && width != 2 && width != 4)
> +		return false;
> +
> +	sig = ops->io_readl(&test->data);
> +	off = ops->io_readl(&test->offset);
> +
> +	for (i = 0; i < nr_writes; i++) {
> +		switch (width) {
> +		case 1: ops->io_writeb(sig, (void *)test + off); break;
> +		case 2: ops->io_writew(sig, (void *)test + off); break;
> +		case 4: ops->io_writel(sig, (void *)test + off); break;
> +		}
> +	}
> +
> +	count = ops->io_readl(&test->count);
> +	if (!count)
> +		return true;
> +
> +	return (int)count == nr_writes;
> +}
> +
> +void pci_testdev_print(struct pci_test_dev_hdr *test,
> +		       struct pci_testdev_ops *ops)
> +{
> +	bool io = (ops == &pci_testdev_io_ops);
> +	int i;
> +
> +	printf("pci-testdev %3s: ", io ? "io" : "mem");
> +	for (i = 0;; ++i) {
> +		char c = ops->io_readb(&test->name[i]);
> +		if (!c)
> +			break;
> +		printf("%c", c);
> +	}
> +	printf("\n");
> +}
> +
> +static int pci_testdev_all(struct pci_test_dev_hdr *test,
> +			   struct pci_testdev_ops *ops)
> +{
> +	int i;
> +
> +	for (i = 0;; i++) {
> +		if (!pci_testdev_one(test, i, ops))
> +			break;
> +		pci_testdev_print(test, ops);
> +	}
> +
> +	return i;
> +}
> +
> +int pci_testdev(void)
> +{
> +	phys_addr_t addr;
> +	void __iomem *mem, *io;
> +	pcidevaddr_t dev;
> +	int nr_tests = 0;
> +	bool ret;
> +
> +	dev = pci_find_dev(PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_TEST);
> +	if (dev == PCIDEVADDR_INVALID) {
> +		printf("'pci-testdev' device is not found, "
> +		       "check QEMU '-device pci-testdev' parameter\n");
> +		return -1;
> +	}
> +
> +	ret = pci_bar_is_valid(dev, 0) && pci_bar_is_valid(dev, 1);
> +	assert(ret);
> +
> +	addr = pci_bar_get_addr(dev, 0);
> +	mem = ioremap(addr, PAGE_SIZE);
> +
> +	addr = pci_bar_get_addr(dev, 1);
> +	io = (void *)(unsigned long)addr;
> +
> +	nr_tests += pci_testdev_all(mem, &pci_testdev_mem_ops);
> +	nr_tests += pci_testdev_all(io, &pci_testdev_io_ops);
> +
> +	return nr_tests;
> +}
> diff --git a/lib/pci.h b/lib/pci.h
> index d0585a0451c2..a0187fed96b0 100644
> --- a/lib/pci.h
> +++ b/lib/pci.h
> @@ -41,6 +41,8 @@ bool pci_bar_is64(pcidevaddr_t dev, int bar_num);
>  bool pci_bar_is_memory(pcidevaddr_t dev, int bar_num);
>  bool pci_bar_is_valid(pcidevaddr_t dev, int bar_num);

I just noticed that lib/pci.h function declarations are missing 'extern'.
It's sort of annoying that we have extern everywhere, but we do, and I
prefer consistency. Can you please fix that with a cleanup patch and
make sure all new function declarations added with this series also
have extern?

Thanks,
drew

>  
> +int pci_testdev(void);
> +
>  /*
>   * pci-testdev is a driver for the pci-testdev qemu pci device. The
>   * device enables testing mmio and portio exits, and measuring their
> @@ -49,7 +51,12 @@ bool pci_bar_is_valid(pcidevaddr_t dev, int bar_num);
>  #define PCI_VENDOR_ID_REDHAT		0x1b36
>  #define PCI_DEVICE_ID_REDHAT_TEST	0x0005
>  
> +/*
> + * pci-testdev supports at least three types of tests (via mmio and
> + * portio BARs): no-eventfd, wildcard-eventfd and datamatch-eventfd
> + */
>  #define PCI_TESTDEV_NUM_BARS		2
> +#define PCI_TESTDEV_NUM_TESTS		3
>  
>  struct pci_test_dev_hdr {
>  	uint8_t  test;
> -- 
> 1.8.3.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[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