diff mbox series

[v1,06/13] xen/arm: set up shared memory foreign mapping for borrower domain

Message ID 20220311061123.1883189-7-Penny.Zheng@arm.com (mailing list archive)
State New, archived
Headers show
Series Static shared memory on dom0less system | expand

Commit Message

Penny Zheng March 11, 2022, 6:11 a.m. UTC
From: Penny Zheng <penny.zheng@arm.com>

This commits introduces a new helper guest_physmap_add_shm to set up shared
memory foreign mapping for borrower domain.

Firstly it should get and take reference of statically shared pages from
owner dom_shared. Then it will setup P2M foreign memory map of these statically
shared pages for borrower domain.

This commits only considers owner domain is the default dom_shared, the
other scenario will be covered in the following patches.

Signed-off-by: Penny Zheng <penny.zheng@arm.com>
---
 xen/arch/arm/domain_build.c | 52 +++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

Comments

Stefano Stabellini March 18, 2022, 2 a.m. UTC | #1
On Fri, 11 Mar 2022, Penny Zheng wrote:
> From: Penny Zheng <penny.zheng@arm.com>
> 
> This commits introduces a new helper guest_physmap_add_shm to set up shared
> memory foreign mapping for borrower domain.
> 
> Firstly it should get and take reference of statically shared pages from
> owner dom_shared. Then it will setup P2M foreign memory map of these statically
> shared pages for borrower domain.
> 
> This commits only considers owner domain is the default dom_shared, the
> other scenario will be covered in the following patches.
> 
> Signed-off-by: Penny Zheng <penny.zheng@arm.com>
> ---
>  xen/arch/arm/domain_build.c | 52 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 52 insertions(+)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 984e70e5fc..8cee5ffbd1 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -798,6 +798,48 @@ static int __init allocate_shared_memory(struct domain *d,
>      return ret;
>  }
>  
> +static int __init guest_physmap_add_shm(struct domain *od, struct domain *bd,
> +                                        unsigned long o_gfn,
> +                                        unsigned long b_gfn,
> +                                        unsigned long nr_gfns)

They should probably be gfn_t type


> +{
> +    struct page_info **pages = NULL;
> +    p2m_type_t p2mt, t;
> +    int ret = 0;
> +
> +    pages = xmalloc_array(struct page_info *, nr_gfns);
> +    if ( !pages )
> +        return -ENOMEM;
> +
> +    /*
> +     * Take reference of statically shared pages from owner domain.
> +     * Reference will be released when destroying shared memory region.
> +     */
> +    ret = get_pages_from_gfn(od, o_gfn, nr_gfns, pages, &p2mt, P2M_ALLOC);
> +    if ( ret )
> +    {
> +        ret = -EINVAL;
> +        goto fail_pages;
> +    }
> +
> +    if ( p2m_is_ram(p2mt) )
> +        t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw : p2m_map_foreign_ro;
> +    else
> +    {
> +        ret = -EINVAL;
> +        goto fail_pages;
> +    }

One idea is to initialize p2mt = p2m_ram_rw and pass it to
get_pages_from_gfn. Then get_pages_from_gfn can return error immediately
if any of the pages are of different type.

This way there is no need for checking again here.


> +    /* Set up guest foreign map. */
> +    ret = guest_physmap_add_pages(bd, _gfn(b_gfn), page_to_mfn(pages[0]),
> +                                  nr_gfns, t);
> +
> + fail_pages:
> +        xfree(pages);
> +
> +    return ret;
> +}
> +
>  static int __init process_shm(struct domain *d,
>                                const struct dt_device_node *node)
>  {
> @@ -855,6 +897,16 @@ static int __init process_shm(struct domain *d,
>  
>              set_bit(shm_id, shm_mask);
>          }
> +
> +        /*
> +         * All domains are borrower domains when owner domain is the
> +         * default dom_shared, so here we could just set up P2M foreign
> +         * mapping for borrower domain immediately.
> +         */
> +        ret = guest_physmap_add_shm(dom_shared, d, PFN_DOWN(pbase),
> +                                    PFN_DOWN(gbase), PFN_DOWN(psize));
> +        if ( ret )
> +            return ret;
>      }
>  
>      return 0;
> -- 
> 2.25.1
>
Penny Zheng March 29, 2022, 3:44 a.m. UTC | #2
Hi Stefano

