From nobody Mon Feb 9 17:59:36 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass(p=quarantine dis=none) header.from=amd.com ARC-Seal: i=2; a=rsa-sha256; t=1693963055; cv=pass; d=zohomail.com; s=zohoarc; b=BQ0i1jHYyU4zF5OEm2Ulb8AQCnOS7ypjCjvgjr0ep0bXGIAtismG91r2Kbq4BQ3GbfBRomovIB1nsGuLjoyGoYKskJIOHprLmvz6eFRs1PjogvWE1eTyfoWbhIX4ciINSM8FVCMCDMX102VK0my5ycjPrL94x7niHc6hnZRhkoI= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1693963055; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=BzU2V5UhlhCONkwcboNamsl2T4uX8forSiEa0laE+KA=; b=XxodL0iMVTgG1KxAdxjWwtEqhu8xqsSydpt2qYiCzHGLuIAHLTTvIwCnjdZiE43DfR9yD7JO6xhiguXKJ60glqfYX0jeY7YdAqcUvferb9jwIuHhLHvs0BoaaXRFtDiqJ1uSxbN928BNUQSnX/r2cpXOwMwW/G6WURymAK4hPVs= ARC-Authentication-Results: i=2; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1693963055208686.132537595806; Tue, 5 Sep 2023 18:17:35 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.596004.929845 (Exim 4.92) (envelope-from ) id 1qdhAF-00032N-U3; Wed, 06 Sep 2023 01:17:03 +0000 Received: by outflank-mailman (output) from mailman id 596004.929845; Wed, 06 Sep 2023 01:17:03 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1qdhAE-0002zS-Bz; Wed, 06 Sep 2023 01:17:02 +0000 Received: by outflank-mailman (input) for mailman id 596004; Wed, 06 Sep 2023 01:17:00 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1qdhAC-00079K-CG for xen-devel@lists.xenproject.org; Wed, 06 Sep 2023 01:17:00 +0000 Received: from NAM11-CO1-obe.outbound.protection.outlook.com (mail-co1nam11on20625.outbound.protection.outlook.com [2a01:111:f400:7eab::625]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 11dc9176-4c53-11ee-9b0d-b553b5be7939; Wed, 06 Sep 2023 03:16:57 +0200 (CEST) Received: from MN2PR19CA0004.namprd19.prod.outlook.com (2603:10b6:208:178::17) by MN0PR12MB6173.namprd12.prod.outlook.com (2603:10b6:208:3c6::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6745.33; Wed, 6 Sep 2023 01:16:52 +0000 Received: from BL02EPF0001A102.namprd05.prod.outlook.com (2603:10b6:208:178:cafe::50) by MN2PR19CA0004.outlook.office365.com (2603:10b6:208:178::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6745.33 via Frontend Transport; Wed, 6 Sep 2023 01:16:52 +0000 Received: from SATLEXMB03.amd.com (165.204.84.17) by BL02EPF0001A102.mail.protection.outlook.com (10.167.241.134) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.6768.25 via Frontend Transport; Wed, 6 Sep 2023 01:16:52 +0000 Received: from SATLEXMB03.amd.com (10.181.40.144) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Tue, 5 Sep 2023 20:16:47 -0500 Received: from xsjfnuv50.xilinx.com (10.180.168.240) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server id 15.1.2507.27 via Frontend Transport; Tue, 5 Sep 2023 20:16:46 -0500 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 11dc9176-4c53-11ee-9b0d-b553b5be7939 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=RpYXkIVdtxM+f5Bq8tKFdm0rU32Oq6xCG/dX2+ppnLRRA1mmHGULOpagioMbdA54EdVvGsi065xoR/XDn+AIm2gbhYcmz8cI9rB28mVwcVMrnvaV+9XqN/WAFsuEIlszIG/Q9AOr+k5fHW7213pbnxxw7K3rv4X9QTkrinbAG1nFanVXSuZ1jD1dm8QoeXhJQUjK0Qtgt/StbpOLJKGuK1oBYI5oG0UJwbSIPTIi65Xhu5QB1nYzsjQRjCS3kmNVDLYgkNr59VuWH65s5MMRlVLKllDXjpOQGcORDbvfvkC+kC9H5A+7Bnoj2X81NWbCSfkP53pw9TQLvfC6gyEVvA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=BzU2V5UhlhCONkwcboNamsl2T4uX8forSiEa0laE+KA=; b=bT+SqQp3y/nAaO7ZRZFLB6MnQKlFDMhbIogNlfzy7kpb3g8tkw0Eha0cxvxqmXu4rXg5h4NpAOapL0gIfBIdwh69XUGj2l7GjLDdV1DyTOgt9//UfoxImEn1Hd1eQeEH9RUGyvhHzW1lhZjKn9uXpfaF8voORc0D94YNhhepgxAZJn+ZkuhYtYC9mLZSCHM8iwTKUNFK8r5qfeHxKWLVYI5ZzLsGP07321nSDhttWCs38ogKIjZ1K7rVRTVefV5d8Q8jGTwLTK4DxAIDfjN2/zH8gMIxbSm2KldVgi9UsdDYxNeMDzxE8reAVx6JBFhrtxznTbjM2wEEfXQCfYgE8Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=lists.xenproject.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=BzU2V5UhlhCONkwcboNamsl2T4uX8forSiEa0laE+KA=; b=imq+Z6paJtrAC27+AePkkoe1BswpSPZRj73dNw5JLjHdC6SEIHyO02xZ8S/ykjPKstN2c9JruMnBsIQPHp5Ssyx9HmEKOkBy1g8UgLTW8ZbitjI/IidzKwYC1gCffbLhsADcLEBN7hlzPU5FskzX/LB8lmTWNE+nwe1riPOiMGQ= X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB03.amd.com; pr=C From: Vikram Garhwal To: CC: , , , , Andrew Cooper , "George Dunlap" , Jan Beulich , Wei Liu , Bertrand Marquis , Volodymyr Babchuk Subject: [XEN][PATCH v12 16/20] xen/arm: Implement device tree node removal functionalities Date: Tue, 5 Sep 2023 18:16:26 -0700 Message-ID: <20230906011631.30310-17-vikram.garhwal@amd.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230906011631.30310-1-vikram.garhwal@amd.com> References: <20230906011631.30310-1-vikram.garhwal@amd.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BL02EPF0001A102:EE_|MN0PR12MB6173:EE_ X-MS-Office365-Filtering-Correlation-Id: dd3e6e9d-59e5-4008-d2f3-08dbae76f3af X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 2V57KMeZkfIB4yQxYIK7sG+DkX8C+Rq1ubbTXLe3wh3H5qzIkIp4Wc0VfLcye+1HmOgHnnYL8MrstzlElcXnpg+lQL6GW27RbCJCqZMAjtTl195Vfm4hUno1jGX2MgTN61mPzz7take+kpk902dKmTicpof6end7p9gfAzhoYylXLdVp1/HJCNO4eDpQl+o2y5U8rPe3sQ87cdU3bv85uyNywkaG7l19c0DLhJEvjQ6jgdh7HhZpLFjuodnZ0ZP7y6/Trk1O3PnfIV9dQgpffkXM7Ht5q21RQUK+cMuWsu25cPejlpx/8AhB51np9aDfwI5RScjF18Hj6uwApPoJJw/b9+IQvpChjRFMF6lMBAK4Ym+8i6bZZOKblTPYRACyF64RHtsE9eq4DO7jJv2PhnRXUEqUDXbyKSS8kzrqOGQC3e16TJBufgYnvYeqVl5ApDU1nPkxLyHaDq6S0rKXGmrQemWZwsdbH2U5meApPvgAQ4BQ+zDcbMSQ2aOBe8BPaf/zcS89b81nt0PGV7TOzm7H0pVg8x/gBVxRfDtyLbu0tuxh0r9b+JNMd/sQ4VlNqwgBhhDvS/uyUbnYwYXUORHbV491LDXlUvnyFd6AT1mKHjTvJkgGr6EhZclirnXyS+KGRunwDiVI1ZQPUdYuYZY65AbTMH6Mla0qQxgV+W3vxzb9DiFjL5OHRBwTdyHQB938orJIHS0YnumNyXWmns4Jm+UgW3sWLIIYOEkiOGpzLNgiRavtfcHeJ7VFDnY5LHjZVQVPBKMA+Nezd2n2oSfQA5HUFbDMG5JV12PABzxCDPK5nLZeln3Y4VNMMSPa X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:SATLEXMB03.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230031)(4636009)(136003)(396003)(39860400002)(346002)(376002)(451199024)(1800799009)(82310400011)(186009)(46966006)(36840700001)(40470700004)(5660300002)(8936002)(6916009)(36756003)(30864003)(54906003)(316002)(2906002)(70206006)(70586007)(4326008)(44832011)(8676002)(40460700003)(41300700001)(36860700001)(336012)(26005)(1076003)(47076005)(40480700001)(426003)(82740400003)(81166007)(356005)(478600001)(83380400001)(2616005)(86362001)(6666004)(333604002)(36900700001);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Sep 2023 01:16:52.0036 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: dd3e6e9d-59e5-4008-d2f3-08dbae76f3af X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[SATLEXMB03.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BL02EPF0001A102.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN0PR12MB6173 X-ZohoMail-DKIM: pass (identity @amd.com) X-ZM-MESSAGEID: 1693963056699100003 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce sysctl XEN_SYSCTL_dt_overlay to remove device-tree nodes added us= ing device tree overlay. xl dt-overlay remove file.dtbo: Removes all the nodes in a given dtbo. First, removes IRQ permissions and MMIO accesses. Next, it finds the no= des in dt_host and delete the device node entries from dt_host. The nodes get removed only if it is not used by any of dom0 or domio. Also, added overlay_track struct to keep the track of added node through de= vice tree overlay. overlay_track has dt_host_new which is unflattened form of up= dated fdt and name of overlay nodes. When a node is removed, we also free the mem= ory used by overlay_track for the particular overlay node. Nested overlay removal is supported in sequential manner only i.e. if overlay_child nests under overlay_parent, it is assumed that user first rem= oves overlay_child and then removes overlay_parent. Also, this is an experimental feature so it is expected from user to make s= ure correct device tree overlays are used when adding nodes and making sure dev= ices are not being used by other domain before removing them from Xen tree. Partially added/removed i.e. failures while removing the overlay may cause = other failures and might need a system reboot. Signed-off-by: Vikram Garhwal Acked-by: Stefano Stabellini --- Changes from v10: Add iommu_remove_dt_device if device has IOMMU added. Changes from v9: Remove iommu and IRQ routing as this will not be done while adding the = nodes. Changes from v8: Remove IRQs and IOMMU entries using rangesets instead of parsing each n= ode. Changes from v7: Add dt-overlay.c in MAINTAINERS. Add comments for dt_overlay_remove_node. Rename handle_remove_irq_iommu() to remove_resources(). Add comment regarding false mapping flag for reason behind not removing= the mapping.. Remove irq_access_premitted() check. Add error handling for remove_all_descendant_nodes Change read_lock with write_lock. Remove check_overlay_fdt() call from handle_remove_overlay_nodes(). Re-organize dt_sysctl and reutnr -EOPNOSTSUPP for error cases. Also, re= named this function to dt_overlay_sysctl. Remove unnecessary header includes in dt-overlay.h Correct indentation and make func tion inputs const wherever possible. Make overlay_fdt const_void inside xen_sysctl_dt_overlay{}. Add comment regarding why we not removing IRQ and MMIO mappings. Move overlay_node_count() out of this patch as it's not being used here anymore. Changes from v6: Add explicit padding for xen_system_dt_overlay{} Update license. Rearrange xfree in dt_sysctl() Update overlay_track struct comment with relevant message. Fix missing xen/errno.h for builds without CONFIG_OVERLAY_DTB cases. Fix header formatting. --- --- MAINTAINERS | 1 + xen/arch/arm/sysctl.c | 16 +- xen/common/Makefile | 1 + xen/common/dt-overlay.c | 406 +++++++++++++++++++++++++++++++++++ xen/include/public/sysctl.h | 24 +++ xen/include/xen/dt-overlay.h | 63 ++++++ 6 files changed, 510 insertions(+), 1 deletion(-) create mode 100644 xen/common/dt-overlay.c create mode 100644 xen/include/xen/dt-overlay.h diff --git a/MAINTAINERS b/MAINTAINERS index 59103dbac0..0e1d1b7655 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -301,6 +301,7 @@ M: Julien Grall S: Supported F: xen/common/libfdt/ F: xen/common/device_tree.c +F: xen/common/dt-overlay.c F: xen/include/xen/libfdt/ F: xen/include/xen/device_tree.h F: xen/drivers/passthrough/device_tree.c diff --git a/xen/arch/arm/sysctl.c b/xen/arch/arm/sysctl.c index e9a0661146..5cda0dc674 100644 --- a/xen/arch/arm/sysctl.c +++ b/xen/arch/arm/sysctl.c @@ -9,6 +9,7 @@ =20 #include #include +#include #include #include #include @@ -25,7 +26,20 @@ void arch_do_physinfo(struct xen_sysctl_physinfo *pi) long arch_do_sysctl(struct xen_sysctl *sysctl, XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl) { - return -ENOSYS; + long ret; + + switch ( sysctl->cmd ) + { + case XEN_SYSCTL_dt_overlay: + ret =3D dt_overlay_sysctl(&sysctl->u.dt_overlay); + break; + + default: + ret =3D -ENOSYS; + break; + } + + return ret; } =20 /* diff --git a/xen/common/Makefile b/xen/common/Makefile index 46049eac35..e7e96b1087 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_DEBUG_TRACE) +=3D debugtrace.o obj-$(CONFIG_HAS_DEVICE_TREE) +=3D device_tree.o obj-$(CONFIG_IOREQ_SERVER) +=3D dm.o obj-y +=3D domain.o +obj-$(CONFIG_OVERLAY_DTB) +=3D dt-overlay.o obj-y +=3D event_2l.o obj-y +=3D event_channel.o obj-y +=3D event_fifo.o diff --git a/xen/common/dt-overlay.c b/xen/common/dt-overlay.c new file mode 100644 index 0000000000..7b7224c29a --- /dev/null +++ b/xen/common/dt-overlay.c @@ -0,0 +1,406 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * xen/common/dt-overlay.c + * + * Device tree overlay support in Xen. + * + * Copyright (C) 2023, Advanced Micro Devices, Inc. All Rights Reserved. + * Written by Vikram Garhwal + * + */ +#include +#include +#include +#include +#include +#include + +static LIST_HEAD(overlay_tracker); +static DEFINE_SPINLOCK(overlay_lock); + +/* Find last descendants of the device_node. */ +static struct dt_device_node * +find_last_descendants_node(const struct dt_device_node *device_node) +{ + struct dt_device_node *child_node; + + for ( child_node =3D device_node->child; child_node->sibling !=3D NULL; + child_node =3D child_node->sibling ); + + /* If last child_node also have children. */ + if ( child_node->child ) + child_node =3D find_last_descendants_node(child_node); + + return child_node; +} + +static int dt_overlay_remove_node(struct dt_device_node *device_node) +{ + struct dt_device_node *np; + struct dt_device_node *parent_node; + struct dt_device_node *last_descendant =3D device_node->child; + + parent_node =3D device_node->parent; + + /* Check if we are trying to remove "/" i.e. root node. */ + if ( parent_node =3D=3D NULL ) + { + dt_dprintk("%s's parent node not found\n", device_node->name); + return -EFAULT; + } + + /* Sanity check for linking between parent and child node. */ + np =3D parent_node->child; + if ( np =3D=3D NULL ) + { + dt_dprintk("parent node %s's not found\n", parent_node->name); + return -EFAULT; + } + + /* If node to be removed is only child node or first child. */ + if ( !dt_node_cmp(np->full_name, device_node->full_name) ) + { + parent_node->child =3D np->sibling; + + /* + * Iterate over all child nodes of device_node. Given that we are + * removing a node, we need to remove all it's descendants too. + * Reason behind finding last_descendant: + * If device_node has multiple children, device_node->allnext will= point + * to first_child and first_child->allnext will be a sibling. When= the + * device_node and it's all children are removed, parent_node->all= next + * should point to node next to last children. + */ + if ( last_descendant ) + { + last_descendant =3D find_last_descendants_node(device_node); + parent_node->allnext =3D last_descendant->allnext; + } + else + parent_node->allnext =3D np->allnext; + + return 0; + } + + for ( np =3D parent_node->child; np->sibling !=3D NULL; np =3D np->sib= ling ) + { + if ( !dt_node_cmp(np->sibling->full_name, device_node->full_name) ) + { + /* Found the node. Now we remove it. */ + np->sibling =3D np->sibling->sibling; + + if ( np->child ) + np =3D find_last_descendants_node(np); + + /* + * Iterate over all child nodes of device_node. Given that we = are + * removing parent node, we need to remove all it's descendant= s too. + */ + if ( last_descendant ) + last_descendant =3D find_last_descendants_node(device_node= ); + + if ( last_descendant ) + np->allnext =3D last_descendant->allnext; + else + np->allnext =3D np->allnext->allnext; + + break; + } + } + + return 0; +} + +/* Basic sanity check for the dtbo tool stack provided to Xen. */ +static int check_overlay_fdt(const void *overlay_fdt, uint32_t overlay_fdt= _size) +{ + if ( (fdt_totalsize(overlay_fdt) !=3D overlay_fdt_size) || + fdt_check_header(overlay_fdt) ) + { + printk(XENLOG_ERR "The overlay FDT is not a valid Flat Device Tree= \n"); + return -EINVAL; + } + + return 0; +} + +static int irq_remove_cb(unsigned long s, unsigned long e, void *dom, + unsigned long *c) +{ + int rc; + struct domain *d =3D dom; + + /* + * TODO: We don't handle shared IRQs for now. So, it is assumed that + * the IRQs was not shared with another devices. + * TODO: Undo the IRQ routing. + */ + rc =3D irq_deny_access(d, s); + if ( rc ) + { + printk(XENLOG_ERR "unable to revoke access for irq %lu\n", s); + } + else + *c +=3D e - s + 1; + + return rc; + +} + +static int iomem_remove_cb(unsigned long s, unsigned long e, void *dom, + unsigned long *c) +{ + int rc; + struct domain *d =3D dom; + + /* + * Remove mmio access. + * TODO: Support for remove/add the mapping in P2M. + */ + rc =3D iomem_deny_access(d, s, e); + if ( rc ) + { + printk(XENLOG_ERR "Unable to remove dom%d access to" + " 0x%"PRIx64" - 0x%"PRIx64"\n", + d->domain_id, + s & PAGE_MASK, PAGE_ALIGN(e) - 1); + } + else + *c +=3D e - s + 1; + + return rc; +} + +/* Check if node itself can be removed and remove node from IOMMU. */ +static int remove_node_resources(struct dt_device_node *device_node) +{ + int rc =3D 0; + unsigned int len; + domid_t domid; + + domid =3D dt_device_used_by(device_node); + + dt_dprintk("Checking if node %s is used by any domain\n", + device_node->full_name); + + /* Remove the node if only it's assigned to hardware domain or domain = io. */ + if ( domid !=3D hardware_domain->domain_id && domid !=3D DOMID_IO ) + { + printk(XENLOG_ERR "Device %s is being used by domain %u. Removing = nodes failed\n", + device_node->full_name, domid); + return -EINVAL; + } + + /* Check if iommu property exists. */ + if ( dt_get_property(device_node, "iommus", &len) ) + { + if ( dt_device_is_protected(device_node) ) + { + rc =3D iommu_remove_dt_device(device_node); + if ( rc < 0 ) + return rc; + } + } + + return rc; +} + +/* Remove all descendants from IOMMU. */ +static int +remove_descendant_nodes_resources(const struct dt_device_node *device_node) +{ + int rc =3D 0; + struct dt_device_node *child_node; + + for ( child_node =3D device_node->child; child_node !=3D NULL; + child_node =3D child_node->sibling ) + { + if ( child_node->child ) + { + rc =3D remove_descendant_nodes_resources(child_node); + if ( rc ) + return rc; + } + + rc =3D remove_node_resources(child_node); + if ( rc ) + return rc; + } + + return rc; +} + +/* Remove nodes from dt_host. */ +static int remove_nodes(const struct overlay_track *tracker) +{ + int rc =3D 0; + struct dt_device_node *overlay_node; + unsigned int j; + struct domain *d =3D hardware_domain; + + for ( j =3D 0; j < tracker->num_nodes; j++ ) + { + overlay_node =3D (struct dt_device_node *)tracker->nodes_address[j= ]; + if ( overlay_node =3D=3D NULL ) + { + printk(XENLOG_ERR "Device %s is not present in the tree. Remov= ing nodes failed\n", + overlay_node->full_name); + return -EINVAL; + } + + rc =3D remove_descendant_nodes_resources(overlay_node); + if ( rc ) + return rc; + + rc =3D remove_node_resources(overlay_node); + if ( rc ) + return rc; + + dt_dprintk("Removing node: %s\n", overlay_node->full_name); + + write_lock(&dt_host_lock); + + rc =3D dt_overlay_remove_node(overlay_node); + if ( rc ) + { + write_unlock(&dt_host_lock); + return rc; + } + + write_unlock(&dt_host_lock); + } + + /* Remove IRQ access. */ + if ( tracker->irq_ranges ) + { + rc =3D rangeset_consume_ranges(tracker->irq_ranges, irq_remove_cb,= d); + if ( rc ) + return rc; + } + + /* Remove mmio access. */ + if ( tracker->iomem_ranges ) + { + rc =3D rangeset_consume_ranges(tracker->iomem_ranges, iomem_remove= _cb, d); + if ( rc ) + return rc; + } + + return rc; +} + +/* + * First finds the device node to remove. Check if the device is being use= d by + * any dom and finally remove it from dt_host. IOMMU is already being take= n care + * while destroying the domain. + */ +static long handle_remove_overlay_nodes(const void *overlay_fdt, + uint32_t overlay_fdt_size) +{ + int rc; + struct overlay_track *entry, *temp, *track; + bool found_entry =3D false; + + rc =3D check_overlay_fdt(overlay_fdt, overlay_fdt_size); + if ( rc ) + return rc; + + spin_lock(&overlay_lock); + + /* + * First check if dtbo is correct i.e. it should one of the dtbo which= was + * used when dynamically adding the node. + * Limitation: Cases with same node names but different property are n= ot + * supported currently. We are relying on user to provide the same dtbo + * as it was used when adding the nodes. + */ + list_for_each_entry_safe( entry, temp, &overlay_tracker, entry ) + { + if ( memcmp(entry->overlay_fdt, overlay_fdt, overlay_fdt_size) =3D= =3D 0 ) + { + track =3D entry; + found_entry =3D true; + break; + } + } + + if ( !found_entry ) + { + rc =3D -EINVAL; + + printk(XENLOG_ERR "Cannot find any matching tracker with input dtb= o." + " Removing nodes is supported only for prior added dtbo.\n"= ); + goto out; + + } + + rc =3D remove_nodes(entry); + if ( rc ) + { + printk(XENLOG_ERR "Removing node failed\n"); + goto out; + } + + list_del(&entry->entry); + + xfree(entry->dt_host_new); + xfree(entry->fdt); + xfree(entry->overlay_fdt); + + xfree(entry->nodes_address); + + rangeset_destroy(entry->irq_ranges); + rangeset_destroy(entry->iomem_ranges); + + xfree(entry); + + out: + spin_unlock(&overlay_lock); + return rc; +} + +long dt_overlay_sysctl(struct xen_sysctl_dt_overlay *op) +{ + long ret; + void *overlay_fdt; + + if ( op->overlay_op !=3D XEN_SYSCTL_DT_OVERLAY_ADD && + op->overlay_op !=3D XEN_SYSCTL_DT_OVERLAY_REMOVE ) + return -EOPNOTSUPP; + + if ( op->overlay_fdt_size =3D=3D 0 || op->overlay_fdt_size > KB(500) ) + return -EINVAL; + + if ( op->pad[0] || op->pad[1] || op->pad[2] ) + return -EINVAL; + + overlay_fdt =3D xmalloc_bytes(op->overlay_fdt_size); + + if ( overlay_fdt =3D=3D NULL ) + return -ENOMEM; + + ret =3D copy_from_guest(overlay_fdt, op->overlay_fdt, op->overlay_fdt_= size); + if ( ret ) + { + gprintk(XENLOG_ERR, "copy from guest failed\n"); + xfree(overlay_fdt); + + return -EFAULT; + } + + if ( op->overlay_op =3D=3D XEN_SYSCTL_DT_OVERLAY_REMOVE ) + ret =3D handle_remove_overlay_nodes(overlay_fdt, op->overlay_fdt_s= ize); + + xfree(overlay_fdt); + + return ret; +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index 3975050248..f1eba78405 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -1185,6 +1185,25 @@ typedef struct xen_sysctl_cpu_policy xen_sysctl_cpu_= policy_t; DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpu_policy_t); #endif =20 +#if defined(__arm__) || defined (__aarch64__) +/* + * XEN_SYSCTL_dt_overlay + * Performs addition/removal of device tree nodes under parent node using = dtbo. + * This does in three steps: + * - Adds/Removes the nodes from dt_host. + * - Adds/Removes IRQ permission for the nodes. + * - Adds/Removes MMIO accesses. + */ +struct xen_sysctl_dt_overlay { + XEN_GUEST_HANDLE_64(const_void) overlay_fdt; /* IN: overlay fdt. */ + uint32_t overlay_fdt_size; /* IN: Overlay dtb size. */ +#define XEN_SYSCTL_DT_OVERLAY_ADD 1 +#define XEN_SYSCTL_DT_OVERLAY_REMOVE 2 + uint8_t overlay_op; /* IN: Add or remove. */ + uint8_t pad[3]; /* IN: Must be zero. */ +}; +#endif + struct xen_sysctl { uint32_t cmd; #define XEN_SYSCTL_readconsole 1 @@ -1215,6 +1234,7 @@ struct xen_sysctl { #define XEN_SYSCTL_livepatch_op 27 /* #define XEN_SYSCTL_set_parameter 28 */ #define XEN_SYSCTL_get_cpu_policy 29 +#define XEN_SYSCTL_dt_overlay 30 uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */ union { struct xen_sysctl_readconsole readconsole; @@ -1245,6 +1265,10 @@ struct xen_sysctl { #if defined(__i386__) || defined(__x86_64__) struct xen_sysctl_cpu_policy cpu_policy; #endif + +#if defined(__arm__) || defined (__aarch64__) + struct xen_sysctl_dt_overlay dt_overlay; +#endif uint8_t pad[128]; } u; }; diff --git a/xen/include/xen/dt-overlay.h b/xen/include/xen/dt-overlay.h new file mode 100644 index 0000000000..c0567741ee --- /dev/null +++ b/xen/include/xen/dt-overlay.h @@ -0,0 +1,63 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ + /* + * xen/dt-overlay.h + * + * Device tree overlay support in Xen. + * + * Copyright (C) 2023, Advanced Micro Devices, Inc. All Rights Reserved. + * Written by Vikram Garhwal + * + */ +#ifndef __XEN_DT_OVERLAY_H__ +#define __XEN_DT_OVERLAY_H__ + +#include +#include +#include + +/* + * overlay_track describes information about added nodes through dtbo. + * @entry: List pointer. + * @dt_host_new: Pointer to the updated dt_host_new which is unflattened f= rom + the 'updated fdt'. + * @fdt: Stores the fdt. + * @overlay_fdt: Stores a copy of input overlay_fdt. + * @nodes_address: Stores each overlay_node's address. + * @num_nodes: Total number of nodes in overlay dtb. + * @iomem_ranges: Range set to keep track of all IOMEMs. + * @irq_ranges: Range set to keep track of all added IRQs. + */ +struct overlay_track { + struct list_head entry; + struct dt_device_node *dt_host_new; + void *fdt; + void *overlay_fdt; + unsigned long *nodes_address; + unsigned int num_nodes; + struct rangeset *iomem_ranges; + struct rangeset *irq_ranges; +}; + +struct xen_sysctl_dt_overlay; + +#ifdef CONFIG_OVERLAY_DTB +long dt_overlay_sysctl(struct xen_sysctl_dt_overlay *op); +#else +#include +static inline long dt_overlay_sysctl(struct xen_sysctl_dt_overlay *op) +{ + return -EOPNOTSUPP; +} +#endif + +#endif /* __XEN_DT_OVERLAY_H__ */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ --=20 2.17.1