summaryrefslogtreecommitdiff
path: root/arch/x86/cpu
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2020-07-17 17:48:21 +0300
committerBin Meng <bmeng.cn@gmail.com>2020-07-20 04:46:46 +0300
commit0538d6833cc61722ee506fab4609d9c1cf010491 (patch)
treee2f8957f458a8c32a4f6581e648281f9fc533353 /arch/x86/cpu
parent99a573fb326faf5a7bff50e4f9875f2066728d95 (diff)
downloadu-boot-0538d6833cc61722ee506fab4609d9c1cf010491.tar.xz
x86: mp: Add iterators for CPUs
It is convenient to iterate through the CPUs performing work on each one and processing the result. Add a few iterator functions which handle this. These can be used by any client code. It can call mp_run_on_cpus() on each CPU that is returned, handling them one at a time. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Wolfgang Wallner <wolfgang.wallner@br-automation.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'arch/x86/cpu')
-rw-r--r--arch/x86/cpu/mp_init.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c
index 427ec8fc23..c373c3099a 100644
--- a/arch/x86/cpu/mp_init.c
+++ b/arch/x86/cpu/mp_init.c
@@ -684,6 +684,69 @@ int mp_park_aps(void)
return 0;
}
+int mp_first_cpu(int cpu_select)
+{
+ struct udevice *dev;
+ int num_cpus;
+ int ret;
+
+ /*
+ * This assumes that CPUs are numbered from 0. This function tries to
+ * avoid assuming the CPU 0 is the boot CPU
+ */
+ if (cpu_select == MP_SELECT_ALL)
+ return 0; /* start with the first one */
+
+ ret = get_bsp(&dev, &num_cpus);
+ if (ret < 0)
+ return log_msg_ret("bsp", ret);
+
+ /* Return boot CPU if requested */
+ if (cpu_select == MP_SELECT_BSP)
+ return ret;
+
+ /* Return something other than the boot CPU, if APs requested */
+ if (cpu_select == MP_SELECT_APS && num_cpus > 1)
+ return ret == 0 ? 1 : 0;
+
+ /* Try to check for an invalid value */
+ if (cpu_select < 0 || cpu_select >= num_cpus)
+ return -EINVAL;
+
+ return cpu_select; /* return the only selected one */
+}
+
+int mp_next_cpu(int cpu_select, int prev_cpu)
+{
+ struct udevice *dev;
+ int num_cpus;
+ int ret;
+ int bsp;
+
+ /* If we selected the BSP or a particular single CPU, we are done */
+ if (!IS_ENABLED(CONFIG_SMP_AP_WORK) || cpu_select == MP_SELECT_BSP ||
+ cpu_select >= 0)
+ return -EFBIG;
+
+ /* Must be doing MP_SELECT_ALL or MP_SELECT_APS; return the next CPU */
+ ret = get_bsp(&dev, &num_cpus);
+ if (ret < 0)
+ return log_msg_ret("bsp", ret);
+ bsp = ret;
+
+ /* Move to the next CPU */
+ assert(prev_cpu >= 0);
+ ret = prev_cpu + 1;
+
+ /* Skip the BSP if needed */
+ if (cpu_select == MP_SELECT_APS && ret == bsp)
+ ret++;
+ if (ret >= num_cpus)
+ return -EFBIG;
+
+ return ret;
+}
+
int mp_init(void)
{
int num_aps, num_cpus;