Sorry for the late response, got sidetracked an emergency issue. ;/

> -----Original Message-----
> From: Stefano Stabellini <sstabelliHini@kernel.org>
> Sent: Friday, March 18, 2022 10:00 AM
> To: Penny Zheng <Penny.Zheng@arm.com>
> Cc: xen-devel@lists.xenproject.org; nd <nd@arm.com>; Stefano Stabellini
> <sstabellini@kernel.org>; Julien Grall <julien@xen.org>; Bertrand Marquis
> <Bertrand.Marquis@arm.com>; Volodymyr Babchuk
> <Volodymyr_Babchuk@epam.com>
> Subject: Re: [PATCH v1 06/13] xen/arm: set up shared memory foreign
> mapping for borrower domain
> 
> On Fri, 11 Mar 2022, Penny Zheng wrote:
> > From: Penny Zheng <penny.zheng@arm.com>
> >
> > This commits introduces a new helper guest_physmap_add_shm to set up
> > shared memory foreign mapping for borrower domain.
> >
> > Firstly it should get and take reference of statically shared pages
> > from owner dom_shared. Then it will setup P2M foreign memory map of
> > these statically shared pages for borrower domain.
> >
> > This commits only considers owner domain is the default dom_shared,
> > the other scenario will be covered in the following patches.
> >
> > Signed-off-by: Penny Zheng <penny.zheng@arm.com>
> > ---
> >  xen/arch/arm/domain_build.c | 52
> > +++++++++++++++++++++++++++++++++++++
> >  1 file changed, 52 insertions(+)
> >
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 984e70e5fc..8cee5ffbd1 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -798,6 +798,48 @@ static int __init allocate_shared_memory(struct
> domain *d,
> >      return ret;
> >  }
> >
> > +static int __init guest_physmap_add_shm(struct domain *od, struct domain
> *bd,
> > +                                        unsigned long o_gfn,
> > +                                        unsigned long b_gfn,
> > +                                        unsigned long nr_gfns)
> 
> They should probably be gfn_t type
> 
>
 
Sure, will do.

> > +{
> > +    struct page_info **pages = NULL;
> > +    p2m_type_t p2mt, t;
> > +    int ret = 0;
> > +
> > +    pages = xmalloc_array(struct page_info *, nr_gfns);
> > +    if ( !pages )
> > +        return -ENOMEM;
> > +
> > +    /*
> > +     * Take reference of statically shared pages from owner domain.
> > +     * Reference will be released when destroying shared memory region.
> > +     */
> > +    ret = get_pages_from_gfn(od, o_gfn, nr_gfns, pages, &p2mt, P2M_ALLOC);
> > +    if ( ret )
> > +    {
> > +        ret = -EINVAL;
> > +        goto fail_pages;
> > +    }
> > +
> > +    if ( p2m_is_ram(p2mt) )
> > +        t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw :
> p2m_map_foreign_ro;
> > +    else
> > +    {
> > +        ret = -EINVAL;
> > +        goto fail_pages;
> > +    }
> 
> One idea is to initialize p2mt = p2m_ram_rw and pass it to
> get_pages_from_gfn. Then get_pages_from_gfn can return error immediately
> if any of the pages are of different type.
> 
> This way there is no need for checking again here.
>

Right now, the memory attribute of static shared memory is RW as default,
What if we add memory attribute setting in device tree configuration, sometimes,
Users want to specify that borrower domain only has RO right, hmm, then the
Initialization for p2mt could be either p2m_ram_rw or p2m_ram_ro?
In such case, we could add another parameter in guest_physmap_add_shm to
show the p2m type...
Hope I understand what you suggested here.
 
> 
> > +    /* Set up guest foreign map. */
> > +    ret = guest_physmap_add_pages(bd, _gfn(b_gfn), page_to_mfn(pages[0]),
> > +                                  nr_gfns, t);
> > +
> > + fail_pages:
> > +        xfree(pages);
> > +
> > +    return ret;
> > +}
> > +
> >  static int __init process_shm(struct domain *d,
> >                                const struct dt_device_node *node)  {
> > @@ -855,6 +897,16 @@ static int __init process_shm(struct domain *d,
> >
> >              set_bit(shm_id, shm_mask);
> >          }
> > +
> > +        /*
> > +         * All domains are borrower domains when owner domain is the
> > +         * default dom_shared, so here we could just set up P2M foreign
> > +         * mapping for borrower domain immediately.
> > +         */
> > +        ret = guest_physmap_add_shm(dom_shared, d, PFN_DOWN(pbase),
> > +                                    PFN_DOWN(gbase), PFN_DOWN(psize));
> > +        if ( ret )
> > +            return ret;
> >      }
> >
> >      return 0;
> > --
> > 2.25.1
> >

