* [PATCH v4 0/2] arm: extended regions fixes
@ 2025-06-09 18:34 Stewart Hildebrand
2025-06-09 18:34 ` [PATCH v4 1/2] xen/arm: exclude xen,reg from direct-map domU extended regions Stewart Hildebrand
2025-06-09 18:34 ` [PATCH v4 2/2] tools/arm: exclude iomem from " Stewart Hildebrand
0 siblings, 2 replies; 7+ messages in thread
From: Stewart Hildebrand @ 2025-06-09 18:34 UTC (permalink / raw)
To: xen-devel
Cc: Stewart Hildebrand, Stefano Stabellini, Julien Grall,
Bertrand Marquis, Michal Orzel, Volodymyr Babchuk, Anthony PERARD,
Juergen Gross
v3->v4:
* see individual patches
v2->v3:
* drop committed patches
* add ("xen/arm: exclude xen,reg from direct-map domU extended regions")
v1->v2:
* rebase
* address feedback
Stewart Hildebrand (2):
xen/arm: exclude xen,reg from direct-map domU extended regions
tools/arm: exclude iomem from domU extended regions
tools/libs/light/libxl_arm.c | 110 +++++++++++++++++++++-----
xen/arch/arm/domain_build.c | 77 ++++++++++++++++--
xen/common/device-tree/domain-build.c | 5 ++
3 files changed, 168 insertions(+), 24 deletions(-)
base-commit: 86a12671c5d33063b6f958bdcca7c9d14cd5aac8
--
2.49.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v4 1/2] xen/arm: exclude xen,reg from direct-map domU extended regions
2025-06-09 18:34 [PATCH v4 0/2] arm: extended regions fixes Stewart Hildebrand
@ 2025-06-09 18:34 ` Stewart Hildebrand
2025-06-10 7:27 ` Orzel, Michal
2025-06-09 18:34 ` [PATCH v4 2/2] tools/arm: exclude iomem from " Stewart Hildebrand
1 sibling, 1 reply; 7+ messages in thread
From: Stewart Hildebrand @ 2025-06-09 18:34 UTC (permalink / raw)
To: xen-devel
Cc: Stewart Hildebrand, Stefano Stabellini, Julien Grall,
Bertrand Marquis, Michal Orzel, Volodymyr Babchuk
Similarly to fba1b0974dd8, when a device is passed through to a
direct-map dom0less domU, the xen,reg ranges may overlap with the
extended regions. Remove xen,reg from direct-map domU extended regions.
Take the opportunity to update the comment ahead of find_memory_holes().
Signed-off-by: Stewart Hildebrand <stewart.hildebrand@amd.com>
---
v3->v4:
* conditionally allocate xen_reg
* use rangeset_report_ranges()
* make find_unallocated_memory() cope with NULL entry
v2->v3:
* new patch
---
xen/arch/arm/domain_build.c | 77 +++++++++++++++++++++++++--
xen/common/device-tree/domain-build.c | 5 ++
2 files changed, 77 insertions(+), 5 deletions(-)
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 590f38e52053..6632191cf602 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -792,15 +792,17 @@ static int __init handle_pci_range(const struct dt_device_node *dev,
}
/*
- * Find the holes in the Host DT which can be exposed to Dom0 as extended
- * regions for the special memory mappings. In order to calculate regions
- * we exclude every addressable memory region described by "reg" and "ranges"
- * properties from the maximum possible addressable physical memory range:
+ * Find the holes in the Host DT which can be exposed to Dom0 or a direct-map
+ * domU as extended regions for the special memory mappings. In order to
+ * calculate regions we exclude every addressable memory region described by
+ * "reg" and "ranges" properties from the maximum possible addressable physical
+ * memory range:
* - MMIO
* - Host RAM
* - PCI aperture
* - Static shared memory regions, which are described by special property
* "xen,shared-mem"
+ * - xen,reg mappings
*/
static int __init find_memory_holes(const struct kernel_info *kinfo,
struct membanks *ext_regions)
@@ -882,6 +884,13 @@ static int __init find_memory_holes(const struct kernel_info *kinfo,
}
}
+ if ( kinfo->xen_reg_assigned )
+ {
+ res = rangeset_subtract(mem_holes, kinfo->xen_reg_assigned);
+ if ( res )
+ goto out;
+ }
+
start = 0;
end = (1ULL << p2m_ipa_bits) - 1;
res = rangeset_report_ranges(mem_holes, PFN_DOWN(start), PFN_DOWN(end),
@@ -962,11 +971,48 @@ static int __init find_domU_holes(const struct kernel_info *kinfo,
return res;
}
+static int __init count(unsigned long s, unsigned long e, void *data)
+{
+ unsigned int *cnt = data;
+
+ (*cnt)++;
+
+ return 0;
+}
+
+static int __init rangeset_to_membank(unsigned long s_gfn, unsigned long e_gfn,
+ void *data)
+{
+ struct membanks *membank = data;
+ paddr_t s = pfn_to_paddr(s_gfn);
+ paddr_t e = pfn_to_paddr(e_gfn + 1) - 1;
+
+ if ( membank->nr_banks >= membank->max_banks )
+ return 0;
+
+ membank->bank[membank->nr_banks].start = s;
+ membank->bank[membank->nr_banks].size = e - s + 1;
+ membank->nr_banks++;
+
+ return 0;
+}
+
static int __init find_host_extended_regions(const struct kernel_info *kinfo,
struct membanks *ext_regions)
{
int res;
struct membanks *gnttab = membanks_xzalloc(1, MEMORY);
+ struct membanks *xen_reg =
+ kinfo->xen_reg_assigned
+ ? ({
+ unsigned int xen_reg_cnt = 0;
+
+ rangeset_report_ranges(kinfo->xen_reg_assigned, 0,
+ PFN_DOWN((1ULL << p2m_ipa_bits) - 1), count,
+ &xen_reg_cnt);
+ membanks_xzalloc(xen_reg_cnt, MEMORY);
+ })
+ : NULL;
/*
* Exclude the following regions:
@@ -974,6 +1020,7 @@ static int __init find_host_extended_regions(const struct kernel_info *kinfo,
* 2) Remove reserved memory
* 3) Grant table assigned to domain
* 4) Remove static shared memory (when the feature is enabled)
+ * 5) Remove xen,reg
*/
const struct membanks *mem_banks[] = {
kernel_info_get_mem_const(kinfo),
@@ -982,12 +1029,29 @@ static int __init find_host_extended_regions(const struct kernel_info *kinfo,
#ifdef CONFIG_STATIC_SHM
bootinfo_get_shmem(),
#endif
+ xen_reg,
};
dt_dprintk("Find unallocated memory for extended regions\n");
if ( !gnttab )
- return -ENOMEM;
+ {
+ res = -ENOMEM;
+ goto out;
+ }
+
+ if ( kinfo->xen_reg_assigned )
+ {
+ if ( !xen_reg )
+ {
+ res = -ENOMEM;
+ goto out;
+ }
+
+ rangeset_report_ranges(kinfo->xen_reg_assigned, 0,
+ PFN_DOWN((1ULL << p2m_ipa_bits) - 1),
+ rangeset_to_membank, xen_reg);
+ }
gnttab->nr_banks = 1;
gnttab->bank[0].start = kinfo->gnttab_start;
@@ -995,6 +1059,9 @@ static int __init find_host_extended_regions(const struct kernel_info *kinfo,
res = find_unallocated_memory(kinfo, mem_banks, ARRAY_SIZE(mem_banks),
ext_regions, add_ext_regions);
+
+ out:
+ xfree(xen_reg);
xfree(gnttab);
return res;
diff --git a/xen/common/device-tree/domain-build.c b/xen/common/device-tree/domain-build.c
index 6b8b8d7cacb6..99ea81198a76 100644
--- a/xen/common/device-tree/domain-build.c
+++ b/xen/common/device-tree/domain-build.c
@@ -193,6 +193,10 @@ int __init find_unallocated_memory(const struct kernel_info *kinfo,
/* Remove all regions listed in mem_banks */
for ( i = 0; i < nr_mem_banks; i++ )
+ {
+ if ( !mem_banks[i] )
+ continue;
+
for ( j = 0; j < mem_banks[i]->nr_banks; j++ )
{
start = mem_banks[i]->bank[j].start;
@@ -212,6 +216,7 @@ int __init find_unallocated_memory(const struct kernel_info *kinfo,
goto out;
}
}
+ }
start = 0;
end = (1ULL << p2m_ipa_bits) - 1;
--
2.49.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v4 2/2] tools/arm: exclude iomem from domU extended regions
2025-06-09 18:34 [PATCH v4 0/2] arm: extended regions fixes Stewart Hildebrand
2025-06-09 18:34 ` [PATCH v4 1/2] xen/arm: exclude xen,reg from direct-map domU extended regions Stewart Hildebrand
@ 2025-06-09 18:34 ` Stewart Hildebrand
2025-06-11 14:10 ` Anthony PERARD
1 sibling, 1 reply; 7+ messages in thread
From: Stewart Hildebrand @ 2025-06-09 18:34 UTC (permalink / raw)
To: xen-devel
Cc: Stewart Hildebrand, Anthony PERARD, Juergen Gross,
Stefano Stabellini
When a device is passed through to a xl domU, the iomem ranges may
overlap with the extended regions. Remove iomem from extended regions.
Signed-off-by: Stewart Hildebrand <stewart.hildebrand@amd.com>
---
Not sure if we need a Fixes: tag, but if we do:
Fixes: 57f87857dc2d ("libxl/arm: Add handling of extended regions for DomU")
v3->v4:
* use "else" instead of continue + another if statement
* remove assert
* s/iomem.end >=/unallocated.start >/ in two conditions
* new variable to distinguish unallocated size from region size
* print base + size - 1
v2->v3:
* no change
v1->v2:
* no change
---
tools/libs/light/libxl_arm.c | 110 +++++++++++++++++++++++++++++------
1 file changed, 91 insertions(+), 19 deletions(-)
diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c
index 75c811053c7c..3086c52acf83 100644
--- a/tools/libs/light/libxl_arm.c
+++ b/tools/libs/light/libxl_arm.c
@@ -798,6 +798,8 @@ static int make_timer_node(libxl__gc *gc, void *fdt,
return 0;
}
+#define MAX_NR_EXT_REGIONS 256
+
static int make_hypervisor_node(libxl__gc *gc, void *fdt,
const libxl_version_info *vers)
{
@@ -821,7 +823,7 @@ static int make_hypervisor_node(libxl__gc *gc, void *fdt,
*/
res = fdt_property_reg_placeholder(gc, fdt, GUEST_ROOT_ADDRESS_CELLS,
GUEST_ROOT_SIZE_CELLS,
- GUEST_RAM_BANKS + 1);
+ MAX_NR_EXT_REGIONS + 1);
if (res) return res;
/*
@@ -1517,17 +1519,29 @@ static void finalise_one_node(libxl__gc *gc, void *fdt, const char *uname,
#define EXT_REGION_MIN_SIZE xen_mk_ullong(0x0004000000) /* 64MB */
-static int finalize_hypervisor_node(libxl__gc *gc, struct xc_dom_image *dom)
+static int compare_iomem(const void *a, const void *b)
+{
+ const libxl_iomem_range *x = a, *y = b;
+
+ if (x->gfn < y->gfn)
+ return -1;
+ if (x->gfn > y->gfn)
+ return 1;
+ return 0;
+}
+
+static int finalize_hypervisor_node(libxl__gc *gc,
+ libxl_domain_build_info *b_info,
+ struct xc_dom_image *dom)
{
void *fdt = dom->devicetree_blob;
- uint64_t region_size[GUEST_RAM_BANKS] = {0}, region_base[GUEST_RAM_BANKS],
- bankend[GUEST_RAM_BANKS];
+ uint64_t region_base[MAX_NR_EXT_REGIONS], region_size[MAX_NR_EXT_REGIONS];
uint32_t regs[(GUEST_ROOT_ADDRESS_CELLS + GUEST_ROOT_SIZE_CELLS) *
- (GUEST_RAM_BANKS + 1)];
+ (MAX_NR_EXT_REGIONS + 1)];
be32 *cells = ®s[0];
const uint64_t bankbase[] = GUEST_RAM_BANK_BASES;
const uint64_t banksize[] = GUEST_RAM_BANK_SIZES;
- unsigned int i, len, nr_regions = 0;
+ unsigned int i, j, len, nr_regions = 0;
libxl_dominfo info;
int offset, rc;
@@ -1542,20 +1556,82 @@ static int finalize_hypervisor_node(libxl__gc *gc, struct xc_dom_image *dom)
if (info.gpaddr_bits > 64)
return ERROR_INVAL;
+ qsort(b_info->iomem, b_info->num_iomem, sizeof(libxl_iomem_range),
+ compare_iomem);
+
/*
* Try to allocate separate 2MB-aligned extended regions from the first
* and second RAM banks taking into the account the maximum supported
* guest physical address space size and the amount of memory assigned
* to the guest.
*/
- for (i = 0; i < GUEST_RAM_BANKS; i++) {
- region_base[i] = bankbase[i] +
+ for (i = 0; i < GUEST_RAM_BANKS && nr_regions < MAX_NR_EXT_REGIONS; i++) {
+ struct {
+ uint64_t start;
+ uint64_t end; /* inclusive */
+ } unallocated;
+ uint64_t unallocated_size = 0;
+
+ unallocated.start = bankbase[i] +
ALIGN_UP_TO_2MB((uint64_t)dom->rambank_size[i] << XC_PAGE_SHIFT);
- bankend[i] = ~0ULL >> (64 - info.gpaddr_bits);
- bankend[i] = min(bankend[i], bankbase[i] + banksize[i] - 1);
- if (bankend[i] > region_base[i])
- region_size[i] = bankend[i] - region_base[i] + 1;
+ unallocated.end = ~0ULL >> (64 - info.gpaddr_bits);
+ unallocated.end = min(unallocated.end, bankbase[i] + banksize[i] - 1);
+
+ if (unallocated.end >= unallocated.start)
+ unallocated_size = unallocated.end - unallocated.start + 1;
+
+ if (unallocated_size < EXT_REGION_MIN_SIZE)
+ continue;
+
+ /* Exclude iomem */
+ for (j = 0; j < b_info->num_iomem && nr_regions < MAX_NR_EXT_REGIONS;
+ j++) {
+ struct {
+ uint64_t start;
+ uint64_t end; /* inclusive */
+ } iomem;
+
+ iomem.start = b_info->iomem[j].gfn << XC_PAGE_SHIFT;
+ iomem.end = ((b_info->iomem[j].gfn + b_info->iomem[j].number)
+ << XC_PAGE_SHIFT) - 1;
+
+ if (iomem.end >= unallocated.start
+ && iomem.start <= unallocated.end) {
+
+ if (iomem.start <= unallocated.start) {
+ unallocated.start = iomem.end + 1;
+
+ if (unallocated.start > unallocated.end)
+ break;
+ } else {
+ uint64_t size = iomem.start - unallocated.start;
+
+ if (size >= EXT_REGION_MIN_SIZE) {
+ region_base[nr_regions] = unallocated.start;
+ region_size[nr_regions] = size;
+ nr_regions++;
+ }
+
+ unallocated.start = iomem.end + 1;
+
+ if (unallocated.start > unallocated.end)
+ break;
+ }
+ }
+ }
+
+ if (unallocated.end >= unallocated.start
+ && nr_regions < MAX_NR_EXT_REGIONS)
+ {
+ uint64_t size = unallocated.end - unallocated.start + 1;
+
+ if (size >= EXT_REGION_MIN_SIZE) {
+ region_base[nr_regions] = unallocated.start;
+ region_size[nr_regions] = size;
+ nr_regions++;
+ }
+ }
}
/*
@@ -1565,16 +1641,12 @@ static int finalize_hypervisor_node(libxl__gc *gc, struct xc_dom_image *dom)
set_range(&cells, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
GUEST_GNTTAB_BASE, GUEST_GNTTAB_SIZE);
- for (i = 0; i < GUEST_RAM_BANKS; i++) {
- if (region_size[i] < EXT_REGION_MIN_SIZE)
- continue;
-
+ for (i = 0; i < nr_regions; i++) {
LOG(DEBUG, "Extended region %u: %#"PRIx64"->%#"PRIx64"",
- nr_regions, region_base[i], region_base[i] + region_size[i]);
+ i, region_base[i], region_base[i] + region_size[i] - 1);
set_range(&cells, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS,
region_base[i], region_size[i]);
- nr_regions++;
}
if (!nr_regions)
@@ -1626,7 +1698,7 @@ int libxl__arch_domain_finalise_hw_description(libxl__gc *gc,
}
- res = finalize_hypervisor_node(gc, dom);
+ res = finalize_hypervisor_node(gc, &d_config->b_info, dom);
if (res)
return res;
--
2.49.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v4 1/2] xen/arm: exclude xen,reg from direct-map domU extended regions
2025-06-09 18:34 ` [PATCH v4 1/2] xen/arm: exclude xen,reg from direct-map domU extended regions Stewart Hildebrand
@ 2025-06-10 7:27 ` Orzel, Michal
2025-06-11 13:49 ` Stewart Hildebrand
0 siblings, 1 reply; 7+ messages in thread
From: Orzel, Michal @ 2025-06-10 7:27 UTC (permalink / raw)
To: Stewart Hildebrand, xen-devel
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis,
Volodymyr Babchuk
On 09/06/2025 20:34, Stewart Hildebrand wrote:
> Similarly to fba1b0974dd8, when a device is passed through to a
> direct-map dom0less domU, the xen,reg ranges may overlap with the
> extended regions. Remove xen,reg from direct-map domU extended regions.
>
> Take the opportunity to update the comment ahead of find_memory_holes().
>
> Signed-off-by: Stewart Hildebrand <stewart.hildebrand@amd.com>
> ---
> v3->v4:
> * conditionally allocate xen_reg
> * use rangeset_report_ranges()
> * make find_unallocated_memory() cope with NULL entry
>
> v2->v3:
> * new patch
> ---
> xen/arch/arm/domain_build.c | 77 +++++++++++++++++++++++++--
> xen/common/device-tree/domain-build.c | 5 ++
> 2 files changed, 77 insertions(+), 5 deletions(-)
>
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 590f38e52053..6632191cf602 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -792,15 +792,17 @@ static int __init handle_pci_range(const struct dt_device_node *dev,
> }
>
> /*
> - * Find the holes in the Host DT which can be exposed to Dom0 as extended
> - * regions for the special memory mappings. In order to calculate regions
> - * we exclude every addressable memory region described by "reg" and "ranges"
> - * properties from the maximum possible addressable physical memory range:
> + * Find the holes in the Host DT which can be exposed to Dom0 or a direct-map
> + * domU as extended regions for the special memory mappings. In order to
> + * calculate regions we exclude every addressable memory region described by
> + * "reg" and "ranges" properties from the maximum possible addressable physical
> + * memory range:
> * - MMIO
> * - Host RAM
> * - PCI aperture
> * - Static shared memory regions, which are described by special property
> * "xen,shared-mem"
> + * - xen,reg mappings
> */
> static int __init find_memory_holes(const struct kernel_info *kinfo,
> struct membanks *ext_regions)
> @@ -882,6 +884,13 @@ static int __init find_memory_holes(const struct kernel_info *kinfo,
> }
> }
>
> + if ( kinfo->xen_reg_assigned )
> + {
> + res = rangeset_subtract(mem_holes, kinfo->xen_reg_assigned);
> + if ( res )
> + goto out;
> + }
> +
> start = 0;
> end = (1ULL << p2m_ipa_bits) - 1;
> res = rangeset_report_ranges(mem_holes, PFN_DOWN(start), PFN_DOWN(end),
> @@ -962,11 +971,48 @@ static int __init find_domU_holes(const struct kernel_info *kinfo,
> return res;
> }
>
> +static int __init count(unsigned long s, unsigned long e, void *data)
> +{
> + unsigned int *cnt = data;
> +
> + (*cnt)++;
> +
> + return 0;
> +}
> +
> +static int __init rangeset_to_membank(unsigned long s_gfn, unsigned long e_gfn,
> + void *data)
> +{
> + struct membanks *membank = data;
> + paddr_t s = pfn_to_paddr(s_gfn);
> + paddr_t e = pfn_to_paddr(e_gfn + 1) - 1;
Why do you subtract 1 here if ...
> +
> + if ( membank->nr_banks >= membank->max_banks )
> + return 0;
> +
> + membank->bank[membank->nr_banks].start = s;
> + membank->bank[membank->nr_banks].size = e - s + 1;
you add it again here.
> + membank->nr_banks++;
> +
> + return 0;
> +}
> +
> static int __init find_host_extended_regions(const struct kernel_info *kinfo,
> struct membanks *ext_regions)
> {
> int res;
> struct membanks *gnttab = membanks_xzalloc(1, MEMORY);
> + struct membanks *xen_reg =
> + kinfo->xen_reg_assigned
> + ? ({
> + unsigned int xen_reg_cnt = 0;
> +
> + rangeset_report_ranges(kinfo->xen_reg_assigned, 0,
> + PFN_DOWN((1ULL << p2m_ipa_bits) - 1), count,
> + &xen_reg_cnt);
This does not look really nice with ({. Why can't we create a helper function to
report the count for xen_reg_assigned and call it here? You could then also open
code your 'count' function that is not used by anything else and is quite ambiguous.
~Michal
> + membanks_xzalloc(xen_reg_cnt, MEMORY);
> + })
> + : NULL;
>
> /*
> * Exclude the following regions:
> @@ -974,6 +1020,7 @@ static int __init find_host_extended_regions(const struct kernel_info *kinfo,
> * 2) Remove reserved memory
> * 3) Grant table assigned to domain
> * 4) Remove static shared memory (when the feature is enabled)
> + * 5) Remove xen,reg
> */
> const struct membanks *mem_banks[] = {
> kernel_info_get_mem_const(kinfo),
> @@ -982,12 +1029,29 @@ static int __init find_host_extended_regions(const struct kernel_info *kinfo,
> #ifdef CONFIG_STATIC_SHM
> bootinfo_get_shmem(),
> #endif
> + xen_reg,
> };
>
> dt_dprintk("Find unallocated memory for extended regions\n");
>
> if ( !gnttab )
> - return -ENOMEM;
> + {
> + res = -ENOMEM;
> + goto out;
> + }
> +
> + if ( kinfo->xen_reg_assigned )
> + {
> + if ( !xen_reg )
> + {
> + res = -ENOMEM;
> + goto out;
> + }
> +
> + rangeset_report_ranges(kinfo->xen_reg_assigned, 0,
> + PFN_DOWN((1ULL << p2m_ipa_bits) - 1),
> + rangeset_to_membank, xen_reg);
> + }
>
> gnttab->nr_banks = 1;
> gnttab->bank[0].start = kinfo->gnttab_start;
> @@ -995,6 +1059,9 @@ static int __init find_host_extended_regions(const struct kernel_info *kinfo,
>
> res = find_unallocated_memory(kinfo, mem_banks, ARRAY_SIZE(mem_banks),
> ext_regions, add_ext_regions);
> +
> + out:
> + xfree(xen_reg);
> xfree(gnttab);
>
> return res;
> diff --git a/xen/common/device-tree/domain-build.c b/xen/common/device-tree/domain-build.c
> index 6b8b8d7cacb6..99ea81198a76 100644
> --- a/xen/common/device-tree/domain-build.c
> +++ b/xen/common/device-tree/domain-build.c
> @@ -193,6 +193,10 @@ int __init find_unallocated_memory(const struct kernel_info *kinfo,
>
> /* Remove all regions listed in mem_banks */
> for ( i = 0; i < nr_mem_banks; i++ )
> + {
> + if ( !mem_banks[i] )
> + continue;
> +
> for ( j = 0; j < mem_banks[i]->nr_banks; j++ )
> {
> start = mem_banks[i]->bank[j].start;
> @@ -212,6 +216,7 @@ int __init find_unallocated_memory(const struct kernel_info *kinfo,
> goto out;
> }
> }
> + }
>
> start = 0;
> end = (1ULL << p2m_ipa_bits) - 1;
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v4 1/2] xen/arm: exclude xen,reg from direct-map domU extended regions
2025-06-10 7:27 ` Orzel, Michal
@ 2025-06-11 13:49 ` Stewart Hildebrand
2025-06-11 13:53 ` Orzel, Michal
0 siblings, 1 reply; 7+ messages in thread
From: Stewart Hildebrand @ 2025-06-11 13:49 UTC (permalink / raw)
To: Orzel, Michal, xen-devel
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis,
Volodymyr Babchuk
On 6/10/25 03:27, Orzel, Michal wrote:
> On 09/06/2025 20:34, Stewart Hildebrand wrote:
>> Similarly to fba1b0974dd8, when a device is passed through to a
>> direct-map dom0less domU, the xen,reg ranges may overlap with the
>> extended regions. Remove xen,reg from direct-map domU extended regions.
>>
>> Take the opportunity to update the comment ahead of find_memory_holes().
>>
>> Signed-off-by: Stewart Hildebrand <stewart.hildebrand@amd.com>
>> ---
>> v3->v4:
>> * conditionally allocate xen_reg
>> * use rangeset_report_ranges()
>> * make find_unallocated_memory() cope with NULL entry
>>
>> v2->v3:
>> * new patch
>> ---
>> xen/arch/arm/domain_build.c | 77 +++++++++++++++++++++++++--
>> xen/common/device-tree/domain-build.c | 5 ++
>> 2 files changed, 77 insertions(+), 5 deletions(-)
>>
>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>> index 590f38e52053..6632191cf602 100644
>> --- a/xen/arch/arm/domain_build.c
>> +++ b/xen/arch/arm/domain_build.c
>> @@ -792,15 +792,17 @@ static int __init handle_pci_range(const struct dt_device_node *dev,
>> }
>>
>> /*
>> - * Find the holes in the Host DT which can be exposed to Dom0 as extended
>> - * regions for the special memory mappings. In order to calculate regions
>> - * we exclude every addressable memory region described by "reg" and "ranges"
>> - * properties from the maximum possible addressable physical memory range:
>> + * Find the holes in the Host DT which can be exposed to Dom0 or a direct-map
>> + * domU as extended regions for the special memory mappings. In order to
>> + * calculate regions we exclude every addressable memory region described by
>> + * "reg" and "ranges" properties from the maximum possible addressable physical
>> + * memory range:
>> * - MMIO
>> * - Host RAM
>> * - PCI aperture
>> * - Static shared memory regions, which are described by special property
>> * "xen,shared-mem"
>> + * - xen,reg mappings
>> */
>> static int __init find_memory_holes(const struct kernel_info *kinfo,
>> struct membanks *ext_regions)
>> @@ -882,6 +884,13 @@ static int __init find_memory_holes(const struct kernel_info *kinfo,
>> }
>> }
>>
>> + if ( kinfo->xen_reg_assigned )
>> + {
>> + res = rangeset_subtract(mem_holes, kinfo->xen_reg_assigned);
>> + if ( res )
>> + goto out;
>> + }
>> +
>> start = 0;
>> end = (1ULL << p2m_ipa_bits) - 1;
>> res = rangeset_report_ranges(mem_holes, PFN_DOWN(start), PFN_DOWN(end),
>> @@ -962,11 +971,48 @@ static int __init find_domU_holes(const struct kernel_info *kinfo,
>> return res;
>> }
>>
>> +static int __init count(unsigned long s, unsigned long e, void *data)
>> +{
>> + unsigned int *cnt = data;
>> +
>> + (*cnt)++;
>> +
>> + return 0;
>> +}
>> +
>> +static int __init rangeset_to_membank(unsigned long s_gfn, unsigned long e_gfn,
>> + void *data)
>> +{
>> + struct membanks *membank = data;
>> + paddr_t s = pfn_to_paddr(s_gfn);
>> + paddr_t e = pfn_to_paddr(e_gfn + 1) - 1;
> Why do you subtract 1 here if ...
>
>> +
>> + if ( membank->nr_banks >= membank->max_banks )
>> + return 0;
>> +
>> + membank->bank[membank->nr_banks].start = s;
>> + membank->bank[membank->nr_banks].size = e - s + 1;
> you add it again here.
To be consistent with add_ext_regions() and add_hwdom_free_regions(),
but I suppose there's no need for that. I'll drop the extraneous -1 and
+1.
>> + membank->nr_banks++;
>> +
>> + return 0;
>> +}
>> +
>> static int __init find_host_extended_regions(const struct kernel_info *kinfo,
>> struct membanks *ext_regions)
>> {
>> int res;
>> struct membanks *gnttab = membanks_xzalloc(1, MEMORY);
>> + struct membanks *xen_reg =
>> + kinfo->xen_reg_assigned
>> + ? ({
>> + unsigned int xen_reg_cnt = 0;
>> +
>> + rangeset_report_ranges(kinfo->xen_reg_assigned, 0,
>> + PFN_DOWN((1ULL << p2m_ipa_bits) - 1), count,
>> + &xen_reg_cnt);
> This does not look really nice with ({. Why can't we create a helper function to
> report the count for xen_reg_assigned and call it here? You could then also open
> code your 'count' function that is not used by anything else and is quite ambiguous.
If I'm reading this right, I think you're suggesting something like this
(in domain_build.c):
static unsigned int __init count_ranges(struct rangeset *r)
{
unsigned int xen_reg_cnt = 0;
rangeset_report_ranges(r,
0,
PFN_DOWN((1ULL << p2m_ipa_bits) - 1),
({
int count(unsigned long s, unsigned long e, void *data)
{
unsigned int *cnt = data;
(*cnt)++;
return 0;
}
count;
}),
&xen_reg_cnt);
return xen_reg_cnt;
}
...
struct membanks *xen_reg =
kinfo->xen_reg_assigned
? membanks_xzalloc(count_ranges(kinfo->xen_reg_assigned), MEMORY)
: NULL;
However, the open-coded/anonymous count function, aside from being a
compiler extension, doesn't seem to play well with __init. As written,
this doesn't link:
Error: size of arch/arm/domain_build.o:.text is 0x00000014
Adding __init leads to:
aarch64-none-linux-gnu-ld: prelink.o: in function `count_ranges':
/home/stew/xen/xen/arch/arm/domain_build.c:978: undefined reference to `count.5'
Making it static leads to:
arch/arm/domain_build.c: In function ‘count_ranges’:
arch/arm/domain_build.c:982:43: error: invalid storage class for function ‘count’
982 | static int count(unsigned long s, unsigned long e, void *data)
| ^~~~~
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v4 1/2] xen/arm: exclude xen,reg from direct-map domU extended regions
2025-06-11 13:49 ` Stewart Hildebrand
@ 2025-06-11 13:53 ` Orzel, Michal
0 siblings, 0 replies; 7+ messages in thread
From: Orzel, Michal @ 2025-06-11 13:53 UTC (permalink / raw)
To: Stewart Hildebrand, xen-devel
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis,
Volodymyr Babchuk
On 11/06/2025 15:49, Stewart Hildebrand wrote:
> On 6/10/25 03:27, Orzel, Michal wrote:
>> On 09/06/2025 20:34, Stewart Hildebrand wrote:
>>> Similarly to fba1b0974dd8, when a device is passed through to a
>>> direct-map dom0less domU, the xen,reg ranges may overlap with the
>>> extended regions. Remove xen,reg from direct-map domU extended regions.
>>>
>>> Take the opportunity to update the comment ahead of find_memory_holes().
>>>
>>> Signed-off-by: Stewart Hildebrand <stewart.hildebrand@amd.com>
>>> ---
>>> v3->v4:
>>> * conditionally allocate xen_reg
>>> * use rangeset_report_ranges()
>>> * make find_unallocated_memory() cope with NULL entry
>>>
>>> v2->v3:
>>> * new patch
>>> ---
>>> xen/arch/arm/domain_build.c | 77 +++++++++++++++++++++++++--
>>> xen/common/device-tree/domain-build.c | 5 ++
>>> 2 files changed, 77 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>>> index 590f38e52053..6632191cf602 100644
>>> --- a/xen/arch/arm/domain_build.c
>>> +++ b/xen/arch/arm/domain_build.c
>>> @@ -792,15 +792,17 @@ static int __init handle_pci_range(const struct dt_device_node *dev,
>>> }
>>>
>>> /*
>>> - * Find the holes in the Host DT which can be exposed to Dom0 as extended
>>> - * regions for the special memory mappings. In order to calculate regions
>>> - * we exclude every addressable memory region described by "reg" and "ranges"
>>> - * properties from the maximum possible addressable physical memory range:
>>> + * Find the holes in the Host DT which can be exposed to Dom0 or a direct-map
>>> + * domU as extended regions for the special memory mappings. In order to
>>> + * calculate regions we exclude every addressable memory region described by
>>> + * "reg" and "ranges" properties from the maximum possible addressable physical
>>> + * memory range:
>>> * - MMIO
>>> * - Host RAM
>>> * - PCI aperture
>>> * - Static shared memory regions, which are described by special property
>>> * "xen,shared-mem"
>>> + * - xen,reg mappings
>>> */
>>> static int __init find_memory_holes(const struct kernel_info *kinfo,
>>> struct membanks *ext_regions)
>>> @@ -882,6 +884,13 @@ static int __init find_memory_holes(const struct kernel_info *kinfo,
>>> }
>>> }
>>>
>>> + if ( kinfo->xen_reg_assigned )
>>> + {
>>> + res = rangeset_subtract(mem_holes, kinfo->xen_reg_assigned);
>>> + if ( res )
>>> + goto out;
>>> + }
>>> +
>>> start = 0;
>>> end = (1ULL << p2m_ipa_bits) - 1;
>>> res = rangeset_report_ranges(mem_holes, PFN_DOWN(start), PFN_DOWN(end),
>>> @@ -962,11 +971,48 @@ static int __init find_domU_holes(const struct kernel_info *kinfo,
>>> return res;
>>> }
>>>
>>> +static int __init count(unsigned long s, unsigned long e, void *data)
>>> +{
>>> + unsigned int *cnt = data;
>>> +
>>> + (*cnt)++;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int __init rangeset_to_membank(unsigned long s_gfn, unsigned long e_gfn,
>>> + void *data)
>>> +{
>>> + struct membanks *membank = data;
>>> + paddr_t s = pfn_to_paddr(s_gfn);
>>> + paddr_t e = pfn_to_paddr(e_gfn + 1) - 1;
>> Why do you subtract 1 here if ...
>>
>>> +
>>> + if ( membank->nr_banks >= membank->max_banks )
>>> + return 0;
>>> +
>>> + membank->bank[membank->nr_banks].start = s;
>>> + membank->bank[membank->nr_banks].size = e - s + 1;
>> you add it again here.
>
> To be consistent with add_ext_regions() and add_hwdom_free_regions(),
> but I suppose there's no need for that. I'll drop the extraneous -1 and
> +1.
>
>>> + membank->nr_banks++;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static int __init find_host_extended_regions(const struct kernel_info *kinfo,
>>> struct membanks *ext_regions)
>>> {
>>> int res;
>>> struct membanks *gnttab = membanks_xzalloc(1, MEMORY);
>>> + struct membanks *xen_reg =
>>> + kinfo->xen_reg_assigned
>>> + ? ({
>>> + unsigned int xen_reg_cnt = 0;
>>> +
>>> + rangeset_report_ranges(kinfo->xen_reg_assigned, 0,
>>> + PFN_DOWN((1ULL << p2m_ipa_bits) - 1), count,
>>> + &xen_reg_cnt);
>> This does not look really nice with ({. Why can't we create a helper function to
>> report the count for xen_reg_assigned and call it here? You could then also open
>> code your 'count' function that is not used by anything else and is quite ambiguous.
>
> If I'm reading this right, I think you're suggesting something like this
> (in domain_build.c):
>
> static unsigned int __init count_ranges(struct rangeset *r)
> {
> unsigned int xen_reg_cnt = 0;
>
> rangeset_report_ranges(r,
> 0,
> PFN_DOWN((1ULL << p2m_ipa_bits) - 1),
> ({
> int count(unsigned long s, unsigned long e, void *data)
> {
> unsigned int *cnt = data;
>
> (*cnt)++;
>
> return 0;
> }
> count;
> }),
> &xen_reg_cnt);
>
> return xen_reg_cnt;
> }
>
> ...
>
> struct membanks *xen_reg =
> kinfo->xen_reg_assigned
> ? membanks_xzalloc(count_ranges(kinfo->xen_reg_assigned), MEMORY)
> : NULL;
>
>
> However, the open-coded/anonymous count function, aside from being a
> compiler extension, doesn't seem to play well with __init. As written,
> this doesn't link:
Sorry, I don't know why I wrote to open code count(). In conclusion my remark
was to place this code in a separate function to avoid ({ in
find_host_extended_regions(). So there will be count() helper and count_ranges().
~Michal
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v4 2/2] tools/arm: exclude iomem from domU extended regions
2025-06-09 18:34 ` [PATCH v4 2/2] tools/arm: exclude iomem from " Stewart Hildebrand
@ 2025-06-11 14:10 ` Anthony PERARD
0 siblings, 0 replies; 7+ messages in thread
From: Anthony PERARD @ 2025-06-11 14:10 UTC (permalink / raw)
To: Stewart Hildebrand; +Cc: xen-devel, Juergen Gross, Stefano Stabellini
On Mon, Jun 09, 2025 at 02:34:33PM -0400, Stewart Hildebrand wrote:
> When a device is passed through to a xl domU, the iomem ranges may
> overlap with the extended regions. Remove iomem from extended regions.
>
> Signed-off-by: Stewart Hildebrand <stewart.hildebrand@amd.com>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
Thanks,
--
Anthony PERARD
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-06-11 14:10 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-09 18:34 [PATCH v4 0/2] arm: extended regions fixes Stewart Hildebrand
2025-06-09 18:34 ` [PATCH v4 1/2] xen/arm: exclude xen,reg from direct-map domU extended regions Stewart Hildebrand
2025-06-10 7:27 ` Orzel, Michal
2025-06-11 13:49 ` Stewart Hildebrand
2025-06-11 13:53 ` Orzel, Michal
2025-06-09 18:34 ` [PATCH v4 2/2] tools/arm: exclude iomem from " Stewart Hildebrand
2025-06-11 14:10 ` Anthony PERARD
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.