All of lore.kernel.org
 help / color / mirror / Atom feed
From: Julien Grall <julien.grall@citrix.com>
To: vijay.kilari@gmail.com, Ian.Campbell@citrix.com,
	julien.grall@citrix.com, stefano.stabellini@eu.citrix.com,
	stefano.stabellini@citrix.com, tim@xen.org,
	xen-devel@lists.xen.org
Cc: Prasun.Kapoor@caviumnetworks.com,
	Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>,
	manish.jaggi@caviumnetworks.com
Subject: Re: [RFC PATCH v3 08/18] xen/arm: vITS: Add virtual ITS driver
Date: Tue, 23 Jun 2015 17:39:01 +0100	[thread overview]
Message-ID: <55898BA5.7040801@citrix.com> (raw)
In-Reply-To: <1434974517-12136-9-git-send-email-vijay.kilari@gmail.com>

Hi Vijay,

On 22/06/15 13:01, vijay.kilari@gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> 
> This patch introduces virtual ITS driver with following
> functionality
>  - Introduces helper functions to manage device table and
>    ITT table in guest memory
>  - Helper function to handle virtual ITS devices assigned
>    to domain
> 
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> ---
>  xen/arch/arm/Makefile         |    1 +
>  xen/arch/arm/vgic-v3-its.c    |  266 +++++++++++++++++++++++++++++++++++++++++
>  xen/include/asm-arm/domain.h  |    2 +
>  xen/include/asm-arm/gic-its.h |   49 ++++++++
>  4 files changed, 318 insertions(+)
> 
> diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
> index 1821ed2..8590846 100644
> --- a/xen/arch/arm/Makefile
> +++ b/xen/arch/arm/Makefile
> @@ -33,6 +33,7 @@ obj-y += traps.o
>  obj-y += vgic.o vgic-v2.o
>  obj-$(CONFIG_ARM_64) += vgic-v3.o
>  obj-$(CONFIG_ARM_64) += gic-v3-its.o
> +obj-$(CONFIG_ARM_64) += vgic-v3-its.o

I would prefer to the vgic-v3-its code not compiled until you finish to
implement it rather than having every function exported while it should
be static.

>  obj-y += vtimer.o
>  obj-y += vuart.o
>  obj-y += hvm.o
> diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
> new file mode 100644
> index 0000000..ea52a87
> --- /dev/null
> +++ b/xen/arch/arm/vgic-v3-its.c

[..]

> +/* GITS register definitions */
> +#define VITS_GITS_TYPER_HCC       (0xffU << 24)

Where does this value comes from? The number of supported collection
should be the maximum number of VCPUs supported by the domain.

Note that the hardware can only hold 256 collections, all the other
requires provisioning. But it's fine for now, although a BUILD_BUG_ON in
the vGIC code would be nice.

> +#define VITS_GITS_TYPER_PTA_SHIFT (19)
> +#define VITS_GITS_DEV_BITS        (0x14U << 13)
> +#define VITS_GITS_ID_BITS         (0x13U << 8)

Where do those values come from? This needs at least to come from the
hardware GIC configuration if we plan to only support DOM0 for now.

> +#define VITS_GITS_ITT_SIZE        (0x7U << 4)

The name is misleading, this is not the size of the ITT but the value to
store in the GITS_TYPER register.

> +#define VITS_GITS_DISTRIBUTED     (0x1U << 3)

Why? This bit is implementation defined in the spec.

> +#define VITS_GITS_PLPIS           (0x1U << 0)

For all these defines, why do you hardcode the shift rather using
GITS_TYPER_* you provide in patch #5? It would make the code more easier
to understand.

> +
> +/* GITS_PIDRn register values for ARM implementations */
> +#define GITS_PIDR0_VAL            (0x94)
> +#define GITS_PIDR1_VAL            (0xb4)
> +#define GITS_PIDR2_VAL            (0x3b)
> +#define GITS_PIDR3_VAL            (0x00)
> +#define GITS_PIDR4_VAL            (0x04)
> +
> +// #define DEBUG_ITS
> +
> +#ifdef DEBUG_ITS
> +# define DPRINTK(fmt, args...) dprintk(XENLOG_DEBUG, fmt, ##args)
> +#else
> +# define DPRINTK(fmt, args...) do {} while ( 0 )
> +#endif
> +
> +#ifdef DEBUG_ITS
> +static void dump_cmd(its_cmd_block *cmd)
> +{
> +    printk("CMD[0] = 0x%lx CMD[1] = 0x%lx CMD[2] = 0x%lx CMD[3] = 0x%lx\n",
> +           cmd->raw_cmd[0], cmd->raw_cmd[1], cmd->raw_cmd[2], cmd->raw_cmd[3]);
> +}
> +#endif
> +
> +/* ITS device table helper functions */
> +int vits_vdevice_entry(struct domain *d, uint32_t dev_id,
> +                       struct vdevice_table *entry, int set)

