From patchwork Mon Oct 10 00:34:17 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haozhong Zhang X-Patchwork-Id: 9368783 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 034736048F for ; Mon, 10 Oct 2016 00:35:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EB4BA288B0 for ; Mon, 10 Oct 2016 00:35:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DFE8C28ADE; Mon, 10 Oct 2016 00:35:38 +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 0D528288BA for ; Mon, 10 Oct 2016 00:35:38 +0000 (UTC) Received: from localhost ([::1]:46592 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1btOZ7-0005w0-5X for patchwork-qemu-devel@patchwork.kernel.org; Sun, 09 Oct 2016 20:35:37 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50978) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1btOYV-0005sh-P1 for qemu-devel@nongnu.org; Sun, 09 Oct 2016 20:35:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1btOYR-00037N-EP for qemu-devel@nongnu.org; Sun, 09 Oct 2016 20:34:58 -0400 Received: from mga01.intel.com ([192.55.52.88]:21712) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1btOYR-00036w-39 for qemu-devel@nongnu.org; Sun, 09 Oct 2016 20:34:55 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga101.fm.intel.com with ESMTP; 09 Oct 2016 17:34:54 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos; i="5.31,469,1473145200"; d="scan'208"; a="1042480516" Received: from hz-desktop.sh.intel.com (HELO localhost) ([10.239.159.148]) by orsmga001.jf.intel.com with ESMTP; 09 Oct 2016 17:34:54 -0700 From: Haozhong Zhang To: qemu-devel@nongnu.org, xen-devel@lists.xensource.com Date: Mon, 10 Oct 2016 08:34:17 +0800 Message-Id: <20161010003423.4333-3-haozhong.zhang@intel.com> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20161010003423.4333-1-haozhong.zhang@intel.com> References: <20161010003423.4333-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.88 Subject: [Qemu-devel] [RFC QEMU PATCH 2/8] xen-hvm: add a function to copy ACPI to guest 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: Anthony Perard , Haozhong Zhang , Stefano Stabellini , Xiao Guangrong , Konrad Rzeszutek Wilk Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP xen_acpi_copy_to_guest() will be used later to copy NVDIMM ACPI to guest. Signed-off-by: Haozhong Zhang --- Cc: Stefano Stabellini Cc: Anthony Perard Cc: xen-devel@lists.xensource.com --- include/hw/xen/xen.h | 6 ++ xen-hvm.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+) diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h index a8f3afb..79273da 100644 --- a/include/hw/xen/xen.h +++ b/include/hw/xen/xen.h @@ -47,4 +47,10 @@ void xen_modified_memory(ram_addr_t start, ram_addr_t length); void xen_register_framebuffer(struct MemoryRegion *mr); +#define XEN_ACPI_TABLE 0 +#define XEN_ACPI_NSDEV 1 + +int xen_acpi_copy_to_guest(const char *name, const char *data, size_t length, + int type); + #endif /* QEMU_HW_XEN_H */ diff --git a/xen-hvm.c b/xen-hvm.c index 2f348ed..168a9ec 100644 --- a/xen-hvm.c +++ b/xen-hvm.c @@ -21,6 +21,7 @@ #include "sysemu/char.h" #include "qemu/error-report.h" #include "qemu/range.h" +#include "qemu/cutils.h" #include "sysemu/xen-mapcache.h" #include "trace.h" #include "exec/address-spaces.h" @@ -39,6 +40,10 @@ do { } while (0) #endif +#define HVM_XS_DM_ACPI_ROOT "/hvmloader/dm-acpi" +#define HVM_XS_DM_ACPI_ADDRESS HVM_XS_DM_ACPI_ROOT"/address" +#define HVM_XS_DM_ACPI_LENGTH HVM_XS_DM_ACPI_ROOT"/length" + static MemoryRegion ram_memory, ram_640k, ram_lo, ram_hi; static MemoryRegion *framebuffer; static bool xen_in_migration; @@ -87,6 +92,14 @@ typedef struct XenPhysmap { QLIST_ENTRY(XenPhysmap) list; } XenPhysmap; +typedef struct XenAcpiBuf { + ram_addr_t base; + ram_addr_t length; + ram_addr_t used; +} XenAcpiBuf; + +static XenAcpiBuf *guest_acpi_buf; + typedef struct XenIOState { ioservid_t ioservid; shared_iopage_t *shared_page; @@ -111,6 +124,8 @@ typedef struct XenIOState { hwaddr free_phys_offset; const XenPhysmap *log_for_dirtybit; + XenAcpiBuf acpi_buf; + Notifier exit; Notifier suspend; Notifier wakeup; @@ -1181,6 +1196,66 @@ static void xen_wakeup_notifier(Notifier *notifier, void *data) xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 0); } +static int guest_acpi_buf_init(XenIOState *state) +{ + char path[80], *value; + unsigned int len; + + guest_acpi_buf = &state->acpi_buf; + + snprintf(path, sizeof(path), + "/local/domain/%d"HVM_XS_DM_ACPI_ADDRESS, xen_domid); + value = xs_read(state->xenstore, 0, path, &len); + if (!value) { + return -EINVAL; + } + if (qemu_strtoull(value, NULL, 16, &guest_acpi_buf->base)) { + return -EINVAL; + } + + snprintf(path, sizeof(path), + "/local/domain/%d"HVM_XS_DM_ACPI_LENGTH, xen_domid); + value = xs_read(state->xenstore, 0, path, &len); + if (!value) { + return -EINVAL; + } + if (qemu_strtoull(value, NULL, 16, &guest_acpi_buf->length)) { + return -EINVAL; + } + + guest_acpi_buf->used = 0; + + return 0; +} + +static ram_addr_t guest_acpi_buf_alloc(size_t length) +{ + ram_addr_t addr; + + if (guest_acpi_buf->length - guest_acpi_buf->used < length) { + return 0; + } + + addr = guest_acpi_buf->base + guest_acpi_buf->used; + guest_acpi_buf->used += length; + + return addr; +} + +static int xen_acpi_needed(PCMachineState *pcms) +{ + return 0; +} + +static int xen_acpi_init(PCMachineState *pcms, XenIOState *state) +{ + if (!xen_acpi_needed(pcms)) { + return 0; + } + + return guest_acpi_buf_init(state); +} + void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory) { int i, rc; @@ -1316,6 +1391,13 @@ void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory) } xen_be_register_common(); xen_read_physmap(state); + + /* Initialize ACPI */ + if (xen_acpi_init(pcms, state)) { + error_report("failed to initialize xen ACPI"); + goto err; + } + return; err: @@ -1392,3 +1474,101 @@ void qmp_xen_set_global_dirty_log(bool enable, Error **errp) memory_global_dirty_log_stop(); } } + +static int xs_write_guest_acpi_blob_key(const char *name, + const char *key, const char *value) +{ + XenIOState *state = container_of(guest_acpi_buf, XenIOState, acpi_buf); + char path[80]; + + snprintf(path, sizeof(path), + "/local/domain/%d"HVM_XS_DM_ACPI_ROOT"/%s/%s", + xen_domid, name, key); + 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 char *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 char *data, size_t length, + int type) +{ + char value[21]; + ram_addr_t buf_addr; + int rc; + + if (type != XEN_ACPI_TABLE && type != XEN_ACPI_NSDEV) { + return -EINVAL; + } + + buf_addr = guest_acpi_buf_alloc(length); + if (!buf_addr) { + return -ENOMEM; + } + if (xen_memcpy_to_guest(buf_addr, data, length) != length) { + return -EIO; + } + + snprintf(value, sizeof(value), "%d", type); + rc = xs_write_guest_acpi_blob_key(name, "type", value); + if (rc) { + return rc; + } + + snprintf(value, sizeof(value), "%"PRIu64, buf_addr - guest_acpi_buf->base); + rc = xs_write_guest_acpi_blob_key(name, "offset", value); + if (rc) { + return rc; + } + + snprintf(value, sizeof(value), "%"PRIu64, length); + rc = xs_write_guest_acpi_blob_key(name, "length", value); + if (rc) { + return rc; + } + + return 0; +}