Kane Chen has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/63566 )
Change subject: cpu/x86/mp_init.c: Add wait_finished_mp_run_on_all_cpus ......................................................................
cpu/x86/mp_init.c: Add wait_finished_mp_run_on_all_cpus
This patch adds a parameter wait_ap_complete in mp_callback to decide when APs call store_callback to notify BSP it already takes jobs. This can allow the caller to decide whether it should wait all APs to continue or not.
Change-Id: I8d1d49bca410c821a3ad0347548afc42eb860594 Signed-off-by: Kane Chen kane.chen@intel.corp-partner.google.com Co-authored-by: Arthur Heymans arthur@aheymans.xyz --- M src/cpu/x86/mp_init.c M src/include/cpu/x86/mp.h 2 files changed, 34 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/66/63566/1
diff --git a/src/cpu/x86/mp_init.c b/src/cpu/x86/mp_init.c index 81c987b..28febdc 100644 --- a/src/cpu/x86/mp_init.c +++ b/src/cpu/x86/mp_init.c @@ -33,6 +33,7 @@ void (*func)(void *); void *arg; int logical_cpu_number; + bool wait_ap_complete; };
static char processor_name[49]; @@ -960,12 +961,15 @@ /* Copy to local variable before signaling consumption. */ memcpy(&lcb, cb, sizeof(lcb)); mfence(); - store_callback(per_cpu_slot, NULL); + if (!lcb.wait_ap_complete) + store_callback(per_cpu_slot, NULL); if (lcb.logical_cpu_number && (cur_cpu != lcb.logical_cpu_number)) continue; else lcb.func(lcb.arg); + if (lcb.wait_ap_complete) + store_callback(per_cpu_slot, NULL); } }
@@ -977,6 +981,15 @@ return run_ap_work(&lcb, expire_us); }
+enum cb_err mp_run_on_aps_and_wait_for_complete(void (*func)(void *), void *arg, + int logical_cpu_num, long expire_us) +{ + struct mp_callback lcb = { .func = func, .arg = arg, + .logical_cpu_number = logical_cpu_num, + .wait_ap_complete = true}; + return run_ap_work(&lcb, expire_us); +} + enum cb_err mp_run_on_all_aps(void (*func)(void *), void *arg, long expire_us, bool run_parallel) { @@ -1009,6 +1022,16 @@ return mp_run_on_aps(func, arg, MP_RUN_ON_ALL_CPUS, 1000 * USECS_PER_MSEC); }
+enum cb_err wait_finished_mp_run_on_all_cpus(void (*func)(void *), void *arg) +{ + /* Run on BSP first. */ + func(arg); + + /* For up to 1 second for AP to finish previous work. */ + return mp_run_on_aps_and_wait_for_complete(func, arg, MP_RUN_ON_ALL_CPUS, + 1000 * USECS_PER_MSEC); +} + enum cb_err mp_park_aps(void) { struct stopwatch sw; diff --git a/src/include/cpu/x86/mp.h b/src/include/cpu/x86/mp.h index 1b4c956..2324c48 100644 --- a/src/include/cpu/x86/mp.h +++ b/src/include/cpu/x86/mp.h @@ -106,6 +106,12 @@ */ enum cb_err mp_run_on_aps(void (*func)(void *), void *arg, int logical_cpu_num, long expire_us); +/* + * This function is similar to mp_run_on_aps but the BSP will wait for all APs + * to complete the assigned tasks and continue + */ +enum cb_err mp_run_on_aps_and_wait_for_complete(void (*func)(void *), void *arg, + int logical_cpu_num, long expire_us);
/* * Runs func on all APs excluding BSP, with a provision to run calls in parallel @@ -117,6 +123,10 @@ /* Like mp_run_on_aps() but also runs func on BSP. */ enum cb_err mp_run_on_all_cpus(void (*func)(void *), void *arg);
+/* Like mp_run_on_all_cpus but make sure all APs finish executing the + function call. The time limit on a function call is 1 second. */ +enum cb_err wait_finished_mp_run_on_all_cpus(void (*func)(void *), void *arg); + /* * Park all APs to prepare for OS boot. This is handled automatically * by the coreboot infrastructure.