[coreboot-gerrit] Change in coreboot[master]: cpu/x86: Add support to run function with argument over APs

Subrata Banik (Code Review) gerrit at coreboot.org
Wed Apr 18 12:59:49 CEST 2018


Subrata Banik has uploaded this change for review. ( https://review.coreboot.org/25725


Change subject: cpu/x86: Add support to run function with argument over APs
......................................................................

cpu/x86: Add support to run function with argument over APs

This patch ensures that user can pass a function with given argument
list to execute over APs.

BUG=b:74436746
BRANCH=none
TEST=Able to run functions over APs with argument.

Change-Id: I668b36752f6b21cb99cd1416c385d53e96117213
Signed-off-by: Subrata Banik <subrata.banik at intel.com>
---
M src/cpu/x86/mp_init.c
M src/include/cpu/x86/mp.h
2 files changed, 106 insertions(+), 24 deletions(-)



  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/25/25725/1

diff --git a/src/cpu/x86/mp_init.c b/src/cpu/x86/mp_init.c
index 18b2c1e..e8b0683 100644
--- a/src/cpu/x86/mp_init.c
+++ b/src/cpu/x86/mp_init.c
@@ -41,7 +41,13 @@
 #define MAX_APIC_IDS 256
 
 typedef void (*mp_callback_t)(void);
+typedef void (*mp_callback_arg_t)(void *data);
 
+struct mp_callback_arg_config {
+	uintptr_t function_arg;
+};
+
+struct mp_callback_arg_config mp_arg_list[CONFIG_MAX_CPUS];
 /*
  * A mp_flight_record details a sequence of calls for the APs to perform
  * along with the BSP to coordinate sequencing. Each flight record either
@@ -600,8 +606,14 @@
 	info = cpu_info();
 	info->cpu = alloc_find_dev(cpu_bus, &cpu_path);
 
-	if (info->index != 0)
+	if (info->index != 0) {
 		printk(BIOS_CRIT, "BSP index(%d) != 0!\n", info->index);
+		if (cpu_path.apic.apic_id == 0) {
+			info->index = 0;
+			printk(BIOS_CRIT, "Seting correct BSP index %x\n",
+					info->index);
+		}
+	}
 
 	/* Track BSP in cpu_map structures. */
 	add_cpu_map_entry(info);
@@ -936,6 +948,7 @@
 }
 
 static mp_callback_t ap_callbacks[CONFIG_MAX_CPUS];
+static mp_callback_arg_t ap_callbacks_arg[CONFIG_MAX_CPUS];
 
 static mp_callback_t read_callback(mp_callback_t *slot)
 {
@@ -947,7 +960,19 @@
 	*(volatile mp_callback_t *)slot = value;
 }
 
