From: Olaf Hering Date: Fri, 5 Feb 2021 20:16:02 +0100 Subject: libxc sr xg_sr_bitmap populated_pfns tools: use xg_sr_bitmap for populated_pfns Signed-off-by: Olaf Hering --- tools/libs/guest/xg_sr_common.h | 20 ++++++- tools/libs/guest/xg_sr_restore.c | 69 ------------------------ tools/libs/guest/xg_sr_restore_x86_hvm.c | 9 ++++ tools/libs/guest/xg_sr_restore_x86_pv.c | 7 +++ 4 files changed, 34 insertions(+), 71 deletions(-) --- a/tools/libs/guest/xg_sr_common.h +++ b/tools/libs/guest/xg_sr_common.h @@ -375,8 +375,7 @@ struct xc_sr_context uint32_t xenstore_domid, console_domid; /* Bitmap of currently populated PFNs during restore. */ - unsigned long *populated_pfns; - xen_pfn_t max_populated_pfn; + struct sr_bitmap populated_pfns; /* Sender has invoked verify mode on the stream. */ bool verify; @@ -632,6 +631,23 @@ static inline bool page_type_has_stream_ } } +static inline bool pfn_is_populated(struct xc_sr_context *ctx, xen_pfn_t pfn) +{ + return sr_test_bit(pfn, &ctx->restore.populated_pfns); +} + +static inline int pfn_set_populated(struct xc_sr_context *ctx, xen_pfn_t pfn) +{ + xc_interface *xch = ctx->xch; + + if ( sr_set_bit(pfn, &ctx->restore.populated_pfns) == false ) + { + PERROR("Failed to realloc populated_pfns bitmap"); + errno = ENOMEM; + return -1; + } + return 0; +} #endif /* * Local variables: --- a/tools/libs/guest/xg_sr_restore.c +++ b/tools/libs/guest/xg_sr_restore.c @@ -72,64 +72,6 @@ static int read_headers(struct xc_sr_con } /* - * Is a pfn populated? - */ -static bool pfn_is_populated(const struct xc_sr_context *ctx, xen_pfn_t pfn) -{ - if ( pfn > ctx->restore.max_populated_pfn ) - return false; - return test_bit(pfn, ctx->restore.populated_pfns); -} - -/* - * Set a pfn as populated, expanding the tracking structures if needed. To - * avoid realloc()ing too excessively, the size increased to the nearest power - * of two large enough to contain the required pfn. - */ -static int pfn_set_populated(struct xc_sr_context *ctx, xen_pfn_t pfn) -{ - xc_interface *xch = ctx->xch; - - if ( pfn > ctx->restore.max_populated_pfn ) - { - xen_pfn_t new_max; - size_t old_sz, new_sz; - unsigned long *p; - - /* Round up to the nearest power of two larger than pfn, less 1. */ - new_max = pfn; - new_max |= new_max >> 1; - new_max |= new_max >> 2; - new_max |= new_max >> 4; - new_max |= new_max >> 8; - new_max |= new_max >> 16; -#ifdef __x86_64__ - new_max |= new_max >> 32; -#endif - - old_sz = bitmap_size(ctx->restore.max_populated_pfn + 1); - new_sz = bitmap_size(new_max + 1); - p = realloc(ctx->restore.populated_pfns, new_sz); - if ( !p ) - { - ERROR("Failed to realloc populated bitmap"); - errno = ENOMEM; - return -1; - } - - memset((uint8_t *)p + old_sz, 0x00, new_sz - old_sz); - - ctx->restore.populated_pfns = p; - ctx->restore.max_populated_pfn = new_max; - } - - assert(!test_bit(pfn, ctx->restore.populated_pfns)); - set_bit(pfn, ctx->restore.populated_pfns); - - return 0; -} - -/* * Given a set of pfns, obtain memory from Xen to fill the physmap for the * unpopulated subset. If types is NULL, no page type checking is performed * and all unpopulated pfns are populated. @@ -911,16 +853,6 @@ static int setup(struct xc_sr_context *c if ( rc ) goto err; - ctx->restore.max_populated_pfn = (32 * 1024 / 4) - 1; - ctx->restore.populated_pfns = bitmap_alloc( - ctx->restore.max_populated_pfn + 1); - if ( !ctx->restore.populated_pfns ) - { - ERROR("Unable to allocate memory for populated_pfns bitmap"); - rc = -1; - goto err; - } - ctx->restore.pfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.pfns)); ctx->restore.types = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.types)); ctx->restore.mfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->restore.mfns)); @@ -969,7 +901,6 @@ static void cleanup(struct xc_sr_context xch, dirty_bitmap, NRPAGES(bitmap_size(ctx->restore.p2m_size))); free(ctx->restore.buffered_records); - free(ctx->restore.populated_pfns); free(ctx->restore.pages); free(ctx->restore.iov); free(ctx->restore.guest_data); --- a/tools/libs/guest/xg_sr_restore_x86_hvm.c +++ b/tools/libs/guest/xg_sr_restore_x86_hvm.c @@ -136,6 +136,7 @@ static int x86_hvm_localise_page(struct static int x86_hvm_setup(struct xc_sr_context *ctx) { xc_interface *xch = ctx->xch; + unsigned long max_pfn, max_pages = ctx->dominfo.max_pages; if ( ctx->restore.guest_type != DHDR_TYPE_X86_HVM ) { @@ -161,6 +162,13 @@ static int x86_hvm_setup(struct xc_sr_co } #endif + max_pfn = max(ctx->restore.p2m_size, max_pages); + if ( !sr_bitmap_expand(&ctx->restore.populated_pfns, max_pfn) ) + { + PERROR("Unable to allocate memory for populated_pfns bitmap"); + return -1; + } + return 0; } @@ -241,6 +249,7 @@ static int x86_hvm_stream_complete(struc static int x86_hvm_cleanup(struct xc_sr_context *ctx) { + sr_bitmap_free(&ctx->restore.populated_pfns); free(ctx->x86.hvm.restore.context.ptr); free(ctx->x86.restore.cpuid.ptr); --- a/tools/libs/guest/xg_sr_restore_x86_pv.c +++ b/tools/libs/guest/xg_sr_restore_x86_pv.c @@ -1060,6 +1060,12 @@ static int x86_pv_setup(struct xc_sr_con if ( rc ) return rc; + if ( !sr_bitmap_expand(&ctx->restore.populated_pfns, 32 * 1024 / 4) ) + { + PERROR("Unable to allocate memory for populated_pfns bitmap"); + return -1; + } + ctx->x86.pv.restore.nr_vcpus = ctx->dominfo.max_vcpu_id + 1; ctx->x86.pv.restore.vcpus = calloc(sizeof(struct xc_sr_x86_pv_restore_vcpu), ctx->x86.pv.restore.nr_vcpus); @@ -1153,6 +1159,7 @@ static int x86_pv_stream_complete(struct */ static int x86_pv_cleanup(struct xc_sr_context *ctx) { + sr_bitmap_free(&ctx->restore.populated_pfns); free(ctx->x86.pv.p2m); free(ctx->x86.pv.p2m_pfns);