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: <20251008190907.181412-4-vvidwans@nvidia.com>
Date: Wed, 8 Oct 2025 19:09:07 +0000
From: Vedashree Vidwans <vvidwans@...dia.com>
To: <salman.nabi@....com>, <lpieralisi@...nel.org>, <mark.rutland@....com>,
	<sudeep.holla@....com>, <andre.przywara@....com>
CC: <ardb@...nel.org>, <chao.gao@...el.com>,
	<linux-arm-kernel@...ts.infradead.org>, <linux-coco@...ts.linux.dev>,
	<linux-kernel@...r.kernel.org>, <sdonthineni@...dia.com>,
	<vsethi@...dia.com>, <vwadekar@...dia.com>, Vedashree Vidwans
	<vvidwans@...dia.com>
Subject: [RFC PATCH 3/3] firmware: smccc: LFA: modify activation approach

Currently, on a LFA IRQ, all activable firmware components are primed
activated sequentially. Modify the approach to prime all firmware
components followed by activation of all components sequentially. This
approach will minimize the time where old and new firmware component
images co-exist.

Signed-off-by: Vedashree Vidwans <vvidwans@...dia.com>
---
 drivers/firmware/smccc/lfa_fw.c | 74 +++++++++++++++++++++++++++++----
 1 file changed, 66 insertions(+), 8 deletions(-)

diff --git a/drivers/firmware/smccc/lfa_fw.c b/drivers/firmware/smccc/lfa_fw.c
index b36b8d7457c30..dead2282cd04b 100644
--- a/drivers/firmware/smccc/lfa_fw.c
+++ b/drivers/firmware/smccc/lfa_fw.c
@@ -46,6 +46,10 @@
 #define LFA_PRIME_CALL_AGAIN		BIT(0)
 #define LFA_ACTIVATE_CALL_AGAIN		BIT(0)
 
+/* PRIME COMPLETE status */
+#define LFA_PRIME_COMPLETE_FALSE	false
+#define LFA_PRIME_COMPLETE_TRUE		true
+
 /* Prime loop limits, TODO: tune after testing */
 #define LFA_PRIME_BUDGET_US		30000000 /* 30s cap */
 #define LFA_PRIME_POLL_DELAY_US		10       /* 10us between polls */
@@ -104,6 +108,7 @@ struct image_props {
 	bool may_reset_cpu;
 	bool cpu_rendezvous;
 	bool cpu_rendezvous_forced;
+	bool prime_complete;
 	struct kobject *image_dir;
 	struct kobj_attribute image_attrs[LFA_ATTR_NR_IMAGES];
 };
@@ -229,6 +234,27 @@ static int call_lfa_activate(void *data)
 }
 
 static int activate_fw_image(struct image_props *attrs)
+{
+	int ret;
+
+	/*
+	 * We want to force CPU rendezvous if either cpu_rendezvous or
+	 * cpu_rendezvous_forced is set. The flag value is flipped as
+	 * it is called skip_cpu_rendezvous in the spec.
+	 */
+	if (!(attrs->cpu_rendezvous_forced || attrs->cpu_rendezvous)) {
+		pr_warn("CPU rendezvous is expected to be selected.");
+		return -EAGAIN;
+	}
+
+	ret = stop_machine(call_lfa_activate, attrs, cpu_online_mask);
+	if (ret != 0)
+		return lfa_cancel(attrs);
+
+	return ret;
+}
+
+static int prime_fw_image(struct image_props *attrs)
 {
 	struct arm_smccc_1_2_regs args = { 0 };
 	struct arm_smccc_1_2_regs res = { 0 };
@@ -285,10 +311,6 @@ static int activate_fw_image(struct image_props *attrs)
 			return ret;
 	}
 
-	ret = stop_machine(call_lfa_activate, attrs, cpu_online_mask);
-	if (ret != 0)
-		return lfa_cancel(attrs);
-
 	return ret;
 }
 
@@ -396,6 +418,17 @@ static ssize_t activate_store(struct kobject *kobj, struct kobj_attribute *attr,
 		return -EAGAIN;
 	}
 
+	ret = prime_fw_image(attrs);
+	if (ret) {
+		pr_err("Firmware prime failed: %s\n",
+			lfa_error_strings[-ret]);
+		mutex_unlock(&lfa_lock);
+		return -ECANCELED;
+	}
+
+	/* Update prime complete status */
+	attrs->prime_complete = LFA_PRIME_COMPLETE_TRUE;
+
 	ret = activate_fw_image(attrs);
 	if (ret) {
 		pr_err("Firmware activation failed: %s\n",
@@ -469,6 +502,8 @@ static int create_fw_inventory(char *fw_uuid, int seq_id, u32 image_flags)
 	INIT_LIST_HEAD(&attrs->image_node);
 	attrs->image_name = image_name;
 	attrs->cpu_rendezvous_forced = 1;
+	/* Reset prime complete status */
+	attrs->prime_complete = LFA_PRIME_COMPLETE_FALSE;
 	set_image_flags(attrs, seq_id, image_flags);
 
 	/*
@@ -573,16 +608,39 @@ static irqreturn_t lfa_irq_thread(int irq, void *data)
 	if (ret != 0)
 		goto exit_unlock;
 
-	/*
-	 * Execute PRIME and ACTIVATE for each FW component
-	 * Start from first FW component
-	 */
+	/* Execute PRIME for all FW components */
 	list_for_each_entry(attrs, &lfa_fw_images, image_node) {
 		if ((!attrs->activation_capable) || (!attrs->activation_pending)) {
 			/* LFA not applicable for this FW component, continue to next component */
 			continue;
 		}
 
+		ret = prime_fw_image(attrs);
+		if (ret) {
+			pr_err("Firmware %s prime failed: %s\n",
+				attrs->image_name, lfa_error_strings[-ret]);
+			goto exit_unlock;
+		}
+
+		/* Update prime complete status */
+		attrs->prime_complete = LFA_PRIME_COMPLETE_TRUE;
+	}
+
+	/* Execute ACTIVATE for all FW components */
+	list_for_each_entry(attrs, &lfa_fw_images, image_node) {
+		if ((!attrs->activation_capable) || (!attrs->activation_pending)) {
+			/* LFA not applicable for this FW component, continue to next component */
+			continue;
+		}
+
+		if (!attrs->prime_complete) {
+			/*
+			 * ACTIVATE not applicable for this FW component,
+			 * continue to next component
+			 */
+			continue;
+		}
+
 		ret = activate_fw_image(attrs);
 		if (ret) {
 			pr_err("Firmware %s activation failed: %s\n",
-- 
2.25.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