diff options
author | Bora Guvendik <bora.guvendik@intel.com> | 2017-01-04 16:51:31 -0800 |
---|---|---|
committer | Martin Roth <martinroth@google.com> | 2017-03-19 21:40:08 +0100 |
commit | 9b76f0b27bbdf4c214f1fe0fdbc81a153b5e9a95 (patch) | |
tree | 40a50da23d6872516629b50d3f9bdb30cfd34dde | |
parent | 4796c32ad60933bd8c23729684414121097b0445 (diff) | |
download | coreboot-9b76f0b27bbdf4c214f1fe0fdbc81a153b5e9a95.tar.xz |
cpu/x86: add a barrier with timeout
In case something goes wrong on one of the
cpus, add the ability to use a barrier with
timeout so that other cpus don't wait forever.
Remove static from barrier wait and release.
BUG=chrome-os-partner:59875
BRANCH=reef
TEST=None
Change-Id: Iab6bd30ddf7632c7a5785b338798960c26016b24
Signed-off-by: Bora Guvendik <bora.guvendik@intel.com>
Reviewed-on: https://review.coreboot.org/18107
Tested-by: build bot (Jenkins)
Reviewed-by: Martin Roth <martinroth@google.com>
-rw-r--r-- | src/cpu/x86/mp_init.c | 27 | ||||
-rw-r--r-- | src/include/cpu/x86/mp.h | 10 |
2 files changed, 35 insertions, 2 deletions
diff --git a/src/cpu/x86/mp_init.c b/src/cpu/x86/mp_init.c index 57a5648ad4..61f153ea3d 100644 --- a/src/cpu/x86/mp_init.c +++ b/src/cpu/x86/mp_init.c @@ -138,14 +138,37 @@ struct cpu_map { /* Keep track of APIC and device structure for each CPU. */ static struct cpu_map cpus[CONFIG_MAX_CPUS]; -static inline void barrier_wait(atomic_t *b) +inline void barrier_wait(atomic_t *b) { while (atomic_read(b) == 0) asm ("pause"); mfence(); } -static inline void release_barrier(atomic_t *b) +/* Returns 1 if timeout occurs before barier is released. + * returns 0 if barrier is released before timeout. */ +int barrier_wait_timeout(atomic_t *b, uint32_t timeout_ms) +{ + int timeout = 0; + struct mono_time current, end; + + timer_monotonic_get(¤t); + end = current; + mono_time_add_msecs(&end, timeout_ms); + + while ((atomic_read(b) == 0) && (!mono_time_after(¤t, &end))) { + timer_monotonic_get(¤t); + asm ("pause"); + } + mfence(); + + if (mono_time_after(¤t, &end)) + timeout = 1; + + return timeout; +} + +inline void release_barrier(atomic_t *b) { mfence(); atomic_set(b, 1); diff --git a/src/include/cpu/x86/mp.h b/src/include/cpu/x86/mp.h index b9b4d5772c..0671b62551 100644 --- a/src/include/cpu/x86/mp.h +++ b/src/include/cpu/x86/mp.h @@ -150,5 +150,15 @@ int mp_park_aps(void); void smm_initiate_relocation_parallel(void); /* Send SMI to self with single execution. */ void smm_initiate_relocation(void); +/* Make a CPU wait until the barrier is released */ +void barrier_wait(atomic_t *b); +/* + * Make a CPU wait until the barrier is released, or timeout occurs + * returns 1 if timeout occurs before barier is released. + * returns 0 if barrier is released before timeout. + */ +int barrier_wait_timeout(atomic_t *b, uint32_t timeout_ms); +/* Release a barrier so that other CPUs waiting for that barrier can continue */ +void release_barrier(atomic_t *b); #endif /* _X86_MP_H_ */ |