[SLOF] [PATCH v1 07/27] virtio: add virtio 1.0 capability parsing

Alexey Kardashevskiy aik at ozlabs.ru
Thu Jan 14 18:07:27 AEDT 2016


On 01/13/2016 10:16 PM, Nikunj A Dadhania wrote:
> Signed-off-by: Nikunj A Dadhania <nikunj at linux.vnet.ibm.com>

Sorry for commenting the same patch twice...


> ---
>   lib/libvirtio/virtio.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++
>   lib/libvirtio/virtio.h |   3 +-
>   2 files changed, 137 insertions(+), 1 deletion(-)
>
> diff --git a/lib/libvirtio/virtio.c b/lib/libvirtio/virtio.c
> index 7e0d6a3..bcf050b 100644
> --- a/lib/libvirtio/virtio.c
> +++ b/lib/libvirtio/virtio.c
> @@ -14,6 +14,7 @@
>   #include <stdbool.h>
>   #include <stdlib.h>
>   #include <string.h>
> +#include <stddef.h>
>   #include <cpu.h>
>   #include <cache.h>
>   #include <byteorder.h>
> @@ -31,6 +32,140 @@
>   #define VIRTIOHDR_ISR_STATUS		19
>   #define VIRTIOHDR_DEVICE_CONFIG 	20
>
> +/* PCI defines */
> +#define PCI_BASE_ADDR_SPACE_IO	0x01
> +#define PCI_BASE_ADDR_SPACE_MEM	0x00
> +#define PCI_BASE_ADDR_MEM_MASK	(~0x0fUL)
> +#define PCI_BASE_ADDR_IO_MASK	(~0x03UL)
> +
> +#define PCI_BASE_ADDR_REG_0	0x10
> +#define PCI_CONFIG_CAP_REG	0x34
> +
> +#define PCI_CAP_ID_VNDR		0x9
> +
> +#define VIRTIO_PCI_CAP_COMMON 1
> +#define VIRTIO_PCI_CAP_NOTIFY 2
> +#define VIRTIO_PCI_CAP_ISR    3
> +#define VIRTIO_PCI_CAP_DEVICE 4
> +#define VIRTIO_PCI_CAP_PCI    5
> +
> +#define VIRTIO_CAP_VNDR     0
> +#define VIRTIO_CAP_NEXT     1
> +#define VIRTIO_CAP_LEN      2
> +#define VIRTIO_CAP_CFG_TYPE 3
> +#define VIRTIO_CAP_BAR      4
> +#define VIRTIO_CAP_OFFSET   8
> +#define VIRTIO_CAP_LENGTH  12
> +
> +#define le64 uint64_t
> +#define le32 uint32_t
> +#define le16 uint16_t
> +
> +struct virtio_dev_common {
> +	le32 dev_features_sel;
> +	le32 dev_features;
> +	le32 drv_features_sel;
> +	le32 drv_features;
> +	le16 msix_config;
> +	le16 num_queues;
> +	uint8_t dev_status;
> +	uint8_t cfg_generation;
> +
> +	le16 q_select;
> +	le16 q_size;
> +	le16 q_msix_vec;
> +	le16 q_enable;
> +	le16 q_notify_off;
> +	le64 q_desc;
> +	le64 q_avail;
> +	le64 q_used;
> +} __attribute__ ((packed));
> +
> +static void virtio_process_cap(struct virtio_device *dev, uint8_t cap_ptr)
> +{
> +	struct virtio_cap *cap;
> +	uint8_t cfg_type, bar;
> +	uint32_t offset;
> +	uint64_t addr = 0;
> +
> +	cfg_type = SLOF_pci_config_read8(cap_ptr + VIRTIO_CAP_CFG_TYPE);
> +	bar = SLOF_pci_config_read8(cap_ptr + VIRTIO_CAP_BAR);
> +	offset = SLOF_pci_config_read32(cap_ptr + VIRTIO_CAP_OFFSET);
> +
> +	switch(cfg_type) {
> +	case VIRTIO_PCI_CAP_COMMON:
> +		cap = &dev->common;
> +		break;
> +	case VIRTIO_PCI_CAP_NOTIFY:
> +		cap = &dev->notify;
> +		dev->notify_off_mul = SLOF_pci_config_read32(cap_ptr + sizeof(struct virtio_cap));
> +		break;
> +	case VIRTIO_PCI_CAP_ISR:
> +		cap = &dev->isr;
> +		break;
> +	case VIRTIO_PCI_CAP_DEVICE:
> +		cap = &dev->device;
> +		break;
> +	default:
> +		cap = NULL;
> +	}
> +
> +	if (cap && cfg_type) {
> +		cap->bar = bar;
> +		addr = SLOF_pci_config_read32(PCI_BASE_ADDR_REG_0 + 4 * cap->bar);
> +		if (addr & PCI_BASE_ADDR_SPACE_IO) {
> +			cap->is_io = 1;
> +			addr = addr & PCI_BASE_ADDR_IO_MASK;
> +		} else if (addr & 4) {
> +			addr = SLOF_pci_config_read32(PCI_BASE_ADDR_REG_0 + 4 * cap->bar) |
> +				(SLOF_pci_config_read32(PCI_BASE_ADDR_REG_0 + 4 * (cap->bar + 1)) << 32);
> +			addr = (uint64_t)SLOF_translate_my_address((void *)addr);
> +			addr = addr & PCI_BASE_ADDR_MEM_MASK;
> +		}
> +		else {
> +			cap->is_io = 0;
> +			addr = addr & PCI_BASE_ADDR_MEM_MASK;
> +		}
> +		cap->addr = (void *)addr + offset;
> +		cap->cap_id = cfg_type;
> +	}
> +	return;
> +}
> +/**
> + * Setup virtio device details, gets called from SLOF routines
> + * Determines legacy or modern device.
> + */
> +void virtio_setup_device(struct virtio_device *dev)
> +{
> +	uint8_t cap_ptr, cap_vndr;
> +	uint64_t addr = 0;
> +
> +	cap_ptr = SLOF_pci_config_read8(PCI_CONFIG_CAP_REG);
> +	while (cap_ptr != 0)
> +	{
> +		cap_vndr = SLOF_pci_config_read8(cap_ptr + VIRTIO_CAP_VNDR);
> +		if (cap_vndr == PCI_CAP_ID_VNDR)
> +			virtio_process_cap(dev, cap_ptr);
> +		cap_ptr = SLOF_pci_config_read8(cap_ptr+VIRTIO_CAP_NEXT);
> +	}
> +	if (dev->common.cap_id && dev->notify.cap_id && dev->isr.cap_id && dev->device.cap_id)
> +		dev->is_modern = 1;


Nit: please use curly braces in both branches if you used then in one of them.


> +	else {
> +		dev->is_modern = 0;
> +		dev->legacy.cap_id = 0;
> +		dev->legacy.bar = 0;
> +		addr = SLOF_pci_config_read32(PCI_BASE_ADDR_REG_0);
> +		if (addr & PCI_BASE_ADDR_SPACE_IO) {
> +			dev->legacy.is_io = 1;
> +			addr = addr & PCI_BASE_ADDR_IO_MASK;
> +		} else {
> +			dev->legacy.is_io = 0;
> +			addr = addr & PCI_BASE_ADDR_MEM_MASK;
> +		}
> +		dev->legacy.addr = (void *)addr;
> +	}
> +	return;
> +}
>
>   /**
>    * Calculate ring size according to queue size number
> diff --git a/lib/libvirtio/virtio.h b/lib/libvirtio/virtio.h
> index 56e044b..eee3144 100644
> --- a/lib/libvirtio/virtio.h
> +++ b/lib/libvirtio/virtio.h
> @@ -74,7 +74,7 @@ struct vring_used {
>
>   /* Structure shared with SLOF and is 16bytes */
>   struct virtio_cap {
> -	uint64_t addr;
> +	void *addr;


You just added @addr in 06/27 and already changing it in the next patch :)


>   	uint8_t bar;
>   	uint8_t is_io;
>   	uint8_t cap_id;
> @@ -116,6 +116,7 @@ extern void virtio_fill_desc(struct vring_desc *desc,
>                                uint16_t flags, uint16_t next);
>   extern int virtio_queue_init_vq(struct virtio_device *dev, struct vqs *vq, unsigned int id);
>
> +extern void virtio_setup_device(struct virtio_device *dev);
>   extern void virtio_reset_device(struct virtio_device *dev);
>   extern void virtio_queue_notify(struct virtio_device *dev, int queue);
>   extern void virtio_set_status(struct virtio_device *dev, int status);
>


-- 
Alexey


More information about the SLOF mailing list