|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v5 05/11] xen/arm: use paddr_assigned to indicate whether host address is provided
Hi Penny,
On 06/12/2023 10:06, Penny Zheng wrote:
>
>
> We use paddr_assigned to indicate whether host address is provided, by
> checking the length of "xen,shared-mem" property.
>
> The shm matching criteria shall also be adapt to cover the new scenario, by
> adding when host address is not provided, if SHMID matches, the region size
> must exactly match too.
>
> During domain creation, right now, a static shared memory node could be
> banked with a statically configured host memory bank, or arbitrary
> host memory of dedicated size, which will later be allocated from heap by Xen.
> To cover both scenarios, we create a new structure shm_meminfo. It is very
> alike meminfo, but with the maximum array size being a smaller number
> NR_SHM_BANKS(16).
> As "shm_meminfo" is also a new member of "enum meminfo_type", we shall
> implement
> its own callback "retrieve_shm_meminfo" to have access to all MACRO
> helpers, e.g. GET_MEMBANK(...).
Previous comments apply here as well and this patch depends on the decision of
others
\wrt previous patch. I'll just add generic remarks.
>
> Also, to make codes tidy and clear, we extract codes about parsing
> "xen,shared-mem" property from function "process_shm" and move them into
> a new helper "parse_shm_property".
>
> Signed-off-by: Penny Zheng <penny.zheng@xxxxxxx>
> ---
> v1 -> v2
> - In order to get allocated banked host memory info during domain creat
> ion,
> we create a new structure shm_meminfo. It is very alike meminfo, with
> the maximum array size being NR_SHM_BANKS. As shm_meminfo is a new
> member of type meminfo_type, we shall implement its own callback
> retrieve_shm_meminfo to have access to all MACRO helpers, e.g.
> GET_MEMBANK(...)
> - rename "acquire_shm_memnode" to "find_shm_memnode"
> ---
> v2 -> v3
> - rebase and no changes
> ---
> v3 -> v4:
> - rebase and no change
> ---
> v4 -> v5:
> - fix bugs of that tot_size and membank shall not be member of union,
> but struct, to differentiate two types of static shared memory node.
> ---
> xen/arch/arm/domain_build.c | 3 +
> xen/arch/arm/include/asm/setup.h | 14 +-
> xen/arch/arm/include/asm/static-shmem.h | 3 +
> xen/arch/arm/static-shmem.c | 360 ++++++++++++++++++------
> 4 files changed, 293 insertions(+), 87 deletions(-)
>
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index a8bc78baa5..c69d481d34 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -70,6 +70,9 @@ static void __init retrieve_meminfo(void *mem, unsigned int
> *max_mem_banks,
>
> retrieve_fn __initdata retrievers[MAX_MEMINFO_TYPE] = {
> [NORMAL_MEMINFO] = retrieve_meminfo,
> +#ifdef CONFIG_STATIC_SHM
> + [SHM_MEMINFO] = retrieve_shm_meminfo,
> +#endif
> };
> #endif
>
> diff --git a/xen/arch/arm/include/asm/setup.h
> b/xen/arch/arm/include/asm/setup.h
> index bc5f08be97..043588cd2d 100644
> --- a/xen/arch/arm/include/asm/setup.h
> +++ b/xen/arch/arm/include/asm/setup.h
> @@ -59,6 +59,9 @@ struct meminfo {
>
> enum meminfo_type {
> NORMAL_MEMINFO,
> +#ifdef CONFIG_STATIC_SHM
> + SHM_MEMINFO,
> +#endif
> MAX_MEMINFO_TYPE,
> };
>
> @@ -150,7 +153,16 @@ struct bootinfo {
> unsigned int nr_nodes;
> struct {
> struct shm_node node;
> - const struct membank *membank;
> + /*
> + * For a static shared memory node, it is either banked with
> + * a statically configured host memory bank, or arbitrary host
> + * memory which will be allocated by Xen with a specified total
> + * size(tot_size).
> + */
> + struct {
> + const struct membank *membank;
> + paddr_t tot_size;
> + };
> } shm_nodes[NR_MEM_BANKS];
> } shminfo;
> #endif
> diff --git a/xen/arch/arm/include/asm/static-shmem.h
> b/xen/arch/arm/include/asm/static-shmem.h
> index 66a3f4c146..a67445cec8 100644
> --- a/xen/arch/arm/include/asm/static-shmem.h
> +++ b/xen/arch/arm/include/asm/static-shmem.h
> @@ -24,6 +24,9 @@ static inline int process_shm_chosen(struct domain *d,
> int process_shm_node(const void *fdt, int node, uint32_t address_cells,
> uint32_t size_cells);
>
> +void retrieve_shm_meminfo(void *mem, unsigned int *max_mem_banks,
> + struct membank **bank,
> + unsigned int **nr_banks);
> #else /* !CONFIG_STATIC_SHM */
>
> static inline int make_resv_memory_node(const struct domain *d, void *fdt,
> diff --git a/xen/arch/arm/static-shmem.c b/xen/arch/arm/static-shmem.c
> index 6a3d8a54bd..a9eb26d543 100644
> --- a/xen/arch/arm/static-shmem.c
> +++ b/xen/arch/arm/static-shmem.c
> @@ -6,6 +6,50 @@
> #include <asm/domain_build.h>
> #include <asm/static-shmem.h>
>
> +#define NR_SHM_BANKS 16
> +
> +/*
> + * There are two types of static shared memory node:
> + * A static shared memory node could be banked with a statically
> + * configured host memory bank, or a set of arbitrary host memory
> + * banks allocated from heap by Xen on runtime.
> + */
> +struct shm_meminfo {
> + unsigned int nr_banks;
> + struct membank bank[NR_SHM_BANKS];
> + paddr_t tot_size;
> +};
> +
> +/*
> + * struct shm_memnode holds banked host memory info for a static
> + * shared memory node
> + */
> +struct shm_memnode {
With the number of structures introduced in this series, the chosen naming does
not help
> + char shm_id[MAX_SHM_ID_LENGTH];
> + struct shm_meminfo meminfo;
> +};
> +
> +static __initdata struct {
> + unsigned int nr_nodes;
> + struct shm_memnode node[NR_MEM_BANKS];
> +} shm_memdata;
> +
> +void __init retrieve_shm_meminfo(void *mem, unsigned int *max_mem_banks,
> + struct membank **bank,
> + unsigned int **nr_banks)
> +{
> + struct shm_meminfo *meminfo = (struct shm_meminfo *)mem;
> +
> + if ( max_mem_banks )
> + *max_mem_banks = NR_SHM_BANKS;
> +
> + if ( nr_banks )
> + *nr_banks = &(meminfo->nr_banks);
> +
> + if ( bank )
> + *bank = meminfo->bank;
> +}
> +
> static int __init acquire_nr_borrower_domain(const char *shm_id,
> unsigned long *nr_borrowers)
> {
> @@ -172,6 +216,129 @@ static int __init append_shm_bank_to_domain(struct
> kernel_info *kinfo,
> return 0;
> }
>
> +static struct shm_memnode * __init find_shm_memnode(const char *shm_id)
> +{
> + unsigned int i;
> + struct shm_memnode *shm_memnode;
> +
> + for ( i = 0 ; i < shm_memdata.nr_nodes; i++ )
> + {
> + shm_memnode = &shm_memdata.node[i];
> +
> + if ( strcmp(shm_id, shm_memnode->shm_id) == 0 )
> + return shm_memnode;
> + }
> +
> + if ( i == NR_MEM_BANKS )
> + return NULL;
> +
We can only be here if i == 0 i.e. no shm nodes?
> + shm_memnode = &shm_memdata.node[i];
> + safe_strcpy(shm_memnode->shm_id, shm_id);
> + shm_memdata.nr_nodes++;
leave one empty line here, please
> + return shm_memnode;
> +}
> +
> +/* Parse "xen,shared-mem" property in static shared memory node */
> +static struct shm_memnode * __init parse_shm_property(struct domain *d,
> + const struct dt_device_node *dt_node,
> + bool *paddr_assigned, paddr_t *gbase,
> + const char *shm_id)
> +{
> + uint32_t addr_cells, size_cells;
> + const struct dt_property *prop;
> + const __be32 *cells;
> + uint32_t len;
> + unsigned int i;
> + paddr_t pbase, psize;
> + struct shm_memnode *shm_memnode;
> +
> + /* xen,shared-mem = <pbase, gbase, size>; And pbase could be optional. */
> + prop = dt_find_property(dt_node, "xen,shared-mem", &len);
> + BUG_ON(!prop);
> + cells = (const __be32 *)prop->value;
> +
> + addr_cells = dt_n_addr_cells(dt_node);
> + size_cells = dt_n_size_cells(dt_node);
> + if ( len != dt_cells_to_size(addr_cells + size_cells + addr_cells) )
> + {
> + /* pbase is not provided in "xen,shared-mem" */
> + if ( len == dt_cells_to_size(size_cells + addr_cells) )
> + *paddr_assigned = false;
what if paddr_assigned is NULL? Also, wouldn't pbase_provided be a better name?
> + else
> + {
> + printk("fdt: invalid `xen,shared-mem` property.\n");
If you are modifying the code anyway, please drop '.' at the end of line. No
need for that
> + return NULL;
> + }
> + }
> +
> + /*
> + * If we firstly process the shared memory node with unique "xen,shm-id",
> + * we allocate a new member "shm_memnode" for it in shm_memdata.
> + */
> + shm_memnode = find_shm_memnode(shm_id);
> + BUG_ON(!shm_memnode);
> + if ( !(*paddr_assigned) )
> + {
> + device_tree_get_reg(&cells, addr_cells, size_cells, gbase, &psize);
> + /* Whether it is a new shm node? */
> + if ( shm_memnode->meminfo.tot_size == 0 )
> + goto out_early1;
> + else
no need for this else
> + goto out_early2;
> + }
> + else
no need for this else. You can be here only if pbase was specified
> + {
> + device_tree_get_reg(&cells, addr_cells, addr_cells, &pbase, gbase);
> + psize = dt_read_number(cells, size_cells);
> +
> + /* Whether it is a new shm node? */
> + if ( shm_memnode->meminfo.nr_banks != 0 )
In previous check with the same comment, you use tot_size to determine if it is
a new shm mode
> + goto out_early2;
> + }
> +
> + /*
> + * The static shared memory node #dt_node is banked with a
> + * statically configured host memory bank.
> + */
> + shm_memnode->meminfo.bank[0].start = pbase;
> + shm_memnode->meminfo.bank[0].size = psize;
> + shm_memnode->meminfo.nr_banks = 1;
You should be first checking for below error conditions before doing assignment?
> +
> + if ( !IS_ALIGNED(pbase, PAGE_SIZE) )
> + {
> + printk("%pd: physical address 0x%"PRIpaddr" is not suitably
> aligned.\n",
> + d, pbase);
> + return NULL;
> + }
> +
> + for ( i = 0; i < PFN_DOWN(psize); i++ )
> + if ( !mfn_valid(mfn_add(maddr_to_mfn(pbase), i)) )
> + {
> + printk("%pd: invalid physical MFN 0x%"PRI_mfn"\n for static
> shared memory node\n",
> + d, mfn_x(mfn_add(maddr_to_mfn(pbase), i)));
> + return NULL;
> + }
> +
> + out_early1:
not really informative. How about new_shm_node:?
> + if ( !IS_ALIGNED(psize, PAGE_SIZE) )
> + {
> + printk("%pd: size 0x%"PRIpaddr" is not suitably aligned\n",
> + d, psize);
> + return NULL;
> + }
> + shm_memnode->meminfo.tot_size = psize;
> +
> + out_early2:
> + if ( !IS_ALIGNED(*gbase, PAGE_SIZE) )
> + {
> + printk("%pd: guest address 0x%"PRIpaddr" is not suitably aligned.\n",
> + d, *gbase);
> + return NULL;
> + }
> +
> + return shm_memnode;
> +}
> +
> int __init process_shm(struct domain *d, struct kernel_info *kinfo,
> const struct dt_device_node *node)
> {
> @@ -179,51 +346,17 @@ int __init process_shm(struct domain *d, struct
> kernel_info *kinfo,
>
> dt_for_each_child_node(node, shm_node)
> {
> - const struct dt_property *prop;
> - const __be32 *cells;
> - uint32_t addr_cells, size_cells;
> paddr_t gbase, pbase, psize;
> int ret = 0;
> - unsigned int i;
> const char *role_str;
> const char *shm_id;
> bool owner_dom_io = true;
> + bool paddr_assigned = true;
wouldn't it be better if parse_shm_property was responsible for setting this to
either false or true.
At the moment it only sets it to false.
> + struct shm_memnode *shm_memnode;
>
> if ( !dt_device_is_compatible(shm_node,
> "xen,domain-shared-memory-v1") )
> continue;
>
> - /*
> - * xen,shared-mem = <pbase, gbase, size>;
> - * TODO: pbase is optional.
> - */
> - addr_cells = dt_n_addr_cells(shm_node);
> - size_cells = dt_n_size_cells(shm_node);
> - prop = dt_find_property(shm_node, "xen,shared-mem", NULL);
> - BUG_ON(!prop);
> - cells = (const __be32 *)prop->value;
> - device_tree_get_reg(&cells, addr_cells, addr_cells, &pbase, &gbase);
> - psize = dt_read_paddr(cells, size_cells);
> - if ( !IS_ALIGNED(pbase, PAGE_SIZE) || !IS_ALIGNED(gbase, PAGE_SIZE) )
> - {
> - printk("%pd: physical address 0x%"PRIpaddr", or guest address
> 0x%"PRIpaddr" is not suitably aligned.\n",
> - d, pbase, gbase);
> - return -EINVAL;
> - }
> - if ( !IS_ALIGNED(psize, PAGE_SIZE) )
> - {
> - printk("%pd: size 0x%"PRIpaddr" is not suitably aligned\n",
> - d, psize);
> - return -EINVAL;
> - }
> -
> - for ( i = 0; i < PFN_DOWN(psize); i++ )
> - if ( !mfn_valid(mfn_add(maddr_to_mfn(pbase), i)) )
> - {
> - printk("%pd: invalid physical address 0x%"PRI_mfn"\n",
> - d, mfn_x(mfn_add(maddr_to_mfn(pbase), i)));
> - return -EINVAL;
> - }
> -
> /*
> * "role" property is optional and if it is defined explicitly,
> * then the owner domain is not the default "dom_io" domain.
> @@ -238,6 +371,13 @@ int __init process_shm(struct domain *d, struct
> kernel_info *kinfo,
> }
> BUG_ON((strlen(shm_id) <= 0) || (strlen(shm_id) >=
> MAX_SHM_ID_LENGTH));
>
> + shm_memnode = parse_shm_property(d, shm_node, &paddr_assigned,
> &gbase,
> + shm_id);
> + if ( !shm_memnode )
> + return -EINVAL;
empty line here please
> + pbase = shm_memnode->meminfo.bank[0].start;
> + psize = shm_memnode->meminfo.bank[0].size;
> +
> /*
> * 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
> @@ -349,10 +489,10 @@ int __init process_shm_node(const void *fdt, int node,
> uint32_t address_cells,
> {
> const struct fdt_property *prop, *prop_id, *prop_role;
> const __be32 *cell;
> - paddr_t paddr, gaddr, size, end;
> + paddr_t paddr, gaddr, size;
> unsigned int i;
> int len;
> - bool owner = false;
> + bool owner = false, paddr_assigned = true;
> const char *shm_id;
>
> if ( address_cells < 1 || size_cells < 1 )
> @@ -404,96 +544,140 @@ int __init process_shm_node(const void *fdt, int node,
> uint32_t address_cells,
>
> if ( len != dt_cells_to_size(address_cells + size_cells + address_cells)
> )
> {
> + /* paddr is not provided in "xen,shared-mem" */
> if ( len == dt_cells_to_size(size_cells + address_cells) )
> - printk("fdt: host physical address must be chosen by users at
> the moment.\n");
> -
> - printk("fdt: invalid `xen,shared-mem` property.\n");
> - return -EINVAL;
> + paddr_assigned = false;
> + else
> + {
> + printk("fdt: invalid `xen,shared-mem` property.\n");
> + return -EINVAL;
> + }
> }
>
> cell = (const __be32 *)prop->data;
> - device_tree_get_reg(&cell, address_cells, address_cells, &paddr, &gaddr);
> - size = dt_next_cell(size_cells, &cell);
> -
> - if ( !size )
> + if ( !paddr_assigned )
> + device_tree_get_reg(&cell, address_cells, size_cells, &gaddr, &size);
> + else
> {
> - printk("fdt: the size for static shared memory region can not be
> zero\n");
> - return -EINVAL;
> - }
> + paddr_t end;
> +
> + device_tree_get_reg(&cell, address_cells, address_cells, &paddr,
> &gaddr);
> + size = dt_next_cell(size_cells, &cell);
> +
> + if ( !size )
> + {
> + printk("fdt: the size for static shared memory region can not be
> zero\n");
> + return -EINVAL;
> + }
> +
> + end = paddr + size;
> + if ( end <= paddr )
> + {
> + printk("fdt: static shared memory region %s overflow\n", shm_id);
> + return -EINVAL;
> + }
>
> - end = paddr + size;
> - if ( end <= paddr )
> - {
> - printk("fdt: static shared memory region %s overflow\n", shm_id);
> - return -EINVAL;
> }
>
> for ( i = 0; i < bootinfo.shminfo.nr_nodes; i++ )
> {
> - paddr_t bank_start = bootinfo.shminfo.shm_nodes[i].membank->start;
> - paddr_t bank_size = bootinfo.shminfo.shm_nodes[i].membank->size;
> const char *bank_id = bootinfo.shminfo.shm_nodes[i].node.shm_id;
> + bool is_shmid_equal = strncmp(shm_id, bank_id, MAX_SHM_ID_LENGTH) ==
> 0 ?
> + true : false;
>
> /*
> * Meet the following check:
> + * when host address is provided:
> * 1) The shm ID matches and the region exactly match
> * 2) The shm ID doesn't match and the region doesn't overlap
> * with an existing one
> + * when host address is not provided:
> + * 1) The shm ID matches and the region size exactly match
> + */
> + /*
> + * For a static shared memory node, it is either banked with
> + * a statically configured host memory bank(membank != NULL), or
> + * arbitrary host memory which will later be allocated by Xen(
> + * tot_size != 0).
> */
> - if ( paddr == bank_start && size == bank_size )
> + if ( bootinfo.shminfo.shm_nodes[i].membank != NULL )
> {
> - if ( strncmp(shm_id, bank_id, MAX_SHM_ID_LENGTH) == 0 )
> + paddr_t bank_start =
> bootinfo.shminfo.shm_nodes[i].membank->start;
> + paddr_t bank_size = bootinfo.shminfo.shm_nodes[i].membank->size;
both lines > 80 chars
> + bool is_same_region = (paddr == bank_start) && (size ==
> bank_size) ?
> + true : false;
> +
> + if ( is_same_region && is_shmid_equal )
> break;
> - else
> + else if ( is_same_region || is_shmid_equal )
> {
> printk("fdt: xen,shm-id %s does not match for all the nodes
> using the same region.\n",
> shm_id);
> return -EINVAL;
> }
continue here and ...
> }
> - else if ( strcmp(shm_id, mem->bank[i].shm_id) != 0 )
> - continue;
> else
no need for this else
> {
> - printk("fdt: different shared memory region could not share the
> same shm ID %s\n",
> - shm_id);
> - return -EINVAL;
> + paddr_t tot_size = bootinfo.shminfo.shm_nodes[i].tot_size;
> + bool is_same_region = tot_size == size ? true : false;
> +
> + if ( !paddr_assigned && is_same_region && is_shmid_equal )
> + break;
> + else if ( is_shmid_equal )
> + {
> + if ( paddr_assigned )
> + {
> + printk("fdt: two different types of static shared memory
> region could not share the same shm-id %s\n",
> + shm_id);
> + return -EINVAL;
> + }
> +
> + printk("fdt: when host address is not provided, if
> xen,shm-id matches, size must stay the same too(%"PRIpaddr" ->
> %"PRIpaddr")\n",
> + size, tot_size);
> + return -EINVAL;
> + }
> }
> }
>
> if ( i == bootinfo.shminfo.nr_nodes )
> {
> - struct meminfo *mem = &bootinfo.reserved_mem;
> -
> - if ( (i < NR_MEM_BANKS) && (mem->nr_banks < NR_MEM_BANKS) )
> + if ( i < NR_MEM_BANKS )
if ( i == NR_MEM_BANKS )
goto fail;
this would reduce the number of if/else blocks
> {
> - struct membank *membank = &mem->bank[mem->nr_banks];
> struct shm_node *shm_node = &bootinfo.shminfo.shm_nodes[i].node;
> -
> - if ( check_reserved_regions_overlap(paddr, size) )
> - return -EINVAL;
> -
> - /* Static shared memory shall be reserved from any other use. */
> - membank->start = paddr;
> - membank->size = size;
> - membank->type = MEMBANK_STATIC_DOMAIN;
> - mem->nr_banks++;
> + struct meminfo *mem = &bootinfo.reserved_mem;
>
> /* Record static shared memory node info in bootinfo.shminfo */
> safe_strcpy(shm_node->shm_id, shm_id);
> - /*
> - * Reserved memory bank is recorded together to assist
> - * doing shm node verification.
> - */
> - bootinfo.shminfo.shm_nodes[i].membank = membank;
> bootinfo.shminfo.nr_nodes++;
> +
> + if ( !paddr_assigned )
> + bootinfo.shminfo.shm_nodes[i].tot_size = size;
> + else if ( mem->nr_banks < NR_MEM_BANKS )
> + {
> + struct membank *membank = &mem->bank[mem->nr_banks];
> +
> + if ( check_reserved_regions_overlap(paddr, size) )
> + return -EINVAL;
> +
> + /* Static shared memory shall be reserved from any other
> use. */
> + membank->start = paddr;
> + membank->size = size;
> + membank->type = MEMBANK_STATIC_DOMAIN;
> + mem->nr_banks++;
> +
> + /*
> + * Reserved memory bank is recorded together to assist
> + * doing shm node verification.
> + */
> + bootinfo.shminfo.shm_nodes[i].membank = membank;
> + }
> + else
> + goto fail;
> }
> else
> - {
> - printk("Warning: Max number of supported memory regions
> reached.\n");
> - return -ENOSPC;
> - }
> + goto fail;
> }
> +
> /*
> * keep a count of the number of borrowers, which later may be used
> * to calculate the reference count.
> @@ -502,6 +686,10 @@ int __init process_shm_node(const void *fdt, int node,
> uint32_t address_cells,
> bootinfo.shminfo.shm_nodes[i].node.nr_shm_borrowers++;
>
> return 0;
> +
> + fail:
> + printk("Warning: Max number of supported memory regions reached.\n");
> + return -ENOSPC;
> }
>
> int __init make_resv_memory_node(const struct domain *d, void *fdt,
> --
> 2.25.1
>
~Michal
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |