lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20230803-ffa_v1-1_notif-v1-12-6613ff2b1f81@arm.com>
Date:   Thu,  3 Aug 2023 20:02:16 +0100
From:   Sudeep Holla <sudeep.holla@....com>
To:     linux-arm-kernel@...ts.infradead.org, linux-kernel@...r.kernel.org
Cc:     Sudeep Holla <sudeep.holla@....com>,
        Jens Wiklander <jens.wiklander@...aro.org>,
        Lucian Paul-Trifu <lucian.paul-trifu@....com>,
        Marc Bonnici <marc.bonnici@....com>,
        Coboy Chen <coboy.chen@...iatek.com>
Subject: [PATCH RFT 12/12] firmware: arm_ffa: Add notification handling mechanism

With all the necessary plumbing in place, let us add handling the
notifications as part of schedule receiver interrupt handler. In order
to do so, we need to just register scheduling callback on behalf of the
driver partition.

Signed-off-by: Sudeep Holla <sudeep.holla@....com>
---
 drivers/firmware/arm_ffa/driver.c | 61 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 59 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index d98d0fbe5605..63daef95b048 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -103,6 +103,7 @@ struct ffa_drv_info {
 	unsigned int cpuhp_state;
 	struct ffa_pcpu_irq __percpu *irq_pcpu;
 	struct workqueue_struct *notif_pcpu_wq;
+	struct work_struct notif_pcpu_work;
 	struct work_struct irq_work;
 	bool info_get_64b;
 	struct xarray partition_info;
@@ -1027,6 +1028,54 @@ static int ffa_notify_send(struct ffa_device *dev, int notify_id,
 				    BIT(notify_id));
 }
 
+static void handle_notif_callbacks(u64 bitmap, u16 part_id)
+{
+	int i = 0;
+	struct notifier_cb_info *cb_info = NULL;
+
+	while (bitmap) {
+		if (bitmap & 1) {
+			mutex_lock(&drv_info->notify_lock);
+			cb_info = notifier_hash_node_get(part_id, i);
+			mutex_unlock(&drv_info->notify_lock);
+			if (cb_info->cb)
+				cb_info->cb(part_id, i, cb_info->cb_data);
+		}
+		i++;
+		bitmap >>= 1;
+	}
+}
+
+static void notif_pcpu_irq_work_fn(struct work_struct *work)
+{
+	int rc;
+	struct ffa_notify_bitmaps bitmaps;
+	struct ffa_drv_info *info = container_of(work, struct ffa_drv_info,
+						 notif_pcpu_work);
+
+	rc = ffa_notification_get(ALL_NOTIFICATION_BITMAPS_FLAGS, &bitmaps);
+	if (rc) {
+		pr_err("Failed to retrieve notifications with %d!\n", rc);
+		return;
+	}
+
+	handle_notif_callbacks(bitmaps.vm_map, info->vm_id);
+	handle_notif_callbacks(bitmaps.sp_map, info->vm_id);
+	handle_notif_callbacks(bitmaps.arch_map, info->vm_id);
+}
+
+static void
+ffa_self_notif_handle(u16 part_id, u16 vcpu, bool is_per_vcpu, void *cb_data)
+{
+	struct ffa_drv_info *info = cb_data;
+
+	if (!is_per_vcpu)
+		notif_pcpu_irq_work_fn(&info->notif_pcpu_work);
+	else
+		queue_work_on(vcpu, info->notif_pcpu_wq,
+			      &info->notif_pcpu_work);
+}
+
 static const struct ffa_info_ops ffa_drv_info_ops = {
 	.api_version_get = ffa_api_version_get,
 	.partition_info_get = ffa_partition_info_get,
@@ -1128,7 +1177,12 @@ static void ffa_setup_partitions(void)
 		}
 		xa_store(&drv_info->partition_info, tpbuf->id, info, GFP_KERNEL);
 	}
-	drv_info->partition_count = count;
+	/* Allocate for the host */
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return;
+	xa_store(&drv_info->partition_info, drv_info->vm_id, info, GFP_KERNEL);
+	drv_info->partition_count = count + 1;
 
 	kfree(pbuf);
 }
@@ -1270,6 +1324,7 @@ static int ffa_init_pcpu_irq(unsigned int irq)
 	}
 
 	INIT_WORK(&drv_info->irq_work, ffa_sched_recv_irq_work_fn);
+	INIT_WORK(&drv_info->notif_pcpu_work, notif_pcpu_irq_work_fn);
 	drv_info->notif_pcpu_wq = create_workqueue("ffa_pcpu_irq_notification");
 	if (!drv_info->notif_pcpu_wq)
 		return -EINVAL;
@@ -1325,7 +1380,9 @@ static int ffa_notifications_setup(void)
 	hash_init(drv_info->notifier_hash);
 	mutex_init(&drv_info->notify_lock);
 
-	return 0;
+	/* Register internal scheduling callback */
+	return ffa_sched_recv_cb_update(drv_info->vm_id,
+					ffa_self_notif_handle, drv_info, true);
 cleanup:
 	ffa_notifications_cleanup();
 	return ret;

-- 
2.41.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