<p>Subrata Banik has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/25725">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">cpu/x86: Add support to run function with argument over APs<br><br>This patch ensures that user can pass a function with given argument<br>list to execute over APs.<br><br>BUG=b:74436746<br>BRANCH=none<br>TEST=Able to run functions over APs with argument.<br><br>Change-Id: I668b36752f6b21cb99cd1416c385d53e96117213<br>Signed-off-by: Subrata Banik <subrata.banik@intel.com><br>---<br>M src/cpu/x86/mp_init.c<br>M src/include/cpu/x86/mp.h<br>2 files changed, 106 insertions(+), 24 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/25/25725/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/cpu/x86/mp_init.c b/src/cpu/x86/mp_init.c</span><br><span>index 18b2c1e..e8b0683 100644</span><br><span>--- a/src/cpu/x86/mp_init.c</span><br><span>+++ b/src/cpu/x86/mp_init.c</span><br><span>@@ -41,7 +41,13 @@</span><br><span> #define MAX_APIC_IDS 256</span><br><span> </span><br><span> typedef void (*mp_callback_t)(void);</span><br><span style="color: hsl(120, 100%, 40%);">+typedef void (*mp_callback_arg_t)(void *data);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct mp_callback_arg_config {</span><br><span style="color: hsl(120, 100%, 40%);">+       uintptr_t function_arg;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct mp_callback_arg_config mp_arg_list[CONFIG_MAX_CPUS];</span><br><span> /*</span><br><span>  * A mp_flight_record details a sequence of calls for the APs to perform</span><br><span>  * along with the BSP to coordinate sequencing. Each flight record either</span><br><span>@@ -600,8 +606,14 @@</span><br><span>     info = cpu_info();</span><br><span>   info->cpu = alloc_find_dev(cpu_bus, &cpu_path);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      if (info->index != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+      if (info->index != 0) {</span><br><span>           printk(BIOS_CRIT, "BSP index(%d) != 0!\n", info->index);</span><br><span style="color: hsl(120, 100%, 40%);">+         if (cpu_path.apic.apic_id == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     info->index = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                   printk(BIOS_CRIT, "Seting correct BSP index %x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                  info->index);</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span> </span><br><span>        /* Track BSP in cpu_map structures. */</span><br><span>       add_cpu_map_entry(info);</span><br><span>@@ -936,6 +948,7 @@</span><br><span> }</span><br><span> </span><br><span> static mp_callback_t ap_callbacks[CONFIG_MAX_CPUS];</span><br><span style="color: hsl(120, 100%, 40%);">+static mp_callback_arg_t ap_callbacks_arg[CONFIG_MAX_CPUS];</span><br><span> </span><br><span> static mp_callback_t read_callback(mp_callback_t *slot)</span><br><span> {</span><br><span>@@ -947,7 +960,19 @@</span><br><span>       *(volatile mp_callback_t *)slot = value;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int execute_callback_on_ap(void)</span><br><span style="color: hsl(120, 100%, 40%);">+static mp_callback_arg_t read_callback_arg(mp_callback_arg_t *slot)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      return *(volatile mp_callback_arg_t *)slot;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void store_callback_arg(mp_callback_arg_t *slot, mp_callback_arg_t</span><br><span style="color: hsl(120, 100%, 40%);">+           value, int index, void *arg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       *(volatile mp_callback_arg_t *)slot = value;</span><br><span style="color: hsl(120, 100%, 40%);">+  mp_arg_list[index].function_arg = (uintptr_t)arg;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int execute_callback_on_ap(void *arg)</span><br><span> {</span><br><span>    int cpus_accepted;</span><br><span>   int i;</span><br><span>@@ -955,17 +980,25 @@</span><br><span> </span><br><span>   cpus_accepted = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  for (i = 0; i < ARRAY_SIZE(ap_callbacks); i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-             if (cur_cpu == i)</span><br><span style="color: hsl(0, 100%, 40%);">-                       continue;</span><br><span style="color: hsl(0, 100%, 40%);">-               if (read_callback(&ap_callbacks[i]) == NULL)</span><br><span style="color: hsl(0, 100%, 40%);">-                        cpus_accepted++;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (arg == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+            for (i = 0; i < ARRAY_SIZE(ap_callbacks); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   if (cur_cpu == i)</span><br><span style="color: hsl(120, 100%, 40%);">+                             continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (read_callback(&ap_callbacks[i]) == NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+                              cpus_accepted++;</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              for (i = 0; i < ARRAY_SIZE(ap_callbacks_arg); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (cur_cpu == i)</span><br><span style="color: hsl(120, 100%, 40%);">+                             continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (read_callback_arg(&ap_callbacks_arg[i]) == NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+                              cpus_accepted++;</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span>    }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>    return cpus_accepted;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int run_ap_work(mp_callback_t func, long expire_us)</span><br><span style="color: hsl(120, 100%, 40%);">+static int run_ap_work(mp_callback_t func, long expire_us, void *arg)</span><br><span> {</span><br><span>         int i;</span><br><span>       int cpus_accepted;</span><br><span>@@ -977,11 +1010,20 @@</span><br><span>          return -1;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* Signal to all the APs to run the func. */</span><br><span style="color: hsl(0, 100%, 40%);">-    for (i = 0; i < ARRAY_SIZE(ap_callbacks); i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-             if (cur_cpu == i)</span><br><span style="color: hsl(0, 100%, 40%);">-                       continue;</span><br><span style="color: hsl(0, 100%, 40%);">-               store_callback(&ap_callbacks[i], func);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (arg == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Signal to all the APs to run the func. */</span><br><span style="color: hsl(120, 100%, 40%);">+          for (i = 0; i < ARRAY_SIZE(ap_callbacks); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   if (cur_cpu == i)</span><br><span style="color: hsl(120, 100%, 40%);">+                             continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                     store_callback(&ap_callbacks[i], func);</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              for (i = 0; i < ARRAY_SIZE(ap_callbacks_arg); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (cur_cpu == i)</span><br><span style="color: hsl(120, 100%, 40%);">+                             continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                     store_callback_arg(&ap_callbacks_arg[i],</span><br><span style="color: hsl(120, 100%, 40%);">+                                  (mp_callback_arg_t)func, i, arg);</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span>    }</span><br><span>    mfence();</span><br><span> </span><br><span>@@ -992,14 +1034,14 @@</span><br><span>                */</span><br><span>          stopwatch_init_usecs_expire(&sw, expire_us);</span><br><span>             do {</span><br><span style="color: hsl(0, 100%, 40%);">-                    cpus_accepted = execute_callback_on_ap();</span><br><span style="color: hsl(120, 100%, 40%);">+                     cpus_accepted = execute_callback_on_ap(arg);</span><br><span>                         if (cpus_accepted == global_num_aps)</span><br><span>                                 return 0;</span><br><span>            } while (!stopwatch_expired(&sw));</span><br><span>       } else {</span><br><span>             /* Wait for all the APs to signal back with no timeout */</span><br><span>            do {</span><br><span style="color: hsl(0, 100%, 40%);">-                    cpus_accepted = execute_callback_on_ap();</span><br><span style="color: hsl(120, 100%, 40%);">+                     cpus_accepted = execute_callback_on_ap(arg);</span><br><span>                         if (cpus_accepted == global_num_aps)</span><br><span>                                 return 0;</span><br><span>            } while (1);</span><br><span>@@ -1012,27 +1054,42 @@</span><br><span> static void ap_wait_for_instruction(void)</span><br><span> {</span><br><span>     int cur_cpu = cpu_index();</span><br><span style="color: hsl(120, 100%, 40%);">+    void *arg;</span><br><span> </span><br><span>       if (!IS_ENABLED(CONFIG_PARALLEL_MP_AP_WORK))</span><br><span>                 return;</span><br><span> </span><br><span>  while (1) {</span><br><span>          mp_callback_t func = read_callback(&ap_callbacks[cur_cpu]);</span><br><span style="color: hsl(120, 100%, 40%);">+               mp_callback_arg_t func_arg = read_callback_arg(</span><br><span style="color: hsl(120, 100%, 40%);">+                               &ap_callbacks_arg[cur_cpu]);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-            if (func == NULL) {</span><br><span style="color: hsl(0, 100%, 40%);">-                     asm ("pause");</span><br><span style="color: hsl(0, 100%, 40%);">-                        continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             arg = (void *)mp_arg_list[cur_cpu].function_arg;</span><br><span style="color: hsl(120, 100%, 40%);">+              if (arg == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    if (func == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+                           asm ("pause");</span><br><span style="color: hsl(120, 100%, 40%);">+                              continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   store_callback(&ap_callbacks[cur_cpu], NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+                     mfence();</span><br><span style="color: hsl(120, 100%, 40%);">+                     func();</span><br><span style="color: hsl(120, 100%, 40%);">+               } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (func_arg == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+                               asm ("pause");</span><br><span style="color: hsl(120, 100%, 40%);">+                              continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                     }</span><br><span style="color: hsl(120, 100%, 40%);">+                     store_callback_arg(&ap_callbacks_arg[cur_cpu], NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+                              cur_cpu, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+                       mfence();</span><br><span style="color: hsl(120, 100%, 40%);">+                     func_arg(arg);</span><br><span>               }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               store_callback(&ap_callbacks[cur_cpu], NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-               mfence();</span><br><span style="color: hsl(0, 100%, 40%);">-               func();</span><br><span>      }</span><br><span> }</span><br><span> </span><br><span> int mp_run_on_aps(void (*func)(void), long expire_us)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-        return run_ap_work(func, expire_us);</span><br><span style="color: hsl(120, 100%, 40%);">+  return run_ap_work(func, expire_us, NULL);</span><br><span> }</span><br><span> </span><br><span> int mp_run_on_all_cpus(void (*func)(void), long expire_us)</span><br><span>@@ -1042,6 +1099,18 @@</span><br><span>   return mp_run_on_aps(func, expire_us);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int mp_run_on_aps_arg(void (*func)(void *data), long expire_us, void *arg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        return run_ap_work((mp_callback_t)func, expire_us, arg);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int mp_run_on_all_cpus_arg(void (*func)(void *data), long expire_us, void *arg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Run on BSP first. */</span><br><span style="color: hsl(120, 100%, 40%);">+       func(arg);</span><br><span style="color: hsl(120, 100%, 40%);">+    return mp_run_on_aps_arg(func, expire_us, arg);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int mp_park_aps(void)</span><br><span> {</span><br><span>   struct stopwatch sw;</span><br><span>diff --git a/src/include/cpu/x86/mp.h b/src/include/cpu/x86/mp.h</span><br><span>index 04fba6a..84a1735 100644</span><br><span>--- a/src/include/cpu/x86/mp.h</span><br><span>+++ b/src/include/cpu/x86/mp.h</span><br><span>@@ -143,6 +143,19 @@</span><br><span> int mp_run_on_all_cpus(void (*func)(void), long expire_us);</span><br><span> </span><br><span> /*</span><br><span style="color: hsl(120, 100%, 40%);">+ * After APs are up and PARALLEL_MP_AP_WORK is enabled one can issue work</span><br><span style="color: hsl(120, 100%, 40%);">+ * to all the APs to perform. Currently the BSP is the only CPU that is allowed</span><br><span style="color: hsl(120, 100%, 40%);">+ * to issue work. i.e. the APs should not call any of these functions.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * BSP should call this function after passing argument.</span><br><span style="color: hsl(120, 100%, 40%);">+ * All functions return < 0 on error, 0 on success.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int mp_run_on_aps_arg(void (*func)(void *data), long expire_us, void *arg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Like mp_run_on_aps_arg() but also runs func on BSP. */</span><br><span style="color: hsl(120, 100%, 40%);">+int mp_run_on_all_cpus_arg(void (*func)(void *data), long expire_us, void *arg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span>  * Park all APs to prepare for OS boot. This is handled automatically</span><br><span>  * by the coreboot infrastructure.</span><br><span>  */</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/25725">change 25725</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/25725"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I668b36752f6b21cb99cd1416c385d53e96117213 </div>
<div style="display:none"> Gerrit-Change-Number: 25725 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Subrata Banik <subrata.banik@intel.com> </div>