---
Cheers,
Penny Zheng
Stefano Stabellini April 8, 2022, 10:18 p.m. UTC | #3
On Tue, 29 Mar 2022, Penny Zheng wrote:
> Hi Stefano
> 
> Sorry for the late response, got sidetracked an emergency issue. ;/
> 
> > -----Original Message-----
> > From: Stefano Stabellini <sstabelliHini@kernel.org>
> > Sent: Friday, March 18, 2022 10:00 AM
> > To: Penny Zheng <Penny.Zheng@arm.com>
> > Cc: xen-devel@lists.xenproject.org; nd <nd@arm.com>; Stefano Stabellini
> > <sstabellini@kernel.org>; Julien Grall <julien@xen.org>; Bertrand Marquis
> > <Bertrand.Marquis@arm.com>; Volodymyr Babchuk
> > <Volodymyr_Babchuk@epam.com>
> > Subject: Re: [PATCH v1 06/13] xen/arm: set up shared memory foreign
> > mapping for borrower domain
> > 
> > On Fri, 11 Mar 2022, Penny Zheng wrote:
> > > From: Penny Zheng <penny.zheng@arm.com>
> > >
> > > This commits introduces a new helper guest_physmap_add_shm to set up
> > > shared memory foreign mapping for borrower domain.
> > >
> > > Firstly it should get and take reference of statically shared pages
> > > from owner dom_shared. Then it will setup P2M foreign memory map of
> > > these statically shared pages for borrower domain.
> > >
> > > This commits only considers owner domain is the default dom_shared,
> > > the other scenario will be covered in the following patches.
> > >
> > > Signed-off-by: Penny Zheng <penny.zheng@arm.com>
> > > ---
> > >  xen/arch/arm/domain_build.c | 52
> > > +++++++++++++++++++++++++++++++++++++
> > >  1 file changed, 52 insertions(+)
> > >
> > > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > > index 984e70e5fc..8cee5ffbd1 100644
> > > --- a/xen/arch/arm/domain_build.c
> > > +++ b/xen/arch/arm/domain_build.c
> > > @@ -798,6 +798,48 @@ static int __init allocate_shared_memory(struct
> > domain *d,
> > >      return ret;
> > >  }
> > >
> > > +static int __init guest_physmap_add_shm(struct domain *od, struct domain
> > *bd,
> > > +                                        unsigned long o_gfn,
> > > +                                        unsigned long b_gfn,
> > > +                                        unsigned long nr_gfns)
> > 
> > They should probably be gfn_t type
> > 
> >
>  
> Sure, will do.
> 
> > > +{
> > > +    struct page_info **pages = NULL;
> > > +    p2m_type_t p2mt, t;
> > > +    int ret = 0;
> > > +
> > > +    pages = xmalloc_array(struct page_info *, nr_gfns);
> > > +    if ( !pages )
> > > +        return -ENOMEM;
> > > +
> > > +    /*
> > > +     * Take reference of statically shared pages from owner domain.
> > > +     * Reference will be released when destroying shared memory region.
> > > +     */
> > > +    ret = get_pages_from_gfn(od, o_gfn, nr_gfns, pages, &p2mt, P2M_ALLOC);
> > > +    if ( ret )
> > > +    {
> > > +        ret = -EINVAL;
> > > +        goto fail_pages;
> > > +    }
> > > +
> > > +    if ( p2m_is_ram(p2mt) )
> > > +        t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw :
> > p2m_map_foreign_ro;
> > > +    else
> > > +    {
> > > +        ret = -EINVAL;
> > > +        goto fail_pages;
> > > +    }
> > 
> > One idea is to initialize p2mt = p2m_ram_rw and pass it to
> > get_pages_from_gfn. Then get_pages_from_gfn can return error immediately
> > if any of the pages are of different type.
> > 
> > This way there is no need for checking again here.
> >
> 
> Right now, the memory attribute of static shared memory is RW as default,
> What if we add memory attribute setting in device tree configuration, sometimes,
> Users want to specify that borrower domain only has RO right, hmm, then the
> Initialization for p2mt could be either p2m_ram_rw or p2m_ram_ro?
> In such case, we could add another parameter in guest_physmap_add_shm to
> show the p2m type...
> Hope I understand what you suggested here.

Yes, I think I understand. I think your suggestion is OK too. However,
your suggestion is much more work than mine: I was only suggesting a
small improvement limited to guest_physmap_add_shm and
get_pages_from_gfn. Your suggestion involves a device tree change that
would have a larger impact on the patch series. So if you are up for it,
I am happy to review it. I am also fine just to have a small improvement
on guest_physmap_add_shm/get_pages_from_gfn.
Julien Grall April 8, 2022, 10:50 p.m. UTC | #4
Hi Stefano,

On 08/04/2022 23:18, Stefano Stabellini wrote:
> On Tue, 29 Mar 2022, Penny Zheng wrote:
>> Right now, the memory attribute of static shared memory is RW as default,
>> What if we add memory attribute setting in device tree configuration, sometimes,
>> Users want to specify that borrower domain only has RO right, hmm, then the
>> Initialization for p2mt could be either p2m_ram_rw or p2m_ram_ro?
>> In such case, we could add another parameter in guest_physmap_add_shm to
>> show the p2m type...
>> Hope I understand what you suggested here.
> 
> Yes, I think I understand. I think your suggestion is OK too. However,
> your suggestion is much more work than mine: I was only suggesting a
> small improvement limited to guest_physmap_add_shm and
> get_pages_from_gfn. Your suggestion involves a device tree change that
> would have a larger impact on the patch series. So if you are up for it,
> I am happy to review it. I am also fine just to have a small improvement
> on guest_physmap_add_shm/get_pages_from_gfn.

AFAIU, your proposal would mean that the behavior for 
get_pages_from_gfn() and get_page_from_gfn() will differ. This is not great.

I don't think we can easily change the behavior of get_page_from_gfn() 
because some callers can accept multiple types.

Furthermore, while today we only check p2m_ram_rw. It might be possible 
that we would want to check different type. For instance, if we want to 
use read-only mapping, it would be fine to accept p2m_ram_ro and p2m_ram_rw.

So overall, I am not in favor of initializing p2mt and let 
get_pages_from_gfn() to check the type.

Cheers,
Julien Grall April 8, 2022, 10:59 p.m. UTC | #5
Hi Penny,

On 11/03/2022 06:11, Penny Zheng wrote:
> From: Penny Zheng <penny.zheng@arm.com>
> 
> This commits introduces a new helper guest_physmap_add_shm to set up shared
> memory foreign mapping for borrower domain.
> 
> Firstly it should get and take reference of statically shared pages from
> owner dom_shared. Then it will setup P2M foreign memory map of these statically
> shared pages for borrower domain.
> 
> This commits only considers owner domain is the default dom_shared, the
> other scenario will be covered in the following patches.
> 
> Signed-off-by: Penny Zheng <penny.zheng@arm.com>
> ---
>   xen/arch/arm/domain_build.c | 52 +++++++++++++++++++++++++++++++++++++
>   1 file changed, 52 insertions(+)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 984e70e5fc..8cee5ffbd1 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -798,6 +798,48 @@ static int __init allocate_shared_memory(struct domain *d,
>       return ret;
>   }
>   
> +static int __init guest_physmap_add_shm(struct domain *od, struct domain *bd,
> +                                        unsigned long o_gfn,
> +                                        unsigned long b_gfn,
> +                                        unsigned long nr_gfns)
> +{
> +    struct page_info **pages = NULL;
> +    p2m_type_t p2mt, t;
> +    int ret = 0;

You don't need to initialize ret.

> +
> +    pages = xmalloc_array(struct page_info *, nr_gfns);
> +    if ( !pages )
> +        return -ENOMEM;
> +
> +    /*
> +     * Take reference of statically shared pages from owner domain.
> +     * Reference will be released when destroying shared memory region.
> +     */
> +    ret = get_pages_from_gfn(od, o_gfn, nr_gfns, pages, &p2mt, P2M_ALLOC);
> +    if ( ret )
> +    {
> +        ret = -EINVAL;
> +        goto fail_pages;
> +    }
> +
> +    if ( p2m_is_ram(p2mt) )
> +        t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw : p2m_map_foreign_ro;
> +    else
> +    {
> +        ret = -EINVAL;
> +        goto fail_pages;

Where would we release the references?

> +    }
> +
> +    /* Set up guest foreign map. */
> +    ret = guest_physmap_add_pages(bd, _gfn(b_gfn), page_to_mfn(pages[0]),
> +                                  nr_gfns, t);

A few things:
   - The beginning of the code assumes that the MFN may be discontiguous 
in the physical memory. But here, you are assuming they are contiguous. 
If you want the latter, then you should check the MFNs are contiguous. 
That said, I am not sure if this restriction is really necessary.

   - IIRC, guest_physmap_add_pages() doesn't revert the mappings. So you 
need to revert it in case of failure.

Cheers,
Stefano Stabellini April 8, 2022, 11:18 p.m. UTC | #6
On Fri, 8 Apr 2022, Julien Grall wrote:
> On 08/04/2022 23:18, Stefano Stabellini wrote:
> > On Tue, 29 Mar 2022, Penny Zheng wrote:
> > > Right now, the memory attribute of static shared memory is RW as default,
> > > What if we add memory attribute setting in device tree configuration,
> > > sometimes,
> > > Users want to specify that borrower domain only has RO right, hmm, then
> > > the
> > > Initialization for p2mt could be either p2m_ram_rw or p2m_ram_ro?
> > > In such case, we could add another parameter in guest_physmap_add_shm to
> > > show the p2m type...
> > > Hope I understand what you suggested here.
> > 
> > Yes, I think I understand. I think your suggestion is OK too. However,
> > your suggestion is much more work than mine: I was only suggesting a
> > small improvement limited to guest_physmap_add_shm and
> > get_pages_from_gfn. Your suggestion involves a device tree change that
> > would have a larger impact on the patch series. So if you are up for it,
> > I am happy to review it. I am also fine just to have a small improvement
> > on guest_physmap_add_shm/get_pages_from_gfn.
> 
> AFAIU, your proposal would mean that the behavior for get_pages_from_gfn() and
> get_page_from_gfn() will differ. This is not great.
> 
> I don't think we can easily change the behavior of get_page_from_gfn() because
> some callers can accept multiple types.
> 
> Furthermore, while today we only check p2m_ram_rw. It might be possible that
> we would want to check different type. For instance, if we want to use
> read-only mapping, it would be fine to accept p2m_ram_ro and p2m_ram_rw.
> 
> So overall, I am not in favor of initializing p2mt and let
> get_pages_from_gfn() to check the type.

OK. In that case, I suggest to leave the code pretty much as is in
regards of how get_pages_from_gfn is called from guest_physmap_add_shm.
Julien Grall April 9, 2022, 9:30 a.m. UTC | #7
Hi,

On 08/04/2022 23:59, Julien Grall wrote:
> On 11/03/2022 06:11, Penny Zheng wrote:
>> From: Penny Zheng <penny.zheng@arm.com>
>>
>> This commits introduces a new helper guest_physmap_add_shm to set up 
>> shared
>> memory foreign mapping for borrower domain.
>>
>> Firstly it should get and take reference of statically shared pages from
>> owner dom_shared. Then it will setup P2M foreign memory map of these 
>> statically
>> shared pages for borrower domain.
>>
>> This commits only considers owner domain is the default dom_shared, the
>> other scenario will be covered in the following patches.
>>
>> Signed-off-by: Penny Zheng <penny.zheng@arm.com>
>> ---
>>   xen/arch/arm/domain_build.c | 52 +++++++++++++++++++++++++++++++++++++
>>   1 file changed, 52 insertions(+)
>>
>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>> index 984e70e5fc..8cee5ffbd1 100644
>> --- a/xen/arch/arm/domain_build.c
>> +++ b/xen/arch/arm/domain_build.c
>> @@ -798,6 +798,48 @@ static int __init allocate_shared_memory(struct 
>> domain *d,
>>       return ret;
>>   }
>> +static int __init guest_physmap_add_shm(struct domain *od, struct 
>> domain *bd,
>> +                                        unsigned long o_gfn,
>> +                                        unsigned long b_gfn,
>> +                                        unsigned long nr_gfns)
>> +{
>> +    struct page_info **pages = NULL;
>> +    p2m_type_t p2mt, t;
>> +    int ret = 0;
> 
> You don't need to initialize ret.
> 
>> +
>> +    pages = xmalloc_array(struct page_info *, nr_gfns);
>> +    if ( !pages )
>> +        return -ENOMEM;
>> +
>> +    /*
>> +     * Take reference of statically shared pages from owner domain.
>> +     * Reference will be released when destroying shared memory region.
>> +     */
>> +    ret = get_pages_from_gfn(od, o_gfn, nr_gfns, pages, &p2mt, 
>> P2M_ALLOC);
>> +    if ( ret )
>> +    {
>> +        ret = -EINVAL;
>> +        goto fail_pages;
>> +    }
>> +
>> +    if ( p2m_is_ram(p2mt) )
>> +        t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw : 
>> p2m_map_foreign_ro;
>> +    else
>> +    {
>> +        ret = -EINVAL;
>> +        goto fail_pages;
> 
> Where would we release the references?
> 
>> +    }
>> +
>> +    /* Set up guest foreign map. */
>> +    ret = guest_physmap_add_pages(bd, _gfn(b_gfn), 
>> page_to_mfn(pages[0]),
>> +                                  nr_gfns, t);
> 
> A few things:
>    - The beginning of the code assumes that the MFN may be discontiguous 
> in the physical memory. But here, you are assuming they are contiguous. 
> If you want the latter, then you should check the MFNs are contiguous. 
> That said, I am not sure if this restriction is really necessary.
> 
>    - IIRC, guest_physmap_add_pages() doesn't revert the mappings. So you 
> need to revert it in case of failure.


There is another issue here. guest_physmap_add_pages() may use superpage 
mapping. The P2M code is currently assuming the foreing mapping will be 
using L3 mapping (4KB).

Do you need to use superpage mapping here?

Cheers,
Penny Zheng April 20, 2022, 8:51 a.m. UTC | #8
Hi julien

> -----Original Message-----
> From: Julien Grall <julien@xen.org>
> Sent: Saturday, April 9, 2022 6:59 AM
> To: Penny Zheng <Penny.Zheng@arm.com>; xen-devel@lists.xenproject.org
> Cc: nd <nd@arm.com>; Stefano Stabellini <sstabellini@kernel.org>; Bertrand
> Marquis <Bertrand.Marquis@arm.com>; Volodymyr Babchuk
> <Volodymyr_Babchuk@epam.com>
> Subject: Re: [PATCH v1 06/13] xen/arm: set up shared memory foreign
> mapping for borrower domain
> 
> Hi Penny,
> 
> On 11/03/2022 06:11, Penny Zheng wrote:
> > From: Penny Zheng <penny.zheng@arm.com>
> >
> > This commits introduces a new helper guest_physmap_add_shm to set up
> > shared memory foreign mapping for borrower domain.
> >
> > Firstly it should get and take reference of statically shared pages
> > from owner dom_shared. Then it will setup P2M foreign memory map of
> > these statically shared pages for borrower domain.
> >
> > This commits only considers owner domain is the default dom_shared,
> > the other scenario will be covered in the following patches.
> >
> > Signed-off-by: Penny Zheng <penny.zheng@arm.com>
> > ---
> >   xen/arch/arm/domain_build.c | 52
> +++++++++++++++++++++++++++++++++++++
> >   1 file changed, 52 insertions(+)
> >
> > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> > index 984e70e5fc..8cee5ffbd1 100644
> > --- a/xen/arch/arm/domain_build.c
> > +++ b/xen/arch/arm/domain_build.c
> > @@ -798,6 +798,48 @@ static int __init allocate_shared_memory(struct
> domain *d,
> >       return ret;
> >   }
> >
> > +static int __init guest_physmap_add_shm(struct domain *od, struct domain
> *bd,
> > +                                        unsigned long o_gfn,
> > +                                        unsigned long b_gfn,
> > +                                        unsigned long nr_gfns) {
> > +    struct page_info **pages = NULL;
> > +    p2m_type_t p2mt, t;
> > +    int ret = 0;
> 
> You don't need to initialize ret.
> 
> > +
> > +    pages = xmalloc_array(struct page_info *, nr_gfns);
> > +    if ( !pages )
> > +        return -ENOMEM;
> > +
> > +    /*
> > +     * Take reference of statically shared pages from owner domain.
> > +     * Reference will be released when destroying shared memory region.
> > +     */
> > +    ret = get_pages_from_gfn(od, o_gfn, nr_gfns, pages, &p2mt, P2M_ALLOC);
> > +    if ( ret )
> > +    {
> > +        ret = -EINVAL;
> > +        goto fail_pages;
> > +    }
> > +
> > +    if ( p2m_is_ram(p2mt) )
> > +        t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw :
> p2m_map_foreign_ro;
> > +    else
> > +    {
> > +        ret = -EINVAL;
> > +        goto fail_pages;
> 
> Where would we release the references?
> 
> > +    }
> > +
> > +    /* Set up guest foreign map. */
> > +    ret = guest_physmap_add_pages(bd, _gfn(b_gfn), page_to_mfn(pages[0]),
> > +                                  nr_gfns, t);
> 
> A few things:
>    - The beginning of the code assumes that the MFN may be discontiguous in
> the physical memory. But here, you are assuming they are contiguous.
> If you want the latter, then you should check the MFNs are contiguous.
> That said, I am not sure if this restriction is really necessary.
> 

Oh,, caught me, it never occurred to me that the pages in array `pages` could
be discontinuous.
I definitely want the latter. This function is always dealing with a memory region
(contiguous MFNS) each time. So maybe a loop to check
page_to_mfn(pages[i]) == mfn_add(smfn, i) is needed.

>    - IIRC, guest_physmap_add_pages() doesn't revert the mappings. So you
> need to revert it in case of failure.
> 

Yes, both failure points you are referring to are requiring reverting the mappings.

> Cheers,
> 
> --
> Julien Grall
Penny Zheng April 20, 2022, 8:53 a.m. UTC | #9
Hi

> -----Original Message-----
> From: Julien Grall <julien@xen.org>
> Sent: Saturday, April 9, 2022 5:31 PM
> To: Penny Zheng <Penny.Zheng@arm.com>; xen-devel@lists.xenproject.org
> Cc: nd <nd@arm.com>; Stefano Stabellini <sstabellini@kernel.org>; Bertrand
> Marquis <Bertrand.Marquis@arm.com>; Volodymyr Babchuk
> <Volodymyr_Babchuk@epam.com>
> Subject: Re: [PATCH v1 06/13] xen/arm: set up shared memory foreign
> mapping for borrower domain
> 
> Hi,
> 
> On 08/04/2022 23:59, Julien Grall wrote:
> > On 11/03/2022 06:11, Penny Zheng wrote:
> >> From: Penny Zheng <penny.zheng@arm.com>
> >>
> >> This commits introduces a new helper guest_physmap_add_shm to set up
> >> shared memory foreign mapping for borrower domain.
> >>
> >> Firstly it should get and take reference of statically shared pages
> >> from owner dom_shared. Then it will setup P2M foreign memory map of
> >> these statically shared pages for borrower domain.
> >>
> >> This commits only considers owner domain is the default dom_shared,
> >> the other scenario will be covered in the following patches.
> >>
> >> Signed-off-by: Penny Zheng <penny.zheng@arm.com>
> >> ---
> >>   xen/arch/arm/domain_build.c | 52
> >> +++++++++++++++++++++++++++++++++++++
> >>   1 file changed, 52 insertions(+)
> >>
> >> diff --git a/xen/arch/arm/domain_build.c
> >> b/xen/arch/arm/domain_build.c index 984e70e5fc..8cee5ffbd1 100644
> >> --- a/xen/arch/arm/domain_build.c
> >> +++ b/xen/arch/arm/domain_build.c
> >> @@ -798,6 +798,48 @@ static int __init allocate_shared_memory(struct
> >> domain *d,
> >>       return ret;
> >>   }
> >> +static int __init guest_physmap_add_shm(struct domain *od, struct
> >> domain *bd,
> >> +                                        unsigned long o_gfn,
> >> +                                        unsigned long b_gfn,
> >> +                                        unsigned long nr_gfns) {
> >> +    struct page_info **pages = NULL;
> >> +    p2m_type_t p2mt, t;
> >> +    int ret = 0;
> >
> > You don't need to initialize ret.
> >
> >> +
> >> +    pages = xmalloc_array(struct page_info *, nr_gfns);
> >> +    if ( !pages )
> >> +        return -ENOMEM;
> >> +
> >> +    /*
> >> +     * Take reference of statically shared pages from owner domain.
> >> +     * Reference will be released when destroying shared memory region.
> >> +     */
> >> +    ret = get_pages_from_gfn(od, o_gfn, nr_gfns, pages, &p2mt,
> >> P2M_ALLOC);
> >> +    if ( ret )
> >> +    {
> >> +        ret = -EINVAL;
> >> +        goto fail_pages;
> >> +    }
> >> +
> >> +    if ( p2m_is_ram(p2mt) )
> >> +        t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw :
> >> p2m_map_foreign_ro;
> >> +    else
> >> +    {
> >> +        ret = -EINVAL;
> >> +        goto fail_pages;
> >
> > Where would we release the references?
> >
> >> +    }
> >> +
> >> +    /* Set up guest foreign map. */
> >> +    ret = guest_physmap_add_pages(bd, _gfn(b_gfn),
> >> page_to_mfn(pages[0]),
> >> +                                  nr_gfns, t);
> >
> > A few things:
> >    - The beginning of the code assumes that the MFN may be
> > discontiguous in the physical memory. But here, you are assuming they are
> contiguous.
> > If you want the latter, then you should check the MFNs are contiguous.
> > That said, I am not sure if this restriction is really necessary.
> >
> >    - IIRC, guest_physmap_add_pages() doesn't revert the mappings. So
> > you need to revert it in case of failure.
> 
> 
> There is another issue here. guest_physmap_add_pages() may use superpage
> mapping. The P2M code is currently assuming the foreing mapping will be
> using L3 mapping (4KB).
> 
> Do you need to use superpage mapping here?
> 

Right now, there is no user case on my side needing superpage mapping.

> Cheers,
> 
> --
> Julien Grall
diff mbox series

Patch

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 984e70e5fc..8cee5ffbd1 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -798,6 +798,48 @@  static int __init allocate_shared_memory(struct domain *d,
     return ret;
 }
 
+static int __init guest_physmap_add_shm(struct domain *od, struct domain *bd,
+                                        unsigned long o_gfn,
+                                        unsigned long b_gfn,
+                                        unsigned long nr_gfns)
+{
+    struct page_info **pages = NULL;
+    p2m_type_t p2mt, t;
+    int ret = 0;
+
+    pages = xmalloc_array(struct page_info *, nr_gfns);
+    if ( !pages )
+        return -ENOMEM;
+
+    /*
+     * Take reference of statically shared pages from owner domain.
+     * Reference will be released when destroying shared memory region.
+     */
+    ret = get_pages_from_gfn(od, o_gfn, nr_gfns, pages, &p2mt, P2M_ALLOC);
+    if ( ret )
+    {
+        ret = -EINVAL;
+        goto fail_pages;
+    }
+
+    if ( p2m_is_ram(p2mt) )
+        t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw : p2m_map_foreign_ro;
+    else
+    {
+        ret = -EINVAL;
+        goto fail_pages;
+    }
+
+    /* Set up guest foreign map. */
+    ret = guest_physmap_add_pages(bd, _gfn(b_gfn), page_to_mfn(pages[0]),
+                                  nr_gfns, t);
+
+ fail_pages:
+        xfree(pages);
+
+    return ret;
+}
+
 static int __init process_shm(struct domain *d,
                               const struct dt_device_node *node)
 {
@@ -855,6 +897,16 @@  static int __init process_shm(struct domain *d,
 
             set_bit(shm_id, shm_mask);
         }
+
+        /*
+         * All domains are borrower domains when owner domain is the
+         * default dom_shared, so here we could just set up P2M foreign
+         * mapping for borrower domain immediately.
+         */
+        ret = guest_physmap_add_shm(dom_shared, d, PFN_DOWN(pbase),
+                                    PFN_DOWN(gbase), PFN_DOWN(psize));
+        if ( ret )
+            return ret;
     }
 
     return 0;