[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [XEN v3 2/9] xen/arm: Typecast the DT values into paddr_t
On Wed, 8 Feb 2023, Ayan Kumar Halder wrote: > In future, we wish to support 32 bit physical address. > However, the current dt and fdt functions can only read u64 values. > We wish to make the DT functions read u64 as well u32 values (depending > on the width of physical address). Also, we wish to detect if any > truncation has occurred (ie while reading u32 physical addresses from > u64 values read from DT). > > device_tree_get_reg() should now be able to return paddr_t. This is > invoked by various callers to get DT address and size. > > For fdt_get_mem_rsv(), we have introduced wrapper ie > fdt_get_mem_rsv_paddr() while will invoke fdt_get_mem_rsv() and translate > u64 to paddr_t. The reason being we cannot modify fdt_get_mem_rsv() as > it has been imported from external source. > > For dt_read_number(), we have also introduced a wrapper ie > dt_read_paddr() to read physical addresses. We chose not to modify the > original function as it been used in places where it needs to > specifically u64 values from dt (For eg dt_property_read_u64()). > > Xen prints an error when it detects a truncation (during typecast > between u64 and paddr_t). It is not possible to return an error in all > scenarios. So, it is user's responsibility to check the error logs. > > To detect truncation, we right shift physical address by > "PADDR_BITS - 1" and then if the resulting number is greater than 1, > we know that truncation has occurred and an appropriate error log is > printed. > > Signed-off-by: Ayan Kumar Halder <ayan.kumar.halder@xxxxxxx> I just wanted to record that aside from Jan's feedback, this patch looks good to me > --- > > Changes from > > v1 - 1. Dropped "[XEN v1 2/9] xen/arm: Define translate_dt_address_size() for > the translation between u64 and paddr_t" and > "[XEN v1 4/9] xen/arm: Use translate_dt_address_size() to translate between > device tree addr/size and paddr_t", instead > this approach achieves the same purpose. > > 2. No need to check for truncation while converting values from u64 to > paddr_t. > > v2 - 1. Use "( (dt_start >> (PADDR_SHIFT - 1)) > 1 )" to detect truncation. > 2. Introduced libfdt_xen.h to implement fdt_get_mem_rsv_paddr > 3. Logged error messages in case truncation is detected. > > xen/arch/arm/bootfdt.c | 38 ++++++++++++++++----- > xen/arch/arm/domain_build.c | 2 +- > xen/arch/arm/include/asm/setup.h | 2 +- > xen/arch/arm/setup.c | 14 ++++---- > xen/arch/arm/smpboot.c | 2 +- > xen/include/xen/device_tree.h | 21 ++++++++++++ > xen/include/xen/libfdt/libfdt_xen.h | 52 +++++++++++++++++++++++++++++ > xen/include/xen/types.h | 2 ++ > 8 files changed, 115 insertions(+), 18 deletions(-) > create mode 100644 xen/include/xen/libfdt/libfdt_xen.h > > diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c > index 0085c28d74..f63da3e831 100644 > --- a/xen/arch/arm/bootfdt.c > +++ b/xen/arch/arm/bootfdt.c > @@ -11,7 +11,7 @@ > #include <xen/efi.h> > #include <xen/device_tree.h> > #include <xen/lib.h> > -#include <xen/libfdt/libfdt.h> > +#include <xen/libfdt/libfdt_xen.h> > #include <xen/sort.h> > #include <xsm/xsm.h> > #include <asm/setup.h> > @@ -53,10 +53,30 @@ static bool __init device_tree_node_compatible(const void > *fdt, int node, > } > > void __init device_tree_get_reg(const __be32 **cell, u32 address_cells, > - u32 size_cells, u64 *start, u64 *size) > + u32 size_cells, paddr_t *start, paddr_t > *size) > { > - *start = dt_next_cell(address_cells, cell); > - *size = dt_next_cell(size_cells, cell); > + u64 dt_start, dt_size; > + > + /* > + * dt_next_cell will return u64 whereas paddr_t may be u64 or u32. Thus, > + * there is an implicit cast from u64 to paddr_t. > + */ > + dt_start = dt_next_cell(address_cells, cell); > + dt_size = dt_next_cell(size_cells, cell); > + > + if ( (dt_start >> (PADDR_SHIFT - 1)) > 1 ) > + printk("Error: Physical address greater than max width supported\n"); > + > + if ( (dt_size >> (PADDR_SHIFT - 1)) > 1 ) > + printk("Error: Physical size greater than max width supported\n"); > + > + /* > + * Note: It is user's responsibility to check for the error messages. > + * Xen will sliently truncate in case if the address/size is greater than > + * the max supported width. > + */ > + *start = dt_start; > + *size = dt_size; > } > > static int __init device_tree_get_meminfo(const void *fdt, int node, > @@ -326,7 +346,7 @@ static int __init process_chosen_node(const void *fdt, > int node, > printk("linux,initrd-start property has invalid length %d\n", len); > return -EINVAL; > } > - start = dt_read_number((void *)&prop->data, dt_size_to_cells(len)); > + start = dt_read_paddr((void *)&prop->data, dt_size_to_cells(len)); > > prop = fdt_get_property(fdt, node, "linux,initrd-end", &len); > if ( !prop ) > @@ -339,7 +359,7 @@ static int __init process_chosen_node(const void *fdt, > int node, > printk("linux,initrd-end property has invalid length %d\n", len); > return -EINVAL; > } > - end = dt_read_number((void *)&prop->data, dt_size_to_cells(len)); > + end = dt_read_paddr((void *)&prop->data, dt_size_to_cells(len)); > > if ( start >= end ) > { > @@ -594,9 +614,11 @@ static void __init early_print_info(void) > for ( i = 0; i < nr_rsvd; i++ ) > { > paddr_t s, e; > - if ( fdt_get_mem_rsv(device_tree_flattened, i, &s, &e) < 0 ) > + > + if ( fdt_get_mem_rsv_paddr(device_tree_flattened, i, &s, &e) < 0 ) > continue; > - /* fdt_get_mem_rsv returns length */ > + > + /* fdt_get_mem_rsv_paddr returns length */ > e += s; > printk(" RESVD[%u]: %"PRIpaddr" - %"PRIpaddr"\n", i, s, e); > } > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c > index a798e0b256..4d7e67560f 100644 > --- a/xen/arch/arm/domain_build.c > +++ b/xen/arch/arm/domain_build.c > @@ -949,7 +949,7 @@ static int __init process_shm(struct domain *d, struct > kernel_info *kinfo, > BUG_ON(!prop); > cells = (const __be32 *)prop->value; > device_tree_get_reg(&cells, addr_cells, addr_cells, &pbase, &gbase); > - psize = dt_read_number(cells, size_cells); > + 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", > diff --git a/xen/arch/arm/include/asm/setup.h > b/xen/arch/arm/include/asm/setup.h > index a926f30a2b..6105e5cae3 100644 > --- a/xen/arch/arm/include/asm/setup.h > +++ b/xen/arch/arm/include/asm/setup.h > @@ -158,7 +158,7 @@ extern uint32_t hyp_traps_vector[]; > void init_traps(void); > > void device_tree_get_reg(const __be32 **cell, u32 address_cells, > - u32 size_cells, u64 *start, u64 *size); > + u32 size_cells, paddr_t *start, paddr_t *size); > > u32 device_tree_get_u32(const void *fdt, int node, > const char *prop_name, u32 dflt); > diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c > index 1f26f67b90..5ade20e6e7 100644 > --- a/xen/arch/arm/setup.c > +++ b/xen/arch/arm/setup.c > @@ -29,7 +29,7 @@ > #include <xen/virtual_region.h> > #include <xen/vmap.h> > #include <xen/trace.h> > -#include <xen/libfdt/libfdt.h> > +#include <xen/libfdt/libfdt_xen.h> > #include <xen/acpi.h> > #include <xen/warning.h> > #include <asm/alternative.h> > @@ -222,11 +222,11 @@ static void __init dt_unreserved_regions(paddr_t s, > paddr_t e, > { > paddr_t r_s, r_e; > > - if ( fdt_get_mem_rsv(device_tree_flattened, i, &r_s, &r_e ) < 0 ) > + if ( fdt_get_mem_rsv_paddr(device_tree_flattened, i, &r_s, &r_e ) < > 0 ) > /* If we can't read it, pretend it doesn't exist... */ > continue; > > - r_e += r_s; /* fdt_get_mem_rsv returns length */ > + r_e += r_s; /* fdt_get_mem_rsv_paddr returns length */ > > if ( s < r_e && r_s < e ) > { > @@ -502,13 +502,13 @@ static paddr_t __init consider_modules(paddr_t s, > paddr_t e, > { > paddr_t mod_s, mod_e; > > - if ( fdt_get_mem_rsv(device_tree_flattened, > - i - mi->nr_mods, > - &mod_s, &mod_e ) < 0 ) > + if ( fdt_get_mem_rsv_paddr(device_tree_flattened, > + i - mi->nr_mods, > + &mod_s, &mod_e ) < 0 ) > /* If we can't read it, pretend it doesn't exist... */ > continue; > > - /* fdt_get_mem_rsv returns length */ > + /* fdt_get_mem_rsv_paddr returns length */ > mod_e += mod_s; > > if ( s < mod_e && mod_s < e ) > diff --git a/xen/arch/arm/smpboot.c b/xen/arch/arm/smpboot.c > index 412ae22869..c15c177487 100644 > --- a/xen/arch/arm/smpboot.c > +++ b/xen/arch/arm/smpboot.c > @@ -159,7 +159,7 @@ static void __init dt_smp_init_cpus(void) > continue; > } > > - addr = dt_read_number(prop, dt_n_addr_cells(cpu)); > + addr = dt_read_paddr(prop, dt_n_addr_cells(cpu)); > > hwid = addr; > if ( hwid != addr ) > diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h > index a28937d12a..b61bac2931 100644 > --- a/xen/include/xen/device_tree.h > +++ b/xen/include/xen/device_tree.h > @@ -244,6 +244,27 @@ static inline u64 dt_read_number(const __be32 *cell, int > size) > return r; > } > > +/* Wrapper for dt_read_number() to return paddr_t (instead of u64) */ > +static inline paddr_t dt_read_paddr(const __be32 *cell, int size) > +{ > + u64 dt_r = 0; > + paddr_t r; > + > + dt_r = dt_read_number(cell, size); > + > + if ( (dt_r >> (PADDR_SHIFT - 1)) > 1 ) > + printk("Error: Physical address greater than max width supported\n"); > + > + /* > + * Note: It is user's responsibility to check for the error messages. > + * Xen will sliently truncate in case if the address/size is greater than > + * the max supported width. > + */ > + r = dt_r; > + > + return r; > +} > + > /* Helper to convert a number of cells to bytes */ > static inline int dt_cells_to_size(int size) > { > diff --git a/xen/include/xen/libfdt/libfdt_xen.h > b/xen/include/xen/libfdt/libfdt_xen.h > new file mode 100644 > index 0000000000..a3196dd96c > --- /dev/null > +++ b/xen/include/xen/libfdt/libfdt_xen.h > @@ -0,0 +1,52 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * xen/include/xen/libfdt/libfdt_xen.h > + * > + * Wrapper functions for device tree. This helps to convert dt values > + * between u64 and paddr_t. > + * > + * Copyright (C) 2023, Advanced Micro Devices, Inc. All Rights Reserved. > + */ > + > +#ifndef LIBFDT_XEN_H > +#define LIBFDT_XEN_H > + > +#include <xen/libfdt/libfdt.h> > + > +inline int fdt_get_mem_rsv_paddr(const void *fdt, int n, > + paddr_t *address, > + paddr_t *size) > +{ > + uint64_t dt_addr; > + uint64_t dt_size; > + int ret = 0; > + > + ret = fdt_get_mem_rsv(fdt, n, &dt_addr, &dt_size); > + > + if ( (dt_addr >> (PADDR_SHIFT - 1)) > 1 ) > + { > + printk("Error: Physical address greater than max width supported\n"); > + return -1; > + } > + > + if ( (dt_size >> (PADDR_SHIFT - 1)) > 1 ) > + { > + printk("Error: Physical size greater than max width supported\n"); > + return -1; > + } > + > + *address = dt_addr; > + *size = dt_size; > + > + return ret; > +} > + > +#endif /* LIBFDT_XEN_H */ > +/* > + * Local variables: > + * mode: C > + * c-file-style: "BSD" > + * c-basic-offset: 4 > + * indent-tabs-mode: nil > + * End: > + */ > diff --git a/xen/include/xen/types.h b/xen/include/xen/types.h > index 6aba80500a..b7255c7c38 100644 > --- a/xen/include/xen/types.h > +++ b/xen/include/xen/types.h > @@ -71,4 +71,6 @@ typedef bool bool_t; > #define test_and_set_bool(b) xchg(&(b), true) > #define test_and_clear_bool(b) xchg(&(b), false) > > +#define PADDR_SHIFT PADDR_BITS > + > #endif /* __TYPES_H__ */ > -- > 2.17.1 > >
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |