trap.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. #include <tos.h>
  16. #include "ureg.h"
  17. #include "../port/pmc.h"
  18. #include "io.h"
  19. #include "amd64.h"
  20. // counters. Set by assembly code.
  21. // interrupt enter and exit, systecm call enter and exit.
  22. unsigned long ire, irx, sce, scx;
  23. // Did we start doing an exit for the interrupts?
  24. // ir exit entry :-)
  25. unsigned long irxe;
  26. extern int notify(Ureg*);
  27. static void debugbpt(Ureg*, void*);
  28. static void faultamd64(Ureg*, void*);
  29. static void doublefault(Ureg*, void*);
  30. static void unexpected(Ureg*, void*);
  31. static void expected(Ureg*, void*);
  32. static void dumpstackwithureg(Ureg*);
  33. static Lock vctllock;
  34. static Vctl *vctl[256];
  35. typedef struct Intrtime Intrtime;
  36. struct Intrtime {
  37. uint64_t count;
  38. uint64_t cycles;
  39. };
  40. static Intrtime intrtimes[256];
  41. void*
  42. intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
  43. {
  44. int vno;
  45. Vctl *v;
  46. extern int ioapicintrenable(Vctl*);
  47. if(f == nil){
  48. print("intrenable: nil handler for %d, tbdf %#ux for %s\n",
  49. irq, tbdf, name);
  50. return nil;
  51. }
  52. v = malloc(sizeof(Vctl));
  53. v->isintr = 1;
  54. v->irq = irq;
  55. v->tbdf = tbdf;
  56. v->f = f;
  57. v->a = a;
  58. strncpy(v->name, name, KNAMELEN-1);
  59. v->name[KNAMELEN-1] = 0;
  60. ilock(&vctllock);
  61. vno = ioapicintrenable(v);
  62. if(vno == -1){
  63. iunlock(&vctllock);
  64. print("intrenable: couldn't enable irq %d, tbdf %#ux for %s\n",
  65. irq, tbdf, v->name);
  66. free(v);
  67. return nil;
  68. }
  69. if(vctl[vno]){
  70. if(vctl[v->vno]->isr != v->isr || vctl[v->vno]->eoi != v->eoi)
  71. panic("intrenable: handler: %s %s %#p %#p %#p %#p",
  72. vctl[v->vno]->name, v->name,
  73. vctl[v->vno]->isr, v->isr, vctl[v->vno]->eoi, v->eoi);
  74. }
  75. v->vno = vno;
  76. v->next = vctl[vno];
  77. vctl[vno] = v;
  78. iunlock(&vctllock);
  79. if(v->mask)
  80. v->mask(v, 0);
  81. /*
  82. * Return the assigned vector so intrdisable can find
  83. * the handler; the IRQ is useless in the wonderful world
  84. * of the IOAPIC.
  85. */
  86. return v;
  87. }
  88. int
  89. intrdisable(void* vector)
  90. {
  91. Vctl *v, *x, **ll;
  92. extern int ioapicintrdisable(int);
  93. ilock(&vctllock);
  94. v = vector;
  95. if(v == nil || vctl[v->vno] != v)
  96. panic("intrdisable: v %#p", v);
  97. for(ll = vctl+v->vno; x = *ll; ll = &x->next)
  98. if(v == x)
  99. break;
  100. if(x != v)
  101. panic("intrdisable: v %#p", v);
  102. if(v->mask)
  103. v->mask(v, 1);
  104. v->f(nil, v->a);
  105. *ll = v->next;
  106. ioapicintrdisable(v->vno);
  107. iunlock(&vctllock);
  108. free(v);
  109. return 0;
  110. }
  111. static int32_t
  112. irqallocread(Chan* c, void *vbuf, int32_t n, int64_t offset)
  113. {
  114. char *buf, *p, str[2*(11+1)+2*(20+1)+(KNAMELEN+1)+(8+1)+1];
  115. int m, vno;
  116. int32_t oldn;
  117. Intrtime *t;
  118. Vctl *v;
  119. if(n < 0 || offset < 0)
  120. error(Ebadarg);
  121. oldn = n;
  122. buf = vbuf;
  123. for(vno=0; vno<nelem(vctl); vno++){
  124. for(v=vctl[vno]; v; v=v->next){
  125. t = intrtimes + vno;
  126. m = snprint(str, sizeof str, "%11d %11d %20llud %20llud %-*.*s %.*s\n",
  127. vno, v->irq, t->count, t->cycles, 8, 8, v->type, KNAMELEN, v->name);
  128. if(m <= offset) /* if do not want this, skip entry */
  129. offset -= m;
  130. else{
  131. /* skip offset bytes */
  132. m -= offset;
  133. p = str+offset;
  134. offset = 0;
  135. /* write at most max(n,m) bytes */
  136. if(m > n)
  137. m = n;
  138. memmove(buf, p, m);
  139. n -= m;
  140. buf += m;
  141. if(n == 0)
  142. return oldn;
  143. }
  144. }
  145. }
  146. return oldn - n;
  147. }
  148. void
  149. trapenable(int vno, void (*f)(Ureg*, void*), void* a, char *name)
  150. {
  151. Vctl *v;
  152. if(vno < 0 || vno >= 256)
  153. panic("trapenable: vno %d\n", vno);
  154. v = malloc(sizeof(Vctl));
  155. v->type = "trap";
  156. v->tbdf = BUSUNKNOWN;
  157. v->f = f;
  158. v->a = a;
  159. strncpy(v->name, name, KNAMELEN);
  160. v->name[KNAMELEN-1] = 0;
  161. ilock(&vctllock);
  162. v->next = vctl[vno];
  163. vctl[vno] = v;
  164. iunlock(&vctllock);
  165. }
  166. static void
  167. nmienable(void)
  168. {
  169. int x;
  170. /*
  171. * Hack: should be locked with NVRAM access.
  172. */
  173. outb(0x70, 0x80); /* NMI latch clear */
  174. outb(0x70, 0);
  175. x = inb(0x61) & 0x07; /* Enable NMI */
  176. outb(0x61, 0x08|x);
  177. outb(0x61, x);
  178. }
  179. void
  180. trapinit(void)
  181. {
  182. /*
  183. * Need to set BPT interrupt gate - here or in vsvminit?
  184. */
  185. /*
  186. * Special traps.
  187. * Syscall() is called directly without going through trap().
  188. */
  189. trapenable(VectorBPT, debugbpt, 0, "#BP");
  190. trapenable(VectorPF, faultamd64, 0, "#PF");
  191. trapenable(Vector2F, doublefault, 0, "#DF");
  192. intrenable(IdtIPI, expected, 0, BUSUNKNOWN, "#IPI");
  193. trapenable(Vector15, unexpected, 0, "#15");
  194. nmienable();
  195. addarchfile("irqalloc", 0444, irqallocread, nil);
  196. }
  197. static char* excname[32] = {
  198. "#DE", /* Divide-by-Zero Error */
  199. "#DB", /* Debug */
  200. "#NMI", /* Non-Maskable-Interrupt */
  201. "#BP", /* Breakpoint */
  202. "#OF", /* Overflow */
  203. "#BR", /* Bound-Range */
  204. "#UD", /* Invalid-Opcode */
  205. "#NM", /* Device-Not-Available */
  206. "#DF", /* Double-Fault */
  207. "#9 (reserved)",
  208. "#TS", /* Invalid-TSS */
  209. "#NP", /* Segment-Not-Present */
  210. "#SS", /* Stack */
  211. "#GP", /* General-Protection */
  212. "#PF", /* Page-Fault */
  213. "#15 (reserved)",
  214. "#MF", /* x87 FPE-Pending */
  215. "#AC", /* Alignment-Check */
  216. "#MC", /* Machine-Check */
  217. "#XF", /* SIMD Floating-Point */
  218. "#20 (reserved)",
  219. "#21 (reserved)",
  220. "#22 (reserved)",
  221. "#23 (reserved)",
  222. "#24 (reserved)",
  223. "#25 (reserved)",
  224. "#26 (reserved)",
  225. "#27 (reserved)",
  226. "#28 (reserved)",
  227. "#29 (reserved)",
  228. "#30 (reserved)",
  229. "#31 (reserved)",
  230. };
  231. /*
  232. * keep interrupt service times and counts
  233. */
  234. void
  235. intrtime(int vno)
  236. {
  237. Proc *up = externup();
  238. uint32_t diff, x; /* should be uint64_t */
  239. x = perfticks();
  240. diff = x - machp()->perf.intrts;
  241. machp()->perf.intrts = x;
  242. machp()->perf.inintr += diff;
  243. if(up == nil && machp()->perf.inidle > diff)
  244. machp()->perf.inidle -= diff;
  245. intrtimes[vno].cycles += diff;
  246. intrtimes[vno].count++;
  247. }
  248. static void
  249. pmcnop(Mach *m)
  250. {
  251. }
  252. void (*_pmcupdate)(Mach *m) = pmcnop;
  253. /* go to user space */
  254. void
  255. kexit(Ureg* u)
  256. {
  257. Proc *up = externup();
  258. uint64_t t;
  259. Tos *tos;
  260. Mach *mp;
  261. /*
  262. * precise time accounting, kernel exit
  263. * initialized in exec, sysproc.c
  264. */
  265. tos = (Tos*)(USTKTOP-sizeof(Tos));
  266. cycles(&t);
  267. tos->kcycles += t - up->kentry;
  268. tos->pcycles = up->pcycles;
  269. tos->pid = up->pid;
  270. if (up->ac != nil)
  271. mp = up->ac;
  272. else
  273. mp = machp();
  274. tos->core = mp->machno;
  275. tos->nixtype = mp->nixtype;
  276. //_pmcupdate(m);
  277. /*
  278. * The process may change its core.
  279. * Be sure it has the right cyclefreq.
  280. */
  281. tos->cyclefreq = mp->cyclefreq;
  282. /* thread local storage */
  283. wrmsr(FSbase, up->tls);
  284. }
  285. void
  286. kstackok(void)
  287. {
  288. Proc *up = externup();
  289. if(up == nil){
  290. uintptr_t *stk = (uintptr_t*)machp()->stack;
  291. if(*stk != STACKGUARD)
  292. panic("trap: mach %d machstk went through bottom %p\n", machp()->machno, machp()->stack);
  293. } else {
  294. uintptr_t *stk = (uintptr_t*)up->kstack;
  295. if(*stk != STACKGUARD)
  296. panic("trap: proc %d kstack went through bottom %p\n", up->pid, up->kstack);
  297. }
  298. }
  299. void
  300. _trap(Ureg *ureg)
  301. {
  302. /*
  303. * If it's a real trap in this core, then we want to
  304. * use the hardware cr2 register.
  305. * We cannot do this in trap() because application cores
  306. * would update m->cr2 with their cr2 values upon page faults,
  307. * and then call trap().
  308. * If we do this in trap(), we would overwrite that with our own cr2.
  309. */
  310. if(ureg->type == VectorPF)
  311. machp()->cr2 = cr2get();
  312. trap(ureg);
  313. }
  314. /*
  315. * All traps come here. It is slower to have all traps call trap()
  316. * rather than directly vectoring the handler. However, this avoids a
  317. * lot of code duplication and possible bugs. The only exception is
  318. * VectorSYSCALL.
  319. * Trap is called with interrupts disabled via interrupt-gates.
  320. */
  321. void
  322. trap(Ureg* ureg)
  323. {
  324. int clockintr, vno, user;
  325. // cache the previous vno to see what might be causing
  326. // trouble
  327. static int lastvno;
  328. vno = ureg->type;
  329. uint64_t gsbase = rdmsr(GSbase);
  330. //if (sce > scx) iprint("====================");
  331. if (vno == 8) {
  332. iprint("Lstar is %p\n", (void *)rdmsr(Lstar));
  333. iprint("GSbase is %p\n", (void *)gsbase);
  334. iprint("ire %d irx %d sce %d scx %d lastvno %d\n",
  335. ire, irx, sce, scx, lastvno);
  336. iprint("irxe %d \n",
  337. irxe);
  338. die("8");
  339. }
  340. lastvno = vno;
  341. if (gsbase < 1ULL<<63)
  342. die("bogus gsbase");
  343. Proc *up = externup();
  344. char buf[ERRMAX];
  345. Vctl *ctl, *v;
  346. if (0 && machp() && up && up->pid == 6) {
  347. //iprint("type %x\n", ureg->type);
  348. if (ureg->type != 0x49)
  349. die("6\n");
  350. }
  351. machp()->perf.intrts = perfticks();
  352. user = userureg(ureg);
  353. if(user && (machp()->nixtype == NIXTC)){
  354. up->dbgreg = ureg;
  355. cycles(&up->kentry);
  356. }
  357. clockintr = 0;
  358. //_pmcupdate(machp());
  359. if(ctl = vctl[vno]){
  360. if(ctl->isintr){
  361. machp()->intr++;
  362. if(vno >= VectorPIC && vno != VectorSYSCALL)
  363. machp()->lastintr = ctl->irq;
  364. }else
  365. if(up)
  366. up->nqtrap++;
  367. if(ctl->isr)
  368. ctl->isr(vno);
  369. for(v = ctl; v != nil; v = v->next){
  370. if(v->f)
  371. v->f(ureg, v->a);
  372. }
  373. if(ctl->eoi)
  374. ctl->eoi(vno);
  375. intrtime(vno);
  376. if(ctl->isintr){
  377. if(ctl->irq == IrqCLOCK || ctl->irq == IrqTIMER)
  378. clockintr = 1;
  379. if(up && !clockintr)
  380. preempted();
  381. }
  382. }
  383. else if(vno < nelem(excname) && user){
  384. spllo();
  385. snprint(buf, sizeof buf, "sys: trap: %s", excname[vno]);
  386. postnote(up, 1, buf, NDebug);
  387. }
  388. else if(vno >= VectorPIC && vno != VectorSYSCALL){
  389. /*
  390. * An unknown interrupt.
  391. * Check for a default IRQ7. This can happen when
  392. * the IRQ input goes away before the acknowledge.
  393. * In this case, a 'default IRQ7' is generated, but
  394. * the corresponding bit in the ISR isn't set.
  395. * In fact, just ignore all such interrupts.
  396. */
  397. /* clear the interrupt */
  398. i8259isr(vno);
  399. iprint("cpu%d: spurious interrupt %d, last %d\n",
  400. machp()->machno, vno, machp()->lastintr);
  401. intrtime(vno);
  402. if(user)
  403. kexit(ureg);
  404. return;
  405. }
  406. else{
  407. if(vno == VectorNMI){
  408. nmienable();
  409. if(machp()->machno != 0){
  410. iprint("cpu%d: PC %#llux\n",
  411. machp()->machno, ureg->ip);
  412. for(;;);
  413. }
  414. }
  415. dumpregs(ureg);
  416. if(!user){
  417. ureg->sp = PTR2UINT(&ureg->sp);
  418. dumpstackwithureg(ureg);
  419. }
  420. if(vno < nelem(excname))
  421. panic("%s", excname[vno]);
  422. panic("unknown trap/intr: %d\n", vno);
  423. }
  424. splhi();
  425. /* delaysched set because we held a lock or because our quantum ended */
  426. if(up && up->delaysched && clockintr){
  427. if(0)
  428. if(user && up->ac == nil && up->nqtrap == 0 && up->nqsyscall == 0){
  429. if(!waserror()){
  430. up->ac = getac(up, -1);
  431. poperror();
  432. runacore();
  433. return;
  434. }
  435. }
  436. sched();
  437. splhi();
  438. }
  439. if(user){
  440. if(up && up->procctl || up->nnote)
  441. notify(ureg);
  442. kexit(ureg);
  443. }
  444. }
  445. /*
  446. * Dump general registers.
  447. */
  448. void
  449. dumpgpr(Ureg* ureg)
  450. {
  451. Proc *up = externup();
  452. if(up != nil)
  453. iprint("cpu%d: registers for %s %d\n",
  454. machp()->machno, up->text, up->pid);
  455. else
  456. iprint("cpu%d: registers for kernel\n", machp()->machno);
  457. iprint("ax\t%#16.16llux\n", ureg->ax);
  458. iprint("bx\t%#16.16llux\n", ureg->bx);
  459. iprint("cx\t%#16.16llux\n", ureg->cx);
  460. iprint("dx\t%#16.16llux\n", ureg->dx);
  461. iprint("di\t%#16.16llux\n", ureg->di);
  462. iprint("si\t%#16.16llux\n", ureg->si);
  463. iprint("bp\t%#16.16llux\n", ureg->bp);
  464. iprint("r8\t%#16.16llux\n", ureg->r8);
  465. iprint("r9\t%#16.16llux\n", ureg->r9);
  466. iprint("r10\t%#16.16llux\n", ureg->r10);
  467. iprint("r11\t%#16.16llux\n", ureg->r11);
  468. iprint("r12\t%#16.16llux\n", ureg->r12);
  469. iprint("r13\t%#16.16llux\n", ureg->r13);
  470. iprint("r14\t%#16.16llux\n", ureg->r14);
  471. iprint("r15\t%#16.16llux\n", ureg->r15);
  472. iprint("type\t%#llux\n", ureg->type);
  473. iprint("error\t%#llux\n", ureg->error);
  474. iprint("pc\t%#llux\n", ureg->ip);
  475. iprint("cs\t%#llux\n", ureg->cs);
  476. iprint("flags\t%#llux\n", ureg->flags);
  477. iprint("sp\t%#llux\n", ureg->sp);
  478. iprint("ss\t%#llux\n", ureg->ss);
  479. iprint("type\t%#llux\n", ureg->type);
  480. iprint("FS\t%#llux\n", rdmsr(FSbase));
  481. iprint("GS\t%#llux\n", rdmsr(GSbase));
  482. iprint("m\t%#16.16p\nup\t%#16.16p\n", machp(), up);
  483. }
  484. void
  485. dumpregs(Ureg* ureg)
  486. {
  487. dumpgpr(ureg);
  488. /*
  489. * Processor control registers.
  490. * If machine check exception, time stamp counter, page size extensions
  491. * or enhanced virtual 8086 mode extensions are supported, there is a
  492. * CR4. If there is a CR4 and machine check extensions, read the machine
  493. * check address and machine check type registers if RDMSR supported.
  494. */
  495. iprint("cr0\t%#16.16llux\n", cr0get());
  496. iprint("cr2\t%#16.16llux\n", machp()->cr2);
  497. iprint("cr3\t%#16.16llux\n", cr3get());
  498. die("dumpregs");
  499. // archdumpregs();
  500. }
  501. /*
  502. * Fill in enough of Ureg to get a stack trace, and call a function.
  503. * Used by debugging interface rdb.
  504. */
  505. void
  506. callwithureg(void (*fn)(Ureg*))
  507. {
  508. Ureg ureg;
  509. ureg.ip = getcallerpc(&fn);
  510. ureg.sp = PTR2UINT(&fn);
  511. fn(&ureg);
  512. }
  513. static void
  514. dumpstackwithureg(Ureg* ureg)
  515. {
  516. Proc *up = externup();
  517. uintptr_t l, v, i, estack;
  518. // extern char etext;
  519. int x;
  520. if (0) { //if((s = getconf("*nodumpstack")) != nil && atoi(s) != 0){
  521. iprint("dumpstack disabled\n");
  522. return;
  523. }
  524. iprint("dumpstack\n");
  525. x = 0;
  526. x += iprint("ktrace 9%s %#p %#p\n", strrchr(conffile, '/')+1, ureg->ip, ureg->sp);
  527. i = 0;
  528. if(up != nil
  529. // && (uintptr)&l >= (uintptr)up->kstack
  530. && (uintptr_t)&l <= (uintptr_t)up->kstack+KSTACK)
  531. estack = (uintptr_t)up->kstack+KSTACK;
  532. else if((uintptr_t)&l >= machp()->stack && (uintptr_t)&l <= machp()->stack+MACHSTKSZ)
  533. estack = machp()->stack+MACHSTKSZ;
  534. else{
  535. if(up != nil)
  536. iprint("&up->kstack %#p &l %#p\n", up->kstack, &l);
  537. else
  538. iprint("&m %#p &l %#p\n", machp(), &l);
  539. return;
  540. }
  541. x += iprint("estackx %#p\n", estack);
  542. for(l = (uintptr_t)&l; l < estack; l += sizeof(uintptr_t)){
  543. v = *(uintptr_t*)l;
  544. if((KTZERO < v && v < (uintptr_t)&etext)
  545. || ((uintptr_t)&l < v && v < estack) || estack-l < 256){
  546. x += iprint("%#16.16p=%#16.16p ", l, v);
  547. i++;
  548. }
  549. if(i == 2){
  550. i = 0;
  551. x += iprint("\n");
  552. }
  553. }
  554. if(i)
  555. iprint("\n");
  556. }
  557. void
  558. dumpstack(void)
  559. {
  560. callwithureg(dumpstackwithureg);
  561. }
  562. static void
  563. debugbpt(Ureg* ureg, void* v)
  564. {
  565. Proc *up = externup();
  566. char buf[ERRMAX];
  567. if(up == 0)
  568. panic("kernel bpt");
  569. /* restore pc to instruction that caused the trap */
  570. ureg->ip--;
  571. sprint(buf, "sys: breakpoint");
  572. postnote(up, 1, buf, NDebug);
  573. }
  574. static void
  575. doublefault(Ureg* ureg, void* v)
  576. {
  577. iprint("cr2 %p\n", (void *)cr2get());
  578. panic("double fault");
  579. }
  580. static void
  581. unexpected(Ureg* ureg, void* v)
  582. {
  583. iprint("unexpected trap %llud; ignoring\n", ureg->type);
  584. }
  585. static void
  586. expected(Ureg* ureg, void* v)
  587. {
  588. }
  589. static void
  590. faultamd64(Ureg* ureg, void* v)
  591. {
  592. Proc *up = externup();
  593. uint64_t addr;
  594. int ftype, user, insyscall;
  595. char buf[ERRMAX];
  596. addr = machp()->cr2;
  597. user = userureg(ureg);
  598. if(!user && mmukmapsync(addr))
  599. return;
  600. /*
  601. * There must be a user context.
  602. * If not, the usual problem is causing a fault during
  603. * initialisation before the system is fully up.
  604. */
  605. if(up == nil){
  606. panic("fault with up == nil; pc %#llux addr %#llux\n",
  607. ureg->ip, addr);
  608. }
  609. ftype = (ureg->error&2) ? FT_WRITE : (ureg->error&16) ? FT_EXEC : FT_READ;
  610. /*
  611. if (read) hi("read fault\n"); else hi("write fault\n");
  612. hi("addr "); put64(addr); hi("\n");
  613. */
  614. insyscall = up->insyscall;
  615. up->insyscall = 1;
  616. if (0)hi("call fault\n");
  617. if(fault(addr, ureg->ip, ftype) < 0){
  618. iprint("could not %s fault %p\n", faulttypes[ftype], addr);
  619. if (! user)
  620. panic("fault went bad in kernel\n");
  621. else
  622. /*
  623. * It is possible to get here with !user if, for example,
  624. * a process was in a system call accessing a shared
  625. * segment but was preempted by another process which shrunk
  626. * or deallocated the shared segment; when the original
  627. * process resumes it may fault while in kernel mode.
  628. * No need to panic this case, post a note to the process
  629. * and unwind the error stack. There must be an error stack
  630. * (up->nerrlab != 0) if this is a system call, if not then
  631. * the game's a bogey.
  632. */
  633. if(!user && (!insyscall || up->nerrlab == 0))
  634. panic("fault: %#llux\n", addr);
  635. sprint(buf, "sys: trap: fault %s addr=%#llux",
  636. faulttypes[ftype], addr);
  637. postnote(up, 1, buf, NDebug);
  638. if(insyscall)
  639. error(buf);
  640. }
  641. up->insyscall = insyscall;
  642. }
  643. /*
  644. * return the userpc the last exception happened at
  645. */
  646. uintptr_t
  647. userpc(Ureg* ureg)
  648. {
  649. Proc *up = externup();
  650. if(ureg == nil)
  651. ureg = up->dbgreg;
  652. return ureg->ip;
  653. }
  654. /* This routine must save the values of registers the user is not permitted
  655. * to write from devproc and then restore the saved values before returning.
  656. * TODO: fix this because the segment registers are wrong for 64-bit mode.
  657. */
  658. void
  659. setregisters(Ureg* ureg, char* pureg, char* uva, int n)
  660. {
  661. uint64_t cs, flags, ss;
  662. ss = ureg->ss;
  663. flags = ureg->flags;
  664. cs = ureg->cs;
  665. memmove(pureg, uva, n);
  666. ureg->cs = cs;
  667. ureg->flags = (ureg->flags & 0x00ff) | (flags & 0xff00);
  668. ureg->ss = ss;
  669. }
  670. /* Give enough context in the ureg to produce a kernel stack for
  671. * a sleeping process
  672. */
  673. void
  674. setkernur(Ureg* ureg, Proc* p)
  675. {
  676. ureg->ip = p->sched.pc;
  677. ureg->sp = p->sched.sp+BY2SE;
  678. }
  679. uintptr_t
  680. dbgpc(Proc *p)
  681. {
  682. Ureg *ureg;
  683. ureg = p->dbgreg;
  684. if(ureg == 0)
  685. return 0;
  686. return ureg->ip;
  687. }