qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Igor Druzhinin <igor.druzhinin@citrix.com>,
	"sstabellini@kernel.org" <sstabellini@kernel.org>,
	Anthony Perard <anthony.perard@citrix.com>
Cc: "qemu-devel@nongnu.org" <qemu-devel@nongnu.org>,
	"xen-devel@lists.xenproject.org" <xen-devel@lists.xenproject.org>
Subject: Re: [Qemu-devel] [PATCH v2] xen: don't save/restore the physmap on VM save/restore
Date: Mon, 13 Mar 2017 09:17:08 +0000	[thread overview]
Message-ID: <28eabb0e517e46b6b644f11d32d70e3d@AMSPEX02CL03.citrite.net> (raw)
In-Reply-To: <1489176412-30529-1-git-send-email-igor.druzhinin@citrix.com>

> -----Original Message-----
> From: Igor Druzhinin
> Sent: 10 March 2017 20:07
> To: sstabellini@kernel.org; Anthony Perard <anthony.perard@citrix.com>
> Cc: Paul Durrant <Paul.Durrant@citrix.com>; qemu-devel@nongnu.org; xen-
> devel@lists.xenproject.org; Igor Druzhinin <igor.druzhinin@citrix.com>
> Subject: [PATCH v2] xen: don't save/restore the physmap on VM
> save/restore
> 
> 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
> only register the pointer to the framebuffer without actual mapping.
> Then, during the memory region restore phase, we perform the mapping
> of the known address and update the VRAM region metadata (including
> previously registered pointer) accordingly.
> 
> Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
> ---
> v2:
> * Fix some building and coding style issues
> ---
>  exec.c               |   3 ++
>  hw/display/vga.c     |   2 +-
>  include/hw/xen/xen.h |   2 +-
>  xen-hvm-stub.c       |   2 +-
>  xen-hvm.c            | 114 ++++++++++++---------------------------------------
>  5 files changed, 33 insertions(+), 90 deletions(-)
> 
> diff --git a/exec.c b/exec.c
> index aabb035..5f2809e 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -2008,6 +2008,9 @@ 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) {
> +            return NULL;
> +        }

I don't think this is right. Callers of this function do not seem to ever expect it to fail. Specifically the call to memory_region_get_ram_ptr() made by vga_common_init() just stashes the pointer as the VRAM base and never checks its validity.

Anyway, if you modify do this code, you should cc the appropriate maintainers (Guest CPU cores) and justify why you need to.

>      }
>      return ramblock_ptr(block, addr);
>  }
> diff --git a/hw/display/vga.c b/hw/display/vga.c
> index 69c3e1d..be554c2 100644
> --- a/hw/display/vga.c
> +++ b/hw/display/vga.c
> @@ -2163,7 +2163,7 @@ void vga_common_init(VGACommonState *s,
> Object *obj, bool global_vmstate)
>      memory_region_init_ram(&s->vram, obj, "vga.vram", s->vram_size,
>                             &error_fatal);
>      vmstate_register_ram(&s->vram, global_vmstate ? NULL : DEVICE(obj));
> -    xen_register_framebuffer(&s->vram);
> +    xen_register_framebuffer(&s->vram, &s->vram_ptr);
>      s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
>      s->get_bpp = vga_get_bpp;
>      s->get_offsets = vga_get_offsets;
> diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h
> index 09c2ce5..3831843 100644
> --- a/include/hw/xen/xen.h
> +++ b/include/hw/xen/xen.h
> @@ -45,6 +45,6 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t
> size,
>                     struct MemoryRegion *mr, Error **errp);
>  void xen_modified_memory(ram_addr_t start, ram_addr_t length);
> 
> -void xen_register_framebuffer(struct MemoryRegion *mr);
> +void xen_register_framebuffer(struct MemoryRegion *mr, uint8_t **ptr);
> 
>  #endif /* QEMU_HW_XEN_H */
> diff --git a/xen-hvm-stub.c b/xen-hvm-stub.c
> index c500325..c89065e 100644
> --- a/xen-hvm-stub.c
> +++ b/xen-hvm-stub.c
> @@ -46,7 +46,7 @@ qemu_irq *xen_interrupt_controller_init(void)
>      return NULL;
>  }
> 
> -void xen_register_framebuffer(MemoryRegion *mr)
> +void xen_register_framebuffer(MemoryRegion *mr, uint8_t **ptr)
>  {
>  }
> 
> diff --git a/xen-hvm.c b/xen-hvm.c
> index 5043beb..270cd99 100644
> --- a/xen-hvm.c
> +++ b/xen-hvm.c
> @@ -41,6 +41,7 @@
> 
>  static MemoryRegion ram_memory, ram_640k, ram_lo, ram_hi;
>  static MemoryRegion *framebuffer;
> +static uint8_t **framebuffer_ptr;
>  static bool xen_in_migration;
> 
>  /* Compatibility with older version */
> @@ -302,7 +303,6 @@ static hwaddr xen_phys_offset_to_gaddr(hwaddr
> start_addr,
>              return physmap->start_addr;
>          }
>      }
> -

Pure whitespace fix. Needs to either be called out in the commit comment or separated.
The rest of the patch looks good to me.

  Paul

>      return start_addr;
>  }
> 
> @@ -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,27 @@ 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)) {
> +        /* At this point we have a physmap entry for the framebuffer region
> +         * established during the restore phase so we can safely update the
> +         * registered framebuffer address here. */

The jump to go_physmap is predicated on (mr == framebuffer && start_addr > 0xbffff) so the following 'if' is unnecessary.

> +        if (mr == framebuffer) {
> +            *framebuffer_ptr = memory_region_get_ram_ptr(framebuffer);
> +        }
> +        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 +370,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 +1140,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 +1279,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;
> @@ -1374,9 +1313,10 @@ void destroy_hvm_domain(bool reboot)
>      }
>  }
> 
> -void xen_register_framebuffer(MemoryRegion *mr)
> +void xen_register_framebuffer(MemoryRegion *mr, uint8_t **ptr)
>  {
>      framebuffer = mr;
> +    framebuffer_ptr = ptr;
>  }
> 
>  void xen_shutdown_fatal_error(const char *fmt, ...)
> --
> 2.7.4

      reply	other threads:[~2017-03-13  9:17 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-10 20:06 [Qemu-devel] [PATCH v2] xen: don't save/restore the physmap on VM save/restore Igor Druzhinin
2017-03-13  9:17 ` Paul Durrant [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=28eabb0e517e46b6b644f11d32d70e3d@AMSPEX02CL03.citrite.net \
    --to=paul.durrant@citrix.com \
    --cc=anthony.perard@citrix.com \
    --cc=igor.druzhinin@citrix.com \
    --cc=qemu-devel@nongnu.org \
    --cc=sstabellini@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).