faults.c
6.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/*
* Copyright (C) 1996-1998 by the Board of Trustees
* of Leland Stanford Junior University.
*
* This file is part of the SimOS distribution.
* See LICENSE file for terms of the license.
*
*/
/****************************************************
*
* Tcl-based fault injection support
*
* Author: John Chapin 1/30/96
*
****************************************************/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include "../../cpus/shared/addr_layout.h"
#include "simmisc.h"
#include "sim_error.h"
#include "tcl_init.h"
#include "cpu_interface.h"
/**** Tcl dispatch table *****/
/* current interface
* fault cpu 1 iparity # next l1 icache access generates parity error
* fault cpu 1 dparity # next l1 dcache access generates parity error
* fault cpu 1 ecc # next l2 access generates ECC cache error
* fault cpu 1 halt # cease executing instructions
* fault cpu 1 powerfail # halt + stop responding to MAGIC interventions
* fault magic 1 iparity # next PP icache access generates parity error
* fault magic 1 dparity # next PP dcache access generates parity error
* fault magic 1 halt # PP ceases executing instructions
* fault magic 1 powerfail # halt + LLP failure on attached router
* fault memory 0x350b00 27 ecc # access to range [addr,numlines] gives ECC
*
* fault inst smash 0x82005000 48 # fault instruction at addr with random seed
* fault inst test 0x82005000 48 # test if can do fault
*/
static int cmdCpu(Tcl_Interp *interp, int argc, char *argv[]);
static int cmdMagic(Tcl_Interp *interp, int argc, char *argv[]);
static int cmdMemory(Tcl_Interp *interp, int argc, char *argv[]);
static int cmdInst(Tcl_Interp *interp, int argc, char *argv[]);
static tclcmd faultCmds[] = {
{ "cpu", 4, cmdCpu, " cpu NodeNum faultType"},
{ "magic", 4, cmdMagic, " magic NodeNum faultType"},
{ "memory", 5, cmdMemory, " memory Addr Numlines faultType"},
{ "inst", 6, cmdInst, " inst <test|smash> Addr randomSeed funcname"},
{ NULL, 0, NULL, NULL}
};
static Tcl_HashTable faultTypeHT;
/* the order of entries in faultTypeEnum and faultTypeNames must match! */
static char* faultTypeNames[] = {
"iparity",
"dparity",
"ecc",
"halt",
"powerfail",
NULL
};
void FaultInit(Tcl_Interp* interp)
{
int i;
Tcl_CreateCommand(interp,
"fault",
DispatchCmd,
(ClientData)faultCmds,
NULL);
Tcl_InitHashTable(&faultTypeHT, TCL_STRING_KEYS);
i = 0;
while (faultTypeNames[i]) {
int new = 0;
Tcl_HashEntry *entry = Tcl_CreateHashEntry(&faultTypeHT,
faultTypeNames[i],
&new);
ASSERT(new);
Tcl_SetHashValue(entry, UINT_TO_PTRSIZE(i));
i++;
}
{
extern void FlashFaultInit(Tcl_Interp*);
FlashFaultInit(interp);
}
}
static int
getNodeFaultType(Tcl_Interp* interp, char *nodeName, char* typeName,
int* nodenum, faultTypeEnum* faultType)
{
int code;
Tcl_HashEntry* entry;
if ((code = Tcl_GetInt(interp, nodeName, nodenum)) != TCL_OK) {
Tcl_AppendResult(interp, "bad cpunum \"", nodeName, "\"", NULL);
return code;
}
if ((entry = Tcl_FindHashEntry(&faultTypeHT, typeName)) == NULL) {
Tcl_AppendResult(interp, "bad fault type \"", typeName, "\"", NULL);
return TCL_ERROR;
}
*faultType = (faultTypeEnum) Tcl_GetHashValue(entry);
return TCL_OK;
}
int cmdCpu(Tcl_Interp *interp, int argc, char *argv[])
{
int nodeNum;
faultTypeEnum faultType;
int code;
code = getNodeFaultType(interp, argv[2], argv[3], &nodeNum, &faultType);
if (code != TCL_OK) return code;
switch (faultType) {
case SIMFAULT_HALT:
CPUVec.FaultInject(nodeNum, faultType);
return TCL_OK;
default:
Tcl_AppendResult(interp, "fault cpu ", faultTypeNames[faultType],
" unimplemented", NULL);
return TCL_ERROR;
}
}
int cmdMagic(Tcl_Interp *interp, int argc, char *argv[])
{
Tcl_AppendResult(interp, "fault magic unimplemented", NULL);
return TCL_ERROR;
}
int cmdMemory(Tcl_Interp *interp, int argc, char *argv[])
{
#ifdef USE_FLASHLITE
extern int insertECC(unsigned int addr, int lines);
int code;
int addrNum, linesNum;
char *addrName = argv[2];
char *linesName = argv[3];
char *faultName = argv[4];
if ((code = Tcl_GetInt(interp, addrName, &addrNum)) != TCL_OK) {
Tcl_AppendResult(interp, "bad address \"", addrName, "\"", NULL);
return code;
}
if ((code = Tcl_GetInt(interp, linesName, &linesNum)) != TCL_OK) {
Tcl_AppendResult(interp, "bad number of lines \"", linesName, "\"", NULL);
return code;
}
if (strcmp(faultName, "ecc")) {
Tcl_AppendResult(interp, "bad fault type \"", linesName, "\"", NULL);
return TCL_ERROR;
}
if (insertECC(addrNum, linesNum)) {
Tcl_AppendResult(interp, "cannot ECC address \"", addrName, "\"", NULL);
return TCL_ERROR;
}
return TCL_OK;
#else
Tcl_AppendResult(interp, "fault memory unimplemented", NULL);
return TCL_ERROR;
#endif
}
int cmdInst(Tcl_Interp *interp, int argc, char *argv[])
{
int addrNum, randomNum, code, doSmash;
char errBuf[256];
extern int smashinst(int dosmash, int cpunum, VA addr, int rnd, char* errbuf);
int r;
char *testName = argv[2];
char *addrName = argv[3];
char *randomName = argv[4];
if (argc < 6) {
Tcl_AppendResult(interp, "need 5 args to fault inst\n", NULL);
return TCL_ERROR;
}
strncpy(errBuf, argv[5], 255);
if (!strcmp(testName, "test")) {
doSmash = 0;
} else if (!strcmp(testName, "smash")) {
doSmash = 1;
} else {
Tcl_AppendResult(interp, "not test or smash: \"", testName, "\"", NULL);
return TCL_ERROR;
}
if ((code = Tcl_GetInt(interp, addrName, &addrNum)) != TCL_OK) {
Tcl_AppendResult(interp, "bad address \"", addrName, "\"", NULL);
return code;
}
if ((code = Tcl_GetInt(interp, randomName, &randomNum)) != TCL_OK) {
Tcl_AppendResult(interp, "bad random seed \"", randomName, "\"", NULL);
return code;
}
r = smashinst(doSmash, CPUVec.CurrentCpuNum(), addrNum, randomNum, errBuf);
Tcl_AppendResult(interp, errBuf, NULL);
if ((r == SUCCESS) || (!strcmp(errBuf, "RETRY")))
return TCL_OK;
else
return TCL_ERROR;
}