From patchwork Wed Apr 1 16:21:39 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Grall X-Patchwork-Id: 46636 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f199.google.com (mail-wi0-f199.google.com [209.85.212.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 8778A218CA for ; Wed, 1 Apr 2015 16:24:32 +0000 (UTC) Received: by wibdy1 with SMTP id dy1sf12823511wib.3 for ; Wed, 01 Apr 2015 09:24:31 -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:mime-version:cc:subject:precedence:list-id :list-unsubscribe:list-post:list-help:list-subscribe:content-type :content-transfer-encoding:sender:errors-to:x-original-sender :x-original-authentication-results:mailing-list:list-archive; bh=DWviijOiGU1Hp7O7NWGEAkysgMPzPpIyrnISGdtdpcI=; b=i/Mol+uueO0RJuqR/URjKqVmErVcdwE/273yABIeoqt8ldUH05r34Qve85nzt0Z78u wqkQqNh/IrmefQs3wWDI1vuWONnLvtuXsV6PnrUOnAfGy1T+Oa76AJ4w81fjHR8Sfjib Sbswcht7Mg6ETgxifn/pLTtZD6l/SyidXH3kcxGvbj2ZMxKl22DWJqxFkGdjAEpHKUXT 2ia+qQyxy2HmFeLUQ8Q96JMyS7sOyUutxGveGmq9J2uVR6XRcD2xH5t5aKHgXO1HHWFw +/9M6GBttGRDUGarCP8BPmPOrQmkc2WcHZy/36D2iwDl2cJVegNTCRF7kboyIrI1gb6b I+mg== X-Gm-Message-State: ALoCoQnOWQDzk5EfFPaF2M5uGddYYi1YVj1UBoWxspGBU0zHpZc/bw+kFnD5trukIBJ5fGPwnwpp X-Received: by 10.112.148.10 with SMTP id to10mr9944693lbb.18.1427905471759; Wed, 01 Apr 2015 09:24:31 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.44.136 with SMTP id e8ls109171lam.91.gmail; Wed, 01 Apr 2015 09:24:31 -0700 (PDT) X-Received: by 10.152.204.168 with SMTP id kz8mr13216107lac.70.1427905471568; Wed, 01 Apr 2015 09:24:31 -0700 (PDT) Received: from mail-lb0-f179.google.com (mail-lb0-f179.google.com. [209.85.217.179]) by mx.google.com with ESMTPS id g7si2003989lbd.52.2015.04.01.09.24.31 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 01 Apr 2015 09:24:31 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.179 as permitted sender) client-ip=209.85.217.179; Received: by lbbzk7 with SMTP id zk7so24039375lbb.0 for ; Wed, 01 Apr 2015 09:24:31 -0700 (PDT) X-Received: by 10.152.23.70 with SMTP id k6mr7805743laf.76.1427905471335; Wed, 01 Apr 2015 09:24:31 -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.57.201 with SMTP id k9csp771098lbq; Wed, 1 Apr 2015 09:24:30 -0700 (PDT) X-Received: by 10.52.104.105 with SMTP id gd9mr44461708vdb.76.1427905469224; Wed, 01 Apr 2015 09:24:29 -0700 (PDT) Received: from lists.xen.org (lists.xen.org. [50.57.142.19]) by mx.google.com with ESMTPS id vm13si1682556vdb.9.2015.04.01.09.24.28 (version=TLSv1 cipher=RC4-SHA bits=128/128); Wed, 01 Apr 2015 09:24:29 -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 1YdLPn-0004h8-KF; Wed, 01 Apr 2015 16:22:51 +0000 Received: from mail6.bemta14.messagelabs.com ([193.109.254.103]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1YdLPl-0004ft-S2 for xen-devel@lists.xenproject.org; Wed, 01 Apr 2015 16:22:50 +0000 Received: from [193.109.254.147] by server-5.bemta-14.messagelabs.com id 4E/44-05046-95B1C155; Wed, 01 Apr 2015 16:22:49 +0000 X-Env-Sender: julien.grall@citrix.com X-Msg-Ref: server-15.tower-27.messagelabs.com!1427905365!14999781!3 X-Originating-IP: [66.165.176.63] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n, received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 6.13.6; banners=-,-,- X-VirusChecked: Checked Received: (qmail 32614 invoked from network); 1 Apr 2015 16:22:48 -0000 Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63) by server-15.tower-27.messagelabs.com with RC4-SHA encrypted SMTP; 1 Apr 2015 16:22:48 -0000 X-IronPort-AV: E=Sophos;i="5.11,504,1422921600"; d="scan'208";a="250389331" From: Julien Grall To: Date: Wed, 1 Apr 2015 17:21:39 +0100 Message-ID: <1427905307-23749-7-git-send-email-julien.grall@citrix.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1427905307-23749-1-git-send-email-julien.grall@citrix.com> References: <1427905307-23749-1-git-send-email-julien.grall@citrix.com> MIME-Version: 1.0 X-DLP: MIA1 Cc: stefano.stabellini@citrix.com, Julien Grall , tim@xen.org, ian.campbell@citrix.com, Stefano Stabellini Subject: [Xen-devel] [PATCH v5 p1 06/14] 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: , 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: patch@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.179 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: From: Julien Grall 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 Acked-by: Ian Campbell --- Changes in v5: - Add Ian's ack 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