All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Woodhouse <dwmw2@infradead.org>
To: Xen-devel <xen-devel@lists.xenproject.org>
Cc: "Stefano Stabellini" <sstabellini@kernel.org>,
	"Julien Grall" <julien@xen.org>, "Wei Liu" <wl@xen.org>,
	"Konrad Rzeszutek Wilk" <konrad.wilk@oracle.com>,
	"George Dunlap" <George.Dunlap@eu.citrix.com>,
	"Andrew Cooper" <andrew.cooper3@citrix.com>,
	"Varad Gautam" <vrd@amazon.de>,
	paul@xen.org, "Ian Jackson" <ian.jackson@eu.citrix.com>,
	"Hongyan Xia" <hongyxia@amazon.com>, "Amit Shah" <aams@amazon.de>,
	"Roger Pau Monné" <roger.pau@citrix.com>
Subject: [Xen-devel] [RFC PATCH v3 07/22] Add basic live update stream creation
Date: Thu, 30 Jan 2020 16:13:15 +0000	[thread overview]
Message-ID: <20200130161330.2324143-7-dwmw2@infradead.org> (raw)
In-Reply-To: <20200130161330.2324143-1-dwmw2@infradead.org>

From: David Woodhouse <dwmw@amazon.co.uk>

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
 xen/common/Makefile    |   1 +
 xen/common/lu/Makefile |   1 +
 xen/common/lu/stream.c | 135 +++++++++++++++++++++++++++++++++++++++++
 xen/include/xen/lu.h   |  29 +++++++++
 4 files changed, 166 insertions(+)
 create mode 100644 xen/common/lu/Makefile
 create mode 100644 xen/common/lu/stream.c
 create mode 100644 xen/include/xen/lu.h

diff --git a/xen/common/Makefile b/xen/common/Makefile
index 2abb8250b0..60502bb909 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -72,3 +72,4 @@ subdir-$(CONFIG_UBSAN) += ubsan
 
 subdir-$(CONFIG_NEEDS_LIBELF) += libelf
 subdir-$(CONFIG_HAS_DEVICE_TREE) += libfdt
