static int e820_host_sanitize(libxl__gc *gc, libxl_domain_build_info *b_info, struct e820entry map[], uint32_t *nr) { int rc; rc = xc_get_machine_memory_map(CTX->xch, map, *nr); if (rc < 0) return ERROR_FAIL; *nr = rc; rc = e820_sanitize(gc, map, nr, b_info->target_memkb, (b_info->max_memkb - b_info->target_memkb) + b_info->u.pv.slack_memkb); return rc; }
static int libxl__e820_alloc(libxl__gc *gc, uint32_t domid, libxl_domain_config *d_config) { libxl_ctx *ctx = libxl__gc_owner(gc); int rc; uint32_t nr; struct e820entry map[E820MAX]; libxl_domain_build_info *b_info; if (d_config == NULL || d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM) return ERROR_INVAL; b_info = &d_config->b_info; if (!libxl_defbool_val(b_info->u.pv.e820_host)) return ERROR_INVAL; rc = xc_get_machine_memory_map(ctx->xch, map, E820MAX); if (rc < 0) { errno = rc; return ERROR_FAIL; } nr = rc; rc = e820_sanitize(ctx, map, &nr, b_info->target_memkb, (b_info->max_memkb - b_info->target_memkb) + b_info->u.pv.slack_memkb); if (rc) return ERROR_FAIL; rc = xc_domain_set_memory_map(ctx->xch, domid, map, nr); if (rc < 0) { errno = rc; return ERROR_FAIL; } return 0; }
/* * Checks for the beginnig and end of RAM in e820 map for domain * and aligns start of first and end of last vNUMA memory block to * that map. vnode memory size are passed here Megabytes. * For PV guest e820 map has fixed hole sizes. */ int libxl__vnuma_align_mem(libxl__gc *gc, uint32_t domid, libxl_domain_build_info *b_info, /* IN: mem sizes */ vmemrange_t *memblks) /* OUT: linux numa blocks in pfn */ { int i, j, rc; uint64_t next_start_pfn, end_max = 0, size, mem_hole; uint32_t nr; struct e820entry map[E820MAX]; if (b_info->nr_vnodes == 0) return -EINVAL; libxl_ctx *ctx = libxl__gc_owner(gc); /* retreive e820 map for this host */ rc = xc_get_machine_memory_map(ctx->xch, map, E820MAX); if (rc < 0) { errno = rc; return -EINVAL; } nr = rc; rc = e820_sanitize(ctx, map, &nr, b_info->target_memkb, (b_info->max_memkb - b_info->target_memkb) + b_info->u.pv.slack_memkb); if (rc) { errno = rc; return -EINVAL; } /* max pfn for this host */ for (j = nr - 1; j >= 0; j--) if (map[j].type == E820_RAM) { end_max = map[j].addr + map[j].size; break; } memset(memblks, 0, sizeof(*memblks) * b_info->nr_vnodes); next_start_pfn = 0; memblks[0].start = map[0].addr; for(i = 0; i < b_info->nr_vnodes; i++) { /* start can be not zero */ memblks[i].start += next_start_pfn; memblks[i].end = memblks[i].start + (b_info->vnuma_memszs[i] << 20); size = memblks[i].end - memblks[i].start; /* * For pv host with e820_host option turned on we need * to rake into account memory holes. For pv host with * e820_host disabled or unset, the map is contiguous * RAM region. */ if (libxl_defbool_val(b_info->u.pv.e820_host)) { while (mem_hole = e820_memory_hole_size(memblks[i].start, memblks[i].end, map, nr), memblks[i].end - memblks[i].start - mem_hole < size) { memblks[i].end += mem_hole; if (memblks[i].end > end_max) { memblks[i].end = end_max; break; } } } next_start_pfn = memblks[i].end; } if (memblks[i-1].end > end_max) memblks[i-1].end = end_max; return 0; }