From patchwork Tue Mar 11 11:16:12 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Grygorii Strashko X-Patchwork-Id: 14011516 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 21280C282EC for ; Tue, 11 Mar 2025 11:16:54 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.907856.1315055 (Exim 4.92) (envelope-from ) id 1trxbB-0006iG-Ay; Tue, 11 Mar 2025 11:16:37 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 907856.1315055; Tue, 11 Mar 2025 11:16:37 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1trxbB-0006i9-7M; Tue, 11 Mar 2025 11:16:37 +0000 Received: by outflank-mailman (input) for mailman id 907856; Tue, 11 Mar 2025 11:16:36 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1trxbA-0006Sq-1X for xen-devel@lists.xenproject.org; Tue, 11 Mar 2025 11:16:36 +0000 Received: from mail-lj1-x234.google.com (mail-lj1-x234.google.com [2a00:1450:4864:20::234]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 4af8f589-fe6a-11ef-9ab9-95dc52dad729; Tue, 11 Mar 2025 12:16:35 +0100 (CET) Received: by mail-lj1-x234.google.com with SMTP id 38308e7fff4ca-30bf5d7d107so41455011fa.2 for ; Tue, 11 Mar 2025 04:16:35 -0700 (PDT) Received: from epuakyiw0a98.kyiv.epam.com (ll-74.141.223.85.sovam.net.ua. [85.223.141.74]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5498ae45fa8sm1755729e87.52.2025.03.11.04.16.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Mar 2025 04:16:33 -0700 (PDT) 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: 4af8f589-fe6a-11ef-9ab9-95dc52dad729 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741691794; x=1742296594; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=04wizIaLTSFlmJKWvZpRMDn++A6FwzgnmnVliYBR7HQ=; b=jtaj1sBtZdLX/b90XHXChtuaoPnJUehP/M0ug+7A8jzopvqfv8mgSj72lQ+tiZENXH vfvijZ1GiS75IWd8QVXKe09oEbK3TRaoxc3DUb1dq5Ofku7wpXPpQAjWe4uYBnPijOgI 3dfwXSUG+19XhwFSHTcxWv4G4b2L5u7fwkpqwT68tjjOnlsMRYwYAJZ8NtKeMxLU9DAi fst5Z3BZ9X0Ll8aSbMnCO7+xn+Gq1EcoV9Lsh1CnSC7ajd8qGTMOegbUGcKRzhI8WV9H OkhRskyt4lPVp7OMcnOAhzTEUTGtSX9N6yDC0Didv9Ul/9FonWpkcukwDV7ycQm8DIvk Cv9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741691794; x=1742296594; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=04wizIaLTSFlmJKWvZpRMDn++A6FwzgnmnVliYBR7HQ=; b=IeAuyYT1KWJULU2MoYRBQCirL9TqbrtR8pUoSWKnmvgGJZ7/cRdlPwvL7+yMftMl7m dc4xiEGkvXxaTtq3BaIIWFzYfHK0Q/5wSV5+A7UEfLI1CENYxX+k5gu+VvmMC5dKrh6b vyaGUKvmIx8O0lcA83ZmCyCNhd6Q4nFCgbcwE79aTlpJ3r/lcu/do1bZumXotqu+1mYZ QV8Nm9uEYF3DD6DE4jkF9RqYoeifkuXif9K9Vgtn/KouXdBHyDdLKPVsEtON/mD/BBOf 38iHbB8Wt0CLSJbdCOO24y+ZERfcKB3IePoo3+yvxHX1FXZ067QFAL9tGrnuo1KT515h QSrg== X-Gm-Message-State: AOJu0Ywi0hYqOEK3DH5Ati1kV+BccZB2VjYo8MzBMZnPSGAhA3iZM/xg MDUYRgK/jeiIhH9jPhUatx/dWXxDbN+JlRskA/HiL87CFxgq4CtDUtsU8rA4 X-Gm-Gg: ASbGncuD/qw3HIuxtB2x9Xi3dOA+IPIASAeRiwBhuuKcPMdMXgwczjVUppMPY1kb6aC ltLtJgRRWzIHNOGA8bVa/D2G3q+G4/jVAWKxu7Ub3vuZ9WW/y934d4VvWet82+ekFfdAQN13dzW ojac0IKiQXbtxCUyv0eXk1E8rMNR2hBMhHyek3sans7CEWxjI/H7T8hBQ/99xcO8tnKT9Ypfvj1 pcNNa+upwQoonNBp6rptugLHfanq7xGx981luW8+bWfERbx0WGRSiifDmFg4w7bFrWxcOp+KU4f WD2Td9+BURX6ut4zzgh0ak6q5ceFd0ptKLcoRDVGpaie/XuB0bweQXxOweKXds+mcAg7WrqXogs ZVM8bBzwb5faXSc+qsSNTfok/rJ/K4EZ6rdhZVg== X-Google-Smtp-Source: AGHT+IEMbJFWqRghLmu/ZOG4/DATF4wm6MfGWoKHG9Dg4MGsf5di/UXYyq9/MBiw5MgtsVaoqqO4MA== X-Received: by 2002:a05:6512:1597:b0:549:4e86:75cc with SMTP id 2adb3069b0e04-54990e2bc0cmr6156848e87.4.1741691793579; Tue, 11 Mar 2025 04:16:33 -0700 (PDT) From: Grygorii Strashko X-Google-Original-From: Grygorii Strashko To: xen-devel@lists.xenproject.org Cc: Stefano Stabellini , Julien Grall , Andrew Cooper , Michal Orzel , "Roger Pau Monne" , Jan Beulich , Anthony PERARD , Volodymyr Babchuk , Oleksii Moisieiev , Bertrand Marquis , Juergen Gross , Grygorii Strashko Subject: [RFC PATCH v3 1/7] xen/arm: add generic SCI subsystem Date: Tue, 11 Mar 2025 13:16:12 +0200 Message-Id: <20250311111618.1850927-2-grygorii_strashko@epam.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250311111618.1850927-1-grygorii_strashko@epam.com> References: <20250311111618.1850927-1-grygorii_strashko@epam.com> MIME-Version: 1.0 From: Oleksii Moisieiev This patch adds the basic framework for ARM SCI mediator. SCI is System Control Interface, which is designed to redirect requests from the Domains to ARM specific Firmware (for example SCMI). This will allow the devices, passed-through to the different Domains, to access to the System resources (such as clocks/resets etc) by sending requests to the firmware. ARM SCI subsystem allows to implement different SCI drivers to handle specific ARM firmware interfaces (like ARM SCMI) and mediate requests between the Domains and the Firmware. Also it allows SCI drivers to perform proper action during Domain creation/destruction which is vital for handling use cases like Domain reboot. This patch introduces new DEVICE_ARM_SCI device subclass for probing SCI drivers basing on device tree, SCI drivers register itself with DT_DEVICE_START/END macro. On init - the SCI drivers should register its SCI ops with sci_register(). Only one SCI driver can be supported. At run-time, the following SCI API calls are introduced: - sci_domain_sanitise_config() called from arch_sanitise_domain_config() - sci_domain_init() called from arch_domain_create() - sci_relinquish_resources() called from domain_relinquish_resources() - sci_domain_destroy() called from arch_domain_destroy() - sci_handle_call() called from vsmccc_handle_call() - sci_dt_handle_node() sci_dt_finalize() called from handle_node() (Dom0 DT) Signed-off-by: Oleksii Moisieiev Signed-off-by: Grygorii Strashko --- MAINTAINERS | 6 + xen/arch/arm/device.c | 5 + xen/arch/arm/dom0less-build.c | 13 ++ xen/arch/arm/domain.c | 12 +- xen/arch/arm/domain_build.c | 8 + xen/arch/arm/firmware/Kconfig | 8 + xen/arch/arm/firmware/Makefile | 1 + xen/arch/arm/firmware/sci.c | 187 +++++++++++++++++++++ xen/arch/arm/include/asm/domain.h | 5 + xen/arch/arm/include/asm/firmware/sci.h | 214 ++++++++++++++++++++++++ xen/arch/arm/vsmc.c | 3 + xen/common/domctl.c | 13 ++ xen/drivers/passthrough/device_tree.c | 7 + xen/include/asm-generic/device.h | 1 + xen/include/public/arch-arm.h | 4 + 15 files changed, 486 insertions(+), 1 deletion(-) create mode 100644 xen/arch/arm/firmware/sci.c create mode 100644 xen/arch/arm/include/asm/firmware/sci.h diff --git a/MAINTAINERS b/MAINTAINERS index c11b82eca98f..c0e8143dca63 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -526,6 +526,12 @@ S: Supported F: xen/arch/arm/include/asm/tee/ F: xen/arch/arm/tee/ +SCI MEDIATORS +M: Oleksii Moisieiev +S: Supported +F: xen/arch/arm/sci +F: xen/include/asm-arm/sci + TOOLSTACK M: Anthony PERARD S: Supported diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c index 5610cddcba8e..bdab96a408c4 100644 --- a/xen/arch/arm/device.c +++ b/xen/arch/arm/device.c @@ -13,6 +13,7 @@ #include #include +#include #include int map_irq_to_domain(struct domain *d, unsigned int irq, @@ -303,6 +304,10 @@ int handle_device(struct domain *d, struct dt_device_node *dev, p2m_type_t p2mt, return res; } } + + res = sci_assign_dt_device(d, dev); + if ( res ) + return res; } res = map_device_irqs_to_domain(d, dev, own_device, irq_ranges); diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c index 49d1f14d659b..c463ab3eaca5 100644 --- a/xen/arch/arm/dom0less-build.c +++ b/xen/arch/arm/dom0less-build.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -321,6 +322,10 @@ static int __init handle_passthrough_prop(struct kernel_info *kinfo, return -EINVAL; } + res = sci_assign_dt_device(kinfo->d, node); + if ( res ) + return res; + res = map_device_irqs_to_domain(kinfo->d, node, true, NULL); if ( res < 0 ) return res; @@ -970,6 +975,14 @@ void __init create_domUs(void) if ( !llc_coloring_enabled && llc_colors_str ) panic("'llc-colors' found, but LLC coloring is disabled\n"); + /* + * TODO: enable ARM SCI for dom0less case + * The configuration need to be retrieved from DT + * - arch.arm_sci_type, like "xen,sci_type" + * - arch.arm_sci_agent_id, like "xen,sci_agent_id" + */ + d_cfg.arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_NONE; + /* * The variable max_init_domid is initialized with zero, so here it's * very important to use the pre-increment operator to call diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 3ba959f86633..652aeb7a55de 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -694,7 +695,7 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config) return -EINVAL; } - return 0; + return sci_domain_sanitise_config(config); } int arch_domain_create(struct domain *d, @@ -786,6 +787,9 @@ int arch_domain_create(struct domain *d, d->arch.sve_vl = config->arch.sve_vl; #endif + if ( (rc = sci_domain_init(d, config)) != 0 ) + goto fail; + return 0; fail: @@ -846,6 +850,7 @@ void arch_domain_destroy(struct domain *d) domain_vgic_free(d); domain_vuart_free(d); free_xenheap_page(d->shared_info); + sci_domain_destroy(d); #ifdef CONFIG_ACPI free_xenheap_pages(d->arch.efi_acpi_table, get_order_from_bytes(d->arch.efi_acpi_len)); @@ -1039,6 +1044,7 @@ enum { PROG_p2m_root, PROG_p2m, PROG_p2m_pool, + PROG_sci, PROG_done, }; @@ -1098,6 +1104,10 @@ int domain_relinquish_resources(struct domain *d) ret = relinquish_p2m_mapping(d); if ( ret ) return ret; + PROGRESS(sci): + ret = sci_relinquish_resources(d); + if ( ret ) + return ret; PROGRESS(p2m_root): /* diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index 7b47abade196..36d28b52a418 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1888,6 +1889,9 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo, return 0; } + if ( sci_dt_handle_node(d, node) ) + return 0; + /* * The vGIC does not support routing hardware PPIs to guest. So * we need to skip any node using PPIs. @@ -1988,6 +1992,10 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo, if ( res ) return res; + res = sci_dt_finalize(d, kinfo->fdt); + if ( res ) + return res; + /* * Create a second memory node to store the ranges covering * reserved-memory regions. diff --git a/xen/arch/arm/firmware/Kconfig b/xen/arch/arm/firmware/Kconfig index 817da745fd43..fc7918c7fc56 100644 --- a/xen/arch/arm/firmware/Kconfig +++ b/xen/arch/arm/firmware/Kconfig @@ -1,3 +1,11 @@ +config ARM_SCI + bool + depends on ARM + help + This option enables generic Arm SCI (System Control Interface) mediators + support. It allows domains to control system resources via one of + Arm SCI mediators drivers implemented in XEN, like SCMI. + menu "Firmware Drivers" config SCMI_SMC diff --git a/xen/arch/arm/firmware/Makefile b/xen/arch/arm/firmware/Makefile index a5e454266625..71bdefc24afb 100644 --- a/xen/arch/arm/firmware/Makefile +++ b/xen/arch/arm/firmware/Makefile @@ -1 +1,2 @@ +obj-$(CONFIG_ARM_SCI) += sci.o obj-$(CONFIG_SCMI_SMC) += scmi-smc.o diff --git a/xen/arch/arm/firmware/sci.c b/xen/arch/arm/firmware/sci.c new file mode 100644 index 000000000000..1fb6b55e030a --- /dev/null +++ b/xen/arch/arm/firmware/sci.c @@ -0,0 +1,187 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Generic part of the SCI (System Control Interface) subsystem. + * + * Oleksii Moisieiev + * Copyright (c) 2025 EPAM Systems + */ + +#include +#include +#include +#include +#include + +#include + +static const struct sci_mediator_ops __read_mostly *cur_mediator; + +int sci_register(const struct sci_mediator_ops *ops) +{ + if ( cur_mediator ) + return -EEXIST; + + if ( !ops->domain_init || !ops->domain_destroy || !ops->handle_call ) + return -EINVAL; + + cur_mediator = ops; + + return 0; +}; + +bool sci_handle_call(struct cpu_user_regs *args) +{ + if ( unlikely(!cur_mediator) ) + return false; + + return cur_mediator->handle_call(args); +} + +int sci_domain_init(struct domain *d, struct xen_domctl_createdomain *config) +{ + if ( !cur_mediator ) + return 0; + + return cur_mediator->domain_init(d, config); +} + +int sci_domain_sanitise_config(struct xen_domctl_createdomain *config) +{ + if ( !cur_mediator ) + return 0; + + if ( !cur_mediator->domain_sanitise_config ) + return 0; + + return cur_mediator->domain_sanitise_config(config); +} + +void sci_domain_destroy(struct domain *d) +{ + if ( !cur_mediator ) + return; + + cur_mediator->domain_destroy(d); +} + +int sci_relinquish_resources(struct domain *d) +{ + if ( !cur_mediator ) + return 0; + + if ( !cur_mediator->relinquish_resources ) + return 0; + + return cur_mediator->relinquish_resources(d); +} + +bool sci_dt_handle_node(struct domain *d, struct dt_device_node *node) +{ + if ( !cur_mediator ) + return 0; + + if ( !cur_mediator->dom0_dt_handle_node ) + return 0; + + return cur_mediator->dom0_dt_handle_node(d, node); +} + +int sci_dt_finalize(struct domain *d, void *fdt) +{ + if ( !cur_mediator ) + return 0; + + if ( !cur_mediator->dom0_dt_finalize ) + return 0; + + return cur_mediator->dom0_dt_finalize(d, fdt); +} + +int sci_assign_dt_device(struct domain *d, struct dt_device_node *dev) +{ + struct dt_phandle_args ac_spec; + int index = 0; + int ret; + + if ( !cur_mediator ) + return 0; + + if ( !cur_mediator->assign_dt_device ) + return 0; + + while ( !dt_parse_phandle_with_args(dev, "access-controllers", + "#access-controller-cells", index, + &ac_spec) ) + { + printk(XENLOG_DEBUG "sci: assign device %s to %pd\n", + dt_node_full_name(dev), d); + + ret = cur_mediator->assign_dt_device(d, &ac_spec); + if ( ret ) + return ret; + + index++; + } + + return 0; +} + +int sci_do_domctl(struct xen_domctl *domctl, struct domain *d, + XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) +{ + struct dt_device_node *dev; + int ret = 0; + + switch ( domctl->cmd ) + { + case XEN_DOMCTL_assign_device: + if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_DT ) + { + ret = -EINVAL; + break; + } + + ret = dt_find_node_by_gpath(domctl->u.assign_device.u.dt.path, + domctl->u.assign_device.u.dt.size, &dev); + if ( ret ) + return ret; + + ret = sci_assign_dt_device(d, dev); + if ( ret ) + break; + + break; + default: + /* do not fail here as call is chained with iommu handling */ + break; + } + + return ret; +} + +static int __init sci_init(void) +{ + struct dt_device_node *np; + unsigned int num_sci = 0; + int rc; + + dt_for_each_device_node(dt_host, np) + { + rc = device_init(np, DEVICE_ARM_SCI, NULL); + if ( !rc && num_sci ) + { + printk(XENLOG_ERR + "SCMI: Only one SCI controller is supported. found second %s\n", + np->name); + return -EOPNOTSUPP; + } + else if ( !rc ) + num_sci++; + else if ( rc != -EBADF && rc != -ENODEV ) + return rc; + } + + return 0; +} + +__initcall(sci_init); diff --git a/xen/arch/arm/include/asm/domain.h b/xen/arch/arm/include/asm/domain.h index f1d72c6e48df..fa0898b7cf80 100644 --- a/xen/arch/arm/include/asm/domain.h +++ b/xen/arch/arm/include/asm/domain.h @@ -118,6 +118,11 @@ struct arch_domain #ifdef CONFIG_TEE void *tee; #endif +#ifdef CONFIG_ARM_SCI + bool sci_enabled; + /* ARM SCI driver's specific data */ + void *sci_data; +#endif } __cacheline_aligned; diff --git a/xen/arch/arm/include/asm/firmware/sci.h b/xen/arch/arm/include/asm/firmware/sci.h new file mode 100644 index 000000000000..4c6f624723c5 --- /dev/null +++ b/xen/arch/arm/include/asm/firmware/sci.h @@ -0,0 +1,214 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Generic ARM SCI (System Control Interface) subsystem. + * + * Oleksii Moisieiev + * Copyright (c) 2025 EPAM Systems + */ + +#ifndef __ASM_ARM_SCI_H +#define __ASM_ARM_SCI_H + +#include +#include +#include +#include +#include + +#ifdef CONFIG_ARM_SCI + +struct sci_mediator_ops { + /* + * Called during domain construction. If it is requested to enable + * SCI support, so SCI driver can create own structures for the new domain + * and inform firmware about new domain (if required). + * Mandatory. + */ + int (*domain_init)(struct domain *d, + struct xen_domctl_createdomain *config); + + /* + * Called during domain construction. The SCI driver uses + * it to sanitize domain SCI configuration parameters. + * Optional. + */ + int (*domain_sanitise_config)(struct xen_domctl_createdomain *config); + + /* + * Called during domain destruction, releases all resources, that + * were allocated for domain. + * Mandatory. + */ + void (*domain_destroy)(struct domain *d); + + /* + * Called during domain destruction to relinquish resources used + * by SCI driver itself and request resources releasing from firmware. + * Optional. + */ + int (*relinquish_resources)(struct domain *d); + + /* SMC/HVC Handle callback */ + bool (*handle_call)(struct cpu_user_regs *regs); + + /* + * Dom0 DT nodes handling callback so SCI driver can detect DT nodes it + * need to handle and decide if those nodes need to be provided to Dom0. + * Optional. + */ + bool (*dom0_dt_handle_node)(struct domain *d, struct dt_device_node *node); + + /* + * SCI driver callback called at the end of Dom0 DT generation, so + * it can perform steps to modify DT to enable/disable SCI + * functionality for Dom0. + */ + int (*dom0_dt_finalize)(struct domain *d, void *fdt); + + /* + * SCI driver callback called when DT device is passed through to guest, + * so SCI driver can enable device access to the domain if SCI FW provides + * Device specific access control functionality. + * Optional. + */ + int (*assign_dt_device)(struct domain *d, struct dt_phandle_args *ac_spec); +}; + + +static inline bool sci_domain_is_enabled(struct domain *d) +{ + return d->arch.sci_enabled; +} + +/* + * Register SCI subsystem ops. + * + * Register SCI drivers operation and so enable SCI functionality. + * Only one SCI driver is supported. + */ +int sci_register(const struct sci_mediator_ops *ops); + +/* + * Initialize SCI functionality for domain if configured. + * + * Initialization routine to enable SCI functionality for the domain. + * The SCI configuration data and decision about enabling SCI functionality + * for the domain is SCI driver specific. + */ +int sci_domain_init(struct domain *d, struct xen_domctl_createdomain *config); + +/* + * Sanitise domain configuration parameters. + * + */ +int sci_domain_sanitise_config(struct xen_domctl_createdomain *config); + +/* + * Destroy SCI domain instance. + */ +void sci_domain_destroy(struct domain *d); + +/* + * Free resources assigned to the certain domain. + */ +int sci_relinquish_resources(struct domain *d); + +/* + * SMC/HVC Handle callback. + * + * SCI driver acts as SMC/HVC server for the registered domains and + * does redirection of the domain calls to the SCI firmware, + * such as ARM TF-A or similar. + */ +bool sci_handle_call(struct cpu_user_regs *regs); + +/* + * Dom0 DT nodes handling function. + * + * Allows SCI driver to detect DT nodes it need to handle and decide if + * those nodes need to be provided to Dom0. + */ +bool sci_dt_handle_node(struct domain *d, struct dt_device_node *node); + +/* + * Dom0 DT generation finalize. + * + * Called at the end of Dom0 DT generation, so SCI driver can perform steps + * to modify DT to enable/disable SCI functionality for Dom0. + */ +int sci_dt_finalize(struct domain *d, void *fdt); + +/* + * Assign DT device to domain. + * + * Called when DT device is passed through to guest, so SCI driver can enable + * device access to the domain if SCI FW provides "Device specific access + * control" functionality. + */ +int sci_assign_dt_device(struct domain *d, struct dt_device_node *dev); + +/* + * SCI domctl handler + * + * Only XEN_DOMCTL_assign_device is handled for now. + */ +int sci_do_domctl(struct xen_domctl *domctl, struct domain *d, + XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl); +#else + +static inline bool sci_domain_is_enabled(struct domain *d) +{ + return false; +} + +static inline int sci_domain_init(struct domain *d, + struct xen_domctl_createdomain *config) +{ + return 0; +} + +static inline int +sci_domain_sanitise_config(struct xen_domctl_createdomain *config) +{ + return 0; +} + +static inline void sci_domain_destroy(struct domain *d) +{} + +static inline int sci_relinquish_resources(struct domain *d) +{ + return 0; +} + +static inline bool sci_handle_call(struct cpu_user_regs *args) +{ + return false; +} + +static inline bool sci_dt_handle_node(struct domain *d, + struct dt_device_node *node) +{ + return false; +} + +static inline int sci_dt_finalize(struct domain *d, void *fdt) +{ + return false; +} + +static inline int sci_assign_dt_device(struct domain *d, + struct dt_device_node *dev) +{ + return 0; +} + +static inline int sci_do_domctl(struct xen_domctl *domctl, struct domain *d, + XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) +{ + return 0; +} + +#endif /* CONFIG_ARM_SCI */ + +#endif /* __ASM_ARM_SCI_H */ diff --git a/xen/arch/arm/vsmc.c b/xen/arch/arm/vsmc.c index 62d8117a120c..51b3c0297314 100644 --- a/xen/arch/arm/vsmc.c +++ b/xen/arch/arm/vsmc.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -300,6 +301,8 @@ static bool vsmccc_handle_call(struct cpu_user_regs *regs) break; case ARM_SMCCC_OWNER_SIP: handled = handle_sip(regs); + if ( !handled ) + handled = sci_handle_call(regs); break; case ARM_SMCCC_OWNER_TRUSTED_APP ... ARM_SMCCC_OWNER_TRUSTED_APP_END: case ARM_SMCCC_OWNER_TRUSTED_OS ... ARM_SMCCC_OWNER_TRUSTED_OS_END: diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 05abb581a03d..b48ad20a6e2b 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -851,6 +852,18 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) case XEN_DOMCTL_deassign_device: case XEN_DOMCTL_get_device_group: ret = iommu_do_domctl(op, d, u_domctl); + + if ( ret >= 0 || (ret == -EOPNOTSUPP) || (ret == -ENODEV) ) + { + /* + * TODO: RFC + * This change will allow to pass DT nodes/devices to + * XEN_DOMCTL_assign_device OP using xl.cfg:"dtdev" property even + * if those DT nodes/devices even are not behind IOMMU (or IOMMU + * is disabled) without failure. + */ + ret = sci_do_domctl(op, d, u_domctl); + } break; case XEN_DOMCTL_get_paging_mempool_size: diff --git a/xen/drivers/passthrough/device_tree.c b/xen/drivers/passthrough/device_tree.c index 075fb25a3706..f2ee0a72f541 100644 --- a/xen/drivers/passthrough/device_tree.c +++ b/xen/drivers/passthrough/device_tree.c @@ -318,6 +318,13 @@ int iommu_do_dt_domctl(struct xen_domctl *domctl, struct domain *d, break; } + /* TODO: RFC allow assignment of devices without IOMMU protection. */ + if ( !dt_device_is_protected(dev) ) + { + ret = 0; + break; + } + ret = iommu_assign_dt_device(d, dev); if ( ret ) diff --git a/xen/include/asm-generic/device.h b/xen/include/asm-generic/device.h index 1acd1ba1d8b4..9fcdabfda9bc 100644 --- a/xen/include/asm-generic/device.h +++ b/xen/include/asm-generic/device.h @@ -18,6 +18,7 @@ enum device_class DEVICE_IOMMU, DEVICE_INTERRUPT_CONTROLLER, DEVICE_PCI_HOSTBRIDGE, + DEVICE_ARM_SCI, /* Use for error */ DEVICE_UNKNOWN, }; diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index 24840eeaa666..55eed9992c9d 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -327,6 +327,8 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); #define XEN_DOMCTL_CONFIG_TEE_OPTEE 1 #define XEN_DOMCTL_CONFIG_TEE_FFA 2 +#define XEN_DOMCTL_CONFIG_ARM_SCI_NONE 0 + struct xen_arch_domainconfig { /* IN/OUT */ uint8_t gic_version; @@ -350,6 +352,8 @@ struct xen_arch_domainconfig { * */ uint32_t clock_frequency; + /* IN */ + uint8_t arm_sci_type; }; #endif /* __XEN__ || __XEN_TOOLS__ */ From patchwork Tue Mar 11 11:16:13 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Grygorii Strashko X-Patchwork-Id: 14011517 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id B57ADC28B2E for ; Tue, 11 Mar 2025 11:16:58 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.907857.1315065 (Exim 4.92) (envelope-from ) id 1trxbC-0006xm-Lf; Tue, 11 Mar 2025 11:16:38 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 907857.1315065; Tue, 11 Mar 2025 11:16:38 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1trxbC-0006xb-Iw; Tue, 11 Mar 2025 11:16:38 +0000 Received: by outflank-mailman (input) for mailman id 907857; Tue, 11 Mar 2025 11:16:37 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1trxbB-0006Sq-4K for xen-devel@lists.xenproject.org; Tue, 11 Mar 2025 11:16:37 +0000 Received: from mail-lf1-x12b.google.com (mail-lf1-x12b.google.com [2a00:1450:4864:20::12b]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 4bd56487-fe6a-11ef-9ab9-95dc52dad729; Tue, 11 Mar 2025 12:16:36 +0100 (CET) Received: by mail-lf1-x12b.google.com with SMTP id 2adb3069b0e04-54298ec925bso7021294e87.3 for ; Tue, 11 Mar 2025 04:16:36 -0700 (PDT) Received: from epuakyiw0a98.kyiv.epam.com (ll-74.141.223.85.sovam.net.ua. [85.223.141.74]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5498ae45fa8sm1755729e87.52.2025.03.11.04.16.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Mar 2025 04:16:34 -0700 (PDT) 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: 4bd56487-fe6a-11ef-9ab9-95dc52dad729 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741691795; x=1742296595; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=hGhUZQZETvwJUHblIGD6a6nZ384/sBHUcT5eMii7h8w=; b=HQt9OphC2vrL27PyMOOOLhC/Vpk728zA79jSt4t2Wg4SedWd0/YE35MfZ71LTlHb0F dMZa0g/aKzMvogPoZYkMZgVRuIE1JqjR2YXenp5n0a1GZ5j6XjUIqH48gmhCb0V3O0/I X5/YmsqrC2mxcWlUYxYWSuMOtr9TAcFM6S5RUYrM+nELX9Q0hNtyF4ga+95PWa9Mj1PQ 858bBCtUolK80Smgnf0UckfWI1qYGo2yYypGKqtGjlZtWZq+ycxcqV21/BRvIvsdYQKE twrip0zGxWHCkVLwYPPx5duAoJwboKG/e5Zvz8Qw9UUuFq7jB61lkp1F8dK2Y5kIX779 EpQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741691795; x=1742296595; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=hGhUZQZETvwJUHblIGD6a6nZ384/sBHUcT5eMii7h8w=; b=mt6Emzmb1LzZyOiRcJ7sx6BytGcRiNY9jSrGjC5AyyG+pBxf0lohLQo6NFLY1KE5Hz Pvirjus+Rk8YnL6lLeFs7RbojCLCVK5GvdjhgTqOihDfyDTr3GCGx/5y4ICZCxn86q0T w5hbhnmzabhmIQaC2vmbmMF4bxNT+VIm2amszMfbJ0pqScT8JA7LPlJ5szTgT/VIVzfH +qD/28LyejY0FVIvjwVPmAld/ZZ3COtgcHwcrPzb30md0YSEIPQ/cngDRZVkWjKTQyiK Yqsvos2/jWJf0NWX2MRjOYgZkobjz4UyjxA2kVtWK+NyZ/jfeRdO/2aQKg7P7tnPHIXq eVuA== X-Gm-Message-State: AOJu0YxoOspnq6i2jTSmcXlI4GLesVo8bFWmwAMq2+6hP0uJP9n9chIr nl9GBbZnE7MlknSeDI+y93HfpbQcDs6ZK46CJ8vJ0e/Npyy2oAbR4pDazA== X-Gm-Gg: ASbGncsZShE7Ep4s/A+22ZFYr0mzpi8sOWJDDmbdxTI0kgsW62TT84XIhFpzV5UMX1K gSn0GO1Qm89k4zzITI6p1SwCEtJiwmZB/vL4Mqv3Qc9wgIbAV4/LNsSfgwVDopZzZqfxwcNqpvD +uFUyDL3U6LS1QfCgbq9E66AYpEcagwr7xgG/aopLnSKEkOwei0JE+eMd3yElQzm4Z+oJaJ4own vU1TfGYSpYp6tiLUjrifcy+xjIFG3QUXeYPBeujqNOFUSElEacE1BtVex55eXRQApGgZVEgvkZ5 RfwKwP/4/fs8pvLXrV6eTVymaQrkEqGk1smRzb585XhLKTwCQHY+yNFSNPFDl1OjWLQyNuQYmOJ AZ/Kb0qrGddIWr7w/hCfxIg8NJME= X-Google-Smtp-Source: AGHT+IHlWv9I8sfmTXTE7NFjAbWldyDQVy4MVUe/rIRmiDwXkC2wZ9bpIauh2gi8vNr/FkdRbc/SLw== X-Received: by 2002:a05:6512:1112:b0:549:4f0e:8e28 with SMTP id 2adb3069b0e04-54990e5d374mr6731453e87.15.1741691795231; Tue, 11 Mar 2025 04:16:35 -0700 (PDT) From: Grygorii Strashko X-Google-Original-From: Grygorii Strashko To: xen-devel@lists.xenproject.org Cc: Stefano Stabellini , Julien Grall , Andrew Cooper , Michal Orzel , "Roger Pau Monne" , Jan Beulich , Anthony PERARD , Volodymyr Babchuk , Oleksii Moisieiev , Bertrand Marquis , Juergen Gross , Grygorii Strashko Subject: [RFC PATCH v3 2/7] xen/arm: scmi-smc: update to be used under sci subsystem Date: Tue, 11 Mar 2025 13:16:13 +0200 Message-Id: <20250311111618.1850927-3-grygorii_strashko@epam.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250311111618.1850927-1-grygorii_strashko@epam.com> References: <20250311111618.1850927-1-grygorii_strashko@epam.com> MIME-Version: 1.0 The introduced SCI (System Control Interface) subsystem provides unified interface to integrate in Xen SCI drivers which adds support for ARM firmware (EL3, SCP) based software interfaces (like SCMI) that are used in system management. The SCI subsystem allows to add drivers for different FW interfaces or have different drivers for the same FW interface (for example, SCMI with different transports). This patch updates SCMI over SMC calls handling layer, introduced by commit 3e322bef8bc0 ("xen/arm: firmware: Add SCMI over SMC calls handling layer"), to be SCI driver: - convert to DT device; - convert to SCI Xen interface. Signed-off-by: Grygorii Strashko --- xen/arch/arm/firmware/Kconfig | 13 ++- xen/arch/arm/firmware/scmi-smc.c | 93 +++++++++++--------- xen/arch/arm/include/asm/firmware/scmi-smc.h | 41 --------- xen/arch/arm/vsmc.c | 5 +- xen/include/public/arch-arm.h | 1 + 5 files changed, 64 insertions(+), 89 deletions(-) delete mode 100644 xen/arch/arm/include/asm/firmware/scmi-smc.h diff --git a/xen/arch/arm/firmware/Kconfig b/xen/arch/arm/firmware/Kconfig index fc7918c7fc56..02d7b600317f 100644 --- a/xen/arch/arm/firmware/Kconfig +++ b/xen/arch/arm/firmware/Kconfig @@ -8,9 +8,18 @@ config ARM_SCI menu "Firmware Drivers" +choice + prompt "ARM SCI driver type" + default ARM_SCI_NONE + help + Choose which ARM SCI driver to enable. + +config ARM_SCI_NONE + bool "none" + config SCMI_SMC bool "Forward SCMI over SMC calls from hwdom to EL3 firmware" - default y + select ARM_SCI help This option enables basic awareness for SCMI calls using SMC as doorbell mechanism and Shared Memory for transport ("arm,scmi-smc" @@ -18,4 +27,6 @@ config SCMI_SMC firmware node is used to trap and forward corresponding SCMI SMCs to firmware running at EL3, for calls coming from the hardware domain. +endchoice + endmenu diff --git a/xen/arch/arm/firmware/scmi-smc.c b/xen/arch/arm/firmware/scmi-smc.c index 33473c04b181..188bd659513b 100644 --- a/xen/arch/arm/firmware/scmi-smc.c +++ b/xen/arch/arm/firmware/scmi-smc.c @@ -9,6 +9,7 @@ * Copyright 2024 NXP */ +#include #include #include #include @@ -16,12 +17,11 @@ #include #include +#include #include -#include #define SCMI_SMC_ID_PROP "arm,smc-id" -static bool __ro_after_init scmi_enabled; static uint32_t __ro_after_init scmi_smc_id; /* @@ -41,14 +41,11 @@ static bool scmi_is_valid_smc_id(uint32_t fid) * * Returns true if SMC was handled (regardless of response), false otherwise. */ -bool scmi_handle_smc(struct cpu_user_regs *regs) +static bool scmi_handle_smc(struct cpu_user_regs *regs) { uint32_t fid = (uint32_t)get_user_reg(regs, 0); struct arm_smccc_res res; - if ( !scmi_enabled ) - return false; - if ( !scmi_is_valid_smc_id(fid) ) return false; @@ -78,49 +75,45 @@ bool scmi_handle_smc(struct cpu_user_regs *regs) return true; } -static int __init scmi_check_smccc_ver(void) +static int scmi_smc_domain_init(struct domain *d, + struct xen_domctl_createdomain *config) { - if ( smccc_ver < ARM_SMCCC_VERSION_1_1 ) - { - printk(XENLOG_WARNING - "SCMI: No SMCCC 1.1 support, SCMI calls forwarding disabled\n"); - return -ENOSYS; - } + if ( !is_hardware_domain(d) ) + return 0; + d->arch.sci_enabled = true; + printk(XENLOG_DEBUG "SCMI: %pd init\n", d); return 0; } -static int __init scmi_dt_init_smccc(void) +static void scmi_smc_domain_destroy(struct domain *d) { - static const struct dt_device_match scmi_ids[] __initconst = - { - /* We only support "arm,scmi-smc" binding for now */ - DT_MATCH_COMPATIBLE("arm,scmi-smc"), - { /* sentinel */ }, - }; - const struct dt_device_node *scmi_node; - int ret; + if ( !is_hardware_domain(d) ) + return; - /* If no SCMI firmware node found, fail silently as it's not mandatory */ - scmi_node = dt_find_matching_node(NULL, scmi_ids); - if ( !scmi_node ) - return -EOPNOTSUPP; + printk(XENLOG_DEBUG "SCMI: %pd destroy\n", d); +} - ret = dt_property_read_u32(scmi_node, SCMI_SMC_ID_PROP, &scmi_smc_id); - if ( !ret ) +static int __init scmi_check_smccc_ver(void) +{ + if ( smccc_ver < ARM_SMCCC_VERSION_1_1 ) { - printk(XENLOG_ERR "SCMI: No valid \"%s\" property in \"%s\" DT node\n", - SCMI_SMC_ID_PROP, scmi_node->full_name); - return -ENOENT; + printk(XENLOG_WARNING + "SCMI: No SMCCC 1.1 support, SCMI calls forwarding disabled\n"); + return -ENOSYS; } - scmi_enabled = true; - return 0; } +static const struct sci_mediator_ops scmi_smc_ops = { + .handle_call = scmi_handle_smc, + .domain_init = scmi_smc_domain_init, + .domain_destroy = scmi_smc_domain_destroy, +}; + /* Initialize the SCMI layer based on SMCs and Device-tree */ -static int __init scmi_init(void) +static int __init scmi_dom0_init(struct dt_device_node *dev, const void *data) { int ret; @@ -134,22 +127,36 @@ static int __init scmi_init(void) if ( ret ) return ret; - ret = scmi_dt_init_smccc(); - if ( ret == -EOPNOTSUPP ) - return ret; + ret = dt_property_read_u32(dev, SCMI_SMC_ID_PROP, &scmi_smc_id); + if ( !ret ) + { + printk(XENLOG_ERR "SCMI: No valid \"%s\" property in \"%s\" DT node\n", + SCMI_SMC_ID_PROP, dt_node_full_name(dev)); + return -ENOENT; + } + + ret = sci_register(&scmi_smc_ops); if ( ret ) - goto err; + { + printk(XENLOG_ERR "SCMI: mediator already registered (ret = %d)\n", + ret); + return ret; + } printk(XENLOG_INFO "Using SCMI with SMC ID: 0x%x\n", scmi_smc_id); return 0; - - err: - printk(XENLOG_ERR "SCMI: Initialization failed (ret = %d)\n", ret); - return ret; } -__initcall(scmi_init); +static const struct dt_device_match scmi_smc_match[] __initconst = { + DT_MATCH_COMPATIBLE("arm,scmi-smc"), + { /* sentinel */ }, +}; + +DT_DEVICE_START(gicv3, "SCMI SMC DOM0", DEVICE_ARM_SCI) + .dt_match = scmi_smc_match, + .init = scmi_dom0_init, +DT_DEVICE_END /* * Local variables: diff --git a/xen/arch/arm/include/asm/firmware/scmi-smc.h b/xen/arch/arm/include/asm/firmware/scmi-smc.h deleted file mode 100644 index 6b1a164a400e..000000000000 --- a/xen/arch/arm/include/asm/firmware/scmi-smc.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * xen/arch/arm/include/asm/firmware/scmi-smc.h - * - * ARM System Control and Management Interface (SCMI) over SMC - * Generic handling layer - * - * Andrei Cherechesu - * Copyright 2024 NXP - */ - -#ifndef __ASM_SCMI_SMC_H__ -#define __ASM_SCMI_SMC_H__ - -#include - -struct cpu_user_regs; - -#ifdef CONFIG_SCMI_SMC - -bool scmi_handle_smc(struct cpu_user_regs *regs); - -#else - -static inline bool scmi_handle_smc(struct cpu_user_regs *regs) -{ - return false; -} - -#endif /* CONFIG_SCMI_SMC */ - -#endif /* __ASM_SCMI_H__ */ - -/* - * Local variables: - * mode: C - * c-file-style: "BSD" - * c-basic-offset: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/arch/arm/vsmc.c b/xen/arch/arm/vsmc.c index 51b3c0297314..b33c69a1c22a 100644 --- a/xen/arch/arm/vsmc.c +++ b/xen/arch/arm/vsmc.c @@ -21,7 +21,6 @@ #include #include #include -#include /* Number of functions currently supported by Hypervisor Service. */ #define XEN_SMCCC_FUNCTION_COUNT 3 @@ -233,7 +232,7 @@ static bool handle_sip(struct cpu_user_regs *regs) if ( platform_smc(regs) ) return true; - return scmi_handle_smc(regs); + return sci_handle_call(regs); } /* @@ -301,8 +300,6 @@ static bool vsmccc_handle_call(struct cpu_user_regs *regs) break; case ARM_SMCCC_OWNER_SIP: handled = handle_sip(regs); - if ( !handled ) - handled = sci_handle_call(regs); break; case ARM_SMCCC_OWNER_TRUSTED_APP ... ARM_SMCCC_OWNER_TRUSTED_APP_END: case ARM_SMCCC_OWNER_TRUSTED_OS ... ARM_SMCCC_OWNER_TRUSTED_OS_END: diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index 55eed9992c9d..095b1a23e30c 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -328,6 +328,7 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); #define XEN_DOMCTL_CONFIG_TEE_FFA 2 #define XEN_DOMCTL_CONFIG_ARM_SCI_NONE 0 +#define XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC 1 struct xen_arch_domainconfig { /* IN/OUT */ From patchwork Tue Mar 11 11:16:14 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Grygorii Strashko X-Patchwork-Id: 14011518 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id CE045C282EC for ; Tue, 11 Mar 2025 11:17:02 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.907860.1315075 (Exim 4.92) (envelope-from ) id 1trxbF-0007G1-Uc; Tue, 11 Mar 2025 11:16:41 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 907860.1315075; Tue, 11 Mar 2025 11:16:41 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1trxbF-0007Fo-Ph; Tue, 11 Mar 2025 11:16:41 +0000 Received: by outflank-mailman (input) for mailman id 907860; Tue, 11 Mar 2025 11:16:40 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1trxbE-0006Sq-5w for xen-devel@lists.xenproject.org; Tue, 11 Mar 2025 11:16:40 +0000 Received: from mail-lj1-x230.google.com (mail-lj1-x230.google.com [2a00:1450:4864:20::230]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 4d8b93ed-fe6a-11ef-9ab9-95dc52dad729; Tue, 11 Mar 2025 12:16:39 +0100 (CET) Received: by mail-lj1-x230.google.com with SMTP id 38308e7fff4ca-30bfc8faef9so32685031fa.1 for ; Tue, 11 Mar 2025 04:16:39 -0700 (PDT) Received: from epuakyiw0a98.kyiv.epam.com (ll-74.141.223.85.sovam.net.ua. [85.223.141.74]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5498ae45fa8sm1755729e87.52.2025.03.11.04.16.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Mar 2025 04:16:36 -0700 (PDT) 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: 4d8b93ed-fe6a-11ef-9ab9-95dc52dad729 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741691798; x=1742296598; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=dZ8IiY6XgKfSZ4z1G9tlPGGTDMovYwX3g0MBfNvj3Cs=; b=CBaP2AX1s5zyWTfjDVj3q/+tD2+qRwbckiCuIN+v1zMrftdEYgcDp9lUdenq1VVAwd hli+fG+LIlsHYFb5YO2DCv91kQgPsqjbCM+Kt5DPNHjpjmXwJA8qRAo57Mc99MQm5Ggv 6Zn7DjE+8D56IYGnTMF5kbeZHxOknghyu1PJBtbSUai0L9d0wBS4CL/SLiaoHr/pOxdj XHntwmEIlfjlwCL5vika/061UpG3WGcZAjtodkSzoQfY8oWkvZN1WlFsjLRyW748E/Iv 1z/LgmLfzxvB3K4r6JiKhNHP1gIcOT/q2WSueoKoF68/eaexsfvdf+GeevpEjMEKpVpR YROQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741691798; x=1742296598; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=dZ8IiY6XgKfSZ4z1G9tlPGGTDMovYwX3g0MBfNvj3Cs=; b=DorzlewQ50RgbQV1pEQpELQpIuqXgpvEfAogoeTH8soIv7DbfLuNDDmEe6uGrM3Huj Vl+WbTzKAHdF4BhW06zy3Ps217FUok4a4SdhiQiSNOF+6dNfonE71Y+1AMha95DHSdtC PpEpNvfmI4HX19tv6gRPjwYjeC4G9eC4zF/82nutjKA2I3EjVOcD4alQrKWfHryPHF/R pvaFoHzU6pOpzQiJt4TE2VOfQLlam3YBF5ovdUkCg2WAVph9bElSgV6UPwixvuxp/vx7 NGSRKVY7Uyh0p05M/uYfxmdPzChs83pM6SbjD1v5Ay6sm8GSCjUzJ0x2ODiIKDT1E10y fjuQ== X-Gm-Message-State: AOJu0YxfPDeYv5AJ64RQ+Qcu2ZKMvVwljm/bHonQ9gppLL0HnTtYNSeY 4vY/DJcOkPEAW4UAeAPHOqvaVgnVQ9cS7+Etwfd0vC/KuJlEBwQYlaU8Yg== X-Gm-Gg: ASbGnctsc7bomL/mWg62N1ZxPHAT/8s520CenkhhD51GXgWOFpX/+mo1eNUeGT0xL5D g/jGWPLX8jykXkTtQ0yWpUntvwlQ5qLquOr/MQnzawmLQ8FHUCr8stmPdSFK+1Cxb/GCYON9rTy zSiJQB/kJ6HSxpvf42IWvlZO0zIH2UWxtMRUp7XRsi7/NOzVbFap72V14XMz9GB1fSaPh1jSLI+ FqyOdHwU9bHBKEG8IGjTQHkcQU0LI6QMHCKTEL14BdrGKZjhXJN5HwsEpoth0IEpP9X6npPt1vq Wa3ueHAWIPK0HkWabCqKrHEiOkYh90NRcFSh1G6ImstrzgOSWN9SfvRRSrYbXoeRMLBsv6x9JHz D5Th1MLo/1ScLzNOJGLOXdXlBEA8= X-Google-Smtp-Source: AGHT+IFxUf27PD/iQbSf+dmvyb3BN7p5RVYXcb02X3oue8L5FSS5VfDdw3RzWVnfz/fqptXjSmChVA== X-Received: by 2002:a05:6512:159a:b0:549:8924:2212 with SMTP id 2adb3069b0e04-54990e5866bmr6506877e87.17.1741691798136; Tue, 11 Mar 2025 04:16:38 -0700 (PDT) From: Grygorii Strashko X-Google-Original-From: Grygorii Strashko To: xen-devel@lists.xenproject.org Cc: Stefano Stabellini , Julien Grall , Andrew Cooper , Michal Orzel , "Roger Pau Monne" , Jan Beulich , Anthony PERARD , Volodymyr Babchuk , Oleksii Moisieiev , Bertrand Marquis , Juergen Gross , Grygorii Strashko Subject: [RFC PATCH v3 3/7] xen/arm: scmi-smc: passthrough SCMI SMC to guest domain Date: Tue, 11 Mar 2025 13:16:14 +0200 Message-Id: <20250311111618.1850927-4-grygorii_strashko@epam.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250311111618.1850927-1-grygorii_strashko@epam.com> References: <20250311111618.1850927-1-grygorii_strashko@epam.com> MIME-Version: 1.0 The commit 3e322bef8bc0 ("xen/arm: firmware: Add SCMI over SMC calls handling layer") introduces simple driver which forwards SCMI over SMC calls from hwdom/dom0 to EL3 firmware (TF-A) with a single SCMI OSPM agent support. While it working gracefully for hwdom/dom0 use case it doesn't cover "thin Dom0 with guest domain, which serves as Driver domain" use-case. In this case HW need to be enable in Driver domain and dom0 is performing only control functions. The EL3 SCMI firmware (TF-A) with a single SCMI OSPM agent support is pretty generic case for the default vendors SDK and new platforms. This patch enables passthrough of SCMI SMC single agent interface to the Driver domain which can be enabled in the following way: - dom0: add dom0_scmi_smc_passthrough to the Xen Command Line - domD: xl.cfg add "arm_sci" option as below arm_sci = "type=scmi_smc" - domD: xl.cfg enable access to the "arm,scmi-shmem" iomem = [ "47ff0,1@22001", ] - domD: add scmi nodes to the Driver domain partial device tree as in the below example: passthrough { scmi_shm_0: sram@22001000 { compatible = "arm,scmi-shmem"; reg = <0x0 0x22001000 0x0 0x1000>; }; firmware { compatible = "simple-bus"; scmi: scmi { compatible = "arm,scmi-smc"; shmem = <&scmi_shm_0>; ... } } } The SCMI SMC single agent interface can be enabled for one and only one domain. In general, the configuration is similar to any other HW passthrough, except explicitly enabling SCMI with "arm_sci" xl.cfg option. Note that SCMI and "arm,scmi-shmem" nodes will be removed from dom0 DT. Signed-off-by: Grygorii Strashko --- docs/man/xl.cfg.5.pod.in | 36 ++++++++++++++ docs/misc/xen-command-line.pandoc | 9 ++++ tools/include/libxl.h | 5 ++ tools/libs/light/libxl_arm.c | 13 ++++++ tools/libs/light/libxl_types.idl | 10 ++++ tools/xl/xl_parse.c | 66 ++++++++++++++++++++++++++ xen/arch/arm/firmware/Kconfig | 4 +- xen/arch/arm/firmware/scmi-smc.c | 78 +++++++++++++++++++++++++++++-- 8 files changed, 217 insertions(+), 4 deletions(-) diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in index 8e1422104e50..7edf272386e3 100644 --- a/docs/man/xl.cfg.5.pod.in +++ b/docs/man/xl.cfg.5.pod.in @@ -3094,6 +3094,42 @@ assigned to the domain. =back +=over 4 + +=item B + +Set ARM_SCI specific options for the guest. ARM SCI is System +Control Protocol allows domain to manage various functions that are provided +by HW platform firmware. + +B is a comma separated list of C settings, +from the following list: + +=over 4 + +=item B + +Specifies an ARM SCI type for the guest. + +=over 4 + +=item B + +Don't allow guest to use ARM SCI if present on the platform. This is the +default value. + +=item B + +Enables ARM SCMI SMC support for the guest by enabling SCMI over SMC calls +forwarding from domain to the EL3 firmware (like Trusted Firmware-A) with a +single SCMI OSPM agent support. +Should be used together with B Xen command line +option. + +=back + +=back + =head3 x86 =over 4 diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc index 9bbd00baef91..8e50f6b7c7ac 100644 --- a/docs/misc/xen-command-line.pandoc +++ b/docs/misc/xen-command-line.pandoc @@ -1082,6 +1082,15 @@ affinities to prefer but be not limited to the specified node(s). Pin dom0 vcpus to their respective pcpus +### dom0_scmi_smc_passthrough (ARM) +> `= ` + +The option is available when `CONFIG_SCMI_SMC` is compiled in, and allows to +enable SCMI SMC single agent interface for any, but only one guest domain, +which serves as Driver domain. The SCMI will be disabled for Dom0/hwdom and +SCMI nodes removed from Dom0/hwdom device tree. +(for example, thin Dom0 with Driver domain use-case). + ### dtuart (ARM) > `= path [:options]` diff --git a/tools/include/libxl.h b/tools/include/libxl.h index f8fe4afd7dca..5fa43637ab76 100644 --- a/tools/include/libxl.h +++ b/tools/include/libxl.h @@ -313,6 +313,11 @@ */ #define LIBXL_HAVE_BUILDINFO_ARCH_NR_SPIS 1 +/* + * libxl_domain_build_info has the arch_arm.sci* fields. + */ +#define LIBXL_HAVE_BUILDINFO_ARCH_ARM_SCI 1 + /* * LIBXL_HAVE_SOFT_RESET indicates that libxl supports performing * 'soft reset' for domains and there is 'soft_reset' shutdown reason diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c index 28cea1f643c9..d41adea1cefd 100644 --- a/tools/libs/light/libxl_arm.c +++ b/tools/libs/light/libxl_arm.c @@ -222,6 +222,19 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc, config->arch.sve_vl = d_config->b_info.arch_arm.sve_vl / 128U; } + switch (d_config->b_info.arm_sci.type) { + case LIBXL_ARM_SCI_TYPE_NONE: + config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_NONE; + break; + case LIBXL_ARM_SCI_TYPE_SCMI_SMC: + config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC; + break; + default: + LOG(ERROR, "Unknown ARM_SCI type %d", + d_config->b_info.arm_sci.type); + return ERROR_FAIL; + } + return 0; } diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl index 33c9cfc1a267..ea0d30654cdd 100644 --- a/tools/libs/light/libxl_types.idl +++ b/tools/libs/light/libxl_types.idl @@ -551,6 +551,15 @@ libxl_sve_type = Enumeration("sve_type", [ (2048, "2048") ], init_val = "LIBXL_SVE_TYPE_DISABLED") +libxl_arm_sci_type = Enumeration("arm_sci_type", [ + (0, "none"), + (1, "scmi_smc") + ], init_val = "LIBXL_ARM_SCI_TYPE_NONE") + +libxl_arm_sci = Struct("arm_sci", [ + ("type", libxl_arm_sci_type), + ]) + libxl_rdm_reserve = Struct("rdm_reserve", [ ("strategy", libxl_rdm_reserve_strategy), ("policy", libxl_rdm_reserve_policy), @@ -639,6 +648,7 @@ libxl_domain_build_info = Struct("domain_build_info",[ ("apic", libxl_defbool), ("dm_restrict", libxl_defbool), ("tee", libxl_tee_type), + ("arm_sci", libxl_arm_sci), ("u", KeyedUnion(None, libxl_domain_type, "type", [("hvm", Struct(None, [("firmware", string), ("bios", libxl_bios_type), diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c index 9a3679c02325..ac9bf0b25c5a 100644 --- a/tools/xl/xl_parse.c +++ b/tools/xl/xl_parse.c @@ -1284,6 +1284,63 @@ out: if (rc) exit(EXIT_FAILURE); } +static int parse_arm_sci_config(XLU_Config *cfg, libxl_arm_sci *arm_sci, + const char *str) +{ + enum { + STATE_OPTION, + STATE_TYPE, + STATE_TERMINAL, + }; + int ret, state = STATE_OPTION; + char *buf2, *tok, *ptr, *end; + + if (NULL == (buf2 = ptr = strdup(str))) + return ERROR_NOMEM; + + for (tok = ptr, end = ptr + strlen(ptr) + 1; ptr < end; ptr++) { + switch(state) { + case STATE_OPTION: + if (*ptr == '=') { + *ptr = '\0'; + if (!strcmp(tok, "type")) { + state = STATE_TYPE; + } else { + fprintf(stderr, "Unknown ARM_SCI option: %s\n", tok); + goto parse_error; + } + tok = ptr + 1; + } + break; + case STATE_TYPE: + if (*ptr == '\0' || *ptr == ',') { + state = *ptr == ',' ? STATE_OPTION : STATE_TERMINAL; + *ptr = '\0'; + ret = libxl_arm_sci_type_from_string(tok, &arm_sci->type); + if (ret) { + fprintf(stderr, "Unknown ARM_SCI type: %s\n", tok); + goto parse_error; + } + tok = ptr + 1; + } + break; + default: + break; + } + } + + if (tok != ptr || state != STATE_TERMINAL) + goto parse_error; + + free(buf2); + + return 0; + +parse_error: + free(buf2); + return ERROR_INVAL; +} + void parse_config_data(const char *config_source, const char *config_data, int config_len, @@ -2981,6 +3038,15 @@ skip_usbdev: if (!xlu_cfg_get_long (config, "nr_spis", &l, 0)) b_info->arch_arm.nr_spis = l; + if (!xlu_cfg_get_string(config, "arm_sci", &buf, 1)) { + libxl_arm_sci arm_sci = { 0 }; + if (!parse_arm_sci_config(config, &arm_sci, buf)) { + b_info->arm_sci.type = arm_sci.type; + } else { + exit(EXIT_FAILURE); + } + } + parse_vkb_list(config, d_config); d_config->virtios = NULL; diff --git a/xen/arch/arm/firmware/Kconfig b/xen/arch/arm/firmware/Kconfig index 02d7b600317f..2686ba313898 100644 --- a/xen/arch/arm/firmware/Kconfig +++ b/xen/arch/arm/firmware/Kconfig @@ -25,7 +25,9 @@ config SCMI_SMC doorbell mechanism and Shared Memory for transport ("arm,scmi-smc" compatible only). The value of "arm,smc-id" DT property from SCMI firmware node is used to trap and forward corresponding SCMI SMCs - to firmware running at EL3, for calls coming from the hardware domain. + to firmware running at EL3, for calls coming from the hardware domain or + driver domain. + Use with EL3 firmware which supports only single SCMI OSPM agent. endchoice diff --git a/xen/arch/arm/firmware/scmi-smc.c b/xen/arch/arm/firmware/scmi-smc.c index 188bd659513b..7a0130ea0ea9 100644 --- a/xen/arch/arm/firmware/scmi-smc.c +++ b/xen/arch/arm/firmware/scmi-smc.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include @@ -22,7 +24,11 @@ #define SCMI_SMC_ID_PROP "arm,smc-id" +static bool __ro_after_init opt_dom0_scmi_smc_passthrough = false; +boolean_param("dom0_scmi_smc_passthrough", opt_dom0_scmi_smc_passthrough); + static uint32_t __ro_after_init scmi_smc_id; +static struct domain *scmi_dom; /* * Check if provided SMC Function Identifier matches the one known by the SCMI @@ -50,7 +56,7 @@ static bool scmi_handle_smc(struct cpu_user_regs *regs) return false; /* Only the hardware domain should use SCMI calls */ - if ( !is_hardware_domain(current->domain) ) + if ( scmi_dom != current->domain ) { gdprintk(XENLOG_WARNING, "SCMI: Unprivileged access attempt\n"); return false; @@ -78,9 +84,18 @@ static bool scmi_handle_smc(struct cpu_user_regs *regs) static int scmi_smc_domain_init(struct domain *d, struct xen_domctl_createdomain *config) { - if ( !is_hardware_domain(d) ) + if ( !opt_dom0_scmi_smc_passthrough && !is_hardware_domain(d) ) + return 0; + + if ( opt_dom0_scmi_smc_passthrough && + (config->arch.arm_sci_type != XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC || + is_hardware_domain(d)) ) return 0; + if ( scmi_dom ) + return -EEXIST; + + scmi_dom = d; d->arch.sci_enabled = true; printk(XENLOG_DEBUG "SCMI: %pd init\n", d); return 0; @@ -88,12 +103,68 @@ static int scmi_smc_domain_init(struct domain *d, static void scmi_smc_domain_destroy(struct domain *d) { - if ( !is_hardware_domain(d) ) + if ( scmi_dom && scmi_dom != d ) return; + scmi_dom = NULL; + d->arch.sci_enabled = false; printk(XENLOG_DEBUG "SCMI: %pd destroy\n", d); } +/* + * Handle Dom0 SCMI SMC specific DT nodes + * + * Copy SCMI nodes into Dom0 device tree if dom0_scmi_smc_passthrough=false. + * + */ +static bool scmi_smc_dt_handle_node(struct domain *d, + struct dt_device_node *node) +{ + static const struct dt_device_match shmem_matches[] __initconst = { + DT_MATCH_COMPATIBLE("arm,scmi-shmem"), + { /* sentinel */ }, + }; + static const struct dt_device_match scmi_matches[] __initconst = { + DT_MATCH_PATH("/firmware/scmi"), + { /* sentinel */ }, + }; + + if ( dt_match_node(shmem_matches, node) && !sci_domain_is_enabled(d) ) + { + dt_dprintk(" Skip scmi shmem node\n"); + return true; + } + + if ( dt_match_node(scmi_matches, node) && !sci_domain_is_enabled(d) ) + { + struct dt_device_node *shmem_node; + const __be32 *prop; + u64 paddr, size; + int ret; + + dt_dprintk(" Skip scmi node\n"); + + prop = dt_get_property(node, "shmem", NULL); + if ( !prop ) + return true; + + shmem_node = dt_find_node_by_phandle(be32_to_cpup(prop)); + if ( !shmem_node ) + return true; + + ret = dt_device_get_address(shmem_node, 0, &paddr, &size); + if ( ret ) + return true; + + ret = iomem_permit_access(d, paddr_to_pfn(paddr), + paddr_to_pfn(paddr + size - 1)); + + return true; + } + + return false; +} + static int __init scmi_check_smccc_ver(void) { if ( smccc_ver < ARM_SMCCC_VERSION_1_1 ) @@ -110,6 +181,7 @@ static const struct sci_mediator_ops scmi_smc_ops = { .handle_call = scmi_handle_smc, .domain_init = scmi_smc_domain_init, .domain_destroy = scmi_smc_domain_destroy, + .dom0_dt_handle_node = scmi_smc_dt_handle_node, }; /* Initialize the SCMI layer based on SMCs and Device-tree */ From patchwork Tue Mar 11 11:16:15 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Grygorii Strashko X-Patchwork-Id: 14011520 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id D2E75C28B2E for ; Tue, 11 Mar 2025 11:17:13 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.907867.1315095 (Exim 4.92) (envelope-from ) id 1trxbM-0007vt-Kd; Tue, 11 Mar 2025 11:16:48 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 907867.1315095; Tue, 11 Mar 2025 11:16:48 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1trxbM-0007vg-EQ; Tue, 11 Mar 2025 11:16:48 +0000 Received: by outflank-mailman (input) for mailman id 907867; Tue, 11 Mar 2025 11:16:47 +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 1trxbL-00061U-20 for xen-devel@lists.xenproject.org; Tue, 11 Mar 2025 11:16:47 +0000 Received: from mail-lj1-x229.google.com (mail-lj1-x229.google.com [2a00:1450:4864:20::229]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 50632b62-fe6a-11ef-9898-31a8f345e629; Tue, 11 Mar 2025 12:16:44 +0100 (CET) Received: by mail-lj1-x229.google.com with SMTP id 38308e7fff4ca-30bee278c2aso52145171fa.0 for ; Tue, 11 Mar 2025 04:16:44 -0700 (PDT) Received: from epuakyiw0a98.kyiv.epam.com (ll-74.141.223.85.sovam.net.ua. [85.223.141.74]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5498ae45fa8sm1755729e87.52.2025.03.11.04.16.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Mar 2025 04:16:40 -0700 (PDT) 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: 50632b62-fe6a-11ef-9898-31a8f345e629 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741691803; x=1742296603; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ULLAK7NmCziJs9BSDGosiIrFW201LWUnnGDpVeP39lU=; b=lNVOBg9q8bq1WyXNqcLHVtcLJ+VW5YlyXFx+7DlcGXFF7vgCxwT2zlZYymZ64Gtttc rdzbIHDsHxR23/4RH+s6125qB2Y1+wYlbyc/A4UssTCll4AGgM96wW9kyXYrPgXGzuh3 rQhnvqhVkhf6jz3mpyilcdtBfZ6lyLyw0wp+98hMLAOyoKHgfx9yBXx7sQeQRszjfcb+ W0i2goNILYCX2oIH2pznq3qKuJZyUnyYuUlZBpigLFAQwyMtonEgVLD1+12/7ImoovRu OjH2cdlhR0IdRFOSmpNVFhYwKzv7uT9CR1AhTyUDZtuuM0fjKLjBOBw9hYYpwPZuF6rz FF9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741691803; x=1742296603; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ULLAK7NmCziJs9BSDGosiIrFW201LWUnnGDpVeP39lU=; b=a9erxy57EXiadMYtpxc7BpgRf8JK1ebypX/f8VU1QD1pyGFeb2dM+7sROA2uC0gjVn el9wdwUw4nt9e8SjCZD/aXxfGYe1AeRza3U7NE509cjCfc3CgyYXRELC2QvA9txTAmQn AHk1emuNV+KU+OPFvZbbt+5lft2FBJ2GXGlBUr81l9b/47aIHX5HPHpA/DvKZjJtGE/6 R1eks5izTYO28ljmKYYQuEQ0S4Oiv1QwNCbKpAb/X/MAr36xe+qQuekB0lbfNaEnnm7y F1Y4CD+iw2FSEqNW7a15WDcHmL3z+OC49e5D2I/qA20EawbsJegVoG8oZmL8I0859Otw RrcA== X-Gm-Message-State: AOJu0Yy2VErUq3Hk0YJaWBCmOsTg9OFsnVdXKamL58n20iTcFkbysjOd IyCAC33YN2QXF0RJCXicAYMx5Aa81E0U99w5MhNFjXeNJfFt7hzlZvdLYQ== X-Gm-Gg: ASbGncv0g8zLEpBtoWytD/c0WHuCkebid+fckntF3vTbjUeGOqBSBYekxtKQ9wyBN6p dmHZUsHlOcnIPtNJ/7igHeSnBGDrh+GAghDalOmemP+p2VpVsI8BdsW0PzdEe7cZ0shWAo6xUf0 43ai8SUn0MZCVhrUd3Srf7z64OMV39OSmhIt1GcMtJMaYC4IySKciN1zVDntkj4Vqpda4Dnt1lD a6PImu8pwfOOTnYKYY25JzXRXS5FxACpjGSrpH66y70ZcRqBDjOfu4nTytsprSLaXU6bIC6bj6B m9uiJbKk1AQMySQUe2Gm5438dVTNRVF/9k3zJKI12R0O7201VgkhJN+FBRhlwJf7iiUR2pwcahI X8XNc9b7N1wOHcAO1VzAm7fpUJ5g= X-Google-Smtp-Source: AGHT+IElCrrkRe4hwT75pzwhZTMPYIUdZ7glJt6yA9xPn9E8GYjecUN2cUo3EXRlfv/KVXK9G2ZkoA== X-Received: by 2002:a05:6512:39d6:b0:545:a70:74c5 with SMTP id 2adb3069b0e04-549abd252a5mr1045694e87.13.1741691802373; Tue, 11 Mar 2025 04:16:42 -0700 (PDT) From: Grygorii Strashko X-Google-Original-From: Grygorii Strashko To: xen-devel@lists.xenproject.org Cc: Stefano Stabellini , Julien Grall , Andrew Cooper , Michal Orzel , "Roger Pau Monne" , Jan Beulich , Anthony PERARD , Volodymyr Babchuk , Oleksii Moisieiev , Bertrand Marquis , Juergen Gross , Grygorii Strashko Subject: [RFC PATCH v3 4/7] xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver Date: Tue, 11 Mar 2025 13:16:15 +0200 Message-Id: <20250311111618.1850927-5-grygorii_strashko@epam.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250311111618.1850927-1-grygorii_strashko@epam.com> References: <20250311111618.1850927-1-grygorii_strashko@epam.com> MIME-Version: 1.0 From: Oleksii Moisieiev This patch introduces SCI driver to support for ARM EL3 Trusted Firmware-A (TF-A) which provides SCMI interface with multi-agnet support, as shown below. +-----------------------------------------+ | | | EL3 TF-A SCMI | +-------+--+-------+--+-------+--+-------++ |shmem0 | |shmem1 | |shmem2 | |shmemX | +-----+-+ +---+---+ +--+----+ +---+---+ smc-id0 | | | | agent0 | | | | +-----v--------+---------+-----------+----+ | | | | | | | | | | +--------------+---------+-----------+----+ smc-id1 | smc-id2| smc-idX| agent1 | agent2 | agentX | | | | +----v---+ +--v-----+ +--v-----+ | | | | | | | Dom0 | | Dom1 | | DomX | | | | | | | | | | | | | +--------+ +--------+ +--------+ The EL3 SCMI multi-agent firmware expected to provide SCMI SMC/HVC shared memory transport for every Agent in the system. The SCMI Agent transport channel defined by pair: - smc-id: SMC/HVC id used for Doorbell - shmem: shared memory for messages transfer, Xen page aligned, p2m_mmio_direct_nc. The follwoing SCMI Agents expected to be defined by SCMI FW to enable SCMI multi-agent functionality under Xen: - Xen manegement agent: trusted agents that accesses to the Base Protocol commands to configure agent specific permissions - OSPM VM agents: non-trusted agent, one for each Guest domain which is allowed direct HW access. At least one OSPM VM agent has to be provided by FW if HW is handled only by Dom0 or Driver Domain. The EL3 SCMI FW expected to implement following Base protocol messages: - BASE_DISCOVER_AGENT - BASE_RESET_AGENT_CONFIGURATION (optional) - BASE_SET_DEVICE_PERMISSIONS (optional) The SCI SCMI SMC multi-agent driver implements following functionality: - It's initialized based on the Host DT SCMI node (only one SCMI interface is supported) which describes Xen management agent SCMI interface. scmi_shm_0 : sram@47ff0000 { compatible = "arm,scmi-shmem"; reg = <0x0 0x47ff0000 0x0 0x1000>; }; firmware { scmi: scmi { compatible = "arm,scmi-smc"; arm,smc-id = <0x82000002>; // Xen manegement agent smc-id \#address-cells = < 1>; \#size-cells = < 0>; \#access-controller - cells = < 1>; shmem = <&scmi_shm_0>; // Xen manegement agent shmem protocol@X{ }; }; }; - It obtains Xen specific SCMI Agent's configuration from the Host DT, probes Agents and build SCMI Agents list. The Agents configuration is taken from: chosen { xen,scmi-secondary-agents = < 1 0x82000003 &scmi_shm_1 2 0x82000004 &scmi_shm_2 3 0x82000005 &scmi_shm_3 4 0x82000006 &scmi_shm_4>; } /{ scmi_shm_1: sram@47ff1000 { compatible = "arm,scmi-shmem"; reg = <0x0 0x47ff1000 0x0 0x1000>; }; scmi_shm_2: sram@47ff2000 { compatible = "arm,scmi-shmem"; reg = <0x0 0x47ff2000 0x0 0x1000>; }; scmi_shm_3: sram@47ff3000 { compatible = "arm,scmi-shmem"; reg = <0x0 0x47ff3000 0x0 0x1000>; }; } where first item is "agent_id", second - "arm,smc-id", and third - "arm,scmi-shmem" for this agent_id. Note that Xen is the only one entry in the system which need to know about SCMI multi-agent support. - It implements the SCI subsystem interface required for configuring and enabling SCMI functionality for Dom0/hwdom and Guest domains. To enable SCMI functionality for domain it has to be configured with unique supported SCMI Agent_id and use corresponding SCMI SMC/HVC shared memory transport [smc-id, shmem] defined for this SCMI Agent_id. - Once Xen domain is configured it can communicate with EL3 SCMI FW: -- zero-copy, the guest domain puts SCMI message in shmem; -- the guest triggers SMC/HVC exception with smc-id (doorbell); -- the Xen driver catches exception, do checks and synchronously forwards it to EL3 FW. - the Xen driver sends BASE_RESET_AGENT_CONFIGURATION message to Xen management agent channel on domain destroy event. This allows to reset resources used by domain and so implement use-case like domain reboot. Dom0 Enable SCMI SMC: - pass dom0_scmi_agent_id= in Xen command line option. if not provided SCMI will be disabled for Dom0 and all SCMI nodes removed from Dom0 DT. The driver updates Dom0 DT SCMI node "arm,smc-id" value and fix up shmem node according to assigned agent_id. Guest domains enable SCMI SMC: - xl.cfg: add configuration option as below arm_sci = "type=scmi_smc_multiagent,agent_id=2" - xl.cfg: enable access to the "arm,scmi-shmem" which should correspond assigned agent_id for the domain, for example: iomem = [ "47ff2,1@22001", ] - DT: add SCMI nodes to the Driver domain partial device tree as in the below example. The "arm,smc-id" should correspond assigned agent_id for the domain: passthrough { scmi_shm_0: sram@22001000 { compatible = "arm,scmi-shmem"; reg = <0x0 0x22001000 0x0 0x1000>; }; firmware { compatible = "simple-bus"; scmi: scmi { compatible = "arm,scmi-smc"; arm,smc-id = <0x82000004>; shmem = <&scmi_shm_0>; ... } } } SCMI "4.2.1.1 Device specific access control" The XEN SCI SCMI SMC multi-agent driver performs "access-controller" provider function in case EL3 SCMI FW implements SCMI "4.2.1.1 Device specific access control" and provides the BASE_SET_DEVICE_PERMISSIONS command to configure the devices that an agents have access to. The DT SCMI node should "#access-controller-cells=<1>" property and DT devices should be bound to the Xen SCMI. &i2c1 { access-controllers = <&scmi 0>; }; The Dom0 and dom0less (TBD) domains DT devices will be processed automatically through sci_assign_dt_device() call, but to assign SCMI devices from toolstack the xl.cfg:"dtdev" property shell be used: dtdev = [ "/soc/i2c@e6508000", ] xl.cfg:dtdev will contain all nodes which are under SCMI management (not only those which are behind IOMMU). TODO: - dom0less is not fully supported yet - move memcpy_fro/tomio in separate patch [1] https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/firmware/arm,scmi.yaml [2] https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/access-controllers/access-controllers.yaml Signed-off-by: Oleksii Moisieiev Signed-off-by: Grygorii Strashko --- docs/man/xl.cfg.5.pod.in | 15 + docs/misc/xen-command-line.pandoc | 9 + tools/libs/light/libxl_arm.c | 4 + tools/libs/light/libxl_types.idl | 4 +- tools/xl/xl_parse.c | 17 + xen/arch/arm/domain_build.c | 3 +- xen/arch/arm/firmware/Kconfig | 11 + xen/arch/arm/firmware/Makefile | 1 + xen/arch/arm/firmware/scmi-proto.h | 164 ++++ xen/arch/arm/firmware/scmi-shmem.c | 172 ++++ xen/arch/arm/firmware/scmi-shmem.h | 45 + xen/arch/arm/firmware/scmi-smc-multiagent.c | 856 ++++++++++++++++++++ xen/include/public/arch-arm.h | 3 + 13 files changed, 1302 insertions(+), 2 deletions(-) create mode 100644 xen/arch/arm/firmware/scmi-proto.h create mode 100644 xen/arch/arm/firmware/scmi-shmem.c create mode 100644 xen/arch/arm/firmware/scmi-shmem.h create mode 100644 xen/arch/arm/firmware/scmi-smc-multiagent.c diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in index 7edf272386e3..fc6041724a13 100644 --- a/docs/man/xl.cfg.5.pod.in +++ b/docs/man/xl.cfg.5.pod.in @@ -3126,6 +3126,21 @@ single SCMI OSPM agent support. Should be used together with B Xen command line option. +=item B + +Enables ARM SCMI SMC multi-agent support for the guest by enabling SCMI over +SMC calls forwarding from domain to the EL3 firmware (like Trusted Firmware-A) +with a multi SCMI OSPM agent support. The SCMI B should be +specified for the guest. + +=back + +=item B + +Specifies a non-zero ARM SCI agent id for the guest. This option is mandatory +if the SCMI SMC support is enabled for the guest. The agent ids of domains +existing on a single host must be unique. + =back =back diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc index 8e50f6b7c7ac..bc3c64d6ec90 100644 --- a/docs/misc/xen-command-line.pandoc +++ b/docs/misc/xen-command-line.pandoc @@ -1091,6 +1091,15 @@ which serves as Driver domain. The SCMI will be disabled for Dom0/hwdom and SCMI nodes removed from Dom0/hwdom device tree. (for example, thin Dom0 with Driver domain use-case). +### dom0_scmi_agent_id (ARM) +> `= ` + +The option is available when `CONFIG_SCMI_SMC_MA` is compiled in, and allows to +enable SCMI functionality for Dom0 by specifying a non-zero ARM SCMI agent id. +The SCMI will be disabled for Dom0 if this option is not specified +(for example, thin Dom0 or dom0less use-cases). +The agent ids of domains existing on a single host must be unique. + ### dtuart (ARM) > `= path [:options]` diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c index d41adea1cefd..cdf5edb299af 100644 --- a/tools/libs/light/libxl_arm.c +++ b/tools/libs/light/libxl_arm.c @@ -229,6 +229,10 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc, case LIBXL_ARM_SCI_TYPE_SCMI_SMC: config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC; break; + case LIBXL_ARM_SCI_TYPE_SCMI_SMC_MULTIAGENT: + config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA; + config->arch.arm_sci_agent_id = d_config->b_info.arm_sci.agent_id; + break; default: LOG(ERROR, "Unknown ARM_SCI type %d", d_config->b_info.arm_sci.type); diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl index ea0d30654cdd..e6707c7ca9e7 100644 --- a/tools/libs/light/libxl_types.idl +++ b/tools/libs/light/libxl_types.idl @@ -553,11 +553,13 @@ libxl_sve_type = Enumeration("sve_type", [ libxl_arm_sci_type = Enumeration("arm_sci_type", [ (0, "none"), - (1, "scmi_smc") + (1, "scmi_smc"), + (2, "scmi_smc_multiagent") ], init_val = "LIBXL_ARM_SCI_TYPE_NONE") libxl_arm_sci = Struct("arm_sci", [ ("type", libxl_arm_sci_type), + ("agent_id", uint8) ]) libxl_rdm_reserve = Struct("rdm_reserve", [ diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c index ac9bf0b25c5a..011222ec55b9 100644 --- a/tools/xl/xl_parse.c +++ b/tools/xl/xl_parse.c @@ -1290,6 +1290,7 @@ static int parse_arm_sci_config(XLU_Config *cfg, libxl_arm_sci *arm_sci, enum { STATE_OPTION, STATE_TYPE, + STATE_AGENT_ID, STATE_TERMINAL, }; int ret, state = STATE_OPTION; @@ -1305,6 +1306,8 @@ static int parse_arm_sci_config(XLU_Config *cfg, libxl_arm_sci *arm_sci, *ptr = '\0'; if (!strcmp(tok, "type")) { state = STATE_TYPE; + } else if (!strcmp(tok, "agent_id")) { + state = STATE_AGENT_ID; } else { fprintf(stderr, "Unknown ARM_SCI option: %s\n", tok); goto parse_error; @@ -1324,11 +1327,24 @@ static int parse_arm_sci_config(XLU_Config *cfg, libxl_arm_sci *arm_sci, tok = ptr + 1; } break; + case STATE_AGENT_ID: + if (*ptr == ',' || *ptr == '\0') { + state = *ptr == ',' ? STATE_OPTION : STATE_TERMINAL; + *ptr = '\0'; + arm_sci->agent_id = strtoul(tok, NULL, 0); + tok = ptr + 1; + } default: break; } } + if (arm_sci->type == LIBXL_ARM_SCI_TYPE_SCMI_SMC_MULTIAGENT && + arm_sci->agent_id == 0) { + fprintf(stderr, "A non-zero ARM_SCI agent_id must be specified\n"); + goto parse_error; + } + if (tok != ptr || state != STATE_TERMINAL) goto parse_error; @@ -3042,6 +3058,7 @@ skip_usbdev: libxl_arm_sci arm_sci = { 0 }; if (!parse_arm_sci_config(config, &arm_sci, buf)) { b_info->arm_sci.type = arm_sci.type; + b_info->arm_sci.agent_id = arm_sci.agent_id; } else { exit(EXIT_FAILURE); } diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index 36d28b52a418..9238771a4aac 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -616,7 +616,8 @@ static int __init write_properties(struct domain *d, struct kernel_info *kinfo, dt_property_name_is_equal(prop, "linux,uefi-mmap-start") || dt_property_name_is_equal(prop, "linux,uefi-mmap-size") || dt_property_name_is_equal(prop, "linux,uefi-mmap-desc-size") || - dt_property_name_is_equal(prop, "linux,uefi-mmap-desc-ver")) + dt_property_name_is_equal(prop, "linux,uefi-mmap-desc-ver") || + dt_property_name_is_equal(prop, "xen,scmi-secondary-agents")) continue; if ( dt_property_name_is_equal(prop, "xen,dom0-bootargs") ) diff --git a/xen/arch/arm/firmware/Kconfig b/xen/arch/arm/firmware/Kconfig index 2686ba313898..63fc5eac8d52 100644 --- a/xen/arch/arm/firmware/Kconfig +++ b/xen/arch/arm/firmware/Kconfig @@ -29,6 +29,17 @@ config SCMI_SMC driver domain. Use with EL3 firmware which supports only single SCMI OSPM agent. +config SCMI_SMC_MA + bool "Enable ARM SCMI SMC multi-agent driver" + select ARM_SCI + help + Enables SCMI SMC/HVC multi-agent in XEN to pass SCMI requests from Domains + to EL3 firmware (TF-A) which supports multi-agent feature. + This feature allows to enable SCMI per Domain using unique SCMI agent_id, + so Domain is identified by EL3 firmware as an SCMI Agent and can access + allowed platform resources through dedicated SMC/HVC Shared memory based + transport. + endchoice endmenu diff --git a/xen/arch/arm/firmware/Makefile b/xen/arch/arm/firmware/Makefile index 71bdefc24afb..37927e690e98 100644 --- a/xen/arch/arm/firmware/Makefile +++ b/xen/arch/arm/firmware/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_ARM_SCI) += sci.o obj-$(CONFIG_SCMI_SMC) += scmi-smc.o +obj-$(CONFIG_SCMI_SMC_MA) += scmi-shmem.o scmi-smc-multiagent.o diff --git a/xen/arch/arm/firmware/scmi-proto.h b/xen/arch/arm/firmware/scmi-proto.h new file mode 100644 index 000000000000..3f4b9c5d6b7c --- /dev/null +++ b/xen/arch/arm/firmware/scmi-proto.h @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Arm System Control and Management Interface definitions + * Version 3.0 (DEN0056C) + * + * Copyright (c) 2024 EPAM Systems + */ + +#ifndef XEN_ARCH_ARM_SCI_SCMI_PROTO_H_ +#define XEN_ARCH_ARM_SCI_SCMI_PROTO_H_ + +#include + +#define SCMI_SHORT_NAME_MAX_SIZE 16 + +/* SCMI status codes. See section 4.1.4 */ +#define SCMI_SUCCESS 0 +#define SCMI_NOT_SUPPORTED (-1) +#define SCMI_INVALID_PARAMETERS (-2) +#define SCMI_DENIED (-3) +#define SCMI_NOT_FOUND (-4) +#define SCMI_OUT_OF_RANGE (-5) +#define SCMI_BUSY (-6) +#define SCMI_COMMS_ERROR (-7) +#define SCMI_GENERIC_ERROR (-8) +#define SCMI_HARDWARE_ERROR (-9) +#define SCMI_PROTOCOL_ERROR (-10) + +/* Protocol IDs */ +#define SCMI_BASE_PROTOCOL 0x10 + +/* Base protocol message IDs */ +#define SCMI_BASE_PROTOCOL_VERSION 0x0 +#define SCMI_BASE_PROTOCOL_ATTIBUTES 0x1 +#define SCMI_BASE_PROTOCOL_MESSAGE_ATTRIBUTES 0x2 +#define SCMI_BASE_DISCOVER_AGENT 0x7 +#define SCMI_BASE_SET_DEVICE_PERMISSIONS 0x9 +#define SCMI_BASE_RESET_AGENT_CONFIGURATION 0xB + +typedef struct scmi_msg_header { + uint8_t id; + uint8_t type; + uint8_t protocol; + uint32_t status; +} scmi_msg_header_t; + +/* Table 2 Message header format */ +#define SCMI_HDR_ID GENMASK(7, 0) +#define SCMI_HDR_TYPE GENMASK(9, 8) +#define SCMI_HDR_PROTO GENMASK(17, 10) + +#define SCMI_FIELD_GET(_mask, _reg) \ + ((typeof(_mask))(((_reg) & (_mask)) >> (ffs64(_mask) - 1))) +#define SCMI_FIELD_PREP(_mask, _val) \ + (((typeof(_mask))(_val) << (ffs64(_mask) - 1)) & (_mask)) + +static inline uint32_t pack_scmi_header(scmi_msg_header_t *hdr) +{ + return SCMI_FIELD_PREP(SCMI_HDR_ID, hdr->id) | + SCMI_FIELD_PREP(SCMI_HDR_TYPE, hdr->type) | + SCMI_FIELD_PREP(SCMI_HDR_PROTO, hdr->protocol); +} + +static inline void unpack_scmi_header(uint32_t msg_hdr, scmi_msg_header_t *hdr) +{ + hdr->id = SCMI_FIELD_GET(SCMI_HDR_ID, msg_hdr); + hdr->type = SCMI_FIELD_GET(SCMI_HDR_TYPE, msg_hdr); + hdr->protocol = SCMI_FIELD_GET(SCMI_HDR_PROTO, msg_hdr); +} + +static inline int scmi_to_xen_errno(int scmi_status) +{ + if ( scmi_status == SCMI_SUCCESS ) + return 0; + + switch ( scmi_status ) + { + case SCMI_NOT_SUPPORTED: + return -EOPNOTSUPP; + case SCMI_INVALID_PARAMETERS: + return -EINVAL; + case SCMI_DENIED: + return -EACCES; + case SCMI_NOT_FOUND: + return -ENOENT; + case SCMI_OUT_OF_RANGE: + return -ERANGE; + case SCMI_BUSY: + return -EBUSY; + case SCMI_COMMS_ERROR: + return -ENOTCONN; + case SCMI_GENERIC_ERROR: + return -EIO; + case SCMI_HARDWARE_ERROR: + return -ENXIO; + case SCMI_PROTOCOL_ERROR: + return -EBADMSG; + default: + return -EINVAL; + } +} + +/* PROTOCOL_VERSION */ +#define SCMI_VERSION_MINOR GENMASK(15, 0) +#define SCMI_VERSION_MAJOR GENMASK(31, 16) + +struct scmi_msg_prot_version_p2a { + uint32_t version; +} __packed; + +/* BASE PROTOCOL_ATTRIBUTES */ +#define SCMI_BASE_ATTR_NUM_PROTO GENMASK(7, 0) +#define SCMI_BASE_ATTR_NUM_AGENT GENMASK(15, 8) + +struct scmi_msg_base_attributes_p2a { + uint32_t attributes; +} __packed; + +/* + * BASE_DISCOVER_AGENT + */ +#define SCMI_BASE_AGENT_ID_OWN 0xFFFFFFFF + +struct scmi_msg_base_discover_agent_a2p { + uint32_t agent_id; +} __packed; + +struct scmi_msg_base_discover_agent_p2a { + uint32_t agent_id; + char name[SCMI_SHORT_NAME_MAX_SIZE]; +} __packed; + +/* + * BASE_SET_DEVICE_PERMISSIONS + */ +#define SCMI_BASE_DEVICE_ACCESS_ALLOW BIT(0, UL) + +struct scmi_msg_base_set_device_permissions_a2p { + uint32_t agent_id; + uint32_t device_id; + uint32_t flags; +} __packed; + +/* + * BASE_RESET_AGENT_CONFIGURATION + */ +#define SCMI_BASE_AGENT_PERMISSIONS_RESET BIT(0, UL) + +struct scmi_msg_base_reset_agent_cfg_a2p { + uint32_t agent_id; + uint32_t flags; +} __packed; + +#endif /* XEN_ARCH_ARM_SCI_SCMI_PROTO_H_ */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/arch/arm/firmware/scmi-shmem.c b/xen/arch/arm/firmware/scmi-shmem.c new file mode 100644 index 000000000000..3815c15bed80 --- /dev/null +++ b/xen/arch/arm/firmware/scmi-shmem.c @@ -0,0 +1,172 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * SCI SCMI multi-agent driver, using SMC/HVC shmem as transport. + * + * Oleksii Moisieiev + * Copyright (c) 2025 EPAM Systems + */ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include + +#include "scmi-proto.h" +#include "scmi-shmem.h" + +/* + * Copy data from IO memory space to "real" memory space. + */ +static void __memcpy_fromio(void *to, const volatile void __iomem *from, + size_t count) +{ + while ( count && !IS_ALIGNED((unsigned long)from, 4) ) + { + *(u8 *)to = readb_relaxed(from); + from++; + to++; + count--; + } + + while ( count >= 4 ) + { + *(u32 *)to = readl_relaxed(from); + from += 4; + to += 4; + count -= 4; + } + + while ( count ) + { + *(u8 *)to = readb_relaxed(from); + from++; + to++; + count--; + } +} + +/* + * Copy data from "real" memory space to IO memory space. + */ +static void __memcpy_toio(volatile void __iomem *to, const void *from, + size_t count) +{ + while ( count && !IS_ALIGNED((unsigned long)to, 4) ) + { + writeb_relaxed(*(u8 *)from, to); + from++; + to++; + count--; + } + + while ( count >= 4 ) + { + writel_relaxed(*(u32 *)from, to); + from += 4; + to += 4; + count -= 4; + } + + while ( count ) + { + writeb_relaxed(*(u8 *)from, to); + from++; + to++; + count--; + } +} + +static inline int +shmem_channel_is_free(const volatile struct scmi_shared_mem __iomem *shmem) +{ + return (readl(&shmem->channel_status) & + SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE) ? 0 : -EBUSY; +} + +int shmem_put_message(volatile struct scmi_shared_mem __iomem *shmem, + scmi_msg_header_t *hdr, void *data, int len) +{ + int ret; + + if ( (len + sizeof(shmem->msg_header)) > SCMI_SHMEM_MAPPED_SIZE ) + { + printk(XENLOG_ERR "scmi: Wrong size of smc message. Data is invalid\n"); + return -EINVAL; + } + + ret = shmem_channel_is_free(shmem); + if ( ret ) + return ret; + + writel_relaxed(0x0, &shmem->channel_status); + /* Writing 0x0 right now, but "shmem"_FLAG_INTR_ENABLED can be set */ + writel_relaxed(0x0, &shmem->flags); + writel_relaxed(sizeof(shmem->msg_header) + len, &shmem->length); + writel(pack_scmi_header(hdr), &shmem->msg_header); + + if ( len > 0 && data ) + __memcpy_toio(shmem->msg_payload, data, len); + + return 0; +} + +int shmem_get_response(const volatile struct scmi_shared_mem __iomem *shmem, + scmi_msg_header_t *hdr, void *data, int len) +{ + int recv_len; + int ret; + int pad = sizeof(hdr->status); + + if ( len >= SCMI_SHMEM_MAPPED_SIZE - sizeof(shmem) ) + { + printk(XENLOG_ERR + "scmi: Wrong size of input smc message. Data may be invalid\n"); + return -EINVAL; + } + + ret = shmem_channel_is_free(shmem); + if ( ret ) + return ret; + + recv_len = readl(&shmem->length) - sizeof(shmem->msg_header); + + if ( recv_len < 0 ) + { + printk(XENLOG_ERR + "scmi: Wrong size of smc message. Data may be invalid\n"); + return -EINVAL; + } + + unpack_scmi_header(readl(&shmem->msg_header), hdr); + + hdr->status = readl(&shmem->msg_payload); + recv_len = recv_len > pad ? recv_len - pad : 0; + + ret = scmi_to_xen_errno(hdr->status); + if ( ret ) { + printk(XENLOG_DEBUG "scmi: Error received: %d\n", ret); + return ret; + } + + if ( recv_len > len ) + { + printk(XENLOG_ERR + "scmi: Not enough buffer for message %d, expecting %d\n", + recv_len, len); + return -EINVAL; + } + + if ( recv_len > 0 ) + __memcpy_fromio(data, shmem->msg_payload + pad, recv_len); + + return 0; +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/arch/arm/firmware/scmi-shmem.h b/xen/arch/arm/firmware/scmi-shmem.h new file mode 100644 index 000000000000..f19e90786824 --- /dev/null +++ b/xen/arch/arm/firmware/scmi-shmem.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Arm System Control and Management Interface definitions + * Version 3.0 (DEN0056C) + * Shared Memory based Transport + * + * Copyright (c) 2024 EPAM Systems + */ + +#ifndef XEN_ARCH_ARM_SCI_SCMI_SHMEM_H_ +#define XEN_ARCH_ARM_SCI_SCMI_SHMEM_H_ + +#include + +#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE BIT(0, UL) +#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR BIT(1, UL) + +struct scmi_shared_mem { + uint32_t reserved; + uint32_t channel_status; + uint32_t reserved1[2]; + uint32_t flags; + uint32_t length; + uint32_t msg_header; + uint8_t msg_payload[]; +}; + +#define SCMI_SHMEM_MAPPED_SIZE PAGE_SIZE + +int shmem_put_message(volatile struct scmi_shared_mem __iomem *shmem, + scmi_msg_header_t *hdr, void *data, int len); + +int shmem_get_response(const volatile struct scmi_shared_mem __iomem *shmem, + scmi_msg_header_t *hdr, void *data, int len); +#endif /* XEN_ARCH_ARM_SCI_SCMI_SHMEM_H_ */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/arch/arm/firmware/scmi-smc-multiagent.c b/xen/arch/arm/firmware/scmi-smc-multiagent.c new file mode 100644 index 000000000000..293fb30fa6c5 --- /dev/null +++ b/xen/arch/arm/firmware/scmi-smc-multiagent.c @@ -0,0 +1,856 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * SCI SCMI multi-agent driver, using SMC/HVC shmem as transport. + * + * Oleksii Moisieiev + * Copyright (c) 2025 EPAM Systems + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "scmi-proto.h" +#include "scmi-shmem.h" + +#define SCMI_AGENT_ID_INVALID 0xFF + +static uint8_t __initdata opt_dom0_scmi_agent_id = SCMI_AGENT_ID_INVALID; +integer_param("dom0_scmi_agent_id", opt_dom0_scmi_agent_id); + +#define SCMI_SECONDARY_AGENTS "xen,scmi-secondary-agents" + +#define HYP_CHANNEL 0x0 + + +struct scmi_channel { + uint32_t agent_id; + uint32_t func_id; + domid_t domain_id; + uint64_t paddr; + uint64_t len; + struct scmi_shared_mem __iomem *shmem; + spinlock_t lock; + struct list_head list; +}; + +struct scmi_data { + struct list_head channel_list; + spinlock_t channel_list_lock; + uint32_t func_id; + bool initialized; + uint32_t shmem_phandle; + struct dt_device_node *dt_dev; +}; + +static struct scmi_data scmi_data; + +static int send_smc_message(struct scmi_channel *chan_info, + scmi_msg_header_t *hdr, void *data, int len) +{ + struct arm_smccc_res resp; + int ret; + + ret = shmem_put_message(chan_info->shmem, hdr, data, len); + if ( ret ) + return ret; + + arm_smccc_1_1_smc(chan_info->func_id, 0, 0, 0, 0, 0, 0, 0, &resp); + + if ( resp.a0 ) + return -EOPNOTSUPP; + + return 0; +} + +static int do_smc_xfer(struct scmi_channel *chan_info, scmi_msg_header_t *hdr, + void *tx_data, int tx_size, void *rx_data, int rx_size) +{ + int ret = 0; + + ASSERT(chan_info && chan_info->shmem); + + if ( !hdr ) + return -EINVAL; + + spin_lock(&chan_info->lock); + + printk(XENLOG_DEBUG + "scmi: agent_id = %d msg_id = %x type = %d, proto = %x\n", + chan_info->agent_id, hdr->id, hdr->type, hdr->protocol); + + ret = send_smc_message(chan_info, hdr, tx_data, tx_size); + if ( ret ) + goto clean; + + ret = shmem_get_response(chan_info->shmem, hdr, rx_data, rx_size); + +clean: + printk(XENLOG_DEBUG + "scmi: get smc response agent_id = %d msg_id = %x proto = %x res=%d\n", + chan_info->agent_id, hdr->id, hdr->protocol, ret); + + spin_unlock(&chan_info->lock); + + return ret; +} + +static struct scmi_channel *get_channel_by_id(uint32_t agent_id) +{ + struct scmi_channel *curr; + bool found = false; + + spin_lock(&scmi_data.channel_list_lock); + list_for_each_entry(curr, &scmi_data.channel_list, list) + { + if ( curr->agent_id == agent_id ) + { + found = true; + break; + } + } + + spin_unlock(&scmi_data.channel_list_lock); + if ( found ) + return curr; + + return NULL; +} + +static struct scmi_channel *aquire_scmi_channel(struct domain *d, + uint32_t agent_id) +{ + struct scmi_channel *curr; + struct scmi_channel *ret = ERR_PTR(-ENOENT); + + spin_lock(&scmi_data.channel_list_lock); + list_for_each_entry(curr, &scmi_data.channel_list, list) + { + if ( curr->agent_id == agent_id ) + { + if ( curr->domain_id != DOMID_INVALID ) + { + ret = ERR_PTR(-EEXIST); + break; + } + + curr->domain_id = d->domain_id; + ret = curr; + break; + } + } + + spin_unlock(&scmi_data.channel_list_lock); + + return ret; +} + +static void relinquish_scmi_channel(struct scmi_channel *channel) +{ + ASSERT(channel != NULL); + + spin_lock(&scmi_data.channel_list_lock); + channel->domain_id = DOMID_INVALID; + spin_unlock(&scmi_data.channel_list_lock); +} + +static int map_channel_memory(struct scmi_channel *channel) +{ + ASSERT( channel && channel->paddr ); + channel->shmem = ioremap_nocache(channel->paddr, SCMI_SHMEM_MAPPED_SIZE); + if ( !channel->shmem ) + return -ENOMEM; + + channel->shmem->channel_status = SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE; + printk(XENLOG_DEBUG "scmi: Got shmem %lx after vmap %p\n", channel->paddr, + channel->shmem); + + return 0; +} + +static void unmap_channel_memory(struct scmi_channel *channel) +{ + ASSERT( channel && channel->shmem ); + iounmap(channel->shmem); + channel->shmem = NULL; +} + +static struct scmi_channel *smc_create_channel(uint32_t agent_id, + uint32_t func_id, uint64_t addr) +{ + struct scmi_channel *channel; + + channel = get_channel_by_id(agent_id); + if ( channel ) + return ERR_PTR(EEXIST); + + channel = xmalloc(struct scmi_channel); + if ( !channel ) + return ERR_PTR(ENOMEM); + + spin_lock_init(&channel->lock); + channel->agent_id = agent_id; + channel->func_id = func_id; + channel->domain_id = DOMID_INVALID; + channel->shmem = NULL; + channel->paddr = addr; + list_add_tail(&channel->list, &scmi_data.channel_list); + return channel; +} + +static void free_channel_list(void) +{ + struct scmi_channel *curr, *_curr; + + list_for_each_entry_safe (curr, _curr, &scmi_data.channel_list, list) + { + list_del(&curr->list); + xfree(curr); + } +} + +static int scmi_dt_read_hyp_channel_addr(struct dt_device_node *scmi_node, + u64 *addr, u64 *size) +{ + struct dt_device_node *shmem_node; + const __be32 *prop; + + prop = dt_get_property(scmi_node, "shmem", NULL); + if ( !prop ) + return -EINVAL; + + shmem_node = dt_find_node_by_phandle(be32_to_cpup(prop)); + if ( IS_ERR_OR_NULL(shmem_node) ) + { + printk(XENLOG_ERR + "scmi: Device tree error, can't parse reserved memory %ld\n", + PTR_ERR(shmem_node)); + return PTR_ERR(shmem_node); + } + + return dt_device_get_address(shmem_node, 0, addr, size); +} + +/* + * Handle Dom0 SCMI specific DT nodes + * + * Make a decision on copying SCMI specific nodes into Dom0 device tree. + * For SCMI multi-agent case: + * - shmem nodes will not be copied and generated instead if SCMI + * is enabled for Dom0 + * - scmi node will be copied if SCMI is enabled for Dom0 + */ +static bool scmi_dt_handle_node(struct domain *d, struct dt_device_node *node) +{ + static const struct dt_device_match skip_matches[] __initconst = { + DT_MATCH_COMPATIBLE("arm,scmi-shmem"), + { /* sentinel */ }, + }; + static const struct dt_device_match scmi_matches[] __initconst = { + DT_MATCH_PATH("/firmware/scmi"), + { /* sentinel */ }, + }; + + if ( !scmi_data.initialized ) + return false; + + /* always drop shmem */ + if ( dt_match_node(skip_matches, node) ) + { + dt_dprintk(" Skip scmi shmem\n"); + return true; + } + + /* drop scmi if not enabled */ + if ( dt_match_node(scmi_matches, node) && !sci_domain_is_enabled(d) ) + { + dt_dprintk(" Skip scmi node\n"); + return true; + } + + return false; +} + +/* + * Finalize Dom0 SCMI specific DT nodes + * + * if SCMI is enabled for Dom0: + * - generate shmem node + * - map SCMI shmem MMIO into Dom0 + */ +static int scmi_dt_finalize(struct domain *d, void *fdt) +{ + __be32 reg[GUEST_ROOT_ADDRESS_CELLS + GUEST_ROOT_SIZE_CELLS]; + struct scmi_channel *channel; + int nodeoffset; + __be32 *cells; + __be32 val; + char buf[64]; + int res, rc; + + if ( !sci_domain_is_enabled(d) ) + return 0; + + channel = d->arch.sci_data; + + /* + * Replace "arm,smc-id" with proper value assigned for Dom0 SCMI channel + */ + nodeoffset = fdt_node_offset_by_compatible(fdt, -1, "arm,scmi-smc"); + if ( nodeoffset < 0 ) + return -ENODEV; + + cells = (__be32 *)&val; + dt_set_cell(&cells, 1, channel->func_id); + res = fdt_setprop_inplace(fdt, nodeoffset, "arm,smc-id", &val, sizeof(val)); + if ( res ) + return -EINVAL; + + /* + * All SCMI shmem nodes should be removed from Dom0 DT at this point, so + * the shmem node for Dom0 need to be generated from SCMI channel assigned + * to Dom0. + * The original SCMI shmem node from platform DT is used by Xen SCMI driver + * itself as privileged channel (agent_id=0) to manage other SCMI + * agents (domains). + */ + snprintf(buf, sizeof(buf), "scmi-shmem@%lx", channel->paddr); + + res = fdt_begin_node(fdt, buf); + if ( res ) + return res; + + res = fdt_property_string(fdt, "compatible", "arm,scmi-shmem"); + if ( res ) + return res; + + cells = ®[0]; + + dt_child_set_range(&cells, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS, + channel->paddr, SCMI_SHMEM_MAPPED_SIZE); + + res = fdt_property(fdt, "reg", reg, sizeof(reg)); + if ( res ) + return res; + + res = fdt_property_cell(fdt, "phandle", scmi_data.shmem_phandle); + if ( res ) + return res; + + res = fdt_end_node(fdt); + if ( res ) + return res; + + /* + * Map SCMI shmem into Dom0 here as shmem nodes are excluded from + * generic Dom0 DT processing + */ + res = iomem_permit_access(d, paddr_to_pfn(channel->paddr), + paddr_to_pfn(channel->paddr + + SCMI_SHMEM_MAPPED_SIZE - 1)); + if ( res ) + return res; + + res = map_regions_p2mt(d, gaddr_to_gfn(channel->paddr), + PFN_UP(SCMI_SHMEM_MAPPED_SIZE), + maddr_to_mfn(channel->paddr), p2m_mmio_direct_nc); + if ( res ) + { + rc = iomem_deny_access(d, paddr_to_pfn(channel->paddr), + paddr_to_pfn(channel->paddr + + SCMI_SHMEM_MAPPED_SIZE - 1)); + if ( rc ) + printk(XENLOG_ERR "scmi: Unable to deny iomem access , err = %d\n", + rc); + } + + return res; +} + +static int scmi_assign_device(uint32_t agent_id, uint32_t device_id, + uint32_t flags) +{ + struct scmi_msg_base_set_device_permissions_a2p tx; + struct scmi_channel *channel; + scmi_msg_header_t hdr; + int ret; + + channel = get_channel_by_id(HYP_CHANNEL); + if ( !channel ) + return -EINVAL; + + hdr.id = SCMI_BASE_SET_DEVICE_PERMISSIONS; + hdr.type = 0; + hdr.protocol = SCMI_BASE_PROTOCOL; + + tx.agent_id = agent_id; + tx.device_id = device_id; + tx.flags = flags; + + ret = do_smc_xfer(channel, &hdr, &tx, sizeof(tx), NULL, 0); + if ( ret == -EOPNOTSUPP ) + return 0; + + return ret; +} + +static int scmi_dt_assign_device(struct domain *d, + struct dt_phandle_args *ac_spec) +{ + struct scmi_channel *agent_channel; + uint32_t scmi_device_id = ac_spec->args[0]; + int ret; + + if ( !d->arch.sci_data ) + return 0; + + /* The access-controllers is specified for DT dev, but it's not a SCMI */ + if ( ac_spec->np != scmi_data.dt_dev ) + return 0; + + agent_channel = d->arch.sci_data; + + spin_lock(&agent_channel->lock); + + ret = scmi_assign_device(agent_channel->agent_id, scmi_device_id, + SCMI_BASE_DEVICE_ACCESS_ALLOW); + if ( ret ) + { + printk(XENLOG_ERR + "scmi: could not assign dev for %pd agent:%d dev_id:%u (%d)", + d, agent_channel->agent_id, scmi_device_id, ret); + } + + spin_unlock(&agent_channel->lock); + return ret; +} + +static __init int collect_agents(struct dt_device_node *scmi_node) +{ + const struct dt_device_node *chosen_node; + const __be32 *prop; + u32 len, i; + + chosen_node = dt_find_node_by_path("/chosen"); + if ( !chosen_node ) + { + printk(XENLOG_ERR "scmi: chosen node not found\n"); + return -ENOENT; + } + + prop = dt_get_property(chosen_node, SCMI_SECONDARY_AGENTS, &len); + if ( !prop ) + { + printk(XENLOG_WARNING "scmi: No %s property found\n", + SCMI_SECONDARY_AGENTS); + return -ENODEV; + } + + if ( len % (3 * sizeof(u32)) ) + { + printk(XENLOG_ERR "scmi: Invalid length of %s property: %d\n", + SCMI_SECONDARY_AGENTS, len); + return -EINVAL; + } + + for ( i = 0 ; i < len / (3 * sizeof(u32)) ; i++ ) + { + u32 agent_id = be32_to_cpu(*prop++); + u32 smc_id = be32_to_cpu(*prop++); + u32 shmem_phandle = be32_to_cpu(*prop++); + struct dt_device_node *node = dt_find_node_by_phandle(shmem_phandle); + u64 addr, size; + int ret; + + if ( !node ) + { + printk(XENLOG_ERR"scmi: Could not find shmem node for agent %d\n", + agent_id); + return -EINVAL; + } + + ret = dt_device_get_address(node, 0, &addr, &size); + if ( ret ) + { + printk(XENLOG_ERR + "scmi: Could not read shmem address for agent %d: %d", + agent_id, ret); + return ret; + } + + if ( !IS_ALIGNED(size, SCMI_SHMEM_MAPPED_SIZE) ) + { + printk(XENLOG_ERR "scmi: shmem memory is not aligned\n"); + return -EINVAL; + } + + ret = PTR_RET(smc_create_channel(agent_id, smc_id, addr)); + if ( ret ) + { + printk(XENLOG_ERR "scmi: Could not create channel for agent %d: %d", + agent_id, ret); + return ret; + } + + printk(XENLOG_DEBUG "scmi: Agent %d SMC %X addr %lx\n", agent_id, + smc_id, addr); + } + + return 0; +} + +static int scmi_domain_init(struct domain *d, + struct xen_domctl_createdomain *config) +{ + struct scmi_channel *channel; + int ret; + + if ( !scmi_data.initialized ) + return 0; + + /* + * Special case for Dom0 - the SCMI support is enabled basing on + * "dom0_sci_agent_id" Xen command line parameter + */ + if ( is_hardware_domain(d) ) { + if ( opt_dom0_scmi_agent_id != SCMI_AGENT_ID_INVALID ) + { + config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA; + config->arch.arm_sci_agent_id = opt_dom0_scmi_agent_id; + } else + config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_NONE; + } + + if ( config->arch.arm_sci_type == XEN_DOMCTL_CONFIG_ARM_SCI_NONE ) + return 0; + + channel = aquire_scmi_channel(d, config->arch.arm_sci_agent_id); + if ( IS_ERR(channel) ) + { + printk(XENLOG_ERR"scmi: Failed to acquire SCMI channel for agent_id %u: %ld\n", + config->arch.arm_sci_agent_id, PTR_ERR(channel)); + return PTR_ERR(channel); + } + + printk(XENLOG_INFO"scmi: Acquire channel id = 0x%x, domain_id = %d paddr = 0x%lx\n", + channel->agent_id, channel->domain_id, channel->paddr); + + /* + * Dom0 (if present) needs to have an access to the guest memory range + * to satisfy iomem_access_permitted() check in XEN_DOMCTL_iomem_permission + * domctl. + */ + if ( hardware_domain && !is_hardware_domain(d) ) + { + ret = iomem_permit_access(hardware_domain, paddr_to_pfn(channel->paddr), + paddr_to_pfn(channel->paddr + PAGE_SIZE - 1)); + if ( ret ) + goto error; + } + + d->arch.sci_data = channel; + d->arch.sci_enabled = true; + + return 0; + +error: + relinquish_scmi_channel(channel); + return ret; +} + +int scmi_domain_sanitise_config(struct xen_domctl_createdomain *config) +{ + if ( config->arch.arm_sci_type != XEN_DOMCTL_CONFIG_ARM_SCI_NONE && + config->arch.arm_sci_type != XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA ) + { + dprintk(XENLOG_INFO, "scmi: Unsupported ARM_SCI type\n"); + return -EINVAL; + } + else if ( config->arch.arm_sci_type == + XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA && + config->arch.arm_sci_agent_id == 0 ) + { + dprintk(XENLOG_INFO, + "scmi: A zero ARM SCMI agent_id is not supported\n"); + return -EINVAL; + } + + return 0; +} + +static int scmi_relinquish_resources(struct domain *d) +{ + int ret; + struct scmi_channel *channel, *agent_channel; + scmi_msg_header_t hdr; + struct scmi_msg_base_reset_agent_cfg_a2p tx; + + if ( !d->arch.sci_data ) + return 0; + + agent_channel = d->arch.sci_data; + + spin_lock(&agent_channel->lock); + tx.agent_id = agent_channel->agent_id; + spin_unlock(&agent_channel->lock); + + channel = get_channel_by_id(HYP_CHANNEL); + if ( !channel ) + { + printk(XENLOG_ERR + "scmi: Unable to get Hypervisor scmi channel for domain %d\n", + d->domain_id); + return -EINVAL; + } + + hdr.id = SCMI_BASE_RESET_AGENT_CONFIGURATION; + hdr.type = 0; + hdr.protocol = SCMI_BASE_PROTOCOL; + + tx.flags = 0; + + ret = do_smc_xfer(channel, &hdr, &tx, sizeof(tx), NULL, 0); + if ( ret == -EOPNOTSUPP ) + return 0; + + return ret; +} + +static void scmi_domain_destroy(struct domain *d) +{ + struct scmi_channel *channel; + + if ( !d->arch.sci_data ) + return; + + channel = d->arch.sci_data; + spin_lock(&channel->lock); + + relinquish_scmi_channel(channel); + printk(XENLOG_DEBUG "scmi: Free domain %d\n", d->domain_id); + + d->arch.sci_data = NULL; + d->arch.sci_enabled = true; + + spin_unlock(&channel->lock); +} + +static bool scmi_handle_call(struct cpu_user_regs *regs) +{ + uint32_t fid = (uint32_t)get_user_reg(regs, 0); + struct scmi_channel *agent_channel; + struct domain *d = current->domain; + struct arm_smccc_res resp; + bool res = false; + + if ( !sci_domain_is_enabled(d) ) + return false; + + agent_channel = d->arch.sci_data; + spin_lock(&agent_channel->lock); + + if ( agent_channel->func_id != fid ) + { + res = false; + goto unlock; + } + + arm_smccc_1_1_smc(fid, + get_user_reg(regs, 1), + get_user_reg(regs, 2), + get_user_reg(regs, 3), + get_user_reg(regs, 4), + get_user_reg(regs, 5), + get_user_reg(regs, 6), + get_user_reg(regs, 7), + &resp); + + set_user_reg(regs, 0, resp.a0); + set_user_reg(regs, 1, resp.a1); + set_user_reg(regs, 2, resp.a2); + set_user_reg(regs, 3, resp.a3); + res = true; +unlock: + spin_unlock(&agent_channel->lock); + + return res; +} + +static const struct sci_mediator_ops scmi_ops = { + .domain_init = scmi_domain_init, + .domain_destroy = scmi_domain_destroy, + .relinquish_resources = scmi_relinquish_resources, + .handle_call = scmi_handle_call, + .dom0_dt_handle_node = scmi_dt_handle_node, + .dom0_dt_finalize = scmi_dt_finalize, + .domain_sanitise_config = scmi_domain_sanitise_config, + .assign_dt_device = scmi_dt_assign_device, +}; + +static int __init scmi_check_smccc_ver(void) +{ + if ( smccc_ver < ARM_SMCCC_VERSION_1_1 ) + { + printk(XENLOG_WARNING + "scmi: No SMCCC 1.1 support, SCMI calls forwarding disabled\n"); + return -ENOSYS; + } + + return 0; +} + +static __init int scmi_probe(struct dt_device_node *scmi_node, const void *data) +{ + u64 addr, size; + int ret, i; + struct scmi_channel *channel, *agent_channel; + int n_agents; + scmi_msg_header_t hdr; + struct scmi_msg_base_attributes_p2a rx; + + ASSERT(scmi_node != NULL); + + INIT_LIST_HEAD(&scmi_data.channel_list); + spin_lock_init(&scmi_data.channel_list_lock); + + if ( !acpi_disabled ) + { + printk(XENLOG_WARNING "scmi: is not supported when using ACPI\n"); + return -EINVAL; + } + + ret = scmi_check_smccc_ver(); + if ( ret ) + return ret; + + if ( !dt_property_read_u32(scmi_node, "arm,smc-id", &scmi_data.func_id) ) + { + printk(XENLOG_ERR "scmi: unable to read smc-id from DT\n"); + return -ENOENT; + } + + /* save shmem phandle and re-use it fro Dom0 DT shmem node */ + if ( !dt_property_read_u32(scmi_node, "shmem", &scmi_data.shmem_phandle) ) + { + printk(XENLOG_ERR "scmi: unable to read shmem phandle from DT\n"); + return -ENOENT; + } + + ret = scmi_dt_read_hyp_channel_addr(scmi_node, &addr, &size); + if ( IS_ERR_VALUE(ret) ) + return -ENOENT; + + if ( !IS_ALIGNED(size, SCMI_SHMEM_MAPPED_SIZE) ) + { + printk(XENLOG_ERR "scmi: shmem memory is not aligned\n"); + return -EINVAL; + } + + scmi_data.dt_dev = scmi_node; + + channel = smc_create_channel(HYP_CHANNEL, scmi_data.func_id, addr); + if ( IS_ERR(channel) ) + goto out; + + ret = map_channel_memory(channel); + if ( ret ) + goto out; + + channel->domain_id = DOMID_XEN; + + hdr.id = SCMI_BASE_PROTOCOL_ATTIBUTES; + hdr.type = 0; + hdr.protocol = SCMI_BASE_PROTOCOL; + + ret = do_smc_xfer(channel, &hdr, NULL, 0, &rx, sizeof(rx)); + if ( ret ) + goto error; + + n_agents = SCMI_FIELD_GET(SCMI_BASE_ATTR_NUM_AGENT, rx.attributes); + printk(XENLOG_DEBUG "scmi: Got agent count %d\n", n_agents); + + ret = collect_agents(scmi_node); + if ( ret ) + goto error; + + i = 1; + + list_for_each_entry(agent_channel, &scmi_data.channel_list, list) + { + struct scmi_msg_base_discover_agent_p2a da_rx; + struct scmi_msg_base_discover_agent_a2p da_tx; + + ret = map_channel_memory(agent_channel); + if ( ret ) + goto error; + + hdr.id = SCMI_BASE_DISCOVER_AGENT; + hdr.type = 0; + hdr.protocol = SCMI_BASE_PROTOCOL; + + da_tx.agent_id = agent_channel->agent_id; + + ret = do_smc_xfer(agent_channel, &hdr, &da_tx, + sizeof(da_tx), &da_rx, sizeof(da_rx)); + if ( agent_channel->domain_id != DOMID_XEN ) + unmap_channel_memory(agent_channel); + if ( ret ) + goto error; + + printk(XENLOG_DEBUG "id=0x%x name=%s\n", + da_rx.agent_id, da_rx.name); + + agent_channel->agent_id = da_rx.agent_id; + + if ( i > n_agents ) + break; + + i++; + } + + ret = sci_register(&scmi_ops); + if (ret) { + printk(XENLOG_ERR "SCMI: mediator already registered (ret = %d)\n", + ret); + return ret; + } + + scmi_data.initialized = true; + goto out; + +error: + unmap_channel_memory(channel); + free_channel_list(); +out: + return ret; +} + +static const struct dt_device_match scmi_smc_match[] __initconst = { + DT_MATCH_COMPATIBLE("arm,scmi-smc"), + { /* sentinel */ }, +}; + +DT_DEVICE_START(gicv3, "SCMI SMC MEDIATOR", DEVICE_ARM_SCI) + .dt_match = scmi_smc_match, + .init = scmi_probe, +DT_DEVICE_END + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index 095b1a23e30c..30e46de6d7a0 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -329,6 +329,7 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); #define XEN_DOMCTL_CONFIG_ARM_SCI_NONE 0 #define XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC 1 +#define XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA 2 struct xen_arch_domainconfig { /* IN/OUT */ @@ -355,6 +356,8 @@ struct xen_arch_domainconfig { uint32_t clock_frequency; /* IN */ uint8_t arm_sci_type; + /* IN */ + uint8_t arm_sci_agent_id; }; #endif /* __XEN__ || __XEN_TOOLS__ */ From patchwork Tue Mar 11 11:16:16 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Grygorii Strashko X-Patchwork-Id: 14011519 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 58D07C282EC for ; Tue, 11 Mar 2025 11:17:07 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.907865.1315085 (Exim 4.92) (envelope-from ) id 1trxbL-0007fU-AZ; Tue, 11 Mar 2025 11:16:47 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 907865.1315085; Tue, 11 Mar 2025 11:16:47 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1trxbL-0007fN-7D; Tue, 11 Mar 2025 11:16:47 +0000 Received: by outflank-mailman (input) for mailman id 907865; Tue, 11 Mar 2025 11:16:46 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1trxbK-0006Sq-6k for xen-devel@lists.xenproject.org; Tue, 11 Mar 2025 11:16:46 +0000 Received: from mail-lf1-x135.google.com (mail-lf1-x135.google.com [2a00:1450:4864:20::135]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 51188313-fe6a-11ef-9ab9-95dc52dad729; Tue, 11 Mar 2025 12:16:45 +0100 (CET) Received: by mail-lf1-x135.google.com with SMTP id 2adb3069b0e04-5495078cd59so6077124e87.1 for ; Tue, 11 Mar 2025 04:16:45 -0700 (PDT) Received: from epuakyiw0a98.kyiv.epam.com (ll-74.141.223.85.sovam.net.ua. [85.223.141.74]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5498ae45fa8sm1755729e87.52.2025.03.11.04.16.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Mar 2025 04:16:43 -0700 (PDT) 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: 51188313-fe6a-11ef-9ab9-95dc52dad729 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741691804; x=1742296604; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=DOtEpGDdd8lHC2aLHRNxzl9ISoh4BrNCKPiIInwVNAg=; b=jBRiO0kkqdvSA4yK0nouc/gtILNiwORc3ZNvygEFl+N2eeoHHQ6ny5l5sojXR1AXZt TUOjyIhuR5kDyACqy1jfNX2OoneZof1iT4adTxMJMCGkxS/26dSkrM6Wvi3Wrk4OmRYr f8+QrnPqSRcU0fBrLXwS7ipgnc86CiiwbH6W9FdryrWZxcoViRwrfLuRjk32eZmtxBcg d2D/sQ3BZj6CjbcYZIbTUob4RcDExj7TBnvd6bOSb4O4ke1cM40gan+ncHRBR+ixdkp3 EDOQKhDhOTZzqL1Ks2f94HHBAxhK6W4+T6K0wV/hEgrpk8ZjpPbLm6V5E4ZnQD8xqzS1 MweQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741691804; x=1742296604; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=DOtEpGDdd8lHC2aLHRNxzl9ISoh4BrNCKPiIInwVNAg=; b=LNajOXVRtcJc8H/bKfy6vaSv6A/Fp6R28efp6Cyzgr8X50EUdp3N8qySJuazyIX1ho MG8SqbFmbJ9w4jj4P+T8aNXsRTxPKXtsrRrOGAW2R9GweAo7RhhQuFG4Zkpch70+vCsy jQ4/1KnVzUSL1RmT4p77Z/xRCE+OFpz/RDM68N8BuNBcaFnJbgeANwAagtBWmjBbC85y c5EoFMrgHu5piNsBvRz8G6Gqkt7m3AWmTyfMYskW8vwInYOZingQCPkGK7k0DGLEixAI /rG2YKVKlujD4XqIb0S0H69t8t0SkyvTUU2fRYjhcGL7gWNGQvlxIDajipADQeswmEcJ l7Vg== X-Gm-Message-State: AOJu0Yz1AR/bpzv4nspbO7FM3gHw0IeRGpfANnklenLm0xsF6Gdwq+ca /GV2bNRqfv5eqWwoTaRSKtjNUwSdKxfhSfXpK/Fv3Klyr4WapMlFyqYdnQ== X-Gm-Gg: ASbGncsbBGMUA9DEASmHL/6vv4ijQMv1rm4T7xhQUEDkD5GpRS8SD8v67D45OdecdVj 60UuJg+ZgojvP9IwdPVASHW4l4AwvW9/rHgwhdhPFnvCUaJx+j2IApUGgmGUKJSiNFKqwE0BaMg XLtvm3bfToyJTcW66ztkTCsqF5AwWNCNwq3J3imiJ+2S/uKxOvULNZJXUlIQ7KxEqNllVAFqlnN n9GBI+aosxsM59aPB2uN+qSWkfL04dEf3fbanuV2y6xHjFOsnyA1LRxa0opjmXG1I3nZWMo6erD dZ+ToUU80PZEXd+cDPnIZhD9QeofzIZadfhmNVZ9iJcl4bPj2vyJYx4xc3fuYUpLXgbaZ6CcHef gRJpJrsX7Y+2aCW8ubUVk3InR50E= X-Google-Smtp-Source: AGHT+IGw121SvpsZ35jLD8nCjjL/pIbEqsB+Js6bNwH38TaKrgmFssk+9nrfBp83LHpRtNi4TrBygQ== X-Received: by 2002:a05:6512:3e01:b0:549:8f47:e67d with SMTP id 2adb3069b0e04-549abae7180mr1223991e87.34.1741691804231; Tue, 11 Mar 2025 04:16:44 -0700 (PDT) From: Grygorii Strashko X-Google-Original-From: Grygorii Strashko To: xen-devel@lists.xenproject.org Cc: Stefano Stabellini , Julien Grall , Andrew Cooper , Michal Orzel , "Roger Pau Monne" , Jan Beulich , Anthony PERARD , Volodymyr Babchuk , Oleksii Moisieiev , Bertrand Marquis , Juergen Gross , Volodymyr Babchuk Subject: [RFC PATCH v3 5/7] libs: libxenhypfs - handle blob properties Date: Tue, 11 Mar 2025 13:16:16 +0200 Message-Id: <20250311111618.1850927-6-grygorii_strashko@epam.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250311111618.1850927-1-grygorii_strashko@epam.com> References: <20250311111618.1850927-1-grygorii_strashko@epam.com> MIME-Version: 1.0 From: Oleksii Moisieiev libxenhypfs will return blob properties as is. This output can be used to retrieve information from the hypfs. Caller is responsible for parsing property value. Signed-off-by: Oleksii Moisieiev Reviewed-by: Volodymyr Babchuk --- tools/libs/hypfs/core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/libs/hypfs/core.c b/tools/libs/hypfs/core.c index 52b30db8d777..d09bba7d8c86 100644 --- a/tools/libs/hypfs/core.c +++ b/tools/libs/hypfs/core.c @@ -307,8 +307,6 @@ char *xenhypfs_read(xenhypfs_handle *fshdl, const char *path) errno = EISDIR; break; case xenhypfs_type_blob: - errno = EDOM; - break; case xenhypfs_type_string: ret_buf = buf; buf = NULL; From patchwork Tue Mar 11 11:16:17 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Grygorii Strashko X-Patchwork-Id: 14011624 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id B167BC282EC for ; Tue, 11 Mar 2025 11:56:39 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.907961.1315155 (Exim 4.92) (envelope-from ) id 1tryDn-0000nK-0q; Tue, 11 Mar 2025 11:56:31 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 907961.1315155; Tue, 11 Mar 2025 11:56:30 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tryDm-0000nD-U2; Tue, 11 Mar 2025 11:56:30 +0000 Received: by outflank-mailman (input) for mailman id 907961; Tue, 11 Mar 2025 11:56:30 +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 1trxbS-00061U-VN for xen-devel@lists.xenproject.org; Tue, 11 Mar 2025 11:16:54 +0000 Received: from mail-lf1-x12c.google.com (mail-lf1-x12c.google.com [2a00:1450:4864:20::12c]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 55919bee-fe6a-11ef-9898-31a8f345e629; Tue, 11 Mar 2025 12:16:52 +0100 (CET) Received: by mail-lf1-x12c.google.com with SMTP id 2adb3069b0e04-549967c72bcso3886836e87.3 for ; Tue, 11 Mar 2025 04:16:52 -0700 (PDT) Received: from epuakyiw0a98.kyiv.epam.com (ll-74.141.223.85.sovam.net.ua. [85.223.141.74]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5498ae45fa8sm1755729e87.52.2025.03.11.04.16.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Mar 2025 04:16:46 -0700 (PDT) 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: 55919bee-fe6a-11ef-9898-31a8f345e629 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741691812; x=1742296612; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=/wR0JYxxte1bhZ8sh6yCrPXhqI+ZP9qFcPRuW8qo1VM=; b=VRIxBeqnnSnOMqrsVvtW87EAOkAaj8ai0xFDS3Hez5Z01U6CENTNVfCIus4YXyQOJf sRPDygVn/LO+a38q6tab9l5W99RY1f5BamezobjjIVJ4Pnlsqr8mWOHp7nJWR/64C9cr PNGOH6Q94RzZfHoFL1mdbbEuTzmyYygmmkPQAWtr5bFKfSoXtLCG21G8p+ZXSrzsqAHU CtnrYjsVa8wAOp+ADXrgNxLVe2NAKHVITL+//wWT1z0q9lI1z+5awIuDr9zyCP4aXufQ Ex/PMgP5+E6yIFkpc53K/JW/QBu/QrTpZBpE1vmFptRVRtDiTAgnIvHH4j+SIHOx8Rsq W6xw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741691812; x=1742296612; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/wR0JYxxte1bhZ8sh6yCrPXhqI+ZP9qFcPRuW8qo1VM=; b=RDkliEj7AOjan9O/ARRtlk7bkTklsbPxlmEEwQoSYg7Dlhtpom9Uv3wFpq7uLA3OIa Fl5VlEI38y13yDIiJHFiXZ9et0ROudchtnDbIVIzBArdp9dbh807mFDifh039R3lu12/ VvFTtPtJQgpmIbVDs+dT534J0HwzHYRlL0l7lKpITGKYWgTU1+UzaRt5yKlD6t7o/76I rscqwRotdhZzHsUi0WOrhVrZNmPXHkH9HVH0MxMEqSN/8znTfO/ZTF8DOZ3+Xu8dARZ2 miq9navycPVbiPHWcK9px8l45zYTgnhW0MrcxCEDg77r1fPdMAlVJzYOdSyFotHHN6qm uvVg== X-Gm-Message-State: AOJu0YxnKcypI23fRi9gt2y7zd8vtSYOCBDQ6BrkhAKp1P7WpxPyadB0 aLU1LfNx0AAf31P8pvo/Q7aGGv1hbM/uGKaSI8eREgrKm5dC/vpQOM9eSQ== X-Gm-Gg: ASbGnctVCO1RFCpTdz+bERLs+LOOXfxp4QSymzpjBwvw1GGqQUHaTyt7DCBbieiE1cl JwcoKhL7xe9La6tcEj1ksFFKnKdcLoDuV5vjZ+bByJvkOmhCxAxEJ5kGrRumwR8CtKdmXKs1ZN1 4xRaSo8gyuFIOAJA4rZtM8lr3B9uvdiK4tCW8qz5cShZ3GtLv8o1DXYAppmQ+raYKros1WBfzDB IAv97IIn6NeV0yaqlLBLrxjOt2b4lw7VWSuFWx1HulffdNwCzj3+FhXGl1LC4PVVFe241OecKhy Lv7pNY1xkn7TBzTpHXqybr/xM8wmGofu2uFcnBXdFj0UdD1kFW73QCoHO7GJImFiFKdfy30oK6n yiDQH3JAaRyEy2sdPO8zGmhppwhJVG9ju/jraLw== X-Google-Smtp-Source: AGHT+IG26J7NKqoiAtVdI7Uj/LA73Tb1+MkPu25XYvQn8u3Jxdn5WZsSviRv1ozk/kK+Fu6pEBCesQ== X-Received: by 2002:a05:6512:b14:b0:545:c89:2bc9 with SMTP id 2adb3069b0e04-549910cb4a9mr6523148e87.43.1741691807076; Tue, 11 Mar 2025 04:16:47 -0700 (PDT) From: Grygorii Strashko X-Google-Original-From: Grygorii Strashko To: xen-devel@lists.xenproject.org Cc: Stefano Stabellini , Julien Grall , Andrew Cooper , Michal Orzel , "Roger Pau Monne" , Jan Beulich , Anthony PERARD , Volodymyr Babchuk , Oleksii Moisieiev , Bertrand Marquis , Juergen Gross Subject: [RFC PATCH v3 6/7] xen/arm: Export host device-tree to hypfs Date: Tue, 11 Mar 2025 13:16:17 +0200 Message-Id: <20250311111618.1850927-7-grygorii_strashko@epam.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250311111618.1850927-1-grygorii_strashko@epam.com> References: <20250311111618.1850927-1-grygorii_strashko@epam.com> MIME-Version: 1.0 From: Oleksii Moisieiev If enabled, host device-tree will be exported to hypfs and can be accessed through /devicetree path. Exported device-tree has the same format, as the device-tree exported to the sysfs by the Linux kernel. This is useful when XEN toolstack needs an access to the host device-tree. Signed-off-by: Oleksii Moisieiev --- xen/arch/arm/Kconfig | 16 ++++++++++++++++ xen/arch/arm/Makefile | 1 + xen/arch/arm/host_dtb_export.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 xen/arch/arm/host_dtb_export.c diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig index a26d3e11827c..fa51244e2706 100644 --- a/xen/arch/arm/Kconfig +++ b/xen/arch/arm/Kconfig @@ -125,6 +125,22 @@ config DOM0LESS_BOOT Xen boot without the need of a control domain (Dom0), which could be present anyway. +config HOST_DTB_EXPORT + bool "Export host device tree to hypfs if enabled" + depends on ARM && HYPFS && !ACPI + help + + Export host device-tree to hypfs so toolstack can have an access for the + host device tree from Dom0. If you unsure say N. + +config HOST_DTB_MAX_SIZE + int "Max host dtb export size" + depends on HOST_DTB_EXPORT + default 8192 + help + + Maximum size of the host device-tree exported to hypfs. + config GICV3 bool "GICv3 driver" depends on !NEW_VGIC diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile index 43ab5e8f2550..1518592deb64 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_DOM0LESS_BOOT) += dom0less-build.init.o obj-y += domain.o obj-y += domain_build.init.o obj-y += domctl.o +obj-$(CONFIG_HOST_DTB_EXPORT) += host_dtb_export.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-y += efi/ obj-y += gic.o diff --git a/xen/arch/arm/host_dtb_export.c b/xen/arch/arm/host_dtb_export.c new file mode 100644 index 000000000000..c9beb2803883 --- /dev/null +++ b/xen/arch/arm/host_dtb_export.c @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Export host FDT to the hypfs + * + * Copyright (C) 2024 EPAM Systems + */ + +#include +#include +#include +#include + +static HYPFS_VARSIZE_INIT(dt_prop, XEN_HYPFS_TYPE_BLOB, + "devicetree", CONFIG_HOST_DTB_MAX_SIZE, + &hypfs_leaf_ro_funcs); + +static int __init host_dtb_export_init(void) +{ + ASSERT(dt_host && (dt_host->sibling == NULL)); + + dt_prop.u.content = device_tree_flattened; + dt_prop.e.size = fdt_totalsize(device_tree_flattened); + hypfs_add_leaf(&hypfs_root, &dt_prop, true); + + return 0; +} + +__initcall(host_dtb_export_init); From patchwork Tue Mar 11 11:16:18 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Grygorii Strashko X-Patchwork-Id: 14011623 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 4220CC282EC for ; Tue, 11 Mar 2025 11:56:36 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.907957.1315144 (Exim 4.92) (envelope-from ) id 1tryDf-0000Nu-Ls; Tue, 11 Mar 2025 11:56:23 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 907957.1315144; Tue, 11 Mar 2025 11:56:23 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tryDf-0000Nn-J5; Tue, 11 Mar 2025 11:56:23 +0000 Received: by outflank-mailman (input) for mailman id 907957; Tue, 11 Mar 2025 11:56:22 +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 1trxbR-00061U-95 for xen-devel@lists.xenproject.org; Tue, 11 Mar 2025 11:16:53 +0000 Received: from mail-lj1-x22f.google.com (mail-lj1-x22f.google.com [2a00:1450:4864:20::22f]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 54932f69-fe6a-11ef-9898-31a8f345e629; Tue, 11 Mar 2025 12:16:51 +0100 (CET) Received: by mail-lj1-x22f.google.com with SMTP id 38308e7fff4ca-30762598511so57568661fa.0 for ; Tue, 11 Mar 2025 04:16:51 -0700 (PDT) Received: from epuakyiw0a98.kyiv.epam.com (ll-74.141.223.85.sovam.net.ua. [85.223.141.74]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5498ae45fa8sm1755729e87.52.2025.03.11.04.16.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Mar 2025 04:16:49 -0700 (PDT) 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: 54932f69-fe6a-11ef-9898-31a8f345e629 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741691810; x=1742296610; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=B96UdKByw6q/7v0qR414AXSgvWpTAQ49fpaibtFfFYs=; b=Ld1T7HdYse4bHSpwXfIacLy+h+X30k1aUUxatCAwFgiyyuytBBPg6eyq/zIyEOTQFG WItagRCAkjfCncq8gW9conTf/rXS6Vf12f0gn32Yrzownf6ydfYiJJlEgsuthvrnAtL/ 4mf8Osru/mTy+y5jsqc8rG4rR+qlfoz5tx+vAxfVFBsmY9Y5yEHOkl24K/HWOW7sst74 /Iie6R9C2PVJwybp+At/+JjUHyCzM6RBAtcL1pvf/D//eNCU6EwuprbRuqxHOCfLHFbd nnMztfZd03jaYBixZYiQLxjUYl3hWjGG+qyfTtWW86hEKphWMWkz1JHfTBvKEjnG+Ilh yhbw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741691810; x=1742296610; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=B96UdKByw6q/7v0qR414AXSgvWpTAQ49fpaibtFfFYs=; b=nhWEBfMEnfV+deqhuWsJZ5VLawTamT6ohSqrxRznQWpLHZU2RoAAz0yGvrC+KHr+9F F3MIRgurKN1pmq5QrO+S8U8dXGXa1Dy/F2/FyS75UEkyr0JTYIZ9KB3UGeJVNqUkXDYa rf/BKQUmwmz2h0vLzBd3DzuVbCJ23G+m4wzidmIt6vxyLh0h84e58AqER1lHRWheCJmE 4nbwS3I/UHyrnXBYwNpV+iBPb/9aht1mtBYS94h2S4syDFyPRGWbhBvfVQtqS8zNZBP2 mtDdcv5UsehWAxKjFMw5XjgfUZZkJ/idoKFh+phQEu9xq+lzJI5wPuqGDdUei96zXje4 9lcA== X-Gm-Message-State: AOJu0YzFSgtWZ8PNrLzJQEhlSLeiuFi3zD2VnlC5RX78vvogKVjWFohZ OvaEQpvNgJGt49T3kasWCwdcIengbnTnFH2oEI03eE1IPcX9kH0drIx1QQ== X-Gm-Gg: ASbGncsPv6kte7hD1Kp9g4Tx/4V3vRQYslXLqPno8klrzC7N8glS4WY2+as738UulcR rBLkVeMVL/+65KZIE0R/BNHwpzhjL3gXfdL7akYW+Q9NHKZ1xmCIMHEakemCEIvJB1klCCxlgge ZkzAuykriFRV5ssOQ/nVMnGEhUCsk6zWQgkh6NykwnrL0l3JxPvpgdW5GVtePvo8AQde4Te0w7N evamUpqROGaBuOubLy6ewhH/PF5/tdo3YwugVyjx8ZTyulEUtsr4wvZ6WRoNTboURx9D0X7H7tr nRXmlVbP08mavvW6/cmOQTBal8BX7K5ODSYFYyhhDXF0XfHcK1D75NToJg2YXn3L4FSt0CiPTsG nFZHdomZp0rKM9nfxaTRDilrtuVE= X-Google-Smtp-Source: AGHT+IF64v2hXGQ00z9GVEJ8U68hv2KGBZFKEJQrCkpVVAWcuKQkSvBRVsWQkqHjxbSg/SHD3m9UlA== X-Received: by 2002:a05:6512:b14:b0:544:11cf:10c1 with SMTP id 2adb3069b0e04-54990e641efmr6135062e87.30.1741691809824; Tue, 11 Mar 2025 04:16:49 -0700 (PDT) From: Grygorii Strashko X-Google-Original-From: Grygorii Strashko To: xen-devel@lists.xenproject.org Cc: Stefano Stabellini , Julien Grall , Andrew Cooper , Michal Orzel , "Roger Pau Monne" , Jan Beulich , Anthony PERARD , Volodymyr Babchuk , Oleksii Moisieiev , Bertrand Marquis , Juergen Gross , Grygorii Strashko Subject: [RFC PATCH v3 7/7] xen/arm: scmi: generate scmi dt node for DomUs Date: Tue, 11 Mar 2025 13:16:18 +0200 Message-Id: <20250311111618.1850927-8-grygorii_strashko@epam.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250311111618.1850927-1-grygorii_strashko@epam.com> References: <20250311111618.1850927-1-grygorii_strashko@epam.com> MIME-Version: 1.0 From: Oleksii Moisieiev This feature introduces SCMI support for DomU domains with partial SCMI DT node generation. During domain creation the following prerequisites are expected: - SCMI node template in partial device-tree, which should contain all subnodes used by DomU: / { firmware { scmi { scmi_reset: protocol@19 { \#reset-cells = <1>; }; scmi_clk: protocol@14 { \#clock-cells = <1>; }; scmi_pinctrl: protocol@19 { sdio_mux: mux { }; mux1: mux1 { }; }; }; }; passthrough { sdio { pinctrl-0 = <&sdio_mux>; resets = <&scmi_reset 0x1>; clocks = <&scmi_clk 0x1>; }; dev1 { resets = <&scmi_reset 2>; pinctrl-0 = <&mux1>; }; }; }; - properly defined "arm_sci" property in domain xl.cfg: arm_sci = "type=scmi_smc_multiagent,agent_id=2" - Platform/Xen DT exposed to Dom0 through Xen hypfs. The Xen toolstack: - obtains from Xen information about phys address of the SCMI shmem and SMC/HVC id used by specified SCMI agent_id (domctl XEN_DOMCTL_get_sci_info) - creates the SCMI shmem node in domain DT using predefined guest MMIO mappings and DT phandle GUEST_SCI_SHMEM_BASE xen_mk_ullong(0x22001000) GUEST_SCI_SHMEM_SIZE xen_mk_ullong(0x01000) GUEST_PHANDLE_SCMI (GUEST_PHANDLE_IOMMU + 1) - creates SCMI node in domain DT with: - "shmem" phandle sets to GUEST_PHANDLE_SCMI - "arm,smc-id" sets to SMC/HVC id obtained from Xen - parses partial device tree and creates corresponding SCMI subnodes in domain DT. All SCMI subnodes properties are copied from Xen DT except phandles, which are taken from partial DT. - maps the SCMI shmem into DomU GUEST_SCI_SHMEM_BASE address. Signed-off-by: Oleksii Moisieiev Signed-off-by: Grygorii Strashko --- tools/include/xenctrl.h | 3 + tools/libs/ctrl/xc_domain.c | 18 ++ tools/libs/light/libxl_arm.c | 294 +++++++++++++++++++- tools/libs/light/libxl_create.c | 12 + tools/libs/light/libxl_internal.h | 3 + xen/arch/arm/domctl.c | 22 ++ xen/arch/arm/firmware/scmi-smc-multiagent.c | 2 + xen/arch/arm/include/asm/domain.h | 6 + xen/include/public/arch-arm.h | 4 + xen/include/public/device_tree_defs.h | 1 + xen/include/public/domctl.h | 11 + 11 files changed, 365 insertions(+), 11 deletions(-) diff --git a/tools/include/xenctrl.h b/tools/include/xenctrl.h index 495598123133..54a93431641a 100644 --- a/tools/include/xenctrl.h +++ b/tools/include/xenctrl.h @@ -1205,6 +1205,9 @@ int xc_domain_getvnuma(xc_interface *xch, int xc_domain_soft_reset(xc_interface *xch, uint32_t domid); +int xc_domain_get_sci_info(xc_interface *xch, uint32_t domid, + uint64_t *paddr, uint32_t *func_id); + #if defined(__i386__) || defined(__x86_64__) /* * PC BIOS standard E820 types and structure. diff --git a/tools/libs/ctrl/xc_domain.c b/tools/libs/ctrl/xc_domain.c index 2ddc3f4f426d..f4ffab2021cd 100644 --- a/tools/libs/ctrl/xc_domain.c +++ b/tools/libs/ctrl/xc_domain.c @@ -2229,6 +2229,24 @@ out: return ret; } + +int xc_domain_get_sci_info(xc_interface *xch, uint32_t domid, + uint64_t *paddr, uint32_t *func_id) +{ + struct xen_domctl domctl = {}; + + memset(&domctl, 0, sizeof(domctl)); + domctl.cmd = XEN_DOMCTL_get_sci_info; + domctl.domain = domid; + + if ( do_domctl(xch, &domctl) != 0 ) + return 1; + + *paddr = domctl.u.sci_info.paddr; + *func_id = domctl.u.sci_info.func_id; + return 0; +} + /* * Local variables: * mode: C diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c index cdf5edb299af..cc54abc1ea79 100644 --- a/tools/libs/light/libxl_arm.c +++ b/tools/libs/light/libxl_arm.c @@ -9,6 +9,7 @@ #include #include #include +#include /* * There is no clear requirements for the total size of Virtio MMIO region. @@ -640,9 +641,6 @@ static int make_optee_node(libxl__gc *gc, void *fdt) int res; LOG(DEBUG, "Creating OP-TEE node in dtb"); - res = fdt_begin_node(fdt, "firmware"); - if (res) return res; - res = fdt_begin_node(fdt, "optee"); if (res) return res; @@ -655,9 +653,6 @@ static int make_optee_node(libxl__gc *gc, void *fdt) res = fdt_end_node(fdt); if (res) return res; - res = fdt_end_node(fdt); - if (res) return res; - return 0; } @@ -1191,10 +1186,9 @@ static int copy_node(libxl__gc *gc, void *fdt, void *pfdt, return 0; } -static int copy_node_by_path(libxl__gc *gc, const char *path, - void *fdt, void *pfdt) +static int get_path_nodeoff(const char *path, void *pfdt) { - int nodeoff, r; + int nodeoff; const char *name = strrchr(path, '/'); if (!name) @@ -1214,12 +1208,277 @@ static int copy_node_by_path(libxl__gc *gc, const char *path, if (strcmp(fdt_get_name(pfdt, nodeoff, NULL), name)) return -FDT_ERR_NOTFOUND; + return nodeoff; +} + +static int copy_node_by_path(libxl__gc *gc, const char *path, + void *fdt, void *pfdt) +{ + int nodeoff, r; + + nodeoff = get_path_nodeoff(path, pfdt); + if (nodeoff < 0) + return nodeoff; + r = copy_node(gc, fdt, pfdt, nodeoff, 0); if (r) return r; return 0; } +static int map_sci_page(libxl__gc *gc, uint32_t domid, uint64_t paddr, + uint64_t guest_addr) +{ + int ret; + uint64_t _paddr_pfn = paddr >> XC_PAGE_SHIFT; + uint64_t _guest_pfn = guest_addr >> XC_PAGE_SHIFT; + + assert(paddr && guest_addr); + LOG(DEBUG, "[%d] mapping sci shmem page %"PRIx64, domid, _paddr_pfn); + + ret = xc_domain_iomem_permission(CTX->xch, domid, _paddr_pfn, 1, 1); + if (ret < 0) { + LOG(ERROR, + "failed give domain access to iomem page %"PRIx64, + _paddr_pfn); + return ret; + } + + ret = xc_domain_memory_mapping(CTX->xch, domid, + _guest_pfn, _paddr_pfn, + 1, 1); + if (ret < 0) { + LOG(ERROR, + "failed to map to domain iomem page %"PRIx64 + " to guest address %"PRIx64, + _paddr_pfn, _guest_pfn); + return ret; + } + + return 0; +} + +static int scmi_dt_make_shmem_node(libxl__gc *gc, void *fdt) +{ + int res; + char buf[64]; + + snprintf(buf, sizeof(buf), "scmi-shmem@%llx", GUEST_SCI_SHMEM_BASE); + + res = fdt_begin_node(fdt, buf); + if (res) return res; + + res = fdt_property_compat(gc, fdt, 1, "arm,scmi-shmem"); + if (res) return res; + + res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, + GUEST_ROOT_SIZE_CELLS, 1, + GUEST_SCI_SHMEM_BASE, GUEST_SCI_SHMEM_SIZE); + if (res) return res; + + res = fdt_property_cell(fdt, "phandle", GUEST_PHANDLE_SCMI); + if (res) return res; + + res = fdt_end_node(fdt); + if (res) return res; + + return 0; +} + +static const char *name_from_path(const char *path) +{ + return strrchr(path, '/') + 1; +} + +static int dt_copy_properties(libxl__gc *gc, void* fdt, void *xen_fdt, + const char *full_name) +{ + int propoff, nameoff, r, nodeoff; + const struct fdt_property *prop; + + LOG(DEBUG, "Copy properties for node: %s", full_name); + nodeoff = get_path_nodeoff(full_name, xen_fdt); + if (nodeoff < 0) + return -FDT_ERR_NOTFOUND; + + for (propoff = fdt_first_property_offset(xen_fdt, nodeoff); + propoff >= 0; + propoff = fdt_next_property_offset(xen_fdt, propoff)) { + + if (!(prop = fdt_get_property_by_offset(xen_fdt, propoff, NULL))) + return -FDT_ERR_INTERNAL; + + nameoff = fdt32_to_cpu(prop->nameoff); + + /* Skipping phandle nodes in xen device-tree */ + if (strcmp(fdt_string(xen_fdt,nameoff), "phandle") == 0 || + strcmp(fdt_string(xen_fdt, nameoff), "linux,phandle") == 0) + continue; + + r = fdt_property(fdt, fdt_string(xen_fdt, nameoff), + prop->data, fdt32_to_cpu(prop->len)); + if (r) return r; + } + + return (propoff != -FDT_ERR_NOTFOUND)? propoff : 0; +} + +static int scmi_dt_scan_node(libxl__gc *gc, void *fdt, void *pfdt, + void *xen_fdt, int nodeoff) +{ + int rc; + int node_next; + char full_name[128]; + uint32_t phandle; + + node_next = fdt_first_subnode(pfdt, nodeoff); + while (node_next > 0) + { + LOG(ERROR,"Processing node %s", + fdt_get_name(pfdt, node_next, NULL)); + + phandle = fdt_get_phandle(pfdt, node_next); + + rc = fdt_get_path(pfdt, node_next, full_name, sizeof(full_name)); + if (rc) return rc; + + rc = fdt_begin_node(fdt, name_from_path(full_name)); + if (rc) return rc; + + rc = dt_copy_properties(gc, fdt, xen_fdt, full_name); + if (rc) return rc; + + if (phandle) { + rc = fdt_property_cell(fdt, "phandle", phandle); + if (rc) return rc; + } + + rc = scmi_dt_scan_node(gc, fdt, pfdt, xen_fdt, node_next); + if (rc) return rc; + + rc = fdt_end_node(fdt); + if (rc) return rc; + + node_next = fdt_next_subnode(pfdt, node_next); + } + + return 0; +} + +static int scmi_hypfs_fdt_check(libxl__gc *gc, void *fdt) +{ + int r; + + if (fdt_magic(fdt) != FDT_MAGIC) { + LOG(ERROR, "FDT is not a valid Flat Device Tree"); + return ERROR_FAIL; + } + + r = fdt_check_header(fdt); + if (r) { + LOG(ERROR, "Failed to check the FDT (%d)", r); + return ERROR_FAIL; + } + + return r; +} + +static int scmi_dt_copy_subnodes(libxl__gc *gc, void *fdt, void *pfdt) +{ + struct xenhypfs_handle *hdl; + struct xenhypfs_dirent *ent; + void *xen_fdt; + int rc, nodeoff; + + hdl = xenhypfs_open(NULL, 0); + if (!hdl) + return -EINVAL; + + xen_fdt = xenhypfs_read_raw(hdl, "/devicetree", &ent); + if (!xen_fdt) { + rc = errno; + LOG(ERROR, "Unable to read hypfs entry: %d", rc); + goto out; + } + + rc = scmi_hypfs_fdt_check(gc, xen_fdt); + if (rc) { + LOG(ERROR, "Hypfs device tree is invalid"); + goto out; + } + + nodeoff = get_path_nodeoff("/firmware/scmi", pfdt); + if (nodeoff <= 0) { + rc = -ENODEV; + goto out; + } + + rc = scmi_dt_scan_node(gc, fdt, pfdt, xen_fdt, nodeoff); + +out: + xenhypfs_close(hdl); + + return rc; +} + +static int scmi_dt_create_node(libxl__gc *gc, void *fdt, void *pfdt, + uint32_t func_id) +{ + int rc = 0; + + rc = fdt_begin_node(fdt, "scmi"); + if (rc) return rc; + + rc = fdt_property_compat(gc, fdt, 1, "arm,scmi-smc"); + if (rc) return rc; + + rc = fdt_property_cell(fdt, "shmem", GUEST_PHANDLE_SCMI); + if (rc) return rc; + + rc = fdt_property_cell(fdt, "#addrets-cells", 1); + if (rc) return rc; + + rc = fdt_property_cell(fdt, "#size-cells", 0); + if (rc) return rc; + + rc = fdt_property_cell(fdt, "arm,smc-id", func_id); + if (rc) return rc; + + rc = scmi_dt_copy_subnodes(gc, fdt, pfdt); + if (rc) return rc; + + rc = fdt_end_node(fdt); + if (rc) return rc; + + return rc; +} + +static int make_firmware_node(libxl__gc *gc, void *fdt, void *pfdt, int tee, + int sci, uint32_t func_id) +{ + int res; + + if ((tee == LIBXL_TEE_TYPE_NONE) && (sci == LIBXL_ARM_SCI_TYPE_NONE)) + return 0; + + res = fdt_begin_node(fdt, "firmware"); + if (res) return res; + + if (tee == LIBXL_TEE_TYPE_OPTEE) { + res = make_optee_node(gc, fdt); + if (res) return res; + } + + if (sci == LIBXL_ARM_SCI_TYPE_SCMI_SMC_MULTIAGENT) { + res = scmi_dt_create_node(gc, fdt, pfdt, func_id); + if (res) return res; + } + + res = fdt_end_node(fdt); + if (res) return res; + return 0; +} + /* * The partial device tree is not copied entirely. Only the relevant bits are * copied to the guest device tree: @@ -1391,8 +1650,11 @@ next_resize: if (info->arch_arm.vuart == LIBXL_VUART_TYPE_SBSA_UART) FDT( make_vpl011_uart_node(gc, fdt, ainfo, dom) ); - if (info->tee == LIBXL_TEE_TYPE_OPTEE) - FDT( make_optee_node(gc, fdt) ); + if (info->arm_sci.type == LIBXL_ARM_SCI_TYPE_SCMI_SMC_MULTIAGENT) + FDT( scmi_dt_make_shmem_node(gc, fdt) ); + + FDT( make_firmware_node(gc, fdt, pfdt, info->tee, info->arm_sci.type, + state->arm_sci_agent_funcid) ); if (d_config->num_pcidevs) FDT( make_vpci_node(gc, fdt, ainfo, dom) ); @@ -1671,6 +1933,16 @@ int libxl__arch_build_dom_finish(libxl__gc *gc, { int rc = 0, ret; + if (info->arm_sci.type == LIBXL_ARM_SCI_TYPE_SCMI_SMC_MULTIAGENT) { + ret = map_sci_page(gc, dom->guest_domid, state->arm_sci_agent_paddr, + GUEST_SCI_SHMEM_BASE); + if (ret < 0) { + LOG(ERROR, "map_sci_page failed\n"); + rc = ERROR_FAIL; + goto out; + } + } + if (info->arch_arm.vuart != LIBXL_VUART_TYPE_SBSA_UART) { rc = 0; goto out; diff --git a/tools/libs/light/libxl_create.c b/tools/libs/light/libxl_create.c index e03599ea99d1..ba26b9784838 100644 --- a/tools/libs/light/libxl_create.c +++ b/tools/libs/light/libxl_create.c @@ -813,6 +813,18 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config, */ assert(libxl_domid_valid_guest(*domid)); + if (d_config->b_info.arm_sci.type == LIBXL_ARM_SCI_TYPE_SCMI_SMC_MULTIAGENT) { + ret = xc_domain_get_sci_info(ctx->xch, *domid, &state->arm_sci_agent_paddr, + &state->arm_sci_agent_funcid); + LOGD(DEBUG, *domid,"sci_agent_paddr = %lx", state->arm_sci_agent_paddr); + if (ret) { + LOGED(ERROR, *domid, "failed to get sci paddr"); + rc = ERROR_FAIL; + goto out; + } + + } + dom_path = libxl__xs_get_dompath(gc, *domid); if (!dom_path) { rc = ERROR_FAIL; diff --git a/tools/libs/light/libxl_internal.h b/tools/libs/light/libxl_internal.h index cfac8e18b6d3..349c89a938ca 100644 --- a/tools/libs/light/libxl_internal.h +++ b/tools/libs/light/libxl_internal.h @@ -1405,6 +1405,9 @@ typedef struct { * applicable to the primary domain, not support domains (e.g. stub QEMU). */ bool restore; bool soft_reset; + + uint64_t arm_sci_agent_paddr; + uint32_t arm_sci_agent_funcid; } libxl__domain_build_state; _hidden void libxl__domain_build_state_init(libxl__domain_build_state *s); diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c index 9d047065ba13..3ac77ea4d497 100644 --- a/xen/arch/arm/domctl.c +++ b/xen/arch/arm/domctl.c @@ -49,6 +49,17 @@ static int handle_vuart_init(struct domain *d, return rc; } +static int get_sci_info(struct domain *d, struct xen_domctl_sci_info *sci_info) +{ +#ifdef CONFIG_ARM_SCI + sci_info->paddr = d->arch.sci_channel.paddr; + sci_info->func_id = d->arch.sci_channel.guest_func_id; + return 0; +#else + return -ENODEV; +#endif +} + long arch_do_domctl(struct xen_domctl *domctl, struct domain *d, XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) { @@ -179,6 +190,17 @@ long arch_do_domctl(struct xen_domctl *domctl, struct domain *d, } case XEN_DOMCTL_dt_overlay: return dt_overlay_domctl(d, &domctl->u.dt_overlay); + + case XEN_DOMCTL_get_sci_info: + { + int rc = get_sci_info(d, &domctl->u.sci_info); + + if ( !rc ) + rc = copy_to_guest(u_domctl, domctl, 1); + + return rc; + } + default: return subarch_do_domctl(domctl, d, u_domctl); } diff --git a/xen/arch/arm/firmware/scmi-smc-multiagent.c b/xen/arch/arm/firmware/scmi-smc-multiagent.c index 293fb30fa6c5..c2f43d97d804 100644 --- a/xen/arch/arm/firmware/scmi-smc-multiagent.c +++ b/xen/arch/arm/firmware/scmi-smc-multiagent.c @@ -560,6 +560,8 @@ static int scmi_domain_init(struct domain *d, d->arch.sci_data = channel; d->arch.sci_enabled = true; + d->arch.sci_channel.paddr = channel->paddr; + d->arch.sci_channel.guest_func_id = channel->func_id; return 0; diff --git a/xen/arch/arm/include/asm/domain.h b/xen/arch/arm/include/asm/domain.h index fa0898b7cf80..511f4aa8ed8d 100644 --- a/xen/arch/arm/include/asm/domain.h +++ b/xen/arch/arm/include/asm/domain.h @@ -59,6 +59,11 @@ struct paging_domain { unsigned long p2m_total_pages; }; +struct sci_channel { + uint32_t guest_func_id; + uint64_t paddr; +}; + struct arch_domain { #ifdef CONFIG_ARM_64 @@ -122,6 +127,7 @@ struct arch_domain bool sci_enabled; /* ARM SCI driver's specific data */ void *sci_data; + struct sci_channel sci_channel; #endif } __cacheline_aligned; diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index 30e46de6d7a0..a5b22225bf31 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -469,6 +469,10 @@ typedef uint64_t xen_callback_t; #define GUEST_PL011_BASE xen_mk_ullong(0x22000000) #define GUEST_PL011_SIZE xen_mk_ullong(0x00001000) +/* SCI mediator */ +#define GUEST_SCI_SHMEM_BASE xen_mk_ullong(0x22001000) +#define GUEST_SCI_SHMEM_SIZE xen_mk_ullong(0x01000) + /* Guest PCI-PCIe memory space where config space and BAR will be available.*/ #define GUEST_VPCI_ADDR_TYPE_MEM xen_mk_ullong(0x02000000) #define GUEST_VPCI_MEM_ADDR xen_mk_ullong(0x23000000) diff --git a/xen/include/public/device_tree_defs.h b/xen/include/public/device_tree_defs.h index 9e80d0499dc3..b8bdfcdcf0b9 100644 --- a/xen/include/public/device_tree_defs.h +++ b/xen/include/public/device_tree_defs.h @@ -14,6 +14,7 @@ */ #define GUEST_PHANDLE_GIC (65000) #define GUEST_PHANDLE_IOMMU (GUEST_PHANDLE_GIC + 1) +#define GUEST_PHANDLE_SCMI (GUEST_PHANDLE_IOMMU + 1) #define GUEST_ROOT_ADDRESS_CELLS 2 #define GUEST_ROOT_SIZE_CELLS 2 diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index e2d392d1e5e5..6ef78c241f8c 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -1223,6 +1223,13 @@ struct xen_domctl_vmtrace_op { #define XEN_DOMCTL_vmtrace_get_option 5 #define XEN_DOMCTL_vmtrace_set_option 6 }; + +/* XEN_DOMCTL_get_sci_info */ +struct xen_domctl_sci_info { + uint64_t paddr; + uint32_t func_id; +}; + typedef struct xen_domctl_vmtrace_op xen_domctl_vmtrace_op_t; DEFINE_XEN_GUEST_HANDLE(xen_domctl_vmtrace_op_t); @@ -1333,6 +1340,9 @@ struct xen_domctl { #define XEN_DOMCTL_dt_overlay 87 #define XEN_DOMCTL_gsi_permission 88 #define XEN_DOMCTL_set_llc_colors 89 + +#define XEN_DOMCTL_get_sci_info 90 + #define XEN_DOMCTL_gdbsx_guestmemio 1000 #define XEN_DOMCTL_gdbsx_pausevcpu 1001 #define XEN_DOMCTL_gdbsx_unpausevcpu 1002 @@ -1400,6 +1410,7 @@ struct xen_domctl { struct xen_domctl_dt_overlay dt_overlay; #endif struct xen_domctl_set_llc_colors set_llc_colors; + struct xen_domctl_sci_info sci_info; uint8_t pad[128]; } u; };