2 #include "../port/lib.h"
7 #include "../port/error.h"
14 typedef struct Fault Fault;
24 extern char *excname[];
26 static Fault lflt, maxflt;
29 reg(Ureg *ur, int regno)
34 case 31: return &ur->r31;
35 case 30: return &ur->r30;
36 case 29: return &ur->sp;
44 * Ask if the instruction at EPC could have cause this badvaddr
56 if(seg(up, iw, 0) == 0)
61 /* print("iw: %#lux\n", iw); /**/
63 switch((iw>>26) & 0x3f) {
80 case 0x32: /* LWCz possible 0x33 */
107 rn = (iw>>21) & 0x1f;
113 /* print("ea %#lux %#lux(R%d) bv %#lux pc %#lux\n", ea, off, rn, ur->badvaddr, ur->pc); /**/
115 if(ur->badvaddr == ea)
122 * we think we get consecutive page faults from unlucky combinations of
123 * scheduling and stlb hashes, and they only happen with 16K pages.
124 * however, we also get page faults while servicing the exact same fault.
125 * more than 5 consecutive faults is unusual, now that we have a better
128 * this can be helpful during mmu and cache debugging.
131 ckfaultstuck(Ureg *ur, int read, int code)
137 if (va != lflt.va || up->pid != lflt.pid || pc != lflt.pc ||
139 /* at least one address or cause is different from last time */
148 if (lflt.cnt >= 1000) /* fixfault() isn't fixing underlying cause? */
149 panic("fault: %d consecutive faults for va %#p", lflt.cnt, va);
150 if (lflt.cnt > maxflt.cnt) {
151 maxflt.cnt = lflt.cnt;
153 maxflt.pid = up->pid;
155 kstrdup(&maxflt.prog, up->text);
158 /* we're servicing that fault now! */
159 /* adjust the threshold and program name to suit */
160 if (lflt.cnt < 5 || strncmp(up->text, "8l", 2) != 0)
162 iprint("%d consecutive faults for va %#p at pc %#p in %s "
163 "pid %ld\n", lflt.cnt, lflt.va, pc, up->text, lflt.pid);
164 iprint("\t%s: %s%s r31 %#lux tlbvirt %#lux\n",
165 excname[code], va == pc? "[instruction] ": "",
166 (read? "read": "write"), ur->r31, tlbvirt());
171 faultsprint(char *p, char *ep)
175 "max consecutive faults %d for va %#p in %s\n",
176 maxflt.cnt, maxflt.va, maxflt.prog);
181 * find out fault address and type of access.
182 * Call common fault handler.
185 faultmips(Ureg *ur, int user, int code)
189 char *p, buf[ERRMAX];
194 read = !(code==CTLBM || code==CTLBS);
196 /* print("fault: %s code %d va %#p pc %#p r31 %#lux tlbvirt %#lux\n",
197 up->text, code, ur->badvaddr, ur->pc, ur->r31, tlbvirt());/**/
199 if (Debug && ckfaultstuck(ur, read, code) || fault(addr, read) == 0)
206 snprint(buf, sizeof buf, "sys: trap: fault %s addr=%#lux r31=%#lux",
207 p, ur->badvaddr, ur->r31);
208 postnote(up, 1, buf, NDebug);
214 print("kernel %s vaddr=%#lux\n", excname[code], ur->badvaddr);
215 print("st=%#lux pc=%#lux r31=%#lux sp=%#lux\n",
216 ur->status, ur->pc, ur->r31, ur->sp);
222 * called in syscallfmt.c, sysfile.c, sysproc.c
225 validalign(uintptr addr, unsigned align)
228 * Plan 9 is a 32-bit O/S, and the hardware it runs on
229 * does not usually have instructions which move 64-bit
230 * quantities directly, synthesizing the operations
231 * with 32-bit move instructions. Therefore, the compiler
232 * (and hardware) usually only enforce 32-bit alignment,
235 * Take this out if the architecture warrants it.
237 if(align == sizeof(vlong))
238 align = sizeof(long);
241 * Check align is a power of 2, then addr alignment.
243 if((align != 0 && !(align & (align-1))) && !(addr & (align-1)))
245 postnote(up, 1, "sys: odd address", NDebug);