mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
xen/arm: Typecast the DT values into paddr_t
The DT functions (dt_read_number(), device_tree_get_reg(), fdt_get_mem_rsv()) currently accept or return 64-bit values. In future when we support 32-bit physical address, these DT functions are expected to accept/return 32-bit or 64-bit values (depending on the width of physical address). Also, we wish to detect if any truncation has occurred (i.e. while parsing 32-bit physical addresses from 64-bit 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 a wrapper named fdt_get_mem_rsv_paddr() which will invoke fdt_get_mem_rsv() and translate uint64_t 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 named dt_read_paddr() dt_read_paddr() to read physical addresses. We chose not to modify the original function as it is used in places where it needs to specifically read 64-bit values from dt (For e.g. dt_property_read_u64()). Xen prints warning when it detects truncation in cases where it is not able to return error. Also, replaced u32/u64 with uint32_t/uint64_t in the functions touched by the code changes. Signed-off-by: Ayan Kumar Halder <ayan.kumar.halder@amd.com> Reviewed-by: Julien Grall <jgrall@amazon.com> Reviewed-by: Michal Orzel <michal.orzel@amd.com>
This commit is contained in:
1 parent
f37a598139
commit
3d4b02468a
7 files changed
+130
-20
No files matched your search
+37
-9
@@ -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>
|
||||
@@ -52,11 +52,37 @@ static bool __init device_tree_node_compatible(const void *fdt, int node,
|
||||
return false;
|
||||
}
|
||||
|
||||
void __init device_tree_get_reg(const __be32 **cell, u32 address_cells,
|
||||
u32 size_cells, u64 *start, u64 *size)
|
||||
void __init device_tree_get_reg(const __be32 **cell, uint32_t address_cells,
|
||||
uint32_t size_cells, paddr_t *start,
|
||||
paddr_t *size)
|
||||
{
|
||||
*start = dt_next_cell(address_cells, cell);
|
||||
*size = dt_next_cell(size_cells, cell);
|
||||
uint64_t dt_start, dt_size;
|
||||
|
||||
/*
|
||||
* dt_next_cell will return uint64_t whereas paddr_t may not be 64-bit.
|
||||
* Thus, there is an implicit cast from uint64_t to paddr_t.
|
||||
*/
|
||||
dt_start = dt_next_cell(address_cells, cell);
|
||||
dt_size = dt_next_cell(size_cells, cell);
|
||||
|
||||
if ( dt_start != (paddr_t)dt_start )
|
||||
{
|
||||
printk("Physical address greater than max width supported\n");
|
||||
WARN();
|
||||
}
|
||||
|
||||
if ( dt_size != (paddr_t)dt_size )
|
||||
{
|
||||
printk("Physical size greater than max width supported\n");
|
||||
WARN();
|
||||
}
|
||||
|
||||
/*
|
||||
* Xen will truncate the address/size if it is greater than the maximum
|
||||
* supported width and it will give an appropriate warning.
|
||||
*/
|
||||
*start = dt_start;
|
||||
*size = dt_size;
|
||||
}
|
||||
|
||||
static int __init device_tree_get_meminfo(const void *fdt, int node,
|
||||
@@ -329,7 +355,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 )
|
||||
@@ -342,7 +368,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 )
|
||||
{
|
||||
@@ -593,9 +619,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);
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -159,8 +159,8 @@ const char *boot_module_kind_as_string(bootmodule_kind kind);
|
||||
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);
|
||||
void device_tree_get_reg(const __be32 **cell, uint32_t address_cells,
|
||||
uint32_t size_cells, paddr_t *start, paddr_t *size);
|
||||
|
||||
u32 device_tree_get_u32(const void *fdt, int node,
|
||||
const char *prop_name, u32 dflt);
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
@@ -592,13 +592,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 )
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -241,6 +241,33 @@ static inline u64 dt_read_number(const __be32 *cell, int size)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Wrapper for dt_read_number() to return paddr_t (instead of uint64_t) */
|
||||
static inline paddr_t dt_read_paddr(const __be32 *cell, int size)
|
||||
{
|
||||
uint64_t dt_r;
|
||||
paddr_t r;
|
||||
|
||||
/*
|
||||
* dt_read_number will return uint64_t whereas paddr_t may not be 64-bit.
|
||||
* Thus, there is an implicit cast from uint64_t to paddr_t.
|
||||
*/
|
||||
dt_r = dt_read_number(cell, size);
|
||||
|
||||
if ( dt_r != (paddr_t)dt_r )
|
||||
{
|
||||
printk("Physical address greater than max width supported\n");
|
||||
WARN();
|
||||
}
|
||||
|
||||
/*
|
||||
* Xen will truncate the address/size if it is greater than the maximum
|
||||
* supported width and it will give an appropriate warning.
|
||||
*/
|
||||
r = dt_r;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Helper to convert a number of cells to bytes */
|
||||
static inline int dt_cells_to_size(int size)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* xen/include/xen/libfdt/libfdt-xen.h
|
||||
*
|
||||
* Wrapper functions for device tree. This helps to convert dt values
|
||||
* between uint64_t 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>
|
||||
|
||||
static 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;
|
||||
|
||||
ret = fdt_get_mem_rsv(fdt, n, &dt_addr, &dt_size);
|
||||
if ( ret < 0 )
|
||||
return ret;
|
||||
|
||||
if ( dt_addr != (paddr_t)dt_addr )
|
||||
{
|
||||
printk("Error: Physical address greater than max width supported\n");
|
||||
return -FDT_ERR_MAX;
|
||||
}
|
||||
|
||||
if ( dt_size != (paddr_t)dt_size )
|
||||
{
|
||||
printk("Error: Physical size greater than max width supported\n");
|
||||
return -FDT_ERR_MAX;
|
||||
}
|
||||
|
||||
*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:
|
||||
*/
|
||||