|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 10/15] x86/PVH: convert find_memory() to using a rangeset
Subsequently we will need to exclude a 2nd range here. To avoid
complicating the logic when it needs to cover two ranges, follow the
suggestion left in a code comment and convert to using a rangeset.
Suggested-by: Xenia Ragiadakou <xenia.ragiadakou@xxxxxxx>
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
---
The Suggested-by: is based on the respective commit's S-o-b. I didn't go
hunt for whether this may have been suggested in review of that patch.
--- a/xen/arch/x86/hvm/dom0_build.c
+++ b/xen/arch/x86/hvm/dom0_build.c
@@ -518,14 +518,38 @@ static int __init pvh_populate_p2m(
#undef MB1_PAGES
}
+struct mem_info {
+ size_t size;
+ paddr_t addr;
+};
+
+static int cf_check __init _find_memory(
+ unsigned long s, unsigned long e, void *data)
+{
+ struct mem_info *info = data;
+
+ if ( e + 1 - s >= info->size )
+ {
+ info->addr = s;
+ return 1;
+ }
+
+ return 0;
+}
+
static paddr_t __init find_memory(
const struct domain *d, const struct elf_binary *elf, size_t size)
{
- paddr_t kernel_start = (paddr_t)elf->dest_base & PAGE_MASK;
- paddr_t kernel_end = ROUNDUP((paddr_t)elf->dest_base + elf->dest_size,
- PAGE_SIZE);
+ struct rangeset *ram = rangeset_new(NULL, NULL, 0);
+ struct mem_info info = {
+ .size = size,
+ .addr = INVALID_PADDR,
+ };
unsigned int i;
+ if ( !ram )
+ return INVALID_PADDR;
+
/*
* The memory map is sorted and all RAM region starts are aligned to
* page boundaries.
@@ -542,26 +566,22 @@ static paddr_t __init find_memory(
ASSERT(IS_ALIGNED(start, PAGE_SIZE));
- /*
- * NB: Even better would be to use rangesets to determine a suitable
- * range, in particular in case a kernel requests multiple heavily
- * discontiguous regions (which right now we fold all into one big
- * region).
- */
- if ( end <= kernel_start || start >= kernel_end )
- {
- /* No overlap, just check whether the region is large enough. */
- if ( end - start >= size )
- return start;
- }
- /* Deal with the kernel already being loaded in the region. */
- else if ( kernel_start > start && kernel_start - start >= size )
- return start;
- else if ( kernel_end < end && end - kernel_end >= size )
- return kernel_end;
+ if ( start < end &&
+ rangeset_add_range(ram, start, end - 1) != 0 )
+ return INVALID_PADDR;
}
- return INVALID_PADDR;
+ /* Remove the kernel range, rounded to page boundaries. */
+ if ( rangeset_remove_range(ram, (paddr_t)elf->dest_base & PAGE_MASK,
+ ROUNDUP((paddr_t)elf->dest_base +
elf->dest_size,
+ PAGE_SIZE) - 1) != 0 )
+ return INVALID_PADDR;
+
+ rangeset_report_ranges(ram, MB(1), -1, _find_memory, &info);
+
+ rangeset_destroy(ram);
+
+ return info.addr;
}
static bool __init check_load_address(
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |