cmos post: Guard with spinlock
The CMOS post code storage mechanism does back-to-back CMOS reads and writes that may be interleaved during CPU bringup, leading to corruption of the log or of other parts of CMOS. Change-Id: I704813cc917a659fe034b71c2ff9eb9b80f7c949 Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/58102 Reviewed-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/4227 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
parent
35bd3fedfe
commit
e807c34a5e
|
@ -1,6 +1,8 @@
|
||||||
#ifndef ARCH_SMP_SPINLOCK_H
|
#ifndef ARCH_SMP_SPINLOCK_H
|
||||||
#define ARCH_SMP_SPINLOCK_H
|
#define ARCH_SMP_SPINLOCK_H
|
||||||
|
|
||||||
|
#ifndef __PRE_RAM__
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Your basic SMP spinlocks, allowing only a single CPU anywhere
|
* Your basic SMP spinlocks, allowing only a single CPU anywhere
|
||||||
*/
|
*/
|
||||||
|
@ -61,4 +63,16 @@ static inline __attribute__((always_inline)) void cpu_relax(void)
|
||||||
__asm__ __volatile__("rep;nop": : :"memory");
|
__asm__ __volatile__("rep;nop": : :"memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* !__PRE_RAM__ */
|
||||||
|
|
||||||
|
#define DECLARE_SPIN_LOCK(x)
|
||||||
|
#define barrier() do {} while(0)
|
||||||
|
#define spin_is_locked(lock) 0
|
||||||
|
#define spin_unlock_wait(lock) do {} while(0)
|
||||||
|
#define spin_lock(lock) do {} while(0)
|
||||||
|
#define spin_unlock(lock) do {} while(0)
|
||||||
|
#define cpu_relax() do {} while(0)
|
||||||
|
|
||||||
|
#endif /* !__PRE_RAM__ */
|
||||||
|
|
||||||
#endif /* ARCH_SMP_SPINLOCK_H */
|
#endif /* ARCH_SMP_SPINLOCK_H */
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#if CONFIG_CMOS_POST
|
#if CONFIG_CMOS_POST
|
||||||
#include <pc80/mc146818rtc.h>
|
#include <pc80/mc146818rtc.h>
|
||||||
|
#include <smp/spinlock.h>
|
||||||
#endif
|
#endif
|
||||||
#include <elog.h>
|
#include <elog.h>
|
||||||
|
|
||||||
|
@ -44,10 +45,14 @@ void __attribute__((weak)) mainboard_post(uint8_t value)
|
||||||
|
|
||||||
#if CONFIG_CMOS_POST
|
#if CONFIG_CMOS_POST
|
||||||
|
|
||||||
|
DECLARE_SPIN_LOCK(cmos_post_lock)
|
||||||
|
|
||||||
#if !defined(__PRE_RAM__)
|
#if !defined(__PRE_RAM__)
|
||||||
void cmos_post_log(void)
|
void cmos_post_log(void)
|
||||||
{
|
{
|
||||||
u8 code;
|
u8 code = 0;
|
||||||
|
|
||||||
|
spin_lock(&cmos_post_lock);
|
||||||
|
|
||||||
/* Get post code from other bank */
|
/* Get post code from other bank */
|
||||||
switch (cmos_read(CMOS_POST_BANK_OFFSET)) {
|
switch (cmos_read(CMOS_POST_BANK_OFFSET)) {
|
||||||
|
@ -57,10 +62,10 @@ void cmos_post_log(void)
|
||||||
case CMOS_POST_BANK_1_MAGIC:
|
case CMOS_POST_BANK_1_MAGIC:
|
||||||
code = cmos_read(CMOS_POST_BANK_0_OFFSET);
|
code = cmos_read(CMOS_POST_BANK_0_OFFSET);
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_unlock(&cmos_post_lock);
|
||||||
|
|
||||||
/* Check last post code in previous boot against normal list */
|
/* Check last post code in previous boot against normal list */
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case POST_OS_BOOT:
|
case POST_OS_BOOT:
|
||||||
|
@ -80,6 +85,8 @@ void cmos_post_log(void)
|
||||||
|
|
||||||
static void cmos_post_code(u8 value)
|
static void cmos_post_code(u8 value)
|
||||||
{
|
{
|
||||||
|
spin_lock(&cmos_post_lock);
|
||||||
|
|
||||||
switch (cmos_read(CMOS_POST_BANK_OFFSET)) {
|
switch (cmos_read(CMOS_POST_BANK_OFFSET)) {
|
||||||
case CMOS_POST_BANK_0_MAGIC:
|
case CMOS_POST_BANK_0_MAGIC:
|
||||||
cmos_write(value, CMOS_POST_BANK_0_OFFSET);
|
cmos_write(value, CMOS_POST_BANK_0_OFFSET);
|
||||||
|
@ -88,6 +95,8 @@ static void cmos_post_code(u8 value)
|
||||||
cmos_write(value, CMOS_POST_BANK_1_OFFSET);
|
cmos_write(value, CMOS_POST_BANK_1_OFFSET);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_unlock(&cmos_post_lock);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_CMOS_POST */
|
#endif /* CONFIG_CMOS_POST */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue