From patchwork Thu Jun 29 05:50:41 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "lan,Tianyu" X-Patchwork-Id: 9816567 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 9519F603D7 for ; Thu, 29 Jun 2017 12:00:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7DD35286F4 for ; Thu, 29 Jun 2017 12:00:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7273028718; Thu, 29 Jun 2017 12:00: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=-2.7 required=2.0 tests=BAYES_00, DATE_IN_PAST_06_12, 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 AFA9828683 for ; Thu, 29 Jun 2017 12:00:37 +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 1dQY5J-0006EL-NQ; Thu, 29 Jun 2017 11:58:09 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dQY5I-0006CT-9V for xen-devel@lists.xen.org; Thu, 29 Jun 2017 11:58:08 +0000 Received: from [85.158.143.35] by server-3.bemta-6.messagelabs.com id FC/32-03044-F4BE4595; Thu, 29 Jun 2017 11:58:07 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrJLMWRWlGSWpSXmKPExsXS1tYhoev/OiT S4MBmHoslHxezODB6HN39mymAMYo1My8pvyKBNeP/8QPsBb8jK6bOWsHWwHjUoYuRk0NIYDqj xN9P9iC2hACvxJFlM1ghbH+JFWfnsXQxcgHVtDNK7J26kRkkwSagLnFi8URGEFtEQFri2ufLY DazwD5GiTfPVUFsYYFkiXfz7oHVswioSkzY9YEdxOYVcJXYdmEV1AIFiSkP34PVcALFG25uYY M4yEXiU89O5gmMvAsYGVYxqhenFpWlFuka6yUVZaZnlOQmZuboGhqY6eWmFhcnpqfmJCYV6yX n525iBAYDAxDsYOz453SIUZKDSUmU1/B5SKQQX1J+SmVGYnFGfFFpTmrxIUYZDg4lCd7TL4Fy gkWp6akVaZk5wLCESUtw8CiJ8PaBtPIWFyTmFmemQ6ROMepybFi9/guTEEtefl6qlDgv1yugI gGQoozSPLgRsBi5xCgrJczLCHSUEE9BalFuZgmq/CtGcQ5GJWHe5SCX8GTmlcBtegV0BBPQEc IzwI4oSURISTUwLrhq81vDY9etH7K+ycq/a6z2la7NLixvT1/6mMPvRu7yhyLC8+pfP9zIPEd Q2fizmtV1R9PnXxmm3Lz5fifPzqboowf2/pnZrunKXjAzPnihxi3fnJQnq+JcdkUWXpwvvyS/ 3s1oZeQdJd6kAoN++yPBtTmWG7SXv+bxfz1pF0P/BRazuph3SizFGYmGWsxFxYkAZAQ6gowCA AA= X-Env-Sender: tianyu.lan@intel.com X-Msg-Ref: server-8.tower-21.messagelabs.com!1498737484!70782526!1 X-Originating-IP: [134.134.136.24] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogMTM0LjEzNC4xMzYuMjQgPT4gMzkwOTcx\n X-StarScan-Received: X-StarScan-Version: 9.4.25; banners=-,-,- X-VirusChecked: Checked Received: (qmail 37854 invoked from network); 29 Jun 2017 11:58:06 -0000 Received: from mga09.intel.com (HELO mga09.intel.com) (134.134.136.24) by server-8.tower-21.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 29 Jun 2017 11:58:06 -0000 Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 29 Jun 2017 04:58:04 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.40,280,1496127600"; d="scan'208";a="280113674" Received: from sky-ws.sh.intel.com (HELO localhost) ([10.239.48.74]) by fmsmga004.fm.intel.com with ESMTP; 29 Jun 2017 04:58:02 -0700 From: Lan Tianyu To: xen-devel@lists.xen.org Date: Thu, 29 Jun 2017 01:50:41 -0400 Message-Id: <1498715457-16565-10-git-send-email-tianyu.lan@intel.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1498715457-16565-1-git-send-email-tianyu.lan@intel.com> References: <1498715457-16565-1-git-send-email-tianyu.lan@intel.com> Cc: Lan Tianyu , kevin.tian@intel.com, wei.liu2@citrix.com, andrew.cooper3@citrix.com, ian.jackson@eu.citrix.com, jbeulich@suse.com, Chao Gao Subject: [Xen-devel] [PATCH 9/25] Tools/libacpi: Add a user configurable parameter to control vIOMMU attributes 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: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Chao Gao a field, viommu_info, is added to struct libxl_domain_build_info. Several attributes can be specified by guest configuration file for the DMAR table building and vIOMMU creation. In domain creation process, a new logic is added to build ACPI DMAR table in tool stack according VM configuration and to pass though it to hvmloader via xenstore ACPI PT channel. If there are ACPI tables needed to pass through, we joint the tables. Signed-off-by: Chao Gao Signed-off-by: Lan Tianyu --- docs/man/xl.cfg.pod.5.in | 34 +++++++++++++++++- tools/libacpi/build.c | 5 +++ tools/libacpi/libacpi.h | 1 + tools/libxl/libxl_dom.c | 87 +++++++++++++++++++++++++++++++++++++++++++++ tools/libxl/libxl_types.idl | 10 ++++++ tools/xl/xl_parse.c | 64 +++++++++++++++++++++++++++++++++ 6 files changed, 200 insertions(+), 1 deletion(-) diff --git a/docs/man/xl.cfg.pod.5.in b/docs/man/xl.cfg.pod.5.in index 38084c7..874f3f2 100644 --- a/docs/man/xl.cfg.pod.5.in +++ b/docs/man/xl.cfg.pod.5.in @@ -1540,7 +1540,39 @@ Do not provide a VM generation ID. See also "Virtual Machine Generation ID" by Microsoft: L -=back +=back + +=item B + +Specifies the viommu which are to be provided to the guest. + +B has the form C where: + +=over 4 + +=item B + +Possible Bs are: + +=over 4 + +=item B + +Currently there is only one valid type: + +(X86 only) "vtd" means providing a emulated intel VT-d to the guest. + +=item B + +Specifies whether the vvtd should support intrrupt remapping +and default 'true'. + +=item B + +Specifies whether the vvtd should support x2apic mode +and default 'true'. + +=back =head3 Guest Virtual Time Controls diff --git a/tools/libacpi/build.c b/tools/libacpi/build.c index d5bedfd..0c3d3db 100644 --- a/tools/libacpi/build.c +++ b/tools/libacpi/build.c @@ -561,6 +561,11 @@ static int new_vm_gid(struct acpi_ctxt *ctxt, return 1; } +uint32_t acpi_get_table_size(struct acpi_header * header) +{ + return header ? header->length : 0; +} + int acpi_build_tables(struct acpi_ctxt *ctxt, struct acpi_config *config) { struct acpi_info *acpi_info; diff --git a/tools/libacpi/libacpi.h b/tools/libacpi/libacpi.h index 6a4e1cf..0a58d6f 100644 --- a/tools/libacpi/libacpi.h +++ b/tools/libacpi/libacpi.h @@ -109,6 +109,7 @@ struct acpi_config { #define DMAR_X2APIC_OPT_OUT 0x2 struct acpi_dmar *construct_dmar(struct acpi_ctxt *ctxt, const struct acpi_config *config); +uint32_t acpi_get_table_size(struct acpi_header * header); int acpi_build_tables(struct acpi_ctxt *ctxt, struct acpi_config *config); #endif /* __LIBACPI_H__ */ diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c index 5d914a5..f8d61c2 100644 --- a/tools/libxl/libxl_dom.c +++ b/tools/libxl/libxl_dom.c @@ -19,11 +19,13 @@ #include "libxl_internal.h" #include "libxl_arch.h" +#include "libacpi/libacpi.h" #include #include #include #include +#include #include "_paths.h" @@ -925,6 +927,43 @@ out: return rc; } +static unsigned long acpi_v2p(struct acpi_ctxt *ctxt, void *v) +{ + return (unsigned long)v; +} + +static void *acpi_mem_alloc(struct acpi_ctxt *ctxt, + uint32_t size, uint32_t align) +{ + return aligned_alloc(align, size); +} + +static void acpi_mem_free(struct acpi_ctxt *ctxt, + void *v, uint32_t size) +{ + /* ACPI builder currently doesn't free memory so this is just a stub */ +} + +static int libxl__acpi_build_dmar(libxl__gc *gc, + struct acpi_config *config, + void **data_r, int *datalen_r) +{ + struct acpi_ctxt ctxt; + void *table; + + ctxt.mem_ops.alloc = acpi_mem_alloc; + ctxt.mem_ops.free = acpi_mem_free; + ctxt.mem_ops.v2p = acpi_v2p; + + table = construct_dmar(&ctxt, config); + if ( !table ) + return ERROR_FAIL; + + *data_r = table; + *datalen_r = acpi_get_table_size((struct acpi_header *)table); + return 0; +} + static int libxl__domain_firmware(libxl__gc *gc, libxl_domain_build_info *info, struct xc_dom_image *dom) @@ -1045,6 +1084,54 @@ static int libxl__domain_firmware(libxl__gc *gc, } } + /* build DMAR table according guest configuration and joint it with other + * apci tables specified by acpi_modules */ + if ((info->u.hvm.viommu.type == VIOMMU_TYPE_INTEL_VTD) && + !libxl_defbool_is_default(info->u.hvm.viommu.intremap) && + info->device_model_version == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) { + struct acpi_config config; + + memset(&config, 0, sizeof(config)); + if (libxl_defbool_val(info->u.hvm.viommu.intremap)) { + config.table_flags |= ACPI_HAS_DMAR; + config.dmar_flag = DMAR_INTR_REMAP; + if (!libxl_defbool_is_default(info->u.hvm.viommu.x2apic) + && !libxl_defbool_val(info->u.hvm.viommu.x2apic)) + config.dmar_flag |= DMAR_X2APIC_OPT_OUT; + + config.viommu_base_addr = info->u.hvm.viommu.base_addr; + data = NULL; + e = libxl__acpi_build_dmar(gc, &config, &data, &datalen); + if (e) { + LOGE(ERROR, "failed to build DMAR table"); + rc = ERROR_FAIL; + goto out; + } + + libxl__ptr_add(gc, data); + if (datalen) { + if (!dom->acpi_modules[0].data) { + dom->acpi_modules[0].data = data; + dom->acpi_modules[0].length = (uint32_t)datalen; + } else { + /* joint tables */ + void *newdata; + newdata = malloc(datalen + dom->acpi_modules[0].length); + if (!newdata) { + LOGE(ERROR, "failed to joint DMAR table to acpi modules"); + rc = ERROR_FAIL; + goto out; + } + memcpy(newdata, dom->acpi_modules[0].data, + dom->acpi_modules[0].length); + memcpy(newdata + dom->acpi_modules[0].length, data, datalen); + dom->acpi_modules[0].data = newdata; + dom->acpi_modules[0].length += (uint32_t)datalen; + } + } + } + } + return 0; out: assert(rc != 0); diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 2204425..93e9e2c 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -450,6 +450,15 @@ libxl_altp2m_mode = Enumeration("altp2m_mode", [ (3, "limited"), ], init_val = "LIBXL_ALTP2M_MODE_DISABLED") +libxl_viommu_info = Struct("viommu_info", [ + ("type", uint64), + ("intremap", libxl_defbool), + ("x2apic", libxl_defbool), + ("cap", uint64), + ("base_addr", uint64), + ("length", uint64), + ]) + libxl_domain_build_info = Struct("domain_build_info",[ ("max_vcpus", integer), ("avail_vcpus", libxl_bitmap), @@ -564,6 +573,7 @@ libxl_domain_build_info = Struct("domain_build_info",[ ("serial_list", libxl_string_list), ("rdm", libxl_rdm_reserve), ("rdm_mem_boundary_memkb", MemKB), + ("viommu", libxl_viommu_info), ])), ("pv", Struct(None, [("kernel", string), ("slack_memkb", MemKB), diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c index 856a304..584d805 100644 --- a/tools/xl/xl_parse.c +++ b/tools/xl/xl_parse.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -29,6 +30,9 @@ extern void set_default_nic_values(libxl_device_nic *nic); +#define VIOMMU_BASE_ADDR 0xfed90000UL +#define VIOMMU_REGISTER_LEN 0x1000UL + #define ARRAY_EXTEND_INIT__CORE(array,count,initfn,more) \ ({ \ typeof((count)) array_extend_old_count = (count); \ @@ -803,6 +807,32 @@ int parse_usbdev_config(libxl_device_usbdev *usbdev, char *token) return 0; } +/* Parses viommu data and adds info into viommu + * Returns 1 if the input token does not match one of the keys + * or parsed values are not correct. Successful parse returns 0 */ +static int parse_viommu_config(libxl_viommu_info *viommu, char *token) +{ + char *oparg; + + if (MATCH_OPTION("type", token, oparg)) { + if (!strcmp(oparg, "vtd")) { + viommu->type = VIOMMU_TYPE_INTEL_VTD; + } else { + fprintf(stderr, "Invalid viommu type: %s\n", oparg); + return 1; + } + } else if (MATCH_OPTION("intremap", token, oparg)) { + libxl_defbool_set(&viommu->intremap, !!strtoul(oparg, NULL, 0)); + } else if (MATCH_OPTION("x2apic", token, oparg)) { + libxl_defbool_set(&viommu->x2apic, !!strtoul(oparg, NULL, 0)); + } else { + fprintf(stderr, "Unknown string `%s' in viommu spec\n", token); + return 1; + } + + return 0; +} + void parse_config_data(const char *config_source, const char *config_data, int config_len, @@ -1182,6 +1212,40 @@ void parse_config_data(const char *config_source, if (!xlu_cfg_get_long (config, "rdm_mem_boundary", &l, 0)) b_info->u.hvm.rdm_mem_boundary_memkb = l * 1024; + + if (!xlu_cfg_get_string(config, "viommu", &buf, 0)) { + libxl_viommu_info viommu; + char *p, *str2; + + str2 = strdup(buf); + if (!str2) { + fprintf(stderr, "ERROR: strdup failed\n"); + exit (1); + } + p = strtok(str2, ","); + if (!p) { + fprintf(stderr, "ERROR: invalid viommu_info format\n"); + exit (1); + } + do { + if (*p == ' ') + p++; + if (parse_viommu_config(&viommu, p)) { + fprintf(stderr, "ERROR: invalid viommu setting\n"); + exit (1); + } + } while ((p=strtok(NULL, ",")) != NULL); + free(str2); + b_info->u.hvm.viommu.type = viommu.type; + b_info->u.hvm.viommu.intremap = viommu.intremap; + b_info->u.hvm.viommu.x2apic = viommu.x2apic; + if ( libxl_defbool_val(b_info->u.hvm.viommu.intremap) ) + { + b_info->u.hvm.viommu.cap = VIOMMU_CAP_IRQ_REMAPPING; + b_info->u.hvm.viommu.base_addr = VIOMMU_BASE_ADDR; + b_info->u.hvm.viommu.length = VIOMMU_REGISTER_LEN; + } + } break; case LIBXL_DOMAIN_TYPE_PV: {