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 --- |