[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 1/2] xen/x86: return partial memory map in case of not enough space
For XENMEM_machine_memory_map the hypervisor returns EINVAL if the caller's buffer can't hold all entries. This is a problem as the caller has normally a static buffer defined and when he is doing the call no dynamic memory allocation is possible as nothing is yet known about the system's memory layout. Instead of just fail deliver as many memory map entries as possible and return with E2BIG indicating the result was incomplete. Then the caller will be capable to use at least some memory reported to exist to allocate a larger buffer for the complete memory map. As E2BIG wasn't returned before a caller not prepared for this case will still see just a failure as before, while someone prepared for this error code running on an old hypervisor won't run into problems other than without this change. Signed-off-by: Juergen Gross <jgross@xxxxxxxx> --- xen/arch/x86/mm.c | 22 ++++++++++++---------- xen/include/public/memory.h | 2 ++ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 14552a1..f8e679d 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -4737,7 +4737,7 @@ static int _handle_iomem_range(unsigned long s, unsigned long e, XEN_GUEST_HANDLE(e820entry_t) buffer; if ( ctxt->n + 1 >= ctxt->map.nr_entries ) - return -EINVAL; + return -E2BIG; ent.addr = (uint64_t)ctxt->s << PAGE_SHIFT; ent.size = (uint64_t)(s - ctxt->s) << PAGE_SHIFT; ent.type = E820_RESERVED; @@ -4985,8 +4985,6 @@ long arch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg) if ( copy_from_guest(&ctxt.map, arg, 1) ) return -EFAULT; - if ( ctxt.map.nr_entries < e820.nr_map + 1 ) - return -EINVAL; buffer_param = guest_handle_cast(ctxt.map.buffer, e820entry_t); buffer = guest_handle_from_param(buffer_param, e820entry_t); @@ -5005,31 +5003,35 @@ long arch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg) if ( !rc ) rc = handle_iomem_range(s, s, &ctxt); if ( rc ) - return rc; + break; + } + if ( ctxt.map.nr_entries <= ctxt.n + 1 ) + { + rc = -E2BIG; + break; } - if ( ctxt.map.nr_entries <= ctxt.n + (e820.nr_map - i) ) - return -EINVAL; if ( __copy_to_guest_offset(buffer, ctxt.n, e820.map + i, 1) ) return -EFAULT; ctxt.s = PFN_UP(e820.map[i].addr + e820.map[i].size); } - if ( ctxt.s ) + if ( !rc && ctxt.s ) { rc = rangeset_report_ranges(current->domain->iomem_caps, ctxt.s, ~0UL, handle_iomem_range, &ctxt); if ( !rc && ctxt.s ) rc = handle_iomem_range(~0UL, ~0UL, &ctxt); - if ( rc ) - return rc; } + if ( rc && rc != -E2BIG ) + return rc; + ctxt.map.nr_entries = ctxt.n; if ( __copy_to_guest(arg, &ctxt.map, 1) ) return -EFAULT; - return 0; + return rc; } case XENMEM_machphys_mapping: diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h index 5bf840f..20df769 100644 --- a/xen/include/public/memory.h +++ b/xen/include/public/memory.h @@ -339,6 +339,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_memory_map_t); /* * Returns the real physical memory map. Passes the same structure as * XENMEM_memory_map. + * In case of a buffer not capable to hold all entries of the physical + * memory map -E2BIG is returned and the buffer is filled completely. * arg == addr of xen_memory_map_t. */ #define XENMEM_machine_memory_map 10 -- 2.10.2 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |