[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v4] xen: don't save/restore the physmap on VM save/restore



On Tue, 14 Mar 2017, Igor Druzhinin wrote:
> Saving/restoring the physmap to/from xenstore was introduced to
> QEMU majorly in order to cover up the VRAM region restore issue.
> The sequence of restore operations implies that we should know
> the effective guest VRAM address *before* we have the VRAM region
> restored (which happens later). Unfortunately, in Xen environment
> VRAM memory does actually belong to a guest - not QEMU itself -
> which means the position of this region is unknown beforehand and
> can't be mapped into QEMU address space immediately.
> 
> Previously, recreating xenstore keys, holding the physmap, by the
> toolstack helped to get this information in place at the right
> moment ready to be consumed by QEMU to map the region properly.
> 
> The extraneous complexity of having those keys transferred by the
> toolstack and unnecessary redundancy prompted us to propose a
> solution which doesn't require any extra data in xenstore. The idea
> is to defer the VRAM region mapping till the point we actually know
> the effective address and able to map it. To that end, we initially
> just skip the mapping request for the framebuffer if we unable to
> map it now. Then, after the memory region restore phase, we perform
> the mapping again, this time successfully, and update the VRAM region
> metadata accordingly.
> 
> Signed-off-by: Igor Druzhinin <igor.druzhinin@xxxxxxxxxx>
> ---
> v4:
> * Use VGA post_load handler for vram_ptr update
> 
> v3:
> * Modify qemu_ram_ptr_length similarly with qemu_map_ram_ptr
> * Add a comment explaining qemu_map_ram_ptr and qemu_ram_ptr_length 
>   semantic change for Xen
> * Dropped some redundant changes
> 
> v2:
> * Fix some building and coding style issues
> ---
>  exec.c           |  16 +++++++++
>  hw/display/vga.c |   5 +++
>  xen-hvm.c        | 104 
> ++++++++++---------------------------------------------
>  3 files changed, 40 insertions(+), 85 deletions(-)
> 
> diff --git a/exec.c b/exec.c
> index aabb035..a1ac8cd 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -2008,6 +2008,14 @@ void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t 
> addr)
>          }
>  
>          block->host = xen_map_cache(block->offset, block->max_length, 1);
> +        if (block->host == NULL) {
> +            /* In case we cannot establish the mapping right away we might
> +             * still be able to do it later e.g. on a later stage of restore.
> +             * We don't touch the block and return NULL here to indicate
> +             * that intention.
> +             */
> +            return NULL;
> +        }
>      }
>      return ramblock_ptr(block, addr);
>  }
> @@ -2041,6 +2049,14 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_block, 
> ram_addr_t addr,
>          }
>  
>          block->host = xen_map_cache(block->offset, block->max_length, 1);
> +        if (block->host == NULL) {
> +            /* In case we cannot establish the mapping right away we might
> +             * still be able to do it later e.g. on a later stage of restore.
> +             * We don't touch the block and return NULL here to indicate
> +             * that intention.
> +             */
> +            return NULL;
> +        }
>      }
>  
>      return ramblock_ptr(block, addr);
> diff --git a/hw/display/vga.c b/hw/display/vga.c
> index 69c3e1d..f8aebe3 100644
> --- a/hw/display/vga.c
> +++ b/hw/display/vga.c
> @@ -2035,6 +2035,11 @@ static int vga_common_post_load(void *opaque, int 
> version_id)
>  {
>      VGACommonState *s = opaque;
>  
> +    if (xen_enabled() && !s->vram_ptr) {
> +        /* update VRAM region pointer in case we've failed
> +         * the last time during init phase */
> +        s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
> +    }

Please add a similar in-code comment at the point where we try to set
vram_ptr the first time. It might be suitable to add a debug printf if
vram_ptr is NULL then.


>      /* force refresh */
>      s->graphic_mode = -1;
>      vbe_update_vgaregs(s);
> diff --git a/xen-hvm.c b/xen-hvm.c
> index 5043beb..8bedd9b 100644
> --- a/xen-hvm.c
> +++ b/xen-hvm.c
> @@ -317,7 +317,6 @@ static int xen_add_to_physmap(XenIOState *state,
>      XenPhysmap *physmap = NULL;
>      hwaddr pfn, start_gpfn;
>      hwaddr phys_offset = memory_region_get_ram_addr(mr);
> -    char path[80], value[17];
>      const char *mr_name;
>  
>      if (get_physmapping(state, start_addr, size)) {
> @@ -340,6 +339,22 @@ go_physmap:
>      DPRINTF("mapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx"\n",
>              start_addr, start_addr + size);
>  
> +    mr_name = memory_region_name(mr);
> +
> +    physmap = g_malloc(sizeof(XenPhysmap));
> +
> +    physmap->start_addr = start_addr;
> +    physmap->size = size;
> +    physmap->name = mr_name;
> +    physmap->phys_offset = phys_offset;
> +
> +    QLIST_INSERT_HEAD(&state->physmap, physmap, list);
> +
> +    if (runstate_check(RUN_STATE_INMIGRATE)) {
> +        /* If we are migrating the region has been already mapped */
> +        return 0;
> +    }
> +
>      pfn = phys_offset >> TARGET_PAGE_BITS;
>      start_gpfn = start_addr >> TARGET_PAGE_BITS;
>      for (i = 0; i < size >> TARGET_PAGE_BITS; i++) {
> @@ -350,49 +365,17 @@ go_physmap:
>          if (rc) {
>              DPRINTF("add_to_physmap MFN %"PRI_xen_pfn" to PFN %"
>                      PRI_xen_pfn" failed: %d (errno: %d)\n", idx, gpfn, rc, 
> errno);
> +
> +            QLIST_REMOVE(physmap, list);
> +            g_free(physmap);
>              return -rc;
>          }
>      }
>  
> -    mr_name = memory_region_name(mr);
> -
> -    physmap = g_malloc(sizeof (XenPhysmap));
> -
> -    physmap->start_addr = start_addr;
> -    physmap->size = size;
> -    physmap->name = mr_name;
> -    physmap->phys_offset = phys_offset;
> -
> -    QLIST_INSERT_HEAD(&state->physmap, physmap, list);
> -
>      xc_domain_pin_memory_cacheattr(xen_xc, xen_domid,
>                                     start_addr >> TARGET_PAGE_BITS,
>                                     (start_addr + size - 1) >> 
> TARGET_PAGE_BITS,
>                                     XEN_DOMCTL_MEM_CACHEATTR_WB);
> -
> -    snprintf(path, sizeof(path),
> -            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/start_addr",
> -            xen_domid, (uint64_t)phys_offset);
> -    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)start_addr);
> -    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
> -        return -1;
> -    }
> -    snprintf(path, sizeof(path),
> -            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/size",
> -            xen_domid, (uint64_t)phys_offset);
> -    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)size);
> -    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
> -        return -1;
> -    }
> -    if (mr_name) {
> -        snprintf(path, sizeof(path),
> -                "/local/domain/0/device-model/%d/physmap/%"PRIx64"/name",
> -                xen_domid, (uint64_t)phys_offset);
> -        if (!xs_write(state->xenstore, 0, path, mr_name, strlen(mr_name))) {
> -            return -1;
> -        }
> -    }
> -
>      return 0;
>  }
>  
> @@ -1152,54 +1135,6 @@ static void xen_exit_notifier(Notifier *n, void *data)
>      xs_daemon_close(state->xenstore);
>  }
>  
> -static void xen_read_physmap(XenIOState *state)
> -{
> -    XenPhysmap *physmap = NULL;
> -    unsigned int len, num, i;
> -    char path[80], *value = NULL;
> -    char **entries = NULL;
> -
> -    snprintf(path, sizeof(path),
> -            "/local/domain/0/device-model/%d/physmap", xen_domid);
> -    entries = xs_directory(state->xenstore, 0, path, &num);
> -    if (entries == NULL)
> -        return;
> -
> -    for (i = 0; i < num; i++) {
> -        physmap = g_malloc(sizeof (XenPhysmap));
> -        physmap->phys_offset = strtoull(entries[i], NULL, 16);
> -        snprintf(path, sizeof(path),
> -                "/local/domain/0/device-model/%d/physmap/%s/start_addr",
> -                xen_domid, entries[i]);
> -        value = xs_read(state->xenstore, 0, path, &len);
> -        if (value == NULL) {
> -            g_free(physmap);
> -            continue;
> -        }
> -        physmap->start_addr = strtoull(value, NULL, 16);
> -        free(value);
> -
> -        snprintf(path, sizeof(path),
> -                "/local/domain/0/device-model/%d/physmap/%s/size",
> -                xen_domid, entries[i]);
> -        value = xs_read(state->xenstore, 0, path, &len);
> -        if (value == NULL) {
> -            g_free(physmap);
> -            continue;
> -        }
> -        physmap->size = strtoull(value, NULL, 16);
> -        free(value);
> -
> -        snprintf(path, sizeof(path),
> -                "/local/domain/0/device-model/%d/physmap/%s/name",
> -                xen_domid, entries[i]);
> -        physmap->name = xs_read(state->xenstore, 0, path, &len);
> -
> -        QLIST_INSERT_HEAD(&state->physmap, physmap, list);
> -    }
> -    free(entries);
> -}
> -
>  static void xen_wakeup_notifier(Notifier *notifier, void *data)
>  {
>      xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 0);
> @@ -1339,7 +1274,6 @@ void xen_hvm_init(PCMachineState *pcms, MemoryRegion 
> **ram_memory)
>          goto err;
>      }
>      xen_be_register_common();
> -    xen_read_physmap(state);
>  
>      /* Disable ACPI build because Xen handles it */
>      pcms->acpi_build_enabled = false;
> -- 
> 2.7.4
> 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.