[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 1/3] xen/arm: Add memory overlap check for bootinfo.reserved_mem



On Wed, 7 Dec 2022, Julien Grall wrote:
> Hi Stefano,
> 
> On 07/12/2022 01:37, Stefano Stabellini wrote:
> > On Mon, 5 Dec 2022, Henry Wang wrote:
> > > As we are having more and more types of static region, and all of
> > > these static regions are defined in bootinfo.reserved_mem, it is
> > > necessary to add the overlap check of reserved memory regions in Xen,
> > > because such check will help user to identify the misconfiguration in
> > > the device tree at the early stage of boot time.
> > > 
> > > Currently we have 3 types of static region, namely (1) static memory,
> > > (2) static heap, (3) static shared memory. (1) and (2) are parsed by
> > > the function `device_tree_get_meminfo()` and (3) is parsed using its
> > > own logic. Therefore, to unify the checking logic for all of these
> > > types of static region, this commit firstly introduces a helper
> > > `check_reserved_regions_overlap()` to check if an input physical
> > > address range is overlapping with the existing reserved memory regions
> > > defined in bootinfo. After that, use this helper in
> > > `device_tree_get_meminfo()` to do the overlap check of (1) and (2)
> > > and replace the original overlap check of (3) with this new helper.
> > > 
> > > Signed-off-by: Henry Wang <Henry.Wang@xxxxxxx>
> > 
> > I wonder if the check should only be done #ifdef DEBUG. The idea would
> > be that a given static configuration should be validated and corrected
> > before going into production. By the time you go in production, it is
> > too late to do checks anyway. Especially the panic below.
> > 
> > Julien, Bertrand, what do you think about this?
> 
> The integrator may be a different person (or even a different company) than
> the one building Xen.
> 
> So I think, the new check shoudl not be protected by CONFIG_DEBUG.

It is almost like we need something else to say "this is really a
production build, disable all checks, I want it to go fast and be as
small as possible". Maybe it would be better as a new kconfig option?

In any case, this patch is OK as is.


> That said, any output in bootfd will only printed when earlyprintk is enabled.
> I think we should consider to support dynamic early printk. Anyway, that's
> something that doesn't need to be handled in this series.

+1


