diff mbox

[v2] hw/vfio/platform: Add Qualcomm Technologies, Inc HIDMA device support

Message ID 1471189341-21103-1-git-send-email-shankerd@codeaurora.org
State New
Headers show

Commit Message

Shanker Donthineni Aug. 14, 2016, 3:42 p.m. UTC
This patch introduces the Qualcomm Technologies, Inc HIDMA device and
allows passthrough the host HIDMA device to a guest machine using the
vfio-platform framework.

A platform device tree node is created for the guest machine which
contains the compat string 'qcom,hidma-1.0', mmio regions, active high
SPIs, and an optional property dma-coherent.

Signed-off-by: Vikram Sethi <vikrams@codeaurora.org>
Signed-off-by: Shanker Donthineni <shankerd@codeaurora.org>
---
Changes sicnce v1:
  combined patches [v1 1/2] and [v1 2/2].
  added '#include "qemu/osdep.h'.
  changed compact string to 'qcom,hidma-1.0' to match the host driver.
  set dma-coherent property based on the IOMMU coherency status.

 hw/arm/sysbus-fdt.c               | 67 +++++++++++++++++++++++++++++++++++++++
 hw/vfio/Makefile.objs             |  1 +
 hw/vfio/qcom-hidma.c              | 58 +++++++++++++++++++++++++++++++++
 include/hw/vfio/vfio-qcom-hidma.h | 50 +++++++++++++++++++++++++++++
 4 files changed, 176 insertions(+)
 create mode 100644 hw/vfio/qcom-hidma.c
 create mode 100644 include/hw/vfio/vfio-qcom-hidma.h

Comments

Peter Maydell Aug. 15, 2016, 4:03 p.m. UTC | #1
Just cc'ing Eric on his new email address...

thanks
-- PMM

On 14 August 2016 at 16:42, Shanker Donthineni <shankerd@codeaurora.org> wrote:
> This patch introduces the Qualcomm Technologies, Inc HIDMA device and
> allows passthrough the host HIDMA device to a guest machine using the
> vfio-platform framework.
>
> A platform device tree node is created for the guest machine which
> contains the compat string 'qcom,hidma-1.0', mmio regions, active high
> SPIs, and an optional property dma-coherent.
>
> Signed-off-by: Vikram Sethi <vikrams@codeaurora.org>
> Signed-off-by: Shanker Donthineni <shankerd@codeaurora.org>
> ---
> Changes sicnce v1:
>   combined patches [v1 1/2] and [v1 2/2].
>   added '#include "qemu/osdep.h'.
>   changed compact string to 'qcom,hidma-1.0' to match the host driver.
>   set dma-coherent property based on the IOMMU coherency status.
>
>  hw/arm/sysbus-fdt.c               | 67 +++++++++++++++++++++++++++++++++++++++
>  hw/vfio/Makefile.objs             |  1 +
>  hw/vfio/qcom-hidma.c              | 58 +++++++++++++++++++++++++++++++++
>  include/hw/vfio/vfio-qcom-hidma.h | 50 +++++++++++++++++++++++++++++
>  4 files changed, 176 insertions(+)
>  create mode 100644 hw/vfio/qcom-hidma.c
>  create mode 100644 include/hw/vfio/vfio-qcom-hidma.h
>
> diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c
> index 5debb33..bdf8cbb 100644
> --- a/hw/arm/sysbus-fdt.c
> +++ b/hw/arm/sysbus-fdt.c
> @@ -27,6 +27,7 @@
>  #include "qemu-common.h"
>  #ifdef CONFIG_LINUX
>  #include <linux/vfio.h>
> +#include <sys/ioctl.h>
>  #endif
>  #include "hw/arm/sysbus-fdt.h"
>  #include "qemu/error-report.h"
> @@ -36,6 +37,7 @@
>  #include "hw/vfio/vfio-platform.h"
>  #include "hw/vfio/vfio-calxeda-xgmac.h"
>  #include "hw/vfio/vfio-amd-xgbe.h"
> +#include "hw/vfio/vfio-qcom-hidma.h"
>  #include "hw/arm/fdt.h"
>
>  /*
> @@ -262,6 +264,70 @@ static int add_calxeda_midway_xgmac_fdt_node(SysBusDevice *sbdev, void *opaque)
>      return 0;
>  }
>
> +/**
> + * add_qcom_hidma_fdt_node
> + *
> + * Generates a simple node with following properties:
> + * compatible string, regs, active-high interrupts, and optional dma-coherent
> + */
> +static int add_qcom_hidma_fdt_node(SysBusDevice *sbdev, void *opaque)
> +{
> +    VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
> +    struct VFIOGroup *group = vdev->vbasedev.group;
> +    VFIODevice *vbasedev = &vdev->vbasedev;
> +    PlatformBusFDTData *data = opaque;
> +    const char *parent_node = data->pbus_node_name;
> +    PlatformBusDevice *pbus = data->pbus;
> +    uint32_t *irq_attr, *reg_attr;
> +    uint64_t mmio_base, irq_number;
> +    void *fdt = data->fdt;
> +    int compat_str_len, i, ret;
> +    char *nodename;
> +
> +    mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
> +    nodename = g_strdup_printf("%s/%s@%" PRIx64, parent_node,
> +                               vbasedev->name, mmio_base);
> +    assert(nodename);
> +    qemu_fdt_add_subnode(fdt, nodename);
> +
> +    compat_str_len = strlen(vdev->compat) + 1;
> +    qemu_fdt_setprop(fdt, nodename, "compatible",
> +                          vdev->compat, compat_str_len);
> +
> +    /* Check if the DMA cache coherency was enabled in IOMMU */
> +    ret = ioctl(group->container->fd, VFIO_CHECK_EXTENSION, VFIO_DMA_CC_IOMMU);
> +    if (ret > 0) {
> +        qemu_fdt_setprop(fdt, nodename, "dma-coherent", "", 0);
> +    }
> +
> +    reg_attr = g_new(uint32_t, vbasedev->num_regions * 2);
> +    assert(reg_attr);
> +    for (i = 0; i < vbasedev->num_regions; i++) {
> +        mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, i);
> +        reg_attr[2 * i] = cpu_to_be32(mmio_base);
> +        reg_attr[2 * i + 1] = cpu_to_be32(
> +                                memory_region_size(vdev->regions[i]->mem));
> +    }
> +    qemu_fdt_setprop(fdt, nodename, "reg", reg_attr,
> +                     vbasedev->num_regions * 2 * sizeof(uint32_t));
> +
> +    irq_attr = g_new(uint32_t, vbasedev->num_irqs * 3);
> +    assert(irq_attr);
> +    for (i = 0; i < vbasedev->num_irqs; i++) {
> +        irq_number = platform_bus_get_irqn(pbus, sbdev , i)
> +                         + data->irq_start;
> +        irq_attr[3 * i] = cpu_to_be32(GIC_FDT_IRQ_TYPE_SPI);
> +        irq_attr[3 * i + 1] = cpu_to_be32(irq_number);
> +        irq_attr[3 * i + 2] = cpu_to_be32(GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> +    }
> +    qemu_fdt_setprop(fdt, nodename, "interrupts",
> +                     irq_attr, vbasedev->num_irqs * 3 * sizeof(uint32_t));
> +    g_free(irq_attr);
> +    g_free(reg_attr);
> +    g_free(nodename);
> +    return 0;
> +}
> +
>  /* AMD xgbe properties whose values are copied/pasted from host */
>  static HostProperty amd_xgbe_copied_properties[] = {
>      {"compatible", false},
> @@ -420,6 +486,7 @@ static const NodeCreationPair add_fdt_node_functions[] = {
>  #ifdef CONFIG_LINUX
>      {TYPE_VFIO_CALXEDA_XGMAC, add_calxeda_midway_xgmac_fdt_node},
>      {TYPE_VFIO_AMD_XGBE, add_amd_xgbe_fdt_node},
> +    {TYPE_VFIO_QCOM_HIDMA, add_qcom_hidma_fdt_node},
>  #endif
>      {"", NULL}, /* last element */
>  };
> diff --git a/hw/vfio/Makefile.objs b/hw/vfio/Makefile.objs
> index c25e32b..ac38c8f 100644
> --- a/hw/vfio/Makefile.objs
> +++ b/hw/vfio/Makefile.objs
> @@ -5,4 +5,5 @@ obj-$(CONFIG_SOFTMMU) += platform.o
>  obj-$(CONFIG_SOFTMMU) += calxeda-xgmac.o
>  obj-$(CONFIG_SOFTMMU) += amd-xgbe.o
>  obj-$(CONFIG_SOFTMMU) += spapr.o
> +obj-$(CONFIG_SOFTMMU) += qcom-hidma.o
>  endif
> diff --git a/hw/vfio/qcom-hidma.c b/hw/vfio/qcom-hidma.c
> new file mode 100644
> index 0000000..ddb3c34
> --- /dev/null
> +++ b/hw/vfio/qcom-hidma.c
> @@ -0,0 +1,58 @@
> +/*
> + * Qualcomm Technologies, Inc VFIO HiDMA platform device
> + *
> + * Copyright (c) 2016, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +#include "qemu/osdep.h"
> +#include "hw/vfio/vfio-qcom-hidma.h"
> +
> +static void qcom_hidma_realize(DeviceState *dev, Error **errp)
> +{
> +    VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(dev);
> +    VFIOQcomHidmaDeviceClass *k = VFIO_QCOM_HIDMA_DEVICE_GET_CLASS(dev);
> +
> +    vdev->compat = g_strdup("qcom,hidma-1.0");
> +
> +    k->parent_realize(dev, errp);
> +}
> +
> +static const VMStateDescription vfio_platform_vmstate = {
> +    .name = TYPE_VFIO_QCOM_HIDMA,
> +    .unmigratable = 1,
> +};
> +
> +static void vfio_qcom_hidma_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    VFIOQcomHidmaDeviceClass *vcxc = VFIO_QCOM_HIDMA_DEVICE_CLASS(klass);
> +
> +    vcxc->parent_realize = dc->realize;
> +    dc->realize = qcom_hidma_realize;
> +    dc->desc = "VFIO QCOM HIDMA";
> +    dc->vmsd = &vfio_platform_vmstate;
> +}
> +
> +static const TypeInfo vfio_qcom_hidma_dev_info = {
> +    .name = TYPE_VFIO_QCOM_HIDMA,
> +    .parent = TYPE_VFIO_PLATFORM,
> +    .instance_size = sizeof(VFIOQcomHidmaDevice),
> +    .class_init = vfio_qcom_hidma_class_init,
> +    .class_size = sizeof(VFIOQcomHidmaDeviceClass),
> +};
> +
> +static void register_qcom_hidma_dev_type(void)
> +{
> +    type_register_static(&vfio_qcom_hidma_dev_info);
> +}
> +
> +type_init(register_qcom_hidma_dev_type)
> diff --git a/include/hw/vfio/vfio-qcom-hidma.h b/include/hw/vfio/vfio-qcom-hidma.h
> new file mode 100644
> index 0000000..23cd66c
> --- /dev/null
> +++ b/include/hw/vfio/vfio-qcom-hidma.h
> @@ -0,0 +1,50 @@
> +/*
> + * Qualcomm Technologies, Inc VFIO HiDMA platform device
> + *
> + * Copyright (c) 2016, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#ifndef HW_VFIO_VFIO_QCOM_HIDMA_H
> +#define HW_VFIO_VFIO_QCOM_HIDMA_H
> +
> +#include "hw/vfio/vfio-platform.h"
> +
> +#define TYPE_VFIO_QCOM_HIDMA "vfio-qcom-hidma"
> +
> +/**
> + * This device exposes:
> + * - MMIO regions corresponding to its register space
> + * - Active high IRQs
> + * - Optional property 'dma-coherent'
> + */
> +typedef struct VFIOQcomHidmaDevice {
> +    VFIOPlatformDevice vdev;
> +} VFIOQcomHidmaDevice;
> +
> +typedef struct VFIOQcomHidmaDeviceClass {
> +    /*< private >*/
> +    VFIOPlatformDeviceClass parent_class;
> +    /*< public >*/
> +    DeviceRealize parent_realize;
> +} VFIOQcomHidmaDeviceClass;
> +
> +#define VFIO_QCOM_HIDMA_DEVICE(obj) \
> +     OBJECT_CHECK(VFIOQcomHidmaDevice, (obj), TYPE_VFIO_QCOM_HIDMA)
> +#define VFIO_QCOM_HIDMA_DEVICE_CLASS(klass) \
> +     OBJECT_CLASS_CHECK(VFIOQcomHidmaDeviceClass, (klass), \
> +                        TYPE_VFIO_QCOM_HIDMA)
> +#define VFIO_QCOM_HIDMA_DEVICE_GET_CLASS(obj) \
> +     OBJECT_GET_CLASS(VFIOQcomHidmaDeviceClass, (obj), \
> +                      TYPE_VFIO_QCOM_HIDMA)
> +
> +#endif
> --
> Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, Inc.
> Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
>
Sinan Kaya Aug. 15, 2016, 4:47 p.m. UTC | #2
On 8/15/2016 12:03 PM, Peter Maydell wrote:
> Just cc'ing Eric on his new email address...
> 
> thanks
> -- PMM
> 
> On 14 August 2016 at 16:42, Shanker Donthineni <shankerd@codeaurora.org> wrote:
>> This patch introduces the Qualcomm Technologies, Inc HIDMA device and
>> allows passthrough the host HIDMA device to a guest machine using the
>> vfio-platform framework.
>>
>> A platform device tree node is created for the guest machine which
>> contains the compat string 'qcom,hidma-1.0', mmio regions, active high
>> SPIs, and an optional property dma-coherent.
>>
>> Signed-off-by: Vikram Sethi <vikrams@codeaurora.org>
>> Signed-off-by: Shanker Donthineni <shankerd@codeaurora.org>
>> ---
>> Changes sicnce v1:
>>   combined patches [v1 1/2] and [v1 2/2].
>>   added '#include "qemu/osdep.h'.
>>   changed compact string to 'qcom,hidma-1.0' to match the host driver.
>>   set dma-coherent property based on the IOMMU coherency status.
>>
>>  hw/arm/sysbus-fdt.c               | 67 +++++++++++++++++++++++++++++++++++++++
>>  hw/vfio/Makefile.objs             |  1 +
>>  hw/vfio/qcom-hidma.c              | 58 +++++++++++++++++++++++++++++++++
>>  include/hw/vfio/vfio-qcom-hidma.h | 50 +++++++++++++++++++++++++++++
>>  4 files changed, 176 insertions(+)
>>  create mode 100644 hw/vfio/qcom-hidma.c
>>  create mode 100644 include/hw/vfio/vfio-qcom-hidma.h
>>
>> diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c
>> index 5debb33..bdf8cbb 100644
>> --- a/hw/arm/sysbus-fdt.c
>> +++ b/hw/arm/sysbus-fdt.c
>> @@ -27,6 +27,7 @@
>>  #include "qemu-common.h"
>>  #ifdef CONFIG_LINUX
>>  #include <linux/vfio.h>
>> +#include <sys/ioctl.h>
>>  #endif
>>  #include "hw/arm/sysbus-fdt.h"
>>  #include "qemu/error-report.h"
>> @@ -36,6 +37,7 @@
>>  #include "hw/vfio/vfio-platform.h"
>>  #include "hw/vfio/vfio-calxeda-xgmac.h"
>>  #include "hw/vfio/vfio-amd-xgbe.h"
>> +#include "hw/vfio/vfio-qcom-hidma.h"
>>  #include "hw/arm/fdt.h"
>>
>>  /*
>> @@ -262,6 +264,70 @@ static int add_calxeda_midway_xgmac_fdt_node(SysBusDevice *sbdev, void *opaque)
>>      return 0;
>>  }
>>
>> +/**
>> + * add_qcom_hidma_fdt_node
>> + *
>> + * Generates a simple node with following properties:
>> + * compatible string, regs, active-high interrupts, and optional dma-coherent
>> + */
>> +static int add_qcom_hidma_fdt_node(SysBusDevice *sbdev, void *opaque)
>> +{
>> +    VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
>> +    struct VFIOGroup *group = vdev->vbasedev.group;
>> +    VFIODevice *vbasedev = &vdev->vbasedev;
>> +    PlatformBusFDTData *data = opaque;
>> +    const char *parent_node = data->pbus_node_name;
>> +    PlatformBusDevice *pbus = data->pbus;
>> +    uint32_t *irq_attr, *reg_attr;
>> +    uint64_t mmio_base, irq_number;
>> +    void *fdt = data->fdt;
>> +    int compat_str_len, i, ret;
>> +    char *nodename;
>> +
>> +    mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
>> +    nodename = g_strdup_printf("%s/%s@%" PRIx64, parent_node,
>> +                               vbasedev->name, mmio_base);
>> +    assert(nodename);
>> +    qemu_fdt_add_subnode(fdt, nodename);
>> +
>> +    compat_str_len = strlen(vdev->compat) + 1;
>> +    qemu_fdt_setprop(fdt, nodename, "compatible",
>> +                          vdev->compat, compat_str_len);
>> +
>> +    /* Check if the DMA cache coherency was enabled in IOMMU */
>> +    ret = ioctl(group->container->fd, VFIO_CHECK_EXTENSION, VFIO_DMA_CC_IOMMU);
>> +    if (ret > 0) {
>> +        qemu_fdt_setprop(fdt, nodename, "dma-coherent", "", 0);
>> +    }
>> +
>> +    reg_attr = g_new(uint32_t, vbasedev->num_regions * 2);
>> +    assert(reg_attr);
>> +    for (i = 0; i < vbasedev->num_regions; i++) {
>> +        mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, i);
>> +        reg_attr[2 * i] = cpu_to_be32(mmio_base);
>> +        reg_attr[2 * i + 1] = cpu_to_be32(
>> +                                memory_region_size(vdev->regions[i]->mem));
>> +    }
>> +    qemu_fdt_setprop(fdt, nodename, "reg", reg_attr,
>> +                     vbasedev->num_regions * 2 * sizeof(uint32_t));
>> +
>> +    irq_attr = g_new(uint32_t, vbasedev->num_irqs * 3);
>> +    assert(irq_attr);
>> +    for (i = 0; i < vbasedev->num_irqs; i++) {
>> +        irq_number = platform_bus_get_irqn(pbus, sbdev , i)
>> +                         + data->irq_start;
>> +        irq_attr[3 * i] = cpu_to_be32(GIC_FDT_IRQ_TYPE_SPI);
>> +        irq_attr[3 * i + 1] = cpu_to_be32(irq_number);
>> +        irq_attr[3 * i + 2] = cpu_to_be32(GIC_FDT_IRQ_FLAGS_LEVEL_HI);
>> +    }
>> +    qemu_fdt_setprop(fdt, nodename, "interrupts",
>> +                     irq_attr, vbasedev->num_irqs * 3 * sizeof(uint32_t));
>> +    g_free(irq_attr);
>> +    g_free(reg_attr);
>> +    g_free(nodename);
>> +    return 0;
>> +}
>> +
>>  /* AMD xgbe properties whose values are copied/pasted from host */
>>  static HostProperty amd_xgbe_copied_properties[] = {
>>      {"compatible", false},
>> @@ -420,6 +486,7 @@ static const NodeCreationPair add_fdt_node_functions[] = {
>>  #ifdef CONFIG_LINUX
>>      {TYPE_VFIO_CALXEDA_XGMAC, add_calxeda_midway_xgmac_fdt_node},
>>      {TYPE_VFIO_AMD_XGBE, add_amd_xgbe_fdt_node},
>> +    {TYPE_VFIO_QCOM_HIDMA, add_qcom_hidma_fdt_node},
>>  #endif
>>      {"", NULL}, /* last element */
>>  };
>> diff --git a/hw/vfio/Makefile.objs b/hw/vfio/Makefile.objs
>> index c25e32b..ac38c8f 100644
>> --- a/hw/vfio/Makefile.objs
>> +++ b/hw/vfio/Makefile.objs
>> @@ -5,4 +5,5 @@ obj-$(CONFIG_SOFTMMU) += platform.o
>>  obj-$(CONFIG_SOFTMMU) += calxeda-xgmac.o
>>  obj-$(CONFIG_SOFTMMU) += amd-xgbe.o
>>  obj-$(CONFIG_SOFTMMU) += spapr.o
>> +obj-$(CONFIG_SOFTMMU) += qcom-hidma.o
>>  endif
>> diff --git a/hw/vfio/qcom-hidma.c b/hw/vfio/qcom-hidma.c
>> new file mode 100644
>> index 0000000..ddb3c34
>> --- /dev/null
>> +++ b/hw/vfio/qcom-hidma.c
>> @@ -0,0 +1,58 @@
>> +/*
>> + * Qualcomm Technologies, Inc VFIO HiDMA platform device
>> + *
>> + * Copyright (c) 2016, The Linux Foundation. All rights reserved.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 and
>> + * only version 2 as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + */
>> +#include "qemu/osdep.h"
>> +#include "hw/vfio/vfio-qcom-hidma.h"
>> +
>> +static void qcom_hidma_realize(DeviceState *dev, Error **errp)
>> +{
>> +    VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(dev);
>> +    VFIOQcomHidmaDeviceClass *k = VFIO_QCOM_HIDMA_DEVICE_GET_CLASS(dev);
>> +
>> +    vdev->compat = g_strdup("qcom,hidma-1.0");
>> +
>> +    k->parent_realize(dev, errp);
>> +}
>> +
>> +static const VMStateDescription vfio_platform_vmstate = {
>> +    .name = TYPE_VFIO_QCOM_HIDMA,
>> +    .unmigratable = 1,
>> +};
>> +
>> +static void vfio_qcom_hidma_class_init(ObjectClass *klass, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +    VFIOQcomHidmaDeviceClass *vcxc = VFIO_QCOM_HIDMA_DEVICE_CLASS(klass);
>> +
>> +    vcxc->parent_realize = dc->realize;
>> +    dc->realize = qcom_hidma_realize;
>> +    dc->desc = "VFIO QCOM HIDMA";
>> +    dc->vmsd = &vfio_platform_vmstate;
>> +}
>> +
>> +static const TypeInfo vfio_qcom_hidma_dev_info = {
>> +    .name = TYPE_VFIO_QCOM_HIDMA,
>> +    .parent = TYPE_VFIO_PLATFORM,
>> +    .instance_size = sizeof(VFIOQcomHidmaDevice),
>> +    .class_init = vfio_qcom_hidma_class_init,
>> +    .class_size = sizeof(VFIOQcomHidmaDeviceClass),
>> +};
>> +
>> +static void register_qcom_hidma_dev_type(void)
>> +{
>> +    type_register_static(&vfio_qcom_hidma_dev_info);
>> +}
>> +
>> +type_init(register_qcom_hidma_dev_type)
>> diff --git a/include/hw/vfio/vfio-qcom-hidma.h b/include/hw/vfio/vfio-qcom-hidma.h
>> new file mode 100644
>> index 0000000..23cd66c
>> --- /dev/null
>> +++ b/include/hw/vfio/vfio-qcom-hidma.h
>> @@ -0,0 +1,50 @@
>> +/*
>> + * Qualcomm Technologies, Inc VFIO HiDMA platform device
>> + *
>> + * Copyright (c) 2016, The Linux Foundation. All rights reserved.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 and
>> + * only version 2 as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + */
>> +
>> +#ifndef HW_VFIO_VFIO_QCOM_HIDMA_H
>> +#define HW_VFIO_VFIO_QCOM_HIDMA_H
>> +
>> +#include "hw/vfio/vfio-platform.h"
>> +
>> +#define TYPE_VFIO_QCOM_HIDMA "vfio-qcom-hidma"
>> +
>> +/**
>> + * This device exposes:
>> + * - MMIO regions corresponding to its register space
>> + * - Active high IRQs
>> + * - Optional property 'dma-coherent'
>> + */
>> +typedef struct VFIOQcomHidmaDevice {
>> +    VFIOPlatformDevice vdev;
>> +} VFIOQcomHidmaDevice;
>> +
>> +typedef struct VFIOQcomHidmaDeviceClass {
>> +    /*< private >*/
>> +    VFIOPlatformDeviceClass parent_class;
>> +    /*< public >*/
>> +    DeviceRealize parent_realize;
>> +} VFIOQcomHidmaDeviceClass;
>> +
>> +#define VFIO_QCOM_HIDMA_DEVICE(obj) \
>> +     OBJECT_CHECK(VFIOQcomHidmaDevice, (obj), TYPE_VFIO_QCOM_HIDMA)
>> +#define VFIO_QCOM_HIDMA_DEVICE_CLASS(klass) \
>> +     OBJECT_CLASS_CHECK(VFIOQcomHidmaDeviceClass, (klass), \
>> +                        TYPE_VFIO_QCOM_HIDMA)
>> +#define VFIO_QCOM_HIDMA_DEVICE_GET_CLASS(obj) \
>> +     OBJECT_GET_CLASS(VFIOQcomHidmaDeviceClass, (obj), \
>> +                      TYPE_VFIO_QCOM_HIDMA)
>> +
>> +#endif
>> --
>> Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, Inc.
>> Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
>>
> 
> 

Tested-by: Sinan Kaya <okaya@codeaurora.org>
Eric Auger Aug. 18, 2016, 9:37 a.m. UTC | #3
Hi Shanker,

Adding Alex in CC for (*)

On 14/08/2016 17:42, Shanker Donthineni wrote:
> This patch introduces the Qualcomm Technologies, Inc HIDMA device and
> allows passthrough the host HIDMA device to a guest machine using the
> vfio-platform framework.
> 
> A platform device tree node is created for the guest machine which
> contains the compat string 'qcom,hidma-1.0', mmio regions, active high
> SPIs, and an optional property dma-coherent.
> 
> Signed-off-by: Vikram Sethi <vikrams@codeaurora.org>
> Signed-off-by: Shanker Donthineni <shankerd@codeaurora.org>
> ---
> Changes sicnce v1:
>   combined patches [v1 1/2] and [v1 2/2].
Some general comments:
- I preferred the previous series organization where we had the creation
of the VFIO device first and its sysbus-fdt dynamic instantiation in a
separate patch.

Peter requested sysbus-fdt stops growing and advised to split the fine
into generic helpers and specific dt creation functions in separate
files. This sounds the right moment to do it with looming new VFIO devices.

(*) Also I am now reconsidering the relevance of creating specific VFIO
devices per compat string. At the begining of VFIO QEMU integration
history we made that choice, advised by Alex (Graf), considering the
QEMU VFIO device could not be generic. With a little more experience now
we could see the specialization is currently done in the dt creation
function (sysbus-fdt) and in the kernel reset module. So I would now
advocate using a non abstract base VFIO device that could be
instantiated passing its compat string as property. Creating
hw/vfio/qcom-hidma.c and include/hw/vfio/vfio-qcom-hidma.h then would
become useless. Alex, what is your feeling now?

I think the split of sysbus-fdt and (*) - if approoved -  shall be
considered before introducing a new QEMU VFIO device. Are you willing to
work on it?

>   added '#include "qemu/osdep.h'.
>   changed compact string to 'qcom,hidma-1.0' to match the host driver.
>   set dma-coherent property based on the IOMMU coherency status.
> 
>  hw/arm/sysbus-fdt.c               | 67 +++++++++++++++++++++++++++++++++++++++
>  hw/vfio/Makefile.objs             |  1 +
>  hw/vfio/qcom-hidma.c              | 58 +++++++++++++++++++++++++++++++++
>  include/hw/vfio/vfio-qcom-hidma.h | 50 +++++++++++++++++++++++++++++
>  4 files changed, 176 insertions(+)
>  create mode 100644 hw/vfio/qcom-hidma.c
>  create mode 100644 include/hw/vfio/vfio-qcom-hidma.h
> 
> diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c
> index 5debb33..bdf8cbb 100644
> --- a/hw/arm/sysbus-fdt.c
> +++ b/hw/arm/sysbus-fdt.c
> @@ -27,6 +27,7 @@
>  #include "qemu-common.h"
>  #ifdef CONFIG_LINUX
>  #include <linux/vfio.h>
> +#include <sys/ioctl.h>
>  #endif
>  #include "hw/arm/sysbus-fdt.h"
>  #include "qemu/error-report.h"
> @@ -36,6 +37,7 @@
>  #include "hw/vfio/vfio-platform.h"
>  #include "hw/vfio/vfio-calxeda-xgmac.h"
>  #include "hw/vfio/vfio-amd-xgbe.h"
> +#include "hw/vfio/vfio-qcom-hidma.h"
>  #include "hw/arm/fdt.h"
>  
>  /*
> @@ -262,6 +264,70 @@ static int add_calxeda_midway_xgmac_fdt_node(SysBusDevice *sbdev, void *opaque)
>      return 0;
>  }
>  
> +/**
> + * add_qcom_hidma_fdt_node
> + *
> + * Generates a simple node with following properties:
> + * compatible string, regs, active-high interrupts, and optional dma-coherent
> + */
> +static int add_qcom_hidma_fdt_node(SysBusDevice *sbdev, void *opaque)
> +{
> +    VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
> +    struct VFIOGroup *group = vdev->vbasedev.group;
> +    VFIODevice *vbasedev = &vdev->vbasedev;
> +    PlatformBusFDTData *data = opaque;
> +    const char *parent_node = data->pbus_node_name;
> +    PlatformBusDevice *pbus = data->pbus;
> +    uint32_t *irq_attr, *reg_attr;
> +    uint64_t mmio_base, irq_number;
> +    void *fdt = data->fdt;
> +    int compat_str_len, i, ret;
> +    char *nodename;
> +
> +    mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
> +    nodename = g_strdup_printf("%s/%s@%" PRIx64, parent_node,
> +                               vbasedev->name, mmio_base);
> +    assert(nodename);
although not very explicit in the glib documentation, I think
g_strdup_printf already handles OOM errors so assert should be safely
removed I think.
> +    qemu_fdt_add_subnode(fdt, nodename);
> +
> +    compat_str_len = strlen(vdev->compat) + 1;
> +    qemu_fdt_setprop(fdt, nodename, "compatible",
> +                          vdev->compat, compat_str_len);
> +
> +    /* Check if the DMA cache coherency was enabled in IOMMU */
> +    ret = ioctl(group->container->fd, VFIO_CHECK_EXTENSION, VFIO_DMA_CC_IOMMU);
> +    if (ret > 0) {
> +        qemu_fdt_setprop(fdt, nodename, "dma-coherent", "", 0);
> +    }
This checks the IOMMU enforces DMA cache coherence -> ie. all the vfio
groups support IOMMU_CACHE property -> depends on whether the host bus
supports cache coherency. This does not tell whether the host device is
dma-capable.

In current xgmac dt node creation function I only check the host dt node
features the dma-coherent property. Maybe we should check both the
device and the bus support the capability? Can we have the dma-coherent
property set in the host dt device node while the bus does not support it?

> +
> +    reg_attr = g_new(uint32_t, vbasedev->num_regions * 2);
> +    assert(reg_attr);
same here
> +    for (i = 0; i < vbasedev->num_regions; i++) {
> +        mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, i);
> +        reg_attr[2 * i] = cpu_to_be32(mmio_base);
> +        reg_attr[2 * i + 1] = cpu_to_be32(
> +                                memory_region_size(vdev->regions[i]->mem));
> +    }
We evoked using a helper function to minimize the code duplication
between devices.
> +    qemu_fdt_setprop(fdt, nodename, "reg", reg_attr,
> +                     vbasedev->num_regions * 2 * sizeof(uint32_t));
> +
> +    irq_attr = g_new(uint32_t, vbasedev->num_irqs * 3);
> +    assert(irq_attr);
same here

Thanks

Eric
> +    for (i = 0; i < vbasedev->num_irqs; i++) {
> +        irq_number = platform_bus_get_irqn(pbus, sbdev , i)
> +                         + data->irq_start;
> +        irq_attr[3 * i] = cpu_to_be32(GIC_FDT_IRQ_TYPE_SPI);
> +        irq_attr[3 * i + 1] = cpu_to_be32(irq_number);
> +        irq_attr[3 * i + 2] = cpu_to_be32(GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> +    }
> +    qemu_fdt_setprop(fdt, nodename, "interrupts",
> +                     irq_attr, vbasedev->num_irqs * 3 * sizeof(uint32_t));
> +    g_free(irq_attr);
> +    g_free(reg_attr);
> +    g_free(nodename);
> +    return 0;
> +}
> +
>  /* AMD xgbe properties whose values are copied/pasted from host */
>  static HostProperty amd_xgbe_copied_properties[] = {
>      {"compatible", false},
> @@ -420,6 +486,7 @@ static const NodeCreationPair add_fdt_node_functions[] = {
>  #ifdef CONFIG_LINUX
>      {TYPE_VFIO_CALXEDA_XGMAC, add_calxeda_midway_xgmac_fdt_node},
>      {TYPE_VFIO_AMD_XGBE, add_amd_xgbe_fdt_node},
> +    {TYPE_VFIO_QCOM_HIDMA, add_qcom_hidma_fdt_node},
>  #endif
>      {"", NULL}, /* last element */
>  };
> diff --git a/hw/vfio/Makefile.objs b/hw/vfio/Makefile.objs
> index c25e32b..ac38c8f 100644
> --- a/hw/vfio/Makefile.objs
> +++ b/hw/vfio/Makefile.objs
> @@ -5,4 +5,5 @@ obj-$(CONFIG_SOFTMMU) += platform.o
>  obj-$(CONFIG_SOFTMMU) += calxeda-xgmac.o
>  obj-$(CONFIG_SOFTMMU) += amd-xgbe.o
>  obj-$(CONFIG_SOFTMMU) += spapr.o
> +obj-$(CONFIG_SOFTMMU) += qcom-hidma.o
>  endif
> diff --git a/hw/vfio/qcom-hidma.c b/hw/vfio/qcom-hidma.c
> new file mode 100644
> index 0000000..ddb3c34
> --- /dev/null
> +++ b/hw/vfio/qcom-hidma.c
> @@ -0,0 +1,58 @@
> +/*
> + * Qualcomm Technologies, Inc VFIO HiDMA platform device
> + *
> + * Copyright (c) 2016, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +#include "qemu/osdep.h"
> +#include "hw/vfio/vfio-qcom-hidma.h"
> +
> +static void qcom_hidma_realize(DeviceState *dev, Error **errp)
> +{
> +    VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(dev);
> +    VFIOQcomHidmaDeviceClass *k = VFIO_QCOM_HIDMA_DEVICE_GET_CLASS(dev);
> +
> +    vdev->compat = g_strdup("qcom,hidma-1.0");
> +
> +    k->parent_realize(dev, errp);
> +}
> +
> +static const VMStateDescription vfio_platform_vmstate = {
> +    .name = TYPE_VFIO_QCOM_HIDMA,
> +    .unmigratable = 1,
> +};
> +
> +static void vfio_qcom_hidma_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    VFIOQcomHidmaDeviceClass *vcxc = VFIO_QCOM_HIDMA_DEVICE_CLASS(klass);
> +
> +    vcxc->parent_realize = dc->realize;
> +    dc->realize = qcom_hidma_realize;
> +    dc->desc = "VFIO QCOM HIDMA";
> +    dc->vmsd = &vfio_platform_vmstate;
> +}
> +
> +static const TypeInfo vfio_qcom_hidma_dev_info = {
> +    .name = TYPE_VFIO_QCOM_HIDMA,
> +    .parent = TYPE_VFIO_PLATFORM,
> +    .instance_size = sizeof(VFIOQcomHidmaDevice),
> +    .class_init = vfio_qcom_hidma_class_init,
> +    .class_size = sizeof(VFIOQcomHidmaDeviceClass),
> +};
> +
> +static void register_qcom_hidma_dev_type(void)
> +{
> +    type_register_static(&vfio_qcom_hidma_dev_info);
> +}
> +
> +type_init(register_qcom_hidma_dev_type)
> diff --git a/include/hw/vfio/vfio-qcom-hidma.h b/include/hw/vfio/vfio-qcom-hidma.h
> new file mode 100644
> index 0000000..23cd66c
> --- /dev/null
> +++ b/include/hw/vfio/vfio-qcom-hidma.h
> @@ -0,0 +1,50 @@
> +/*
> + * Qualcomm Technologies, Inc VFIO HiDMA platform device
> + *
> + * Copyright (c) 2016, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#ifndef HW_VFIO_VFIO_QCOM_HIDMA_H
> +#define HW_VFIO_VFIO_QCOM_HIDMA_H
> +
> +#include "hw/vfio/vfio-platform.h"
> +
> +#define TYPE_VFIO_QCOM_HIDMA "vfio-qcom-hidma"
> +
> +/**
> + * This device exposes:
> + * - MMIO regions corresponding to its register space
> + * - Active high IRQs
> + * - Optional property 'dma-coherent'
> + */
> +typedef struct VFIOQcomHidmaDevice {
> +    VFIOPlatformDevice vdev;
> +} VFIOQcomHidmaDevice;
> +
> +typedef struct VFIOQcomHidmaDeviceClass {
> +    /*< private >*/
> +    VFIOPlatformDeviceClass parent_class;
> +    /*< public >*/
> +    DeviceRealize parent_realize;
> +} VFIOQcomHidmaDeviceClass;
> +
> +#define VFIO_QCOM_HIDMA_DEVICE(obj) \
> +     OBJECT_CHECK(VFIOQcomHidmaDevice, (obj), TYPE_VFIO_QCOM_HIDMA)
> +#define VFIO_QCOM_HIDMA_DEVICE_CLASS(klass) \
> +     OBJECT_CLASS_CHECK(VFIOQcomHidmaDeviceClass, (klass), \
> +                        TYPE_VFIO_QCOM_HIDMA)
> +#define VFIO_QCOM_HIDMA_DEVICE_GET_CLASS(obj) \
> +     OBJECT_GET_CLASS(VFIOQcomHidmaDeviceClass, (obj), \
> +                      TYPE_VFIO_QCOM_HIDMA)
> +
> +#endif
>
Sinan Kaya Aug. 18, 2016, 1:52 p.m. UTC | #4
On 8/18/2016 5:37 AM, Auger Eric wrote:
> Some general comments:
> - I preferred the previous series organization where we had the creation
> of the VFIO device first and its sysbus-fdt dynamic instantiation in a
> separate patch.
> 
> Peter requested sysbus-fdt stops growing and advised to split the fine
> into generic helpers and specific dt creation functions in separate
> files. This sounds the right moment to do it with looming new VFIO devices.
> 
> (*) Also I am now reconsidering the relevance of creating specific VFIO
> devices per compat string. At the begining of VFIO QEMU integration
> history we made that choice, advised by Alex (Graf), considering the
> QEMU VFIO device could not be generic. With a little more experience now
> we could see the specialization is currently done in the dt creation
> function (sysbus-fdt) and in the kernel reset module. So I would now
> advocate using a non abstract base VFIO device that could be
> instantiated passing its compat string as property. Creating
> hw/vfio/qcom-hidma.c and include/hw/vfio/vfio-qcom-hidma.h then would
> become useless. Alex, what is your feeling now?
> 
> I think the split of sysbus-fdt and (*) - if approoved -  shall be
> considered before introducing a new QEMU VFIO device. Are you willing to
> work on it?

I really like generic device approach. It would save a ton of burden from
developers.

If somebody needs a specialized device, they can do so. For simple objects
that just needs a compat string, it doesn't make sense to create a driver
every single time.

Similarly, there is generic PCI host driver in the Linux kernel that works
for systems that is CAM or ECAM compliant. If somebody needs to do more,
they can implement their own PCI host driver too. 

We are really looking for the same model.

I'm interested in virtualization of platform SATA and HIDMA devices. The
only difference between these are the compatible strings. 

Why submit a new SATA AHCI driver for QEMU just to set the compat string?
Alexander Graf Aug. 18, 2016, 10:35 p.m. UTC | #5
> On 18 Aug 2016, at 05:37, Auger Eric <eric.auger@redhat.com> wrote:
> 
> Hi Shanker,
> 
> Adding Alex in CC for (*)
> 
> On 14/08/2016 17:42, Shanker Donthineni wrote:
>> This patch introduces the Qualcomm Technologies, Inc HIDMA device and
>> allows passthrough the host HIDMA device to a guest machine using the
>> vfio-platform framework.
>> 
>> A platform device tree node is created for the guest machine which
>> contains the compat string 'qcom,hidma-1.0', mmio regions, active high
>> SPIs, and an optional property dma-coherent.
>> 
>> Signed-off-by: Vikram Sethi <vikrams@codeaurora.org>
>> Signed-off-by: Shanker Donthineni <shankerd@codeaurora.org>
>> ---
>> Changes sicnce v1:
>>  combined patches [v1 1/2] and [v1 2/2].
> Some general comments:
> - I preferred the previous series organization where we had the creation
> of the VFIO device first and its sysbus-fdt dynamic instantiation in a
> separate patch.
> 
> Peter requested sysbus-fdt stops growing and advised to split the fine
> into generic helpers and specific dt creation functions in separate
> files. This sounds the right moment to do it with looming new VFIO devices.
> 
> (*) Also I am now reconsidering the relevance of creating specific VFIO
> devices per compat string. At the begining of VFIO QEMU integration
> history we made that choice, advised by Alex (Graf), considering the
> QEMU VFIO device could not be generic. With a little more experience now
> we could see the specialization is currently done in the dt creation
> function (sysbus-fdt) and in the kernel reset module. So I would now
> advocate using a non abstract base VFIO device that could be
> instantiated passing its compat string as property. Creating
> hw/vfio/qcom-hidma.c and include/hw/vfio/vfio-qcom-hidma.h then would
> become useless. Alex, what is your feeling now?

Back when we set up the rule we were concerned with a few things that a generic sysbus devices can’t implement properly:

  * generic reset
  * power control
  * clock control

I guess the first two are mostly a matter of the in-kernel driver, not the user space one. Clock control hopefully isn’t much of a thing with real hardware ;).

So yes, if you can make a generic driver work, I’m not opposed.


Alex
Eric Auger Aug. 19, 2016, 11:43 a.m. UTC | #6
Hi Alex,

On 19/08/2016 00:35, Alexander Graf wrote:
> 
>> On 18 Aug 2016, at 05:37, Auger Eric <eric.auger@redhat.com> wrote:
>>
>> Hi Shanker,
>>
>> Adding Alex in CC for (*)
>>
>> On 14/08/2016 17:42, Shanker Donthineni wrote:
>>> This patch introduces the Qualcomm Technologies, Inc HIDMA device and
>>> allows passthrough the host HIDMA device to a guest machine using the
>>> vfio-platform framework.
>>>
>>> A platform device tree node is created for the guest machine which
>>> contains the compat string 'qcom,hidma-1.0', mmio regions, active high
>>> SPIs, and an optional property dma-coherent.
>>>
>>> Signed-off-by: Vikram Sethi <vikrams@codeaurora.org>
>>> Signed-off-by: Shanker Donthineni <shankerd@codeaurora.org>
>>> ---
>>> Changes sicnce v1:
>>>  combined patches [v1 1/2] and [v1 2/2].
>> Some general comments:
>> - I preferred the previous series organization where we had the creation
>> of the VFIO device first and its sysbus-fdt dynamic instantiation in a
>> separate patch.
>>
>> Peter requested sysbus-fdt stops growing and advised to split the fine
>> into generic helpers and specific dt creation functions in separate
>> files. This sounds the right moment to do it with looming new VFIO devices.
>>
>> (*) Also I am now reconsidering the relevance of creating specific VFIO
>> devices per compat string. At the begining of VFIO QEMU integration
>> history we made that choice, advised by Alex (Graf), considering the
>> QEMU VFIO device could not be generic. With a little more experience now
>> we could see the specialization is currently done in the dt creation
>> function (sysbus-fdt) and in the kernel reset module. So I would now
>> advocate using a non abstract base VFIO device that could be
>> instantiated passing its compat string as property. Creating
>> hw/vfio/qcom-hidma.c and include/hw/vfio/vfio-qcom-hidma.h then would
>> become useless. Alex, what is your feeling now?
> 
> Back when we set up the rule we were concerned with a few things that a generic sysbus devices can’t implement properly:
> 
>   * generic reset
>   * power control
>   * clock control
> 
> I guess the first two are mostly a matter of the in-kernel driver, not the user space one. Clock control hopefully isn’t much of a thing with real hardware ;).
> 
> So yes, if you can make a generic driver work, I’m not opposed.

