aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBorislav Petkov <borislav.petkov@amd.com>2011-12-08 06:28:33 -0500
committerBorislav Petkov <bp@amd64.org>2011-12-14 06:50:13 -0500
commit0937195715713b37ec843f28d99930dd7b1e8fbe (patch)
tree11a96986c1768fd117f95267371db27895d487d2
parent3653ada5d3e173489b3a466305687cb5c44b2ab1 (diff)
x86, MCE: Drain mcelog buffer
Add a function which drains whatever MCEs were logged in already during boot and before the decoder chains were registered. Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index c3c66ac6ef74..5be2464cce6a 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -189,9 +189,48 @@ void mce_log(struct mce *mce)
189 set_bit(0, &mce_need_notify); 189 set_bit(0, &mce_need_notify);
190} 190}
191 191
192static void drain_mcelog_buffer(void)
193{
194 unsigned int next, i, prev = 0;
195
196 next = rcu_dereference_check_mce(mcelog.next);
197
198 do {
199 struct mce *m;
200
201 /* drain what was logged during boot */
202 for (i = prev; i < next; i++) {
203 unsigned long start = jiffies;
204 unsigned retries = 1;
205
206 m = &mcelog.entry[i];
207
208 while (!m->finished) {
209 if (time_after_eq(jiffies, start + 2*retries))
210 retries++;
211
212 cpu_relax();
213
214 if (!m->finished && retries >= 4) {
215 pr_err("MCE: skipping error being logged currently!\n");
216 break;
217 }
218 }
219 smp_rmb();
220 atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, m);
221 }
222
223 memset(mcelog.entry + prev, 0, (next - prev) * sizeof(*m));
224 prev = next;
225 next = cmpxchg(&mcelog.next, prev, 0);
226 } while (next != prev);
227}
228
229
192void mce_register_decode_chain(struct notifier_block *nb) 230void mce_register_decode_chain(struct notifier_block *nb)
193{ 231{
194 atomic_notifier_chain_register(&x86_mce_decoder_chain, nb); 232 atomic_notifier_chain_register(&x86_mce_decoder_chain, nb);
233 drain_mcelog_buffer();
195} 234}
196EXPORT_SYMBOL_GPL(mce_register_decode_chain); 235EXPORT_SYMBOL_GPL(mce_register_decode_chain);
197 236