+subdir-y += lu
diff --git a/xen/common/lu/Makefile b/xen/common/lu/Makefile
new file mode 100644
index 0000000000..68991b3ca4
--- /dev/null
+++ b/xen/common/lu/Makefile
@@ -0,0 +1 @@
+obj-y += stream.o
diff --git a/xen/common/lu/stream.c b/xen/common/lu/stream.c
new file mode 100644
index 0000000000..10e123a466
--- /dev/null
+++ b/xen/common/lu/stream.c
@@ -0,0 +1,135 @@
+/*
+ * Live update data stream handling.
+ *
+ * During live update, one version of Xen (Xen#1) performs a kexec into
+ * a new version of Xen (Xen#2), performing guest-transparent live
+ * migration of all existing domains.
+ *
+ * Xen#2 must avoid scribbling on any pages which may belong to existing
+ * domains. In order to achieve this, we reserve a contiguous area of
+ * physical memory to be used by the boot allocator in Xen#2. Xen must
+ * not allocate pages from that region which are later shared with
+ * guests or need to persist across live update.
+ *
+ * The live update bootmem region is reserved by the first Xen to boot,
+ * and userspace can obtain its address using KEXEC_CMD_kexec_get_range
+ * with the new KEXEC_RANGE_MA_LIVEUPDATE type. Userspace kexec(8)
+ * appends the appropriate 'liveupdate=' parameter to the command line
+ * of Xen#2 when setting up the kexec image.
+ *
+ * At the time of kexec, Xen#1 serialises the domain state into buffers
+ * allocated from its own heap., then creates a single physically
+ * contiguous scatter-gather list containing the MFNs of those data
+ * pages (which Xen#2 can then trivially vmap()). In a system with
+ * 4KiB pages, the MFN list for the live update data stream will fit
+ * into a single page until the total size of the live update data
+ * exceeds 2MiB.
+ *
+ * The physical address of the MFN list is passed to Xen#2 by placing
+ * it at the start of the reserved live update bootmem region, with a
+ * magic number to avoid false positives.
+ */
+
+#include <xen/types.h>
+#include <xen/vmap.h>
+#include <xen/lu.h>
+
+static int lu_stream_extend(struct lu_stream *stream, int nr_pages)
+{
+    int order = get_order_from_bytes((nr_pages + 1) * sizeof(mfn_t));
+    int old_order = get_order_from_bytes((stream->nr_pages + 1) * sizeof(mfn_t));
+
+    if ( !stream->nr_pages || order > old_order )
+    {
+        mfn_t *new_pglist = alloc_xenheap_pages(order, 0);
+
+		if ( !new_pglist )
+            return -ENOMEM;
+
+        if ( stream->nr_pages )
+        {
+            memcpy(new_pglist, stream->pagelist,
+                   stream->nr_pages * sizeof(mfn_t));
+            free_xenheap_pages(stream->pagelist, old_order);
+        }
+        stream->pagelist = new_pglist;
+    }
+    while ( stream->nr_pages < nr_pages )
+    {
+        struct page_info *pg = alloc_domheap_page(NULL, MEMF_no_owner);
+
+        if ( !pg )
+        {
+            /* Ensure the cleanup frees the correct order of pagelist */
+            stream->nr_pages++;
+
+            return -ENOMEM;
+        }
+        stream->pagelist[stream->nr_pages++] = page_to_mfn(pg);
+        stream->pagelist[stream->nr_pages] = INVALID_MFN;
+    }
+
+    if ( stream->data )
+        vunmap(stream->data);
+    stream->data = vmap(stream->pagelist, stream->nr_pages);
+    if ( !stream->data )
+        return -ENOMEM;
+
+    return 0;
+}
+
+void *lu_stream_reserve(struct lu_stream *stream, size_t size)
+{
+    int nr_pages = (stream->len + size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+    if ( stream->nr_pages < nr_pages && lu_stream_extend(stream, nr_pages) )
+        return NULL;
+
+    return stream->data + stream->len;
+}
+
+void lu_stream_end_reservation(struct lu_stream *stream, size_t size)
+{
+    stream->len += size;
+}
+
+int lu_stream_append(struct lu_stream *stream, const void *data, size_t size)
+{
+	void *p = lu_stream_reserve(stream, size);
+
+    if ( !p )
+        return -ENOMEM;
+    memcpy(p, data, size);
+    lu_stream_end_reservation(stream, size);
+
+    return 0;
+}
+
+void lu_stream_free(struct lu_stream *stream)
+{
+    unsigned int order = get_order_from_bytes((stream->nr_pages + 1) * sizeof(mfn_t));
+    unsigned int i;
+
+    if ( stream->data )
+        vunmap(stream->data);
+
+    if ( stream->pagelist )
+    {
+        for ( i = 0; i < stream->nr_pages; i++ )
+        {
+            if (mfn_valid(stream->pagelist[i]))
+                free_domheap_page(mfn_to_page(stream->pagelist[i]));
+        }
+        free_xenheap_pages(stream->pagelist, order);
+    }
+}
+
+/*
+ * local variables:
+ * mode: c
+ * c-file-style: "bsd"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * end:
+ */
diff --git a/xen/include/xen/lu.h b/xen/include/xen/lu.h
new file mode 100644
index 0000000000..abb30545fe
--- /dev/null
+++ b/xen/include/xen/lu.h
@@ -0,0 +1,29 @@
+#ifndef __XEN_LU_H__
+#define __XEN_LU_H__
+
+#include <xen/types.h>
+#include <xen/mm.h>
+
+struct lu_stream {
+    mfn_t *pagelist;
+    size_t len;
+    int nr_pages;
+    char *data;
+};
+
+void *lu_stream_reserve(struct lu_stream *stream, size_t size);
+void lu_stream_end_reservation(struct lu_stream *stream, size_t size);
+int lu_stream_append(struct lu_stream *stream, const void *data, size_t size);
+void lu_stream_free(struct lu_stream *stream);
+
+#endif /* __XEN_LU_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.21.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  parent reply	other threads:[~2020-01-30 16:14 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-30 16:12 [Xen-devel] [RFC PATCH v3 0/22] Live update: boot memory management, data stream handling, record format David Woodhouse
2020-01-30 16:13 ` [Xen-devel] [RFC PATCH v3 01/22] x86/setup: Don't skip 2MiB underneath relocated Xen image David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 02/22] x86/boot: Reserve live update boot memory David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 03/22] Reserve live update memory regions David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 04/22] Add KEXEC_RANGE_MA_LIVEUPDATE David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 05/22] Add KEXEC_TYPE_LIVE_UPDATE David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 06/22] Add IND_WRITE64 primitive to kexec kimage David Woodhouse
2020-01-30 16:13   ` David Woodhouse [this message]
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 08/22] Add kimage_add_live_update_data() David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 09/22] Add basic lu_save_all() shell David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 10/22] Don't add bad pages above HYPERVISOR_VIRT_END to the domheap David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 11/22] xen/vmap: allow vm_init_type to be called during early_boot David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 12/22] xen/vmap: allow vmap() to be called during early boot David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 13/22] x86/setup: move vm_init() before end_boot_allocator() David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 14/22] Detect live update breadcrumb at boot and map data stream David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 15/22] Start documenting the live update handover David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 16/22] Migrate migration stream definitions into Xen public headers David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 17/22] Add lu_stream_{open, close, append}_record() David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 18/22] Add LU_VERSION and LU_END records to live update stream David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 19/22] Add shell of lu_reserve_pages() David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 20/22] x86/setup: lift dom0 creation out into create_dom0 function David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 21/22] x86/setup: finish plumbing in live update path through __start_xen() David Woodhouse
2020-01-30 16:13   ` [Xen-devel] [RFC PATCH v3 22/22] x86/setup: simplify handling of initrdidx when no initrd present David Woodhouse
2020-01-31 17:16 ` [Xen-devel] [RFC PATCH v3 23/22] x86/smp: reset x2apic_enabled in smp_send_stop() David Woodhouse
2020-02-18 15:22 ` [Xen-devel] [RFC PATCH v3 0/22] Live update: boot memory management, data stream handling, record format Ian Jackson

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=20200130161330.2324143-7-dwmw2@infradead.org \
    --to=dwmw2@infradead.org \
    --cc=George.Dunlap@eu.citrix.com \
    --cc=aams@amazon.de \
    --cc=andrew.cooper3@citrix.com \
    --cc=hongyxia@amazon.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=julien@xen.org \
    --cc=konrad.wilk@oracle.com \
    --cc=paul@xen.org \
    --cc=roger.pau@citrix.com \
    --cc=sstabellini@kernel.org \
    --cc=vrd@amazon.de \
    --cc=wl@xen.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.