summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/i960/rxgen960/startup/fault.c
blob: 6142851fd20cdd664f8f8c9c016ff24062fbb10c (plain) (blame)
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
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
/*-------------------------------------*/
/* fault.c                             */
/* Last change : 13. 7.95              */
/*-------------------------------------*/  
/*
 *  $Id$
 */

#include "prcb.h"
#include "i960.h"
#include "flttbl.h"
#include "fault.h"
#include "asmstub.h"
#include <stdio.h>
#include <string.h>

extern void romFaultStart(void);

/*-------------------------------------*/
  /* Table of user-registered fault handler entry.
   */
typedef struct {
  UserFaultHandler hndl;         /* Handler itself. */
  int cnt;                       /* Handler is valid for cnt times. */ 
} UserFaultEntry;  
  /* Table itself.
   */
static UserFaultEntry userFaultTable[] = {  
  {0, 0},                       /* Parallel */
  {0, 0},                       /* Trace */
  {0, 0},                       /* Operation */
  {0, 0},                       /* Arithmetic */
  {0, 0},                       /* Reserved */
  {0, 0},                       /* Constraint */
  {0, 0},                       /* Reserved */
  {0, 0},                       /* Protection */
  {0, 0},                       /* Reserved */
  {0, 0}                        /* Type */
};
  /* Number of Faults.
   */
#define FaultNmbr (sizeof(userFaultTable)/sizeof(UserFaultEntry))