Thank you for the confirmation!

Best Regards

Eric
> 
> 
> Alex
>
Shanker Donthineni Aug. 19, 2016, 4:52 p.m. UTC | #7
Eric/Alex,

Seems everyone was agreed, and add support for a generic vfio platform 
device class. I'm going to drop this HIDMA patch since the new generic 
vfio platform device class will cover.

Shanker

On 08/19/2016 06:43 AM, Auger Eric wrote:
> Hi Alex,
>
> On 19/08/2016 00:35, Alexander Graf wrote:
>>> On 18 Aug 2016, at 05:37, Auger Eric <eric.auger@redhat.com> wrote:
>>>
>>> Hi Shanker,
>>>
>>> Adding Alex in CC for (*)
>>>
>>> On 14/08/2016 17:42, Shanker Donthineni wrote:
>>>> This patch introduces the Qualcomm Technologies, Inc HIDMA device and
>>>> allows passthrough the host HIDMA device to a guest machine using the
>>>> vfio-platform framework.
>>>>
>>>> A platform device tree node is created for the guest machine which
>>>> contains the compat string 'qcom,hidma-1.0', mmio regions, active high
>>>> SPIs, and an optional property dma-coherent.
>>>>
>>>> Signed-off-by: Vikram Sethi <vikrams@codeaurora.org>
>>>> Signed-off-by: Shanker Donthineni <shankerd@codeaurora.org>
>>>> ---
>>>> Changes sicnce v1:
>>>>   combined patches [v1 1/2] and [v1 2/2].
>>> Some general comments:
>>> - I preferred the previous series organization where we had the
> creation
>>> of the VFIO device first and its sysbus-fdt dynamic instantiation in a
>>> separate patch.
>>>
>>> Peter requested sysbus-fdt stops growing and advised to split the fine
>>> into generic helpers and specific dt creation functions in separate
>>> files. This sounds the right moment to do it with looming new VFIO
> devices.
>>> (*) Also I am now reconsidering the relevance of creating specific VFIO
>>> devices per compat string. At the begining of VFIO QEMU integration
>>> history we made that choice, advised by Alex (Graf), considering the
>>> QEMU VFIO device could not be generic. With a little more experience
> now
>>> we could see the specialization is currently done in the dt creation
>>> function (sysbus-fdt) and in the kernel reset module. So I would now
>>> advocate using a non abstract base VFIO device that could be
>>> instantiated passing its compat string as property. Creating
>>> hw/vfio/qcom-hidma.c and include/hw/vfio/vfio-qcom-hidma.h then would
>>> become useless. Alex, what is your feeling now?
>> Back when we set up the rule we were concerned with a few things that a
> generic sysbus devices can’t implement properly:
>>    * generic reset
>>    * power control
>>    * clock control
>>
>> I guess the first two are mostly a matter of the in-kernel driver, not
> the user space one. Clock control hopefully isn’t much of a thing with
> real hardware ;).
>> So yes, if you can make a generic driver work, I’m not opposed.
> Thank you for the confirmation!
>
> Best Regards
>
> Eric
>>
>> Alex
>>
diff mbox

Patch

diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c
index 5debb33..bdf8cbb 100644
--- a/hw/arm/sysbus-fdt.c
+++ b/hw/arm/sysbus-fdt.c
@@ -27,6 +27,7 @@ 
 #include "qemu-common.h"
 #ifdef CONFIG_LINUX
 #include <linux/vfio.h>
+#include <sys/ioctl.h>
 #endif
 #include "hw/arm/sysbus-fdt.h"
 #include "qemu/error-report.h"
@@ -36,6 +37,7 @@ 
 #include "hw/vfio/vfio-platform.h"
 #include "hw/vfio/vfio-calxeda-xgmac.h"
 #include "hw/vfio/vfio-amd-xgbe.h"
+#include "hw/vfio/vfio-qcom-hidma.h"
 #include "hw/arm/fdt.h"
 
 /*
@@ -262,6 +264,70 @@  static int add_calxeda_midway_xgmac_fdt_node(SysBusDevice *sbdev, void *opaque)
     return 0;
 }
 
+/**
+ * add_qcom_hidma_fdt_node
+ *
+ * Generates a simple node with following properties:
+ * compatible string, regs, active-high interrupts, and optional dma-coherent
+ */
+static int add_qcom_hidma_fdt_node(SysBusDevice *sbdev, void *opaque)
+{
+    VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
+    struct VFIOGroup *group = vdev->vbasedev.group;
+    VFIODevice *vbasedev = &vdev->vbasedev;
+    PlatformBusFDTData *data = opaque;
+    const char *parent_node = data->pbus_node_name;
+    PlatformBusDevice *pbus = data->pbus;
+    uint32_t *irq_attr, *reg_attr;
+    uint64_t mmio_base, irq_number;
+    void *fdt = data->fdt;
+    int compat_str_len, i, ret;
+    char *nodename;
+
+    mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
+    nodename = g_strdup_printf("%s/%s@%" PRIx64, parent_node,
+                               vbasedev->name, mmio_base);
+    assert(nodename);
+    qemu_fdt_add_subnode(fdt, nodename);
+
+    compat_str_len = strlen(vdev->compat) + 1;
+    qemu_fdt_setprop(fdt, nodename, "compatible",
+                          vdev->compat, compat_str_len);
+
+    /* Check if the DMA cache coherency was enabled in IOMMU */
+    ret = ioctl(group->container->fd, VFIO_CHECK_EXTENSION, VFIO_DMA_CC_IOMMU);
+    if (ret > 0) {
+        qemu_fdt_setprop(fdt, nodename, "dma-coherent", "", 0);
+    }
+
+    reg_attr = g_new(uint32_t, vbasedev->num_regions * 2);
+    assert(reg_attr);
+    for (i = 0; i < vbasedev->num_regions; i++) {
+        mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, i);
+        reg_attr[2 * i] = cpu_to_be32(mmio_base);
+        reg_attr[2 * i + 1] = cpu_to_be32(
+                                memory_region_size(vdev->regions[i]->mem));
+    }
+    qemu_fdt_setprop(fdt, nodename, "reg", reg_attr,
+                     vbasedev->num_regions * 2 * sizeof(uint32_t));
+
+    irq_attr = g_new(uint32_t, vbasedev->num_irqs * 3);
+    assert(irq_attr);
+    for (i = 0; i < vbasedev->num_irqs; i++) {
+        irq_number = platform_bus_get_irqn(pbus, sbdev , i)
+                         + data->irq_start;
+        irq_attr[3 * i] = cpu_to_be32(GIC_FDT_IRQ_TYPE_SPI);
+        irq_attr[3 * i + 1] = cpu_to_be32(irq_number);
+        irq_attr[3 * i + 2] = cpu_to_be32(GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+    }
+    qemu_fdt_setprop(fdt, nodename, "interrupts",
+                     irq_attr, vbasedev->num_irqs * 3 * sizeof(uint32_t));
+    g_free(irq_attr);
+    g_free(reg_attr);
+    g_free(nodename);
+    return 0;
+}
+
 /* AMD xgbe properties whose values are copied/pasted from host */
 static HostProperty amd_xgbe_copied_properties[] = {
     {"compatible", false},
@@ -420,6 +486,7 @@  static const NodeCreationPair add_fdt_node_functions[] = {
 #ifdef CONFIG_LINUX
     {TYPE_VFIO_CALXEDA_XGMAC, add_calxeda_midway_xgmac_fdt_node},
     {TYPE_VFIO_AMD_XGBE, add_amd_xgbe_fdt_node},
+    {TYPE_VFIO_QCOM_HIDMA, add_qcom_hidma_fdt_node},
 #endif
     {"", NULL}, /* last element */
 };
diff --git a/hw/vfio/Makefile.objs b/hw/vfio/Makefile.objs
index c25e32b..ac38c8f 100644
--- a/hw/vfio/Makefile.objs
+++ b/hw/vfio/Makefile.objs
@@ -5,4 +5,5 @@  obj-$(CONFIG_SOFTMMU) += platform.o
 obj-$(CONFIG_SOFTMMU) += calxeda-xgmac.o
 obj-$(CONFIG_SOFTMMU) += amd-xgbe.o
 obj-$(CONFIG_SOFTMMU) += spapr.o
+obj-$(CONFIG_SOFTMMU) += qcom-hidma.o
 endif
diff --git a/hw/vfio/qcom-hidma.c b/hw/vfio/qcom-hidma.c
new file mode 100644
index 0000000..ddb3c34
--- /dev/null
+++ b/hw/vfio/qcom-hidma.c
@@ -0,0 +1,58 @@ 
+/*
+ * Qualcomm Technologies, Inc VFIO HiDMA platform device
+ *
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "qemu/osdep.h"
+#include "hw/vfio/vfio-qcom-hidma.h"
+
+static void qcom_hidma_realize(DeviceState *dev, Error **errp)
+{
+    VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(dev);
+    VFIOQcomHidmaDeviceClass *k = VFIO_QCOM_HIDMA_DEVICE_GET_CLASS(dev);
+
+    vdev->compat = g_strdup("qcom,hidma-1.0");
+
+    k->parent_realize(dev, errp);
+}
+
+static const VMStateDescription vfio_platform_vmstate = {
+    .name = TYPE_VFIO_QCOM_HIDMA,
+    .unmigratable = 1,
+};
+
+static void vfio_qcom_hidma_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VFIOQcomHidmaDeviceClass *vcxc = VFIO_QCOM_HIDMA_DEVICE_CLASS(klass);
+
+    vcxc->parent_realize = dc->realize;
+    dc->realize = qcom_hidma_realize;
+    dc->desc = "VFIO QCOM HIDMA";
+    dc->vmsd = &vfio_platform_vmstate;
+}
+
+static const TypeInfo vfio_qcom_hidma_dev_info = {
+    .name = TYPE_VFIO_QCOM_HIDMA,
+    .parent = TYPE_VFIO_PLATFORM,
+    .instance_size = sizeof(VFIOQcomHidmaDevice),
+    .class_init = vfio_qcom_hidma_class_init,
+    .class_size = sizeof(VFIOQcomHidmaDeviceClass),
+};
+
+static void register_qcom_hidma_dev_type(void)
+{
+    type_register_static(&vfio_qcom_hidma_dev_info);
+}
+
+type_init(register_qcom_hidma_dev_type)
diff --git a/include/hw/vfio/vfio-qcom-hidma.h b/include/hw/vfio/vfio-qcom-hidma.h
new file mode 100644
index 0000000..23cd66c
--- /dev/null
+++ b/include/hw/vfio/vfio-qcom-hidma.h
@@ -0,0 +1,50 @@ 
+/*
+ * Qualcomm Technologies, Inc VFIO HiDMA platform device
+ *
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef HW_VFIO_VFIO_QCOM_HIDMA_H
+#define HW_VFIO_VFIO_QCOM_HIDMA_H
+
+#include "hw/vfio/vfio-platform.h"
+
+#define TYPE_VFIO_QCOM_HIDMA "vfio-qcom-hidma"
+
+/**
+ * This device exposes:
+ * - MMIO regions corresponding to its register space
+ * - Active high IRQs
+ * - Optional property 'dma-coherent'
+ */
+typedef struct VFIOQcomHidmaDevice {
+    VFIOPlatformDevice vdev;
+} VFIOQcomHidmaDevice;
+
+typedef struct VFIOQcomHidmaDeviceClass {
+    /*< private >*/
+    VFIOPlatformDeviceClass parent_class;
+    /*< public >*/
+    DeviceRealize parent_realize;
+} VFIOQcomHidmaDeviceClass;
+
+#define VFIO_QCOM_HIDMA_DEVICE(obj) \
+     OBJECT_CHECK(VFIOQcomHidmaDevice, (obj), TYPE_VFIO_QCOM_HIDMA)
+#define VFIO_QCOM_HIDMA_DEVICE_CLASS(klass) \
+     OBJECT_CLASS_CHECK(VFIOQcomHidmaDeviceClass, (klass), \
+                        TYPE_VFIO_QCOM_HIDMA)
+#define VFIO_QCOM_HIDMA_DEVICE_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(VFIOQcomHidmaDeviceClass, (obj), \
+                      TYPE_VFIO_QCOM_HIDMA)
+
+#endif