From patchwork Tue Jan 13 14:25:16 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Grall X-Patchwork-Id: 43000 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ee0-f72.google.com (mail-ee0-f72.google.com [74.125.83.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id A83E720DE8 for ; Tue, 13 Jan 2015 14:28:03 +0000 (UTC) Received: by mail-ee0-f72.google.com with SMTP id e53sf2094357eek.3 for ; Tue, 13 Jan 2015 06:28:02 -0800 (PST) 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=iLgMDqEcs9qmuY4bXNxAbNUG29iMmtDLneK0TL3jnok=; b=OCckpzJX51QqBDhjJniubwtck2zK09iHroobXzFqe/Ebd7N9M4pfblnkSJz9OqIWUI KusqwxL1o6pZn6t/NgW0qGGs/n4sUj020okFfpE260uKsYHpnBFxa6i/qWzGOIntnVdo zCnu+96oPBvbbuTYjWVfFrotUgY6lK2MbXbguZUIW07zN5AkhdxLfYX/OMggw0NGshxR JS+fiux18zEtEWJFd4lZjjUoZztevdlF5MP9uVwTr4vgYMTrx2QqATjy8Az6H5WVgPWs f2k9oloxmvIhsJieT/AOUNDnIhv+GJVx9J+Y2mfWD5K6bBcYL9kbwqDBPfNVOM73m/U6 CV9Q== X-Gm-Message-State: ALoCoQmvnEkC4kqjBlhKhgqFyrAe++YZf5x8IQpum9eaAjm0dRmCJ0sncw5clux1pA3DqlRuEvnr X-Received: by 10.180.76.40 with SMTP id h8mr2899010wiw.3.1421159282913; Tue, 13 Jan 2015 06:28:02 -0800 (PST) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.37.104 with SMTP id x8ls3644laj.4.gmail; Tue, 13 Jan 2015 06:28:02 -0800 (PST) X-Received: by 10.152.37.168 with SMTP id z8mr42672499laj.63.1421159282704; Tue, 13 Jan 2015 06:28:02 -0800 (PST) Received: from mail-la0-f53.google.com (mail-la0-f53.google.com. [209.85.215.53]) by mx.google.com with ESMTPS id t1si3122766laa.10.2015.01.13.06.28.02 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 13 Jan 2015 06:28:02 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.53 as permitted sender) client-ip=209.85.215.53; Received: by mail-la0-f53.google.com with SMTP id gm9so2865729lab.12 for ; Tue, 13 Jan 2015 06:28:02 -0800 (PST) X-Received: by 10.112.30.71 with SMTP id q7mr42684998lbh.41.1421159282550; Tue, 13 Jan 2015 06:28:02 -0800 (PST) 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.9.200 with SMTP id c8csp1398798lbb; Tue, 13 Jan 2015 06:28:01 -0800 (PST) X-Received: by 10.140.29.138 with SMTP id b10mr56555816qgb.34.1421159272944; Tue, 13 Jan 2015 06:27:52 -0800 (PST) Received: from lists.xen.org (lists.xen.org. [50.57.142.19]) by mx.google.com with ESMTPS id y2si26911895qal.99.2015.01.13.06.27.52 (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 13 Jan 2015 06:27:52 -0800 (PST) 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 1YB2QY-0001BR-LA; Tue, 13 Jan 2015 14:26:38 +0000 Received: from mail6.bemta14.messagelabs.com ([193.109.254.103]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1YB2QW-000196-8K for xen-devel@lists.xenproject.org; Tue, 13 Jan 2015 14:26:36 +0000 Received: from [193.109.254.147] by server-7.bemta-14.messagelabs.com id 5E/99-27785-B1B25B45; Tue, 13 Jan 2015 14:26:35 +0000 X-Env-Sender: julien.grall@linaro.org X-Msg-Ref: server-8.tower-27.messagelabs.com!1421159193!20326390!1 X-Originating-IP: [74.125.82.177] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 6.12.5; banners=-,-,- X-VirusChecked: Checked Received: (qmail 20729 invoked from network); 13 Jan 2015 14:26:34 -0000 Received: from mail-we0-f177.google.com (HELO mail-we0-f177.google.com) (74.125.82.177) by server-8.tower-27.messagelabs.com with RC4-SHA encrypted SMTP; 13 Jan 2015 14:26:34 -0000 Received: by mail-we0-f177.google.com with SMTP id q59so3192353wes.8 for ; Tue, 13 Jan 2015 06:26:33 -0800 (PST) X-Received: by 10.180.107.70 with SMTP id ha6mr4861167wib.71.1421159193331; Tue, 13 Jan 2015 06:26:33 -0800 (PST) Received: from chilopoda.uk.xensource.com. ([185.25.64.249]) by mx.google.com with ESMTPSA id ni15sm14513482wic.18.2015.01.13.06.26.31 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Jan 2015 06:26:32 -0800 (PST) From: Julien Grall To: xen-devel@lists.xenproject.org Date: Tue, 13 Jan 2015 14:25:16 +0000 Message-Id: <1421159133-31526-8-git-send-email-julien.grall@linaro.org> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1421159133-31526-1-git-send-email-julien.grall@linaro.org> References: <1421159133-31526-1-git-send-email-julien.grall@linaro.org> Cc: stefano.stabellini@citrix.com, Julien Grall , tim@xen.org, ian.campbell@citrix.com Subject: [Xen-devel] [PATCH v3 07/24] 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.215.53 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). 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 --- 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 | 7 ++ xen/arch/arm/device.c | 2 +- xen/arch/arm/domain_build.c | 102 ++++++++++++++++++++++-------- xen/common/device_tree.c | 6 ++ xen/include/xen/device_tree.h | 11 ++++ 5 files changed, 100 insertions(+), 28 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..04645b3 --- /dev/null +++ b/docs/misc/arm/device-tree/passthrough.txt @@ -0,0 +1,7 @@ +Device passthrough +=================== + +Any device that will be passthrough to a guest should have a property +"xen,passthrough" in their device tree node. + +The device won't be exposed to DOM0 and therefore no driver will be loaded. diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c index 1993929..1a01793 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_match type, 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 f68755f..b48b5d0 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; @@ -919,8 +943,14 @@ 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; @@ -929,13 +959,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); @@ -947,7 +979,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); @@ -980,22 +1012,34 @@ static int map_device(struct domain *d, struct dt_device_node *dev) irq = res; DPRINT("irq %u = %u\n", i, irq); - /* - * 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)); + + 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); @@ -1019,17 +1063,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; + } } } @@ -1104,7 +1152,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 bb9d7ce..ce10574 100644 --- a/xen/common/device_tree.c +++ b/xen/common/device_tree.c @@ -1103,6 +1103,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 890d356..caaf65f 100644 --- a/xen/include/xen/device_tree.h +++ b/xen/include/xen/device_tree.h @@ -555,6 +555,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