[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: > On 07/12/2022 22:27, Stefano Stabellini wrote: > > On Wed, 7 Dec 2022, Julien Grall wrote: > > > 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? > > I am not convinced this should be a Kconfig option for the same reason as > before: the integrator may be a different entity and you want to be able to > check your setup with the final binary. > > So this most likely want to a be a command line 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. > > It is not clear to me what are the three types you are referring to. Looking > at the definition of bootinfo is: > > struct bootinfo { > struct meminfo mem; > /* The reserved regions are only used when booting using Device-Tree */ > struct meminfo reserved_mem; > struct bootmodules modules; > struct bootcmdlines cmdlines; > #ifdef CONFIG_ACPI > struct meminfo acpi; > #endif > bool static_heap; > }; > > cmdlines is something uninteresting here. So we have two types: > - bootmodules for modules > - meminfo used by reserved_mem, mem and acpi > > Looking in details the code, now I understand why you suggested the macro. > This is far better than the checking what the array type (not very scalable). Thank you :-) > Personally, I think trying to share the code between the two types is a bit > odd. The logic is the same today, but I envision to merge reserved_mem, mem > and acpi in a single array (it would look like the E820) as this would make > easier to find the caching attributes per regions when mapping the RAM. So > sharing the code would not be possible. > > That said, if you really want to share the code between the two types. Then I > would prefer one of the following option: > 1) Provide a callback that is used to fetch the information from the array > 2) Provide a common structure that could be used by the function. > > This would match other generic function like sort & co. I think option 2) would be the best but I couldn't think of a simple way to do it (without using a union and I thought a union would not make things nicer in this case). Rather than option 1), I think I would rather have 2 different functions to check struct bootmodules and struct meminfo, or the macro.
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |