ras.c (d47d1d8af52e37bcf9059dd86878474e5ccc9c2a) ras.c (d368514c3097a48a109b6ba64e12047106c7473d)
1/*
2 * Copyright (C) 2001 Dave Engebretsen IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *

--- 40 unchanged lines hidden (view full) ---

49#include <asm/udbg.h>
50#include <asm/firmware.h>
51
52#include "pseries.h"
53
54static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX];
55static DEFINE_SPINLOCK(ras_log_buf_lock);
56
1/*
2 * Copyright (C) 2001 Dave Engebretsen IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *

--- 40 unchanged lines hidden (view full) ---

49#include <asm/udbg.h>
50#include <asm/firmware.h>
51
52#include "pseries.h"
53
54static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX];
55static DEFINE_SPINLOCK(ras_log_buf_lock);
56
57static char mce_data_buf[RTAS_ERROR_LOG_MAX];
57static char global_mce_data_buf[RTAS_ERROR_LOG_MAX];
58static DEFINE_PER_CPU(__u64, mce_data_buf);
58
59static int ras_get_sensor_state_token;
60static int ras_check_exception_token;
61
62#define EPOW_SENSOR_TOKEN 9
63#define EPOW_SENSOR_INDEX 0
64
65static irqreturn_t ras_epow_interrupt(int irq, void *dev_id);

--- 125 unchanged lines hidden (view full) ---

191 "Warning: Recoverable hardware error <0x%lx 0x%x>\n",
192 *((unsigned long *)&ras_log_buf), status);
193 }
194
195 spin_unlock(&ras_log_buf_lock);
196 return IRQ_HANDLED;
197}
198
59
60static int ras_get_sensor_state_token;
61static int ras_check_exception_token;
62
63#define EPOW_SENSOR_TOKEN 9
64#define EPOW_SENSOR_INDEX 0
65
66static irqreturn_t ras_epow_interrupt(int irq, void *dev_id);

--- 125 unchanged lines hidden (view full) ---

192 "Warning: Recoverable hardware error <0x%lx 0x%x>\n",
193 *((unsigned long *)&ras_log_buf), status);
194 }
195
196 spin_unlock(&ras_log_buf_lock);
197 return IRQ_HANDLED;
198}
199
199/* Get the error information for errors coming through the
200/*
201 * Some versions of FWNMI place the buffer inside the 4kB page starting at
202 * 0x7000. Other versions place it inside the rtas buffer. We check both.
203 */
204#define VALID_FWNMI_BUFFER(A) \
205 ((((A) >= 0x7000) && ((A) < 0x7ff0)) || \
206 (((A) >= rtas.base) && ((A) < (rtas.base + rtas.size - 16))))
207
208/*
209 * Get the error information for errors coming through the
200 * FWNMI vectors. The pt_regs' r3 will be updated to reflect
201 * the actual r3 if possible, and a ptr to the error log entry
202 * will be returned if found.
203 *
210 * FWNMI vectors. The pt_regs' r3 will be updated to reflect
211 * the actual r3 if possible, and a ptr to the error log entry
212 * will be returned if found.
213 *
204 * The mce_data_buf does not have any locks or protection around it,
214 * If the RTAS error is not of the extended type, then we put it in a per
215 * cpu 64bit buffer. If it is the extended type we use global_mce_data_buf.
216 *
217 * The global_mce_data_buf does not have any locks or protection around it,
205 * if a second machine check comes in, or a system reset is done
206 * before we have logged the error, then we will get corruption in the
207 * error log. This is preferable over holding off on calling
208 * ibm,nmi-interlock which would result in us checkstopping if a
209 * second machine check did come in.
210 */
211static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
212{
218 * if a second machine check comes in, or a system reset is done
219 * before we have logged the error, then we will get corruption in the
220 * error log. This is preferable over holding off on calling
221 * ibm,nmi-interlock which would result in us checkstopping if a
222 * second machine check did come in.
223 */
224static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
225{
213 unsigned long errdata = regs->gpr[3];
214 struct rtas_error_log *errhdr = NULL;
215 unsigned long *savep;
226 unsigned long *savep;
227 struct rtas_error_log *h, *errhdr = NULL;
216
228
217 if ((errdata >= 0x7000 && errdata < 0x7fff0) ||
218 (errdata >= rtas.base && errdata < rtas.base + rtas.size - 16)) {
219 savep = __va(errdata);
220 regs->gpr[3] = savep[0]; /* restore original r3 */
221 memset(mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
222 memcpy(mce_data_buf, (char *)(savep + 1), RTAS_ERROR_LOG_MAX);
223 errhdr = (struct rtas_error_log *)mce_data_buf;
229 if (!VALID_FWNMI_BUFFER(regs->gpr[3])) {
230 printk(KERN_ERR "FWNMI: corrupt r3\n");
231 return NULL;
232 }
233
234 savep = __va(regs->gpr[3]);
235 regs->gpr[3] = savep[0]; /* restore original r3 */
236
237 /* If it isn't an extended log we can use the per cpu 64bit buffer */
238 h = (struct rtas_error_log *)&savep[1];
239 if (!h->extended) {
240 memcpy(&__get_cpu_var(mce_data_buf), h, sizeof(__u64));
241 errhdr = (struct rtas_error_log *)&__get_cpu_var(mce_data_buf);
224 } else {
242 } else {
225 printk("FWNMI: corrupt r3\n");
243 int len;
244
245 len = max_t(int, 8+h->extended_log_length, RTAS_ERROR_LOG_MAX);
246 memset(global_mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
247 memcpy(global_mce_data_buf, h, len);
248 errhdr = (struct rtas_error_log *)global_mce_data_buf;
226 }
249 }
250
227 return errhdr;
228}
229
230/* Call this when done with the data returned by FWNMI_get_errinfo.
231 * It will release the saved data area for other CPUs in the
232 * partition to receive FWNMI errors.
233 */
234static void fwnmi_release_errinfo(void)
235{
236 int ret = rtas_call(rtas_token("ibm,nmi-interlock"), 0, 1, NULL);
237 if (ret != 0)
251 return errhdr;
252}
253
254/* Call this when done with the data returned by FWNMI_get_errinfo.
255 * It will release the saved data area for other CPUs in the
256 * partition to receive FWNMI errors.
257 */
258static void fwnmi_release_errinfo(void)
259{
260 int ret = rtas_call(rtas_token("ibm,nmi-interlock"), 0, 1, NULL);
261 if (ret != 0)
238 printk("FWNMI: nmi-interlock failed: %d\n", ret);
262 printk(KERN_ERR "FWNMI: nmi-interlock failed: %d\n", ret);
239}
240
241int pSeries_system_reset_exception(struct pt_regs *regs)
242{
243 if (fwnmi_active) {
244 struct rtas_error_log *errhdr = fwnmi_get_errinfo(regs);
245 if (errhdr) {
246 /* XXX Should look at FWNMI information */

--- 77 unchanged lines hidden ---
263}
264
265int pSeries_system_reset_exception(struct pt_regs *regs)
266{
267 if (fwnmi_active) {
268 struct rtas_error_log *errhdr = fwnmi_get_errinfo(regs);
269 if (errhdr) {
270 /* XXX Should look at FWNMI information */

--- 77 unchanged lines hidden ---