From patchwork Mon Sep 30 23:28:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Stabellini X-Patchwork-Id: 11167863 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DE6BE1599 for ; Mon, 30 Sep 2019 23:30:28 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B9DCA20815 for ; Mon, 30 Sep 2019 23:30:28 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=kernel.org header.i=@kernel.org header.b="w6MNPV5G" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B9DCA20815 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iF56V-0000lK-Mp; Mon, 30 Sep 2019 23:29:19 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iF56T-0000k3-Oq for xen-devel@lists.xen.org; Mon, 30 Sep 2019 23:29:17 +0000 X-Inumbo-ID: 1cd65824-e3da-11e9-96ea-12813bfff9fa Received: from mail.kernel.org (unknown [198.145.29.99]) by localhost (Halon) with ESMTPS id 1cd65824-e3da-11e9-96ea-12813bfff9fa; Mon, 30 Sep 2019 23:29:14 +0000 (UTC) Received: from sstabellini-ThinkPad-T480s.xilinx.com (c-67-164-102-47.hsd1.ca.comcast.net [67.164.102.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 33B72218DE; Mon, 30 Sep 2019 23:29:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1569886153; bh=LI4s3NbSLn05GkkTyR/Pgd8dR/8rX/SnbCC3WdcRvEg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=w6MNPV5Ge46deBe6ICHo4tY6eSWvcXhTZWahKTN5YgH3vKKxCsHch3aMYJJZZB8Fz 3FmO2kPA2U5/9rtitGhxKjqgWAgVVuRZv4Vgy/i83J2zF5MHMhbsnd21OASurmL4Ou 2BMgOnJorSiyQwERWP3uF5Y7OwOCZR7ZZEy8Cc3A= From: Stefano Stabellini To: julien.grall@arm.com Date: Mon, 30 Sep 2019 16:28:46 -0700 Message-Id: <20190930232849.1820-5-sstabellini@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: Subject: [Xen-devel] [PATCH v7a 5/8] xen/arm: assign devices to boot domains X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Stefano Stabellini , sstabellini@kernel.org, andrii_anisov@epam.com, Achin.Gupta@arm.com, xen-devel@lists.xen.org, Volodymyr_Babchuk@epam.com MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Scan the user provided dtb fragment at boot. For each device node, map memory to guests, and route interrupts and setup the iommu. The memory region to remap is specified by the "xen,reg" property. The iommu is setup by passing the node of the device to assign on the host device tree. The path is specified in the device tree fragment as the "xen,path" string property. The interrupts are remapped based on the information from the corresponding node on the host device tree. Call handle_device_interrupts to remap interrupts. Interrupts related device tree properties are copied from the device tree fragment, same as all the other properties. Also set add the new flag XEN_DOMCTL_CDF_iommu so that dom0less domU can use the IOMMU if a partial dtb is specified. Signed-off-by: Stefano Stabellini --- Changes in v7: - improve in-code comment - code style - return 1 instead of ENOENT Changes in v6: - turn dprintks into printks - return error on page alignment check failure - set XEN_DOMCTL_CDF_iommu if partial dtb is specified Changes in v5: - use local variable for name - use map_regions_p2mt - add warning for not page aligned addresses/sizes - introduce handle_passthrough_prop Changes in v4: - use unsigned - improve commit message - code style - use dt_prop_cmp - use device_tree_get_reg - don't copy over xen,reg and xen,path - don't create special interrupt properties for domU: copy them from the fragment - in-code comment Changes in v3: - improve commit message - remove superfluous cast - merge code with the copy code - add interrup-parent - demove depth > 2 check - reuse code from handle_device_interrupts - copy interrupts from host dt Changes in v2: - rename "path" to "xen,path" - grammar fix - use gaddr_to_gfn and maddr_to_mfn - remove depth <= 2 limitation in scanning the dtb fragment - introduce and parse xen,reg - code style - support more than one interrupt per device - specify only the GIC is supported --- xen/arch/arm/domain_build.c | 115 +++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 3 deletions(-) diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index 84b65b8f25..80ac597bb6 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -1714,6 +1714,96 @@ static int __init make_vpl011_uart_node(struct kernel_info *kinfo) } #endif +/* + * Scan device tree properties for passthrough specific information. + * Returns 1 when no passthrough properties are found + * < 0 on error + * 0 on success + */ +static int __init handle_passthrough_prop(struct kernel_info *kinfo, + const struct fdt_property *prop, + const char *name, + uint32_t address_cells, uint32_t size_cells) +{ + const __be32 *cell; + unsigned int i, len; + struct dt_device_node *node; + int res; + + /* xen,reg specifies where to map the MMIO region */ + if ( dt_prop_cmp("xen,reg", name) == 0 ) + { + paddr_t mstart, size, gstart; + + cell = (const __be32 *)prop->data; + len = fdt32_to_cpu(prop->len) / + ((address_cells * 2 + size_cells) * sizeof(uint32_t)); + + for ( i = 0; i < len; i++ ) + { + device_tree_get_reg(&cell, address_cells, size_cells, + &mstart, &size); + gstart = dt_next_cell(address_cells, &cell); + + if ( gstart & ~PAGE_MASK || mstart & ~PAGE_MASK || size & ~PAGE_MASK ) + { + printk(XENLOG_ERR + "DomU passthrough config has not page aligned addresses/sizes\n"); + return -EINVAL; + } + + res = map_regions_p2mt(kinfo->d, + gaddr_to_gfn(gstart), + PFN_DOWN(size), + maddr_to_mfn(mstart), + p2m_mmio_direct_dev); + if ( res < 0 ) + { + printk(XENLOG_ERR + "Failed to map %"PRIpaddr" to the guest at%"PRIpaddr"\n", + mstart, gstart); + return -EFAULT; + } + } + + return 0; + } + /* + * xen,path specifies the corresponding node in the host DT. + * Both interrupt mappings and IOMMU settings are based on it, + * as they are done based on the corresponding host DT node. + */ + else if ( dt_prop_cmp("xen,path", name) == 0 ) + { + node = dt_find_node_by_path(prop->data); + if ( node == NULL ) + { + printk(XENLOG_ERR "Couldn't find node %s in host_dt!\n", + (char *)prop->data); + return -EINVAL; + } + + res = iommu_add_dt_device(node); + if ( res < 0 ) + return res; + + if ( dt_device_is_protected(node) ) + { + res = iommu_assign_dt_device(kinfo->d, node); + if ( res < 0 ) + return res; + } + + res = handle_device_interrupts(kinfo->d, node, true); + if ( res < 0 ) + return res; + + return 0; + } + + return 1; +} + static int __init handle_prop_pfdt(struct kernel_info *kinfo, const void *pfdt, int nodeoff, uint32_t address_cells, uint32_t size_cells, @@ -1722,6 +1812,7 @@ static int __init handle_prop_pfdt(struct kernel_info *kinfo, void *fdt = kinfo->fdt; int propoff, nameoff, res; const struct fdt_property *prop; + const char *name; for ( propoff = fdt_first_property_offset(pfdt, nodeoff); propoff >= 0; @@ -1730,11 +1821,26 @@ static int __init handle_prop_pfdt(struct kernel_info *kinfo, if ( !(prop = fdt_get_property_by_offset(pfdt, propoff, NULL)) ) return -FDT_ERR_INTERNAL; + res = 0; nameoff = fdt32_to_cpu(prop->nameoff); - res = fdt_property(fdt, fdt_string(pfdt, nameoff), - prop->data, fdt32_to_cpu(prop->len)); - if ( res ) + name = fdt_string(pfdt, nameoff); + + if ( scan_passthrough_prop ) + res = handle_passthrough_prop(kinfo, prop, name, + address_cells, size_cells); + if ( res < 0 ) return res; + + /* + * Copy properties other than xen,reg and xen,path, which are + * handled by handle_passthrough_prop. + */ + if ( !scan_passthrough_prop || res > 0 ) + { + res = fdt_property(fdt, name, prop->data, fdt32_to_cpu(prop->len)); + if ( res ) + return res; + } } /* FDT_ERR_NOTFOUND => There is no more properties for this node */ @@ -2291,6 +2397,9 @@ void __init create_domUs(void) panic("Missing property 'cpus' for domain %s\n", dt_node_name(node)); + if ( dt_find_compatible_node(node, NULL, "multiboot,device-tree") ) + d_cfg.flags |= XEN_DOMCTL_CDF_iommu; + d = domain_create(++max_init_domid, &d_cfg, false); if ( IS_ERR(d) ) panic("Error creating domain %s\n", dt_node_name(node));