[PATCH] x86_64: Fix mce_log
The attempt to fixup the lockless mce log buffer introduced an infinite loop when trying to find a free entry. And: Using rcu_dereference() to load mcelog.next doesn't seem to be sufficient enough to ensure that mcelog.next is loaded each time around the loop in mce_log(). Instead, use an explicit rmb() to ensure that the compiler gets it right. AK: turned the smp_wmbs into true wmbs to make sure they are not reordered by the compiler on UP. Signed-off-by: Mike Waychison <mikew@google.com> Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Родитель
7d318d7747
Коммит
7644143cd6
|
@ -54,9 +54,12 @@ void mce_log(struct mce *mce)
|
|||
{
|
||||
unsigned next, entry;
|
||||
mce->finished = 0;
|
||||
smp_wmb();
|
||||
wmb();
|
||||
for (;;) {
|
||||
entry = rcu_dereference(mcelog.next);
|
||||
/* The rmb forces the compiler to reload next in each
|
||||
iteration */
|
||||
rmb();
|
||||
for (;;) {
|
||||
/* When the buffer fills up discard new entries. Assume
|
||||
that the earlier errors are the more interesting. */
|
||||
|
@ -69,6 +72,7 @@ void mce_log(struct mce *mce)
|
|||
entry++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
smp_rmb();
|
||||
next = entry + 1;
|
||||
|
@ -76,9 +80,9 @@ void mce_log(struct mce *mce)
|
|||
break;
|
||||
}
|
||||
memcpy(mcelog.entry + entry, mce, sizeof(struct mce));
|
||||
smp_wmb();
|
||||
wmb();
|
||||
mcelog.entry[entry].finished = 1;
|
||||
smp_wmb();
|
||||
wmb();
|
||||
|
||||
if (!test_and_set_bit(0, &console_logged))
|
||||
notify_user = 1;
|
||||
|
|
Загрузка…
Ссылка в новой задаче