Files
seta75D 2e8a93c394 Init
2021-10-11 18:20:23 -03:00

501 lines
8.2 KiB
C

/* test_memtest.c */
/*
* User-level program to test the memtest driver.
*
* Usage: test_memtest function [...]
* See below for the list of functions.
*
* Specifying more than one function is probably a waste of time, as the
* system will either panic or kill the process on the first error.
*
* TODO: catch signals and continue
*/
#include <stdio.h>
#include <setjmp.h>
#include <sys/ioctl.h>
#include <memtestio.h>
char Usage[] = "Usage: %s function [...]\n\
where function is one (or more) of\n\
kfetch cause a kernel ifetch parity error\n\
kload cause a kernel load parity error\n\
kstore cause a kernel store timeout error\n\
kloadt cause a kernel load timeout error\n\
kfetcht cause a kernel fetch timeout error\n\
ufetch cause a user ifetch parity error\n\
uload cause a user load parity error\n\
uloadc cause a user load parity error on cache load\n\
uloadm cause multiple user parity errors on cache load\n\
ustore cause a user store timeout error\n\
ustoreX cause both a user store timeout and protection error\n\
(X is one of 0, 1, 2, or 3)\n\
uloadt cause a user load timeout error\n\
ufetcht cause a user fetch timeout error\n\
dma cause a dma parity error\n\
";
char *progname;
int errcnt = 0;
int dokfetch(), dokload(), dokstore(), dokloadt(), dokfetcht();
int doufetch(), douload(), doustore(), douloadt(), doufetcht();
int douloadc(), douloadm(), dodma();
int doustorem0(), doustorem1(), doustorem2(), doustorem3();
struct command {
char *c_name;
int (*c_func)();
} command[] = {
"kfetch", dokfetch,
"kload", dokload,
"kstore", dokstore,
"kloadt", dokloadt,
"kfetcht", dokfetcht,
"ufetch", doufetch,
"uload", douload,
"uloadc", douloadc,
"uloadm", douloadm,
"ustore", doustore,
"ustore0", doustorem0,
"ustore1", doustorem1,
"ustore2", doustorem2,
"ustore3", doustorem3,
"uloadt", douloadt,
"ufetcht", doufetcht,
"dma", dodma,
NULL, NULL};
jmp_buf env;
main(argc, argv)
int argc;
char **argv;
{
char *arg;
progname = *argv++;
if (--argc <= 0) {
usage();
exit(1);
}
init();
setjmp(env); /* in case of a race, we do this twice */
catchsigs();
setjmp(env); /* this is where we really want to be */
while (arg = *argv++) {
struct command *p;
for (p = command; p->c_name != NULL; p++) {
if (strcmp(arg, p->c_name) == 0)
break;
}
if (p->c_func == NULL)
error("unknown function \"%s\"\n", arg);
else {
fprintf(stderr, "calling %s\n", p->c_name);
(*p->c_func)();
}
}
return (errcnt);
}
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
char *memtest = "/dev/memtest";
int fdmemtest = -1; /* file descriptor */
caddr_t badmem = NULL; /* bad memory */
caddr_t u_data = NULL; /* data area */
extern char *valloc();
char *filetest = "/tmp/memtest";
int fdfiletest = -1; /* file descriptor */
int *fileaddr = NULL;
init()
{
fdmemtest = open(memtest, O_RDWR);
if (fdmemtest == -1) {
fprintf(stderr, "%s: couldn't open ", progname);
perror(memtest);
exit(1);
}
#define PROT_ALL (PROT_READ | PROT_WRITE | PROT_EXEC)
badmem = mmap(0, getpagesize(), PROT_ALL, MAP_SHARED, fdmemtest, 0);
if (badmem == (caddr_t)-1) {
fprintf(stderr, "%s: couldn't mmap ", progname);
perror(memtest);
exit(1);
}
fdfiletest = open(filetest, O_RDWR | O_CREAT | O_TRUNC, 0666);
if (fdfiletest == -1) {
fprintf(stderr, "%s: couldn't create ", progname);
perror(filetest);
exit(1);
}
if (ftruncate(fdfiletest, 8) != 0) {
fprintf(stderr, "%s: couldn't extend ", progname);
perror(filetest);
exit(1);
}
if (fsync(fdfiletest) != 0) {
fprintf(stderr, "%s: couldn't fsync ", progname);
perror(filetest);
exit(1);
}
fileaddr = (int *)mmap(0, getpagesize(), PROT_ALL, MAP_SHARED, fdfiletest, 0);
if (fileaddr == (int *)-1) {
fprintf(stderr, "%s: couldn't mmap ", progname);
perror(filetest);
exit(1);
}
u_data = valloc(getpagesize());
if (u_data == NULL) {
fprintf(stderr, "%s: couldn't allocate u_data\n",
progname);
exit(1);
}
}
#include <varargs.h>
error(va_alist)
va_dcl
{
va_list pvar;
char *fmt;
va_start(pvar);
fmt = va_arg(pvar, char *);
fprintf(stderr, "%s: ", progname);
vfprintf(stderr, fmt, pvar);
va_end(pvar);
usage();
}
usage()
{
if (errcnt++ == 0)
fprintf(stderr, Usage, progname);
}
int
dokload()
{
int i;
Sync();
i = ioctl(fdmemtest, MEMTESTBADLOAD, 0);
if (i != 0) {
fprintf(stderr, "%s: ", progname);
perror("ioctl BADLOAD failed");
}
return i;
}
int
dokfetch()
{
int i;
Sync();
i = ioctl(fdmemtest, MEMTESTBADFETCH, 0);
if (i != 0) {
fprintf(stderr, "%s: ", progname);
perror("ioctl BADFETCH failed");
}
return i;
}
int
dokstore()
{
int i;
Sync();
i = ioctl(fdmemtest, MEMTESTBADSTORE, badmem);
if (i != 0) {
fprintf(stderr, "%s: ", progname);
perror("ioctl BADSTORE failed");
}
return i;
}
int
dokloadt()
{
int i;
Sync();
i = ioctl(fdmemtest, MEMTESTBADLOADT, badmem);
if (i != 0) {
fprintf(stderr, "%s: ", progname);
perror("ioctl BADLOADT failed");
}
return i;
}
int
dokfetcht()
{
int i;
Sync();
i = ioctl(fdmemtest, MEMTESTBADFETCHT, badmem);
if (i != 0) {
fprintf(stderr, "%s: ", progname);
perror("ioctl BADFETCHT failed");
}
return i;
}
int
douload()
{
register int c, d;
c = u_data[0];
u_data[0] = c; /* touch the page */
upar(&u_data[0]);
Sync();
d = u_data[0]; /* should crash here */
fprintf(stderr, "test_memtest: didn't crash!?\n");
fprintf(stderr, "\tbefore: 0x%x after: 0x%x\n", c, d);
return(c ^ d);
}
int
douloadc()
{
register int c, d;
register int i;
register char *p, *q;
p = u_data;
p = (char *)((int)p & ~0xf); /* cache-line boundary */
q = p + 15;
c = *p;
*p = c; /* touch the page */
fprintf(stderr, "writing bad parity to 0x%x.\n", q);
upar(q);
Sync();
for (i = 0; i < 16; i++) {
d = p[i]; /* should eventually crash here */
}
fprintf(stderr, "test_memtest: didn't crash!?\n");
fprintf(stderr, "\tbefore: 0x%x after: 0x%x\n", c, d);
return(c ^ d);
}
int
douloadm()
{
register int c, d;
register int i;
register char *p, *q1, *q2;
p = u_data;
p = (char *)((int)p & ~0xf); /* cache-line boundary */
q1 = p + 6;
q2 = p + 15;
c = *p;
*p = c; /* touch the page */
fprintf(stderr, "writing bad parity to 0x%x and 0x%x.\n",
q1, q2);
upar(q1);
upar(q2);
Sync();
for (i = 0; i < 16; i++) {
d = p[i]; /* should eventually crash here */
}
fprintf(stderr, "test_memtest: didn't crash!?\n");
fprintf(stderr, "\tbefore: 0x%x after: 0x%x\n", c, d);
return(c ^ d);
}
/* function used by doufetch */
extern int u_retl();
int
doufetch()
{
register int c, d;
c = *(char *)u_retl;
upar(u_retl);
Sync();
u_retl(); /* should crash here */
fprintf(stderr, "test_memtest: didn't crash!?\n");
d = *(char *)u_retl; /* or at least here! */
fprintf(stderr, "\tbefore: 0x%x after: 0x%x\n", c, d);
}
int
doustore()
{
Sync();
*badmem = 0; /* should crash here */
return 0;
}
int
doustorem0()
{
Sync();
doustorem_asm0(badmem); /* should crash here */
return 0;
}
int
doustorem1()
{
Sync();
doustorem_asm1(badmem); /* should crash here */
return 0;
}
int
doustorem2()
{
Sync();
doustorem_asm2(badmem); /* should crash here */
return 0;
}
int
doustorem3()
{
Sync();
doustorem_asm3(badmem); /* should crash here */
return 0;
}
int
douloadt()
{
char c;
Sync();
c = *badmem; /* should crash here */
return 0;
}
int
doufetcht()
{
Sync();
(*(int (*)())badmem)(); /* should crash here */
return 0;
}
int
dodma()
{
int i;
Sync();
fileaddr[0] = 0x12345678;
upar((caddr_t)fileaddr);
fileaddr[1] = 0x9abcdef0;
i = fsync(fdfiletest); /* should crash here */
if (i != 0) {
fprintf(stderr, "%s: ", progname);
perror("fsync failed");
}
return(i);
}
int
Sync()
{
fflush(stderr);
fsync(fileno(stderr));
sync();
}
int
upar(addr)
caddr_t addr;
{
int i;
i = ioctl(fdmemtest, MEMTESTBADPAR, addr);
if (i != 0) {
fprintf(stderr, "%s: ", progname);
perror("couldn't set parity");
}
return i;
}
/*
* Note: Do we have to be type 407 for this to work?
* No; memtest.c has been improved to write to "read-only" pages.
*/
int
u_retl()
{
return 0;
}
#include <signal.h>
handler(sig, code, scp, addr)
int sig;
int code;
struct sigcontext *scp;
char *addr;
{
psignal(sig, "received signal");
fprintf(stderr, " code=%d addr=0x%x\n", code, addr);
longjmp(env, 1);
}
catchsigs()
{
signal(SIGBUS, handler);
signal(SIGSEGV, handler);
}