#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>
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,
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 )
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 )
{
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);
}
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",
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);
#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>
{
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 )
{
{
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 )
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 )
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)
{
--- /dev/null
+/* 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:
+ */