Received: by 2002:a05:6358:700f:b0:131:369:b2a3 with SMTP id 15csp2663612rwo; Thu, 3 Aug 2023 12:54:44 -0700 (PDT) X-Google-Smtp-Source: APBJJlH+lxLg5++UomZEeYt5GqhTWMJT51VHWmBRlHwC1hPoJF9JoR1iVmGvoN+4C3C5CWFyc1Mt X-Received: by 2002:a17:906:3191:b0:99b:f8e7:130f with SMTP id 17-20020a170906319100b0099bf8e7130fmr8543029ejy.15.1691092483802; Thu, 03 Aug 2023 12:54:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691092483; cv=none; d=google.com; s=arc-20160816; b=JeqTfLmw6+JrmWRz+g3Q89Qtkkrudh1IjkEtOa1eauHT5Kra0En7rABG478XWAqPd8 tO0/s1NCwYbG5LlyIL4FQA51S55sbzF6q2q6Miszj752q8pXUkZtK1Zojsy5b5r9zijP G0pSs3wgsbGwbBv2XAFK6xoCGpWlI61ss2cqG4Adeo5m+ZLGTyXV8PMRd9Zuot6aUcnD Q2l0WAsa5bTv5ibE+Pobkb7Q738OJqFSEGhktNl2YvbxeYPxxUroUj6+P13njGEbmAL6 U5lIMDJWmeWnifg106vwyENXV+AU1rYD7rydUJcQLCClo6zgI3Xd6htG65NBFMqdHclO Nk/A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=3+id7RwNNZVY4dwv/BFus8ZIaRYS2JgijZHBJ6Lg2A0=; fh=uIXkm8cj3c9TR2+QLs5NFfyS+JdekmBAQ3a9JCgCFII=; b=Dqz9S+du8GY6SDPxvCp379ozSlKEfxwtGlfivgVCt1eshxr7c4kR503Xz/2acGWMYY DAfSsrrpl7WR2luHewNz+ge2yMP6Y3ip5l9zTZKV3K5ChZGfmCwDWMXNU1kEHcP0RCum GloA10IwJX74yuA7IhKFdtBEIw0kWA7T1KAN9G/OKR5vaeTh8jm5s+BrxhEcMtb/z/Af cQH3/0Oue8SFnmiUCuoh0dcjewEMmelkvwqxJAAnLPwezxKvF5depT8Jgr2fzCqhmNjA m3EfQrLNMMIvpCl2bQ9vQmiI11C/too6u4UnBbtpAEyfcDbdQKhWFwfAykeO9GhPAhX/ RKPg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 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 out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id m2-20020a1709062ac200b009938899a3besi342709eje.211.2023.08.03.12.54.19; Thu, 03 Aug 2023 12:54:43 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232411AbjHCTCv (ORCPT + 99 others); Thu, 3 Aug 2023 15:02:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46930 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232326AbjHCTCm (ORCPT ); Thu, 3 Aug 2023 15:02:42 -0400 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B591C3A9F for ; Thu, 3 Aug 2023 12:02:33 -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 9DBA21477; Thu, 3 Aug 2023 12:03:15 -0700 (PDT) Received: from usa.arm.com (e103737-lin.cambridge.arm.com [10.1.197.49]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 817323F6C4; Thu, 3 Aug 2023 12:02:31 -0700 (PDT) From: Sudeep Holla To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: Sudeep Holla , Jens Wiklander , Lucian Paul-Trifu , Marc Bonnici , Coboy Chen Subject: [PATCH RFT 08/12] firmware: arm_ffa: Initial support for scheduler receiver interrupt Date: Thu, 3 Aug 2023 20:02:12 +0100 Message-ID: <20230803-ffa_v1-1_notif-v1-8-6613ff2b1f81@arm.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230803-ffa_v1-1_notif-v1-0-6613ff2b1f81@arm.com> References: <20230803-ffa_v1-1_notif-v1-0-6613ff2b1f81@arm.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=7308; i=sudeep.holla@arm.com; h=from:subject:message-id; bh=cR9CtR2RFxlY81K/6ozS49XFT+Nzf9J2+LUO1GGNRM8=; b=owEBbQKS/ZANAwAIAQBBurwxfuKYAcsmYgBky/iNo49Ygu4XVqY3+8BL3EjsrgF4PmJ1aetrb lHlAKERRtqJAjMEAAEIAB0WIQS6ceUSBvMeskPdk+EAQbq8MX7imAUCZMv4jQAKCRAAQbq8MX7i mJ8GD/sHbjxENa8NCw2cX/z46yE1yjZob8hLmLa/1RN+15h/nHmMIVoyuXZss2ot3iqH3fr1aoC 1XoNTQiMMQlJUrVXGXF3MY+6iZ4aetC4fOOJFMEsjZ+wBYybMBaY/flkdnR/ng52D2MsW14c3bX gLI05ZzQxTxkb1OcwlufwaC+37SoR9oR1+8FbtSJJMgTf9TCg7QOFlfHQWrvvod+I79ZoxhdjTO 0kIq9CWF7NqLFkegK4Lf2J0oSnmheo75ElhwqmswxyjbyAm2PJtK1aqIkWW0rhrHTpTt0cCK4/s DSHkReVq5Tc0Osh00jzF3rTbHeOm6TVNrHTA5xsSAjMlg6FX30Z0UmFA5T8FupcuA99pKI3G5IX qMPKA8zQc4+Z6ja6K8tXI+LjCcqlzx944syuBPsf/T3t2q8sg2ON7Qr58eLjyqoBjU/s9c8u394 ukAhjpCDAbyQKYSnwT+5FB+/2OHc+Xesenx+plVAYON5GZ8jF3kVLCWA5aMn9ImbxDy7fudec1a 0mvDMwcPYt6Rs1IPevUV2L9DOZ1/nWoqqtvScR1EFp1ZxWuZiTXoO/iYkAP1/i2CzylZvnQo/Nx nLknDGYPgQAONFFV8UeG5Voc3rBBLnBNfUDS+f+nRLBla1i7duOINrPytoBKC7LL9hvw0NF6G+c 4cGpE7SH tSOTYLw== X-Developer-Key: i=sudeep.holla@arm.com; a=openpgp; fpr=7360A21742ADF5A11767C1C139CFD4755FE2D5B4 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_NONE,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 PPI. 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 | 183 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 175 insertions(+), 8 deletions(-) diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index 77ca9753e3f0..84c934a0ec14 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,147 @@ 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; + + 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; + + 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); + } else { + irq = acpi_register_gsi(NULL, sr_intid, ACPI_EDGE_SENSITIVE, + ACPI_ACTIVE_HIGH); + } + + 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(); +} + static int ffa_notifications_setup(void) { - int ret; + int ret, irq; ret = ffa_features(FFA_NOTIFICATION_BITMAP_CREATE, 0, NULL, NULL); if (!ret) { @@ -924,13 +1077,23 @@ 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(); + if (FFA_FN_NATIVE(NOTIFICATION_INFO_GET) == + FFA_FN64_NOTIFICATION_INFO_GET) + drv_info->info_get_64b = true; + + ret = ffa_init_pcpu_irq(irq); + if (ret) + goto cleanup; + + drv_info->sched_recv_irq = irq; + return 0; +cleanup: + ffa_notifications_cleanup(); + return ret; } static int __init ffa_init(void) @@ -988,7 +1151,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.41.0