-static int execute_callback_on_ap(void)
+static mp_callback_arg_t read_callback_arg(mp_callback_arg_t *slot)
+{
+	return *(volatile mp_callback_arg_t *)slot;
+}
+
+static void store_callback_arg(mp_callback_arg_t *slot, mp_callback_arg_t
+		value, int index, void *arg)
+{
+	*(volatile mp_callback_arg_t *)slot = value;
+	mp_arg_list[index].function_arg = (uintptr_t)arg;
+}
+
+static int execute_callback_on_ap(void *arg)
 {
 	int cpus_accepted;
 	int i;
@@ -955,17 +980,25 @@
 
 	cpus_accepted = 0;
 
-	for (i = 0; i < ARRAY_SIZE(ap_callbacks); i++) {
-		if (cur_cpu == i)
-			continue;
-		if (read_callback(&ap_callbacks[i]) == NULL)
-			cpus_accepted++;
+	if (arg == NULL) {
+		for (i = 0; i < ARRAY_SIZE(ap_callbacks); i++) {
+			if (cur_cpu == i)
+				continue;
+			if (read_callback(&ap_callbacks[i]) == NULL)
+				cpus_accepted++;
+		}
+	} else {
+		for (i = 0; i < ARRAY_SIZE(ap_callbacks_arg); i++) {
+			if (cur_cpu == i)
+				continue;
+			if (read_callback_arg(&ap_callbacks_arg[i]) == NULL)
+				cpus_accepted++;
+		}
 	}
-
 	return cpus_accepted;
 }
 
-static int run_ap_work(mp_callback_t func, long expire_us)
+static int run_ap_work(mp_callback_t func, long expire_us, void *arg)
 {
 	int i;
 	int cpus_accepted;
@@ -977,11 +1010,20 @@
 		return -1;
 	}
 
-	/* Signal to all the APs to run the func. */
-	for (i = 0; i < ARRAY_SIZE(ap_callbacks); i++) {
-		if (cur_cpu == i)
-			continue;
-		store_callback(&ap_callbacks[i], func);
+	if (arg == NULL) {
+		/* Signal to all the APs to run the func. */
+		for (i = 0; i < ARRAY_SIZE(ap_callbacks); i++) {
+			if (cur_cpu == i)
+				continue;
+			store_callback(&ap_callbacks[i], func);
+		}
+	} else {
+		for (i = 0; i < ARRAY_SIZE(ap_callbacks_arg); i++) {
+			if (cur_cpu == i)
+				continue;
+			store_callback_arg(&ap_callbacks_arg[i],
+					(mp_callback_arg_t)func, i, arg);
+		}
 	}
 	mfence();
 
@@ -992,14 +1034,14 @@
 		 */
 		stopwatch_init_usecs_expire(&sw, expire_us);
 		do {
-			cpus_accepted = execute_callback_on_ap();
+			cpus_accepted = execute_callback_on_ap(arg);
 			if (cpus_accepted == global_num_aps)
 				return 0;
 		} while (!stopwatch_expired(&sw));
 	} else {
 		/* Wait for all the APs to signal back with no timeout */
 		do {
-			cpus_accepted = execute_callback_on_ap();
+			cpus_accepted = execute_callback_on_ap(arg);
 			if (cpus_accepted == global_num_aps)
 				return 0;
 		} while (1);
@@ -1012,27 +1054,42 @@
 static void ap_wait_for_instruction(void)
 {
 	int cur_cpu = cpu_index();
+	void *arg;
 
 	if (!IS_ENABLED(CONFIG_PARALLEL_MP_AP_WORK))
 		return;
 
 	while (1) {
 		mp_callback_t func = read_callback(&ap_callbacks[cur_cpu]);
+		mp_callback_arg_t func_arg = read_callback_arg(
+				&ap_callbacks_arg[cur_cpu]);
 
-		if (func == NULL) {
-			asm ("pause");
-			continue;
+		arg = (void *)mp_arg_list[cur_cpu].function_arg;
+		if (arg == NULL) {
+			if (func == NULL) {
+				asm ("pause");
+				continue;
+			}
+
+			store_callback(&ap_callbacks[cur_cpu], NULL);
+			mfence();
+			func();
+		} else {
+			if (func_arg == NULL) {
+				asm ("pause");
+				continue;
+			}
+			store_callback_arg(&ap_callbacks_arg[cur_cpu], NULL,
+				cur_cpu, NULL);
+			mfence();
+			func_arg(arg);
 		}
-
-		store_callback(&ap_callbacks[cur_cpu], NULL);
-		mfence();
-		func();
 	}
 }
 
 int mp_run_on_aps(void (*func)(void), long expire_us)
 {
-	return run_ap_work(func, expire_us);
+	return run_ap_work(func, expire_us, NULL);
 }
 
 int mp_run_on_all_cpus(void (*func)(void), long expire_us)
@@ -1042,6 +1099,18 @@
 	return mp_run_on_aps(func, expire_us);
 }
 
+int mp_run_on_aps_arg(void (*func)(void *data), long expire_us, void *arg)
+{
+	return run_ap_work((mp_callback_t)func, expire_us, arg);
+}
+
+int mp_run_on_all_cpus_arg(void (*func)(void *data), long expire_us, void *arg)
+{
+	/* Run on BSP first. */
+	func(arg);
+	return mp_run_on_aps_arg(func, expire_us, arg);
+}
+
 int mp_park_aps(void)
 {
 	struct stopwatch sw;
diff --git a/src/include/cpu/x86/mp.h b/src/include/cpu/x86/mp.h
index 04fba6a..84a1735 100644
--- a/src/include/cpu/x86/mp.h
+++ b/src/include/cpu/x86/mp.h
@@ -143,6 +143,19 @@
 int mp_run_on_all_cpus(void (*func)(void), long expire_us);
 
 /*
+ * After APs are up and PARALLEL_MP_AP_WORK is enabled one can issue work
+ * to all the APs to perform. Currently the BSP is the only CPU that is allowed
+ * to issue work. i.e. the APs should not call any of these functions.
+ *
+ * BSP should call this function after passing argument.
+ * All functions return < 0 on error, 0 on success.
+ */
+int mp_run_on_aps_arg(void (*func)(void *data), long expire_us, void *arg);
+
+/* Like mp_run_on_aps_arg() but also runs func on BSP. */
+int mp_run_on_all_cpus_arg(void (*func)(void *data), long expire_us, void *arg);
+
+/*
  * Park all APs to prepare for OS boot. This is handled automatically
  * by the coreboot infrastructure.
  */

-- 
To view, visit https://review.coreboot.org/25725
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I668b36752f6b21cb99cd1416c385d53e96117213
Gerrit-Change-Number: 25725
Gerrit-PatchSet: 1
Gerrit-Owner: Subrata Banik <subrata.banik at intel.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20180418/db636e20/attachment-0001.html>


More information about the coreboot-gerrit mailing list