From patchwork Mon Sep 11 04:41:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haozhong Zhang X-Patchwork-Id: 9946663 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 527E0603F4 for ; Mon, 11 Sep 2017 04:48:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4801128AD7 for ; Mon, 11 Sep 2017 04:48:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3CD2F28ADD; Mon, 11 Sep 2017 04:48:40 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 9D69A28AD7 for ; Mon, 11 Sep 2017 04:48:39 +0000 (UTC) Received: from localhost ([::1]:55376 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1drGeE-0005Im-Rb for patchwork-qemu-devel@patchwork.kernel.org; Mon, 11 Sep 2017 00:48:38 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56292) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1drGYE-0000xs-Sd for qemu-devel@nongnu.org; Mon, 11 Sep 2017 00:42:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1drGYA-0004Ze-U9 for qemu-devel@nongnu.org; Mon, 11 Sep 2017 00:42:26 -0400 Received: from mga04.intel.com ([192.55.52.120]:23374) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1drGYA-0004UV-KI for qemu-devel@nongnu.org; Mon, 11 Sep 2017 00:42:22 -0400 Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 10 Sep 2017 21:42:22 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos; i="5.42,376,1500966000"; d="scan'208"; a="1217079145" Received: from hz-desktop.sh.intel.com (HELO localhost) ([10.239.159.142]) by fmsmga002.fm.intel.com with ESMTP; 10 Sep 2017 21:42:20 -0700 From: Haozhong Zhang To: qemu-devel@nongnu.org, xen-devel@lists.xen.org Date: Mon, 11 Sep 2017 12:41:53 +0800 Message-Id: <20170911044157.15403-7-haozhong.zhang@intel.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170911044157.15403-1-haozhong.zhang@intel.com> References: <20170911044157.15403-1-haozhong.zhang@intel.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 192.55.52.120 Subject: [Qemu-devel] [RFC QEMU PATCH v3 06/10] hw/xen-hvm: add function to copy ACPI into guest memory X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Haozhong Zhang , Stefano Stabellini , Eduardo Habkost , Konrad Rzeszutek Wilk , "Michael S. Tsirkin" , Paolo Bonzini , Anthony Perard , Chao Peng , Dan Williams , Richard Henderson Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Xen relies on QEMU to build guest NFIT and NVDIMM namespace devices, and implements an interface to allow QEMU to copy its ACPI into guest memory. This commit implements the QEMU side support. The location of guest memory that can receive QEMU ACPI can be found from XenStore entries /local/domain/$dom_id/hvmloader/dm-acpi/{address,length}, which have been handled by previous commit. QEMU ACPI copied to guest is organized in blobs. For each blob, QEMU creates following XenStore entries under /local/domain/$dom_id/hvmloader/dm-acpi/$name to indicate its type, location in above guest memory region and size. - type the type of the passed ACPI, which can be the following values. * XEN_DM_ACPI_BLOB_TYPE_TABLE (0) indicates it's a complete ACPI table, and its signature is indicated by $name in the XenStore path. * XEN_DM_ACPI_BLOB_TYPE_NSDEV (1) indicates it's the body of a namespace device, and its device name is indicated by $name in the XenStore path. - offset offset in byte from the beginning of above guest memory region - length size in byte of the copied ACPI Signed-off-by: Haozhong Zhang --- Cc: Stefano Stabellini Cc: Anthony Perard Cc: "Michael S. Tsirkin" Cc: Paolo Bonzini Cc: Richard Henderson Cc: Eduardo Habkost --- hw/i386/xen/xen-hvm.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/hw/xen/xen.h | 18 ++++++++ stubs/xen-hvm.c | 6 +++ 3 files changed, 137 insertions(+) diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c index ae895aaf03..b74c4ffb9c 100644 --- a/hw/i386/xen/xen-hvm.c +++ b/hw/i386/xen/xen-hvm.c @@ -1286,6 +1286,20 @@ static int dm_acpi_buf_init(XenIOState *state) return 0; } +static ram_addr_t dm_acpi_buf_alloc(size_t length) +{ + ram_addr_t addr; + + if (dm_acpi_buf->length - dm_acpi_buf->used < length) { + return 0; + } + + addr = dm_acpi_buf->base + dm_acpi_buf->used; + dm_acpi_buf->used += length; + + return addr; +} + static int xen_dm_acpi_init(PCMachineState *pcms, XenIOState *state) { if (!xen_dm_acpi_needed(pcms)) { @@ -1295,6 +1309,105 @@ static int xen_dm_acpi_init(PCMachineState *pcms, XenIOState *state) return dm_acpi_buf_init(state); } +static int xs_write_dm_acpi_blob_entry(const char *name, + const char *entry, const char *value) +{ + XenIOState *state = container_of(dm_acpi_buf, XenIOState, dm_acpi_buf); + char path[80]; + + snprintf(path, sizeof(path), + "/local/domain/%d"HVM_XS_DM_ACPI_ROOT"/%s/%s", + xen_domid, name, entry); + if (!xs_write(state->xenstore, 0, path, value, strlen(value))) { + return -EIO; + } + + return 0; +} + +static size_t xen_memcpy_to_guest(ram_addr_t gpa, + const void *buf, size_t length) +{ + size_t copied = 0, size; + ram_addr_t s, e, offset, cur = gpa; + xen_pfn_t cur_pfn; + void *page; + + if (!buf || !length) { + return 0; + } + + s = gpa & TARGET_PAGE_MASK; + e = gpa + length; + if (e < s) { + return 0; + } + + while (cur < e) { + cur_pfn = cur >> TARGET_PAGE_BITS; + offset = cur - (cur_pfn << TARGET_PAGE_BITS); + size = (length >= TARGET_PAGE_SIZE - offset) ? + TARGET_PAGE_SIZE - offset : length; + + page = xenforeignmemory_map(xen_fmem, xen_domid, PROT_READ | PROT_WRITE, + 1, &cur_pfn, NULL); + if (!page) { + break; + } + + memcpy(page + offset, buf, size); + xenforeignmemory_unmap(xen_fmem, page, 1); + + copied += size; + buf += size; + cur += size; + length -= size; + } + + return copied; +} + +int xen_acpi_copy_to_guest(const char *name, const void *blob, size_t length, + int type) +{ + char value[21]; + ram_addr_t buf_addr; + int rc; + + if (type != XEN_DM_ACPI_BLOB_TYPE_TABLE && + type != XEN_DM_ACPI_BLOB_TYPE_NSDEV) { + return -EINVAL; + } + + buf_addr = dm_acpi_buf_alloc(length); + if (!buf_addr) { + return -ENOMEM; + } + if (xen_memcpy_to_guest(buf_addr, blob, length) != length) { + return -EIO; + } + + snprintf(value, sizeof(value), "%d", type); + rc = xs_write_dm_acpi_blob_entry(name, "type", value); + if (rc) { + return rc; + } + + snprintf(value, sizeof(value), "%"PRIu64, buf_addr - dm_acpi_buf->base); + rc = xs_write_dm_acpi_blob_entry(name, "offset", value); + if (rc) { + return rc; + } + + snprintf(value, sizeof(value), "%"PRIu64, length); + rc = xs_write_dm_acpi_blob_entry(name, "length", value); + if (rc) { + return rc; + } + + return 0; +} + void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory) { int i, rc; diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h index 7efcdaa8fe..38dcd1a7d4 100644 --- a/include/hw/xen/xen.h +++ b/include/hw/xen/xen.h @@ -48,4 +48,22 @@ void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length); void xen_register_framebuffer(struct MemoryRegion *mr); +/* + * Copy an ACPI blob from QEMU to HVM guest. + * + * Parameters: + * name: a unique name of the data blob; for XEN_DM_ACPI_BLOB_TYPE_NSDEV, + * name should be less then 4 characters + * blob: the ACPI blob to be copied + * length: the length in bytes of the ACPI blob + * type: the type of content in the ACPI blob, one of XEN_DM_ACPI_BLOB_TYPE_* + * + * Return: + * 0 on success; a non-zero error code on failures. + */ +#define XEN_DM_ACPI_BLOB_TYPE_TABLE 0 /* ACPI table */ +#define XEN_DM_ACPI_BLOB_TYPE_NSDEV 1 /* AML of ACPI namespace device */ +int xen_acpi_copy_to_guest(const char *name, const void *blob, size_t length, + int type); + #endif /* QEMU_HW_XEN_H */ diff --git a/stubs/xen-hvm.c b/stubs/xen-hvm.c index 3ca6c51b21..58889ae0fb 100644 --- a/stubs/xen-hvm.c +++ b/stubs/xen-hvm.c @@ -61,3 +61,9 @@ void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory) void qmp_xen_set_global_dirty_log(bool enable, Error **errp) { } + +int xen_acpi_copy_to_guest(const char *name, const void *blob, size_t length, + int type) +{ + return -1; +}