From patchwork Thu Mar 19 19:29:32 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Grall X-Patchwork-Id: 46106 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f200.google.com (mail-wi0-f200.google.com [209.85.212.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id BE6A021515 for ; Thu, 19 Mar 2015 19:32:48 +0000 (UTC) Received: by wibbs8 with SMTP id bs8sf14588553wib.3 for ; Thu, 19 Mar 2015 12:32:48 -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=UtH8R4QbUwSQ6B+/eCXaLcPPzhGXlSOlvxCLanDwhdk=; b=DJa2RiVr9My+glq2r4BdOBakyZxOhE8MWjvHcsxS+V+xhuzkdYHauuw8WC4vaT9TGt NsBipAGiW7GbOgU8YOhOcLHC4gObGP2MfOfBB9dpndQpaVJxHEZa/TNomCtanF/XrVFq ty2MIxt99yAEsycP0oWvCsmtgrIkN04L7fSj7+pVf7DiZUkxsL4KCHZBX5RbcSXBcgJY fKz9rBXnglEWGc8t4bccqiqCrWxntnpjYjRQbBoiUOsS2ttz5pLPp1ocWr5vft22A6Tx nPyP125GdfYw9OrBKXA80Ar2o8OQmABCPjomQeqA7nlLDzaj0qOzxsUTM5Pu5zlU3Qnt gGfQ== X-Gm-Message-State: ALoCoQnybA1y5rsqQIFPVD2Zo0XrylG6PezxplEbQ3/Kz+6ojsQDhTuwXHw7877cmbHjVJDl1wHR X-Received: by 10.181.29.66 with SMTP id ju2mr2068546wid.1.1426793568105; Thu, 19 Mar 2015 12:32:48 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.181.137 with SMTP id dw9ls307305lac.85.gmail; Thu, 19 Mar 2015 12:32:47 -0700 (PDT) X-Received: by 10.152.22.104 with SMTP id c8mr107566laf.87.1426793567735; Thu, 19 Mar 2015 12:32:47 -0700 (PDT) Received: from mail-lb0-f178.google.com (mail-lb0-f178.google.com. [209.85.217.178]) by mx.google.com with ESMTPS id ti8si1617808lbb.149.2015.03.19.12.32.47 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 19 Mar 2015 12:32:47 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.178 as permitted sender) client-ip=209.85.217.178; Received: by lbblx11 with SMTP id lx11so38294274lbb.3 for ; Thu, 19 Mar 2015 12:32:47 -0700 (PDT) X-Received: by 10.152.116.11 with SMTP id js11mr48316287lab.106.1426793567602; Thu, 19 Mar 2015 12:32:47 -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 h5csp597771lbj; Thu, 19 Mar 2015 12:32:46 -0700 (PDT) X-Received: by 10.52.121.229 with SMTP id ln5mr25554292vdb.0.1426793552111; Thu, 19 Mar 2015 12:32:32 -0700 (PDT) Received: from lists.xen.org (lists.xen.org. [50.57.142.19]) by mx.google.com with ESMTPS id sq15si1979793vdb.51.2015.03.19.12.32.31 (version=TLSv1 cipher=RC4-SHA bits=128/128); Thu, 19 Mar 2015 12:32:32 -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 1YYg9a-0004E3-0Z; Thu, 19 Mar 2015 19:30:50 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1YYg9Y-0004DW-JV for xen-devel@lists.xenproject.org; Thu, 19 Mar 2015 19:30:48 +0000 Received: from [85.158.137.68] by server-16.bemta-3.messagelabs.com id 41/2C-01563-7E32B055; Thu, 19 Mar 2015 19:30:47 +0000 X-Env-Sender: julien.grall@linaro.org X-Msg-Ref: server-7.tower-31.messagelabs.com!1426793446!13802825!1 X-Originating-IP: [74.125.82.174] 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 1512 invoked from network); 19 Mar 2015 19:30:46 -0000 Received: from mail-we0-f174.google.com (HELO mail-we0-f174.google.com) (74.125.82.174) by server-7.tower-31.messagelabs.com with RC4-SHA encrypted SMTP; 19 Mar 2015 19:30:46 -0000 Received: by weop45 with SMTP id p45so65622954weo.0 for ; Thu, 19 Mar 2015 12:30:46 -0700 (PDT) X-Received: by 10.194.187.236 with SMTP id fv12mr157110869wjc.131.1426793446421; Thu, 19 Mar 2015 12:30:46 -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.30.44 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 19 Mar 2015 12:30:45 -0700 (PDT) From: Julien Grall To: xen-devel@lists.xenproject.org Date: Thu, 19 Mar 2015 19:29:32 +0000 Message-Id: <1426793399-6283-7-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: stefano.stabellini@citrix.com, Julien Grall , tim@xen.org, ian.campbell@citrix.com, Stefano Stabellini Subject: [Xen-devel] [PATCH v4 06/33] xen/arm: Introduce xen, passthrough property 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.217.178 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: When a device is marked for passthrough (via the new property "xen,passthrough"), dom0 must not access to the device (i.e not loading a driver), but should be able to manage the MMIO/interrupt of the passthrough device. The latter part will allow the toolstack to map MMIO/IRQ when a device is pass through to a guest. The property "xen,passthrough" will be translated as 'status="disabled"' in the device tree to avoid DOM0 using the device. We assume that DOM0 is able to cope with this property (already the case for Linux, and required by ePAPR). Rework the function map_device (renamed into handle_device) to: * For a given device node: - Give permission to manage IRQ/MMIO for this device - Retrieve the IRQ configuration (i.e edge/level) from the device tree * When the device is not marked for guest passthrough: - Assign the device to the guest if it's protected by an IOMMU - Map the IRQs and MMIOs regions to the guest Signed-off-by: Julien Grall Acked-by: Stefano Stabellini --- Changes in v4: - Add Stefano's ack - Rebase on the latest staging (no function changes) - Rework the device passthrough documentation to be weaker - Coding style and typoes Changes in v3: - This patch was formely "xen/arm: Follow-up to allow DOM0 manage IRQ and MMIO". It has been split in 2 parts [1]. - Update commit title and improve message - Remove spurious change [1] https://patches.linaro.org/34669/ --- docs/misc/arm/device-tree/passthrough.txt | 9 +++ xen/arch/arm/device.c | 2 +- xen/arch/arm/domain_build.c | 97 ++++++++++++++++++++++++------- xen/common/device_tree.c | 6 ++ xen/include/xen/device_tree.h | 11 ++++ 5 files changed, 103 insertions(+), 22 deletions(-) create mode 100644 docs/misc/arm/device-tree/passthrough.txt diff --git a/docs/misc/arm/device-tree/passthrough.txt b/docs/misc/arm/device-tree/passthrough.txt new file mode 100644 index 0000000..6715646 --- /dev/null +++ b/docs/misc/arm/device-tree/passthrough.txt @@ -0,0 +1,9 @@ +Device passthrough +=================== + +Any device with the property "xen,passthrough" set will not be exposed to +DOM0 and therefore no driver will be loaded. + +It is highly recommended to set this property on devices which are passed +through since many devices will not cope with being accessed by dom0 and +then handed over to another domain. diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c index 675784c..0b53f6a 100644 --- a/xen/arch/arm/device.c +++ b/xen/arch/arm/device.c @@ -30,7 +30,7 @@ int __init device_init(struct dt_device_node *dev, enum device_class class, ASSERT(dev != NULL); - if ( !dt_device_is_available(dev) ) + if ( !dt_device_is_available(dev) || dt_device_for_passthrough(dev) ) return -ENODEV; for ( desc = _sdevice; desc != _edevice; desc++ ) diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index 31b32df..2eb31ad 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -402,7 +402,7 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo, const struct dt_device_node *node) { const char *bootargs = NULL; - const struct dt_property *prop; + const struct dt_property *prop, *status = NULL; int res = 0; int had_dom0_bootargs = 0; @@ -457,6 +457,17 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo, } } + /* Don't expose the property "xen,passthrough" to the guest */ + if ( dt_property_name_is_equal(prop, "xen,passthrough") ) + continue; + + /* Remember and skip the status property as Xen may modify it later */ + if ( dt_property_name_is_equal(prop, "status") ) + { + status = prop; + continue; + } + res = fdt_property(kinfo->fdt, prop->name, prop_data, prop_len); xfree(new_data); @@ -465,6 +476,19 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo, return res; } + /* + * Override the property "status" to disable the device when it's + * marked for passthrough. + */ + if ( dt_device_for_passthrough(node) ) + res = fdt_property_string(kinfo->fdt, "status", "disabled"); + else if ( status ) + res = fdt_property(kinfo->fdt, "status", status->value, + status->length); + + if ( res ) + return res; + if ( dt_node_path_is_equal(node, "/chosen") ) { const struct bootmodule *mod = kinfo->initrd_bootmodule; @@ -903,8 +927,15 @@ static int make_timer_node(const struct domain *d, void *fdt, return res; } -/* Map the device in the domain */ -static int map_device(struct domain *d, struct dt_device_node *dev) +/* + * For a given device node: + * - Give permission to the guest to manage IRQ and MMIO range + * - Retrieve the IRQ configuration (i.e edge/level) from device tree + * When the device is not marked for guest passthrough: + * - Assign the device to the guest if it's protected by an IOMMU + * - Map the IRQs and iomem regions to DOM0 + */ +static int handle_device(struct domain *d, struct dt_device_node *dev) { unsigned int nirq; unsigned int naddr; @@ -913,13 +944,15 @@ static int map_device(struct domain *d, struct dt_device_node *dev) unsigned int irq; struct dt_raw_irq rirq; u64 addr, size; + bool_t need_mapping = !dt_device_for_passthrough(dev); nirq = dt_number_of_irq(dev); naddr = dt_number_of_address(dev); - DPRINT("%s nirq = %d naddr = %u\n", dt_node_full_name(dev), nirq, naddr); + DPRINT("%s passthrough = %d nirq = %d naddr = %u\n", dt_node_full_name(dev), + need_mapping, nirq, naddr); - if ( dt_device_is_protected(dev) ) + if ( dt_device_is_protected(dev) && need_mapping ) { DPRINT("%s setup iommu\n", dt_node_full_name(dev)); res = iommu_assign_dt_device(d, dev); @@ -931,7 +964,7 @@ static int map_device(struct domain *d, struct dt_device_node *dev) } } - /* Map IRQs */ + /* Give permission and map IRQs */ for ( i = 0; i < nirq; i++ ) { res = dt_device_get_raw_irq(dev, i, &rirq); @@ -970,16 +1003,34 @@ static int map_device(struct domain *d, struct dt_device_node *dev) * the IRQ twice. This can legitimately happen if the IRQ is shared */ vgic_reserve_virq(d, irq); - res = route_irq_to_guest(d, irq, dt_node_name(dev)); + + res = irq_permit_access(d, irq); if ( res ) { - printk(XENLOG_ERR "Unable to route IRQ %u to domain %u\n", - irq, d->domain_id); + printk(XENLOG_ERR "Unable to permit to dom%u access to IRQ %u\n", + d->domain_id, irq); return res; } + + if ( need_mapping ) + { + /* + * Checking the return of vgic_reserve_virq is not + * necessary. It should not fail except when we try to map + * twice the IRQ. This can happen if the IRQ is shared + */ + vgic_reserve_virq(d, irq); + res = route_irq_to_guest(d, irq, dt_node_name(dev)); + if ( res ) + { + printk(XENLOG_ERR "Unable to route IRQ %u to domain %u\n", + irq, d->domain_id); + return res; + } + } } - /* Map the address ranges */ + /* Give permission and map MMIOs */ for ( i = 0; i < naddr; i++ ) { res = dt_device_get_address(dev, i, &addr, &size); @@ -1003,17 +1054,21 @@ static int map_device(struct domain *d, struct dt_device_node *dev) addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1); return res; } - res = map_mmio_regions(d, - paddr_to_pfn(addr & PAGE_MASK), - DIV_ROUND_UP(size, PAGE_SIZE), - paddr_to_pfn(addr & PAGE_MASK)); - if ( res ) + + if ( need_mapping ) { - printk(XENLOG_ERR "Unable to map 0x%"PRIx64 - " - 0x%"PRIx64" in domain %d\n", - addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1, - d->domain_id); - return res; + res = map_mmio_regions(d, + paddr_to_pfn(addr & PAGE_MASK), + DIV_ROUND_UP(size, PAGE_SIZE), + paddr_to_pfn(addr & PAGE_MASK)); + if ( res ) + { + printk(XENLOG_ERR "Unable to map 0x%"PRIx64 + " - 0x%"PRIx64" in domain %d\n", + addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1, + d->domain_id); + return res; + } } } @@ -1085,7 +1140,7 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo, return 0; } - res = map_device(d, node); + res = handle_device(d, node); if ( res) return res; diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c index 25880e8..02cae91 100644 --- a/xen/common/device_tree.c +++ b/xen/common/device_tree.c @@ -1104,6 +1104,12 @@ bool_t dt_device_is_available(const struct dt_device_node *device) return 0; } +bool_t dt_device_for_passthrough(const struct dt_device_node *device) +{ + return (dt_find_property(device, "xen,passthrough", NULL) != NULL); + +} + static int __dt_parse_phandle_with_args(const struct dt_device_node *np, const char *list_name, const char *cells_name, diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h index 6bbee6d..57eb3ee 100644 --- a/xen/include/xen/device_tree.h +++ b/xen/include/xen/device_tree.h @@ -556,6 +556,17 @@ int dt_n_addr_cells(const struct dt_device_node *np); bool_t dt_device_is_available(const struct dt_device_node *device); /** + * dt_device_for_passthrough - Check if a device will be used for + * passthrough later + * + * @device: Node to check + * + * Return true if the property "xen,passthrough" is present in the node, + * false otherwise. + */ +bool_t dt_device_for_passthrough(const struct dt_device_node *device); + +/** * dt_match_node - Tell if a device_node has a matching of dt_device_match * @matches: array of dt_device_match structures to search in * @node: the dt_device_node structure to match against