From patchwork Thu Mar 19 19:29:55 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Grall X-Patchwork-Id: 46118 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-we0-f198.google.com (mail-we0-f198.google.com [74.125.82.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 585BA21515 for ; Thu, 19 Mar 2015 19:33:23 +0000 (UTC) Received: by wesu56 with SMTP id u56sf14149151wes.2 for ; Thu, 19 Mar 2015 12:33:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id:in-reply-to :references:cc:subject:precedence:list-id:list-unsubscribe:list-post :list-help:list-subscribe:mime-version:content-type :content-transfer-encoding:sender:errors-to:x-original-sender :x-original-authentication-results:mailing-list:list-archive; bh=2Xuv2rLl3d7RwLoH1iLuMjFNwCgWug4/Z2BjnXBNdSw=; b=KTzsPOTFubYM9dadqBCeeeGlsZqlmqT1KFg2PFCDSvGcj0wqQLkoaP9cNXbaab2w1P jXcOD8Vx+GEbe0oi0EH3Gx0ob8j2+bxmLI5uOmip9rKs/uE+CuOcGffyhp35FtUzG4zH a2RIR5GiW4PIupkDil+vRLL0HsPWhDa2br9LijA583/1gm0BnBSd5CqvSUdV+8E+7fRF jQwOOGKK3npgvL9WbaCkbeuVUtbV1HLbDpT8j9yIxcF1Yeiv/2IN201Mf5prGKKn+A4P LZ4M1l+4G66sNGn3DwO0mKrAISM++1x3a/ftcjYUB30Yn/LhCN3GWtXqWMUhyLfmrOGw CzzQ== X-Gm-Message-State: ALoCoQkGnt7aIPjAYB+bZuRIbHZBKul3E7rfM8mdkLUsmShIFxUZsp7HG2tCtA3uh8yGstolNLh0 X-Received: by 10.112.98.38 with SMTP id ef6mr11490734lbb.3.1426793602633; Thu, 19 Mar 2015 12:33:22 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.36.36 with SMTP id n4ls286791laj.27.gmail; Thu, 19 Mar 2015 12:33:22 -0700 (PDT) X-Received: by 10.112.160.165 with SMTP id xl5mr44829359lbb.109.1426793602167; Thu, 19 Mar 2015 12:33:22 -0700 (PDT) Received: from mail-la0-f46.google.com (mail-la0-f46.google.com. [209.85.215.46]) by mx.google.com with ESMTPS id y8si1645561lad.102.2015.03.19.12.33.22 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 19 Mar 2015 12:33:22 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.46 as permitted sender) client-ip=209.85.215.46; Received: by lagg8 with SMTP id g8so70678266lag.1 for ; Thu, 19 Mar 2015 12:33:22 -0700 (PDT) X-Received: by 10.152.206.70 with SMTP id lm6mr71452859lac.35.1426793602054; Thu, 19 Mar 2015 12:33:22 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.35.133 with SMTP id h5csp598050lbj; Thu, 19 Mar 2015 12:33:21 -0700 (PDT) X-Received: by 10.140.23.227 with SMTP id 90mr7330403qgp.84.1426793573229; Thu, 19 Mar 2015 12:32:53 -0700 (PDT) Received: from lists.xen.org (lists.xen.org. [50.57.142.19]) by mx.google.com with ESMTPS id 124si2182558qht.74.2015.03.19.12.32.52 (version=TLSv1 cipher=RC4-SHA bits=128/128); Thu, 19 Mar 2015 12:32:53 -0700 (PDT) Received-SPF: none (google.com: xen-devel-bounces@lists.xen.org does not designate permitted sender hosts) client-ip=50.57.142.19; Received: from localhost ([127.0.0.1] helo=lists.xen.org) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1YYgAA-0005SR-Mk; Thu, 19 Mar 2015 19:31:26 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1YYgA8-0005Lf-Jz for xen-devel@lists.xenproject.org; Thu, 19 Mar 2015 19:31:24 +0000 Received: from [85.158.137.68] by server-1.bemta-3.messagelabs.com id E3/79-02005-B042B055; Thu, 19 Mar 2015 19:31:23 +0000 X-Env-Sender: julien.grall@linaro.org X-Msg-Ref: server-9.tower-31.messagelabs.com!1426793482!10091447!1 X-Originating-IP: [74.125.82.175] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 6.13.4; banners=-,-,- X-VirusChecked: Checked Received: (qmail 21175 invoked from network); 19 Mar 2015 19:31:22 -0000 Received: from mail-we0-f175.google.com (HELO mail-we0-f175.google.com) (74.125.82.175) by server-9.tower-31.messagelabs.com with RC4-SHA encrypted SMTP; 19 Mar 2015 19:31:22 -0000 Received: by weop45 with SMTP id p45so65634579weo.0 for ; Thu, 19 Mar 2015 12:31:22 -0700 (PDT) X-Received: by 10.194.185.9 with SMTP id ey9mr157225363wjc.135.1426793481130; Thu, 19 Mar 2015 12:31:21 -0700 (PDT) Received: from chilopoda.uk.xensource.com. ([185.25.64.249]) by mx.google.com with ESMTPSA id hl8sm3203005wjb.38.2015.03.19.12.31.19 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 19 Mar 2015 12:31:20 -0700 (PDT) From: Julien Grall To: xen-devel@lists.xenproject.org Date: Thu, 19 Mar 2015 19:29:55 +0000 Message-Id: <1426793399-6283-30-git-send-email-julien.grall@linaro.org> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1426793399-6283-1-git-send-email-julien.grall@linaro.org> References: <1426793399-6283-1-git-send-email-julien.grall@linaro.org> Cc: Wei Liu , ian.campbell@citrix.com, tim@xen.org, Julien Grall , Ian Jackson , stefano.stabellini@citrix.com Subject: [Xen-devel] [PATCH v4 29/33] tools/(lib)xl: Add partial device tree support for ARM X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: List-Unsubscribe: , List-Post: , List-Help: , List-Subscribe: , MIME-Version: 1.0 Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: julien.grall@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.46 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Archive: Let the user to pass additional nodes to the guest device tree. For this purpose, everything in the node /passthrough from the partial device tree will be copied into the guest device tree. The node /aliases will be also copied to allow the user to define aliases which can be used by the guest kernel. A simple partial device tree will look like: /dts-v1/; / { #address-cells = <2>; #size-cells = <2>; passthrough { compatible = "simple-bus"; ranges; #address-cells = <2>; #size-cells = <2>; /* List of your nodes */ } }; Note that: * The interrupt-parent property will be added by the toolstack in the root node * The properties compatible, ranges, #address-cells and #size-cells in /passthrough are mandatory. The helpers provided by the libfdt don't perform all the necessary security check on a given device tree. Therefore, only trusted device tree should be used. Signed-off-by: Julien Grall Cc: Ian Jackson Cc: Wei Liu --- An example of the partial device tree, as long as how to passthrough a non-pci device will be added to the tree in a follow-up patch. A new LIBXL_HAVE_* will be added in the patch which add support for non-PCI passthrough as both are tight. Changes in v4: - Mark the option as unsafe - The _fdt_* helpers has been moved in a separate patch/file. Only the prototype is declared - The partial DT is considered valid. Remove some security check which make the code cleaner - Typoes Changes in v3: - Patch added --- docs/man/xl.cfg.pod.5 | 10 +++ tools/libxl/libxl_arm.c | 171 ++++++++++++++++++++++++++++++++++++++++++++ tools/libxl/libxl_types.idl | 1 + tools/libxl/xl_cmdimpl.c | 1 + 4 files changed, 183 insertions(+) diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5 index 93cd7d2..bcbc277 100644 --- a/docs/man/xl.cfg.pod.5 +++ b/docs/man/xl.cfg.pod.5 @@ -453,6 +453,16 @@ not emulated. Specify that this domain is a driver domain. This enables certain features needed in order to run a driver domain. +=item B + +Specify a partial device tree (compiled via the Device Tree Compiler). +Everything under the node "/passthrough" will be copied into the guest +device tree. For convenience, the node "/aliases" is also copied to allow +the user to defined aliases which can be used by the guest kernel. + +Given the complexity of verifying the validity of a device tree, this +option should only be used with trusted device tree. + =back =head2 Devices diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c index 06e940b..54d197b 100644 --- a/tools/libxl/libxl_arm.c +++ b/tools/libxl/libxl_arm.c @@ -542,6 +542,156 @@ out: } } +/* Only FDT v17 is supported */ +#define FDT_REQUIRED_VERSION 0x11 + +static int check_partial_fdt(libxl__gc *gc, void *fdt, size_t size) +{ + int r; + + if (size < FDT_V17_SIZE) { + LOG(ERROR, "Partial FDT is too small"); + return ERROR_FAIL; + } + + if (fdt_magic(fdt) != FDT_MAGIC) { + LOG(ERROR, "Partial FDT is not a valid Flat Device Tree"); + return ERROR_FAIL; + } + + if (fdt_version(fdt) != FDT_REQUIRED_VERSION) { + LOG(ERROR, "Partial FDT version not supported. Required 0x%x got 0x%x", + FDT_REQUIRED_VERSION, fdt_version(fdt)); + return ERROR_FAIL; + } + + r = fdt_check_header(fdt); + if (r) { + LOG(ERROR, "Failed to check the partial FDT (%d)", r); + return ERROR_FAIL; + } + + if (fdt_totalsize(fdt) > size) { + LOG(ERROR, "Partial FDT totalsize is too big"); + return ERROR_FAIL; + } + + return 0; +} + +static int copy_properties(libxl__gc *gc, void *fdt, void *pfdt, + int nodeoff) +{ + int propoff, nameoff, r; + const struct fdt_property *prop; + + for (propoff = fdt_first_property_offset(pfdt, nodeoff); + propoff >= 0; + propoff = fdt_next_property_offset(pfdt, propoff)) { + + if (!(prop = fdt_get_property_by_offset(pfdt, propoff, NULL))) { + return -FDT_ERR_INTERNAL; + } + + nameoff = fdt32_to_cpu(prop->nameoff); + r = fdt_property(fdt, fdt_string(pfdt, nameoff), + prop->data, fdt32_to_cpu(prop->len)); + if (r) return r; + } + + /* FDT_ERR_NOTFOUND => There is no more properties for this node */ + return (propoff != -FDT_ERR_NOTFOUND)? propoff : 0; +} + +/* + * These functions are defined by libfdt or libxl_fdt.c if it's not + * present on the former. + */ +int fdt_next_subnode(const void *fdt, int offset); +int fdt_first_subnode(const void *fdt, int offset); + +/* Copy a node from the partial device tree to the guest device tree */ +static int copy_node(libxl__gc *gc, void *fdt, void *pfdt, + int nodeoff, int depth) +{ + int r; + + r = fdt_begin_node(fdt, fdt_get_name(pfdt, nodeoff, NULL)); + if (r) return r; + + r = copy_properties(gc, fdt, pfdt, nodeoff); + if (r) return r; + + for (nodeoff = fdt_first_subnode(pfdt, nodeoff); + nodeoff >= 0; + nodeoff = fdt_next_subnode(pfdt, nodeoff)) { + r = copy_node(gc, fdt, pfdt, nodeoff, depth + 1); + if (r) return r; + } + + if (nodeoff != -FDT_ERR_NOTFOUND) + return nodeoff; + + r = fdt_end_node(fdt); + if (r) return r; + + return 0; +} + +static int copy_node_by_path(libxl__gc *gc, const char *path, + void *fdt, void *pfdt) +{ + int nodeoff, r; + const char *name = strrchr(path, '/'); + + if (!name) + return -FDT_ERR_INTERNAL; + + name++; + + /* + * The FDT function to look at a node doesn't take into account the + * unit (i.e anything after @) when search by name. Check if the + * name exactly matches. + */ + nodeoff = fdt_path_offset(pfdt, path); + if (nodeoff < 0) + return nodeoff; + + if (strcmp(fdt_get_name(pfdt, nodeoff, NULL), name)) + return -FDT_ERR_NOTFOUND; + + r = copy_node(gc, fdt, pfdt, nodeoff, 0); + if (r) return r; + + return 0; +} + +/* + * The partial device tree is not copied entirely. Only the relevant bits are + * copied to the guest device tree: + * - /passthrough node + * - /aliases node + */ +static int copy_partial_fdt(libxl__gc *gc, void *fdt, void *pfdt) +{ + int r; + + r = copy_node_by_path(gc, "/passthrough", fdt, pfdt); + if (r < 0) { + LOG(ERROR, "Can't copy the node \"/passthrough\" from the partial FDT"); + return r; + } + + r = copy_node_by_path(gc, "/aliases", fdt, pfdt); + if (r < 0 && r != -FDT_ERR_NOTFOUND) { + LOG(ERROR, "Can't copy the node \"/aliases\" from the partial FDT"); + return r; + } + + return 0; +} + #define FDT_MAX_SIZE (1<<20) int libxl__arch_domain_init_hw_description(libxl__gc *gc, @@ -550,8 +700,10 @@ int libxl__arch_domain_init_hw_description(libxl__gc *gc, struct xc_dom_image *dom) { void *fdt = NULL; + void *pfdt = NULL; int rc, res; size_t fdt_size = 0; + int pfdt_size = 0; const libxl_version_info *vers; const struct arch_info *ainfo; @@ -571,6 +723,22 @@ int libxl__arch_domain_init_hw_description(libxl__gc *gc, vers->xen_version_major, vers->xen_version_minor); LOG(DEBUG, " - vGIC version: %s\n", gicv_to_string(xc_config->gic_version)); + if (info->device_tree) { + LOG(DEBUG, " - Partial device tree provided: %s", info->device_tree); + + rc = libxl_read_file_contents(CTX, info->device_tree, + &pfdt, &pfdt_size); + if (rc) { + LOGEV(ERROR, rc, "failed to read the partial device file %s", + info->device_tree); + return ERROR_FAIL; + } + libxl__ptr_add(gc, pfdt); + + if (check_partial_fdt(gc, pfdt, pfdt_size)) + return ERROR_FAIL; + } + /* * Call "call" handling FDT_ERR_*. Will either: * - loop back to retry_resize @@ -637,6 +805,9 @@ next_resize: FDT( make_timer_node(gc, fdt, ainfo) ); FDT( make_hypervisor_node(gc, fdt, vers) ); + if (pfdt) + FDT( copy_partial_fdt(gc, fdt, pfdt) ); + FDT( fdt_end_node(fdt) ); FDT( fdt_finish(fdt) ); diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 0866433..c97e6ed 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -411,6 +411,7 @@ libxl_domain_build_info = Struct("domain_build_info",[ ("kernel", string), ("cmdline", string), ("ramdisk", string), + ("device_tree", string), ("u", KeyedUnion(None, libxl_domain_type, "type", [("hvm", Struct(None, [("firmware", string), ("bios", libxl_bios_type), diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index 394b55d..c2415ba 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -1379,6 +1379,7 @@ static void parse_config_data(const char *config_source, xlu_cfg_replace_string (config, "kernel", &b_info->kernel, 0); xlu_cfg_replace_string (config, "ramdisk", &b_info->ramdisk, 0); + xlu_cfg_replace_string (config, "device_tree", &b_info->device_tree, 0); b_info->cmdline = parse_cmdline(config); xlu_cfg_get_defbool(config, "driver_domain", &c_info->driver_domain, 0);