Re: [PATCH kvm-unit-tests v6 11/14] pci: edu: introduce pci-edu helpers

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

 



On Wed, Nov 23, 2016 at 06:57:31PM +0800, Peter Xu wrote:
> QEMU edu device is a pci device that is originally written for
> educational purpose, however it also suits for IOMMU unit test. Adding
> helpers for this specific device to implement the device logic.
> 
> The device supports lots of functions, here only DMA operation is
> supported.
> 
> The spec of the device can be found at:
> 
>   https://github.com/qemu/qemu/blob/master/docs/specs/edu.txt
> 
> Reviewed-by: Andrew Jones <drjones@xxxxxxxxxx>
> Signed-off-by: Peter Xu <peterx@xxxxxxxxxx>
> ---
>  lib/pci-edu.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/pci-edu.h | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 155 insertions(+)
>  create mode 100644 lib/pci-edu.c
>  create mode 100644 lib/pci-edu.h
> 
> diff --git a/lib/pci-edu.c b/lib/pci-edu.c
> new file mode 100644
> index 0000000..c9a8b0c
> --- /dev/null
> +++ b/lib/pci-edu.c
> @@ -0,0 +1,73 @@
> +/*
> + * Edu PCI device.
> + *
> + * Copyright (C) 2016 Red Hat, Inc.
> + *
> + * Authors:
> + *   Peter Xu <peterx@xxxxxxxxxx>,
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2 or
> + * later.
> + */
> +
> +#include "pci-edu.h"
> +#include "asm/barrier.h"
> +
> +/* Return true if alive */
> +static inline bool edu_check_alive(struct pci_edu_dev *dev)
> +{
> +	static uint32_t live_count = 1;
> +	uint32_t value;
> +
> +	edu_reg_writel(dev, EDU_REG_ALIVE, live_count++);
> +	value = edu_reg_readl(dev, EDU_REG_ALIVE);
> +	return (live_count - 1 == ~value);
> +}
> +
> +bool edu_init(struct pci_edu_dev *dev)
> +{
> +	pcidevaddr_t dev_addr;
> +
> +	dev_addr = pci_find_dev(PCI_VENDOR_ID_QEMU, PCI_DEVICE_ID_EDU);
> +	if (dev_addr == PCIDEVADDR_INVALID)
> +		return false;
> +
> +	pci_dev_init(&dev->pci_dev, dev_addr);
> +	pci_enable_defaults(&dev->pci_dev);
> +	assert(edu_check_alive(dev));
> +	return true;
> +}
> +
> +void edu_dma(struct pci_edu_dev *dev, iova_t iova,
> +	     size_t size, int dev_offset, bool from_device)
> +{
> +	uint64_t from, to;
> +	uint32_t cmd = EDU_CMD_DMA_START;
> +
> +	assert(size <= EDU_DMA_SIZE_MAX);
> +	assert(dev_offset < EDU_DMA_SIZE_MAX &&
> +	       dev_offset >= 0);
> +
> +	printf("edu device DMA start %s addr %p size 0x%lu off 0x%x\n",
> +	       from_device ? "FROM" : "TO",
> +	       (void *)iova, size, dev_offset);
> +
> +	if (from_device) {
> +		from = dev_offset + EDU_DMA_START;
> +		to = iova;
> +		cmd |= EDU_CMD_DMA_FROM;
> +	} else {
> +		from = iova;
> +		to = EDU_DMA_START + dev_offset;
> +		cmd |= EDU_CMD_DMA_TO;
> +	}
> +
> +	edu_reg_writeq(dev, EDU_REG_DMA_SRC, from);
> +	edu_reg_writeq(dev, EDU_REG_DMA_DST, to);
> +	edu_reg_writeq(dev, EDU_REG_DMA_COUNT, size);
> +	edu_reg_writel(dev, EDU_REG_DMA_CMD, cmd);
> +
> +	/* Wait until DMA finished */
> +	while (edu_reg_readl(dev, EDU_REG_DMA_CMD) & EDU_CMD_DMA_START)
> +		cpu_relax();
> +}
> diff --git a/lib/pci-edu.h b/lib/pci-edu.h
> new file mode 100644
> index 0000000..5d896c9
> --- /dev/null
> +++ b/lib/pci-edu.h
> @@ -0,0 +1,82 @@
> +/*
> + * Edu PCI device header.
> + *
> + * Copyright (C) 2016 Red Hat, Inc.
> + *
> + * Authors:
> + *   Peter Xu <peterx@xxxxxxxxxx>,
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2 or
> + * later.
> + *
> + * Edu device is a virtualized device in QEMU. Please refer to
> + * docs/specs/edu.txt in QEMU repository for EDU device manual.
> + */
> +#ifndef __PCI_EDU_H__
> +#define __PCI_EDU_H__
> +
> +#include "pci.h"
> +#include "asm/io.h"
> +
> +#define  PCI_VENDOR_ID_QEMU              0x1234
> +#define  PCI_DEVICE_ID_EDU               0x11e8
> +
> +/* The only bar used by EDU device */
> +#define EDU_BAR                     0
> +#define EDU_MAGIC                   0xed
> +#define EDU_VERSION                 0x100
> +#define EDU_DMA_BUF_SIZE            (1 << 20)
> +#define EDU_INPUT_BUF_SIZE          256
> +
> +#define EDU_REG_ID                  0x0
> +#define EDU_REG_ALIVE               0x4
> +#define EDU_REG_FACTORIAL           0x8
> +#define EDU_REG_STATUS              0x20
> +#define EDU_REG_DMA_SRC             0x80
> +#define EDU_REG_DMA_DST             0x88
> +#define EDU_REG_DMA_COUNT           0x90
> +#define EDU_REG_DMA_CMD             0x98
> +
> +#define EDU_CMD_DMA_START           0x01
> +#define EDU_CMD_DMA_FROM            0x02
> +#define EDU_CMD_DMA_TO              0x00
> +
> +#define EDU_STATUS_FACTORIAL        0x1
> +#define EDU_STATUS_INT_ENABLE       0x80
> +
> +#define EDU_DMA_START               0x40000
> +#define EDU_DMA_SIZE_MAX            4096
> +
> +struct pci_edu_dev {
> +	struct pci_dev pci_dev;
> +};
> +
> +#define edu_reg(d, r) (volatile void *)((d)->pci_dev.resource[EDU_BAR] + (r))
> +
> +static inline uint64_t edu_reg_readq(struct pci_edu_dev *dev, int reg)
> +{
> +	return __raw_readq(edu_reg(dev, reg));
> +}
> +
> +static inline uint32_t edu_reg_readl(struct pci_edu_dev *dev, int reg)
> +{
> +	return __raw_readl(edu_reg(dev, reg));
> +}
> +
> +static inline void edu_reg_writeq(struct pci_edu_dev *dev, int reg,
> +				  uint64_t val)
> +{
> +	__raw_writeq(val, edu_reg(dev, reg));
> +}
> +
> +static inline void edu_reg_writel(struct pci_edu_dev *dev, int reg,
> +				  uint32_t val)
> +{
> +	__raw_writel(val, edu_reg(dev, reg));
> +}

Can you refresh my memory on why we're using __raw accessors here instead
of the __raw wrappers that include barriers and endian conversion? Hmm,
actually it doesn't look like the EDU device specifies an endianness...

> +
> +bool edu_init(struct pci_edu_dev *dev);
> +void edu_dma(struct pci_edu_dev *dev, iova_t iova,
> +	     size_t size, int dev_offset, bool from_device);
> +
> +#endif
> -- 
> 2.7.4
> 
> --
> 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