[Xen-devel] [RFC PATCH 12/19] xen/arm: its: Add support to emulate GICR register for LPIs

2015-03-02 Thread vijay . kilari
From: Vijaya Kumar K 

With this patch add emulation of GICR registers for LPIs.
Also add LPI property table emulation.

Domain's LPI property table is unmapped during domain init
on LPIPROPBASE update and trapped on LPI property
table read and write

Signed-off-by: Vijaya Kumar K 
---
 xen/arch/arm/vgic-v3-its.c|  156 +
 xen/arch/arm/vgic-v3.c|   64 ---
 xen/include/asm-arm/domain.h  |1 +
 xen/include/asm-arm/gic-its.h |1 +
 xen/include/asm-arm/gic.h |2 +
 xen/include/asm-arm/gic_v3_defs.h |2 +
 6 files changed, 214 insertions(+), 12 deletions(-)

diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
index 7e1cc04..48c880a 100644
--- a/xen/arch/arm/vgic-v3-its.c
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -996,6 +996,162 @@ err:
 return 0;
 }
 
+/* Search device structure and get corresponding plpi */
+int vgic_its_get_pid(struct vcpu *v, uint32_t vid, uint32_t *pid)
+{
+struct domain *d = v->domain;
+struct vits_device *dev;
+struct its_lpi_chunk *chunk;
+int i;
+
+list_for_each_entry( dev, &d->arch.vits->vits_dev_list, entry )
+{
+list_for_each_entry( chunk, &dev->hwirq_list, entry )
+{
+for ( i = 0; i < IRQS_PER_CHUNK; i++ )
+{
+if ( test_bit(i, &chunk->lpi_map) && chunk->vid[i] == vid )
+{
+*pid = chunk->pid[i];
+ return 0;
+}
+}
+}
+}
+
+return 1;
+}
+
+static int vgic_v3_gits_lpi_mmio_read(struct vcpu *v, mmio_info_t *info)
+{
+uint32_t offset;
+struct hsr_dabt dabt = info->dabt;
+struct cpu_user_regs *regs = guest_cpu_user_regs();
+register_t *r = select_user_reg(regs, dabt.reg);
+uint8_t cfg;
+
+spin_lock(&v->domain->arch.vits->lock);
+offset = info->gpa -
+ (v->domain->arch.vits->lpi_propbase & 0xf000UL);
+
+if ( offset < SZ_64K )
+{
+DPRINTK("vITS: LPI Table read offset 0x%x\n", offset );
+cfg = readb_relaxed(v->domain->arch.vits->lpi_prop_page + offset);
+*r = cfg;
+spin_unlock(&v->domain->arch.vits->lock);
+return 1;
+}
+else
+dprintk(XENLOG_ERR, "vITS: LPI Table read with wrong offset 0x%x\n",
+offset);
+
+spin_unlock(&v->domain->arch.vits->lock);
+
+return 0;
+}
+
+static int vgic_v3_gits_lpi_mmio_write(struct vcpu *v, mmio_info_t *info)
+{
+uint32_t offset;
+uint32_t pid, vid;
+uint8_t cfg;
+bool_t enable;
+struct hsr_dabt dabt = info->dabt;
+struct cpu_user_regs *regs = guest_cpu_user_regs();
+register_t *r = select_user_reg(regs, dabt.reg);
+
+spin_lock(&v->domain->arch.vits->lock);
+offset = info->gpa -
+ (v->domain->arch.vits->lpi_propbase & 0xf000UL);
+
+vid = offset + NR_GIC_LPI;
+if ( offset < SZ_64K )
+{
+DPRINTK("vITS: LPI Table write offset 0x%x\n", offset );
+if ( vgic_its_get_pid(v, vid, &pid) )
+{
+spin_unlock(&v->domain->arch.vits->lock);
+dprintk(XENLOG_ERR, "vITS: pID not found for vid %d\n", vid);
+return 0;
+}
+
+cfg = readb_relaxed(v->domain->arch.vits->lpi_prop_page + offset);
+enable = (cfg & *r) & 0x1;
+
+if ( !enable )
+ vgic_its_enable_lpis(v, pid);
+else
+ vgic_its_disable_lpis(v, pid);
+
+/* Update virtual prop page */
+writeb_relaxed((*r & 0xff),
+v->domain->arch.vits->lpi_prop_page + offset);
+
+spin_unlock(&v->domain->arch.vits->lock);
+return 1;
+}
+else
+dprintk(XENLOG_ERR, "vITS: LPI Table write with wrong offset 0x%x\n",
+offset);
+
+spin_unlock(&v->domain->arch.vits->lock);
+
+return 0;
+}
+
+static const struct mmio_handler_ops vgic_gits_lpi_mmio_handler = {
+.read_handler  = vgic_v3_gits_lpi_mmio_read,
+.write_handler = vgic_v3_gits_lpi_mmio_write,
+};
+
+int vgic_its_unmap_lpi_prop(struct vcpu *v)
+{
+paddr_t maddr;
+uint32_t lpi_size;
+int i;
+
+spin_lock(&v->domain->arch.vits->lock);
+maddr = v->domain->arch.vits->lpi_propbase & 0xf000UL;
+lpi_size = 1UL << ((v->domain->arch.vits->lpi_propbase & 0x1f) + 1);
+
+DPRINTK("vITS: Unmap guest LPI conf table maddr 0x%lx lpi_size 0x%x\n",
+ maddr, lpi_size);
+
+if ( lpi_size < SZ_64K )
+{
+spin_unlock(&v->domain->arch.vits->lock);
+dprintk(XENLOG_ERR, "vITS: LPI Prop page < 64K\n");
+return 0;
+}
+
+/* XXX: As per 4.8.9 each re-distributor shares a common LPI configuration 
table
+ * So one set of mmio handlers to manage configuration table is enough
+ */
+for ( i = 0; i < lpi_size / PAGE_SIZE; i++ )
+guest_physmap_remove_page(v->domain, paddr_to_pfn(maddr),
+gmfn

Re: [Xen-devel] [RFC PATCH 12/19] xen/arm: its: Add support to emulate GICR register for LPIs

2015-03-03 Thread Stefano Stabellini
On Mon, 2 Mar 2015, vijay.kil...@gmail.com wrote:
> From: Vijaya Kumar K 
> 
> With this patch add emulation of GICR registers for LPIs.
> Also add LPI property table emulation.
> 
> Domain's LPI property table is unmapped during domain init
> on LPIPROPBASE update and trapped on LPI property
> table read and write
> 
> Signed-off-by: Vijaya Kumar K 
> ---
>  xen/arch/arm/vgic-v3-its.c|  156 
> +
>  xen/arch/arm/vgic-v3.c|   64 ---
>  xen/include/asm-arm/domain.h  |1 +
>  xen/include/asm-arm/gic-its.h |1 +
>  xen/include/asm-arm/gic.h |2 +
>  xen/include/asm-arm/gic_v3_defs.h |2 +
>  6 files changed, 214 insertions(+), 12 deletions(-)
> 
> diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
> index 7e1cc04..48c880a 100644
> --- a/xen/arch/arm/vgic-v3-its.c
> +++ b/xen/arch/arm/vgic-v3-its.c
> @@ -996,6 +996,162 @@ err:
>  return 0;
>  }
>  
> +/* Search device structure and get corresponding plpi */
> +int vgic_its_get_pid(struct vcpu *v, uint32_t vid, uint32_t *pid)
> +{
> +struct domain *d = v->domain;
> +struct vits_device *dev;
> +struct its_lpi_chunk *chunk;
> +int i;
> +
> +list_for_each_entry( dev, &d->arch.vits->vits_dev_list, entry )
> +{
> +list_for_each_entry( chunk, &dev->hwirq_list, entry )
> +{
> +for ( i = 0; i < IRQS_PER_CHUNK; i++ )
> +{
> +if ( test_bit(i, &chunk->lpi_map) && chunk->vid[i] == vid )
> +{
> +*pid = chunk->pid[i];
> + return 0;
> +}
> +}
> +}
> +}
> +
> +return 1;
> +}
> +
> +static int vgic_v3_gits_lpi_mmio_read(struct vcpu *v, mmio_info_t *info)
> +{
> +uint32_t offset;
> +struct hsr_dabt dabt = info->dabt;
> +struct cpu_user_regs *regs = guest_cpu_user_regs();
> +register_t *r = select_user_reg(regs, dabt.reg);
> +uint8_t cfg;
> +
> +spin_lock(&v->domain->arch.vits->lock);
> +offset = info->gpa -
> + (v->domain->arch.vits->lpi_propbase & 0xf000UL);
> +
> +if ( offset < SZ_64K )
> +{
> +DPRINTK("vITS: LPI Table read offset 0x%x\n", offset );
> +cfg = readb_relaxed(v->domain->arch.vits->lpi_prop_page + offset);
> +*r = cfg;
> +spin_unlock(&v->domain->arch.vits->lock);
> +return 1;
> +}
> +else
> +dprintk(XENLOG_ERR, "vITS: LPI Table read with wrong offset 0x%x\n",
> +offset);
> +
> +spin_unlock(&v->domain->arch.vits->lock);
> +
> +return 0;
> +}
> +
> +static int vgic_v3_gits_lpi_mmio_write(struct vcpu *v, mmio_info_t *info)
> +{
> +uint32_t offset;
> +uint32_t pid, vid;
> +uint8_t cfg;
> +bool_t enable;
> +struct hsr_dabt dabt = info->dabt;
> +struct cpu_user_regs *regs = guest_cpu_user_regs();
> +register_t *r = select_user_reg(regs, dabt.reg);
> +
> +spin_lock(&v->domain->arch.vits->lock);
> +offset = info->gpa -
> + (v->domain->arch.vits->lpi_propbase & 0xf000UL);
> +
> +vid = offset + NR_GIC_LPI;
> +if ( offset < SZ_64K )
> +{
> +DPRINTK("vITS: LPI Table write offset 0x%x\n", offset );
> +if ( vgic_its_get_pid(v, vid, &pid) )
> +{
> +spin_unlock(&v->domain->arch.vits->lock);
> +dprintk(XENLOG_ERR, "vITS: pID not found for vid %d\n", vid);
> +return 0;
> +}
> +
> +cfg = readb_relaxed(v->domain->arch.vits->lpi_prop_page + offset);
> +enable = (cfg & *r) & 0x1;
> +
> +if ( !enable )
> + vgic_its_enable_lpis(v, pid);
> +else
> + vgic_its_disable_lpis(v, pid);
> +
> +/* Update virtual prop page */
> +writeb_relaxed((*r & 0xff),
> +v->domain->arch.vits->lpi_prop_page + offset);

We need to properly support priorities too.


> +spin_unlock(&v->domain->arch.vits->lock);
> +return 1;
> +}
> +else
> +dprintk(XENLOG_ERR, "vITS: LPI Table write with wrong offset 0x%x\n",
> +offset);
> +
> +spin_unlock(&v->domain->arch.vits->lock);
> +
> +return 0;
> +}
> +
> +static const struct mmio_handler_ops vgic_gits_lpi_mmio_handler = {
> +.read_handler  = vgic_v3_gits_lpi_mmio_read,
> +.write_handler = vgic_v3_gits_lpi_mmio_write,
> +};
> +
> +int vgic_its_unmap_lpi_prop(struct vcpu *v)
> +{
> +paddr_t maddr;
> +uint32_t lpi_size;
> +int i;
> +
> +spin_lock(&v->domain->arch.vits->lock);
> +maddr = v->domain->arch.vits->lpi_propbase & 0xf000UL;
> +lpi_size = 1UL << ((v->domain->arch.vits->lpi_propbase & 0x1f) + 1);
> +
> +DPRINTK("vITS: Unmap guest LPI conf table maddr 0x%lx lpi_size 0x%x\n",
> + maddr, lpi_size);
> +
> +if ( lpi_size < SZ_64K )
> +{
> +spin_unlock(&v->domain->arch.vits->lock);
> +dpri

Re: [Xen-devel] [RFC PATCH 12/19] xen/arm: its: Add support to emulate GICR register for LPIs

2015-03-04 Thread Stefano Stabellini
On Tue, 3 Mar 2015, Stefano Stabellini wrote:
> On Mon, 2 Mar 2015, vijay.kil...@gmail.com wrote:
> > @@ -94,19 +95,29 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu 
> > *v, mmio_info_t *info,
> >  switch ( gicr_reg )
> >  {
> >  case GICR_CTLR:
> > -/* We have not implemented LPI's, read zero */
> > -goto read_as_zero;
> > +/*
> > + * Enable LPI's for ITS. Direct injection of LPI
> > + * by writing to GICR_{SET,CLR}LPIR are not supported
> > + */
> 
> Is this actually a limitation that we can have? Is there a way to
> communicate to the guest OS that GICR_{SET,CLR}LPIR are not supported?

Actually the GICv3 spec says:

Note: this register is mandatory in an implementation that supports LPIs
and does not include an ITS. The register location is IMPLEMENTATION
DEFINED in an implementation that does include an ITS.

So, if we include the vITS, does this mean that we can simply make this
register disappear?


> 
> > +if ( dabt.size != DABT_WORD ) goto bad_width;
> > +vgic_lock(v);
> > +*r = v->domain->arch.vgic.gicr_ctlr;
> > +vgic_unlock(v);
> > +return 1;
> >  case GICR_IIDR:
> >  if ( dabt.size != DABT_WORD ) goto bad_width;
> >  *r = GICV3_GICR_IIDR_VAL;
> >  return 1;
> >  case GICR_TYPER:
> > -if ( dabt.size != DABT_DOUBLE_WORD ) goto bad_width;
> > -/* TBD: Update processor id in [23:8] when ITS support is added */
> > +if ( dabt.size != DABT_WORD && dabt.size != DABT_DOUBLE_WORD )
> > +goto bad_width;
> > +/* XXX: Update processor id in [23:8] if GITS_TYPER: PTA is not 
> > set */
> >  aff = (MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 3) << 56 |
> > MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 2) << 48 |
> > MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 1) << 40 |
> > MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 0) << 32);
> > +/* Set LPI support */
> > +aff |= (GICR_TYPER_DISTRIBUTED_IMP | GICR_TYPER_PLPIS);
> >  *r = aff;
> >  return 1;
> >  case GICR_STATUSR:

___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel