|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2 5/8] xen/arm: support static shared memory when host address not provided
Hi Penny
On 2/23/23 00:41, Penny Zheng wrote:
> In order to support static shared memory when host address not provided,
> we shall do the following modification:
> - we shall let Xen allocate memory from heap for static shared memory
> at first domain, no matter it is owner or borrower.
> - In acquire_shared_memory_bank, as static shared memory has already
> been allocated from heap, we shall assign them to the owner domain
> using function "assign_pages".
> - Function get_shm_pages_reference is created to add as many
> additional reference as the number of borrowers.
> - We implement a new helper "add_foreign_mapping_for_borrower" to set
> up foreign memory mapping for borrower.
>
> Instead of using multiple function parameters to deliver various shm-related
> info, like host physical address, SHMID, etc, and with the introduction
> of new struct "shm_memnode" to include banked host memory info, we switch to
> use "shm_memnode" as function parameter to replace them all, to make codes
> more
> clear and tidy.
>
> Signed-off-by: Penny Zheng <penny.zheng@xxxxxxx>
> ---
> v1 -> v2:
> - combine commits 4 - 6 in Serie 1
> - Adapt to changes of introducing "struct shm_memnode"
> ---
> xen/arch/arm/domain_build.c | 222 +++++++++++++++++++++++++-----------
> 1 file changed, 155 insertions(+), 67 deletions(-)
>
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 91feb8f37c..9b4aabaf22 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -869,6 +869,11 @@ static void __init assign_static_memory_11(struct domain
> *d,
> }
>
> #ifdef CONFIG_STATIC_SHM
> +static bool __init is_shm_allocated_from_heap(struct shm_memnode *node)
> +{
> + return (node->meminfo.nr_banks != 0);
> +}
> +
> static int __init acquire_nr_borrower_domain(const char *shm_id,
> unsigned long *nr_borrowers)
> {
> @@ -912,12 +917,12 @@ static struct shm_memnode * __init
> find_shm_memnode(const char *shm_id)
> * This function checks whether the static shared memory region is
> * already allocated to dom_io.
> */
> -static bool __init is_shm_allocated_to_domio(paddr_t pbase)
> +static bool __init is_shm_allocated_to_domio(struct shm_memnode *node)
> {
> struct page_info *page;
> struct domain *d;
>
> - page = maddr_to_page(pbase);
> + page = maddr_to_page(node->meminfo.bank[0].start);
> d = page_get_owner_and_reference(page);
> if ( d == NULL )
> return false;
> @@ -935,67 +940,129 @@ static bool __init is_shm_allocated_to_domio(paddr_t
> pbase)
> }
>
> static mfn_t __init acquire_shared_memory_bank(struct domain *d,
> - paddr_t pbase, paddr_t psize)
> + struct shm_meminfo *meminfo,
> + bool paddr_assigned)
> {
> - mfn_t smfn;
> - unsigned long nr_pfns;
> int res;
> + unsigned int i = 0;
>
> - /*
> - * Pages of statically shared memory shall be included
> - * into domain_tot_pages().
> - */
> - nr_pfns = PFN_DOWN(psize);
> - if ( (UINT_MAX - d->max_pages) < nr_pfns )
> + for ( ; i < meminfo->nr_banks; i++ )
> {
> - printk(XENLOG_ERR "%pd: Over-allocation for d->max_pages: %lu.\n",
> - d, nr_pfns);
> + paddr_t pbase = meminfo->bank[i].start, psize =
> meminfo->bank[i].size;
> + unsigned long nr_pfns;
> +
> + /*
> + * Pages of statically shared memory shall be included
> + * into domain_tot_pages().
> + */
> + nr_pfns = PFN_DOWN(psize);
> + if ( (UINT_MAX - d->max_pages) < nr_pfns )
> + {
> + printk(XENLOG_ERR "%pd: Over-allocation for d->max_pages:
> %lu.\n",
> + d, nr_pfns);
> + return INVALID_MFN;
> + }
> + d->max_pages += nr_pfns;
> +
> + if ( paddr_assigned )
> + {
> + res = acquire_domstatic_pages(d, maddr_to_mfn(pbase), nr_pfns,
> 0);
> + if ( res )
> + {
> + printk(XENLOG_ERR
> + "%pd: failed to acquire static memory: %d.\n", d,
> res);
> + goto fail;
> + }
> + }
> + else
> + /*
> + * When host address is not provided, static shared memory is
> + * allocated from heap and shall be assigned to owner domain.
> + */
> + if ( assign_pages(maddr_to_page(pbase), nr_pfns, d, 0) )
> + goto fail;
> + }
> +
> + return maddr_to_mfn(meminfo->bank[0].start);
> +
> + fail:
> + while( --i >= 0 )
This is an infinite loop. When building with
EXTRA_CFLAGS_XEN_CORE="-Wtype-limits -Wno-error=type-limits", we see:
arch/arm/domain_build.c: In function ‘acquire_shared_memory_bank’:
arch/arm/domain_build.c:989:20: warning: comparison of unsigned expression in
‘>= 0’ is always true [-Wtype-limits]
989 | while( --i >= 0 )
| ^~
Also, the indentation seems off here.
> + d->max_pages -= PFN_DOWN(meminfo->bank[i].size);
> return INVALID_MFN;
> +}
> +
> +static int __init get_shm_pages_reference(struct domain *d,
> + struct shm_meminfo *meminfo,
> + unsigned long count)
> +{
> + struct page_info *page;
> + unsigned int i = 0, j;
> +
> + for ( ; i < meminfo->nr_banks; i++ )
> + {
> + paddr_t pbase = meminfo->bank[i].start, psize =
> meminfo->bank[i].size;
> + unsigned long nr_pages = PFN_DOWN(psize);
> +
> + page = maddr_to_page(pbase);
> + for ( j = 0; j < nr_pages; j++ )
> + {
> + if ( !get_page_nr(page + j, d, count) )
> + {
> + printk(XENLOG_ERR
> + "Failed to add %lu references to page %"PRI_mfn".\n",
> + count, mfn_x(page_to_mfn(page + j)));
> + goto fail;
> + }
> + }
> }
> - d->max_pages += nr_pfns;
>
> - smfn = maddr_to_mfn(pbase);
> - res = acquire_domstatic_pages(d, smfn, nr_pfns, 0);
> - if ( res )
> + return 0;
> +
> + fail:
> + while ( --j >= 0 )
Infinite loop [-Wtype-limits]
> + put_page_nr(page + j, count);
> + while ( --i >= 0 )
Infinite loop [-Wtype-limits]
> {
> - printk(XENLOG_ERR
> - "%pd: failed to acquire static memory: %d.\n", d, res);
> - d->max_pages -= nr_pfns;
> - return INVALID_MFN;
> + page = maddr_to_page(meminfo->bank[i].start);
> + j = PFN_DOWN(meminfo->bank[i].size);
> + while ( --j >= 0 )
Infinite loop [-Wtype-limits]
> + put_page_nr(page + j, count);
> }
> + return -EINVAL;
>
> - return smfn;
> }
> -
> static int __init assign_shared_memory(struct domain *d,
> - paddr_t pbase, paddr_t psize,
> - paddr_t gbase, const char *shm_id)
> + struct shm_memnode *node, paddr_t
> gbase,
> + bool paddr_assigned)
> {
> mfn_t smfn;
> - int ret = 0;
> - unsigned long nr_pages, nr_borrowers, i;
> - struct page_info *page;
> -
> - printk("%pd: allocate static shared memory BANK
> %#"PRIpaddr"-%#"PRIpaddr".\n",
> - d, pbase, pbase + psize);
> + int ret;
> + unsigned long nr_borrowers, i;
> + struct shm_meminfo *meminfo = &node->meminfo;
>
> - smfn = acquire_shared_memory_bank(d, pbase, psize);
> + smfn = acquire_shared_memory_bank(d, meminfo, paddr_assigned);
> if ( mfn_eq(smfn, INVALID_MFN) )
> return -EINVAL;
>
> - /*
> - * DOMID_IO is not auto-translated (i.e. it sees RAM 1:1). So we do not
> need
> - * to create mapping in the P2M.
> - */
> - nr_pages = PFN_DOWN(psize);
> - if ( d != dom_io )
> + for ( i = 0; i < meminfo->nr_banks; i++ )
> {
> - ret = guest_physmap_add_pages(d, gaddr_to_gfn(gbase), smfn,
> - PFN_DOWN(psize));
> - if ( ret )
> + paddr_t pbase = meminfo->bank[i].start, psize =
> meminfo->bank[i].size;
> +
> + /*
> + * DOMID_IO is not auto-translated (i.e. it sees RAM 1:1). So we do
> + * not need to create mapping in the P2M.
> + */
> + if ( d != dom_io )
> {
> - printk(XENLOG_ERR "Failed to map shared memory to %pd.\n", d);
> - return ret;
> + ret = guest_physmap_add_pages(d, gaddr_to_gfn(gbase),
> + maddr_to_mfn(pbase),
> + PFN_DOWN(psize));
> + if ( ret )
> + {
> + printk(XENLOG_ERR "Failed to map shared memory to %pd.\n",
> d);
> + return ret;
> + }
> + gbase += psize;
> }
> }
>
> @@ -1003,7 +1070,7 @@ static int __init assign_shared_memory(struct domain *d,
> * Get the right amount of references per page, which is the number of
> * borrower domains.
> */
> - ret = acquire_nr_borrower_domain(shm_id, &nr_borrowers);
> + ret = acquire_nr_borrower_domain(node->shm_id, &nr_borrowers);
> if ( ret )
> return ret;
>
> @@ -1015,24 +1082,30 @@ static int __init assign_shared_memory(struct domain
> *d,
> * So if the borrower is created first, it will cause adding pages
> * in the P2M without reference.
> */
> - page = mfn_to_page(smfn);
> - for ( i = 0; i < nr_pages; i++ )
> + return get_shm_pages_reference(d, meminfo, nr_borrowers);
> +}
> +
> +static int __init add_foreign_mapping_for_borrower(struct domain *d,
> + struct shm_memnode *node,
> + paddr_t gbase)
> +{
> + unsigned int i = 0;
> + struct shm_meminfo *meminfo = &node->meminfo;
> +
> + for ( ; i < meminfo->nr_banks; i++ )
> {
> - if ( !get_page_nr(page + i, d, nr_borrowers) )
> - {
> - printk(XENLOG_ERR
> - "Failed to add %lu references to page %"PRI_mfn".\n",
> - nr_borrowers, mfn_x(smfn) + i);
> - goto fail;
> - }
> + paddr_t pbase = meminfo->bank[i].start, psize =
> meminfo->bank[i].size;
> + int ret;
> +
> + /* Set up P2M foreign mapping for borrower domain. */
> + ret = map_regions_p2mt(d, _gfn(PFN_UP(gbase)), PFN_DOWN(psize),
> + _mfn(PFN_UP(pbase)), p2m_map_foreign_rw);
> + if ( ret )
> + return ret;
> + gbase += psize;
> }
>
> return 0;
> -
> - fail:
> - while ( --i >= 0 )
> - put_page_nr(page + i, nr_borrowers);
> - return ret;
> }
>
> static int __init append_shm_bank_to_domain(struct kernel_info *kinfo,
> @@ -1156,7 +1229,7 @@ static int __init process_shm(struct domain *d, struct
> kernel_info *kinfo,
>
> dt_for_each_child_node(node, shm_node)
> {
> - paddr_t gbase, pbase, psize;
> + paddr_t gbase;
> int ret = 0;
> const char *role_str;
> const char *shm_id;
> @@ -1185,15 +1258,30 @@ static int __init process_shm(struct domain *d,
> struct kernel_info *kinfo,
> shm_id);
> if ( !shm_memnode )
> return -EINVAL;
> - pbase = shm_memnode->meminfo.bank[0].start;
> - psize = shm_memnode->meminfo.bank[0].size;
> +
> + /*
> + * When host address is not provided in "xen,shared-mem",
> + * we let Xen allocate memory from heap at first domain.
> + */
> + if ( !paddr_assigned && !is_shm_allocated_from_heap(shm_memnode) )
> + {
> + if ( !allocate_domheap_memory(NULL,
> shm_memnode->meminfo.tot_size,
> + (void *)&shm_memnode->meminfo,
> + SHM_MEMINFO) )
> + {
> + printk(XENLOG_ERR
> + "Failed to allocate (%"PRIpaddr"MB) pages as static
> shared memory from heap\n",
> + shm_memnode->meminfo.tot_size >> 20);
> + return -EINVAL;
> + }
> + }
>
> /*
> * DOMID_IO is a fake domain and is not described in the Device-Tree.
> * Therefore when the owner of the shared region is DOMID_IO, we will
> * only find the borrowers.
> */
> - if ( (owner_dom_io && !is_shm_allocated_to_domio(pbase)) ||
> + if ( (owner_dom_io && !is_shm_allocated_to_domio(shm_memnode)) ||
> (!owner_dom_io && strcmp(role_str, "owner") == 0) )
> {
> /*
> @@ -1201,16 +1289,14 @@ static int __init process_shm(struct domain *d,
> struct kernel_info *kinfo,
> * specified, so they should be assigned to dom_io.
> */
> ret = assign_shared_memory(owner_dom_io ? dom_io : d,
> - pbase, psize, gbase, shm_id);
> + shm_memnode, gbase, paddr_assigned);
> if ( ret )
> return ret;
> }
>
> if ( owner_dom_io || (strcmp(role_str, "borrower") == 0) )
> {
> - /* Set up P2M foreign mapping for borrower domain. */
> - ret = map_regions_p2mt(d, _gfn(PFN_UP(gbase)), PFN_DOWN(psize),
> - _mfn(PFN_UP(pbase)), p2m_map_foreign_rw);
> + ret = add_foreign_mapping_for_borrower(d, shm_memnode, gbase);
> if ( ret )
> return ret;
> }
> @@ -1219,7 +1305,9 @@ static int __init process_shm(struct domain *d, struct
> kernel_info *kinfo,
> * Record static shared memory region info for later setting
> * up shm-node in guest device tree.
> */
> - ret = append_shm_bank_to_domain(kinfo, gbase, psize, shm_id);
> + ret = append_shm_bank_to_domain(kinfo, gbase,
> + shm_memnode->meminfo.tot_size,
> + shm_memnode->shm_id);
> if ( ret )
> return ret;
> }
> --
> 2.25.1
>
>
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |