From patchwork Fri Feb 17 10:27:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 9579545 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 9BEDA600C5 for ; Fri, 17 Feb 2017 10:30:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 85B5F2862B for ; Fri, 17 Feb 2017 10:30:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7A26D286AB; Fri, 17 Feb 2017 10:30:41 +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=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id EBB192862B for ; Fri, 17 Feb 2017 10:30:38 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cefl1-00088x-ML; Fri, 17 Feb 2017 10:27:19 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cefl0-00086t-5s for xen-devel@lists.xenproject.org; Fri, 17 Feb 2017 10:27:18 +0000 Received: from [85.158.137.68] by server-7.bemta-3.messagelabs.com id 19/45-23854-500D6A85; Fri, 17 Feb 2017 10:27:17 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprKIsWRWlGSWpSXmKPExsXitHRDpC7LhWU RBu0TuC2+b5nM5MDocfjDFZYAxijWzLyk/IoE1oxpW56zFfw8xVwxZ9o1tgbGljtMXYycHBIC /hInJt5gBrHZBHQkpj69xNrFyMEhIqAicXuvAUiYWaBY4u//brASYYEwif9T5rOA2CwCqhI9H zvAxvAKuEt0bnrGDjFSTuL88Z9g9ZwCHhIXd75m62Jk5xACqjmYDhIVAhq+fuosNohOQYmTM5 +wQGySkDj44gXzBEbeWUhSs5CkFjAyrWJUL04tKkst0jXTSyrKTM8oyU3MzNE1NDDWy00tLk5 MT81JTCrWS87P3cQIDJx6BgbGHYxX2pwPMUpyMCmJ8i6atixCiC8pP6UyI7E4I76oNCe1+BCj DAeHkgTvrbNAOcGi1PTUirTMHGAIw6QlOHiURCDSvMUFibnFmekQqVOMxhynbpx+ycSxb/uZl 0xCLHn5ealS4rye54BKBUBKM0rz4AbBYusSo6yUMC8jAwODEE9BalFuZgmq/CtGcQ5GJWHeOy ALeTLzSuD2vQI6hQnolM6IpSCnlCQipKQaGBNdFsrsMQu315f/1JFevbCO1Uu7TIeVs7NdMsf uWbV25oFjug+38NfEyPbf4O6uuyn6urpk0h2V5tv8tz48t9vH92VCXSzvpAjXugUtdnM7tyut KHtsWv10eZZ/lXFY2IUFc3iv1m3uFdx74JeHYb3uqp4fL9Pihc/P3rn52lq7hasa1E8tVmIpz kg01GIuKk4EAMrCQDqoAgAA X-Env-Sender: prvs=214e09179=Paul.Durrant@citrix.com X-Msg-Ref: server-16.tower-31.messagelabs.com!1487327234!78488007!1 X-Originating-IP: [66.165.176.89] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n, received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 9.2.3; banners=-,-,- X-VirusChecked: Checked Received: (qmail 33419 invoked from network); 17 Feb 2017 10:27:15 -0000 Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89) by server-16.tower-31.messagelabs.com with RC4-SHA encrypted SMTP; 17 Feb 2017 10:27:15 -0000 X-IronPort-AV: E=Sophos;i="5.35,171,1484006400"; d="scan'208";a="407699465" From: Paul Durrant To: Date: Fri, 17 Feb 2017 10:27:07 +0000 Message-ID: <1487327229-14641-2-git-send-email-paul.durrant@citrix.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1487327229-14641-1-git-send-email-paul.durrant@citrix.com> References: <1487327229-14641-1-git-send-email-paul.durrant@citrix.com> MIME-Version: 1.0 Cc: Wei Liu , Paul Durrant , Ian Jackson Subject: [Xen-devel] [PATCH 2/4] tools/libxendevicemodel: extract functions and add a compat layer X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP This patch extracts all functions resulting in a dm_op hypercall from libxenctrl and moves them into libxendevicemodel. It also adds a compat layer into libxenctrl, which can be selected by defining XC_WANT_COMPAT_DEVICEMODEL_API to 1 before including xenctrl.h. With this patch the core of libxendevicemodel still uses libxencall to issue the dm_op hypercalls, but this is done by calling through code that can be modified on a per-OS basis. A subsequent patch will add a Linux- specific variant. NOTE: After applying this patch the compat layer will need to be enabled in qemu-xen-traditional by applying patch [1]. [1] http://xenbits.xen.org/gitweb/?p=people/pauldu/qemu-xen-traditional.git;a=commit;h=82d15bd7 Signed-off-by: Paul Durrant --- Cc: Ian Jackson Cc: Wei Liu --- tools/Makefile | 1 + tools/Rules.mk | 2 +- tools/libs/devicemodel/Makefile | 10 +- tools/libs/devicemodel/compat.c | 45 +++ tools/libs/devicemodel/core.c | 435 ++++++++++++++++++++++++ tools/libs/devicemodel/include/xendevicemodel.h | 258 ++++++++++++++ tools/libs/devicemodel/libxendevicemodel.map | 16 + tools/libs/devicemodel/private.h | 19 ++ tools/libxc/Makefile | 1 + tools/libxc/include/xenctrl.h | 197 ----------- tools/libxc/include/xenctrl_compat.h | 47 +++ tools/libxc/xc_devicemodel_compat.c | 139 ++++++++ tools/libxc/xc_domain.c | 201 ----------- tools/libxc/xc_misc.c | 154 --------- tools/libxc/xc_private.c | 73 ---- 15 files changed, 970 insertions(+), 628 deletions(-) create mode 100644 tools/libs/devicemodel/compat.c create mode 100644 tools/libxc/xc_devicemodel_compat.c diff --git a/tools/Makefile b/tools/Makefile index 0890cc9..e6c0cc5 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -262,6 +262,7 @@ subdir-all-qemu-xen-dir: qemu-xen-dir-find --extra-cflags="-DXC_WANT_COMPAT_EVTCHN_API=1 \ -DXC_WANT_COMPAT_GNTTAB_API=1 \ -DXC_WANT_COMPAT_MAP_FOREIGN_API=1 \ + -DXC_WANT_COMPAT_DEVICEMODEL_API=1 \ -I$(XEN_ROOT)/tools/include \ -I$(XEN_ROOT)/tools/libs/toollog/include \ -I$(XEN_ROOT)/tools/libs/evtchn/include \ diff --git a/tools/Rules.mk b/tools/Rules.mk index e3415f0..8ea3901 100644 --- a/tools/Rules.mk +++ b/tools/Rules.mk @@ -119,7 +119,7 @@ LDLIBS_libxenforeignmemory = $(XEN_LIBXENFOREIGNMEMORY)/libxenforeignmemory$(lib SHLIB_libxenforeignmemory = -Wl,-rpath-link=$(XEN_LIBXENFOREIGNMEMORY) CFLAGS_libxendevicemodel = -I$(XEN_LIBXENDEVICEMODEL)/include $(CFLAGS_xeninclude) -SHDEPS_libxendevicemodel = $(SHLIB_libxentoollog) +SHDEPS_libxendevicemodel = $(SHLIB_libxentoollog) $(SHLIB_xencall) LDLIBS_libxendevicemodel = $(XEN_LIBXENDEVICEMODEL)/libxendevicemodel$(libextension) SHLIB_libxendevicemodel = -Wl,-rpath-link=$(XEN_LIBXENDEVICEMODEL) diff --git a/tools/libs/devicemodel/Makefile b/tools/libs/devicemodel/Makefile index 4f1e616..b87bf84 100644 --- a/tools/libs/devicemodel/Makefile +++ b/tools/libs/devicemodel/Makefile @@ -8,8 +8,14 @@ SHLIB_LDFLAGS += -Wl,--version-script=libxendevicemodel.map CFLAGS += -Werror -Wmissing-prototypes CFLAGS += -I./include $(CFLAGS_xeninclude) CFLAGS += $(CFLAGS_libxentoollog) - -SRCS-y += core.c +CFLAGS += $(CFLAGS_libxencall) + +SRCS-y += core.c +SRCS-$(CONFIG_Linux) += compat.c +SRCS-$(CONFIG_FreeBSD) += compat.c +SRCS-$(CONFIG_SunOS) += compat.c +SRCS-$(CONFIG_NetBSD) += compat.c +SRCS-$(CONFIG_MiniOS) += compat.c LIB_OBJS := $(patsubst %.c,%.o,$(SRCS-y)) PIC_OBJS := $(patsubst %.c,%.opic,$(SRCS-y)) diff --git a/tools/libs/devicemodel/compat.c b/tools/libs/devicemodel/compat.c new file mode 100644 index 0000000..245e907 --- /dev/null +++ b/tools/libs/devicemodel/compat.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017 Citrix Systems Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; If not, see . + */ + +#include "private.h" + +int osdep_xendevicemodel_open(xendevicemodel_handle *dmod) +{ + return 0; +} + +int osdep_xendevicemodel_close(xendevicemodel_handle *dmod) +{ + return 0; +} + +int osdep_xendevicemodel_op(xendevicemodel_handle *dmod, + domid_t domid, unsigned int nr_bufs, + struct xendevicemodel_buf bufs[]) +{ + return xendevicemodel_xcall(dmod, domid, nr_bufs, bufs); +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libs/devicemodel/core.c b/tools/libs/devicemodel/core.c index ec18142..7e9f893 100644 --- a/tools/libs/devicemodel/core.c +++ b/tools/libs/devicemodel/core.c @@ -16,6 +16,8 @@ */ #include +#include +#include #include "private.h" @@ -23,6 +25,7 @@ xendevicemodel_handle *xendevicemodel_open(xentoollog_logger *logger, unsigned open_flags) { xendevicemodel_handle *dmod = malloc(sizeof(*dmod)); + int rc; if (!dmod) return NULL; @@ -39,6 +42,14 @@ xendevicemodel_handle *xendevicemodel_open(xentoollog_logger *logger, goto err; } + dmod->xcall = xencall_open(dmod->logger, 0); + if (!dmod->xcall) + goto err; + + rc = osdep_xendevicemodel_open(dmod); + if (rc) + goto err; + return dmod; err: @@ -49,14 +60,438 @@ err: int xendevicemodel_close(xendevicemodel_handle *dmod) { + int rc; + if (!dmod) return 0; + rc = osdep_xendevicemodel_close(dmod); + + xencall_close(dmod->xcall); xtl_logger_destroy(dmod->logger_tofree); free(dmod); + return rc; +} + +int xendevicemodel_xcall(xendevicemodel_handle *dmod, + domid_t domid, unsigned int nr_bufs, + struct xendevicemodel_buf bufs[]) +{ + int ret = -1; + void **xcall_bufs; + xen_dm_op_buf_t *op_bufs; + unsigned int i; + + xcall_bufs = calloc(nr_bufs, sizeof(*xcall_bufs)); + if (xcall_bufs == NULL) + goto out; + + op_bufs = xencall_alloc_buffer(dmod->xcall, sizeof(xen_dm_op_buf_t) * + nr_bufs); + if (op_bufs == NULL) + goto out; + + for (i = 0; i < nr_bufs; i++) { + xcall_bufs[i] = xencall_alloc_buffer(dmod->xcall, bufs[i].size); + if ( xcall_bufs[i] == NULL ) + goto out; + + memcpy(xcall_bufs[i], bufs[i].ptr, bufs[i].size); + set_xen_guest_handle_raw(op_bufs[i].h, xcall_bufs[i]); + + op_bufs[i].size = bufs[i].size; + } + + ret = xencall3(dmod->xcall, __HYPERVISOR_dm_op, + domid, nr_bufs, (unsigned long)op_bufs); + if (ret < 0) + goto out; + + for (i = 0; i < nr_bufs; i++) + memcpy(bufs[i].ptr, xcall_bufs[i], bufs[i].size); + +out: + if (xcall_bufs) + for (i = 0; i < nr_bufs; i++) + xencall_free_buffer(dmod->xcall, xcall_bufs[i]); + + xencall_free_buffer(dmod->xcall, op_bufs); + free(xcall_bufs); + + return ret; +} + +static int xendevicemodel_op( + xendevicemodel_handle *dmod, domid_t domid, unsigned int nr_bufs, ...) +{ + struct xendevicemodel_buf *bufs; + va_list args; + unsigned int i; + int ret; + + bufs = calloc(nr_bufs, sizeof(*bufs)); + if (!bufs) + return -1; + + va_start(args, nr_bufs); + for (i = 0; i < nr_bufs; i++) { + bufs[i].ptr = va_arg(args, void *); + bufs[i].size = va_arg(args, size_t); + } + va_end(args); + + ret = osdep_xendevicemodel_op(dmod, domid, nr_bufs, bufs); + + free(bufs); + + return ret; +} + +int xendevicemodel_create_ioreq_server( + xendevicemodel_handle *dmod, domid_t domid, int handle_bufioreq, + ioservid_t *id) +{ + struct xen_dm_op op; + struct xen_dm_op_create_ioreq_server *data; + int rc; + + memset(&op, 0, sizeof(op)); + + op.op = XEN_DMOP_create_ioreq_server; + data = &op.u.create_ioreq_server; + + data->handle_bufioreq = handle_bufioreq; + + rc = xendevicemodel_op(dmod, domid, 1, &op, sizeof(op)); + if (rc) + return rc; + + *id = data->id; + + return 0; +} + +int xendevicemodel_get_ioreq_server_info( + xendevicemodel_handle *dmod, domid_t domid, ioservid_t id, + xen_pfn_t *ioreq_pfn, xen_pfn_t *bufioreq_pfn, + evtchn_port_t *bufioreq_port) +{ + struct xen_dm_op op; + struct xen_dm_op_get_ioreq_server_info *data; + int rc; + + memset(&op, 0, sizeof(op)); + + op.op = XEN_DMOP_get_ioreq_server_info; + data = &op.u.get_ioreq_server_info; + + data->id = id; + + rc = xendevicemodel_op(dmod, domid, 1, &op, sizeof(op)); + if (rc) + return rc; + + if (ioreq_pfn) + *ioreq_pfn = data->ioreq_pfn; + + if (bufioreq_pfn) + *bufioreq_pfn = data->bufioreq_pfn; + + if (bufioreq_port) + *bufioreq_port = data->bufioreq_port; + return 0; } +int xendevicemodel_map_io_range_to_ioreq_server( + xendevicemodel_handle *dmod, domid_t domid, ioservid_t id, int is_mmio, + uint64_t start, uint64_t end) +{ + struct xen_dm_op op; + struct xen_dm_op_ioreq_server_range *data; + + memset(&op, 0, sizeof(op)); + + op.op = XEN_DMOP_map_io_range_to_ioreq_server; + data = &op.u.map_io_range_to_ioreq_server; + + data->id = id; + data->type = is_mmio ? XEN_DMOP_IO_RANGE_MEMORY : XEN_DMOP_IO_RANGE_PORT; + data->start = start; + data->end = end; + + return xendevicemodel_op(dmod, domid, 1, &op, sizeof(op)); +} + +int xendevicemodel_unmap_io_range_from_ioreq_server( + xendevicemodel_handle *dmod, domid_t domid, ioservid_t id, int is_mmio, + uint64_t start, uint64_t end) +{ + struct xen_dm_op op; + struct xen_dm_op_ioreq_server_range *data; + + memset(&op, 0, sizeof(op)); + + op.op = XEN_DMOP_unmap_io_range_from_ioreq_server; + data = &op.u.unmap_io_range_from_ioreq_server; + + data->id = id; + data->type = is_mmio ? XEN_DMOP_IO_RANGE_MEMORY : XEN_DMOP_IO_RANGE_PORT; + data->start = start; + data->end = end; + + return xendevicemodel_op(dmod, domid, 1, &op, sizeof(op)); +} + +int xendevicemodel_map_pcidev_to_ioreq_server( + xendevicemodel_handle *dmod, domid_t domid, ioservid_t id, + uint16_t segment, uint8_t bus, uint8_t device, uint8_t function) +{ + struct xen_dm_op op; + struct xen_dm_op_ioreq_server_range *data; + + if (device > 0x1f || function > 0x7) { + errno = EINVAL; + return -1; + } + + memset(&op, 0, sizeof(op)); + + op.op = XEN_DMOP_map_io_range_to_ioreq_server; + data = &op.u.map_io_range_to_ioreq_server; + + data->id = id; + data->type = XEN_DMOP_IO_RANGE_PCI; + + /* + * The underlying hypercall will deal with ranges of PCI SBDF + * but, for simplicity, the API only uses singletons. + */ + data->start = data->end = XEN_DMOP_PCI_SBDF((uint64_t)segment, + (uint64_t)bus, + (uint64_t)device, + (uint64_t)function); + + return xendevicemodel_op(dmod, domid, 1, &op, sizeof(op)); +} + +int xendevicemodel_unmap_pcidev_from_ioreq_server( + xendevicemodel_handle *dmod, domid_t domid, ioservid_t id, + uint16_t segment, uint8_t bus, uint8_t device, uint8_t function) +{ + struct xen_dm_op op; + struct xen_dm_op_ioreq_server_range *data; + + if (device > 0x1f || function > 0x7) { + errno = EINVAL; + return -1; + } + + memset(&op, 0, sizeof(op)); + + op.op = XEN_DMOP_unmap_io_range_from_ioreq_server; + data = &op.u.unmap_io_range_from_ioreq_server; + + data->id = id; + data->type = XEN_DMOP_IO_RANGE_PCI; + + /* + * The underlying hypercall will deal with ranges of PCI SBDF + * but, for simplicity, the API only uses singletons. + */ + data->start = data->end = XEN_DMOP_PCI_SBDF((uint64_t)segment, + (uint64_t)bus, + (uint64_t)device, + (uint64_t)function); + + return xendevicemodel_op(dmod, domid, 1, &op, sizeof(op)); +} + +int xendevicemodel_destroy_ioreq_server( + xendevicemodel_handle *dmod, domid_t domid, ioservid_t id) +{ + struct xen_dm_op op; + struct xen_dm_op_destroy_ioreq_server *data; + + memset(&op, 0, sizeof(op)); + + op.op = XEN_DMOP_destroy_ioreq_server; + data = &op.u.destroy_ioreq_server; + + data->id = id; + + return xendevicemodel_op(dmod, domid, 1, &op, sizeof(op)); +} + +int xendevicemodel_set_ioreq_server_state( + xendevicemodel_handle *dmod, domid_t domid, ioservid_t id, int enabled) +{ + struct xen_dm_op op; + struct xen_dm_op_set_ioreq_server_state *data; + + memset(&op, 0, sizeof(op)); + + op.op = XEN_DMOP_set_ioreq_server_state; + data = &op.u.set_ioreq_server_state; + + data->id = id; + data->enabled = !!enabled; + + return xendevicemodel_op(dmod, domid, 1, &op, sizeof(op)); +} + +int xendevicemodel_set_pci_intx_level( + xendevicemodel_handle *dmod, domid_t domid, uint16_t segment, + uint8_t bus, uint8_t device, uint8_t intx, unsigned int level) +{ + struct xen_dm_op op; + struct xen_dm_op_set_pci_intx_level *data; + + memset(&op, 0, sizeof(op)); + + op.op = XEN_DMOP_set_pci_intx_level; + data = &op.u.set_pci_intx_level; + + data->domain = segment; + data->bus = bus; + data->device = device; + data->intx = intx; + data->level = level; + + return xendevicemodel_op(dmod, domid, 1, &op, sizeof(op)); +} + +int xendevicemodel_set_isa_irq_level( + xendevicemodel_handle *dmod, domid_t domid, uint8_t irq, + unsigned int level) +{ + struct xen_dm_op op; + struct xen_dm_op_set_isa_irq_level *data; + + memset(&op, 0, sizeof(op)); + + op.op = XEN_DMOP_set_isa_irq_level; + data = &op.u.set_isa_irq_level; + + data->isa_irq = irq; + data->level = level; + + return xendevicemodel_op(dmod, domid, 1, &op, sizeof(op)); +} + +int xendevicemodel_set_pci_link_route( + xendevicemodel_handle *dmod, domid_t domid, uint8_t link, uint8_t irq) +{ + struct xen_dm_op op; + struct xen_dm_op_set_pci_link_route *data; + + memset(&op, 0, sizeof(op)); + + op.op = XEN_DMOP_set_pci_link_route; + data = &op.u.set_pci_link_route; + + data->link = link; + data->isa_irq = irq; + + return xendevicemodel_op(dmod, domid, 1, &op, sizeof(op)); +} + +int xendevicemodel_inject_msi( + xendevicemodel_handle *dmod, domid_t domid, uint64_t msi_addr, + uint32_t msi_data) +{ + struct xen_dm_op op; + struct xen_dm_op_inject_msi *data; + + memset(&op, 0, sizeof(op)); + + op.op = XEN_DMOP_inject_msi; + data = &op.u.inject_msi; + + data->addr = msi_addr; + data->data = msi_data; + + return xendevicemodel_op(dmod, domid, 1, &op, sizeof(op)); +} + +int xendevicemodel_track_dirty_vram( + xendevicemodel_handle *dmod, domid_t domid, uint64_t first_pfn, + uint32_t nr, unsigned long *dirty_bitmap) +{ + struct xen_dm_op op; + struct xen_dm_op_track_dirty_vram *data; + + memset(&op, 0, sizeof(op)); + + op.op = XEN_DMOP_track_dirty_vram; + data = &op.u.track_dirty_vram; + + data->first_pfn = first_pfn; + data->nr = nr; + + return xendevicemodel_op(dmod, domid, 2, &op, sizeof(op), + dirty_bitmap, (nr + 7) / 8); +} + +int xendevicemodel_modified_memory( + xendevicemodel_handle *dmod, domid_t domid, uint64_t first_pfn, + uint32_t nr) +{ + struct xen_dm_op op; + struct xen_dm_op_modified_memory *data; + + memset(&op, 0, sizeof(op)); + + op.op = XEN_DMOP_modified_memory; + data = &op.u.modified_memory; + + data->first_pfn = first_pfn; + data->nr = nr; + + return xendevicemodel_op(dmod, domid, 1, &op, sizeof(op)); +} + +int xendevicemodel_set_mem_type( + xendevicemodel_handle *dmod, domid_t domid, hvmmem_type_t mem_type, + uint64_t first_pfn, uint32_t nr) +{ + struct xen_dm_op op; + struct xen_dm_op_set_mem_type *data; + + memset(&op, 0, sizeof(op)); + + op.op = XEN_DMOP_set_mem_type; + data = &op.u.set_mem_type; + + data->mem_type = mem_type; + data->first_pfn = first_pfn; + data->nr = nr; + + return xendevicemodel_op(dmod, domid, 1, &op, sizeof(op)); +} + +int xendevicemodel_inject_event( + xendevicemodel_handle *dmod, domid_t domid, int vcpu, uint8_t vector, + uint8_t type, uint32_t error_code, uint8_t insn_len, uint64_t cr2) +{ + struct xen_dm_op op; + struct xen_dm_op_inject_event *data; + + memset(&op, 0, sizeof(op)); + + op.op = XEN_DMOP_inject_event; + data = &op.u.inject_event; + + data->vcpuid = vcpu; + data->vector = vector; + data->type = type; + data->error_code = error_code; + data->insn_len = insn_len; + data->cr2 = cr2; + + return xendevicemodel_op(dmod, domid, 1, &op, sizeof(op)); +} + /* * Local variables: * mode: C diff --git a/tools/libs/devicemodel/include/xendevicemodel.h b/tools/libs/devicemodel/include/xendevicemodel.h index f977b0e..e00f8da 100644 --- a/tools/libs/devicemodel/include/xendevicemodel.h +++ b/tools/libs/devicemodel/include/xendevicemodel.h @@ -17,6 +17,14 @@ #ifndef XENDEVICEMODEL_H #define XENDEVICEMODEL_H +#ifdef __XEN_TOOLS__ + +#include + +#include +#include +#include + /* Callers who don't care don't need to #include */ struct xentoollog_logger; @@ -27,6 +35,256 @@ xendevicemodel_handle *xendevicemodel_open(struct xentoollog_logger *logger, int xendevicemodel_close(xendevicemodel_handle *dmod); +/* + * IOREQ Server API. (See section on IOREQ Servers in public/hvm_op.h). + */ + +/** + * This function instantiates an IOREQ Server. + * + * @parm dmod a handle to an open devicemodel interface. + * @parm domid the domain id to be serviced + * @parm handle_bufioreq how should the IOREQ Server handle buffered + * requests (HVM_IOREQSRV_BUFIOREQ_*)? + * @parm id pointer to an ioservid_t to receive the IOREQ Server id. + * @return 0 on success, -1 on failure. + */ +int xendevicemodel_create_ioreq_server( + xendevicemodel_handle *dmod, domid_t domid, int handle_bufioreq, + ioservid_t *id); + +/** + * This function retrieves the necessary information to allow an + * emulator to use an IOREQ Server. + * + * @parm dmod a handle to an open devicemodel interface. + * @parm domid the domain id to be serviced + * @parm id the IOREQ Server id. + * @parm ioreq_pfn pointer to a xen_pfn_t to receive the synchronous ioreq + * gmfn + * @parm bufioreq_pfn pointer to a xen_pfn_t to receive the buffered ioreq + * gmfn + * @parm bufioreq_port pointer to a evtchn_port_t to receive the buffered + * ioreq event channel + * @return 0 on success, -1 on failure. + */ +int xendevicemodel_get_ioreq_server_info( + xendevicemodel_handle *dmod, domid_t domid, ioservid_t id, + xen_pfn_t *ioreq_pfn, xen_pfn_t *bufioreq_pfn, + evtchn_port_t *bufioreq_port); + +/** + * This function registers a range of memory or I/O ports for emulation. + * + * @parm dmod a handle to an open devicemodel interface. + * @parm domid the domain id to be serviced + * @parm id the IOREQ Server id. + * @parm is_mmio is this a range of ports or memory + * @parm start start of range + * @parm end end of range (inclusive). + * @return 0 on success, -1 on failure. + */ +int xendevicemodel_map_io_range_to_ioreq_server( + xendevicemodel_handle *dmod, domid_t domid, ioservid_t id, int is_mmio, + uint64_t start, uint64_t end); + +/** + * This function deregisters a range of memory or I/O ports for emulation. + * + * @parm dmod a handle to an open devicemodel interface. + * @parm domid the domain id to be serviced + * @parm id the IOREQ Server id. + * @parm is_mmio is this a range of ports or memory + * @parm start start of range + * @parm end end of range (inclusive). + * @return 0 on success, -1 on failure. + */ +int xendevicemodel_unmap_io_range_from_ioreq_server( + xendevicemodel_handle *dmod, domid_t domid, ioservid_t id, int is_mmio, + uint64_t start, uint64_t end); + +/** + * This function registers a PCI device for config space emulation. + * + * @parm dmod a handle to an open devicemodel interface. + * @parm domid the domain id to be serviced + * @parm id the IOREQ Server id. + * @parm segment the PCI segment of the device + * @parm bus the PCI bus of the device + * @parm device the 'slot' number of the device + * @parm function the function number of the device + * @return 0 on success, -1 on failure. + */ +int xendevicemodel_map_pcidev_to_ioreq_server( + xendevicemodel_handle *dmod, domid_t domid, ioservid_t id, + uint16_t segment, uint8_t bus, uint8_t device, uint8_t function); + +/** + * This function deregisters a PCI device for config space emulation. + * + * @parm dmod a handle to an open devicemodel interface. + * @parm domid the domain id to be serviced + * @parm id the IOREQ Server id. + * @parm segment the PCI segment of the device + * @parm bus the PCI bus of the device + * @parm device the 'slot' number of the device + * @parm function the function number of the device + * @return 0 on success, -1 on failure. + */ +int xendevicemodel_unmap_pcidev_from_ioreq_server( + xendevicemodel_handle *dmod, domid_t domid, ioservid_t id, + uint16_t segment, uint8_t bus, uint8_t device, uint8_t function); + +/** + * This function destroys an IOREQ Server. + * + * @parm dmod a handle to an open devicemodel interface. + * @parm domid the domain id to be serviced + * @parm id the IOREQ Server id. + * @return 0 on success, -1 on failure. + */ +int xendevicemodel_destroy_ioreq_server( + xendevicemodel_handle *dmod, domid_t domid, ioservid_t id); + +/** + * This function sets IOREQ Server state. An IOREQ Server + * will not be passed emulation requests until it is in + * the enabled state. + * Note that the contents of the ioreq_pfn and bufioreq_pfn are + * not meaningful until the IOREQ Server is in the enabled state. + * + * @parm dmod a handle to an open devicemodel interface. + * @parm domid the domain id to be serviced + * @parm id the IOREQ Server id. + * @parm enabled the state. + * @return 0 on success, -1 on failure. + */ +int xendevicemodel_set_ioreq_server_state( + xendevicemodel_handle *dmod, domid_t domid, ioservid_t id, int enabled); + +/** + * This function sets the level of INTx pin of an emulated PCI device. + * + * @parm dmod a handle to an open devicemodel interface. + * @parm domid the domain id to be serviced + * @parm segment the PCI segment number of the emulated device + * @parm bus the PCI bus number of the emulated device + * @parm device the PCI device number of the emulated device + * @parm intx the INTx pin to modify (0 => A .. 3 => D) + * @parm level the level (1 for asserted, 0 for de-asserted) + * @return 0 on success, -1 on failure. + */ +int xendevicemodel_set_pci_intx_level( + xendevicemodel_handle *dmod, domid_t domid, uint16_t segment, + uint8_t bus, uint8_t device, uint8_t intx, unsigned int level); + +/** + * This function sets the level of an ISA IRQ line. + * + * @parm dmod a handle to an open devicemodel interface. + * @parm domid the domain id to be serviced + * @parm irq the IRQ number (0 - 15) + * @parm level the level (1 for asserted, 0 for de-asserted) + * @return 0 on success, -1 on failure. + */ +int xendevicemodel_set_isa_irq_level( + xendevicemodel_handle *dmod, domid_t domid, uint8_t irq, + unsigned int level); + +/** + * This function maps a PCI INTx line to a an IRQ line. + * + * @parm dmod a handle to an open devicemodel interface. + * @parm domid the domain id to be serviced + * @parm line the INTx line (0 => A .. 3 => B) + * @parm irq the IRQ number (0 - 15) + * @return 0 on success, -1 on failure. + */ +int xendevicemodel_set_pci_link_route( + xendevicemodel_handle *dmod, domid_t domid, uint8_t link, uint8_t irq); + +/** + * This function injects an MSI into a guest. + * + * @parm dmod a handle to an open devicemodel interface. + * @parm domid the domain id to be serviced + * @parm msi_addr the MSI address (0xfeexxxxx) + * @parm msi_data the MSI data + * @return 0 on success, -1 on failure. +*/ +int xendevicemodel_inject_msi( + xendevicemodel_handle *dmod, domid_t domid, uint64_t msi_addr, + uint32_t msi_data); + +/** + * This function enables tracking of changes in the VRAM area. + * + * The following is done atomically: + * - get the dirty bitmap since the last call. + * - set up dirty tracking area for period up to the next call. + * - clear the dirty tracking area. + * + * @parm dmod a handle to an open devicemodel interface. + * @parm domid the domain id to be serviced + * @parm first_pfn the start of the area to track + * @parm nr the number of pages to track + * @parm dirty_bitmal a pointer to the bitmap to be updated + * @return 0 on success, -1 on failure. + */ +int xendevicemodel_track_dirty_vram( + xendevicemodel_handle *dmod, domid_t domid, uint64_t first_pfn, + uint32_t nr, unsigned long *dirty_bitmap); + +/** + * This function notifies the hypervisor that a set of domain pages + * have been modified. + * + * @parm dmod a handle to an open devicemodel interface. + * @parm domid the domain id to be serviced + * @parm first_pfn the start of the modified area + * @parm nr the number of pages modified + * @return 0 on success, -1 on failure. + */ +int xendevicemodel_modified_memory( + xendevicemodel_handle *dmod, domid_t domid, uint64_t first_pfn, + uint32_t nr); + +/** + * This function notifies the hypervisor that a set of domain pages + * are to be treated in a specific way. (See the definition of + * hvmmem_type_t). + * + * @parm dmod a handle to an open devicemodel interface. + * @parm domid the domain id to be serviced + * @parm mem_type determines how the set is to be treated + * @parm first_pfn the start of the set + * @parm nr the number of pages in the set + * @return 0 on success, -1 on failure. + */ +int xendevicemodel_set_mem_type( + xendevicemodel_handle *dmod, domid_t domid, hvmmem_type_t mem_type, + uint64_t first_pfn, uint32_t nr); + +/** + * This function injects an event into a vCPU to take effect the next + * time it resumes. + * + * @parm dmod a handle to an open devicemodel interface. + * @parm domid the domain id to be serviced + * @parm vcpu the vcpu id + * @parm vector the interrupt vector + * @parm type the event type (see the definition of enum x86_event_type) + * @parm error_code the error code or ~0 to skip + * @parm insn_len the instruction length + * @parm cr2 the value of CR2 for page faults + * @return 0 on success, -1 on failure. + */ +int xendevicemodel_inject_event( + xendevicemodel_handle *dmod, domid_t domid, int vcpu, uint8_t vector, + uint8_t type, uint32_t error_code, uint8_t insn_len, uint64_t cr2); + +#endif /* __XEN_TOOLS__ */ + #endif /* XENDEVICEMODEL_H */ /* diff --git a/tools/libs/devicemodel/libxendevicemodel.map b/tools/libs/devicemodel/libxendevicemodel.map index 980c429..abc6d06 100644 --- a/tools/libs/devicemodel/libxendevicemodel.map +++ b/tools/libs/devicemodel/libxendevicemodel.map @@ -1,6 +1,22 @@ VERS_1.0 { global: xendevicemodel_open; + xendevicemodel_create_ioreq_server; + xendevicemodel_get_ioreq_server_info; + xendevicemodel_map_io_range_to_ioreq_server; + xendevicemodel_unmap_io_range_from_ioreq_server; + xendevicemodel_map_pcidev_to_ioreq_server; + xendevicemodel_unmap_pcidev_from_ioreq_server; + xendevicemodel_destroy_ioreq_server; + xendevicemodel_set_ioreq_server_state; + xendevicemodel_set_pci_intx_level; + xendevicemodel_set_isa_irq_level; + xendevicemodel_set_pci_link_route; + xendevicemodel_inject_msi; + xendevicemodel_track_dirty_vram; + xendevicemodel_modified_memory; + xendevicemodel_set_mem_type; + xendevicemodel_inject_event; xendevicemodel_close; local: *; /* Do not expose anything by default */ }; diff --git a/tools/libs/devicemodel/private.h b/tools/libs/devicemodel/private.h index cf1e4b0..7c7acf2 100644 --- a/tools/libs/devicemodel/private.h +++ b/tools/libs/devicemodel/private.h @@ -1,14 +1,33 @@ #ifndef XENDEVICEMODEL_PRIVATE_H #define XENDEVICEMODEL_PRIVATE_H +#define __XEN_TOOLS__ 1 + #include #include +#include struct xendevicemodel_handle { xentoollog_logger *logger, *logger_tofree; unsigned int flags; + xencall_handle *xcall; +}; + +struct xendevicemodel_buf { + void *ptr; + size_t size; }; +int xendevicemodel_xcall(xendevicemodel_handle *dmod, + domid_t domid, unsigned int nr_bufs, + struct xendevicemodel_buf bufs[]); + +int osdep_xendevicemodel_open(xendevicemodel_handle *dmod); +int osdep_xendevicemodel_close(xendevicemodel_handle *dmod); +int osdep_xendevicemodel_op(xendevicemodel_handle *dmod, + domid_t domid, unsigned int nr_bufs, + struct xendevicemodel_buf bufs[]); + #endif /* diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile index af5e49c..da689c4 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -50,6 +50,7 @@ CTRL_SRCS-$(CONFIG_NetBSDRump) += xc_netbsd.c CTRL_SRCS-$(CONFIG_MiniOS) += xc_minios.c CTRL_SRCS-y += xc_evtchn_compat.c CTRL_SRCS-y += xc_gnttab_compat.c +CTRL_SRCS-y += xc_devicemodel_compat.c GUEST_SRCS-y := GUEST_SRCS-y += xg_private.c xc_suspend.c diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index 85d7fe5..90ca6ad 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -1592,59 +1592,6 @@ int xc_physdev_unmap_pirq(xc_interface *xch, int domid, int pirq); -int xc_hvm_set_pci_intx_level( - xc_interface *xch, domid_t dom, - uint16_t domain, uint8_t bus, uint8_t device, uint8_t intx, - unsigned int level); -int xc_hvm_set_isa_irq_level( - xc_interface *xch, domid_t dom, - uint8_t isa_irq, - unsigned int level); - -int xc_hvm_set_pci_link_route( - xc_interface *xch, domid_t dom, uint8_t link, uint8_t isa_irq); - -int xc_hvm_inject_msi( - xc_interface *xch, domid_t dom, uint64_t addr, uint32_t data); - -/* - * Track dirty bit changes in the VRAM area - * - * All of this is done atomically: - * - get the dirty bitmap since the last call - * - set up dirty tracking area for period up to the next call - * - clear the dirty tracking area. - * - * Returns -ENODATA and does not fill bitmap if the area has changed since the - * last call. - */ -int xc_hvm_track_dirty_vram( - xc_interface *xch, domid_t dom, - uint64_t first_pfn, uint32_t nr, - unsigned long *bitmap); - -/* - * Notify that some pages got modified by the Device Model - */ -int xc_hvm_modified_memory( - xc_interface *xch, domid_t dom, uint64_t first_pfn, uint32_t nr); - -/* - * Set a range of memory to a specific type. - * Allowed types are HVMMEM_ram_rw, HVMMEM_ram_ro, HVMMEM_mmio_dm - */ -int xc_hvm_set_mem_type( - xc_interface *xch, domid_t dom, hvmmem_type_t memtype, uint64_t first_pfn, uint32_t nr); - -/* - * Injects a hardware/software CPU trap, to take effect the next time the HVM - * resumes. - */ -int xc_hvm_inject_trap( - xc_interface *xch, domid_t dom, int vcpu, uint8_t vector, - uint8_t type, uint32_t error_code, uint8_t insn_len, - uint64_t cr2); - /* * LOGGING AND ERROR REPORTING */ @@ -1689,150 +1636,6 @@ int xc_hvm_param_get(xc_interface *handle, domid_t dom, uint32_t param, uint64_t int xc_set_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long value); int xc_get_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long *value); -/* - * IOREQ Server API. (See section on IOREQ Servers in public/hvm_op.h). - */ - -/** - * This function instantiates an IOREQ Server. - * - * @parm xch a handle to an open hypervisor interface. - * @parm domid the domain id to be serviced - * @parm handle_bufioreq how should the IOREQ Server handle buffered requests - * (HVM_IOREQSRV_BUFIOREQ_*)? - * @parm id pointer to an ioservid_t to receive the IOREQ Server id. - * @return 0 on success, -1 on failure. - */ -int xc_hvm_create_ioreq_server(xc_interface *xch, - domid_t domid, - int handle_bufioreq, - ioservid_t *id); - -/** - * This function retrieves the necessary information to allow an - * emulator to use an IOREQ Server. - * - * @parm xch a handle to an open hypervisor interface. - * @parm domid the domain id to be serviced - * @parm id the IOREQ Server id. - * @parm ioreq_pfn pointer to a xen_pfn_t to receive the synchronous ioreq gmfn - * @parm bufioreq_pfn pointer to a xen_pfn_t to receive the buffered ioreq gmfn - * @parm bufioreq_port pointer to a evtchn_port_t to receive the buffered ioreq event channel - * @return 0 on success, -1 on failure. - */ -int xc_hvm_get_ioreq_server_info(xc_interface *xch, - domid_t domid, - ioservid_t id, - xen_pfn_t *ioreq_pfn, - xen_pfn_t *bufioreq_pfn, - evtchn_port_t *bufioreq_port); - -/** - * This function sets IOREQ Server state. An IOREQ Server - * will not be passed emulation requests until it is in - * the enabled state. - * Note that the contents of the ioreq_pfn and bufioreq_pfn are - * not meaningful until the IOREQ Server is in the enabled state. - * - * @parm xch a handle to an open hypervisor interface. - * @parm domid the domain id to be serviced - * @parm id the IOREQ Server id. - * @parm enabled the state. - * @return 0 on success, -1 on failure. - */ -int xc_hvm_set_ioreq_server_state(xc_interface *xch, - domid_t domid, - ioservid_t id, - int enabled); - -/** - * This function registers a range of memory or I/O ports for emulation. - * - * @parm xch a handle to an open hypervisor interface. - * @parm domid the domain id to be serviced - * @parm id the IOREQ Server id. - * @parm is_mmio is this a range of ports or memory - * @parm start start of range - * @parm end end of range (inclusive). - * @return 0 on success, -1 on failure. - */ -int xc_hvm_map_io_range_to_ioreq_server(xc_interface *xch, - domid_t domid, - ioservid_t id, - int is_mmio, - uint64_t start, - uint64_t end); - -/** - * This function deregisters a range of memory or I/O ports for emulation. - * - * @parm xch a handle to an open hypervisor interface. - * @parm domid the domain id to be serviced - * @parm id the IOREQ Server id. - * @parm is_mmio is this a range of ports or memory - * @parm start start of range - * @parm end end of range (inclusive). - * @return 0 on success, -1 on failure. - */ -int xc_hvm_unmap_io_range_from_ioreq_server(xc_interface *xch, - domid_t domid, - ioservid_t id, - int is_mmio, - uint64_t start, - uint64_t end); - -/** - * This function registers a PCI device for config space emulation. - * - * @parm xch a handle to an open hypervisor interface. - * @parm domid the domain id to be serviced - * @parm id the IOREQ Server id. - * @parm segment the PCI segment of the device - * @parm bus the PCI bus of the device - * @parm device the 'slot' number of the device - * @parm function the function number of the device - * @return 0 on success, -1 on failure. - */ -int xc_hvm_map_pcidev_to_ioreq_server(xc_interface *xch, - domid_t domid, - ioservid_t id, - uint16_t segment, - uint8_t bus, - uint8_t device, - uint8_t function); - -/** - * This function deregisters a PCI device for config space emulation. - * - * @parm xch a handle to an open hypervisor interface. - * @parm domid the domain id to be serviced - * @parm id the IOREQ Server id. - * @parm segment the PCI segment of the device - * @parm bus the PCI bus of the device - * @parm device the 'slot' number of the device - * @parm function the function number of the device - * @return 0 on success, -1 on failure. - */ -int xc_hvm_unmap_pcidev_from_ioreq_server(xc_interface *xch, - domid_t domid, - ioservid_t id, - uint16_t segment, - uint8_t bus, - uint8_t device, - uint8_t function); - -/** - * This function destroys an IOREQ Server. - * - * @parm xch a handle to an open hypervisor interface. - * @parm domid the domain id to be serviced - * @parm id the IOREQ Server id. - * @return 0 on success, -1 on failure. - */ -int xc_hvm_destroy_ioreq_server(xc_interface *xch, - domid_t domid, - ioservid_t id); - /* HVM guest pass-through */ int xc_assign_device(xc_interface *xch, uint32_t domid, diff --git a/tools/libxc/include/xenctrl_compat.h b/tools/libxc/include/xenctrl_compat.h index 93ccadb..040e7b2 100644 --- a/tools/libxc/include/xenctrl_compat.h +++ b/tools/libxc/include/xenctrl_compat.h @@ -120,6 +120,53 @@ int xc_gntshr_munmap(xc_gntshr *xcg, void *start_address, uint32_t count); #endif /* XC_WANT_COMPAT_GNTTAB_API */ +#ifdef XC_WANT_COMPAT_DEVICEMODEL_API + +int xc_hvm_create_ioreq_server( + xc_interface *xch, domid_t domid, int handle_bufioreq, + ioservid_t *id); +int xc_hvm_get_ioreq_server_info( + xc_interface *xch, domid_t domid, ioservid_t id, xen_pfn_t *ioreq_pfn, + xen_pfn_t *bufioreq_pfn, evtchn_port_t *bufioreq_port); +int xc_hvm_map_io_range_to_ioreq_server( + xc_interface *xch, domid_t domid, ioservid_t id, int is_mmio, + uint64_t start, uint64_t end); +int xc_hvm_unmap_io_range_from_ioreq_server( + xc_interface *xch, domid_t domid, ioservid_t id, int is_mmio, + uint64_t start, uint64_t end); +int xc_hvm_map_pcidev_to_ioreq_server( + xc_interface *xch, domid_t domid, ioservid_t id, uint16_t segment, + uint8_t bus, uint8_t device, uint8_t function); +int xc_hvm_unmap_pcidev_from_ioreq_server( + xc_interface *xch, domid_t domid, ioservid_t id, uint16_t segment, + uint8_t bus, uint8_t device, uint8_t function); +int xc_hvm_destroy_ioreq_server( + xc_interface *xch, domid_t domid, ioservid_t id); +int xc_hvm_set_ioreq_server_state( + xc_interface *xch, domid_t domid, ioservid_t id, int enabled); +int xc_hvm_set_pci_intx_level( + xc_interface *xch, domid_t domid, uint16_t segment, uint8_t bus, + uint8_t device, uint8_t intx, unsigned int level); +int xc_hvm_set_isa_irq_level( + xc_interface *xch, domid_t domid, uint8_t irq, unsigned int level); +int xc_hvm_set_pci_link_route( + xc_interface *xch, domid_t domid, uint8_t link, uint8_t irq); +int xc_hvm_inject_msi( + xc_interface *xch, domid_t domid, uint64_t msi_addr, uint32_t msi_data); +int xc_hvm_track_dirty_vram( + xc_interface *xch, domid_t domid, uint64_t first_pfn, uint32_t nr, + unsigned long *dirty_bitmap); +int xc_hvm_modified_memory( + xc_interface *xch, domid_t domid, uint64_t first_pfn, uint32_t nr); +int xc_hvm_set_mem_type( + xc_interface *xch, domid_t domid, hvmmem_type_t type, + uint64_t first_pfn, uint32_t nr); +int xc_hvm_inject_trap( + xc_interface *xch, domid_t domid, int vcpu, uint8_t vector, + uint8_t type, uint32_t error_code, uint8_t insn_len, uint64_t cr2); + +#endif /* XC_WANT_COMPAT_DEVICEMODEL_API */ + #endif /* diff --git a/tools/libxc/xc_devicemodel_compat.c b/tools/libxc/xc_devicemodel_compat.c new file mode 100644 index 0000000..e4edeea --- /dev/null +++ b/tools/libxc/xc_devicemodel_compat.c @@ -0,0 +1,139 @@ +/* + * Compat shims for use of 3rd party consumers of libxenctrl device model + * functionality which has been split into separate libraries. + */ + +#define XC_WANT_COMPAT_DEVICEMODEL_API +#include "xc_private.h" + +int xc_hvm_create_ioreq_server( + xc_interface *xch, domid_t domid, int handle_bufioreq, + ioservid_t *id) +{ + return xendevicemodel_create_ioreq_server(xch->dmod, domid, + handle_bufioreq, id); +} + +int xc_hvm_get_ioreq_server_info( + xc_interface *xch, domid_t domid, ioservid_t id, xen_pfn_t *ioreq_pfn, + xen_pfn_t *bufioreq_pfn, evtchn_port_t *bufioreq_port) +{ + return xendevicemodel_get_ioreq_server_info(xch->dmod, domid, id, + ioreq_pfn, bufioreq_pfn, + bufioreq_port); +} + +int xc_hvm_map_io_range_to_ioreq_server( + xc_interface *xch, domid_t domid, ioservid_t id, int is_mmio, + uint64_t start, uint64_t end) +{ + return xendevicemodel_map_io_range_to_ioreq_server(xch->dmod, domid, + id, is_mmio, start, + end); +} + +int xc_hvm_unmap_io_range_from_ioreq_server( + xc_interface *xch, domid_t domid, ioservid_t id, int is_mmio, + uint64_t start, uint64_t end) +{ + return xendevicemodel_unmap_io_range_from_ioreq_server(xch->dmod, domid, + id, is_mmio, + start, end); +} + +int xc_hvm_map_pcidev_to_ioreq_server( + xc_interface *xch, domid_t domid, ioservid_t id, uint16_t segment, + uint8_t bus, uint8_t device, uint8_t function) +{ + return xendevicemodel_map_pcidev_to_ioreq_server(xch->dmod, domid, id, + segment, bus, device, + function); +} + +int xc_hvm_unmap_pcidev_from_ioreq_server( + xc_interface *xch, domid_t domid, ioservid_t id, uint16_t segment, + uint8_t bus, uint8_t device, uint8_t function) +{ + return xendevicemodel_unmap_pcidev_from_ioreq_server(xch->dmod, domid, + id, segment, bus, + device, function); +} + +int xc_hvm_destroy_ioreq_server( + xc_interface *xch, domid_t domid, ioservid_t id) +{ + return xendevicemodel_destroy_ioreq_server(xch->dmod, domid, id); +} + +int xc_hvm_set_ioreq_server_state( + xc_interface *xch, domid_t domid, ioservid_t id, int enabled) +{ + return xendevicemodel_set_ioreq_server_state(xch->dmod, domid, id, + enabled); +} + +int xc_hvm_set_pci_intx_level( + xc_interface *xch, domid_t domid, uint16_t segment, uint8_t bus, + uint8_t device, uint8_t intx, unsigned int level) +{ + return xendevicemodel_set_pci_intx_level(xch->dmod, domid, segment, + bus, device, intx, level); +} + +int xc_hvm_set_isa_irq_level( + xc_interface *xch, domid_t domid, uint8_t irq, unsigned int level) +{ + return xendevicemodel_set_isa_irq_level(xch->dmod, domid, irq, level); +} + +int xc_hvm_set_pci_link_route( + xc_interface *xch, domid_t domid, uint8_t link, uint8_t irq) +{ + return xendevicemodel_set_pci_link_route(xch->dmod, domid, link, irq); +} + +int xc_hvm_inject_msi( + xc_interface *xch, domid_t domid, uint64_t msi_addr, uint32_t msi_data) +{ + return xendevicemodel_inject_msi(xch->dmod, domid, msi_addr, msi_data); +} + +int xc_hvm_track_dirty_vram( + xc_interface *xch, domid_t domid, uint64_t first_pfn, uint32_t nr, + unsigned long *dirty_bitmap) +{ + return xendevicemodel_track_dirty_vram(xch->dmod, domid, first_pfn, + nr, dirty_bitmap); +} + +int xc_hvm_modified_memory( + xc_interface *xch, domid_t domid, uint64_t first_pfn, uint32_t nr) +{ + return xendevicemodel_modified_memory(xch->dmod, domid, first_pfn, nr); +} + +int xc_hvm_set_mem_type( + xc_interface *xch, domid_t domid, hvmmem_type_t type, + uint64_t first_pfn, uint32_t nr) +{ + return xendevicemodel_set_mem_type(xch->dmod, domid, type, first_pfn, + nr); +} + +int xc_hvm_inject_trap( + xc_interface *xch, domid_t domid, int vcpu, uint8_t vector, + uint8_t type, uint32_t error_code, uint8_t insn_len, uint64_t cr2) +{ + return xendevicemodel_inject_event(xch->dmod, domid, vcpu, vector, + type, error_code, insn_len, cr2); +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index fa1daeb..d862e53 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -1412,207 +1412,6 @@ int xc_get_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long return 0; } -int xc_hvm_create_ioreq_server(xc_interface *xch, - domid_t domid, - int handle_bufioreq, - ioservid_t *id) -{ - struct xen_dm_op op; - struct xen_dm_op_create_ioreq_server *data; - int rc; - - memset(&op, 0, sizeof(op)); - - op.op = XEN_DMOP_create_ioreq_server; - data = &op.u.create_ioreq_server; - - data->handle_bufioreq = handle_bufioreq; - - rc = do_dm_op(xch, domid, 1, &op, sizeof(op)); - if ( rc ) - return rc; - - *id = data->id; - - return 0; -} - -int xc_hvm_get_ioreq_server_info(xc_interface *xch, - domid_t domid, - ioservid_t id, - xen_pfn_t *ioreq_pfn, - xen_pfn_t *bufioreq_pfn, - evtchn_port_t *bufioreq_port) -{ - struct xen_dm_op op; - struct xen_dm_op_get_ioreq_server_info *data; - int rc; - - memset(&op, 0, sizeof(op)); - - op.op = XEN_DMOP_get_ioreq_server_info; - data = &op.u.get_ioreq_server_info; - - data->id = id; - - rc = do_dm_op(xch, domid, 1, &op, sizeof(op)); - if ( rc ) - return rc; - - if ( ioreq_pfn ) - *ioreq_pfn = data->ioreq_pfn; - - if ( bufioreq_pfn ) - *bufioreq_pfn = data->bufioreq_pfn; - - if ( bufioreq_port ) - *bufioreq_port = data->bufioreq_port; - - return 0; -} - -int xc_hvm_map_io_range_to_ioreq_server(xc_interface *xch, domid_t domid, - ioservid_t id, int is_mmio, - uint64_t start, uint64_t end) -{ - struct xen_dm_op op; - struct xen_dm_op_ioreq_server_range *data; - - memset(&op, 0, sizeof(op)); - - op.op = XEN_DMOP_map_io_range_to_ioreq_server; - data = &op.u.map_io_range_to_ioreq_server; - - data->id = id; - data->type = is_mmio ? XEN_DMOP_IO_RANGE_MEMORY : XEN_DMOP_IO_RANGE_PORT; - data->start = start; - data->end = end; - - return do_dm_op(xch, domid, 1, &op, sizeof(op)); -} - -int xc_hvm_unmap_io_range_from_ioreq_server(xc_interface *xch, domid_t domid, - ioservid_t id, int is_mmio, - uint64_t start, uint64_t end) -{ - struct xen_dm_op op; - struct xen_dm_op_ioreq_server_range *data; - - memset(&op, 0, sizeof(op)); - - op.op = XEN_DMOP_unmap_io_range_from_ioreq_server; - data = &op.u.unmap_io_range_from_ioreq_server; - - data->id = id; - data->type = is_mmio ? XEN_DMOP_IO_RANGE_MEMORY : XEN_DMOP_IO_RANGE_PORT; - data->start = start; - data->end = end; - - return do_dm_op(xch, domid, 1, &op, sizeof(op)); -} - -int xc_hvm_map_pcidev_to_ioreq_server(xc_interface *xch, domid_t domid, - ioservid_t id, uint16_t segment, - uint8_t bus, uint8_t device, - uint8_t function) -{ - struct xen_dm_op op; - struct xen_dm_op_ioreq_server_range *data; - - if (device > 0x1f || function > 0x7) { - errno = EINVAL; - return -1; - } - - memset(&op, 0, sizeof(op)); - - op.op = XEN_DMOP_map_io_range_to_ioreq_server; - data = &op.u.map_io_range_to_ioreq_server; - - data->id = id; - data->type = XEN_DMOP_IO_RANGE_PCI; - - /* - * The underlying hypercall will deal with ranges of PCI SBDF - * but, for simplicity, the API only uses singletons. - */ - data->start = data->end = XEN_DMOP_PCI_SBDF((uint64_t)segment, - (uint64_t)bus, - (uint64_t)device, - (uint64_t)function); - - return do_dm_op(xch, domid, 1, &op, sizeof(op)); -} - -int xc_hvm_unmap_pcidev_from_ioreq_server(xc_interface *xch, domid_t domid, - ioservid_t id, uint16_t segment, - uint8_t bus, uint8_t device, - uint8_t function) -{ - struct xen_dm_op op; - struct xen_dm_op_ioreq_server_range *data; - - if (device > 0x1f || function > 0x7) { - errno = EINVAL; - return -1; - } - - memset(&op, 0, sizeof(op)); - - op.op = XEN_DMOP_unmap_io_range_from_ioreq_server; - data = &op.u.unmap_io_range_from_ioreq_server; - - data->id = id; - data->type = XEN_DMOP_IO_RANGE_PCI; - - /* - * The underlying hypercall will deal with ranges of PCI SBDF - * but, for simplicity, the API only uses singletons. - */ - data->start = data->end = XEN_DMOP_PCI_SBDF((uint64_t)segment, - (uint64_t)bus, - (uint64_t)device, - (uint64_t)function); - - return do_dm_op(xch, domid, 1, &op, sizeof(op)); -} - -int xc_hvm_destroy_ioreq_server(xc_interface *xch, - domid_t domid, - ioservid_t id) -{ - struct xen_dm_op op; - struct xen_dm_op_destroy_ioreq_server *data; - - memset(&op, 0, sizeof(op)); - - op.op = XEN_DMOP_destroy_ioreq_server; - data = &op.u.destroy_ioreq_server; - - data->id = id; - - return do_dm_op(xch, domid, 1, &op, sizeof(op)); -} - -int xc_hvm_set_ioreq_server_state(xc_interface *xch, - domid_t domid, - ioservid_t id, - int enabled) -{ - struct xen_dm_op op; - struct xen_dm_op_set_ioreq_server_state *data; - - memset(&op, 0, sizeof(op)); - - op.op = XEN_DMOP_set_ioreq_server_state; - data = &op.u.set_ioreq_server_state; - - data->id = id; - data->enabled = !!enabled; - - return do_dm_op(xch, domid, 1, &op, sizeof(op)); -} - int xc_domain_setdebugging(xc_interface *xch, uint32_t domid, unsigned int enable) diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c index 0fc6c22..88084fd 100644 --- a/tools/libxc/xc_misc.c +++ b/tools/libxc/xc_misc.c @@ -467,160 +467,6 @@ int xc_getcpuinfo(xc_interface *xch, int max_cpus, return rc; } - -int xc_hvm_set_pci_intx_level( - xc_interface *xch, domid_t dom, - uint16_t domain, uint8_t bus, uint8_t device, uint8_t intx, - unsigned int level) -{ - struct xen_dm_op op; - struct xen_dm_op_set_pci_intx_level *data; - - memset(&op, 0, sizeof(op)); - - op.op = XEN_DMOP_set_pci_intx_level; - data = &op.u.set_pci_intx_level; - - data->domain = domain; - data->bus = bus; - data->device = device; - data->intx = intx; - data->level = level; - - return do_dm_op(xch, dom, 1, &op, sizeof(op)); -} - -int xc_hvm_set_isa_irq_level( - xc_interface *xch, domid_t dom, - uint8_t isa_irq, - unsigned int level) -{ - struct xen_dm_op op; - struct xen_dm_op_set_isa_irq_level *data; - - memset(&op, 0, sizeof(op)); - - op.op = XEN_DMOP_set_isa_irq_level; - data = &op.u.set_isa_irq_level; - - data->isa_irq = isa_irq; - data->level = level; - - return do_dm_op(xch, dom, 1, &op, sizeof(op)); -} - -int xc_hvm_set_pci_link_route( - xc_interface *xch, domid_t dom, uint8_t link, uint8_t isa_irq) -{ - struct xen_dm_op op; - struct xen_dm_op_set_pci_link_route *data; - - memset(&op, 0, sizeof(op)); - - op.op = XEN_DMOP_set_pci_link_route; - data = &op.u.set_pci_link_route; - - data->link = link; - data->isa_irq = isa_irq; - - return do_dm_op(xch, dom, 1, &op, sizeof(op)); -} - -int xc_hvm_inject_msi( - xc_interface *xch, domid_t dom, uint64_t msi_addr, uint32_t msi_data) -{ - struct xen_dm_op op; - struct xen_dm_op_inject_msi *data; - - memset(&op, 0, sizeof(op)); - - op.op = XEN_DMOP_inject_msi; - data = &op.u.inject_msi; - - data->addr = msi_addr; - data->data = msi_data; - - return do_dm_op(xch, dom, 1, &op, sizeof(op)); -} - -int xc_hvm_track_dirty_vram( - xc_interface *xch, domid_t dom, - uint64_t first_pfn, uint32_t nr, - unsigned long *dirty_bitmap) -{ - struct xen_dm_op op; - struct xen_dm_op_track_dirty_vram *data; - - memset(&op, 0, sizeof(op)); - - op.op = XEN_DMOP_track_dirty_vram; - data = &op.u.track_dirty_vram; - - data->first_pfn = first_pfn; - data->nr = nr; - - return do_dm_op(xch, dom, 2, &op, sizeof(op), - dirty_bitmap, (nr + 7) / 8); -} - -int xc_hvm_modified_memory( - xc_interface *xch, domid_t dom, uint64_t first_pfn, uint32_t nr) -{ - struct xen_dm_op op; - struct xen_dm_op_modified_memory *data; - - memset(&op, 0, sizeof(op)); - - op.op = XEN_DMOP_modified_memory; - data = &op.u.modified_memory; - - data->first_pfn = first_pfn; - data->nr = nr; - - return do_dm_op(xch, dom, 1, &op, sizeof(op)); -} - -int xc_hvm_set_mem_type( - xc_interface *xch, domid_t dom, hvmmem_type_t mem_type, uint64_t first_pfn, uint32_t nr) -{ - struct xen_dm_op op; - struct xen_dm_op_set_mem_type *data; - - memset(&op, 0, sizeof(op)); - - op.op = XEN_DMOP_set_mem_type; - data = &op.u.set_mem_type; - - data->mem_type = mem_type; - data->first_pfn = first_pfn; - data->nr = nr; - - return do_dm_op(xch, dom, 1, &op, sizeof(op)); -} - -int xc_hvm_inject_trap( - xc_interface *xch, domid_t dom, int vcpu, uint8_t vector, - uint8_t type, uint32_t error_code, uint8_t insn_len, - uint64_t cr2) -{ - struct xen_dm_op op; - struct xen_dm_op_inject_event *data; - - memset(&op, 0, sizeof(op)); - - op.op = XEN_DMOP_inject_event; - data = &op.u.inject_event; - - data->vcpuid = vcpu; - data->vector = vector; - data->type = type; - data->error_code = error_code; - data->insn_len = insn_len; - data->cr2 = cr2; - - return do_dm_op(xch, dom, 1, &op, sizeof(op)); -} - int xc_livepatch_upload(xc_interface *xch, char *name, unsigned char *payload, diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 32379b6..dc8a1e7 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -785,79 +785,6 @@ int xc_ffs64(uint64_t x) return l ? xc_ffs32(l) : h ? xc_ffs32(h) + 32 : 0; } -int do_dm_op(xc_interface *xch, domid_t domid, unsigned int nr_bufs, ...) -{ - int ret = -1; - struct { - void *u; - void *h; - } *bounce; - DECLARE_HYPERCALL_BUFFER(xen_dm_op_buf_t, bufs); - va_list args; - unsigned int idx; - - bounce = calloc(nr_bufs, sizeof(*bounce)); - if ( bounce == NULL ) - goto fail1; - - bufs = xc_hypercall_buffer_alloc(xch, bufs, sizeof(*bufs) * nr_bufs); - if ( bufs == NULL ) - goto fail2; - - va_start(args, nr_bufs); - for ( idx = 0; idx < nr_bufs; idx++ ) - { - void *u = va_arg(args, void *); - size_t size = va_arg(args, size_t); - - bounce[idx].h = xencall_alloc_buffer(xch->xcall, size); - if ( bounce[idx].h == NULL ) - break; /* Error path handled after va_end(). */ - - memcpy(bounce[idx].h, u, size); - bounce[idx].u = u; - - set_xen_guest_handle_raw(bufs[idx].h, bounce[idx].h); - bufs[idx].size = size; - } - va_end(args); - - if ( idx != nr_bufs ) - goto fail3; - - ret = xencall3(xch->xcall, __HYPERVISOR_dm_op, - domid, nr_bufs, HYPERCALL_BUFFER_AS_ARG(bufs)); - if ( ret < 0 ) - goto fail4; - - while ( idx-- != 0 ) - { - memcpy(bounce[idx].u, bounce[idx].h, bufs[idx].size); - xencall_free_buffer(xch->xcall, bounce[idx].h); - } - - xc_hypercall_buffer_free(xch, bufs); - - free(bounce); - - return 0; - - fail4: - idx = nr_bufs; - - fail3: - while ( idx-- != 0 ) - xencall_free_buffer(xch->xcall, bounce[idx].h); - - xc_hypercall_buffer_free(xch, bufs); - - fail2: - free(bounce); - - fail1: - return ret; -} - /* * Local variables: * mode: C