From nobody Mon Feb 9 17:59:26 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=1692951148; cv=pass; d=zohomail.com; s=zohoarc; b=j7LoPUNOf3oo8CBB7wIJADkBt7hj4bFERCblT5y87i2eXFSKQpUzmtxyOpvjCkOySd0sAtdw6QBKvfMIbUpFiWgx/PEgqOCuxZ5CNFJzfrZLuWLbXVrgGCoIy/0LkAGW9p/pEqXU+uWnwbjF+cqae4tNXXPOMsioBWRAiHer5/4= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1692951148; 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=zt/V6Dm8rU3iuQaBnl1b6JyUY5OvDZ99vua8YutGWYU=; b=YtOCqPMUMMQW1WRMDXMoJf6wKVopMm0rUIeKbe5xovnPeKC3DNFaAgGI+QYxCeCeGQ9iQQopw4ERd2Uc2/Ntgfa7WCz9KYDj4Xv7zK1hCtc48MGJQkMHH98vwnU7c1m2O4L42U9nm9PvFS8Bisxd8E9Q9W+zDvJjT7zyvyoWG5U= 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 1692951148784902.0505676194766; Fri, 25 Aug 2023 01:12:28 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.590704.923087 (Exim 4.92) (envelope-from ) id 1qZRvP-0005LG-MX; Fri, 25 Aug 2023 08:12:11 +0000 Received: by outflank-mailman (output) from mailman id 590704.923087; Fri, 25 Aug 2023 08:12:11 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1qZRvP-0005L9-Jq; Fri, 25 Aug 2023 08:12:11 +0000 Received: by outflank-mailman (input) for mailman id 590704; Fri, 25 Aug 2023 08:12:10 +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 1qZRnP-0007G4-V4 for xen-devel@lists.xenproject.org; Fri, 25 Aug 2023 08:03:56 +0000 Received: from NAM10-MW2-obe.outbound.protection.outlook.com (mail-mw2nam10on20611.outbound.protection.outlook.com [2a01:111:f400:7e89::611]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id ecf36cd5-431d-11ee-9b0c-b553b5be7939; Fri, 25 Aug 2023 10:03:53 +0200 (CEST) Received: from DS7PR03CA0122.namprd03.prod.outlook.com (2603:10b6:5:3b4::7) by MN2PR12MB4128.namprd12.prod.outlook.com (2603:10b6:208:1dd::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.27; Fri, 25 Aug 2023 08:03:47 +0000 Received: from SN1PEPF0002636C.namprd02.prod.outlook.com (2603:10b6:5:3b4:cafe::27) by DS7PR03CA0122.outlook.office365.com (2603:10b6:5:3b4::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.30 via Frontend Transport; Fri, 25 Aug 2023 08:03:47 +0000 Received: from SATLEXMB04.amd.com (165.204.84.17) by SN1PEPF0002636C.mail.protection.outlook.com (10.167.241.137) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.6699.15 via Frontend Transport; Fri, 25 Aug 2023 08:03:46 +0000 Received: from SATLEXMB04.amd.com (10.181.40.145) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 25 Aug 2023 03:03:08 -0500 Received: from xsjfnuv50.xilinx.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server id 15.1.2507.27 via Frontend Transport; Fri, 25 Aug 2023 03:03:07 -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: ecf36cd5-431d-11ee-9b0c-b553b5be7939 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=BeTObQ4RvJZOwegyp65K0/kaf9HbX+dksOkw1soA5EMBOiOtbfuT4T3DOcCl60wH8C8C1E0kpj8CHURy0YnGW5lVJVS7RNUBGwJBbMwTmrfHidXmpcC/HBhFsf9l/gjg0tMONYN5KJkVNkxh3JFQflcQdW5B653nuxGziN6LkcNUrnH7L8hcmAlI49kOOJ5oIycqIfJhElLegjxWiCt2g0tZH9D2WajSmZcN9AgXUNirRFNbV16p/+61blkDOyelL1lAQzxsgWicje0QMC9X9C8VDMbJ24Fd+6c4oq6SaRYcZLzWYUZNu9rFOsS1XOYLWdZAy6UZUcDi2FP/P0b/ww== 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=zt/V6Dm8rU3iuQaBnl1b6JyUY5OvDZ99vua8YutGWYU=; b=ne8wK+ZqTPEaMh9GBMpQmhGjLc2j34N1EerAaAsZZZs3VKM8z19kQL/lLpuwgTDbu18wZIBTvl1fjRVzpLh3ppR0U+MYAv7B+sQBKkmxDldmyvlwOcusY63RTK6wrNMEA4Z81cp1rHHGZyExPHD3vowWunfCwWFM+C5QamKmdXoHNzIGnwOKIC38EShCbItv2MUIXM4TNCmo/TJjIcZ/pU6KNjZcRBcPGQNydSn9iwjAtBuYSI+ZNyd63BghOLCL4YFqYRo8Lif01OUBSapa27Pasfzg01vHG7aQuKuZYFuw0u5WUwxzmkVZHlYkumMxUewIodMFO+LZKhSBwP+D4Q== 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=zt/V6Dm8rU3iuQaBnl1b6JyUY5OvDZ99vua8YutGWYU=; b=mBvRBfvYZnwYI5T2uXJc3g098XrHoV8pb1RrQXGmYaz2ePUh9yt1yOHMi7Oks3gPpeYgRK9PFsk3sxs2JFPQURQUGPbvmGoq5GK+UVS61UWm0Zq/Y9qIN76NMgprl5s8aULCA4en4Oa3iY6R3JjgQewR4/iYvcFOqqlurNZMa5g= 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=SATLEXMB04.amd.com; pr=C From: Vikram Garhwal To: CC: , , , , Andrew Cooper , George Dunlap , "Jan Beulich" , Wei Liu , Bertrand Marquis , Volodymyr Babchuk Subject: [XEN][PATCH v10 16/20] xen/arm: Implement device tree node removal functionalities Date: Fri, 25 Aug 2023 01:02:18 -0700 Message-ID: <20230825080222.14247-17-vikram.garhwal@amd.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230825080222.14247-1-vikram.garhwal@amd.com> References: <20230825080222.14247-1-vikram.garhwal@amd.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SN1PEPF0002636C:EE_|MN2PR12MB4128:EE_ X-MS-Office365-Filtering-Correlation-Id: af614152-bad7-4e36-3a1d-08dba541cee8 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 1W4x7UTG/uQjyY1GBJLvwhbR1z9bJN29lWBe/5U/xChxnnkXaV+doWkjEr0gG3qgZ1iXFw/F4J+yu5b5Mw5874mpiU9YCF5hSQpw1fiusnBdF04EI9RIQxesQjgiawMSynh6bJAHHnwYvUG0+Qu6ui3bSZakn4mQs6rKUgJARhSqw1q7FEvweGjXjUkmT2IB6/OheRvxJVbl4j7VRMmRI052MEr0y+cfDDSrsZ7YKiXJHW9ssg175zPEgAzZQjGpLDcapsfenQiHqmXK+emRBXXhbQauUHKpLM1TP+NeiWNXn/eRcY4KpT7S+5Y/nksI7Yk9JzdRAN3LIeSpoeOKQqLR2JOSfl3L4S8eSexmfHn7UlWw+AFn7bMeuGXsjTNT8Ew93IoGeeNO4OnFAvMsS5+SWHO3Kgc7mGLf3dt1fgwyJvDTr+LLjgnauJcr8vUgNHJf4EIq8D1N/oewM5PSqSyHOsLP4f+JOeIR4/8Mj8HBxEnw+0tYjWbXNZs6FVigjC+cw7bLTE/Tg7LCc4O/sxBGXf25qwgMT9V0YMyfOYXvntNYng3YBbDLxcZ0N9Ire5sAOVe86qQoTpbW7HgO5FX4p84lHS8RJssQsecQPBtNVPi6Ff3y71030tb58nOaqeD3ZWP5Q8RBDwlzgAmJXG6LSzNXvUsl9KyvxwIE9aUHbWQRDPhjM2ZA1z3wyT0scArMY4btjhJNtRu0lpTkrOSjxIV2GDY4zPALLlkUIbZnOpLgUhIrgi8ETs+1TMIOr2ZKHFlMDjWXYtcpGlcgZwTmZASTXeb69AL/ZdCRBoPFRScS7oNEqyuXek1nhrxI X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:SATLEXMB04.amd.com;PTR:ErrorRetry;CAT:NONE;SFS:(13230031)(4636009)(136003)(396003)(376002)(39860400002)(346002)(451199024)(82310400011)(186009)(1800799009)(40470700004)(36840700001)(46966006)(54906003)(70206006)(70586007)(316002)(81166007)(40480700001)(6916009)(478600001)(26005)(36860700001)(44832011)(6666004)(356005)(82740400003)(41300700001)(86362001)(2906002)(8936002)(8676002)(4326008)(1076003)(40460700003)(2616005)(5660300002)(83380400001)(36756003)(30864003)(336012)(426003)(47076005)(333604002)(36900700001);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 Aug 2023 08:03:46.5371 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: af614152-bad7-4e36-3a1d-08dba541cee8 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=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: SN1PEPF0002636C.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4128 X-ZohoMail-DKIM: pass (identity @amd.com) X-ZM-MESSAGEID: 1692951151161100005 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 --- 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 | 392 +++++++++++++++++++++++++++++++++++ xen/include/public/sysctl.h | 24 +++ xen/include/xen/dt-overlay.h | 63 ++++++ 6 files changed, 496 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 a0805d35cd..c41a7c5440 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..12a3029fee --- /dev/null +++ b/xen/common/dt-overlay.c @@ -0,0 +1,392 @@ +/* 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. */ +static bool check_node_removable(struct dt_device_node *device_node) +{ + 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 false; + } + + + return true; +} + +/* Check if all descendants of the given node are removable. */ +static bool +check_descendant_nodes_removable(const struct dt_device_node *device_node) +{ + bool rc =3D true; + 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 check_descendant_nodes_removable(child_node); + if ( !rc ) + return rc; + } + + rc =3D check_node_removable(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; + } + + if ( !check_descendant_nodes_removable(overlay_node) ) + return -EINVAL; + + if ( !check_node_removable(overlay_node) ) + return -EINVAL; + + 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 fa7147de47..900239133a 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -1059,6 +1059,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 @@ -1089,6 +1108,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; @@ -1119,6 +1139,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