From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Xen-devel <xen-devel@lists.xen.org>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: [Patch v6 05/13] tools/libxc: noarch common code
Date: Mon, 7 Jul 2014 18:37:54 +0100 [thread overview]
Message-ID: <1404754682-28379-6-git-send-email-andrew.cooper3@citrix.com> (raw)
In-Reply-To: <1404754682-28379-1-git-send-email-andrew.cooper3@citrix.com>
Add the context structure used to keep state during the save/restore
process.
Define the set of architecture or domain type specific operations with a
set of callbacks (save_ops, and restore_ops).
Add common functions for writing records.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
v6:
* Use writev() instead of write()
---
tools/libxc/saverestore/common.c | 42 ++++++
tools/libxc/saverestore/common.h | 273 ++++++++++++++++++++++++++++++++++++++
2 files changed, 315 insertions(+)
diff --git a/tools/libxc/saverestore/common.c b/tools/libxc/saverestore/common.c
index 7884175..6925bd9 100644
--- a/tools/libxc/saverestore/common.c
+++ b/tools/libxc/saverestore/common.c
@@ -1,3 +1,5 @@
+#include <assert.h>
+
#include "common.h"
static const char *dhdr_types[] =
@@ -61,6 +63,46 @@ const char *rec_type_to_str(uint32_t type)
return "Reserved";
}
+int write_split_record(struct xc_sr_context *ctx, struct xc_sr_record *rec,
+ void *buf, size_t sz)
+{
+ static const char zeroes[(1u << REC_ALIGN_ORDER) - 1] = { 0 };
+
+ xc_interface *xch = ctx->xch;
+ typeof(rec->length) combined_length = rec->length + sz;
+ size_t record_length = ROUNDUP(combined_length, REC_ALIGN_ORDER);
+ struct iovec parts[] =
+ {
+ { &rec->type, sizeof(rec->type) },
+ { &combined_length, sizeof(combined_length) },
+ { rec->data, rec->length },
+ { buf, sz },
+ { (void*)zeroes, record_length - combined_length },
+ };
+
+ if ( record_length > REC_LENGTH_MAX )
+ {
+ ERROR("Record (0x%08"PRIx32", %s) length 0x%"PRIx32
+ " exceeds max (0x%"PRIx32")", rec->type,
+ rec_type_to_str(rec->type), rec->length, REC_LENGTH_MAX);
+ return -1;
+ }
+
+ if ( rec->length )
+ assert(rec->data);
+ if ( sz )
+ assert(buf);
+
+ if ( writev_exact(ctx->fd, parts, ARRAY_SIZE(parts)) )
+ goto err;
+
+ return 0;
+
+ err:
+ PERROR("Unable to write record to stream");
+ return -1;
+}
+
static void __attribute__((unused)) build_assertions(void)
{
XC_BUILD_BUG_ON(sizeof(struct xc_sr_ihdr) != 24);
diff --git a/tools/libxc/saverestore/common.h b/tools/libxc/saverestore/common.h
index cbecf0a..5021c15 100644
--- a/tools/libxc/saverestore/common.h
+++ b/tools/libxc/saverestore/common.h
@@ -1,7 +1,12 @@
#ifndef __COMMON__H
#define __COMMON__H
+#include <stdbool.h>
+
#include "../xg_private.h"
+#include "../xg_save_restore.h"
+#include "../xc_dom.h"
+#include "../xc_bitops.h"
#include "stream_format.h"
@@ -11,6 +16,274 @@ const char *dhdr_type_to_str(uint32_t type);
/* String representation of Record types. */
const char *rec_type_to_str(uint32_t type);
+struct xc_sr_context;
+struct xc_sr_record;
+
+/**
+ * Save operations. To be implemented for each type of guest, for use by the
+ * common save algorithm.
+ *
+ * Every function must be implemented, even if only with a no-op stub.
+ */
+struct xc_sr_save_ops
+{
+ /* Convert a PFN to GFN. May return ~0UL for an invalid mapping. */
+ xen_pfn_t (*pfn_to_gfn)(const struct xc_sr_context *ctx, xen_pfn_t pfn);
+
+ /**
+ * Optionally transform the contents of a page from being specific to the
+ * sending environment, to being generic for the stream.
+ *
+ * The page of data at the end of 'page' may be a read-only mapping of a
+ * running guest; it must not be modified. If no transformation is
+ * required, the callee should leave '*pages' unouched.
+ *
+ * If a transformation is required, the callee should allocate themselves
+ * a local page using malloc() and return it via '*page'.
+ *
+ * The caller shall free() '*page' in all cases. In the case that the
+ * callee enounceters an error, it should *NOT* free() the memory it
+ * allocated for '*page'.
+ *
+ * It is valid to fail with EAGAIN if the transformation is not able to be
+ * completed at this point. The page shall be retried later.
+ *
+ * @returns 0 for success, -1 for failure, with errno appropriately set.
+ */
+ int (*normalise_page)(struct xc_sr_context *ctx, xen_pfn_t type,
+ void **page);
+
+ /**
+ * Set up local environment to restore a domain. This is called before
+ * any records are written to the stream. (Typically querying running
+ * domain state, setting up mappings etc.)
+ */
+ int (*setup)(struct xc_sr_context *ctx);
+
+ /**
+ * Write records which need to be at the start of the stream. This is
+ * called after the Image and Domain headers are written. (Any records
+ * which need to be ahead of the memory.)
+ */
+ int (*start_of_stream)(struct xc_sr_context *ctx);
+
+ /**
+ * Write records which need to be at the end of the stream, following the
+ * complete memory contents. The caller shall handle writing the END
+ * record into the stream. (Any records which need to be after the memory
+ * is complete.)
+ */
+ int (*end_of_stream)(struct xc_sr_context *ctx);
+
+ /**
+ * Clean up the local environment. Will be called exactly once, either
+ * after a successful save, or upon encountering an error.
+ */
+ int (*cleanup)(struct xc_sr_context *ctx);
+};
+
+
+/**
+ * Restore operations. To be implemented for each type of guest, for use by
+ * the common restore algorithm.
+ *
+ * Every function must be implemented, even if only with a no-op stub.
+ */
+struct xc_sr_restore_ops
+{
+ /* Convert a PFN to GFN. May return ~0UL for an invalid mapping. */
+ xen_pfn_t (*pfn_to_gfn)(const struct xc_sr_context *ctx, xen_pfn_t pfn);
+
+ /* Check to see whether a PFN is valid. */
+ bool (*pfn_is_valid)(const struct xc_sr_context *ctx, xen_pfn_t pfn);
+
+ /* Set the GFN of a PFN. */
+ void (*set_gfn)(struct xc_sr_context *ctx, xen_pfn_t pfn, xen_pfn_t gfn);
+
+ /* Set the type of a PFN. */
+ void (*set_page_type)(struct xc_sr_context *ctx, xen_pfn_t pfn,
+ xen_pfn_t type);
+
+ /**
+ * Optionally transform the contents of a page from being generic in the
+ * stream, to being specific to the restoring environment.
+ *
+ * 'page' is expected to be modified in-place if a transformation is
+ * required.
+ *
+ * @returns 0 for success, -1 for failure, with errno appropriately set.
+ */
+ int (*localise_page)(struct xc_sr_context *ctx, uint32_t type, void *page);
+
+ /**
+ * Set up local environment to restore a domain. This is called before
+ * any records are read from the stream.
+ */
+ int (*setup)(struct xc_sr_context *ctx);
+
+ /**
+ * Process an individual record from the stream. The caller shall take
+ * care of processing common records (e.g. END, PAGE_DATA).
+ *
+ * @return 0 for success, -1 for failure, or the sentinal value
+ * RECORD_NOT_PROCESSED.
+ */
+#define RECORD_NOT_PROCESSED 1
+ int (*process_record)(struct xc_sr_context *ctx, struct xc_sr_record *rec);
+
+ /**
+ * Perform any actions required after the stream has been finished. Called
+ * after the END record has been received.
+ */
+ int (*stream_complete)(struct xc_sr_context *ctx);
+
+ /**
+ * Clean up the local environment. Will be called exactly once, either
+ * after a successful restore, or upon encountering an error.
+ */
+ int (*cleanup)(struct xc_sr_context *ctx);
+};
+
+
+struct xc_sr_context
+{
+ xc_interface *xch;
+ uint32_t domid;
+ int fd;
+
+ xc_dominfo_t dominfo;
+
+ union
+ {
+ struct
+ {
+ struct xc_sr_save_ops ops;
+ struct save_callbacks *callbacks;
+
+ /* Live migrate vs nonlive suspend. */
+ bool live;
+
+ /* Further debugging information in the stream. */
+ bool debug;
+
+ unsigned long p2m_size;
+
+ xen_pfn_t *batch_pfns;
+ unsigned nr_batch_pfns;
+ unsigned long *deferred_pages;
+ } save;
+
+ struct
+ {
+ struct xc_sr_restore_ops ops;
+ struct restore_callbacks *callbacks;
+
+ /* From Image Header. */
+ uint32_t format_version;
+
+ /* From Domain Header. */
+ uint32_t guest_type;
+ uint32_t guest_page_size;
+
+ /* Xenstore and Console parameters. Some as input from caller,
+ * some as input from stream, some output. */
+ unsigned long xenstore_mfn, console_mfn;
+ unsigned int xenstore_evtchn, console_evtchn;
+ domid_t xenstore_domid, console_domid;
+
+ /* Bitmap of currently populated PFNs during restore. */
+ unsigned long *populated_pfns;
+ xen_pfn_t max_populated_pfn;
+
+ /* Sender has invoked verify mode on the stream. */
+ bool verify;
+ } restore;
+ };
+
+ union
+ {
+ struct
+ {
+ /* 4 or 8; 32 or 64 bit domain */
+ unsigned int width;
+ /* 3 or 4 pagetable levels */
+ unsigned int levels;
+
+ /* Maximum Xen frame */
+ unsigned long max_mfn;
+ /* Read-only machine to phys map */
+ xen_pfn_t *m2p;
+ /* first mfn of the compat m2p (Only needed for 32bit PV guests) */
+ xen_pfn_t compat_m2p_mfn0;
+ /* Number of m2p frames mapped */
+ unsigned long nr_m2p_frames;
+
+ /* Maximum guest frame */
+ unsigned long max_pfn;
+
+ /* Number of frames making up the p2m */
+ unsigned int p2m_frames;
+ /* Guest's phys to machine map. Mapped read-only (save) or
+ * allocated locally (restore). Uses guest unsigned longs. */
+ void *p2m;
+ /* The guest pfns containing the p2m leaves */
+ xen_pfn_t *p2m_pfns;
+ /* Types for each page */
+ uint32_t *pfn_types;
+
+ /* Read-only mapping of guests shared info page */
+ shared_info_any_t *shinfo;
+ } x86_pv;
+ };
+};
+
+
+struct xc_sr_record
+{
+ uint32_t type;
+ uint32_t length;
+ void *data;
+};
+
+/*
+ * Writes a split record to the stream, applying correct padding where
+ * appropriate. It is common when sending records containing blobs from Xen
+ * that the header and blob data are separate. This function accepts a second
+ * buffer and length, and will merge it with the main record when sending.
+ *
+ * Records with a non-zero length must provide a valid data field; records
+ * with a 0 length shall have their data field ignored.
+ *
+ * Returns 0 on success and non0 on failure.
+ */
+int write_split_record(struct xc_sr_context *ctx, struct xc_sr_record *rec,
+ void *buf, size_t sz);
+
+/*
+ * Writes a record to the stream, applying correct padding where appropriate.
+ * Records with a non-zero length must provide a valid data field; records
+ * with a 0 length shall have their data field ignored.
+ *
+ * Returns 0 on success and non0 on failure.
+ */
+static inline int write_record(struct xc_sr_context *ctx,
+ struct xc_sr_record *rec)
+{
+ return write_split_record(ctx, rec, NULL, 0);
+}
+
+/*
+ * Architecture specific function to write a SAVING_CPU record into the stream.
+ * May be stub.
+ */
+int arch_write_saving_cpu(struct xc_sr_context *ctx);
+
+/*
+ * Architecture specific function to handle a SAVING_CPU record from the stream.
+ * May be stub.
+ */
+int arch_handle_saving_cpu(struct xc_sr_context *ctx, struct xc_sr_record *rec);
+
#endif
/*
* Local variables:
--
1.7.10.4
next prev parent reply other threads:[~2014-07-07 17:37 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-07 17:37 [PATCH v6 0/13] Migration Stream v2 Andrew Cooper
2014-07-07 17:37 ` [Patch v6 01/13] docs: libxc migration stream specification Andrew Cooper
2014-07-08 3:53 ` Hongyang Yang
2014-07-08 8:48 ` Andrew Cooper
2014-07-08 8:59 ` Hongyang Yang
2014-07-08 9:36 ` David Vrabel
2014-07-08 10:48 ` Andrew Cooper
2014-07-07 17:37 ` [Patch v6 02/13] tools/python: Scripts relating to migrationv2 streams Andrew Cooper
2014-07-28 15:20 ` Ian Campbell
2014-07-28 15:38 ` Andrew Cooper
2014-07-28 15:58 ` Ian Campbell
2014-07-29 13:55 ` Jon Ludlam
2014-07-07 17:37 ` [Patch v6 03/13] [HACK] tools/libxc: save/restore v2 framework Andrew Cooper
2014-07-07 17:37 ` [Patch v6 04/13] tools/libxc: C implementation of stream format Andrew Cooper
2014-07-07 17:37 ` Andrew Cooper [this message]
2014-07-07 17:37 ` [Patch v6 06/13] tools/libxc: x86 common code Andrew Cooper
2014-07-07 17:37 ` [Patch v6 07/13] tools/libxc: x86 PV " Andrew Cooper
2014-07-07 17:37 ` [Patch v6 08/13] tools/libxc: x86 PV save code Andrew Cooper
2014-07-07 17:37 ` [Patch v6 09/13] tools/libxc: x86 PV restore code Andrew Cooper
2014-07-07 17:37 ` [Patch v6 10/13] tools/libxc: x86 HVM save code Andrew Cooper
2014-07-07 17:38 ` [Patch v6 11/13] tools/libxc: x86 HVM restore code Andrew Cooper
2014-07-18 14:38 ` Wen Congyang
2014-07-18 15:09 ` Andrew Cooper
2014-07-18 15:42 ` Paul Durrant
2014-07-18 16:13 ` Wen Congyang
2014-07-07 17:38 ` [Patch v6 12/13] tools/libxc: noarch save code Andrew Cooper
2014-07-07 17:38 ` [Patch v6 13/13] tools/libxc: noarch restore code Andrew Cooper
2014-07-08 10:50 ` [PATCH v6 0/13] Migration Stream v2 David Vrabel
2014-07-08 11:10 ` Ian Campbell
2014-07-08 16:35 ` Konrad Rzeszutek Wilk
2014-07-08 17:35 ` Andrew Cooper
2014-07-09 6:01 ` Hongyang Yang
2014-07-09 9:40 ` Andrew Cooper
2014-07-09 15:27 ` Konrad Rzeszutek Wilk
2014-07-10 10:19 ` Andrew Cooper
2014-07-28 15:01 ` Ian Campbell
2014-07-28 15:02 ` Andrew Cooper
2014-07-28 15:20 ` Ian Campbell
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=1404754682-28379-6-git-send-email-andrew.cooper3@citrix.com \
--to=andrew.cooper3@citrix.com \
--cc=xen-devel@lists.xen.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).