blob: c157a53b340b3e1522c46c4ed10063a2908f4a09 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2015 Intel Corporation
* Author: Tony Luck
*/
#include "einj.h"
struct error_type error_types[] = {
{ 0x00000001, "Processor Correctable",},
{ 0x00000002, "Processor Uncorrectable non-fatal",},
{ 0x00000004, "Processor Uncorrectable fatal",},
{ 0x00000008, "Memory Correctable",},
{ 0x00000010, "Memory Uncorrectable non-fatal",},
{ 0x00000020, "Memory Uncorrectable fatal",},
{ 0x00000040, "PCI Express Correctable",},
{ 0x00000080, "PCI Express Uncorrectable non-fatal",},
{ 0x00000100, "PCI Express Uncorrectable fatal",},
{ 0x00000200, "Platform Correctabl",},
{ 0x00000400, "Platform Uncorrectable non-fatal",},
{ 0x00000800, "Platform Uncorrectable fatal",},
{ -1, NULL }
};
int check_errortype_available(char *file, unsigned long long val)
{
FILE *fp;
int ret = -1;
unsigned long long available_error_type;
if (strcmp(file, EINJ_ETYPE) != 0)
return 0;
fp = fopen(EINJ_ETYPE_AVAILABLE, "r");
if (!fp) {
fprintf(stderr, "%s: cannot open '%s'\n", progname, file);
exit(1);
}
while (fscanf(fp, "%llx%*[^\n]", &available_error_type) == 1) {
if (val == available_error_type) {
ret = 0;
break;
}
}
fclose(fp);
return ret;
}
void wfile(char *file, unsigned long long val)
{
FILE *fp;
if (check_errortype_available(file, val) != 0) {
fprintf(stderr, "%s: no support for error type: 0x%llx\n", progname, val);
exit(1);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
if (!strcmp(file, EINJ_FLAGS))
return;
#endif
fp = fopen(file, "w");
if (fp == NULL) {
fprintf(stderr, "%s: cannot open '%s'\n", progname, file);
exit(1);
}
fprintf(fp, "0x%llx\n", val);
if (fclose(fp) == EOF) {
fprintf(stderr, "%s: write error on '%s'\n", progname, file);
exit(1);
}
}
int is_einj_support(void)
{
if (access("/sys/firmware/acpi/tables/EINJ", R_OK) == -1) {
fprintf(stderr, "%s: Error injection not supported, check your BIOS settings\n", progname);
return 0;
}
if (access(EINJ_NOTRIGGER, R_OK|W_OK) == -1) {
fprintf(stderr, "%s: Is the einj.ko module loaded?\n", progname);
return 0;
}
return 1;
}
int is_privileged(void)
{
if (getuid() != 0) {
fprintf(stderr, "%s: must be root to run error injection tests\n", progname);
return 0;
}
return 1;
}
void inject_mem_uc(unsigned long long addr, void *vaddr, int notrigger)
{
PRINT_INJECTING;
if (Sflag) {
vaddr = (void *)((long)vaddr & ~(pagesize - 1));
madvise(vaddr, pagesize, MADV_HWPOISON);
return;
}
wfile(EINJ_ETYPE, 0x10);
wfile(EINJ_ADDR, addr);
wfile(EINJ_MASK, ~0x0ul);
wfile(EINJ_FLAGS, 2);
wfile(EINJ_NOTRIGGER, notrigger);
wfile(EINJ_DOIT, 1);
}
char *lookup_type_name(unsigned long long type)
{
struct error_type *t;
for (t = error_types; t->type_name; t++)
if (t->type == type)
return t->type_name;
fprintf(stderr, "%s: unknown type '%x'\n", progname, type);
exit(1);
}