Any functions not exported should be static. I won't repeat for all the
others within this file.

Also, please use bool_t for set.

> +{
> +    uint64_t offset;
> +    paddr_t dt_entry;
> +    struct page_info *page;
> +    p2m_type_t p2mt;
> +    void *p;
> +
> +    offset = dev_id * sizeof(struct vdevice_table);
> +    if ( offset > d->arch.vits->dt_size )

If you gonna let the guest to write deci

> +    {
> +        dprintk(XENLOG_G_ERR,
> +                "vITS:d%dv%d: Out of range offset 0x%lx id 0x%x size 0x%lx\n",

You can use %pv to print the domain/vcpuid (see an example in vgic-v3.c).

Also, all the value can be printed in decimal because we have to use
them for addition...

> +                d->domain_id, current->vcpu_id, offset, dev_id,

Please don't mix d and current.

> +                d->arch.vits->dt_size);
> +        return -EINVAL;
> +    }
> +
> +    dt_entry = d->arch.vits->dt_ipa + offset;
> +
> +    page = get_page_from_gfn(d, paddr_to_pfn(dt_entry), &p2mt, P2M_ALLOC);
> +    if ( !page )
> +    {
> +        dprintk(XENLOG_G_ERR, "vITS:d%dv%d Failed to get VITT device table\n",
> +                d->domain_id, current->vcpu_id);
> +        return -EINVAL;
> +    }
> +
> +    if ( !p2m_is_ram(p2mt) )
> +    {
> +        put_page(page);
> +        dprintk(XENLOG_G_ERR, "vITS:d%dv%d with wrong attributes\n",
> +                d->domain_id, current->vcpu_id);
> +        return -EINVAL;
> +        return -EINVAL;

Duplicate "return -EINVAL".

> +    }
> +
> +    p = __map_domain_page(page);
> +    /* Offset within the mapped page */
> +    offset = dt_entry & (PAGE_SIZE - 1);
> +
> +    if ( set )
> +        memcpy(p + offset, entry, sizeof(struct vdevice_table));
> +    else
> +        memcpy(entry, p + offset, sizeof(struct vdevice_table));
> +
> +    unmap_domain_page(p);
> +    put_page(page);
> +
> +    return 0;
> +}
> +
> +int vits_set_vdevice_entry(struct domain *d, uint32_t devid,
> +                           struct vdevice_table *entry)
> +{
> +    return vits_vdevice_entry(d, devid, entry, 1);  
> +}
> +
> +int vits_get_vdevice_entry(struct domain *d, uint32_t devid,
> +                           struct vdevice_table *entry)
> +{
> +    return vits_vdevice_entry(d, devid, entry, 0);  
> +}
> +
> +int vits_vitt_entry(struct domain *d, uint32_t devid,
> +                    uint32_t event, struct vitt *entry, int set)
> +{
> +    struct vdevice_table dt_entry;
> +    struct page_info *page;
> +    paddr_t vitt_entry;
> +    p2m_type_t p2mt;
> +    uint64_t offset;
> +    void *p;
> +
> +    if ( vits_get_vdevice_entry(d, devid, &dt_entry) )
> +    {
> +        dprintk(XENLOG_G_ERR, "vITS:d%dv%d Fail to get vdevice for dev 0x%x\n",
> +                d->domain_id, current->vcpu_id, devid);
> +        return -EINVAL;
> +    }
> +
> +    /* dt_entry is validated when read */
> +    offset = event * sizeof(struct vitt);
> +    if ( offset > dt_entry.vitt_size )
> +    {
> +        dprintk(XENLOG_G_ERR, "vITS:d%dv%d ITT out of range\n",
> +                d->domain_id, current->vcpu_id);
> +        return -EINVAL;
> +    }
> +   
> +    vitt_entry = dt_entry.vitt_ipa + offset;
> +    page = get_page_from_gfn(d, paddr_to_pfn(vitt_entry), &p2mt, P2M_ALLOC);
> +    if ( !page )
> +    {
> +        dprintk(XENLOG_G_ERR, "vITS:d%dv%d Failed to get VITT device table\n",
> +                d->domain_id, current->vcpu_id);
> +        return -EINVAL;
> +    }
> +
> +    if ( !p2m_is_ram(p2mt) )
> +    {
> +        put_page(page);
> +        dprintk(XENLOG_G_ERR, "vITS:d%dv%d with wrong attributes\n",
> +                d->domain_id, current->vcpu_id);
> +        return -EINVAL;
> +    }
> +
> +    p = __map_domain_page(page);
> +    /* Offset within the mapped page */
> +    offset = vitt_entry & (PAGE_SIZE - 1);
> +
> +    if ( set )
> +        memcpy(p + offset, entry, sizeof(struct vitt));
> +    else
> +        memcpy(entry, p + offset, sizeof(struct vitt));
> +
> +    unmap_domain_page(p);
> +    put_page(page);

The code to transfer the data is exactly the same as vits_vdevice_entry
except the size of the copy. Can you make an helper? It would avoid
duplicate code.

> +
> +    return 0;
> +}
> +
> +int vits_set_vitt_entry(struct domain *d, uint32_t devid,
> +                        uint32_t event, struct vitt *entry)
> +{
> +    return vits_vitt_entry(d, devid, event, entry, 1);  
> +}
> +
> +int vits_get_vitt_entry(struct domain *d, uint32_t devid,
> +                        uint32_t event, struct vitt *entry)
> +{
> +    return vits_vitt_entry(d, devid, event, entry, 0);
> +}
> +
> +/* RB-tree helpers for vits_device attached to a domain */
> +struct vits_device * find_vits_device(struct rb_root *root, uint32_t devid)

Coding style: vits_device *find_

> +{
> +    struct rb_node *node = root->rb_node;
> +
> +    while ( node )
> +    {
> +        struct vits_device *dev;
> +
> +        dev = container_of(node, struct vits_device, node);
> +
> +        if ( devid < dev->vdevid )
> +            node = node->rb_left;
> +        else if ( devid > dev->vdevid )
> +            node = node->rb_right;
> +        else
> +            return dev;
> +    }
> +
> +    return NULL;
> +}
> +
> +int insert_vits_device(struct rb_root *root, struct vits_device *dev)
> +{
> +    struct rb_node **new, *parent;
> +
> +    new = &root->rb_node;
> +    parent = NULL;
> +    while ( *new )
> +    {
> +        struct vits_device *this;
> +
> +        this  = container_of(*new, struct vits_device, node);
> +
> +        parent = *new;
> +        if ( dev->vdevid < this->vdevid )
> +            new = &((*new)->rb_left);
> +        else if ( dev->vdevid > this->vdevid )
> +            new = &((*new)->rb_right);
> +        else
> +            return -EEXIST;
> +    }
> +
> +    rb_link_node(&dev->node, parent, new);
> +    rb_insert_color(&dev->node, root);
> +
> +    return 0;
> +}
> +
> +int remove_vits_device(struct rb_root *root, struct vits_device *dev)

This function can be void.

