blob: dc45c1ae393945662aec5655395844ee9c078d34 [file] [log] [blame]
/* Copyright (C) 2009 Intel Corporation
Author: Andi Kleen
Handle 'yellow bit' cache error threshold indications.
mcelog is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; version
2.
mcelog is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should find a copy of v2 of the GNU General Public License somewhere
on your Linux system; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define _GNU_SOURCE 1
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include "memutil.h"
#include "mcelog.h"
#include "config.h"
#include "trigger.h"
#include "yellow.h"
#include "cache.h"
#define BITS_PER_U (sizeof(unsigned) * 8)
#define test_bit(i, a) (((unsigned *)(a))[(i) / BITS_PER_U] & (1U << ((i) % BITS_PER_U)))
static char *yellow_trigger;
static int yellow_log = 1;
enum {
MAX_ENV = 10,
};
static char *cpulist(char *prefix, unsigned *cpumask, unsigned cpumasklen)
{
unsigned i, k;
char *buf = NULL;
size_t size = 0;
FILE *f = open_memstream(&buf, &size);
if (!f)
Enomem();
fprintf(f, "%s", prefix);
k = 0;
for (i = 0; i < cpumasklen * 8; i++) {
if (test_bit(i, cpumask)) {
fprintf(f, "%s%u", k > 0 ? " " : "", i);
k++;
}
}
fclose(f);
return buf;
}
void run_yellow_trigger(int cpu, int tnum, int lnum, char *ts, char *ls, int socket)
{
int ei = 0;
char *env[MAX_ENV];
unsigned *cpumask;
int cpumasklen;
int i;
char *msg;
char *location;
if (socket >= 0)
xasprintf(&location, "CPU %d on socket %d", cpu, socket);
else
xasprintf(&location, "CPU %d", cpu);
xasprintf(&msg, "%s has large number of corrected cache errors in %s %s",
location, ls, ts);
free(location);
if (yellow_log) {
Lprintf("%s\n", msg);
Lprintf("System operating correctly, but might lead to uncorrected cache errors soon\n");
}
if (!yellow_trigger)
goto out;
if (socket >= 0)
xasprintf(&env[ei++], "SOCKETID=%d", socket);
xasprintf(&env[ei++], "MESSAGE=%s", msg);
xasprintf(&env[ei++], "CPU=%d", cpu);
xasprintf(&env[ei++], "LEVEL=%d", lnum);
xasprintf(&env[ei++], "TYPE=%s", ts);
if (cache_to_cpus(cpu, lnum, tnum, &cpumasklen, &cpumask) >= 0)
env[ei++] = cpulist("AFFECTED_CPUS=", cpumask, cpumasklen);
else
xasprintf(&env[ei++], "AFFECTED_CPUS=unknown");
env[ei] = NULL;
assert(ei < MAX_ENV);
run_trigger(yellow_trigger, NULL, env);
for (i = 0; i < ei; i++)
free(env[i]);
out:
free(msg);
}
void yellow_setup(void)
{
int n;
yellow_trigger = config_string("cache", "cache-threshold-trigger");
if (yellow_trigger && trigger_check(yellow_trigger) < 0) {
SYSERRprintf("Cannot access cache threshold trigger `%s'",
yellow_trigger);
exit(1);
}
n = config_bool("cache", "cache-threshold-log");
if (n >= 0)
yellow_log = n;
}