From patchwork Tue Aug 18 10:30:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11720489 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C5266739 for ; Tue, 18 Aug 2020 10:31:50 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 96DC52075E for ; Tue, 18 Aug 2020 10:31:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=xen.org header.i=@xen.org header.b="GVu8xgu0" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 96DC52075E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=xen.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7yt6-00060I-JC; Tue, 18 Aug 2020 10:30:40 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7yt5-0005zo-O9 for xen-devel@lists.xenproject.org; Tue, 18 Aug 2020 10:30:39 +0000 X-Inumbo-ID: 9e626d64-ca0d-489a-a4f4-b8b8512d11c7 Received: from mail.xenproject.org (unknown [104.130.215.37]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 9e626d64-ca0d-489a-a4f4-b8b8512d11c7; Tue, 18 Aug 2020 10:30:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=xen.org; s=20200302mail; h=Content-Transfer-Encoding:Content-Type:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=WlInuve+Ty0i06juzwZCIvdmRjEkUUv4m/E/u80tNVw=; b=GVu8xgu0W/tEIjT6o8yyiDvwrv MTuJHwgv6sm/qgFPa4vFDcVe3Vnu0gt2495BOVcMijVXdph8xBp3JE83m8pzbPiM3kfxswMrp/N6r OeoZ94XuTg+/6vsonX6TLzziKN8fzajlDxUBLNphHQPrEnl1tw/SwsxXzTJzJTanRG9Y=; Received: from xenbits.xenproject.org ([104.239.192.120]) by mail.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7yt2-00013P-OU; Tue, 18 Aug 2020 10:30:36 +0000 Received: from host31-48-92-96.range31-48.btcentralplus.com ([31.48.92.96] helo=u2f063a87eabd5f.home) by xenbits.xenproject.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1k7yt2-0003Rw-G1; Tue, 18 Aug 2020 10:30:36 +0000 From: Paul Durrant To: xen-devel@lists.xenproject.org Cc: Paul Durrant , Julien Grall , Jan Beulich , Andrew Cooper , George Dunlap , Ian Jackson , Stefano Stabellini , Wei Liu , Volodymyr Babchuk , =?utf-8?q?Roger_Pau_Monn?= =?utf-8?q?=C3=A9?= Subject: [PATCH v7 1/9] xen/common: introduce a new framework for save/restore of 'domain' context Date: Tue, 18 Aug 2020 11:30:24 +0100 Message-Id: <20200818103032.3050-2-paul@xen.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200818103032.3050-1-paul@xen.org> References: <20200818103032.3050-1-paul@xen.org> MIME-Version: 1.0 X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" To allow enlightened HVM guests (i.e. those that have PV drivers) to be migrated without their co-operation it will be necessary to transfer 'PV' state such as event channel state, grant entry state, etc. Currently there is a framework (entered via the hvm_save/load() functions) that allows a domain's 'HVM' (architectural) state to be transferred but 'PV' state is also common with pure PV guests and so this framework is not really suitable. This patch adds the new public header and low level implementation of a new common framework, entered via the domain_save/load() functions. Subsequent patches will introduce other parts of the framework, and code that will make use of it within the current version of the libxc migration stream. This patch also marks the HVM-only framework as deprecated in favour of the new framework. Signed-off-by: Paul Durrant Acked-by: Julien Grall Reviewed-by: Jan Beulich --- Cc: Andrew Cooper Cc: George Dunlap Cc: Ian Jackson Cc: Stefano Stabellini Cc: Wei Liu Cc: Volodymyr Babchuk Cc: "Roger Pau Monné" v7: - Add an option to domain_load_end() to ignore unconsumed data, which will be needed by a subsequent patch - Kept acks since the modification is very small v4: - Addressed further comments from Jan v3: - Addressed comments from Julien and Jan - Save handlers no longer need to state entry length up-front - Save handlers expected to deal with multiple instances internally - Entries are now auto-padded to 8 byte boundary v2: - Allow multi-stage save/load to avoid the need to double-buffer - Get rid of the masks and add an 'ignore' flag instead - Create copy function union to preserve const save buffer - Deprecate HVM-only framework --- xen/common/Makefile | 1 + xen/common/save.c | 315 +++++++++++++++++++++++++ xen/include/public/arch-arm/hvm/save.h | 5 + xen/include/public/arch-x86/hvm/save.h | 5 + xen/include/public/save.h | 89 +++++++ xen/include/xen/save.h | 170 +++++++++++++ 6 files changed, 585 insertions(+) create mode 100644 xen/common/save.c create mode 100644 xen/include/public/save.h create mode 100644 xen/include/xen/save.h diff --git a/xen/common/Makefile b/xen/common/Makefile index 06881d023c..df4e884c57 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -39,6 +39,7 @@ obj-y += radix-tree.o obj-y += rbtree.o obj-y += rcupdate.o obj-y += rwlock.o +obj-y += save.o obj-y += shutdown.o obj-y += softirq.o obj-y += sort.o diff --git a/xen/common/save.c b/xen/common/save.c new file mode 100644 index 0000000000..841c4d0e4e --- /dev/null +++ b/xen/common/save.c @@ -0,0 +1,315 @@ +/* + * save.c: Save and restore PV guest state common to all domain types. + * + * Copyright Amazon.com Inc. or its affiliates. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; If not, see . + */ + +#include +#include + +struct domain_context { + struct domain *domain; + const char *name; /* for logging purposes */ + struct domain_save_descriptor desc; + size_t len; /* for internal accounting */ + union { + const struct domain_save_ops *save; + const struct domain_load_ops *load; + } ops; + void *priv; +}; + +static struct { + const char *name; + domain_save_handler save; + domain_load_handler load; +} handlers[DOMAIN_SAVE_CODE_MAX + 1]; + +void __init domain_register_save_type(unsigned int typecode, + const char *name, + domain_save_handler save, + domain_load_handler load) +{ + BUG_ON(typecode >= ARRAY_SIZE(handlers)); + + ASSERT(!handlers[typecode].save); + ASSERT(!handlers[typecode].load); + + handlers[typecode].name = name; + handlers[typecode].save = save; + handlers[typecode].load = load; +} + +int domain_save_begin(struct domain_context *c, unsigned int typecode, + unsigned int instance) +{ + int rc; + + if ( typecode != c->desc.typecode ) + { + ASSERT_UNREACHABLE(); + return -EINVAL; + } + ASSERT(!c->desc.length); /* Should always be zero during domain_save() */ + ASSERT(!c->len); /* Verify domain_save_end() was called */ + + rc = c->ops.save->begin(c->priv, &c->desc); + if ( rc ) + return rc; + + return 0; +} + +int domain_save_data(struct domain_context *c, const void *src, size_t len) +{ + int rc = c->ops.save->append(c->priv, src, len); + + if ( !rc ) + c->len += len; + + return rc; +} + +#define DOMAIN_SAVE_ALIGN 8 + +int domain_save_end(struct domain_context *c) +{ + struct domain *d = c->domain; + size_t len = ROUNDUP(c->len, DOMAIN_SAVE_ALIGN) - c->len; /* padding */ + int rc; + + if ( len ) + { + static const uint8_t pad[DOMAIN_SAVE_ALIGN] = {}; + + rc = domain_save_data(c, pad, len); + + if ( rc ) + return rc; + } + ASSERT(IS_ALIGNED(c->len, DOMAIN_SAVE_ALIGN)); + + if ( c->name ) + gdprintk(XENLOG_INFO, "%pd save: %s[%u] +%zu (-%zu)\n", d, c->name, + c->desc.instance, c->len, len); + + rc = c->ops.save->end(c->priv, c->len); + c->len = 0; + + return rc; +} + +int domain_save(struct domain *d, const struct domain_save_ops *ops, + void *priv, bool dry_run) +{ + struct domain_context c = { + .domain = d, + .ops.save = ops, + .priv = priv, + }; + static const struct domain_save_header h = { + .magic = DOMAIN_SAVE_MAGIC, + .xen_major = XEN_VERSION, + .xen_minor = XEN_SUBVERSION, + .version = DOMAIN_SAVE_VERSION, + }; + const struct domain_save_end e = {}; + unsigned int i; + int rc; + + ASSERT(d != current->domain); + domain_pause(d); + + c.name = !dry_run ? "HEADER" : NULL; + c.desc.typecode = DOMAIN_SAVE_CODE(HEADER); + + rc = DOMAIN_SAVE_ENTRY(HEADER, &c, 0, &h, sizeof(h)); + if ( rc ) + goto out; + + for ( i = 0; i < ARRAY_SIZE(handlers); i++ ) + { + domain_save_handler save = handlers[i].save; + + if ( !save ) + continue; + + c.name = !dry_run ? handlers[i].name : NULL; + memset(&c.desc, 0, sizeof(c.desc)); + c.desc.typecode = i; + + rc = save(d, &c, dry_run); + if ( rc ) + goto out; + } + + c.name = !dry_run ? "END" : NULL; + memset(&c.desc, 0, sizeof(c.desc)); + c.desc.typecode = DOMAIN_SAVE_CODE(END); + + rc = DOMAIN_SAVE_ENTRY(END, &c, 0, &e, sizeof(e)); + + out: + domain_unpause(d); + + return rc; +} + +int domain_load_begin(struct domain_context *c, unsigned int typecode, + unsigned int *instance) +{ + if ( typecode != c->desc.typecode ) + { + ASSERT_UNREACHABLE(); + return -EINVAL; + } + + ASSERT(!c->len); /* Verify domain_load_end() was called */ + + *instance = c->desc.instance; + + return 0; +} + +int domain_load_data(struct domain_context *c, void *dst, size_t len) +{ + size_t copy_len = min_t(size_t, len, c->desc.length - c->len); + int rc; + + c->len += copy_len; + ASSERT(c->len <= c->desc.length); + + rc = copy_len ? c->ops.load->read(c->priv, dst, copy_len) : 0; + if ( rc ) + return rc; + + /* Zero extend if the entry is exhausted */ + len -= copy_len; + if ( len ) + { + dst += copy_len; + memset(dst, 0, len); + } + + return 0; +} + +int domain_load_end(struct domain_context *c, bool ignore_data) +{ + struct domain *d = c->domain; + size_t len = c->desc.length - c->len; + + while ( c->len != c->desc.length ) /* unconsumed data or pad */ + { + uint8_t pad; + int rc = domain_load_data(c, &pad, sizeof(pad)); + + if ( rc ) + return rc; + + if ( !ignore_data && pad ) + return -EINVAL; + } + + ASSERT(c->name); + gdprintk(XENLOG_INFO, "%pd load: %s[%u] +%zu (-%zu)\n", d, c->name, + c->desc.instance, c->len, len); + + c->len = 0; + + return 0; +} + +int domain_load(struct domain *d, const struct domain_load_ops *ops, + void *priv) +{ + struct domain_context c = { + .domain = d, + .ops.load = ops, + .priv = priv, + }; + unsigned int instance; + struct domain_save_header h; + int rc; + + ASSERT(d != current->domain); + + rc = c.ops.load->read(c.priv, &c.desc, sizeof(c.desc)); + if ( rc ) + return rc; + + c.name = "HEADER"; + + rc = DOMAIN_LOAD_ENTRY(HEADER, &c, &instance, &h, sizeof(h)); + if ( rc ) + return rc; + + if ( instance || h.magic != DOMAIN_SAVE_MAGIC || + h.version != DOMAIN_SAVE_VERSION ) + return -EINVAL; + + domain_pause(d); + + for (;;) + { + unsigned int i; + domain_load_handler load; + + rc = c.ops.load->read(c.priv, &c.desc, sizeof(c.desc)); + if ( rc ) + return rc; + + rc = -EINVAL; + + if ( c.desc.typecode == DOMAIN_SAVE_CODE(END) ) + { + struct domain_save_end e; + + c.name = "END"; + + rc = DOMAIN_LOAD_ENTRY(END, &c, &instance, &e, sizeof(e)); + + if ( instance ) + return -EINVAL; + + break; + } + + i = c.desc.typecode; + if ( i >= ARRAY_SIZE(handlers) ) + break; + + c.name = handlers[i].name; + load = handlers[i].load; + + rc = load ? load(d, &c) : -EOPNOTSUPP; + if ( rc ) + break; + } + + domain_unpause(d); + + return rc; +} + +/* + * 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/public/arch-arm/hvm/save.h b/xen/include/public/arch-arm/hvm/save.h index 75b8e65bcb..d5b0c15203 100644 --- a/xen/include/public/arch-arm/hvm/save.h +++ b/xen/include/public/arch-arm/hvm/save.h @@ -26,6 +26,11 @@ #ifndef __XEN_PUBLIC_HVM_SAVE_ARM_H__ #define __XEN_PUBLIC_HVM_SAVE_ARM_H__ +/* + * Further use of HVM state is deprecated. New state records should only + * be added to the domain state header: public/save.h + */ + #endif /* diff --git a/xen/include/public/arch-x86/hvm/save.h b/xen/include/public/arch-x86/hvm/save.h index 773a380bc2..e61e2dbcd7 100644 --- a/xen/include/public/arch-x86/hvm/save.h +++ b/xen/include/public/arch-x86/hvm/save.h @@ -648,6 +648,11 @@ struct hvm_msr { */ #define HVM_SAVE_CODE_MAX 20 +/* + * Further use of HVM state is deprecated. New state records should only + * be added to the domain state header: public/save.h + */ + #endif /* __XEN_PUBLIC_HVM_SAVE_X86_H__ */ /* diff --git a/xen/include/public/save.h b/xen/include/public/save.h new file mode 100644 index 0000000000..551dbbddb8 --- /dev/null +++ b/xen/include/public/save.h @@ -0,0 +1,89 @@ +/* + * save.h + * + * Structure definitions for common PV/HVM domain state that is held by + * Xen and must be saved along with the domain's memory. + * + * Copyright Amazon.com Inc. or its affiliates. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef XEN_PUBLIC_SAVE_H +#define XEN_PUBLIC_SAVE_H + +#if defined(__XEN__) || defined(__XEN_TOOLS__) + +#include "xen.h" + +/* Entry data is preceded by a descriptor */ +struct domain_save_descriptor { + uint16_t typecode; + + /* + * Instance number of the entry (since there may be multiple of some + * types of entries). + */ + uint16_t instance; + + /* Entry length not including this descriptor */ + uint32_t length; +}; + +/* + * Each entry has a type associated with it. DECLARE_DOMAIN_SAVE_TYPE + * binds these things together, although it is not intended that the + * resulting type is ever instantiated. + */ +#define DECLARE_DOMAIN_SAVE_TYPE(_x, _code, _type) \ + struct DOMAIN_SAVE_TYPE_##_x { char c[_code]; _type t; }; + +#define DOMAIN_SAVE_CODE(_x) \ + (sizeof(((struct DOMAIN_SAVE_TYPE_##_x *)0)->c)) +#define DOMAIN_SAVE_TYPE(_x) \ + typeof(((struct DOMAIN_SAVE_TYPE_##_x *)0)->t) + +/* + * All entries will be zero-padded to the next 64-bit boundary when saved, + * so there is no need to include trailing pad fields in structure + * definitions. + * When loading, entries will be zero-extended if the load handler reads + * beyond the length specified in the descriptor. + */ + +/* Terminating entry */ +struct domain_save_end {}; +DECLARE_DOMAIN_SAVE_TYPE(END, 0, struct domain_save_end); + +#define DOMAIN_SAVE_MAGIC 0x53415645 +#define DOMAIN_SAVE_VERSION 0x00000001 + +/* Initial entry */ +struct domain_save_header { + uint32_t magic; /* Must be DOMAIN_SAVE_MAGIC */ + uint16_t xen_major, xen_minor; /* Xen version */ + uint32_t version; /* Save format version */ +}; +DECLARE_DOMAIN_SAVE_TYPE(HEADER, 1, struct domain_save_header); + +#define DOMAIN_SAVE_CODE_MAX 1 + +#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */ + +#endif /* XEN_PUBLIC_SAVE_H */ diff --git a/xen/include/xen/save.h b/xen/include/xen/save.h new file mode 100644 index 0000000000..e631a2e85e --- /dev/null +++ b/xen/include/xen/save.h @@ -0,0 +1,170 @@ +/* + * save.h: support routines for save/restore + * + * Copyright Amazon.com Inc. or its affiliates. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; If not, see . + */ + +#ifndef XEN_SAVE_H +#define XEN_SAVE_H + +#include +#include +#include + +#include + +struct domain_context; + +int domain_save_begin(struct domain_context *c, unsigned int typecode, + unsigned int instance); + +#define DOMAIN_SAVE_BEGIN(x, c, i) \ + domain_save_begin((c), DOMAIN_SAVE_CODE(x), (i)) + +int domain_save_data(struct domain_context *c, const void *data, size_t len); +int domain_save_end(struct domain_context *c); + +static inline int domain_save_entry(struct domain_context *c, + unsigned int typecode, + unsigned int instance, const void *src, + size_t len) +{ + int rc; + + rc = domain_save_begin(c, typecode, instance); + if ( rc ) + return rc; + + rc = domain_save_data(c, src, len); + if ( rc ) + return rc; + + return domain_save_end(c); +} + +#define DOMAIN_SAVE_ENTRY(x, c, i, s, l) \ + domain_save_entry((c), DOMAIN_SAVE_CODE(x), (i), (s), (l)) + +int domain_load_begin(struct domain_context *c, unsigned int typecode, + unsigned int *instance); + +#define DOMAIN_LOAD_BEGIN(x, c, i) \ + domain_load_begin((c), DOMAIN_SAVE_CODE(x), (i)) + +int domain_load_data(struct domain_context *c, void *data, size_t len); +int domain_load_end(struct domain_context *c, bool ignore_data); + +static inline int domain_load_entry(struct domain_context *c, + unsigned int typecode, + unsigned int *instance, void *dst, + size_t len) +{ + int rc; + + rc = domain_load_begin(c, typecode, instance); + if ( rc ) + return rc; + + rc = domain_load_data(c, dst, len); + if ( rc ) + return rc; + + return domain_load_end(c, false); +} + +#define DOMAIN_LOAD_ENTRY(x, c, i, d, l) \ + domain_load_entry((c), DOMAIN_SAVE_CODE(x), (i), (d), (l)) + +/* + * The 'dry_run' flag indicates that the caller of domain_save() (see below) + * is not trying to actually acquire the data, only the size of the data. + * The save handler can therefore limit work to only that which is necessary + * to call domain_save_data() the correct number of times with accurate values + * for 'len'. + */ +typedef int (*domain_save_handler)(const struct domain *d, + struct domain_context *c, + bool dry_run); +typedef int (*domain_load_handler)(struct domain *d, + struct domain_context *c); + +void domain_register_save_type(unsigned int typecode, const char *name, + domain_save_handler save, + domain_load_handler load); + +/* + * Register save and load handlers. + * + * Save handlers will be invoked in an order which copes with any inter- + * entry dependencies. For now this means that HEADER will come first and + * END will come last, all others being invoked in order of 'typecode'. + * + * Load handlers will be invoked in the order of entries present in the + * buffer. + */ +#define DOMAIN_REGISTER_SAVE_LOAD(x, s, l) \ + static int __init __domain_register_##x##_save_load(void) \ + { \ + domain_register_save_type( \ + DOMAIN_SAVE_CODE(x), \ + #x, \ + &(s), \ + &(l)); \ + \ + return 0; \ + } \ + __initcall(__domain_register_##x##_save_load); + +/* Callback functions */ +struct domain_save_ops { + /* + * Begin a new entry with the given descriptor (only type and instance + * are valid). + */ + int (*begin)(void *priv, const struct domain_save_descriptor *desc); + /* Append data/padding to the buffer */ + int (*append)(void *priv, const void *data, size_t len); + /* + * Complete the entry by updating the descriptor with the total + * length of the appended data (not including padding). + */ + int (*end)(void *priv, size_t len); +}; + +struct domain_load_ops { + /* Read data/padding from the buffer */ + int (*read)(void *priv, void *data, size_t len); +}; + +/* + * Entry points: + * + * ops: These are callback functions provided by the caller that will + * be used to write to (in the save case) or read from (in the + * load case) the context buffer. See above for more detail. + * priv: This is a pointer that will be passed to the copy function to + * allow it to identify the context buffer and the current state + * of the save or load operation. + * dry_run: If this is set then the caller of domain_save() is only trying + * to acquire the total size of the data, not the data itself. + * In this case the caller may supply different ops to avoid doing + * unnecessary work. + */ +int domain_save(struct domain *d, const struct domain_save_ops *ops, + void *priv, bool dry_run); +int domain_load(struct domain *d, const struct domain_load_ops *ops, + void *priv); + +#endif /* XEN_SAVE_H */ From patchwork Tue Aug 18 10:30:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11720495 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 62DF5739 for ; Tue, 18 Aug 2020 10:31:59 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 308032075E for ; Tue, 18 Aug 2020 10:31:59 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=xen.org header.i=@xen.org header.b="x9IME32n" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 308032075E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=xen.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7ytA-00062e-A9; Tue, 18 Aug 2020 10:30:44 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7yt8-0005zI-Fg for xen-devel@lists.xenproject.org; Tue, 18 Aug 2020 10:30:42 +0000 X-Inumbo-ID: 0bfb8583-ec99-49a6-a80d-637296711666 Received: from mail.xenproject.org (unknown [104.130.215.37]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 0bfb8583-ec99-49a6-a80d-637296711666; Tue, 18 Aug 2020 10:30:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=xen.org; s=20200302mail; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=L8u/9CW9fkccZkkc3rhepPxEsG8WeWzyLfcHNbGO+Mk=; b=x9IME32n4s7MQJ/NLFAiPk6SGe O66InovFt1HBKyAuDvYYXnu74Df7JKO6BcWB+0mBu/IyyzwXRLymBgdbWZXHVlMTsbUAphB3+Pp+J xoCZUAo7BAQQjbrC6ssV+gcG79sHNvWr53xbA4RDiCjxkjbKEazHW7wc8Ln8uxl7IGno=; Received: from xenbits.xenproject.org ([104.239.192.120]) by mail.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7yt4-00013W-8F; Tue, 18 Aug 2020 10:30:38 +0000 Received: from host31-48-92-96.range31-48.btcentralplus.com ([31.48.92.96] helo=u2f063a87eabd5f.home) by xenbits.xenproject.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1k7yt4-0003Rw-0W; Tue, 18 Aug 2020 10:30:38 +0000 From: Paul Durrant To: xen-devel@lists.xenproject.org Cc: Paul Durrant , Julien Grall , Daniel De Graaf , Ian Jackson , Wei Liu , Andrew Cooper , George Dunlap , Jan Beulich , Stefano Stabellini Subject: [PATCH v7 2/9] xen/common/domctl: introduce XEN_DOMCTL_get/setdomaincontext Date: Tue, 18 Aug 2020 11:30:25 +0100 Message-Id: <20200818103032.3050-3-paul@xen.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200818103032.3050-1-paul@xen.org> References: <20200818103032.3050-1-paul@xen.org> MIME-Version: 1.0 X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" These domctls provide a mechanism to get and set domain context from the toolstack. Signed-off-by: Paul Durrant Reviewed-by: Julien Grall --- Cc: Daniel De Graaf Cc: Ian Jackson Cc: Wei Liu Cc: Andrew Cooper Cc: George Dunlap Cc: Jan Beulich Cc: Stefano Stabellini v4: - Add missing zero pad checks v3: - Addressed comments from Julien and Jan - Use vmalloc() rather than xmalloc_bytes() v2: - drop mask parameter - const-ify some more buffers --- tools/flask/policy/modules/xen.if | 4 +- tools/libxc/include/xenctrl.h | 5 + tools/libxc/xc_domain.c | 56 +++++++++ xen/common/domctl.c | 173 ++++++++++++++++++++++++++++ xen/include/public/domctl.h | 41 +++++++ xen/xsm/flask/hooks.c | 6 + xen/xsm/flask/policy/access_vectors | 4 + 7 files changed, 287 insertions(+), 2 deletions(-) diff --git a/tools/flask/policy/modules/xen.if b/tools/flask/policy/modules/xen.if index 8eb2293a52..2bc9db4f64 100644 --- a/tools/flask/policy/modules/xen.if +++ b/tools/flask/policy/modules/xen.if @@ -53,7 +53,7 @@ define(`create_domain_common', ` allow $1 $2:domain2 { set_cpu_policy settsc setscheduler setclaim set_vnumainfo get_vnumainfo cacheflush psr_cmt_op psr_alloc soft_reset - resource_map get_cpu_policy }; + resource_map get_cpu_policy setcontext }; allow $1 $2:security check_context; allow $1 $2:shadow enable; allow $1 $2:mmu { map_read map_write adjust memorymap physmap pinpage mmuext_op updatemp }; @@ -97,7 +97,7 @@ define(`migrate_domain_out', ` allow $1 $2:hvm { gethvmc getparam }; allow $1 $2:mmu { stat pageinfo map_read }; allow $1 $2:domain { getaddrsize getvcpucontext pause destroy }; - allow $1 $2:domain2 gettsc; + allow $1 $2:domain2 { gettsc getcontext }; allow $1 $2:shadow { enable disable logdirty }; ') diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index 4c89b7294c..5eb04dcb38 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -867,6 +867,11 @@ int xc_domain_hvm_setcontext(xc_interface *xch, uint8_t *hvm_ctxt, uint32_t size); +int xc_domain_getcontext(xc_interface *xch, uint32_t domid, + void *ctxt_buf, size_t *size); +int xc_domain_setcontext(xc_interface *xch, uint32_t domid, + const void *ctxt_buf, size_t size); + /** * This function will return guest IO ABI protocol * diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index 71829c2bce..e462a6f728 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -537,6 +537,62 @@ int xc_domain_hvm_setcontext(xc_interface *xch, return ret; } +int xc_domain_getcontext(xc_interface *xch, uint32_t domid, + void *ctxt_buf, size_t *size) +{ + int ret; + DECLARE_DOMCTL = { + .cmd = XEN_DOMCTL_getdomaincontext, + .domain = domid, + .u.getdomaincontext.size = *size, + }; + DECLARE_HYPERCALL_BOUNCE(ctxt_buf, *size, XC_HYPERCALL_BUFFER_BOUNCE_OUT); + + if ( xc_hypercall_bounce_pre(xch, ctxt_buf) ) + return -1; + + set_xen_guest_handle(domctl.u.setdomaincontext.buffer, ctxt_buf); + + ret = do_domctl(xch, &domctl); + + xc_hypercall_bounce_post(xch, ctxt_buf); + + if ( ret ) + return ret; + + *size = domctl.u.getdomaincontext.size; + if ( *size != domctl.u.getdomaincontext.size ) + { + errno = EOVERFLOW; + return -1; + } + + return 0; +} + +int xc_domain_setcontext(xc_interface *xch, uint32_t domid, + const void *ctxt_buf, size_t size) +{ + int ret; + DECLARE_DOMCTL = { + .cmd = XEN_DOMCTL_setdomaincontext, + .domain = domid, + .u.setdomaincontext.size = size, + }; + DECLARE_HYPERCALL_BOUNCE_IN(ctxt_buf, size); + + if ( xc_hypercall_bounce_pre(xch, ctxt_buf) ) + return -1; + + set_xen_guest_handle(domctl.u.setdomaincontext.buffer, ctxt_buf); + + ret = do_domctl(xch, &domctl); + + xc_hypercall_bounce_post(xch, ctxt_buf); + + return ret; +} + int xc_vcpu_getcontext(xc_interface *xch, uint32_t domid, uint32_t vcpu, diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 20ef8399bd..a795156e8f 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -358,6 +360,168 @@ static struct vnuma_info *vnuma_init(const struct xen_domctl_vnuma *uinfo, return ERR_PTR(ret); } +struct domctl_context +{ + void *buffer; + struct domain_save_descriptor *desc; + size_t len; + size_t cur; +}; + +static int dry_run_append(void *priv, const void *data, size_t len) +{ + struct domctl_context *c = priv; + + if ( c->len + len < c->len ) + return -EOVERFLOW; + + c->len += len; + + return 0; +} + +static int dry_run_begin(void *priv, const struct domain_save_descriptor *desc) +{ + return dry_run_append(priv, NULL, sizeof(*desc)); +} + +static int dry_run_end(void *priv, size_t len) +{ + return 0; +} + +static struct domain_save_ops dry_run_ops = { + .begin = dry_run_begin, + .append = dry_run_append, + .end = dry_run_end, +}; + +static int save_begin(void *priv, const struct domain_save_descriptor *desc) +{ + struct domctl_context *c = priv; + + if ( c->len - c->cur < sizeof(*desc) ) + return -ENOSPC; + + c->desc = c->buffer + c->cur; /* stash pointer to descriptor */ + *c->desc = *desc; + + c->cur += sizeof(*desc); + + return 0; +} + +static int save_append(void *priv, const void *data, size_t len) +{ + struct domctl_context *c = priv; + + if ( c->len - c->cur < len ) + return -ENOSPC; + + memcpy(c->buffer + c->cur, data, len); + c->cur += len; + + return 0; +} + +static int save_end(void *priv, size_t len) +{ + struct domctl_context *c = priv; + + c->desc->length = len; + + return 0; +} + +static struct domain_save_ops save_ops = { + .begin = save_begin, + .append = save_append, + .end = save_end, +}; + +static int getdomaincontext(struct domain *d, + struct xen_domctl_getdomaincontext *gdc) +{ + struct domctl_context c = { .buffer = ZERO_BLOCK_PTR }; + int rc; + + if ( d == current->domain ) + return -EPERM; + + if ( gdc->pad ) + return -EINVAL; + + if ( guest_handle_is_null(gdc->buffer) ) /* query for buffer size */ + { + if ( gdc->size ) + return -EINVAL; + + /* dry run to acquire buffer size */ + rc = domain_save(d, &dry_run_ops, &c, true); + if ( rc ) + return rc; + + gdc->size = c.len; + return 0; + } + + c.len = gdc->size; + c.buffer = vmalloc(c.len); + if ( !c.buffer ) + return -ENOMEM; + + rc = domain_save(d, &save_ops, &c, false); + + gdc->size = c.cur; + if ( !rc && copy_to_guest(gdc->buffer, c.buffer, gdc->size) ) + rc = -EFAULT; + + vfree(c.buffer); + + return rc; +} + +static int load_read(void *priv, void *data, size_t len) +{ + struct domctl_context *c = priv; + + if ( c->len - c->cur < len ) + return -ENODATA; + + memcpy(data, c->buffer + c->cur, len); + c->cur += len; + + return 0; +} + +static struct domain_load_ops load_ops = { + .read = load_read, +}; + +static int setdomaincontext(struct domain *d, + const struct xen_domctl_setdomaincontext *sdc) +{ + struct domctl_context c = { .buffer = ZERO_BLOCK_PTR, .len = sdc->size }; + int rc; + + if ( d == current->domain ) + return -EPERM; + + if ( sdc->pad ) + return -EINVAL; + + c.buffer = vmalloc(c.len); + if ( !c.buffer ) + return -ENOMEM; + + rc = !copy_from_guest(c.buffer, sdc->buffer, c.len) ? + domain_load(d, &load_ops, &c) : -EFAULT; + + vfree(c.buffer); + + return rc; +} + long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) { long ret = 0; @@ -942,6 +1106,15 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) copyback = 1; break; + case XEN_DOMCTL_getdomaincontext: + ret = getdomaincontext(d, &op->u.getdomaincontext); + copyback = !ret; + break; + + case XEN_DOMCTL_setdomaincontext: + ret = setdomaincontext(d, &op->u.setdomaincontext); + break; + default: ret = arch_do_domctl(op, d, u_domctl); break; diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 9464a9058a..a889719323 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -1135,6 +1135,43 @@ struct xen_domctl_vuart_op { */ }; +/* + * XEN_DOMCTL_getdomaincontext + * --------------------------- + * + * buffer (IN): The buffer into which the context data should be + * copied, or NULL to query the buffer size that should + * be allocated. + * size (IN/OUT): If 'buffer' is NULL then the value passed in must be + * zero, and the value passed out will be the size of the + * buffer to allocate. + * If 'buffer' is non-NULL then the value passed in must + * be the size of the buffer into which data may be copied. + * The value passed out will be the size of data written. + */ +struct xen_domctl_getdomaincontext { + uint32_t size; + uint32_t pad; + XEN_GUEST_HANDLE_64(void) buffer; +}; + +/* XEN_DOMCTL_setdomaincontext + * --------------------------- + * + * buffer (IN): The buffer from which the context data should be + * copied. + * size (IN): The size of the buffer from which data may be copied. + * This data must include DOMAIN_SAVE_CODE_HEADER at the + * start and terminate with a DOMAIN_SAVE_CODE_END record. + * Any data beyond the DOMAIN_SAVE_CODE_END record will be + * ignored. + */ +struct xen_domctl_setdomaincontext { + uint32_t size; + uint32_t pad; + XEN_GUEST_HANDLE_64(const_void) buffer; +}; + struct xen_domctl { uint32_t cmd; #define XEN_DOMCTL_createdomain 1 @@ -1216,6 +1253,8 @@ struct xen_domctl { #define XEN_DOMCTL_vuart_op 81 #define XEN_DOMCTL_get_cpu_policy 82 #define XEN_DOMCTL_set_cpu_policy 83 +#define XEN_DOMCTL_getdomaincontext 84 +#define XEN_DOMCTL_setdomaincontext 85 #define XEN_DOMCTL_gdbsx_guestmemio 1000 #define XEN_DOMCTL_gdbsx_pausevcpu 1001 #define XEN_DOMCTL_gdbsx_unpausevcpu 1002 @@ -1277,6 +1316,8 @@ struct xen_domctl { struct xen_domctl_monitor_op monitor_op; struct xen_domctl_psr_alloc psr_alloc; struct xen_domctl_vuart_op vuart_op; + struct xen_domctl_getdomaincontext getdomaincontext; + struct xen_domctl_setdomaincontext setdomaincontext; uint8_t pad[128]; } u; }; diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index a314bf85ce..4cbf787b1f 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -745,6 +745,12 @@ static int flask_domctl(struct domain *d, int cmd) case XEN_DOMCTL_get_cpu_policy: return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__GET_CPU_POLICY); + case XEN_DOMCTL_setdomaincontext: + return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__SETCONTEXT); + + case XEN_DOMCTL_getdomaincontext: + return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__GETCONTEXT); + default: return avc_unknown_permission("domctl", cmd); } diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors index b87c99ea98..54a2759886 100644 --- a/xen/xsm/flask/policy/access_vectors +++ b/xen/xsm/flask/policy/access_vectors @@ -245,6 +245,10 @@ class domain2 resource_map # XEN_DOMCTL_get_cpu_policy get_cpu_policy +# XEN_DOMCTL_setdomaincontext + setcontext +# XEN_DOMCTL_getdomaincontext + getcontext } # Similar to class domain, but primarily contains domctls related to HVM domains From patchwork Tue Aug 18 10:30:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11720493 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7AAD6138C for ; Tue, 18 Aug 2020 10:31:58 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 571362075E for ; Tue, 18 Aug 2020 10:31:58 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=xen.org header.i=@xen.org header.b="5vTI/zq4" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 571362075E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=xen.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7yt8-00061N-S8; Tue, 18 Aug 2020 10:30:42 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7yt7-0005zo-A8 for xen-devel@lists.xenproject.org; Tue, 18 Aug 2020 10:30:41 +0000 X-Inumbo-ID: 32d6f7b2-af59-451d-b2b4-cf93ea382235 Received: from mail.xenproject.org (unknown [104.130.215.37]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 32d6f7b2-af59-451d-b2b4-cf93ea382235; Tue, 18 Aug 2020 10:30:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=xen.org; s=20200302mail; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=m3L0Qwt75VQeY/gR+JcBF0R6pPuj2jl9noLoJU874z0=; b=5vTI/zq4NveV7yvK7ihnFTm+bx vvSiBcRL4GRFuruDloOi9F13/jjrV4ZKpNslyrTVyK2PD7CwnSy71MnOB/8v8buYMJD4ndiBGVKAk kXV/pXkd4A6qSsCsK3MykkiWaE1SJi2u+1Xj10fqblRi18XwCLXooYky8fMFvSMBWIr0=; Received: from xenbits.xenproject.org ([104.239.192.120]) by mail.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7yt5-00013Z-8H; Tue, 18 Aug 2020 10:30:39 +0000 Received: from host31-48-92-96.range31-48.btcentralplus.com ([31.48.92.96] helo=u2f063a87eabd5f.home) by xenbits.xenproject.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1k7yt5-0003Rw-0g; Tue, 18 Aug 2020 10:30:39 +0000 From: Paul Durrant To: xen-devel@lists.xenproject.org Cc: Paul Durrant , Ian Jackson , Andrew Cooper , Wei Liu Subject: [PATCH v7 3/9] tools/misc: add xen-domctx to present domain context Date: Tue, 18 Aug 2020 11:30:26 +0100 Message-Id: <20200818103032.3050-4-paul@xen.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200818103032.3050-1-paul@xen.org> References: <20200818103032.3050-1-paul@xen.org> MIME-Version: 1.0 X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" This tool is analogous to 'xen-hvmctx' which presents HVM context. Subsequent patches will add 'dump' functions when new records are introduced. Signed-off-by: Paul Durrant Acked-by: Ian Jackson --- Cc: Andrew Cooper Cc: Wei Liu NOTE: Ian requested ack from Andrew v3: - Re-worked to avoid copying onto stack - Added optional typecode and instance arguments v2: - Change name from 'xen-ctx' to 'xen-domctx' --- .gitignore | 1 + tools/misc/Makefile | 4 + tools/misc/xen-domctx.c | 200 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 tools/misc/xen-domctx.c diff --git a/.gitignore b/.gitignore index 36ce2ea104..7e5dccacce 100644 --- a/.gitignore +++ b/.gitignore @@ -211,6 +211,7 @@ tools/misc/xen_cpuperf tools/misc/xen-cpuid tools/misc/xen-detect tools/misc/xen-diag +tools/misc/xen-domctx tools/misc/xen-tmem-list-parse tools/misc/xen-livepatch tools/misc/xenperf diff --git a/tools/misc/Makefile b/tools/misc/Makefile index 9fdb13597f..13e37402e2 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -31,6 +31,7 @@ INSTALL_SBIN += xenpm INSTALL_SBIN += xenwatchdogd INSTALL_SBIN += xen-livepatch INSTALL_SBIN += xen-diag +INSTALL_SBIN += xen-domctx INSTALL_SBIN += $(INSTALL_SBIN-y) # Everything to be installed in a private bin/ @@ -114,6 +115,9 @@ xen-livepatch: xen-livepatch.o xen-diag: xen-diag.o $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS) +xen-domctx: xen-domctx.o + $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS) + xen-lowmemd: xen-lowmemd.o $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS) diff --git a/tools/misc/xen-domctx.c b/tools/misc/xen-domctx.c new file mode 100644 index 0000000000..243325dfce --- /dev/null +++ b/tools/misc/xen-domctx.c @@ -0,0 +1,200 @@ +/* + * xen-domctx.c + * + * Print out domain save records in a human-readable way. + * + * Copyright Amazon.com Inc. or its affiliates. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static void *buf = NULL; +static size_t len, off; + +#define GET_PTR(_x) \ + do { \ + if ( len - off < sizeof(*(_x)) ) \ + { \ + fprintf(stderr, \ + "error: need another %lu bytes, only %lu available\n", \ + sizeof(*(_x)), len - off); \ + exit(1); \ + } \ + (_x) = buf + off; \ + } while (false); + +static void dump_header(void) +{ + DOMAIN_SAVE_TYPE(HEADER) *h; + + GET_PTR(h); + + printf(" HEADER: magic %#x, version %u\n", + h->magic, h->version); + +} + +static void dump_end(void) +{ + DOMAIN_SAVE_TYPE(END) *e; + + GET_PTR(e); + + printf(" END\n"); +} + +static void usage(const char *prog) +{ + fprintf(stderr, "usage: %s [ [ ]]\n", + prog); + exit(1); +} + +int main(int argc, char **argv) +{ + char *s, *e; + long domid; + long typecode = -1; + long instance = -1; + unsigned int entry; + xc_interface *xch; + int rc; + + if ( argc < 2 || argc > 4 ) + usage(argv[0]); + + s = e = argv[1]; + domid = strtol(s, &e, 0); + + if ( *s == '\0' || *e != '\0' || + domid < 0 || domid >= DOMID_FIRST_RESERVED ) + { + fprintf(stderr, "invalid domid '%s'\n", s); + exit(1); + } + + if ( argc >= 3 ) + { + s = e = argv[2]; + typecode = strtol(s, &e, 0); + + if ( *s == '\0' || *e != '\0' ) + { + fprintf(stderr, "invalid typecode '%s'\n", s); + exit(1); + } + } + + if ( argc == 4 ) + { + s = e = argv[3]; + instance = strtol(s, &e, 0); + + if ( *s == '\0' || *e != '\0' ) + { + fprintf(stderr, "invalid instance '%s'\n", s); + exit(1); + } + } + + xch = xc_interface_open(0, 0, 0); + if ( !xch ) + { + fprintf(stderr, "error: can't open libxc handle\n"); + exit(1); + } + + rc = xc_domain_getcontext(xch, domid, NULL, &len); + if ( rc < 0 ) + { + fprintf(stderr, "error: can't get record length for dom %lu: %s\n", + domid, strerror(errno)); + exit(1); + } + + buf = malloc(len); + if ( !buf ) + { + fprintf(stderr, "error: can't allocate %lu bytes\n", len); + exit(1); + } + + rc = xc_domain_getcontext(xch, domid, buf, &len); + if ( rc < 0 ) + { + fprintf(stderr, "error: can't get domain record for dom %lu: %s\n", + domid, strerror(errno)); + exit(1); + } + off = 0; + + entry = 0; + for ( ; ; ) + { + struct domain_save_descriptor *desc; + + GET_PTR(desc); + + off += sizeof(*desc); + + if ( (typecode < 0 || typecode == desc->typecode) && + (instance < 0 || instance == desc->instance) ) + { + printf("[%u] type: %u instance: %u length: %u\n", entry++, + desc->typecode, desc->instance, desc->length); + + switch (desc->typecode) + { + case DOMAIN_SAVE_CODE(HEADER): dump_header(); break; + case DOMAIN_SAVE_CODE(END): dump_end(); break; + default: + printf("Unknown type %u: skipping\n", desc->typecode); + break; + } + } + + if ( desc->typecode == DOMAIN_SAVE_CODE(END) ) + break; + + off += desc->length; + } + + return 0; +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ From patchwork Tue Aug 18 10:30:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11720487 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C3973138C for ; Tue, 18 Aug 2020 10:31:09 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9FE022075E for ; Tue, 18 Aug 2020 10:31:09 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=xen.org header.i=@xen.org header.b="38xHLYP4" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9FE022075E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=xen.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7ytE-00065T-Tc; Tue, 18 Aug 2020 10:30:48 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7ytD-0005zI-Fv for xen-devel@lists.xenproject.org; Tue, 18 Aug 2020 10:30:47 +0000 X-Inumbo-ID: 9c319070-5a32-4881-ad6b-0ca37fb04855 Received: from mail.xenproject.org (unknown [104.130.215.37]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 9c319070-5a32-4881-ad6b-0ca37fb04855; Tue, 18 Aug 2020 10:30:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=xen.org; s=20200302mail; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=Q48nB/F4uU8xPjTIE8qhVPPBlboQ5C2A8+ikvUg0FYs=; b=38xHLYP4EgnuuyRVwsdfJGaudc jUx1E4+GfNq9ma2ubdK7PhwL6ldSe4Umw6AY6qFquyWcNgHRY2c6GXnN0X00CVYNSLXvfmVNz/eag csYkoO1ITnaHyubSiTJ5m+JTBSy+CJ+OVmsq/0p4j1HiNEpNcjFu8bVBza9sXDJslZso=; Received: from xenbits.xenproject.org ([104.239.192.120]) by mail.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7yt6-00013i-Mc; Tue, 18 Aug 2020 10:30:40 +0000 Received: from host31-48-92-96.range31-48.btcentralplus.com ([31.48.92.96] helo=u2f063a87eabd5f.home) by xenbits.xenproject.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1k7yt6-0003Rw-Db; Tue, 18 Aug 2020 10:30:40 +0000 From: Paul Durrant To: xen-devel@lists.xenproject.org Cc: Paul Durrant , Andrew Cooper , George Dunlap , Ian Jackson , Jan Beulich , Julien Grall , Stefano Stabellini , Wei Liu Subject: [PATCH v7 4/9] docs/specs: add missing definitions to libxc-migration-stream Date: Tue, 18 Aug 2020 11:30:27 +0100 Message-Id: <20200818103032.3050-5-paul@xen.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200818103032.3050-1-paul@xen.org> References: <20200818103032.3050-1-paul@xen.org> MIME-Version: 1.0 X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" From: Paul Durrant The STATIC_DATA_END, X86_CPUID_POLICY and X86_MSR_POLICY record types have sections explaining what they are but their values are not defined. Indeed their values are defined as "Reserved for future mandatory records." Also, the spec revision is adjusted to match the migration stream version and an END record is added to the description of a 'typical save record for and x86 HVM guest.' Signed-off-by: Paul Durrant Fixes: 6f71b5b1506 ("docs/migration Specify migration v3 and STATIC_DATA_END") Fixes: ddd273d8863 ("docs/migration: Specify X86_{CPUID,MSR}_POLICY records") --- Cc: Andrew Cooper Cc: George Dunlap Cc: Ian Jackson Cc: Jan Beulich Cc: Julien Grall Cc: Stefano Stabellini Cc: Wei Liu v7: - New in v7 --- docs/specs/libxc-migration-stream.pandoc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/specs/libxc-migration-stream.pandoc b/docs/specs/libxc-migration-stream.pandoc index 6b0c49e97a..8aeab3b11b 100644 --- a/docs/specs/libxc-migration-stream.pandoc +++ b/docs/specs/libxc-migration-stream.pandoc @@ -3,7 +3,7 @@ Andrew Cooper <> Wen Congyang <> Yang Hongyang <> -% Revision 2 +% Revision 3 Introduction ============ @@ -227,7 +227,13 @@ type 0x00000000: END 0x0000000F: CHECKPOINT_DIRTY_PFN_LIST (Secondary -> Primary) - 0x00000010 - 0x7FFFFFFF: Reserved for future _mandatory_ + 0x00000010: STATIC_DATA_END + + 0x00000011: X86_CPUID_POLICY + + 0x00000012: X86_MSR_POLICY + + 0x00000013 - 0x7FFFFFFF: Reserved for future _mandatory_ records. 0x80000000 - 0xFFFFFFFF: Reserved for future _optional_ @@ -732,6 +738,7 @@ A typical save record for an x86 HVM guest image would look like: * X86_TSC_INFO * HVM_PARAMS * HVM_CONTEXT +* END record HVM_PARAMS must precede HVM_CONTEXT, as certain parameters can affect the validity of architectural state in the context. From patchwork Tue Aug 18 10:30:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11720501 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7FA72739 for ; Tue, 18 Aug 2020 10:32:21 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5C7962075E for ; Tue, 18 Aug 2020 10:32:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=xen.org header.i=@xen.org header.b="b9ztcpIR" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5C7962075E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=xen.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7ytC-000641-Jo; Tue, 18 Aug 2020 10:30:46 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7ytA-0005zo-Mg for xen-devel@lists.xenproject.org; Tue, 18 Aug 2020 10:30:44 +0000 X-Inumbo-ID: 1c9f4782-60a5-4efc-b338-db07017089b0 Received: from mail.xenproject.org (unknown [104.130.215.37]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 1c9f4782-60a5-4efc-b338-db07017089b0; Tue, 18 Aug 2020 10:30:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=xen.org; s=20200302mail; h=Content-Transfer-Encoding:Content-Type:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=9B06LaTam4r9aPcamK/16qRY4ae2xUL3Egxlq2b/Qp0=; b=b9ztcpIRqul/ks1IMiOzPToZk9 XP0WXOO8P4p9UykXTvxiZwybYQVzm3cc1LAqNCucDliKVYESZtfPW3s1IGDgCzY2ruHc5zjXNeNzb iKU+CVhYfAZgopEG5BWyRqU0iF8nPoZNASPzglopOexHX80D7rnzoqPMLhj3pe7DzcJc=; Received: from xenbits.xenproject.org ([104.239.192.120]) by mail.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7yt8-00013x-5F; Tue, 18 Aug 2020 10:30:42 +0000 Received: from host31-48-92-96.range31-48.btcentralplus.com ([31.48.92.96] helo=u2f063a87eabd5f.home) by xenbits.xenproject.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1k7yt7-0003Rw-Tr; Tue, 18 Aug 2020 10:30:42 +0000 From: Paul Durrant To: xen-devel@lists.xenproject.org Cc: Paul Durrant , Andrew Cooper , George Dunlap , Ian Jackson , Jan Beulich , Julien Grall , Stefano Stabellini , Wei Liu , =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= Subject: [PATCH v7 5/9] docs / tools: specific migration v4 to include DOMAIN_CONTEXT Date: Tue, 18 Aug 2020 11:30:28 +0100 Message-Id: <20200818103032.3050-6-paul@xen.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200818103032.3050-1-paul@xen.org> References: <20200818103032.3050-1-paul@xen.org> MIME-Version: 1.0 X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" From: Paul Durrant A new 'domain context' framework was recently introduced to facilitate transfer of state for both PV and HVM guests. Hence this patch mandates the presence of a new DOMAIN_CONTEXT record in version 4 of the libxc migration stream. This record will incorprate the content of the domain's 'shared_info' page and the TSC informaiton so the SHARED_INFO and TSC_INFO records are deprecated. It is intended that, in future, this record will contain state currently present in the HVM_CONTEXT record. However, for compatibility with earlier migration streams, the version 4 stream format continues to specify an HVM_CONTEXT record and XEN_DOMCTL_sethvmcontext will continue to accept all content of that record that may be present in a version 3 stream. Signed-off-by: Paul Durrant --- Cc: Andrew Cooper Cc: George Dunlap Cc: Ian Jackson Cc: Jan Beulich Cc: Julien Grall Cc: Stefano Stabellini Cc: Wei Liu Cc: "Marek Marczykowski-Górecki" v7: - New in v7 --- docs/specs/libxc-migration-stream.pandoc | 62 ++++++++++++++++++------ tools/libxc/xc_sr_common.c | 1 + tools/libxc/xc_sr_stream_format.h | 1 + tools/python/xen/migration/libxc.py | 2 + 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/docs/specs/libxc-migration-stream.pandoc b/docs/specs/libxc-migration-stream.pandoc index 8aeab3b11b..989f2a0cb6 100644 --- a/docs/specs/libxc-migration-stream.pandoc +++ b/docs/specs/libxc-migration-stream.pandoc @@ -3,7 +3,7 @@ Andrew Cooper <> Wen Congyang <> Yang Hongyang <> -% Revision 3 +% Revision 4 Introduction ============ @@ -127,7 +127,7 @@ marker 0xFFFFFFFFFFFFFFFF. id 0x58454E46 ("XENF" in ASCII). -version 0x00000003. The version of this specification. +version 0x00000004. The version of this specification. options bit 0: Endianness. 0 = little-endian, 1 = big-endian. @@ -209,9 +209,9 @@ type 0x00000000: END 0x00000006: X86_PV_VCPU_XSAVE - 0x00000007: SHARED_INFO + 0x00000007: SHARED_INFO (deprecated) - 0x00000008: X86_TSC_INFO + 0x00000008: X86_TSC_INFO (deprecated) 0x00000009: HVM_CONTEXT @@ -233,7 +233,9 @@ type 0x00000000: END 0x00000012: X86_MSR_POLICY - 0x00000013 - 0x7FFFFFFF: Reserved for future _mandatory_ + 0x00000013: DOMAIN_CONTEXT + + 0x00000014 - 0x7FFFFFFF: Reserved for future _mandatory_ records. 0x80000000 - 0xFFFFFFFF: Reserved for future _optional_ @@ -442,10 +444,11 @@ X86_PV_VCPU_MSRS XEN_DOMCTL_{get,set}\_vcpu_msrs \clearpage -SHARED_INFO ------------ +SHARED_INFO (deprecated) +------------------------ -The content of the Shared Info page. +The content of the Shared Info page. This is incorporated into the +DOMAIN_CONTEXT record as of specification version 4. 0 1 2 3 4 5 6 7 octet +-------------------------------------------------+ @@ -462,11 +465,12 @@ shared_info Contents of the shared info page. This record \clearpage -X86_TSC_INFO ------------- +X86_TSC_INFO (deprecated) +------------------------- Domain TSC information, as accessed by the -XEN_DOMCTL_{get,set}tscinfo hypercall sub-ops. +XEN_DOMCTL_{get,set}tscinfo hypercall sub-ops. This is incorporated into the +DOMAIN_CONTEXT record as of specification version 4. 0 1 2 3 4 5 6 7 octet +------------------------+------------------------+ @@ -680,6 +684,25 @@ MSR_policy Array of xen_msr_entry_t[]'s \clearpage +DOMAIN_CONTEXT +-------------- + +Domain context, as accessed by the +XEN_DOMCTL_{get,set}domaincontext hypercall sub-ops. + + 0 1 2 3 4 5 6 7 octet + +-------------------------------------------------+ + | dom_ctx | + ... + +-------------------------------------------------+ + +-------------------------------------------------------------------- +Field Description +----------- --------------------------------------------------- +dom_ctx The Domain Context blob from Xen. +-------------------------------------------------------------------- + +\clearpage Layout ====== @@ -706,8 +729,7 @@ A typical save record for an x86 PV guest image would look like: * STATIC_DATA_END * X86_PV_P2M_FRAMES record * Many PAGE_DATA records -* X86_TSC_INFO -* SHARED_INFO record +* DOMAIN_CONTEXT * VCPU context records for each online VCPU * X86_PV_VCPU_BASIC record * X86_PV_VCPU_EXTENDED record @@ -735,7 +757,7 @@ A typical save record for an x86 HVM guest image would look like: * X86_{CPUID,MSR}_POLICY * STATIC_DATA_END * Many PAGE_DATA records -* X86_TSC_INFO +* DOMAIN_CONTEXT * HVM_PARAMS * HVM_CONTEXT * END record @@ -746,6 +768,18 @@ the validity of architectural state in the context. Compatibility with older versions ================================= +v4 compat with v3 +----------------- + +A v4 stream is compatible with a v3 stream, but mandates the presence of a +DOMAIN_CONTEXT record. This incorporates context such as the content of +the domain's Shared Info page and the TSC information, hence the SHARED_INFO +and TSC_INFO records are deprecated. +It also supercedes HVM_CONTEXT and, over time, data that is currently part of +the HVM_CONTEXT blob will move to the DOMAIN_CONTEXT blob. Xen, however, will +continue to accept all defined HVM_CONTEXT records so a v4-compatible +receiver can still accept an unmodified v3 stream. + v3 compat with v2 ----------------- diff --git a/tools/libxc/xc_sr_common.c b/tools/libxc/xc_sr_common.c index 7c54b03414..2fdb6e6634 100644 --- a/tools/libxc/xc_sr_common.c +++ b/tools/libxc/xc_sr_common.c @@ -39,6 +39,7 @@ static const char *const mandatory_rec_types[] = [REC_TYPE_STATIC_DATA_END] = "Static data end", [REC_TYPE_X86_CPUID_POLICY] = "x86 CPUID policy", [REC_TYPE_X86_MSR_POLICY] = "x86 MSR policy", + [REC_TYPE_DOMAIN_CONTEXT] = "Domain context", }; const char *rec_type_to_str(uint32_t type) diff --git a/tools/libxc/xc_sr_stream_format.h b/tools/libxc/xc_sr_stream_format.h index 8a0da26f75..bc538bc192 100644 --- a/tools/libxc/xc_sr_stream_format.h +++ b/tools/libxc/xc_sr_stream_format.h @@ -76,6 +76,7 @@ struct xc_sr_rhdr #define REC_TYPE_STATIC_DATA_END 0x00000010U #define REC_TYPE_X86_CPUID_POLICY 0x00000011U #define REC_TYPE_X86_MSR_POLICY 0x00000012U +#define REC_TYPE_DOMAIN_CONTEXT 0x00000013U #define REC_TYPE_OPTIONAL 0x80000000U diff --git a/tools/python/xen/migration/libxc.py b/tools/python/xen/migration/libxc.py index 9881f5ced4..08ac81344f 100644 --- a/tools/python/xen/migration/libxc.py +++ b/tools/python/xen/migration/libxc.py @@ -59,6 +59,7 @@ REC_TYPE_checkpoint_dirty_pfn_list = 0x0000000f REC_TYPE_static_data_end = 0x00000010 REC_TYPE_x86_cpuid_policy = 0x00000011 REC_TYPE_x86_msr_policy = 0x00000012 +REC_TYPE_domain_context = 0x00000013 rec_type_to_str = { REC_TYPE_end : "End", @@ -80,6 +81,7 @@ rec_type_to_str = { REC_TYPE_static_data_end : "Static data end", REC_TYPE_x86_cpuid_policy : "x86 CPUID policy", REC_TYPE_x86_msr_policy : "x86 MSR policy", + REC_TYPE_domain_context : "Domain context", } # page_data From patchwork Tue Aug 18 10:30:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11720491 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A21E214F6 for ; Tue, 18 Aug 2020 10:31:55 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7F871207FF for ; Tue, 18 Aug 2020 10:31:55 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=xen.org header.i=@xen.org header.b="IoU2922M" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7F871207FF Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=xen.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7ytH-00067M-BC; Tue, 18 Aug 2020 10:30:51 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7ytF-0005zo-Mw for xen-devel@lists.xenproject.org; Tue, 18 Aug 2020 10:30:49 +0000 X-Inumbo-ID: 9e8c31ba-2ac6-408d-a3f2-7ae4f002bea8 Received: from mail.xenproject.org (unknown [104.130.215.37]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 9e8c31ba-2ac6-408d-a3f2-7ae4f002bea8; Tue, 18 Aug 2020 10:30:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=xen.org; s=20200302mail; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=nABtIpE3ocPIbmrY/Y6TR8lqLGhPX2t/r6AUyXMJ7rQ=; b=IoU2922M7bsU8yeqsYH6tiihY2 MshAGFNsqPc9jChRx63ddW1Tnzs1arwkJnNJf/hsJPYzd3UfT7dD8BL+cNST851In1hjxrAJPJ/Fm FfBQNVMEeuTNM5S1jG/VeVXy+7K3Z2M4gD3+GkSxUqNkRaduD9aUP/K8NUnoH/rp/vgc=; Received: from xenbits.xenproject.org ([104.239.192.120]) by mail.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7yt9-000145-1w; Tue, 18 Aug 2020 10:30:43 +0000 Received: from host31-48-92-96.range31-48.btcentralplus.com ([31.48.92.96] helo=u2f063a87eabd5f.home) by xenbits.xenproject.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1k7yt8-0003Rw-Ql; Tue, 18 Aug 2020 10:30:43 +0000 From: Paul Durrant To: xen-devel@lists.xenproject.org Cc: Paul Durrant , Ian Jackson , Wei Liu Subject: [PATCH v7 6/9] tools/libxc: split restore handler handle_shared_info() functionality Date: Tue, 18 Aug 2020 11:30:29 +0100 Message-Id: <20200818103032.3050-7-paul@xen.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200818103032.3050-1-paul@xen.org> References: <20200818103032.3050-1-paul@xen.org> MIME-Version: 1.0 X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" From: Paul Durrant The code is invoked when a SHARED_INFO record is processed but actually performs two functions: [1] Copy the 'vcpu_info' and 'arch' substructures from the record into the new domain's shared_info [2] Clear out any pending event channel state, mask all channels and also clear 'arch.pfn_to_mfn_frame_list_list' To facilitate deprecation of the SHARED_INFO record in version 4 of the migration stream, this patch splits the functionality, leaving [1] in handle_shared_info() and adding update_shared_info() (called from x86_pv_stream_complete()) to deal with [2]. Signed-off-by: Paul Durrant --- Cc: Ian Jackson Cc: Wei Liu v7: - New in v7 --- tools/libxc/xc_sr_restore_x86_pv.c | 31 +++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/tools/libxc/xc_sr_restore_x86_pv.c b/tools/libxc/xc_sr_restore_x86_pv.c index d086271efb..1ed8cc66ca 100644 --- a/tools/libxc/xc_sr_restore_x86_pv.c +++ b/tools/libxc/xc_sr_restore_x86_pv.c @@ -880,7 +880,6 @@ static int handle_shared_info(struct xc_sr_context *ctx, struct xc_sr_record *rec) { xc_interface *xch = ctx->xch; - unsigned int i; int rc = -1; shared_info_any_t *guest_shinfo = NULL; const shared_info_any_t *old_shinfo = rec->data; @@ -911,6 +910,32 @@ static int handle_shared_info(struct xc_sr_context *ctx, MEMCPY_FIELD(guest_shinfo, old_shinfo, vcpu_info, ctx->x86.pv.width); MEMCPY_FIELD(guest_shinfo, old_shinfo, arch, ctx->x86.pv.width); + rc = 0; + + err: + if ( guest_shinfo ) + munmap(guest_shinfo, PAGE_SIZE); + + return rc; +} + +static int update_shared_info(struct xc_sr_context *ctx) +{ + xc_interface *xch = ctx->xch; + unsigned int i; + int rc = -1; + shared_info_any_t *guest_shinfo = NULL; + + guest_shinfo = xc_map_foreign_range( + xch, ctx->domid, PAGE_SIZE, PROT_READ | PROT_WRITE, + ctx->dominfo.shared_info_frame); + if ( !guest_shinfo ) + { + PERROR("Failed to map Shared Info at mfn %#lx", + ctx->dominfo.shared_info_frame); + goto err; + } + SET_FIELD(guest_shinfo, arch.pfn_to_mfn_frame_list_list, 0, ctx->x86.pv.width); @@ -1122,6 +1147,10 @@ static int x86_pv_stream_complete(struct xc_sr_context *ctx) xc_interface *xch = ctx->xch; int rc; + rc = update_shared_info(ctx); + if ( rc ) + return rc; + rc = update_vcpu_context(ctx); if ( rc ) return rc; From patchwork Tue Aug 18 10:30:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11720499 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 20C8E138C for ; Tue, 18 Aug 2020 10:32:20 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id F0D5E2075E for ; Tue, 18 Aug 2020 10:32:19 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=xen.org header.i=@xen.org header.b="b5sTrGH2" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org F0D5E2075E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=xen.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7ytL-0006Ah-Vm; Tue, 18 Aug 2020 10:30:55 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7ytK-0005zo-Mz for xen-devel@lists.xenproject.org; Tue, 18 Aug 2020 10:30:54 +0000 X-Inumbo-ID: 4963137f-f75f-4163-8652-b2aba8a3af45 Received: from mail.xenproject.org (unknown [104.130.215.37]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 4963137f-f75f-4163-8652-b2aba8a3af45; Tue, 18 Aug 2020 10:30:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=xen.org; s=20200302mail; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=TOWerHJHjID6iOKKVnPbdbazPZUTu0OfzhxePXc84AM=; b=b5sTrGH2/4YSg+6kB0IaWF9eBG F4Rx6pWURhOoJ8ItUPMEt+VQJFfP8invYcHEOHdvtQTji1EhgQ9tO66+N+yaLwqkIXnxPw6U7y9xT aKD8Ge3RRZZ6YogxO+5NCAASbVKdMa6tU53bw/jRC/Oqpw4/eWekWjWfdoi9mCkQ/+1k=; Received: from xenbits.xenproject.org ([104.239.192.120]) by mail.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7ytA-00014F-FY; Tue, 18 Aug 2020 10:30:44 +0000 Received: from host31-48-92-96.range31-48.btcentralplus.com ([31.48.92.96] helo=u2f063a87eabd5f.home) by xenbits.xenproject.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1k7ytA-0003Rw-83; Tue, 18 Aug 2020 10:30:44 +0000 From: Paul Durrant To: xen-devel@lists.xenproject.org Cc: Paul Durrant , Ian Jackson , Wei Liu , Andrew Cooper , George Dunlap , Jan Beulich , Julien Grall , Stefano Stabellini Subject: [PATCH v7 7/9] common/domain: add a domain context record for shared_info... Date: Tue, 18 Aug 2020 11:30:30 +0100 Message-Id: <20200818103032.3050-8-paul@xen.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200818103032.3050-1-paul@xen.org> References: <20200818103032.3050-1-paul@xen.org> MIME-Version: 1.0 X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" From: Paul Durrant ... and update xen-domctx to dump some information describing the record. NOTE: Processing of the content during restore is currently limited to PV domains, and matches processing of the PV-only SHARED_INFO record done by libxc. All content is, however, saved such that restore processing can be modified in future without requiring a new record format. Signed-off-by: Paul Durrant --- Cc: Ian Jackson Cc: Wei Liu Cc: Andrew Cooper Cc: George Dunlap Cc: Jan Beulich Cc: Julien Grall Cc: Stefano Stabellini v7: - Only restore vcpu_info and arch sub-structures for PV domains, to match processing of SHARED_INFO in xc_sr_restore_x86_pv.c - Use additional option to domain_load_end() to ignore the record for HVM domains v6: - Only save compat_shared_info buffer if has_32bit_shinfo is set - Validate flags field in load handler v5: - Addressed comments from Julien v4: - Addressed comments from Jan v3: - Actually dump some of the content of shared_info v2: - Drop the header change to define a 'Xen' page size and instead use a variable length struct now that the framework makes this is feasible - Guard use of 'has_32bit_shinfo' in common code with CONFIG_COMPAT --- tools/misc/xen-domctx.c | 78 ++++++++++++++++++++++++++ xen/common/domain.c | 114 ++++++++++++++++++++++++++++++++++++++ xen/include/public/save.h | 13 ++++- 3 files changed, 204 insertions(+), 1 deletion(-) diff --git a/tools/misc/xen-domctx.c b/tools/misc/xen-domctx.c index 243325dfce..6ead7ea89d 100644 --- a/tools/misc/xen-domctx.c +++ b/tools/misc/xen-domctx.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -61,6 +62,82 @@ static void dump_header(void) } +static void print_binary(const char *prefix, const void *val, size_t size, + const char *suffix) +{ + printf("%s", prefix); + + while ( size-- ) + { + uint8_t octet = *(const uint8_t *)val++; + unsigned int i; + + for ( i = 0; i < 8; i++ ) + { + printf("%u", octet & 1); + octet >>= 1; + } + } + + printf("%s", suffix); +} + +static void dump_shared_info(void) +{ + DOMAIN_SAVE_TYPE(SHARED_INFO) *s; + bool has_32bit_shinfo; + shared_info_any_t *info; + unsigned int i, n; + + GET_PTR(s); + has_32bit_shinfo = s->flags & DOMAIN_SAVE_32BIT_SHINFO; + + printf(" SHARED_INFO: has_32bit_shinfo: %s buffer_size: %u\n", + has_32bit_shinfo ? "true" : "false", s->buffer_size); + + info = (shared_info_any_t *)s->buffer; + +#define GET_FIELD_PTR(_f) \ + (has_32bit_shinfo ? \ + (const void *)&(info->x32._f) : \ + (const void *)&(info->x64._f)) +#define GET_FIELD_SIZE(_f) \ + (has_32bit_shinfo ? sizeof(info->x32._f) : sizeof(info->x64._f)) +#define GET_FIELD(_f) \ + (has_32bit_shinfo ? info->x32._f : info->x64._f) + + n = has_32bit_shinfo ? + ARRAY_SIZE(info->x32.evtchn_pending) : + ARRAY_SIZE(info->x64.evtchn_pending); + + for ( i = 0; i < n; i++ ) + { + const char *prefix = !i ? + " evtchn_pending: " : + " "; + + print_binary(prefix, GET_FIELD_PTR(evtchn_pending[0]), + GET_FIELD_SIZE(evtchn_pending[0]), "\n"); + } + + for ( i = 0; i < n; i++ ) + { + const char *prefix = !i ? + " evtchn_mask: " : + " "; + + print_binary(prefix, GET_FIELD_PTR(evtchn_mask[0]), + GET_FIELD_SIZE(evtchn_mask[0]), "\n"); + } + + printf(" wc: version: %u sec: %u nsec: %u\n", + GET_FIELD(wc_version), GET_FIELD(wc_sec), GET_FIELD(wc_nsec)); + +#undef GET_FIELD +#undef GET_FIELD_SIZE +#undef GET_FIELD_PTR +} + static void dump_end(void) { DOMAIN_SAVE_TYPE(END) *e; @@ -173,6 +250,7 @@ int main(int argc, char **argv) switch (desc->typecode) { case DOMAIN_SAVE_CODE(HEADER): dump_header(); break; + case DOMAIN_SAVE_CODE(SHARED_INFO): dump_shared_info(); break; case DOMAIN_SAVE_CODE(END): dump_end(); break; default: printf("Unknown type %u: skipping\n", desc->typecode); diff --git a/xen/common/domain.c b/xen/common/domain.c index f0f9c62feb..9ac2158d6c 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -1659,6 +1660,119 @@ int continue_hypercall_on_cpu( return 0; } +static int save_shared_info(const struct domain *d, struct domain_context *c, + bool dry_run) +{ + struct domain_shared_info_context ctxt = { +#ifdef CONFIG_COMPAT + .flags = has_32bit_shinfo(d) ? DOMAIN_SAVE_32BIT_SHINFO : 0, + .buffer_size = has_32bit_shinfo(d) ? + sizeof(struct compat_shared_info) : + sizeof(struct shared_info), +#else + .buffer_size = sizeof(struct shared_info), +#endif + }; + size_t hdr_size = offsetof(typeof(ctxt), buffer); + int rc; + + rc = DOMAIN_SAVE_BEGIN(SHARED_INFO, c, 0); + if ( rc ) + return rc; + + rc = domain_save_data(c, &ctxt, hdr_size); + if ( rc ) + return rc; + + rc = domain_save_data(c, d->shared_info, ctxt.buffer_size); + if ( rc ) + return rc; + + return domain_save_end(c); +} + +static int load_shared_info(struct domain *d, struct domain_context *c) +{ + struct domain_shared_info_context ctxt; + size_t hdr_size = offsetof(typeof(ctxt), buffer); + unsigned int i; + int rc; + + rc = DOMAIN_LOAD_BEGIN(SHARED_INFO, c, &i); + if ( rc ) + return rc; + + if ( i ) /* expect only a single instance */ + return -ENXIO; + + rc = domain_load_data(c, &ctxt, hdr_size); + if ( rc ) + return rc; + + if ( ctxt.buffer_size > sizeof(shared_info_t) || + (ctxt.flags & ~DOMAIN_SAVE_32BIT_SHINFO) ) + return -EINVAL; + + if ( ctxt.flags & DOMAIN_SAVE_32BIT_SHINFO ) + { +#ifdef CONFIG_COMPAT + has_32bit_shinfo(d) = true; +#else + return -EINVAL; +#endif + } + + if ( is_pv_domain(d) ) + { + shared_info_t *shinfo = xmalloc(shared_info_t); + + rc = domain_load_data(c, shinfo, sizeof(*shinfo)); + if ( rc ) + { + xfree(shinfo); + return rc; + } + +#ifdef CONFIG_COMPAT + if ( has_32bit_shinfo(d) ) + { + memcpy(&d->shared_info->compat.vcpu_info, + &shinfo->compat.vcpu_info, + sizeof(d->shared_info->compat.vcpu_info)); + memcpy(&d->shared_info->compat.arch, + &shinfo->compat.arch, + sizeof(d->shared_info->compat.vcpu_info)); + } + else + { + memcpy(&d->shared_info->native.vcpu_info, + &shinfo->native.vcpu_info, + sizeof(d->shared_info->native.vcpu_info)); + memcpy(&d->shared_info->native.arch, + &shinfo->native.arch, + sizeof(d->shared_info->native.arch)); + } +#else + memcpy(&d->shared_info->vcpu_info, + &shinfo->vcpu_info, + sizeof(d->shared_info->vcpu_info)); + memcpy(&d->shared_info->arch, + &shinfo->arch, + sizeof(d->shared_info->shared)); +#endif + + xfree(shinfo); + + rc = domain_load_end(c, false); + } + else + rc = domain_load_end(c, true); + + return rc; +} + +DOMAIN_REGISTER_SAVE_LOAD(SHARED_INFO, save_shared_info, load_shared_info); + /* * Local variables: * mode: C diff --git a/xen/include/public/save.h b/xen/include/public/save.h index 551dbbddb8..0e855a4b97 100644 --- a/xen/include/public/save.h +++ b/xen/include/public/save.h @@ -82,7 +82,18 @@ struct domain_save_header { }; DECLARE_DOMAIN_SAVE_TYPE(HEADER, 1, struct domain_save_header); -#define DOMAIN_SAVE_CODE_MAX 1 +struct domain_shared_info_context { + uint32_t flags; + +#define DOMAIN_SAVE_32BIT_SHINFO 0x00000001 + + uint32_t buffer_size; + uint8_t buffer[XEN_FLEX_ARRAY_DIM]; /* Implementation specific size */ +}; + +DECLARE_DOMAIN_SAVE_TYPE(SHARED_INFO, 2, struct domain_shared_info_context); + +#define DOMAIN_SAVE_CODE_MAX 2 #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */ From patchwork Tue Aug 18 10:30:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11720503 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 517B6739 for ; Tue, 18 Aug 2020 10:32:31 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2E67C2075E for ; Tue, 18 Aug 2020 10:32:30 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=xen.org header.i=@xen.org header.b="FuA1OU59" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2E67C2075E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=xen.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7ytR-0006HD-9G; Tue, 18 Aug 2020 10:31:01 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7ytP-0005zo-NE for xen-devel@lists.xenproject.org; Tue, 18 Aug 2020 10:30:59 +0000 X-Inumbo-ID: c59afaba-b84f-4ebd-a365-e9f923ab4cc3 Received: from mail.xenproject.org (unknown [104.130.215.37]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id c59afaba-b84f-4ebd-a365-e9f923ab4cc3; Tue, 18 Aug 2020 10:30:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=xen.org; s=20200302mail; h=Content-Transfer-Encoding:Content-Type:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=0B+/exvkZXk9UaGSfy4aEbkmijHI3UBAG2GUZIo9jRQ=; b=FuA1OU59lP4vZMREqb9t/otfTd SE2qr5h8lFkvFnE1sEtUw2zG1+wN7yg3u4NPaDYsC7Zj+Q7bp7B9MVN/DrwKKl4oNANdFw27AEaDk VMHr0kyZauOQ1ZnBz3E6wHidQyI+o1/hlZikXrOa/WnZZgP3nK9obQo8MObxm/YNCTrM=; Received: from xenbits.xenproject.org ([104.239.192.120]) by mail.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7ytB-00014r-WC; Tue, 18 Aug 2020 10:30:45 +0000 Received: from host31-48-92-96.range31-48.btcentralplus.com ([31.48.92.96] helo=u2f063a87eabd5f.home) by xenbits.xenproject.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1k7ytB-0003Rw-OT; Tue, 18 Aug 2020 10:30:45 +0000 From: Paul Durrant To: xen-devel@lists.xenproject.org Cc: Paul Durrant , Ian Jackson , Wei Liu , Andrew Cooper , George Dunlap , Jan Beulich , Julien Grall , Stefano Stabellini , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Subject: [PATCH v7 8/9] x86/time: add a domain context record for tsc_info... Date: Tue, 18 Aug 2020 11:30:31 +0100 Message-Id: <20200818103032.3050-9-paul@xen.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200818103032.3050-1-paul@xen.org> References: <20200818103032.3050-1-paul@xen.org> MIME-Version: 1.0 X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" From: Paul Durrant ... and update xen-domctx to dump some information describing the record. NOTE: Whilst the record definition is x86 specific, it is visible directly in the common header as context record numbers should be unique across all architectures. Signed-off-by: Paul Durrant Reviewed-by: Jan Beulich --- Cc: Ian Jackson Cc: Wei Liu Cc: Andrew Cooper Cc: George Dunlap Cc: Jan Beulich Cc: Julien Grall Cc: Stefano Stabellini Cc: "Roger Pau Monné" v7: - New in v7 --- tools/misc/xen-domctx.c | 12 ++++++++++++ xen/arch/x86/time.c | 34 +++++++++++++++++++++++++++++++++- xen/include/asm-x86/time.h | 5 +++-- xen/include/public/save.h | 13 ++++++++++++- 4 files changed, 60 insertions(+), 4 deletions(-) diff --git a/tools/misc/xen-domctx.c b/tools/misc/xen-domctx.c index 6ead7ea89d..e09d75cf68 100644 --- a/tools/misc/xen-domctx.c +++ b/tools/misc/xen-domctx.c @@ -59,9 +59,20 @@ static void dump_header(void) printf(" HEADER: magic %#x, version %u\n", h->magic, h->version); +} + +static void dump_tsc_info(void) +{ + DOMAIN_SAVE_TYPE(TSC_INFO) *t; + GET_PTR(t); + + printf(" TSC_INFO: mode: %u incarnation: %u\n" + " khz %u elapsed_nsec: %"PRIu64"\n", + t->mode, t->incarnation, t->khz, t->elapsed_nsec); } + static void print_binary(const char *prefix, const void *val, size_t size, const char *suffix) { @@ -251,6 +262,7 @@ int main(int argc, char **argv) { case DOMAIN_SAVE_CODE(HEADER): dump_header(); break; case DOMAIN_SAVE_CODE(SHARED_INFO): dump_shared_info(); break; + case DOMAIN_SAVE_CODE(TSC_INFO): dump_tsc_info(); break; case DOMAIN_SAVE_CODE(END): dump_end(); break; default: printf("Unknown type %u: skipping\n", desc->typecode); diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index 505e54ebd7..05f65fbf12 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -2334,7 +2335,7 @@ int host_tsc_is_safe(void) * called to collect tsc-related data only for save file or live * migrate; called after last rdtsc is done on this incarnation */ -void tsc_get_info(struct domain *d, uint32_t *tsc_mode, +void tsc_get_info(const struct domain *d, uint32_t *tsc_mode, uint64_t *elapsed_nsec, uint32_t *gtsc_khz, uint32_t *incarnation) { @@ -2453,6 +2454,37 @@ int tsc_set_info(struct domain *d, return 0; } +static int save_tsc_info(const struct domain *d, struct domain_context *c, + bool dry_run) +{ + struct domain_tsc_info_context ctxt; + + if ( !dry_run ) + tsc_get_info(d, &ctxt.mode, &ctxt.elapsed_nsec, &ctxt.khz, + &ctxt.incarnation); + + return DOMAIN_SAVE_ENTRY(TSC_INFO, c, 0, &ctxt, sizeof(ctxt)); +} + +static int load_tsc_info(struct domain *d, struct domain_context *c) +{ + struct domain_tsc_info_context ctxt; + unsigned int i; + int rc; + + rc = DOMAIN_LOAD_ENTRY(TSC_INFO, c, &i, &ctxt, sizeof(ctxt)); + if ( rc ) + return rc; + + if ( i ) /* expect only a single instance */ + return -ENXIO; + + return tsc_set_info(d, ctxt.mode, ctxt.elapsed_nsec, ctxt.khz, + ctxt.incarnation); +} + +DOMAIN_REGISTER_SAVE_LOAD(TSC_INFO, save_tsc_info, load_tsc_info); + /* vtsc may incur measurable performance degradation, diagnose with this */ static void dump_softtsc(unsigned char key) { diff --git a/xen/include/asm-x86/time.h b/xen/include/asm-x86/time.h index f347311cc4..7f2ce6226a 100644 --- a/xen/include/asm-x86/time.h +++ b/xen/include/asm-x86/time.h @@ -59,8 +59,9 @@ u64 gtsc_to_gtime(struct domain *d, u64 tsc); int tsc_set_info(struct domain *d, uint32_t tsc_mode, uint64_t elapsed_nsec, uint32_t gtsc_khz, uint32_t incarnation); -void tsc_get_info(struct domain *d, uint32_t *tsc_mode, uint64_t *elapsed_nsec, - uint32_t *gtsc_khz, uint32_t *incarnation); +void tsc_get_info(const struct domain *d, uint32_t *tsc_mode, + uint64_t *elapsed_nsec, uint32_t *gtsc_khz, + uint32_t *incarnation); void force_update_vcpu_system_time(struct vcpu *v); diff --git a/xen/include/public/save.h b/xen/include/public/save.h index 0e855a4b97..aeb17298eb 100644 --- a/xen/include/public/save.h +++ b/xen/include/public/save.h @@ -93,7 +93,18 @@ struct domain_shared_info_context { DECLARE_DOMAIN_SAVE_TYPE(SHARED_INFO, 2, struct domain_shared_info_context); -#define DOMAIN_SAVE_CODE_MAX 2 +#if defined(__i386__) || defined(__x86_64__) +struct domain_tsc_info_context { + uint32_t mode; + uint32_t incarnation; + uint64_t elapsed_nsec; + uint32_t khz; +}; + +DECLARE_DOMAIN_SAVE_TYPE(TSC_INFO, 3, struct domain_tsc_info_context); +#endif + +#define DOMAIN_SAVE_CODE_MAX 3 #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */ From patchwork Tue Aug 18 10:30:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11720497 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3165B138C for ; Tue, 18 Aug 2020 10:32:17 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0E1682075E for ; Tue, 18 Aug 2020 10:32:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=xen.org header.i=@xen.org header.b="1GCGsik4" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0E1682075E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=xen.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7ytJ-00068v-Lm; Tue, 18 Aug 2020 10:30:53 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7ytI-0005zI-G8 for xen-devel@lists.xenproject.org; Tue, 18 Aug 2020 10:30:52 +0000 X-Inumbo-ID: f17407ad-409f-4325-8f5f-79208b53798c Received: from mail.xenproject.org (unknown [104.130.215.37]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id f17407ad-409f-4325-8f5f-79208b53798c; Tue, 18 Aug 2020 10:30:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=xen.org; s=20200302mail; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=uCNYjocIfT1Bb/G3WJgONNuto9xcJ5WXtW2Z0YXVZkM=; b=1GCGsik4dClZ70iV2HUTJN3FXP zfqy9RHrLV3fNf33PTGeaVli3BY7UlacJPRQRKdrljetQrrG1jG0QryJFlE94ezYma91bypKiqrlP tENNnU00C/3CbSbQp8GUz8XXp8zlC1Cy+57zD7SJba142GdiPhcPO37hotTu9bZ9orAc=; Received: from xenbits.xenproject.org ([104.239.192.120]) by mail.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7ytC-00014x-TE; Tue, 18 Aug 2020 10:30:46 +0000 Received: from host31-48-92-96.range31-48.btcentralplus.com ([31.48.92.96] helo=u2f063a87eabd5f.home) by xenbits.xenproject.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1k7ytC-0003Rw-LK; Tue, 18 Aug 2020 10:30:46 +0000 From: Paul Durrant To: xen-devel@lists.xenproject.org Cc: Paul Durrant , Ian Jackson , Wei Liu Subject: [PATCH v7 9/9] tools/libxc: add DOMAIN_CONTEXT records to the migration stream... Date: Tue, 18 Aug 2020 11:30:32 +0100 Message-Id: <20200818103032.3050-10-paul@xen.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200818103032.3050-1-paul@xen.org> References: <20200818103032.3050-1-paul@xen.org> MIME-Version: 1.0 X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" From: Paul Durrant ... and bump the version. This patch implements version 4 of the migration stream by adding the code necessary to save and restore DOMAIN_CONTEXT records, and removing the code to save the SHARED_INFO and TSC_INFO records (as these are deprecated in version 4). Signed-off-by: Paul Durrant --- Cc: Ian Jackson Cc: Wei Liu v7: - New in v7 --- tools/libxc/xc_sr_common.h | 3 ++ tools/libxc/xc_sr_common_x86.c | 20 ------------ tools/libxc/xc_sr_common_x86.h | 6 ---- tools/libxc/xc_sr_restore.c | 45 +++++++++++++++++++++++++-- tools/libxc/xc_sr_save.c | 52 +++++++++++++++++++++++++++++++- tools/libxc/xc_sr_save_x86_hvm.c | 5 --- tools/libxc/xc_sr_save_x86_pv.c | 22 -------------- 7 files changed, 97 insertions(+), 56 deletions(-) diff --git a/tools/libxc/xc_sr_common.h b/tools/libxc/xc_sr_common.h index f3bdea8006..91ba918b32 100644 --- a/tools/libxc/xc_sr_common.h +++ b/tools/libxc/xc_sr_common.h @@ -298,6 +298,9 @@ struct xc_sr_context /* Sender has invoked verify mode on the stream. */ bool verify; + + /* Domain context blob. */ + struct xc_sr_blob context; } restore; }; diff --git a/tools/libxc/xc_sr_common_x86.c b/tools/libxc/xc_sr_common_x86.c index 77ea044a74..dda8e1053c 100644 --- a/tools/libxc/xc_sr_common_x86.c +++ b/tools/libxc/xc_sr_common_x86.c @@ -1,25 +1,5 @@ #include "xc_sr_common_x86.h" -int write_x86_tsc_info(struct xc_sr_context *ctx) -{ - xc_interface *xch = ctx->xch; - struct xc_sr_rec_x86_tsc_info tsc = {}; - struct xc_sr_record rec = { - .type = REC_TYPE_X86_TSC_INFO, - .length = sizeof(tsc), - .data = &tsc, - }; - - if ( xc_domain_get_tsc_info(xch, ctx->domid, &tsc.mode, - &tsc.nsec, &tsc.khz, &tsc.incarnation) < 0 ) - { - PERROR("Unable to obtain TSC information"); - return -1; - } - - return write_record(ctx, &rec); -} - int handle_x86_tsc_info(struct xc_sr_context *ctx, struct xc_sr_record *rec) { xc_interface *xch = ctx->xch; diff --git a/tools/libxc/xc_sr_common_x86.h b/tools/libxc/xc_sr_common_x86.h index e08d81e0e7..39645d0196 100644 --- a/tools/libxc/xc_sr_common_x86.h +++ b/tools/libxc/xc_sr_common_x86.h @@ -3,12 +3,6 @@ #include "xc_sr_common.h" -/* - * Obtains a domains TSC information from Xen and writes a X86_TSC_INFO record - * into the stream. - */ -int write_x86_tsc_info(struct xc_sr_context *ctx); - /* * Parses a X86_TSC_INFO record and applies the result to the domain. */ diff --git a/tools/libxc/xc_sr_restore.c b/tools/libxc/xc_sr_restore.c index bc811e6e3a..858d0c184e 100644 --- a/tools/libxc/xc_sr_restore.c +++ b/tools/libxc/xc_sr_restore.c @@ -35,9 +35,9 @@ static int read_headers(struct xc_sr_context *ctx) return -1; } - if ( ihdr.version < 2 || ihdr.version > 3 ) + if ( ihdr.version < 2 || ihdr.version > 4 ) { - ERROR("Invalid Version: Expected 2 <= ver <= 3, Got %d", + ERROR("Invalid Version: Expected 2 <= ver <= 4, Got %d", ihdr.version); return -1; } @@ -529,6 +529,20 @@ static int send_checkpoint_dirty_pfn_list(struct xc_sr_context *ctx) return rc; } +static int stream_complete(struct xc_sr_context *ctx) +{ + xc_interface *xch = ctx->xch; + int rc; + + rc = xc_domain_setcontext(xch, ctx->domid, + ctx->restore.context.ptr, + ctx->restore.context.size); + if ( rc < 0 ) + PERROR("Unable to restore domain context"); + + return rc; +} + static int process_record(struct xc_sr_context *ctx, struct xc_sr_record *rec); static int handle_checkpoint(struct xc_sr_context *ctx) { @@ -597,6 +611,10 @@ static int handle_checkpoint(struct xc_sr_context *ctx) /* COLO */ /* We need to resume guest */ + rc = stream_complete(ctx); + if ( rc ) + goto err; + rc = ctx->restore.ops.stream_complete(ctx); if ( rc ) goto err; @@ -682,6 +700,21 @@ int handle_static_data_end(struct xc_sr_context *ctx) return rc; } +/* + * Process a DOMAIN_CONTEXT record from the stream. + */ +static int handle_domain_context(struct xc_sr_context *ctx, + struct xc_sr_record *rec) +{ + xc_interface *xch = ctx->xch; + int rc = update_blob(&ctx->restore.context, rec->data, rec->length); + + if ( rc ) + ERROR("Unable to allocate %u bytes for domain context", rec->length); + + return rc; +} + static int process_record(struct xc_sr_context *ctx, struct xc_sr_record *rec) { xc_interface *xch = ctx->xch; @@ -709,6 +742,10 @@ static int process_record(struct xc_sr_context *ctx, struct xc_sr_record *rec) rc = handle_static_data_end(ctx); break; + case REC_TYPE_DOMAIN_CONTEXT: + rc = handle_domain_context(ctx, rec); + break; + default: rc = ctx->restore.ops.process_record(ctx, rec); break; @@ -860,6 +897,10 @@ static int restore(struct xc_sr_context *ctx) * With Remus, if we reach here, there must be some error on primary, * failover from the last checkpoint state. */ + rc = stream_complete(ctx); + if ( rc ) + goto err; + rc = ctx->restore.ops.stream_complete(ctx); if ( rc ) goto err; diff --git a/tools/libxc/xc_sr_save.c b/tools/libxc/xc_sr_save.c index 80b1d5de1f..60f88d9c24 100644 --- a/tools/libxc/xc_sr_save.c +++ b/tools/libxc/xc_sr_save.c @@ -13,7 +13,7 @@ static int write_headers(struct xc_sr_context *ctx, uint16_t guest_type) struct xc_sr_ihdr ihdr = { .marker = IHDR_MARKER, .id = htonl(IHDR_ID), - .version = htonl(3), + .version = htonl(4), .options = htons(IHDR_OPT_LITTLE_ENDIAN), }; struct xc_sr_dhdr dhdr = { @@ -44,6 +44,52 @@ static int write_headers(struct xc_sr_context *ctx, uint16_t guest_type) return 0; } +/* + * Writes a DOMAIN_CONTEXT record into the stream. + */ +static int write_domain_context_record(struct xc_sr_context *ctx) +{ + xc_interface *xch = ctx->xch; + struct xc_sr_record rec = { + .type = REC_TYPE_DOMAIN_CONTEXT, + }; + size_t len = 0; + int rc; + + rc = xc_domain_getcontext(xch, ctx->domid, NULL, &len); + if ( rc < 0 ) + { + PERROR("can't get record length for dom %u\n", ctx->domid); + goto out; + } + + rec.data = malloc(len); + + rc = -1; + if ( !rec.data ) + { + PERROR("can't allocate %lu bytes\n", len); + goto out; + } + + rc = xc_domain_getcontext(xch, ctx->domid, rec.data, &len); + if ( rc < 0 ) + { + PERROR("can't get domain record for dom %u\n", ctx->domid); + goto out; + } + + rec.length = len; + rc = write_record(ctx, &rec); + if ( rc < 0 ) + PERROR("failed to write DOMAIN_CONTEXT record"); + + out: + free(rec.data); + + return rc; +} + /* * Writes an END record into the stream. */ @@ -905,6 +951,10 @@ static int save(struct xc_sr_context *ctx, uint16_t guest_type) goto err; } + rc = write_domain_context_record(ctx); + if ( rc ) + goto err; + rc = ctx->save.ops.end_of_checkpoint(ctx); if ( rc ) goto err; diff --git a/tools/libxc/xc_sr_save_x86_hvm.c b/tools/libxc/xc_sr_save_x86_hvm.c index 0b2abb26bd..4c4de914c9 100644 --- a/tools/libxc/xc_sr_save_x86_hvm.c +++ b/tools/libxc/xc_sr_save_x86_hvm.c @@ -193,11 +193,6 @@ static int x86_hvm_end_of_checkpoint(struct xc_sr_context *ctx) { int rc; - /* Write the TSC record. */ - rc = write_x86_tsc_info(ctx); - if ( rc ) - return rc; - /* Write the HVM_CONTEXT record. */ rc = write_hvm_context(ctx); if ( rc ) diff --git a/tools/libxc/xc_sr_save_x86_pv.c b/tools/libxc/xc_sr_save_x86_pv.c index c7e246ef4f..fdd2562994 100644 --- a/tools/libxc/xc_sr_save_x86_pv.c +++ b/tools/libxc/xc_sr_save_x86_pv.c @@ -849,20 +849,6 @@ static int write_x86_pv_p2m_frames(struct xc_sr_context *ctx) return rc; } -/* - * Writes an SHARED_INFO record into the stream. - */ -static int write_shared_info(struct xc_sr_context *ctx) -{ - struct xc_sr_record rec = { - .type = REC_TYPE_SHARED_INFO, - .length = PAGE_SIZE, - .data = ctx->x86.pv.shinfo, - }; - - return write_record(ctx, &rec); -} - /* * Normalise a pagetable for the migration stream. Performs mfn->pfn * conversions on the ptes. @@ -1093,14 +1079,6 @@ static int x86_pv_end_of_checkpoint(struct xc_sr_context *ctx) { int rc; - rc = write_x86_tsc_info(ctx); - if ( rc ) - return rc; - - rc = write_shared_info(ctx); - if ( rc ) - return rc; - rc = write_all_vcpu_information(ctx); if ( rc ) return rc;