mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-18 01:34:14 +08:00
[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:
parent
7d318d7747
commit
7644143cd6
@ -54,9 +54,12 @@ void mce_log(struct mce *mce)
|
|||||||
{
|
{
|
||||||
unsigned next, entry;
|
unsigned next, entry;
|
||||||
mce->finished = 0;
|
mce->finished = 0;
|
||||||
smp_wmb();
|
wmb();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
entry = rcu_dereference(mcelog.next);
|
entry = rcu_dereference(mcelog.next);
|
||||||
|
/* The rmb forces the compiler to reload next in each
|
||||||
|
iteration */
|
||||||
|
rmb();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* When the buffer fills up discard new entries. Assume
|
/* When the buffer fills up discard new entries. Assume
|
||||||
that the earlier errors are the more interesting. */
|
that the earlier errors are the more interesting. */
|
||||||
@ -69,6 +72,7 @@ void mce_log(struct mce *mce)
|
|||||||
entry++;
|
entry++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
smp_rmb();
|
smp_rmb();
|
||||||
next = entry + 1;
|
next = entry + 1;
|
||||||
@ -76,9 +80,9 @@ void mce_log(struct mce *mce)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
memcpy(mcelog.entry + entry, mce, sizeof(struct mce));
|
memcpy(mcelog.entry + entry, mce, sizeof(struct mce));
|
||||||
smp_wmb();
|
wmb();
|
||||||
mcelog.entry[entry].finished = 1;
|
mcelog.entry[entry].finished = 1;
|
||||||
smp_wmb();
|
wmb();
|
||||||
|
|
||||||
if (!test_and_set_bit(0, &console_logged))
|
if (!test_and_set_bit(0, &console_logged))
|
||||||
notify_user = 1;
|
notify_user = 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user