xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Julien Grall <julien.grall@arm.com>
To: Andre Przywara <andre.przywara@arm.com>,
	Stefano Stabellini <sstabellini@kernel.org>
Cc: xen-devel@lists.xenproject.org,
	Shanker Donthineni <shankerd@codeaurora.org>,
	Vijay Kilari <vijay.kilari@gmail.com>
Subject: Re: [PATCH v3 11/26] ARM: vGICv3: handle virtual LPI pending and property tables
Date: Tue, 4 Apr 2017 13:56:54 +0100	[thread overview]
Message-ID: <0d92de72-9f52-39c5-be30-db1289b6c16b@arm.com> (raw)
In-Reply-To: <bbd2e755-7b97-c7fd-2b90-6efbe088e30b@arm.com>

Hmmm I posted the comment on v3, rather than v4 :/. I will duplicate 
them on v4 for convenience.

Cheers,

On 04/04/17 13:55, Julien Grall wrote:
> Hi Andre,
>
> On 31/03/17 19:05, Andre Przywara wrote:
>> Allow a guest to provide the address and size for the memory regions
>> it has reserved for the GICv3 pending and property tables.
>> We sanitise the various fields of the respective redistributor
>> registers and map those pages into Xen's address space to have easy
>> access.
>>
>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>> ---
>>  xen/arch/arm/vgic-v3.c       | 136
>> +++++++++++++++++++++++++++++++++++++------
>>  xen/common/memory.c          |  61 +++++++++++++++++++
>>  xen/include/asm-arm/domain.h |   6 +-
>>  xen/include/asm-arm/vgic.h   |   2 +
>>  xen/include/xen/mm.h         |   8 +++
>>  5 files changed, 195 insertions(+), 18 deletions(-)
>>
>> diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
>> index 69572e3..7f84fbf 100644
>> --- a/xen/arch/arm/vgic-v3.c
>> +++ b/xen/arch/arm/vgic-v3.c
>> @@ -20,12 +20,14 @@
>>
>>  #include <xen/bitops.h>
>>  #include <xen/config.h>
>> +#include <xen/domain_page.h>
>>  #include <xen/lib.h>
>>  #include <xen/init.h>
>>  #include <xen/softirq.h>
>>  #include <xen/irq.h>
>>  #include <xen/sched.h>
>>  #include <xen/sizes.h>
>> +#include <xen/vmap.h>
>>  #include <asm/current.h>
>>  #include <asm/mmio.h>
>>  #include <asm/gic_v3_defs.h>
>> @@ -229,12 +231,15 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct
>> vcpu *v, mmio_info_t *info,
>>          goto read_reserved;
>>
>>      case VREG64(GICR_PROPBASER):
>> -        /* LPI's not implemented */
>> -        goto read_as_zero_64;
>> +        if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
>> +        *r = vgic_reg64_extract(v->domain->arch.vgic.rdist_propbase,
>> info);
>
> vgic_reg64_extract will likely turned into a series of non-atomic
> operation. So how do you prevent issue?
>
>> +        return 1;
>>
>>      case VREG64(GICR_PENDBASER):
>> -        /* LPI's not implemented */
>> -        goto read_as_zero_64;
>> +        if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
>> +        *r = vgic_reg64_extract(v->arch.vgic.rdist_pendbase, info);
>
> Ditto.
>
>> +        *r &= ~GICR_PENDBASER_PTZ;       /* WO, reads as 0 */
>> +        return 1;
>
> [...]
>
>>  static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu *v, mmio_info_t
>> *info,
>>                                            uint32_t gicr_reg,
>>                                            register_t r)
>>  {
>>      struct hsr_dabt dabt = info->dabt;
>> +    uint64_t reg;
>>
>>      switch ( gicr_reg )
>>      {
>> @@ -394,36 +478,54 @@ static int __vgic_v3_rdistr_rd_mmio_write(struct
>> vcpu *v, mmio_info_t *info,
>>          goto write_impl_defined;
>>
>>      case VREG64(GICR_SETLPIR):
>> -        /* LPI is not implemented */
>> +        /* LPIs without an ITS are not implemented */
>>          goto write_ignore_64;
>>
>>      case VREG64(GICR_CLRLPIR):
>> -        /* LPI is not implemented */
>> +        /* LPIs without an ITS are not implemented */
>>          goto write_ignore_64;
>>
>>      case 0x0050:
>>          goto write_reserved;
>>
>>      case VREG64(GICR_PROPBASER):
>> -        /* LPI is not implemented */
>> -        goto write_ignore_64;
>> +        if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
>> +
>> +        /* Writing PROPBASER with LPIs enabled is UNPREDICTABLE. */
>> +        if ( v->arch.vgic.flags & VGIC_V3_LPIS_ENABLED )
>
> v will point to the vCPU associated to the re-distributor. However, this
> could be updated from any vCPU. So I think there is tiny race where
> v->arch.vgic.flags may not been seen and therefore you will
>
>> +            return 1;
>> +
>> +        reg = v->domain->arch.vgic.rdist_propbase;
>> +        vgic_reg64_update(&reg, r, info);
>> +        reg = sanitize_propbaser(reg);
>> +        v->domain->arch.vgic.rdist_propbase = reg;
>
> This code could be called concurrently and I don't think this will
> behave well.
>
>> +        return 1;
>>
>>      case VREG64(GICR_PENDBASER):
>> -        /* LPI is not implemented */
>> -        goto write_ignore_64;
>> +        if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
>> +
>> +        /* Writing PENDBASER with LPIs enabled is UNPREDICTABLE. */
>> +        if ( v->arch.vgic.flags & VGIC_V3_LPIS_ENABLED )
>
> Ditto
>
>> +            return 1;
>> +
>> +        reg = v->arch.vgic.rdist_pendbase;
>> +        vgic_reg64_update(&reg, r, info);
>> +        reg = sanitize_pendbaser(reg);
>> +        v->arch.vgic.rdist_pendbase = reg;
>
> Ditto.
>
>
>> +        return 1;
>
> [...]
>
>> diff --git a/xen/common/memory.c b/xen/common/memory.c
>> index 21797ca..29ef9bb 100644
>> --- a/xen/common/memory.c
>> +++ b/xen/common/memory.c
>
> Any modification in common code should be a separate patch and have
> appropriate maintainers CCed.
>
>> @@ -1419,6 +1419,67 @@ int prepare_ring_for_helper(
>>  }
>>
>>  /*
>> + * Mark a given number of guest pages as used (by increasing their
>> refcount),
>> + * starting with the given guest address. This needs to be called
>> once before
>> + * calling (possibly repeatedly) map_one_guest_pages().
>> + * Before the domain gets destroyed, call put_guest_pages() to drop the
>> + * reference.
>> + */
>
> I was hoping that you would have taken my comments into account where
> you wrote the new functions but it seems they were ignored :/. I feel
> like it is a wasted of my time to repeat again and again comments.
>
> Both get_guest_pages and put_guest_pages are wrong because you are
> assuming the p2m mapping will never changes. This is wrong and I asked a
> forward plan for that which seems to have been skipped too...
>
>> +int get_guest_pages(struct domain *d, paddr_t gpa, unsigned int
>> nr_pages)
>
> Many comments here:
>    * please use the type gfn_t rather paddr_t,
>
>> +{
>> +    unsigned int i;
>> +    struct page_info *page;
>> +
>> +    for ( i = 0; i < nr_pages; i++ )
>> +    {
>> +        page = get_page_from_gfn(d, (gpa >> PAGE_SHIFT) + i, NULL,
>> P2M_ALLOC);
>
> Get page may return a foreign page (e.g belonging to another domain) and
> we don't want to use this type of page for ITS memory.
>
>> +        if ( !page )
>> +        {
>> +            /* Make sure we drop the references of pages we got so
>> far. */
>> +            put_guest_pages(d, gpa, i);
>> +            return -EINVAL;
>> +        }
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +void put_guest_pages(struct domain *d, paddr_t gpa, unsigned int
>> nr_pages)
>
> Same comments as above.
>
>> +{
>> +    mfn_t mfn;
>> +    int i;
>> +
>> +    p2m_read_lock(&d->arch.p2m);
>> +    for ( i = 0; i < nr_pages; i++ )
>> +    {
>> +        mfn = p2m_get_entry(&d->arch.p2m, _gfn((gpa >> PAGE_SHIFT) + i),
>> +                            NULL, NULL, NULL);
>> +        if ( mfn_eq(mfn, INVALID_MFN) )
>> +            continue;
>> +        put_page(mfn_to_page(mfn_x(mfn)));
>
> This function is completely wrong in the actual state. You assume that
> the stage-2 page table has not been modified by the guest between
> get_guest_pages and put_guest_pages. If it has been modified, you may
> remove a reference on the wrong page.
>
> Furthermore, it is likely an error to have the mfn not valid in this case.
>
> As we discussed earlier, the way forward is to protect the pages. It is
> not mandatory for DOM0, but a comment in the code is necessary to
> explain what is missing.
>
>> +    }
>> +    p2m_read_unlock(&d->arch.p2m);
>> +}
>> +
>> +/*
>> + * Provides easy access to guest memory by "mapping" one page of it into
>> + * Xen's VA space. In fact it relies on the memory being already mapped
>> + * and just provides a pointer to it.
>> + */
>> +void *map_one_guest_page(struct domain *d, paddr_t guest_addr)
>> +{
>> +    void *ptr = map_domain_page(_mfn(guest_addr >> PAGE_SHIFT));
>
> This might be correct for DOM0 but will not work for guest. Even if you
> don't support guest right now, we should really avoid such assumption in
> the code. It will likely mean quite a lot of rework which I'd like to
> see now.
>
> Looking at how you use this, it would make more sense to have an helper
> to copy from the guest memory to a buffer. I think this is not the first
> time I am suggesting that.
>
> I think this would also avoid protecting the guest memory.
>
> For an example of what I meant give a look to the vITS series sent by
> Cavium a year ago:
>
> https://patchwork.kernel.org/patch/8177251/
>
>> +
>> +    return ptr + (guest_addr & ~PAGE_MASK);
>> +}
>> +
>> +/* "Unmap" a previously mapped guest page. Could be optimized away. */
>> +void unmap_one_guest_page(void *va)
>> +{
>> +    unmap_domain_page(((uintptr_t)va & PAGE_MASK));
>> +}
>> +
>> +/*
>>   * Local variables:
>>   * mode: C
>>   * c-file-style: "BSD"
>> diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
>> index a83904a..ad4dfdc 100644
>> --- a/xen/include/asm-arm/domain.h
>> +++ b/xen/include/asm-arm/domain.h
>> @@ -110,6 +110,8 @@ struct arch_domain
>>          } *rdist_regions;
>>          int nr_regions;                     /* Number of rdist
>> regions */
>>          uint32_t rdist_stride;              /* Re-Distributor stride */
>> +        unsigned int nr_lpis;
>
> You switched to "unsigned long" in the gic-v3-its code, but still keep
> "unsigned int" here.
>
> Why that?
>
> [...]
>
>> diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
>> index eabdf91..9f48e9a 100644
>> --- a/xen/include/asm-arm/vgic.h
>> +++ b/xen/include/asm-arm/vgic.h
>> @@ -310,6 +310,8 @@ extern void register_vgic_ops(struct domain *d,
>> const struct vgic_ops *ops);
>>  int vgic_v2_init(struct domain *d, int *mmio_count);
>>  int vgic_v3_init(struct domain *d, int *mmio_count);
>>
>> +extern int vgic_lpi_get_priority(struct domain *d, uint32_t vlpi);
>
> Prototype should be added in the same patch as the declaration. So
> please move to patch #10.
>
> Cheers,
>

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

  reply	other threads:[~2017-04-04 12:56 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-31 18:04 [PATCH v3 00/26] arm64: Dom0 ITS emulation Andre Przywara
2017-03-31 18:05 ` [PATCH v3 01/26] ARM: GICv3 ITS: parse and store ITS subnodes from hardware DT Andre Przywara
2017-03-31 23:08   ` Stefano Stabellini
2017-03-31 18:05 ` [PATCH v3 02/26] ARM: GICv3: allocate LPI pending and property table Andre Przywara
2017-03-31 22:59   ` Stefano Stabellini
2017-04-03  9:05     ` Andre Przywara
2017-04-03 18:16       ` Stefano Stabellini
2017-04-03 13:53   ` Julien Grall
2017-04-03 14:01     ` Julien Grall
2017-03-31 18:05 ` [PATCH v3 03/26] ARM: GICv3 ITS: allocate device and collection table Andre Przywara
2017-03-31 23:06   ` Stefano Stabellini
2017-04-03 15:38   ` Julien Grall
2017-04-03 17:22     ` Julien Grall
2017-04-03 19:39       ` Andre Przywara
2017-04-03 20:46         ` Julien Grall
2017-03-31 18:05 ` [PATCH v3 04/26] ARM: GICv3 ITS: map ITS command buffer Andre Przywara
2017-03-31 23:10   ` Stefano Stabellini
2017-04-03 16:00   ` Julien Grall
2017-03-31 18:05 ` [PATCH v3 05/26] ARM: GICv3 ITS: introduce ITS command handling Andre Przywara
2017-03-31 23:16   ` Stefano Stabellini
2017-04-03 17:32   ` Julien Grall
2017-03-31 18:05 ` [PATCH v3 06/26] ARM: GICv3 ITS: introduce device mapping Andre Przywara
2017-03-31 23:20   ` Stefano Stabellini
2017-04-01  8:01   ` Vijay Kilari
2017-04-03 18:33     ` Julien Grall
2017-04-03 18:56   ` Julien Grall
2017-03-31 18:05 ` [PATCH v3 07/26] ARM: GICv3 ITS: introduce host LPI array Andre Przywara
2017-03-31 23:24   ` Stefano Stabellini
2017-03-31 18:05 ` [PATCH v3 08/26] ARM: GICv3: introduce separate pending_irq structs for LPIs Andre Przywara
2017-03-31 18:05 ` [PATCH v3 09/26] ARM: GICv3: forward pending LPIs to guests Andre Przywara
2017-03-31 18:05 ` [PATCH v3 10/26] ARM: GICv3: enable ITS and LPIs on the host Andre Przywara
2017-03-31 18:05 ` [PATCH v3 11/26] ARM: vGICv3: handle virtual LPI pending and property tables Andre Przywara
2017-04-04 12:55   ` Julien Grall
2017-04-04 12:56     ` Julien Grall [this message]
2017-03-31 18:05 ` [PATCH v3 12/26] ARM: vGICv3: Handle disabled LPIs Andre Przywara
2017-03-31 18:05 ` [PATCH v3 13/26] ARM: vGICv3: introduce basic ITS emulation bits Andre Przywara
2017-03-31 18:05 ` [PATCH v3 14/26] ARM: vITS: introduce translation table walks Andre Przywara
2017-03-31 18:05 ` [PATCH v3 15/26] ARM: vITS: handle CLEAR command Andre Przywara
2017-03-31 18:05 ` [PATCH v3 16/26] ARM: vITS: handle INT command Andre Przywara
2017-03-31 18:05 ` [PATCH v3 17/26] ARM: vITS: handle MAPC command Andre Przywara
2017-03-31 18:05 ` [PATCH v3 18/26] ARM: vITS: handle MAPD command Andre Przywara
2017-03-31 18:05 ` [PATCH v3 19/26] ARM: vITS: handle MAPTI command Andre Przywara
2017-04-01  8:32   ` Vijay Kilari
2017-03-31 18:05 ` [PATCH v3 20/26] ARM: vITS: handle MOVI command Andre Przywara
2017-03-31 18:05 ` [PATCH v3 21/26] ARM: vITS: handle DISCARD command Andre Przywara
2017-03-31 18:05 ` [PATCH v3 22/26] ARM: vITS: handle INV command Andre Przywara
2017-03-31 18:05 ` [PATCH v3 23/26] ARM: vITS: handle INVALL command Andre Przywara
2017-03-31 18:05 ` [PATCH v3 24/26] ARM: vITS: create and initialize virtual ITSes for Dom0 Andre Przywara
2017-03-31 18:05 ` [PATCH v3 25/26] ARM: vITS: create ITS subnodes for Dom0 DT Andre Przywara
2017-03-31 18:05 ` [PATCH v3 26/26] ARM: vGIC: advertise LPI support Andre Przywara
2017-04-04 17:06   ` Julien Grall
2017-04-01 20:37 ` [PATCH v3 00/26] arm64: Dom0 ITS emulation Julien Grall

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=0d92de72-9f52-39c5-be30-db1289b6c16b@arm.com \
    --to=julien.grall@arm.com \
    --cc=andre.przywara@arm.com \
    --cc=shankerd@codeaurora.org \
    --cc=sstabellini@kernel.org \
    --cc=vijay.kilari@gmail.com \
    --cc=xen-devel@lists.xenproject.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).