From patchwork Fri Mar 27 18:50:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11462965 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 D517B15AB for ; Fri, 27 Mar 2020 18:51:37 +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 A6654206F2 for ; Fri, 27 Mar 2020 18:51:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=xen.org header.i=@xen.org header.b="bY68tZwe" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A6654206F2 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.89) (envelope-from ) id 1jHu3g-0007yG-3f; Fri, 27 Mar 2020 18:50:20 +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.89) (envelope-from ) id 1jHu3f-0007y5-FD for xen-devel@lists.xenproject.org; Fri, 27 Mar 2020 18:50:19 +0000 X-Inumbo-ID: cd6b50e6-705b-11ea-8a16-12813bfff9fa Received: from mail.xenproject.org (unknown [104.130.215.37]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id cd6b50e6-705b-11ea-8a16-12813bfff9fa; Fri, 27 Mar 2020 18:50:18 +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:Sender:Reply-To:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=pJOwAcrK6KIKWnvYsNAA9b7zTABurM9HiPwMs3sEXl8=; b=bY68tZweZSBfM2QtlBah3yF8Qf TNW51pccTQxSjhnwM7XRqQbG5t5eAcvyuxgWAwnxHCgJCwd/DAkW+j9GsZUagNNc0YtmTvPUqSbwM N3pAl15oBGtYm0bMpDOmhEI1AQgga2rlUlf9FdskdzGiAjlK+oAarewRaYECqI+zVSpg=; Received: from xenbits.xenproject.org ([104.239.192.120]) by mail.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1jHu3d-0008KG-EA; Fri, 27 Mar 2020 18:50:17 +0000 Received: from 54-240-197-232.amazon.com ([54.240.197.232] helo=u2f063a87eabd5f.cbg10.amazon.com) by xenbits.xenproject.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.89) (envelope-from ) id 1jHu3c-0007P4-TW; Fri, 27 Mar 2020 18:50:17 +0000 From: Paul Durrant To: xen-devel@lists.xenproject.org Date: Fri, 27 Mar 2020 18:50:08 +0000 Message-Id: <20200327185012.1795-2-paul@xen.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200327185012.1795-1-paul@xen.org> References: <20200327185012.1795-1-paul@xen.org> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 1/5] xen/common: introduce a new framework for save/restore of 'domain' context X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Stefano Stabellini , Julien Grall , Wei Liu , Paul Durrant , Andrew Cooper , Ian Jackson , George Dunlap , Jan Beulich Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Domain context is state held in the hypervisor that does not come under the category of 'HVM state' but is instead 'PV state' that is common between PV guests and enlightened HVM guests (i.e. those that have PV drivers) such as event channel state, grant entry state, etc. To allow enlightened HVM guests to be migrated without their co-operation it will be necessary to transfer such state along with the domain's memory image, architectural state, etc. This framework is introduced for that purpose. This patch adds the new public header and the low level implementation, entered via the domain_save() or domain_load() functions. Subsequent patches will introduce other parts of the framwork, and code that will make use of it within the current version of the libxc migration 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 --- xen/common/Makefile | 1 + xen/common/save.c | 262 ++++++++++++++++++++++++++++++++++++++ xen/include/public/save.h | 74 +++++++++++ xen/include/xen/save.h | 115 +++++++++++++++++ 4 files changed, 452 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 e8cde65370..90553ba5d7 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -37,6 +37,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..bef99452d8 --- /dev/null +++ b/xen/common/save.c @@ -0,0 +1,262 @@ +/* + * 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 + +struct domain_context { + bool log; + struct domain_save_descriptor desc; + domain_copy_entry copy; + void *priv; +}; + +static struct { + const char *name; + bool per_vcpu; + domain_save_handler save; + domain_load_handler load; +} handlers[DOMAIN_SAVE_CODE_MAX + 1]; + +void __init domain_register_save_type(unsigned int tc, const char *name, + bool per_vcpu, + domain_save_handler save, + domain_load_handler load) +{ + BUG_ON(tc > ARRAY_SIZE(handlers)); + + ASSERT(!handlers[tc].save); + ASSERT(!handlers[tc].load); + + handlers[tc].name = name; + handlers[tc].per_vcpu = per_vcpu; + handlers[tc].save = save; + handlers[tc].load = load; +} + +int domain_save_entry(struct domain_context *c, unsigned int tc, + const char *name, const struct vcpu *v, void *src, + size_t src_len) +{ + int rc; + + if ( c->log && tc != DOMAIN_SAVE_CODE(HEADER) && + tc != DOMAIN_SAVE_CODE(END) ) + gdprintk(XENLOG_INFO, "%pv save: %s (%lu)\n", v, name, src_len); + + if ( !IS_ALIGNED(src_len, 8) ) + return -EINVAL; + + BUG_ON(tc != c->desc.typecode); + BUG_ON(v->vcpu_id != c->desc.instance); + c->desc.length = src_len; + + rc = c->copy(c->priv, &c->desc, sizeof(c->desc)); + if ( rc ) + return rc; + + return c->copy(c->priv, src, src_len); +} + +int domain_save(struct domain *d, domain_copy_entry copy, void *priv, + unsigned long mask, bool dry_run) +{ + struct domain_context c = { + .copy = copy, + .priv = priv, + .log = !dry_run, + }; + struct domain_save_header h = { + .magic = DOMAIN_SAVE_MAGIC, + .version = DOMAIN_SAVE_VERSION, + }; + struct domain_save_header e; + unsigned int i; + int rc; + + ASSERT(d != current->domain); + + if ( d->is_dying ) + return -EINVAL; + + domain_pause(d); + + c.desc.typecode = DOMAIN_SAVE_CODE(HEADER); + + rc = DOMAIN_SAVE_ENTRY(HEADER, &c, d->vcpu[0], &h, sizeof(h)); + if ( rc ) + goto out; + + for ( i = 0; i < ARRAY_SIZE(handlers); i++ ) + { + domain_save_handler save = handlers[i].save; + + if ( (mask && !test_bit(i, &mask)) || !save ) + continue; + + memset(&c.desc, 0, sizeof(c.desc)); + c.desc.typecode = i; + + if ( handlers[i].per_vcpu ) + { + struct vcpu *v; + + for_each_vcpu ( d, v ) + { + c.desc.instance = v->vcpu_id; + + rc = save(v, &c, dry_run); + if ( rc ) + goto out; + } + } + else + { + rc = save(d->vcpu[0], &c, dry_run); + if ( rc ) + goto out; + } + } + + memset(&c.desc, 0, sizeof(c.desc)); + c.desc.typecode = DOMAIN_SAVE_CODE(END); + + rc = DOMAIN_SAVE_ENTRY(END, &c, d->vcpu[0], &e, 0); + + out: + domain_unpause(d); + + return rc; +} + +int domain_load_entry(struct domain_context *c, unsigned int tc, + const char *name, const struct vcpu *v, void *dst, + size_t dst_len, bool exact) +{ + int rc; + + if ( c->log && tc != DOMAIN_SAVE_CODE(HEADER) && + tc != DOMAIN_SAVE_CODE(END) ) + gdprintk(XENLOG_INFO, "%pv load: %s (%lu)\n", v, name, dst_len); + + BUG_ON(tc != c->desc.typecode); + BUG_ON(v->vcpu_id != c->desc.instance); + + if ( (exact ? + (dst_len != c->desc.length) : (dst_len < c->desc.length)) || + !IS_ALIGNED(c->desc.length, 8) ) + return -EINVAL; + + rc = c->copy(c->priv, dst, c->desc.length); + if ( rc ) + return rc; + + if ( !exact ) + { + dst += c->desc.length; + memset(dst, 0, dst_len - c->desc.length); + } + + return 0; +} + +int domain_load(struct domain *d, domain_copy_entry copy, void *priv, + unsigned long mask) +{ + struct domain_context c = { + .copy = copy, + .priv = priv, + .log = true, + }; + struct domain_save_header h, e; + int rc; + + ASSERT(d != current->domain); + + if ( d->is_dying ) + return -EINVAL; + + rc = c.copy(c.priv, &c.desc, sizeof(c.desc)); + if ( rc ) + return rc; + + if ( c.desc.typecode != DOMAIN_SAVE_CODE(HEADER) || + c.desc.instance != 0 ) + return -EINVAL; + + rc = DOMAIN_LOAD_ENTRY(HEADER, &c, d->vcpu[0], &h, sizeof(h), true); + if ( rc ) + return rc; + + if ( h.magic != DOMAIN_SAVE_MAGIC || h.version != DOMAIN_SAVE_VERSION ) + return -EINVAL; + + domain_pause(d); + + for (;;) + { + unsigned int i; + domain_load_handler load; + struct vcpu *v; + + rc = c.copy(c.priv, &c.desc, sizeof(c.desc)); + if ( rc ) + break; + + if ( c.desc.typecode == DOMAIN_SAVE_CODE(END) ) { + rc = DOMAIN_LOAD_ENTRY(END, &c, d->vcpu[0], &e, 0, true); + break; + } + + rc = -EINVAL; + if ( c.desc.typecode >= ARRAY_SIZE(handlers) || + c.desc.instance >= d->max_vcpus ) + break; + + i = c.desc.typecode; + load = handlers[i].load; + v = d->vcpu[c.desc.instance]; + + if ( mask && !test_bit(i, &mask) ) + { + /* Sink the data */ + rc = c.copy(c.priv, NULL, c.desc.length); + if ( rc ) + break; + + continue; + } + + rc = load ? load(v, &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/save.h b/xen/include/public/save.h new file mode 100644 index 0000000000..84981cd0f6 --- /dev/null +++ b/xen/include/public/save.h @@ -0,0 +1,74 @@ +/* + * 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__ + +#include "xen.h" + +/* Each entry is preceded by a descriptor */ +struct domain_save_descriptor { + uint16_t typecode; + uint16_t instance; + /* + * Entry length not including this descriptor. Entries must be padded + * to a multiple of 8 bytes to make sure descriptors remain correctly + * aligned. + */ + uint32_t length; +}; + +/* + * Each entry has a type associated with it. DECLARE_DOMAIN_SAVE_TYPE + * binds these things together. + */ +#define DECLARE_DOMAIN_SAVE_TYPE(_x, _code, _type) \ + struct __DOMAIN_SAVE_TYPE_##_x { _type t; char c[_code]; }; + +#define DOMAIN_SAVE_TYPE(_x) \ + typeof (((struct __DOMAIN_SAVE_TYPE_##_x *)(0))->t) +#define DOMAIN_SAVE_CODE(_x) \ + (sizeof (((struct __DOMAIN_SAVE_TYPE_##_x *)(0))->c)) +#define DOMAIN_SAVE_MASK(_x) (1u << DOMAIN_SAVE_CODE(_x)) + +/* 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 */ + uint32_t version; /* Save format version */ +}; +DECLARE_DOMAIN_SAVE_TYPE(HEADER, 1, struct domain_save_header); + +#define DOMAIN_SAVE_CODE_MAX 1 + +#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..d5846f9e68 --- /dev/null +++ b/xen/include/xen/save.h @@ -0,0 +1,115 @@ +/* + * 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 +#include + +struct domain_context; + +int domain_save_entry(struct domain_context *c, unsigned int tc, + const char *name, const struct vcpu *v, void *src, + size_t src_len); + +#define DOMAIN_SAVE_ENTRY(_x, _c, _v, _src, _len) \ + domain_save_entry((_c), DOMAIN_SAVE_CODE(_x), #_x, (_v), (_src), \ + (_len)); + +int domain_load_entry(struct domain_context *c, unsigned int tc, + const char *name, const struct vcpu *v, void *dest, + size_t dest_len, bool exact); + +#define DOMAIN_LOAD_ENTRY(_x, _c, _v, _src, _len, _exact) \ + domain_load_entry((_c), DOMAIN_SAVE_CODE(_x), #_x, (_v), (_src), \ + (_len), (_exact)); + +/* + * 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_ENTRY() with an accurate value + * for '_len'. + */ +typedef int (*domain_save_handler)(const struct vcpu *v, + struct domain_context *h, + bool dry_run); +typedef int (*domain_load_handler)(struct vcpu *v, + struct domain_context *h); + +void domain_register_save_type(unsigned int tc, const char *name, + bool per_vcpu, + domain_save_handler save, + domain_load_handler load); + +#define DOMAIN_REGISTER_SAVE_RESTORE(_x, _per_vcpu, _save, _load) \ +static int __init __domain_register_##_x##_save_restore(void) \ +{ \ + domain_register_save_type( \ + DOMAIN_SAVE_CODE(_x), \ + #_x, \ + (_per_vcpu), \ + &(_save), \ + &(_load)); \ + \ + return 0; \ +} \ +__initcall(__domain_register_##_x##_save_restore); + +/* Copy callback function */ +typedef int (*domain_copy_entry)(void *priv, void *data, size_t len); + +/* + * Entry points: + * + * int domain_save(struct domain *d, domain_copy_entry copy, void *priv, + * unsigned long mask, bool dry_run); + * int domain_load(struct domain *d, domain_copy_entry copy, void *priv, + * unsigned long mask); + * + * copy: This is a callback function 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. + * 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. + * mask: This is a mask to determine which save record types should be + * copied to or from the buffer. + * If it is zero then all save record types will be copied. + * If it is non-zero then only record types with codes + * corresponding to set bits will be copied. I.e. to copy save + * record 'type', set the bit in position DOMAIN_SAVE_CODE(type). + * DOMAIN_SAVE_CODE(HEADER) and DOMAIN_SAVE_CODE(END) records must + * always be present and thus will be copied regardless of whether + * the bits in those positions are set or not. + * dry_run: See the comment concerning (*domain_save) above. + * + * NOTE: A convenience macro, DOMAIN_SAVE_MASK(type), is defined to support + * setting bits in the mask field. + */ +int domain_save(struct domain *d, domain_copy_entry copy, void *priv, + unsigned long mask, bool dry_run); +int domain_load(struct domain *d, domain_copy_entry copy, void *priv, + unsigned long mask); + +#endif /* __XEN_SAVE_H__ */ From patchwork Fri Mar 27 18:50:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11462961 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 2D8B681 for ; Fri, 27 Mar 2020 18:51:29 +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 F37CD206F2 for ; Fri, 27 Mar 2020 18:51:28 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=xen.org header.i=@xen.org header.b="2k55iij7" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org F37CD206F2 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.89) (envelope-from ) id 1jHu3q-00082f-6u; Fri, 27 Mar 2020 18:50:30 +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.89) (envelope-from ) id 1jHu3p-00082I-9u for xen-devel@lists.xenproject.org; Fri, 27 Mar 2020 18:50:29 +0000 X-Inumbo-ID: cebd5d4a-705b-11ea-8a16-12813bfff9fa Received: from mail.xenproject.org (unknown [104.130.215.37]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id cebd5d4a-705b-11ea-8a16-12813bfff9fa; Fri, 27 Mar 2020 18:50:20 +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:Sender:Reply-To:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=RhHIz1pjEQhWx/GUslfny2ub9WzhPjQ1t0Bca4BN9bM=; b=2k55iij7UNmbJD5/bMhcmi47rI fKi2BC6Uz87cpv04SZjsCBJUUoVFfe50yNZWaML0Aza2A29xpUGdOc0/ADCBGZBqI/Og1EldutynK xX2vd4g25JWoX9rzYVEHcS6e6zYkcYiuBnxneuWpXa9npV8UTI+R0YMZbCmNj74tkhYo=; Received: from xenbits.xenproject.org ([104.239.192.120]) by mail.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1jHu3f-0008KP-3a; Fri, 27 Mar 2020 18:50:19 +0000 Received: from 54-240-197-232.amazon.com ([54.240.197.232] helo=u2f063a87eabd5f.cbg10.amazon.com) by xenbits.xenproject.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.89) (envelope-from ) id 1jHu3e-0007P4-On; Fri, 27 Mar 2020 18:50:18 +0000 From: Paul Durrant To: xen-devel@lists.xenproject.org Date: Fri, 27 Mar 2020 18:50:09 +0000 Message-Id: <20200327185012.1795-3-paul@xen.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200327185012.1795-1-paul@xen.org> References: <20200327185012.1795-1-paul@xen.org> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 2/5] xen/common/domctl: introduce XEN_DOMCTL_get/setdomaincontext X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Stefano Stabellini , Julien Grall , Wei Liu , Paul Durrant , Andrew Cooper , Ian Jackson , George Dunlap , Jan Beulich , Daniel De Graaf 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 --- Cc: Daniel De Graaf Cc: Ian Jackson Cc: Wei Liu Cc: Andrew Cooper Cc: George Dunlap Cc: Jan Beulich Cc: Julien Grall Cc: Stefano Stabellini --- tools/flask/policy/modules/xen.if | 4 +- tools/libxc/include/xenctrl.h | 11 +++ tools/libxc/xc_domain.c | 52 +++++++++++++ xen/common/domctl.c | 115 ++++++++++++++++++++++++++++ xen/include/public/domctl.h | 41 +++++++++- xen/xsm/flask/hooks.c | 6 ++ xen/xsm/flask/policy/access_vectors | 4 + 7 files changed, 230 insertions(+), 3 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 fc6e57a1a0..5c0d0d27a4 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -867,6 +867,17 @@ 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, + uint32_t mask, + uint8_t *ctxt_buf, + uint32_t size); +int xc_domain_setcontext(xc_interface *xch, + uint32_t domid, + uint32_t mask, + uint8_t *ctxt_buf, + uint32_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..15bcf671fc 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -537,6 +537,58 @@ int xc_domain_hvm_setcontext(xc_interface *xch, return ret; } +int xc_domain_getcontext(xc_interface *xch, + uint32_t domid, + uint32_t mask, + uint8_t *ctxt_buf, + uint32_t size) +{ + int ret; + DECLARE_DOMCTL; + DECLARE_HYPERCALL_BOUNCE(ctxt_buf, size, XC_HYPERCALL_BUFFER_BOUNCE_OUT); + + if ( xc_hypercall_bounce_pre(xch, ctxt_buf) ) + return -1; + + domctl.cmd = XEN_DOMCTL_getdomaincontext; + domctl.domain = domid; + domctl.u.domaincontext.mask = mask; + domctl.u.domaincontext.size = size; + set_xen_guest_handle(domctl.u.domaincontext.buffer, ctxt_buf); + + ret = do_domctl(xch, &domctl); + + xc_hypercall_bounce_post(xch, ctxt_buf); + + return !ret ? domctl.u.domaincontext.size : -1; +} + +int xc_domain_setcontext(xc_interface *xch, + uint32_t domid, + uint32_t mask, + uint8_t *ctxt_buf, + uint32_t size) +{ + int ret; + DECLARE_DOMCTL; + DECLARE_HYPERCALL_BOUNCE(ctxt_buf, size, XC_HYPERCALL_BUFFER_BOUNCE_IN); + + if ( xc_hypercall_bounce_pre(xch, ctxt_buf) ) + return -1; + + domctl.cmd = XEN_DOMCTL_setdomaincontext; + domctl.domain = domid; + domctl.u.domaincontext.mask = mask; + domctl.u.domaincontext.size = size; + set_xen_guest_handle(domctl.u.domaincontext.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 a69b3b59a8..9c39519b04 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -358,6 +359,111 @@ static struct vnuma_info *vnuma_init(const struct xen_domctl_vnuma *uinfo, return ERR_PTR(ret); } +struct domctl_context +{ + void *buffer; + size_t len; + size_t cur; +}; + +static int accumulate_size(void *priv, void *data, size_t len) +{ + struct domctl_context *c = priv; + + c->len += len; + + return 0; +} + +static int save_data(void *priv, 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 getdomaincontext(struct domain *d, + struct xen_domctl_domaincontext *dc) +{ + struct domctl_context c = { }; + int rc; + + if ( d == current->domain ) + return -EPERM; + + if ( guest_handle_is_null(dc->buffer) ) /* query for buffer size */ + + { + if ( dc->size ) + return -EINVAL; + + /* dry run to acquire buffer size */ + rc = domain_save(d, accumulate_size, &c, dc->mask, true); + if ( rc ) + return rc; + + dc->size = c.len; + return 0; + } + + c.len = dc->size; + c.buffer = xmalloc_bytes(c.len); + if ( !c.buffer ) + return -ENOMEM; + + rc = domain_save(d, save_data, &c, dc->mask, false); + + dc->size = c.cur; + if ( !rc && copy_to_guest(dc->buffer, c.buffer, dc->size) ) + rc = -EFAULT; + + xfree(c.buffer); + + return rc; +} + +static int load_data(void *priv, void *data, size_t len) +{ + struct domctl_context *c = priv; + + if ( c->len - c->cur < len ) + return -ENODATA; + + if ( data ) + memcpy(data, c->buffer + c->cur, len); + + c->cur += len; + + return 0; +} + +static int setdomaincontext(struct domain *d, + const struct xen_domctl_domaincontext *dc) +{ + struct domctl_context c = { .len = dc->size }; + int rc; + + if ( d == current->domain ) + return -EPERM; + + c.buffer = xmalloc_bytes(c.len); + if ( !c.buffer ) + return -ENOMEM; + + rc = !copy_from_guest(c.buffer, dc->buffer, c.len) ? + domain_load(d, load_data, &c, dc->mask) : -EFAULT; + + xfree(c.buffer); + + return rc; +} + long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) { long ret = 0; @@ -942,6 +1048,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.domaincontext); + copyback = !ret; + break; + + case XEN_DOMCTL_setdomaincontext: + ret = setdomaincontext(d, &op->u.domaincontext); + 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 1ad34c35eb..24ed6852cf 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -38,7 +38,7 @@ #include "hvm/save.h" #include "memory.h" -#define XEN_DOMCTL_INTERFACE_VERSION 0x00000012 +#define XEN_DOMCTL_INTERFACE_VERSION 0x00000013 /* * NB. xen_domctl.domain is an IN/OUT parameter for this operation. @@ -1129,6 +1129,42 @@ struct xen_domctl_vuart_op { */ }; +/* + * Get/Set domain PV context. The same struct xen_domctl_domaincontext + * is used for both commands but with slightly different field semantics + * as follows: + * + * 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. + * mask (IN): See comment on domain_save/load() in xen/save.h. + * + * 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. + * mask (IN): See comment on domain_save/load() in xen/save.h. + */ +struct xen_domctl_domaincontext { + uint32_t size; + uint32_t mask; + XEN_GUEST_HANDLE_64(uint8) buffer; +}; + struct xen_domctl { uint32_t cmd; #define XEN_DOMCTL_createdomain 1 @@ -1210,6 +1246,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 @@ -1270,6 +1308,7 @@ 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_domaincontext domaincontext; uint8_t pad[128]; } u; }; diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 8af8602b46..d94d0fc125 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -744,6 +744,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 c055c14c26..fccfb9de82 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 Fri Mar 27 18:50:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11462955 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 18C9A15AB for ; Fri, 27 Mar 2020 18:51:23 +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 E8FD9206F2 for ; Fri, 27 Mar 2020 18:51:22 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=xen.org header.i=@xen.org header.b="bHjHZbkq" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E8FD9206F2 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.89) (envelope-from ) id 1jHu3l-0007zz-Py; Fri, 27 Mar 2020 18:50:25 +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.89) (envelope-from ) id 1jHu3k-0007yx-9l for xen-devel@lists.xenproject.org; Fri, 27 Mar 2020 18:50:24 +0000 X-Inumbo-ID: cebcf95e-705b-11ea-8a16-12813bfff9fa Received: from mail.xenproject.org (unknown [104.130.215.37]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id cebcf95e-705b-11ea-8a16-12813bfff9fa; Fri, 27 Mar 2020 18:50:20 +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:Sender:Reply-To:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=gaej7huESA3uufYv2UCPxiLF2FbJiwCLGYTRpcZ6bD0=; b=bHjHZbkqZkzKiN2Lc5fRXj8hQL eF0RamGUkN0GEuYsgz9hsPwDUK8Fyq6aQO5iuL5IkCtCgHqDkehvBCoIlC0/n5/N09rvvkuMqyqDU 7+nztf19nwTZRmbLOHJS4jYIKKQMq+K16ZhKkzTCIOVQ0/CfgHCJ4qnL9kw42VxNLb6U=; Received: from xenbits.xenproject.org ([104.239.192.120]) by mail.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1jHu3f-0008KU-V6; Fri, 27 Mar 2020 18:50:19 +0000 Received: from 54-240-197-232.amazon.com ([54.240.197.232] helo=u2f063a87eabd5f.cbg10.amazon.com) by xenbits.xenproject.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.89) (envelope-from ) id 1jHu3f-0007P4-MV; Fri, 27 Mar 2020 18:50:19 +0000 From: Paul Durrant To: xen-devel@lists.xenproject.org Date: Fri, 27 Mar 2020 18:50:10 +0000 Message-Id: <20200327185012.1795-4-paul@xen.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200327185012.1795-1-paul@xen.org> References: <20200327185012.1795-1-paul@xen.org> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 3/5] tools/misc: add xen-ctx to present domain context X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Ian Jackson , Wei Liu , Paul Durrant Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" This tools 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 --- Cc: Ian Jackson Cc: Wei Liu --- .gitignore | 1 + tools/misc/Makefile | 4 ++ tools/misc/xen-ctx.c | 144 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 tools/misc/xen-ctx.c diff --git a/.gitignore b/.gitignore index 4ca679ddbc..72b807141f 100644 --- a/.gitignore +++ b/.gitignore @@ -206,6 +206,7 @@ tools/misc/cpuperf/cpuperf-xen tools/misc/xc_shadow tools/misc/xen_cpuperf tools/misc/xen-cpuid +tools/misc/xen-ctx tools/misc/xen-detect tools/misc/xen-diag tools/misc/xen-tmem-list-parse diff --git a/tools/misc/Makefile b/tools/misc/Makefile index 63947bfadc..6347bb24e9 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -30,6 +30,7 @@ INSTALL_SBIN += xenpm INSTALL_SBIN += xenwatchdogd INSTALL_SBIN += xen-livepatch INSTALL_SBIN += xen-diag +INSTALL_SBIN += xen-ctx INSTALL_SBIN += $(INSTALL_SBIN-y) # Everything to be installed in a private bin/ @@ -108,6 +109,9 @@ xen-livepatch: xen-livepatch.o xen-diag: xen-diag.o $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS) +xen-ctx: xen-ctx.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-ctx.c b/tools/misc/xen-ctx.c new file mode 100644 index 0000000000..c31dd5d8e9 --- /dev/null +++ b/tools/misc/xen-ctx.c @@ -0,0 +1,144 @@ +/* + * xen-ctx.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 READ(_x) do { \ + if ( len - off < sizeof (_x) ) \ + { \ + fprintf(stderr, "Error: need another %lu bytes, only %lu available",\ + sizeof(_x), len - off); \ + exit(1); \ + } \ + memcpy(&(_x), buf + off, sizeof (_x)); \ + off += sizeof (_x); \ +} while (0) + +static void dump_header(void) +{ + DOMAIN_SAVE_TYPE(HEADER) h; + READ(h); + printf(" HEADER: magic %#x, version %u\n", + h.magic, h.version); +} + +static void dump_end(void) +{ + DOMAIN_SAVE_TYPE(END) e; + READ(e); + printf(" END\n"); +} + +int main(int argc, char **argv) +{ + uint32_t domid; + unsigned int entry; + xc_interface *xch; + int rc; + + if ( argc != 2 || !argv[1] || (rc = atoi(argv[1])) < 0 ) + { + fprintf(stderr, "usage: %s \n", argv[0]); + exit(1); + } + domid = rc; + + 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, 0, 0, 0); + if ( rc < 0 ) + { + fprintf(stderr, "Error: can't get record length for dom %u: %s\n", + domid, strerror(errno)); + exit(1); + } + len = rc; + + buf = malloc(len); + if ( !buf ) + { + fprintf(stderr, "Error: can't allocate %lu bytes\n", len); + exit(1); + } + + rc = xc_domain_getcontext(xch, domid, 0, buf, len); + if ( rc < 0 ) + { + fprintf(stderr, "Error: can't get domain record for dom %u: %s\n", + domid, strerror(errno)); + exit(1); + } + len = rc; + off = 0; + + printf("Domain save records for d%u\n", domid); + + entry = 0; + for (;;) { + struct domain_save_descriptor desc; + + READ(desc); + 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(); return 0; + default: + printf("Unknown type %u: skipping\n", desc.typecode); + off += desc.length; + break; + } + } +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ From patchwork Fri Mar 27 18:50:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11462957 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 3858181 for ; Fri, 27 Mar 2020 18:51:27 +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 14BAF206F2 for ; Fri, 27 Mar 2020 18:51:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=xen.org header.i=@xen.org header.b="r/izpxsq" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 14BAF206F2 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.89) (envelope-from ) id 1jHu3l-0007zf-GM; Fri, 27 Mar 2020 18:50:25 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1jHu3j-0007yq-R6 for xen-devel@lists.xenproject.org; Fri, 27 Mar 2020 18:50:23 +0000 X-Inumbo-ID: cfaf9f10-705b-11ea-bec1-bc764e2007e4 Received: from mail.xenproject.org (unknown [104.130.215.37]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id cfaf9f10-705b-11ea-bec1-bc764e2007e4; Fri, 27 Mar 2020 18:50:21 +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:Sender:Reply-To:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=Ari6gro6vIHbJy4JWToLoL3jkvF1i1YmcxQJlN3+ER0=; b=r/izpxsq1BCRc7awuaGGPdcAka SW64gj477rlzDT7U5H7ebNrPIH6HbA5vYwGlZU6A11GTLqTPe5I6ofRmoMsWZgN19Af0PZeMDxTQN BPHTUgFoiybBRT1j5xktVV+6HFyS3cb2eQuqvrma46qmZFRCleGU4eS1i7DnyMqzJTCU=; Received: from xenbits.xenproject.org ([104.239.192.120]) by mail.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1jHu3h-0008Kh-FX; Fri, 27 Mar 2020 18:50:21 +0000 Received: from 54-240-197-232.amazon.com ([54.240.197.232] helo=u2f063a87eabd5f.cbg10.amazon.com) by xenbits.xenproject.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.89) (envelope-from ) id 1jHu3h-0007P4-6c; Fri, 27 Mar 2020 18:50:21 +0000 From: Paul Durrant To: xen-devel@lists.xenproject.org Date: Fri, 27 Mar 2020 18:50:11 +0000 Message-Id: <20200327185012.1795-5-paul@xen.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200327185012.1795-1-paul@xen.org> References: <20200327185012.1795-1-paul@xen.org> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 4/5] common/domain: add a domain context record for shared_info... X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Stefano Stabellini , Julien Grall , Wei Liu , Paul Durrant , Andrew Cooper , Ian Jackson , George Dunlap , Jan Beulich Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" ... and update xen-ctx to dump some information describing the record. NOTE: To allow a sensible definition of the record in public/save.h this patch also adds a definition of the Xen ABI's de-facto page size into public/xen.h. 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 --- tools/misc/xen-ctx.c | 8 ++++++ xen/common/domain.c | 55 +++++++++++++++++++++++++++++++++++++++ xen/include/public/save.h | 10 ++++++- xen/include/public/xen.h | 3 +++ 4 files changed, 75 insertions(+), 1 deletion(-) diff --git a/tools/misc/xen-ctx.c b/tools/misc/xen-ctx.c index c31dd5d8e9..8f9692843b 100644 --- a/tools/misc/xen-ctx.c +++ b/tools/misc/xen-ctx.c @@ -57,6 +57,13 @@ static void dump_header(void) h.magic, h.version); } +static void dump_shared_info(void) +{ + DOMAIN_SAVE_TYPE(SHARED_INFO) s; + READ(s); + printf(" SHARED_INFO: field_width %u\n", s.field_width); +} + static void dump_end(void) { DOMAIN_SAVE_TYPE(END) e; @@ -124,6 +131,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(); return 0; default: printf("Unknown type %u: skipping\n", desc.typecode); diff --git a/xen/common/domain.c b/xen/common/domain.c index 3dcd73f67c..484f6bde13 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -1646,6 +1647,60 @@ int continue_hypercall_on_cpu( return 0; } +static int save_shared_info(const struct vcpu *v, struct domain_context *c, + bool dry_run) +{ + struct domain *d = v->domain; + struct domain_shared_info_context ctxt = {}; + + if ( !dry_run ) + { + memcpy(ctxt.buffer, d->shared_info, PAGE_SIZE); + ctxt.field_width = has_32bit_shinfo(d) ? 4 : 8; + } + + return DOMAIN_SAVE_ENTRY(SHARED_INFO, c, v, &ctxt, sizeof(ctxt)); +} + +static int load_shared_info(struct vcpu *v, struct domain_context *c) +{ + struct domain *d = v->domain; + struct domain_shared_info_context ctxt; + unsigned int i; + int rc; + + rc = DOMAIN_LOAD_ENTRY(SHARED_INFO, c, v, &ctxt, sizeof(ctxt), true); + if ( rc ) + return rc; + + for ( i = 0; i < ARRAY_SIZE(ctxt.pad); i++ ) + if ( ctxt.pad[i] ) + return -EINVAL; + + switch ( ctxt.field_width ) + { + case 4: + d->arch.has_32bit_shinfo = 1; + break; + + case 8: + d->arch.has_32bit_shinfo = 0; + break; + + default: + rc = -EINVAL; + break; + } + + if ( !rc ) + memcpy(d->shared_info, ctxt.buffer, PAGE_SIZE); + + return rc; +} + +DOMAIN_REGISTER_SAVE_RESTORE(SHARED_INFO, false, 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 84981cd0f6..ff804a7dbf 100644 --- a/xen/include/public/save.h +++ b/xen/include/public/save.h @@ -69,6 +69,14 @@ 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 { + uint8_t buffer[XEN_PAGE_SIZE]; + uint8_t field_width; + uint8_t pad[7]; +}; + +DECLARE_DOMAIN_SAVE_TYPE(SHARED_INFO, 2, struct domain_shared_info_context); + +#define DOMAIN_SAVE_CODE_MAX 2 #endif /* __XEN_PUBLIC_SAVE_H__ */ diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index 75b1619d0d..cbf603f289 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -37,6 +37,9 @@ #error "Unsupported architecture" #endif +/* The Xen ABI assumes a page size of 4k. */ +#define XEN_PAGE_SIZE 4096 + #ifndef __ASSEMBLY__ /* Guest handles for primitive C types. */ DEFINE_XEN_GUEST_HANDLE(char); From patchwork Fri Mar 27 18:50:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11462959 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 99FDD15AB for ; Fri, 27 Mar 2020 18:51:27 +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 7756B206F2 for ; Fri, 27 Mar 2020 18:51:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=xen.org header.i=@xen.org header.b="Hbc52EMF" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7756B206F2 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.89) (envelope-from ) id 1jHu3v-00085R-Gu; Fri, 27 Mar 2020 18:50:35 +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.89) (envelope-from ) id 1jHu3u-00084u-AN for xen-devel@lists.xenproject.org; Fri, 27 Mar 2020 18:50:34 +0000 X-Inumbo-ID: d0334ad6-705b-11ea-8a16-12813bfff9fa Received: from mail.xenproject.org (unknown [104.130.215.37]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id d0334ad6-705b-11ea-8a16-12813bfff9fa; Fri, 27 Mar 2020 18:50:22 +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:Sender:Reply-To:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=BE/ggHUpivzYWOJvoMk+gTgNDKBm4EEXr+ZyW2JUzQI=; b=Hbc52EMFjO4AE9KmOyBeHC70oq 8Zq9G0+Qt7apNPBHg4kuf3l8jG+VM9Y8Vp73H/rll0Z+BEkV+phZQIEsT2Zj7jRE85tR8wJYIOxBb lZrGdDTuxmv7g9e2jjkyT7VKB6XWL9pynwVcJKABh5GUzvf4ryhGXP2ywiD+akHIzGwA=; Received: from xenbits.xenproject.org ([104.239.192.120]) by mail.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1jHu3i-0008Ko-D8; Fri, 27 Mar 2020 18:50:22 +0000 Received: from 54-240-197-232.amazon.com ([54.240.197.232] helo=u2f063a87eabd5f.cbg10.amazon.com) by xenbits.xenproject.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.89) (envelope-from ) id 1jHu3i-0007P4-4L; Fri, 27 Mar 2020 18:50:22 +0000 From: Paul Durrant To: xen-devel@lists.xenproject.org Date: Fri, 27 Mar 2020 18:50:12 +0000 Message-Id: <20200327185012.1795-6-paul@xen.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200327185012.1795-1-paul@xen.org> References: <20200327185012.1795-1-paul@xen.org> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 5/5] tools/libxc: make use of domain context SHARED_INFO record... X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Ian Jackson , Wei Liu , Paul Durrant Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" ... in the save/restore code. This patch replaces direct mapping of the shared_info_frame (retrieved using XEN_DOMCTL_getdomaininfo) with save/load of the domain context SHARED_INFO record. No modifications are made to the definition of the migration stream at this point. Subsequent patches will define a record in the libxc domain image format for passing domain context and convert the save/restore code to use that. Signed-off-by: Paul Durrant --- Cc: Ian Jackson Cc: Wei Liu --- tools/libxc/xc_sr_common.h | 7 +++- tools/libxc/xc_sr_common_x86.c | 58 ++++++++++++++++++++++++++++++ tools/libxc/xc_sr_common_x86.h | 4 +++ tools/libxc/xc_sr_common_x86_pv.c | 52 +++++++++++++++++++++++++++ tools/libxc/xc_sr_common_x86_pv.h | 3 ++ tools/libxc/xc_sr_restore_x86_pv.c | 40 ++++++++------------- tools/libxc/xc_sr_save_x86_pv.c | 26 ++------------ tools/libxc/xg_save_restore.h | 1 + 8 files changed, 142 insertions(+), 49 deletions(-) diff --git a/tools/libxc/xc_sr_common.h b/tools/libxc/xc_sr_common.h index 5dd51ccb15..df21b46dc7 100644 --- a/tools/libxc/xc_sr_common.h +++ b/tools/libxc/xc_sr_common.h @@ -287,6 +287,11 @@ struct xc_sr_context { struct /* x86 */ { + struct { + void *buffer; + unsigned int len; + } domain_context; + struct /* x86 PV guest. */ { /* 4 or 8; 32 or 64 bit domain */ @@ -314,7 +319,7 @@ struct xc_sr_context /* The guest pfns containing the p2m leaves */ xen_pfn_t *p2m_pfns; - /* Read-only mapping of guests shared info page */ + /* Pointer to shared_info (located in context buffer) */ shared_info_any_t *shinfo; /* p2m generation count for verifying validity of local p2m. */ diff --git a/tools/libxc/xc_sr_common_x86.c b/tools/libxc/xc_sr_common_x86.c index 011684df97..7d297b75b5 100644 --- a/tools/libxc/xc_sr_common_x86.c +++ b/tools/libxc/xc_sr_common_x86.c @@ -42,6 +42,64 @@ int handle_x86_tsc_info(struct xc_sr_context *ctx, struct xc_sr_record *rec) return 0; } +int x86_get_context(struct xc_sr_context *ctx, uint32_t mask) +{ + xc_interface *xch = ctx->xch; + int rc; + + if ( ctx->x86.domain_context.buffer ) + { + ERROR("Domain context already present"); + return -1; + } + + rc = xc_domain_getcontext(xch, ctx->domid, mask, NULL, 0); + if ( rc < 0 ) + { + PERROR("Unable to get size of domain context"); + return -1; + } + + ctx->x86.domain_context.buffer = malloc(rc); + if ( ctx->x86.domain_context.buffer == NULL ) + { + PERROR("Unable to allocate memory for domain context"); + return -1; + } + + rc = xc_domain_getcontext(xch, ctx->domid, mask, + ctx->x86.domain_context.buffer, rc); + if ( rc < 0 ) + { + PERROR("Unable to get domain context"); + return -1; + } + + ctx->x86.domain_context.len = rc; + + return 0; +} + +int x86_set_context(struct xc_sr_context *ctx, uint32_t mask) +{ + xc_interface *xch = ctx->xch; + + if ( !ctx->x86.domain_context.buffer ) + { + ERROR("Domain context not present"); + return -1; + } + + return xc_domain_setcontext(xch, ctx->domid, mask, + ctx->x86.domain_context.buffer, + ctx->x86.domain_context.len); +} + +void x86_cleanup(struct xc_sr_context *ctx) +{ + free(ctx->x86.domain_context.buffer); +} + /* * Local variables: * mode: C diff --git a/tools/libxc/xc_sr_common_x86.h b/tools/libxc/xc_sr_common_x86.h index ebc4355bd1..1746094081 100644 --- a/tools/libxc/xc_sr_common_x86.h +++ b/tools/libxc/xc_sr_common_x86.h @@ -14,6 +14,10 @@ int write_x86_tsc_info(struct xc_sr_context *ctx); */ int handle_x86_tsc_info(struct xc_sr_context *ctx, struct xc_sr_record *rec); +int x86_get_context(struct xc_sr_context *ctx, uint32_t mask); +int x86_set_context(struct xc_sr_context *ctx, uint32_t mask); +void x86_cleanup(struct xc_sr_context *ctx); + #endif /* * Local variables: diff --git a/tools/libxc/xc_sr_common_x86_pv.c b/tools/libxc/xc_sr_common_x86_pv.c index d3d425cb82..3e6f130e56 100644 --- a/tools/libxc/xc_sr_common_x86_pv.c +++ b/tools/libxc/xc_sr_common_x86_pv.c @@ -182,6 +182,58 @@ int x86_pv_map_m2p(struct xc_sr_context *ctx) return rc; } +int x86_pv_get_shinfo(struct xc_sr_context *ctx) +{ + unsigned int off = 0; + struct domain_save_descriptor *desc; + int rc; + + rc = x86_get_context(ctx, DOMAIN_SAVE_MASK(SHARED_INFO)); + if ( rc ) + return rc; + + do { + if ( ctx->x86.domain_context.len - off < sizeof(*desc) ) + { + return -1; + } + desc = ctx->x86.domain_context.buffer + off; + off += sizeof(*desc); + + switch (desc->typecode) + { + case DOMAIN_SAVE_CODE(SHARED_INFO): + { + DOMAIN_SAVE_TYPE(SHARED_INFO) *s; + + if ( ctx->x86.domain_context.len - off < sizeof(*s) ) + return -1; + + s = ctx->x86.domain_context.buffer + off; + ctx->x86.pv.shinfo = (shared_info_any_t *)s->buffer; + /* fall through */ + } + default: + off += (desc->length); + break; + } + } while ( desc->typecode != DOMAIN_SAVE_CODE(END) ); + + if ( !ctx->x86.pv.shinfo ) + return -1; + + return 0; +} + +int x86_pv_set_shinfo(struct xc_sr_context *ctx) +{ + if ( !ctx->x86.pv.shinfo ) + return -1; + + return ctx->x86.pv.shinfo ? + x86_set_context(ctx, DOMAIN_SAVE_MASK(SHARED_INFO)) : -1; +} + /* * Local variables: * mode: C diff --git a/tools/libxc/xc_sr_common_x86_pv.h b/tools/libxc/xc_sr_common_x86_pv.h index 2ed03309af..01442f48fb 100644 --- a/tools/libxc/xc_sr_common_x86_pv.h +++ b/tools/libxc/xc_sr_common_x86_pv.h @@ -97,6 +97,9 @@ int x86_pv_domain_info(struct xc_sr_context *ctx); */ int x86_pv_map_m2p(struct xc_sr_context *ctx); +int x86_pv_get_shinfo(struct xc_sr_context *ctx); +int x86_pv_set_shinfo(struct xc_sr_context *ctx); + #endif /* * Local variables: diff --git a/tools/libxc/xc_sr_restore_x86_pv.c b/tools/libxc/xc_sr_restore_x86_pv.c index 904ccc462a..4dbc7f0da5 100644 --- a/tools/libxc/xc_sr_restore_x86_pv.c +++ b/tools/libxc/xc_sr_restore_x86_pv.c @@ -864,8 +864,7 @@ static int handle_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; + int rc; const shared_info_any_t *old_shinfo = rec->data; if ( !ctx->x86.pv.restore.seen_pv_info ) @@ -878,39 +877,30 @@ static int handle_shared_info(struct xc_sr_context *ctx, { ERROR("X86_PV_SHARED_INFO record wrong size: length %u" ", expected 4096", rec->length); - goto err; + return -1; } - 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; - } + rc = x86_pv_get_shinfo(ctx); + if ( rc ) + return rc; - MEMCPY_FIELD(guest_shinfo, old_shinfo, vcpu_info, ctx->x86.pv.width); - MEMCPY_FIELD(guest_shinfo, old_shinfo, arch, ctx->x86.pv.width); + MEMCPY_FIELD(ctx->x86.pv.shinfo, old_shinfo, vcpu_info, + ctx->x86.pv.width); + MEMCPY_FIELD(ctx->x86.pv.shinfo, old_shinfo, arch, ctx->x86.pv.width); - SET_FIELD(guest_shinfo, arch.pfn_to_mfn_frame_list_list, + SET_FIELD(ctx->x86.pv.shinfo, arch.pfn_to_mfn_frame_list_list, 0, ctx->x86.pv.width); - MEMSET_ARRAY_FIELD(guest_shinfo, evtchn_pending, 0, ctx->x86.pv.width); + MEMSET_ARRAY_FIELD(ctx->x86.pv.shinfo, evtchn_pending, 0, + ctx->x86.pv.width); for ( i = 0; i < XEN_LEGACY_MAX_VCPUS; i++ ) - SET_FIELD(guest_shinfo, vcpu_info[i].evtchn_pending_sel, + SET_FIELD(ctx->x86.pv.shinfo, vcpu_info[i].evtchn_pending_sel, 0, ctx->x86.pv.width); - MEMSET_ARRAY_FIELD(guest_shinfo, evtchn_mask, 0xff, ctx->x86.pv.width); - - rc = 0; + MEMSET_ARRAY_FIELD(ctx->x86.pv.shinfo, evtchn_mask, 0xff, + ctx->x86.pv.width); - err: - if ( guest_shinfo ) - munmap(guest_shinfo, PAGE_SIZE); - - return rc; + return x86_pv_set_shinfo(ctx); } /* restore_ops function. */ diff --git a/tools/libxc/xc_sr_save_x86_pv.c b/tools/libxc/xc_sr_save_x86_pv.c index f3ccf5bb4b..7c4fcffa92 100644 --- a/tools/libxc/xc_sr_save_x86_pv.c +++ b/tools/libxc/xc_sr_save_x86_pv.c @@ -9,25 +9,6 @@ static inline bool is_canonical_address(xen_vaddr_t vaddr) return ((int64_t)vaddr >> 47) == ((int64_t)vaddr >> 63); } -/* - * Maps the guests shared info page. - */ -static int map_shinfo(struct xc_sr_context *ctx) -{ - xc_interface *xch = ctx->xch; - - ctx->x86.pv.shinfo = xc_map_foreign_range( - xch, ctx->domid, PAGE_SIZE, PROT_READ, ctx->dominfo.shared_info_frame); - if ( !ctx->x86.pv.shinfo ) - { - PERROR("Failed to map shared info frame at mfn %#lx", - ctx->dominfo.shared_info_frame); - return -1; - } - - return 0; -} - /* * Copy a list of mfns from a guest, accounting for differences between guest * and toolstack width. Can fail if truncation would occur. @@ -1041,7 +1022,7 @@ static int x86_pv_setup(struct xc_sr_context *ctx) if ( rc ) return rc; - rc = map_shinfo(ctx); + rc = x86_pv_get_shinfo(ctx); if ( rc ) return rc; @@ -1112,12 +1093,11 @@ static int x86_pv_cleanup(struct xc_sr_context *ctx) if ( ctx->x86.pv.p2m ) munmap(ctx->x86.pv.p2m, ctx->x86.pv.p2m_frames * PAGE_SIZE); - if ( ctx->x86.pv.shinfo ) - munmap(ctx->x86.pv.shinfo, PAGE_SIZE); - if ( ctx->x86.pv.m2p ) munmap(ctx->x86.pv.m2p, ctx->x86.pv.nr_m2p_frames * PAGE_SIZE); + x86_cleanup(ctx); + return 0; } diff --git a/tools/libxc/xg_save_restore.h b/tools/libxc/xg_save_restore.h index 303081df0d..296b523963 100644 --- a/tools/libxc/xg_save_restore.h +++ b/tools/libxc/xg_save_restore.h @@ -19,6 +19,7 @@ #include #include +#include /* ** We process save/restore/migrate in batches of pages; the below