int faultRegister(int fault, UserFaultHandler hndl, int cnt)
{
  static unsigned int faultNewCheckSum(void);
  int rsl = 0;

  if (0 <= fault &&  fault <= FaultNmbr)  {
      /* Register handler.
       */
    userFaultTable[fault].hndl = hndl;
    userFaultTable[fault].cnt = cnt;
      /* Checksum has changed.
       */
    faultCheckSum = faultNewCheckSum();
    rsl = 1;
  }
  return rsl;
}
int faultOk(int fault)
{
  static unsigned int faultNewCheckSum(void);
  int rsl = 0;

  if (0 <= fault &&  fault <= FaultNmbr)  {
      /* Fault handler recovered successfully.
       * Can use it at least once more.
       */
    userFaultTable[fault].cnt ++;
      /* Check sum has changed.
       */
#if 0
    faultCheckSum = faultNewCheckSum();
#endif
    faultCheckSum ++; 
    rsl = 1;
  }
  return rsl;
}
void faultBad(int invokedFromRom,
              unsigned int inst, unsigned int * faultBuffer,
              unsigned int type, unsigned int sbtp)
{
  static void faultInfo(int invokedFromRom,
                        unsigned int inst, unsigned int * faultBuffer,
                        unsigned int type, unsigned int sbtp);

    /* Close the mem channel nicely.
     */
/*  memChnlI960Fault();*/
    /* Give some panic message.
     */ 
  faultInfo(invokedFromRom, inst, faultBuffer, type, sbtp);
     /* At this point RAM is repaired. Do
      * whatever you want.
      */
#if 0
  if (OsfIsUp)  {    
    asm_exit(romFaultStart, & ram_prcb);
  }
  else  {
    asm_exit(romStart, & ram_prcb);
  }  
# endif
  asm_exit(romFaultStart, & ram_prcb);
}
void faultGood(unsigned int inst, unsigned int * faultBuffer,
               unsigned int type, unsigned int sbtp)
{
  static unsigned int faultNewCheckSum(void);
 
  if (userFaultTable[type].hndl != 0 && userFaultTable[type].cnt > 0)  {
      /* This is done to avoid the situation when
       * handler causes a fault and, thus, infinite recursion.
       */
    userFaultTable[type].cnt --;
      /* Check sum has changed.
       */
#if 0
    faultCheckSum = faultNewCheckSum();
#endif
    faultCheckSum --;
      /* Invoke handler.
       */ 
    (* userFaultTable[type].hndl)(inst, faultBuffer, type, sbtp);
      /* If this returns => fault is bad.
       */ 
  }
  faultBad(0, inst, faultBuffer, type, sbtp);
}
static unsigned int faultNewCheckSum(void)
{
  unsigned int * f = faultStart;
  unsigned int * l = faultEnd; 
  unsigned int sum;
  
  for (sum = 0; f < l; f ++)  {
    sum += * f;
  }
  return sum;
}
static void faultInfo(int invokedFromRom,
                      unsigned int inst, unsigned int * faultBuffer,
                      unsigned int type, unsigned int sbtp)
{
  char * typeStr;
  char * sbtpStr;
  static char * faultParallelSbtpStr(unsigned int);
  static char * faultTraceSbtpStr(unsigned int);
  static char * faultOperationSbtpStr(unsigned int);
  static char * faultArithmeticSbtpStr(unsigned int);
  static char * faultReservedSbtpStr(unsigned int);
  static char * faultConstraintSbtpStr(unsigned int);
  static char * faultProtectionSbtpStr(unsigned int);
  static char * faultTypeSbtpStr(unsigned int);
  static char * faultUnknownSbtpStr(unsigned int);
  static struct {
    char * name;
    char * (* sbtpStr)(unsigned int);
  } faultInfo[] = {
    {"Parallel", faultParallelSbtpStr},
    {"Trace", faultTraceSbtpStr},
    {"Operation", faultOperationSbtpStr},
    {"Arithmetic", faultArithmeticSbtpStr},
    {"Reserved", faultReservedSbtpStr},
    {"Constraint", faultConstraintSbtpStr},
    {"Reserved", faultReservedSbtpStr},
    {"Protection", faultProtectionSbtpStr},
    {"Reserved", faultReservedSbtpStr},
    {"Type", faultTypeSbtpStr},
    {"Unknown", faultUnknownSbtpStr}
  };
  unsigned int ix;

/*  console_set_channel(CHANNEL_B);*/
  ix = type >= FaultNmbr ? FaultNmbr : type;
  typeStr = faultInfo[ix].name;
  sbtpStr = (* faultInfo[ix].sbtpStr)(sbtp);
  printf("\nFault at 0x%08x: %s[%s]\n",
           faultBuffer[IP_REGNUM], typeStr, sbtpStr);
  printf("Bad instruction: 0x%08x\n", inst);
  printf("AC=0x%08x PC=0x%08x\n",
           faultBuffer[ACW_REGNUM],
           faultBuffer[PCW_REGNUM]);
  printf("g0=0x%08x g1=0x%08x g2=0x%08x g3=0x%08x\n",
         faultBuffer[G0_REGNUM+0], faultBuffer[G0_REGNUM+1],
         faultBuffer[G0_REGNUM+2], faultBuffer[G0_REGNUM+3]);
  printf("g4=0x%08x g5=0x%08x g6=0x%08x g7=0x%08x\n",
         faultBuffer[G0_REGNUM+4], faultBuffer[G0_REGNUM+5],
         faultBuffer[G0_REGNUM+6], faultBuffer[G0_REGNUM+7]);
  printf("g8=0x%08x g9=0x%08x gA=0x%08x gB=0x%08x\n",
         faultBuffer[G0_REGNUM+8], faultBuffer[G0_REGNUM+9],
         faultBuffer[G0_REGNUM+10], faultBuffer[G0_REGNUM+11]); 
  printf("gC=0x%08x gD=0x%08x gE=0x%08x gF=0x%08x\n",
         faultBuffer[G0_REGNUM+12], faultBuffer[G0_REGNUM+13],
         faultBuffer[G0_REGNUM+14], faultBuffer[G0_REGNUM+15]);
  printf("r0=0x%08x r1=0x%08x r2=0x%08x r3=0x%08x\n",
         faultBuffer[R0_REGNUM+0], faultBuffer[R0_REGNUM+1],
         faultBuffer[R0_REGNUM+2], faultBuffer[R0_REGNUM+3]);
  printf("r4=0x%08x r5=0x%08x r6=0x%08x r7=0x%08x\n",
         faultBuffer[R0_REGNUM+4], faultBuffer[R0_REGNUM+5],
         faultBuffer[R0_REGNUM+6], faultBuffer[R0_REGNUM+7]);
  printf("r8=0x%08x r9=0x%08x rA=0x%08x rB=0x%08x\n",
         faultBuffer[R0_REGNUM+8], faultBuffer[R0_REGNUM+9],
         faultBuffer[R0_REGNUM+10], faultBuffer[R0_REGNUM+11]); 
  printf("rC=0x%08x rD=0x%08x rE=0x%08x rF=0x%08x\n",
         faultBuffer[R0_REGNUM+12], faultBuffer[R0_REGNUM+13],
         faultBuffer[R0_REGNUM+14], faultBuffer[R0_REGNUM+15]);                
  if (invokedFromRom)  {
    printf("RAM image damaged. No chance to recover\n");
  } 
  else  {
    printf("RAM image not damaged. Still no recovery\n"); 
  }
} 
static char * faultParallelSbtpStr(unsigned int sbtp)
{
  static char buf[10];
  
  sprintf(buf, "%d", sbtp);
  return buf;
}
static char * faultTraceSbtpStr(unsigned int sbtp)
{
  static char buf[256];
  int notEmpty;

  buf[0] = '\0';
  notEmpty = 0;
  if (sbtp & 0x2)  {
     strcat(buf, "Instruction");
     notEmpty = 1;
  }   
  if (sbtp & 0x4)  {
    if (notEmpty) strcat(buf, ":");
    strcat(buf, "Branch");
    notEmpty = 1;
  } 
  if (sbtp & 0x8)  {
    if (notEmpty) strcat(buf, ":");
    strcat(buf, "Call");
    notEmpty = 1;
  } 
  if (sbtp & 0x10)  {
    if (notEmpty) strcat(buf, ":");
    strcat(buf, "Return");
    notEmpty = 1;
  } 
  if (sbtp & 0x20)  {
    if (notEmpty) strcat(buf, ":");
    strcat(buf, "Prereturn");
    notEmpty = 1;
  }  
  if (sbtp & 0x40)  {
    if (notEmpty) strcat(buf, ":");
    strcat(buf, "Supervisor");
    notEmpty = 1;
  }   
  if (sbtp & 0x80)  {
    if (notEmpty) strcat(buf, ":");
    strcat(buf, "Breakpoint");
    notEmpty = 1;
  } 
  if (! notEmpty)  {
    strcat(buf, "Unknown");
  }        
  return buf;
}
static char * faultOperationSbtpStr(unsigned int sbtp)
{
  char * rsl;
  
  if (sbtp == 0x1)      rsl = "Invalid Opcode";
  else if (sbtp == 0x2) rsl = "Unimplemented";
  else if (sbtp == 0x3) rsl = "Unaligned";
  else if (sbtp == 0x4) rsl = "Invalid Operand";
  else                  rsl = "Unknown";
  return rsl;
}
static char * faultArithmeticSbtpStr(unsigned int sbtp)
{
  char * rsl;
  
  if (sbtp == 0x1)      rsl = "Integer Overflow";
  else if (sbtp == 0x2) rsl = "Arithmetic Zero-Divide";
  else                  rsl = "Unknown";  
  return rsl;
}
static char * faultReservedSbtpStr(unsigned int sbtp)
{
  return "Unknown";  
}
static char * faultConstraintSbtpStr(unsigned int sbtp)
{
  char * rsl;
  
  if (sbtp == 0x1)      rsl = "Constraint Range";
  else if (sbtp == 0x2) rsl = "Priveleged";
  else                  rsl = "Unknown";    
  return rsl;
}
static char * faultProtectionSbtpStr(unsigned int sbtp)
{
  char * rsl;
  
  if (sbtp == 0x1)    rsl = "Length";
  else                rsl = "Unknown";     
  return rsl;
}
static char * faultTypeSbtpStr(unsigned int sbtp)
{
  char * rsl;
  
  if (sbtp == 0x1)    rsl = "Type Mismatch";
  else                rsl = "Unknown";     
  return rsl;
}
static char * faultUnknownSbtpStr(unsigned int sbtp)
{
  return "Unknown";
}
/*-------------*/
/* End of file */
/*-------------*/