Example #1
0
/*
 * Get the error information for errors coming through the
 * FWNMI vectors.  The pt_regs' r3 will be updated to reflect
 * the actual r3 if possible, and a ptr to the error log entry
 * will be returned if found.
 *
 * Use one buffer mce_data_buf per cpu to store RTAS error.
 *
 * The mce_data_buf does not have any locks or protection around it,
 * if a second machine check comes in, or a system reset is done
 * before we have logged the error, then we will get corruption in the
 * error log.  This is preferable over holding off on calling
 * ibm,nmi-interlock which would result in us checkstopping if a
 * second machine check did come in.
 */
static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
{
	unsigned long *savep;
	struct rtas_error_log *h;

	/* Mask top two bits */
	regs->gpr[3] &= ~(0x3UL << 62);

	if (!VALID_FWNMI_BUFFER(regs->gpr[3])) {
		printk(KERN_ERR "FWNMI: corrupt r3 0x%016lx\n", regs->gpr[3]);
		return NULL;
	}

	savep = __va(regs->gpr[3]);
	regs->gpr[3] = be64_to_cpu(savep[0]);	/* restore original r3 */

	h = (struct rtas_error_log *)&savep[1];
	/* Use the per cpu buffer from paca to store rtas error log */
	memset(local_paca->mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
	if (!rtas_error_extended(h)) {
		memcpy(local_paca->mce_data_buf, h, sizeof(__u64));
	} else {
		int len, error_log_length;

		error_log_length = 8 + rtas_error_extended_log_length(h);
		len = min_t(int, error_log_length, RTAS_ERROR_LOG_MAX);
		memcpy(local_paca->mce_data_buf, h, len);
	}

	return (struct rtas_error_log *)local_paca->mce_data_buf;
}
Example #2
0
/*
 * Get the error information for errors coming through the
 * FWNMI vectors.  The pt_regs' r3 will be updated to reflect
 * the actual r3 if possible, and a ptr to the error log entry
 * will be returned if found.
 *
 * If the RTAS error is not of the extended type, then we put it in a per
 * cpu 64bit buffer. If it is the extended type we use global_mce_data_buf.
 *
 * The global_mce_data_buf does not have any locks or protection around it,
 * if a second machine check comes in, or a system reset is done
 * before we have logged the error, then we will get corruption in the
 * error log.  This is preferable over holding off on calling
 * ibm,nmi-interlock which would result in us checkstopping if a
 * second machine check did come in.
 */
static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
{
    unsigned long *savep;
    struct rtas_error_log *h, *errhdr = NULL;

    if (!VALID_FWNMI_BUFFER(regs->gpr[3])) {
        printk(KERN_ERR "FWNMI: corrupt r3 0x%016lx\n", regs->gpr[3]);
        return NULL;
    }

    savep = __va(regs->gpr[3]);
    regs->gpr[3] = savep[0];	/* restore original r3 */

    /* If it isn't an extended log we can use the per cpu 64bit buffer */
    h = (struct rtas_error_log *)&savep[1];
    if (!h->extended) {
        memcpy(&__get_cpu_var(mce_data_buf), h, sizeof(__u64));
        errhdr = (struct rtas_error_log *)&__get_cpu_var(mce_data_buf);
    } else {
        int len;

        len = max_t(int, 8+h->extended_log_length, RTAS_ERROR_LOG_MAX);
        memset(global_mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
        memcpy(global_mce_data_buf, h, len);
        errhdr = (struct rtas_error_log *)global_mce_data_buf;
    }

    return errhdr;
}