Received: by 2002:a05:7412:37c9:b0:e2:908c:2ebd with SMTP id jz9csp810143rdb; Tue, 19 Sep 2023 10:44:37 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFc8NwYxiElLbgCs0kkNBGm/m1jS6i4hr2YvqK17nH70TSA1KPHiLTRqD+iWkBN43VEZk7/ X-Received: by 2002:a17:90a:bf0b:b0:263:fbe5:2125 with SMTP id c11-20020a17090abf0b00b00263fbe52125mr414324pjs.15.1695145477156; Tue, 19 Sep 2023 10:44:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695145477; cv=none; d=google.com; s=arc-20160816; b=zl6lHYf7XUrlKxVeeSKvsNcyigVs6/HYtyiNjrK4bC1krGtBjnN8G+qRJUYUu/bT7v eZGzAOaevwxJuXtqTTqbNTZbdguEujDBgilQmRSFMQU6PIqvX4tHfqmN/i/MleQcNLmE XzI14pwpGAevOnyqK1iZy05QvNndW9ECY7a9aMZFN58fhlKW4q7GsPtlq7x0HND8prqk /PE6tBx+4YoMHJJyblXtovtxO1EroD9UInP17PAe0GYt9p0Z/S/m/VhAsboXOeykvAvO /QAFGp0f6DOJvppMCy9TYKw3cTxB/LjAlD6MlbA03FlRCgYor7CjdwEcLkooNVtzRYQP qAXA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from; bh=dSjpqJrx1CgoPgr9bqZnCXfaapKEfkFPowNIUTRdD/k=; fh=vcyxKNiHD7TmKqmM0/rwqxGOTauIz60tMzPVV7I2N7Q=; b=bUu8fGmzFpFnO3khRgrxF/LLGWRd/x+0fJyFc+WD9AnVmtkKByLSKYmQH0op3iyC7T xiCMXa7eny0XyaDtl2rAdkBzeaMippaNaYwFAQrVKnmjfZhq1zF4FU5V0jkuhK6qLVun t8OfKx+OY2h4Cbhqeti06odZnHKU1mIh2dB+cvu/PxR0Fk/3Mr5NI4zOAWYOcJyKT3PX OPv8spJkZfChbcP2IYCer8/IhhCaqwQ3s5dnlU/NAJR3AIB+1TRqT72HSNlVPcFy9waG wIeiw+XLgeHKqF4r6fQHD0n1BmyWpV8/jqmMwSsY6sEF9OHR/U0RuE2xAT5MUGaU7B47 EhTA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from lipwig.vger.email (lipwig.vger.email. [23.128.96.33]) by mx.google.com with ESMTPS id c8-20020a17090a674800b002685065230asi12305137pjm.37.2023.09.19.10.44.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Sep 2023 10:44:37 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) client-ip=23.128.96.33; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by lipwig.vger.email (Postfix) with ESMTP id 9AFD2828D032; Tue, 19 Sep 2023 10:42:33 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at lipwig.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232441AbjISRlt (ORCPT + 99 others); Tue, 19 Sep 2023 13:41:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55742 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232359AbjISRlm (ORCPT ); Tue, 19 Sep 2023 13:41:42 -0400 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 65493ED for ; Tue, 19 Sep 2023 10:41:28 -0700 (PDT) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 74240FEC; Tue, 19 Sep 2023 10:42:05 -0700 (PDT) Received: from e103737-lin.cambridge.arm.com (e103737-lin.cambridge.arm.com [10.1.197.49]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 28F153F5A1; Tue, 19 Sep 2023 10:41:27 -0700 (PDT) From: Sudeep Holla Date: Tue, 19 Sep 2023 18:40:56 +0100 Subject: [PATCH RFT v2 08/18] firmware: arm_ffa: Initial support for scheduler receiver interrupt MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Message-Id: <20230919-ffa_v1-1_notif-v2-8-6f3a3ca3923c@arm.com> References: <20230919-ffa_v1-1_notif-v2-0-6f3a3ca3923c@arm.com> In-Reply-To: <20230919-ffa_v1-1_notif-v2-0-6f3a3ca3923c@arm.com> To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Sudeep Holla , Jens Wiklander , Marc Bonnici , Coboy Chen , Lorenzo Pieralisi , Olivier Deprez X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=7566; i=sudeep.holla@arm.com; h=from:subject:message-id; bh=FrcEGevbFkIUMjTrfQy4wukuAwXYSEQfEEVHCn1ql00=; b=owEBbQKS/ZANAwAIAQBBurwxfuKYAcsmYgBlCd073Ts/IYXTdAVKgOOdvj18pP6Q6WlJFdiAn 0fkuiq9wLCJAjMEAAEIAB0WIQS6ceUSBvMeskPdk+EAQbq8MX7imAUCZQndOwAKCRAAQbq8MX7i mNsvEAC0s+0Rcc+2kwS3rekvuQLrKljT70t5TwjY3H4bxSlfmn+CDWLVvBRjxQ2UxnoU53pHjvT 7RJiOlBOiIZDsfj/wBloNnvvh/grsnvbwfIqp7SquKgEoIBzhTmzV3Ki/F2ZHMI2CjFbrfoTQmy +Ixa/mSL4hFv9gny6rySbln1Dy5xlRfMIlKOwtRKr/VRR164i3su6ePh2HuG0/3X3i4XemYH+jA fJJ72LMxc1LVE34lerS08SQHbSH7sh5TzXQkf94pd8OavFhDu8tesduNy3CrWkiti7FEskfQgjf cI0T5LXQZzZy/o58qFmNoVpdrzJMcsW/hXN39mSwD+HhzUktLeF6VpGfWF7Ct4oudayp3PM1Gls 8bvPqllNtNNkb8/TCX/lrTqdn6KtjtLEz1MpkvmfRHDBgxfimuXsxkqvNzNBzJvM/KnLMI+WUfK tZSSKcNp0TN+jKxoxSR/jabmMDgAfIaLr9A9XpgwGYdHtILon/pMrC1MPwvc4aeQUwrHDXj9vXl 6eyLkIVrZOMLyagL2/avf/iSz9DwnK6TAVdeQZNzONBedD0HvFBRpNGOHX1hkEXyjJKKBQcFgHf AfBVjdqQb6dwHmdMmg1JDBnbMZNEh4rtWFlbmXFkcRY3SWXzBv12PYbNt7yJ7XHpVJbJa5urCO2 asqvrubQltrRkjA== X-Developer-Key: i=sudeep.holla@arm.com; a=openpgp; fpr=7360A21742ADF5A11767C1C139CFD4755FE2D5B4 X-Spam-Status: No, score=-0.8 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lipwig.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (lipwig.vger.email [0.0.0.0]); Tue, 19 Sep 2023 10:42:33 -0700 (PDT) The Framework uses the schedule receiver interrupt to inform the receiver’s scheduler that the receiver must be run to handle a pending notification. A receiver’s scheduler can obtain the description of the schedule receiver interrupt by invoking the FFA_FEATURES interface. The delivery of the physical schedule receiver interrupt from the secure state to the non-secure state depends upon the state of the interrupt controller as configured by the hypervisor. The schedule seceiver interrupt is assumed to be a SGI. The Arm GIC specification defines 16 SGIs. It recommends that they are equally divided between the non-secure and secure states. OS like Linux kernel in the non-secure state typically do not have SGIs to spare. The usage of SGIs in the secure state is however limited. It is more likely that software in the Secure world does not use all the SGIs allocated to it. It is recommended that the secure world software donates an unused SGI to the normal world for use as the schedule receiver interrupt. This implies that secure world software must configure the SGI in the GIC as a non-secure interrupt before presenting it to the normal world. Signed-off-by: Sudeep Holla --- drivers/firmware/arm_ffa/driver.c | 192 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 182 insertions(+), 10 deletions(-) diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index e097e894b433..3d8f1daea32d 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -22,15 +22,20 @@ #define DRIVER_NAME "ARM FF-A" #define pr_fmt(fmt) DRIVER_NAME ": " fmt +#include #include #include +#include #include +#include #include #include #include #include +#include #include #include +#include #include #include "common.h" @@ -76,6 +81,10 @@ static inline int ffa_to_linux_errno(int errno) return -EINVAL; } +struct ffa_pcpu_irq { + struct ffa_drv_info *info; +}; + struct ffa_drv_info { u32 version; u16 vm_id; @@ -85,6 +94,12 @@ struct ffa_drv_info { void *tx_buffer; bool mem_ops_native; bool bitmap_created; + unsigned int sched_recv_irq; + unsigned int cpuhp_state; + struct ffa_pcpu_irq __percpu *irq_pcpu; + struct workqueue_struct *notif_pcpu_wq; + struct work_struct irq_work; + bool info_get_64b; }; static struct ffa_drv_info *drv_info; @@ -910,9 +925,153 @@ static void ffa_setup_partitions(void) kfree(pbuf); } +/* FFA FEATURE IDs */ +#define FFA_FEAT_NOTIFICATION_PENDING_INT (1) +#define FFA_FEAT_SCHEDULE_RECEIVER_INT (2) +#define FFA_FEAT_MANAGED_EXIT_INT (3) + +static irqreturn_t irq_handler(int irq, void *irq_data) +{ + struct ffa_pcpu_irq *pcpu = irq_data; + struct ffa_drv_info *info = pcpu->info; + + queue_work(info->notif_pcpu_wq, &info->irq_work); + + return IRQ_HANDLED; +} + +static void ffa_sched_recv_irq_work_fn(struct work_struct *work) +{ + struct ffa_drv_info *info = container_of(work, struct ffa_drv_info, + irq_work); + + ffa_notification_info_get(info->info_get_64b); +} + +static int ffa_sched_recv_irq_map(void) +{ + int ret, irq, sr_intid; + + /* The returned sr_intid is assumed to be SGI donated to NS world */ + ret = ffa_features(FFA_FEAT_SCHEDULE_RECEIVER_INT, 0, &sr_intid, NULL); + if (ret < 0) { + if (ret != -EOPNOTSUPP) + pr_err("Failed to retrieve scheduler Rx interrupt\n"); + return ret; + } + + if (acpi_disabled) { + struct of_phandle_args oirq = {}; + struct device_node *gic; + + /* Only GICv3 supported currently with the device tree */ + gic = of_find_compatible_node(NULL, NULL, "arm,gic-v3"); + if (!gic) + return -ENXIO; + + oirq.np = gic; + oirq.args_count = 1; + oirq.args[0] = sr_intid; + irq = irq_create_of_mapping(&oirq); + of_node_put(gic); +#ifdef CONFIG_ACPI + } else { + irq = acpi_register_gsi(NULL, sr_intid, ACPI_EDGE_SENSITIVE, + ACPI_ACTIVE_HIGH); +#endif + } + + if (irq <= 0) { + pr_err("Failed to create IRQ mapping!\n"); + return -ENODATA; + } + + return irq; +} + +static void ffa_sched_recv_irq_unmap(void) +{ + if (drv_info->sched_recv_irq) + irq_dispose_mapping(drv_info->sched_recv_irq); +} + +static int ffa_cpuhp_pcpu_irq_enable(unsigned int cpu) +{ + enable_percpu_irq(drv_info->sched_recv_irq, IRQ_TYPE_NONE); + return 0; +} + +static int ffa_cpuhp_pcpu_irq_disable(unsigned int cpu) +{ + disable_percpu_irq(drv_info->sched_recv_irq); + return 0; +} + +static void ffa_uninit_pcpu_irq(void) +{ + if (drv_info->cpuhp_state) + cpuhp_remove_state(drv_info->cpuhp_state); + + if (drv_info->notif_pcpu_wq) + destroy_workqueue(drv_info->notif_pcpu_wq); + + if (drv_info->sched_recv_irq) + free_percpu_irq(drv_info->sched_recv_irq, drv_info->irq_pcpu); + + if (drv_info->irq_pcpu) + free_percpu(drv_info->irq_pcpu); +} + +static int ffa_init_pcpu_irq(unsigned int irq) +{ + struct ffa_pcpu_irq __percpu *irq_pcpu; + int ret, cpu; + + irq_pcpu = alloc_percpu(struct ffa_pcpu_irq); + if (!irq_pcpu) + return -ENOMEM; + + for_each_present_cpu(cpu) + per_cpu_ptr(irq_pcpu, cpu)->info = drv_info; + + drv_info->irq_pcpu = irq_pcpu; + + ret = request_percpu_irq(irq, irq_handler, "ARM-FFA", irq_pcpu); + if (ret) { + pr_err("Error registering notification IRQ %d: %d\n", irq, ret); + return ret; + } + + INIT_WORK(&drv_info->irq_work, ffa_sched_recv_irq_work_fn); + drv_info->notif_pcpu_wq = create_workqueue("ffa_pcpu_irq_notification"); + if (!drv_info->notif_pcpu_wq) + return -EINVAL; + + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ffa/pcpu-irq:starting", + ffa_cpuhp_pcpu_irq_enable, + ffa_cpuhp_pcpu_irq_disable); + + if (ret < 0) + return ret; + + drv_info->cpuhp_state = ret; + return 0; +} + +static void ffa_notifications_cleanup(void) +{ + ffa_uninit_pcpu_irq(); + ffa_sched_recv_irq_unmap(); + + if (drv_info->bitmap_created) { + ffa_notification_bitmap_destroy(); + drv_info->bitmap_created = false; + } +} + static int ffa_notifications_setup(void) { - int ret; + int ret, irq; ret = ffa_features(FFA_NOTIFICATION_BITMAP_CREATE, 0, NULL, NULL); if (!ret) { @@ -924,15 +1083,24 @@ static int ffa_notifications_setup(void) } drv_info->bitmap_created = true; - return 0; -} + irq = ffa_sched_recv_irq_map(); + if (irq <= 0) + goto cleanup; -static void ffa_notifications_cleanup(void) -{ - if (drv_info->bitmap_created) { - ffa_notification_bitmap_destroy(); - drv_info->bitmap_created = false; - } + if (FFA_FN_NATIVE(NOTIFICATION_INFO_GET) == + FFA_FN64_NOTIFICATION_INFO_GET) + drv_info->info_get_64b = true; + + drv_info->sched_recv_irq = irq; + + ret = ffa_init_pcpu_irq(irq); + if (ret) + goto cleanup; + + return 0; +cleanup: + ffa_notifications_cleanup(); + return ret; } static int __init ffa_init(void) @@ -990,7 +1158,11 @@ static int __init ffa_init(void) ffa_set_up_mem_ops_native_flag(); - return ffa_notifications_setup(); + ret = ffa_notifications_setup(); + if (ret) + goto free_pages; + + return 0; free_pages: if (drv_info->tx_buffer) free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE); -- 2.42.0