> +{
> +    if ( dev )
> +        rb_erase(&dev->node, root);
> +
> +    return 0;
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
> index f1a087e..da73cf5 100644
> --- a/xen/include/asm-arm/domain.h
> +++ b/xen/include/asm-arm/domain.h
> @@ -115,6 +115,8 @@ struct arch_domain
>  #endif
>      } vgic;
>  
> +    struct vgic_its *vits;
> +
>      struct vuart {
>  #define VUART_BUF_SIZE 128
>          char                        *buf;
> diff --git a/xen/include/asm-arm/gic-its.h b/xen/include/asm-arm/gic-its.h
> index a47cf26..a1099a1 100644
> --- a/xen/include/asm-arm/gic-its.h
> +++ b/xen/include/asm-arm/gic-its.h
> @@ -31,6 +31,35 @@ struct its_collection {
>      u16 col_id;
>  };
>  
> +/*
> + * Per domain virtual ITS structure.
> + * One per Physical ITS node available for the domain

Left over of the previous version? AFAICT, the agreed design [1] only
expose one vITS per domain.


> + */
> +struct vgic_its
> +{
> +   spinlock_t lock;
> +   /* Command queue base */
> +   paddr_t cmd_base;
> +   /* Command queue write pointer */
> +   paddr_t cmd_write;
> +   /* Command queue write saved pointer */
> +   paddr_t cmd_write_save;
> +   /* Command queue read pointer */
> +   paddr_t cmd_read;
> +   /* Command queue size */
> +   unsigned long cmd_qsize;
> +   /* ITS physical node */
> +   struct its_node *its;

This is not necessary.

> +   /* vITT device table ipa */
> +   paddr_t dt_ipa;
> +   /* vITT device table size */
> +   uint64_t dt_size;
> +   /* Radix-tree root of devices attached to this domain */
> +   struct rb_root dev_root;
> +   /* collections mapped */
> +   struct its_collection *collections;
> +};
> +
>  /* ITS command structures */
>  typedef struct __packed {
>      u64 cmd:8;
> @@ -200,6 +229,26 @@ struct its_device {
>      struct rb_node          node;
>  };
>  
> +struct vits_device {
> +    uint32_t vdevid;
> +    uint32_t pdevid;
> +    struct its_device *its_dev;
> +    struct rb_node node;
> +};

We spoke about a specific structure in the design [2] but you introduced
a new one. Why?

Having everything in the its_device would help to catch a device
attached to 2 different domains...

Also, the field pdevid is not vits specific but its.

> +
> +struct vdevice_table {
> +    uint64_t vitt_ipa;
> +    uint32_t vitt_size;
> +    uint32_t padding;
> +};
> +
> +struct vitt {
> +    uint16_t valid:1;
> +    uint16_t pad:15;
> +    uint16_t vcollection;
> +    uint32_t vlpi;
> +};

You forgot to add the BUILD_BUG_ON for each structure here. It's very
important as you decided to hardcoded the value in the registers.

> +
>  static inline uint8_t its_decode_cmd(its_cmd_block *cmd)
>  {
>      return cmd->raw_cmd[0] & 0xff;
> 

Regards,

[1]
http://xenbits.xensource.com/people/ianc/vits/draftF.html#vits-to-pits-mapping
[2]
http://xenbits.xensource.com/people/ianc/vits/draftF.html#vits-to-pits-mapping


-- 
Julien Grall

  reply	other threads:[~2015-06-23 16:39 UTC|newest]

Thread overview: 88+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-22 12:01 [RFC PATCH v3 00/18] Add ITS support vijay.kilari
2015-06-22 12:01 ` [RFC PATCH v3 01/18] xen/arm: Add bitmap_find_next_zero_area helper function vijay.kilari
2015-06-22 14:14   ` Julien Grall
2015-06-22 12:01 ` [RFC PATCH v3 02/18] xen: Add log2 functionality vijay.kilari
2015-06-22 13:17   ` Jan Beulich
2015-06-24 13:05     ` Vijay Kilari
2015-06-24 13:21       ` Jan Beulich
2015-06-22 12:01 ` [RFC PATCH v3 03/18] xen: console: Add ratelimit support for error message vijay.kilari
2015-06-22 13:21   ` Jan Beulich
2015-06-25 13:14     ` Vijay Kilari
2015-06-25 13:21       ` Andrew Cooper
2015-06-25 13:31       ` Jan Beulich
2015-06-22 12:01 ` [RFC PATCH v3 04/18] xen/arm: gicv3: Refactor redistributor information vijay.kilari
2015-06-22 15:00   ` Julien Grall
2015-06-29 11:09   ` Ian Campbell
2015-06-22 12:01 ` [RFC PATCH v3 05/18] xen/arm: ITS: Port ITS driver to xen vijay.kilari
2015-06-22 17:16   ` Julien Grall
2015-06-26  9:19     ` Vijay Kilari
2015-06-26  9:52       ` Julien Grall
2015-06-29 11:39   ` Ian Campbell
2015-06-29 15:43     ` Vijay Kilari
2015-06-29 15:47       ` Vijay Kilari
2015-06-29 16:49         ` Ian Campbell
2015-06-22 12:01 ` [RFC PATCH v3 06/18] xen/arm: ITS: Add helper functions to manage its_devices vijay.kilari
2015-06-23 10:21   ` Julien Grall
2015-06-22 12:01 ` [RFC PATCH v3 07/18] xen/arm: ITS: implement hw_irq_controller for LPIs vijay.kilari
2015-06-23 14:32   ` Julien Grall
2015-06-26 12:54     ` Vijay Kilari
2015-06-26 15:05       ` Julien Grall
2015-06-29 11:53         ` Ian Campbell
2015-06-29 12:46           ` Julien Grall
2015-07-02 12:15         ` Vijay Kilari
2015-06-26 14:25     ` Vijay Kilari
2015-06-26 15:15       ` Julien Grall
2015-06-29 11:59     ` Ian Campbell
2015-07-02 12:21       ` Vijay Kilari
2015-07-02 12:35         ` Ian Campbell
2015-07-02 12:44           ` Vijay Kilari
2015-07-02 12:59             ` Ian Campbell
2015-07-02 16:11               ` Julien Grall
2015-06-22 12:01 ` [RFC PATCH v3 08/18] xen/arm: vITS: Add virtual ITS driver vijay.kilari
2015-06-23 16:39   ` Julien Grall [this message]
2015-07-02 13:33     ` Vijay Kilari
2015-07-02 14:30       ` Ian Campbell
2015-06-24  9:20   ` Julien Grall
2015-06-29 12:13   ` Ian Campbell
2015-06-22 12:01 ` [RFC PATCH v3 09/18] xen/arm: ITS: Add virtual ITS commands support vijay.kilari
2015-06-24 10:29   ` Julien Grall
2015-06-29 12:16     ` Ian Campbell
2015-06-29 12:18   ` Ian Campbell
2015-06-29 12:23   ` Ian Campbell
2015-07-03  6:50     ` Vijay Kilari
2015-07-03  8:41       ` Ian Campbell
2015-06-22 12:01 ` [RFC PATCH v3 10/18] xen/arm: ITS: Add APIs to add and assign device vijay.kilari
2015-06-24 11:38   ` Julien Grall
2015-06-29 12:25     ` Ian Campbell
2015-06-29 12:29   ` Ian Campbell
2015-07-02  8:40     ` Vijay Kilari
2015-07-02  9:01       ` Ian Campbell
2015-07-02 10:30         ` Julien Grall
2015-06-22 12:01 ` [RFC PATCH v3 11/18] xen/arm: ITS: Add GITS registers emulation vijay.kilari
2015-06-26 12:51   ` Julien Grall
2015-07-08 12:11   ` Ian Campbell
2015-06-22 12:01 ` [RFC PATCH v3 12/18] xen/arm: ITS: Add GICR register emulation vijay.kilari
2015-06-22 12:01 ` [RFC PATCH v3 13/18] xen/arm: ITS: Add irq descriptors for LPIs vijay.kilari
2015-06-29 12:58   ` Ian Campbell
2015-06-29 13:11     ` Julien Grall
2015-07-07 11:00       ` Vijay Kilari
2015-07-07 11:16         ` Julien Grall
2015-07-07 15:50           ` Ian Campbell
2015-07-07 15:52             ` Julien Grall
2015-07-07 16:04               ` Ian Campbell
2015-06-22 12:01 ` [RFC PATCH v3 14/18] xen/arm: ITS: Initialize physical ITS vijay.kilari
2015-06-22 12:01 ` [RFC PATCH v3 15/18] xen/arm: ITS: Add domain specific ITS initialization vijay.kilari
2015-06-29 13:01   ` Ian Campbell
2015-06-22 12:01 ` [RFC PATCH v3 16/18] xen/arm: ITS: Handle LPI interrupts vijay.kilari
2015-06-29 13:03   ` Ian Campbell
2015-06-22 12:01 ` [RFC PATCH v3 17/18] xen/arm: ITS: Generate ITS node for Dom0 vijay.kilari
2015-06-29 13:06   ` Ian Campbell
2015-07-07  5:31     ` Vijay Kilari
2015-07-07  8:21       ` Julien Grall
2015-07-07 10:25         ` Vijay Kilari
2015-07-07 11:07           ` Julien Grall
2015-06-22 12:01 ` [RFC PATCH v3 18/18] xen/arm: ITS: Map ITS translation space vijay.kilari
2015-06-22 13:52 ` [RFC PATCH v3 00/18] Add ITS support Julien Grall
2015-06-22 13:56   ` Ian Campbell
2015-06-24 10:02 ` Ian Campbell
2015-06-29 13:11 ` Ian Campbell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=55898BA5.7040801@citrix.com \
    --to=julien.grall@citrix.com \
    --cc=Ian.Campbell@citrix.com \
    --cc=Prasun.Kapoor@caviumnetworks.com \
    --cc=Vijaya.Kumar@caviumnetworks.com \
    --cc=manish.jaggi@caviumnetworks.com \
    --cc=stefano.stabellini@citrix.com \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=tim@xen.org \
    --cc=vijay.kilari@gmail.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.