> > > ---
> > >   xen/arch/arm/bootfdt.c           | 13 ++++----
> > >   xen/arch/arm/include/asm/setup.h |  2 ++
> > >   xen/arch/arm/setup.c             | 52 ++++++++++++++++++++++++++++++++
> > >   3 files changed, 60 insertions(+), 7 deletions(-)
> > > 
> > > diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
> > > index 6014c0f852..b31379b9ac 100644
> > > --- a/xen/arch/arm/bootfdt.c
> > > +++ b/xen/arch/arm/bootfdt.c
> > > @@ -91,6 +91,9 @@ static int __init device_tree_get_meminfo(const void
> > > *fdt, int node,
> > >       for ( i = 0; i < banks && mem->nr_banks < NR_MEM_BANKS; i++ )
> > >       {
> > >           device_tree_get_reg(&cell, address_cells, size_cells, &start,
> > > &size);
> > > +        if ( mem == &bootinfo.reserved_mem &&
> > > +             check_reserved_regions_overlap(start, size) )
> > > +            return -EINVAL;
> > >           /* Some DT may describe empty bank, ignore them */
> > >           if ( !size )
> > >               continue;
> > > @@ -485,7 +488,9 @@ static int __init process_shm_node(const void *fdt,
> > > int node,
> > >                   return -EINVAL;
> > >               }
> > >   -            if ( (end <= mem->bank[i].start) || (paddr >= bank_end) )
> > > +            if ( check_reserved_regions_overlap(paddr, size) )
> > > +                return -EINVAL;
> > > +            else
> > >               {
> > >                   if ( strcmp(shm_id, mem->bank[i].shm_id) != 0 )
> > >                       continue;
> > > @@ -496,12 +501,6 @@ static int __init process_shm_node(const void *fdt,
> > > int node,
> > >                       return -EINVAL;
> > >                   }
> > >               }
> > > -            else
> > > -            {
> > > -                printk("fdt: shared memory region overlap with an
> > > existing entry %#"PRIpaddr" - %#"PRIpaddr"\n",
> > > -                        mem->bank[i].start, bank_end);
> > > -                return -EINVAL;
> > > -            }
> > >           }
> > >       }
> > >   diff --git a/xen/arch/arm/include/asm/setup.h
> > > b/xen/arch/arm/include/asm/setup.h
> > > index fdbf68aadc..6a9f88ecbb 100644
> > > --- a/xen/arch/arm/include/asm/setup.h
> > > +++ b/xen/arch/arm/include/asm/setup.h
> > > @@ -143,6 +143,8 @@ void fw_unreserved_regions(paddr_t s, paddr_t e,
> > >   size_t boot_fdt_info(const void *fdt, paddr_t paddr);
> > >   const char *boot_fdt_cmdline(const void *fdt);
> > >   +int check_reserved_regions_overlap(paddr_t region_start, paddr_t
> > > region_size);
> > > +
> > >   struct bootmodule *add_boot_module(bootmodule_kind kind,
> > >                                      paddr_t start, paddr_t size, bool
> > > domU);
> > >   struct bootmodule *boot_module_find_by_kind(bootmodule_kind kind);
> > > diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> > > index 4395640019..94d232605e 100644
> > > --- a/xen/arch/arm/setup.c
> > > +++ b/xen/arch/arm/setup.c
> > > @@ -270,6 +270,42 @@ static void __init dt_unreserved_regions(paddr_t s,
> > > paddr_t e,
> > >       cb(s, e);
> > >   }
> > >   +static int __init overlap_check(void *bootinfo_type,
> > > +                                paddr_t region_start, paddr_t region_end)
> > > +{
> > > +    unsigned int i, num = 0;
> > > +    paddr_t bank_start = INVALID_PADDR, bank_end = 0;
> > > +    char *type_str = "NONAME";
> > > +
> > > +    if ( bootinfo_type == &bootinfo.reserved_mem )
> > > +    {
> > > +        num = bootinfo.reserved_mem.nr_banks;
> > > +        type_str = "reserved_mem";
> > > +    }
> > > +    else
> > > +        panic("Invalid bootinfo type passed to overlap check\n");
> > > +
> > > +    for ( i = 0; i < num; i++ )
> > > +    {
> > > +        if ( bootinfo_type == &bootinfo.reserved_mem )
> > > +        {
> > > +            bank_start = bootinfo.reserved_mem.bank[i].start;
> > > +            bank_end = bank_start + bootinfo.reserved_mem.bank[i].size;
> > > +        }
> > > +
> > > +        if ( region_end <= bank_start || region_start >= bank_end )
> > > +            continue;
> > > +        else
> > > +        {
> > > +            printk("%s: Region %#"PRIpaddr" - %#"PRIpaddr" overlapping
> > > with bank[%u] %#"PRIpaddr" - %#"PRIpaddr"\n",
> > > +                   type_str, region_start, region_end, i, bank_start,
> > > bank_end);
> > > +            return -EINVAL;
> > > +        }
> > > +    }
> > > +
> > > +    return 0;
> > > +}
> > 
> > As much as I dislike MACROs in general I think this function should be
> > written as a MACRO so that we can write it once for all use cases. The
> > below in not compiled and not tested, just for explanation purposes.
> > Look how much simpler the code becomes.
> 
> I agree the duplication is not nice. But it is not clear to me why a static
> inline function cannot be used.

You mean a macro generating static inline functions?

It cannot be a single static inline function because the bootinfo
arguments are of three different types, it just happens that all three
have a "start" and "size" struct member so it works great with a macro,
but doesn't for a function.


> > 
> > #define overlap_check(bootinfo,     \
> >                        num,          \
> >                        region_start, \
> >                        region_end)   \
> > ({  \
> >      unsigned int i, ret; \
> >      paddr_t bank_start = INVALID_PADDR, bank_end = 0; \
> >      \
> >      for ( i = 0; i < num; i++ ) \
> >      { \
> >          bank_start = bootinfo->start; \
> >          bank_end = bank_start + bootinfo->size; \
> >      \
> >          if ( region_end <= bank_start || region_start >= bank_end ) \
> >              continue; \
> >          else \
> >          { \
> >              printk("Region %#"PRIpaddr" - %#"PRIpaddr" overlapping with
> > bank[%u] %#"PRIpaddr" - %#"PRIpaddr"\n", \
> >                     region_start, region_end, i, bank_start, bank_end); \
> >              ret = -EINVAL; \
> >              break; \
> >          } \
> >      } \
> >      \
> >      retval = 0; \
> >      retval;\
> > })
> > 
> > 
> > And the caller:
> > 
> > check_reserved_regions_overlap(&bootinfo.reserved_mem,
> >                                 bootinfo.reserved_mem.nr_banks,
> >                                 start, size);



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.