trap.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  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 "encoding.h"
  20. enum traps {
  21. InstructionAlignment = 0,
  22. InstructionAccessFault,
  23. IllegalInstruction,
  24. Breakpoint,
  25. Trap4Reserved,
  26. LoadAccessFault,
  27. AMOAddressMisaligned,
  28. Store_AMOAccessFault,
  29. EnvironmentCall,
  30. LastTrap = EnvironmentCall,
  31. InterruptMask = 0x8000000000000000ULL
  32. };
  33. enum interrupts {
  34. UserSoftware,
  35. SupervisorSoftware,
  36. Interrupt2Reserved,
  37. Interrupt3eserved,
  38. UserTimer,
  39. SupervisorTimer,
  40. LastInterrupt = SupervisorTimer
  41. };
  42. void msg(char *);
  43. int getchar(void);
  44. // counters. Set by assembly code.
  45. // interrupt enter and exit, systecm call enter and exit.
  46. unsigned long ire, irx, sce, scx;
  47. // Did we start doing an exit for the interrupts?
  48. // ir exit entry :-)
  49. unsigned long irxe;
  50. extern int notify(Ureg*);
  51. //static void debugbpt(Ureg*, void*);
  52. static void faultarch(Ureg*);
  53. //static void doublefault(Ureg*, void*);
  54. //static void unexpected(Ureg*, void*);
  55. //static void expected(Ureg*, void*);
  56. static void dumpstackwithureg(Ureg*);
  57. //extern int bus_irq_setup(Vctl*);
  58. static Lock vctllock;
  59. static Vctl *vctl[256];
  60. typedef struct Intrtime Intrtime;
  61. struct Intrtime {
  62. uint64_t count;
  63. uint64_t cycles;
  64. };
  65. static Intrtime intrtimes[256];
  66. void*
  67. intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
  68. {
  69. int vno;
  70. Vctl *v;
  71. if(f == nil){
  72. print("intrenable: nil handler for %d, tbdf %#x for %s\n",
  73. irq, tbdf, name);
  74. panic("FIX ME");
  75. return nil;
  76. }
  77. v = malloc(sizeof(Vctl));
  78. v->isintr = 1;
  79. v->Vkey.irq = irq;
  80. v->Vkey.tbdf = tbdf;
  81. v->f = f;
  82. v->a = a;
  83. strncpy(v->name, name, KNAMELEN-1);
  84. v->name[KNAMELEN-1] = 0;
  85. ilock(&vctllock);
  86. print(" ignoring bus_irq_setup");
  87. //vno = bus_irq_setup(v);
  88. vno = irq;
  89. if(vno == -1){
  90. iunlock(&vctllock);
  91. print("intrenable: couldn't enable irq %d, tbdf %#x for %s\n",
  92. irq, tbdf, v->name);
  93. panic("DIE");
  94. free(v);
  95. return nil;
  96. }
  97. if(vctl[vno]){
  98. if(vctl[v->vno]->isr != v->isr || vctl[v->vno]->eoi != v->eoi)
  99. print("intrenable: handler: %s %s %#p %#p %#p %#p",
  100. vctl[v->vno]->name, v->name,
  101. vctl[v->vno]->isr, v->isr, vctl[v->vno]->eoi, v->eoi);
  102. panic("CONFLICT");
  103. }
  104. v->vno = vno;
  105. v->next = vctl[vno];
  106. vctl[vno] = v;
  107. iunlock(&vctllock);
  108. if(v->mask)
  109. v->mask(&v->Vkey, 0);
  110. /*
  111. * Return the assigned vector so intrdisable can find
  112. * the handler; the IRQ is useless in the wonderful world
  113. * of the IOAPIC.
  114. */
  115. return v;
  116. }
  117. static const char *const excname[] = {
  118. "Instruction address misaligned",
  119. "Instruction access fault",
  120. "Illegal instruction",
  121. "Breakpoint",
  122. "Load address misaligned",
  123. "Load access fault",
  124. "Store address misaligned",
  125. "Store access fault",
  126. "Environment call from U-mode",
  127. "Environment call from S-mode",
  128. "Environment call from H-mode",
  129. "Environment call from M-mode"
  130. };
  131. static void print_trap_information(const Ureg *ureg)
  132. {
  133. Proc *up = externup();
  134. const char *previous_mode;
  135. int status = ureg->status;
  136. /* Leave some space around the trap message */
  137. print("\n PID %d\n", up ? up->pid : -1);
  138. if (ureg->cause < nelem(excname))
  139. print("Exception: %s\n",
  140. excname[ureg->cause]);
  141. else
  142. print("Trap: Unknown cause %p\n",
  143. (void *)ureg->cause);
  144. previous_mode = status & 0x100 ? "Supervisor" : "User";
  145. print("Previous mode: %s\n", previous_mode);
  146. print("Bad instruction pc: %p\n", (void *)ureg->epc);
  147. print("Bad address: %p\n", (void *)ureg->badaddr);
  148. print("Stored ip: %p\n", (void*) ureg->ip);
  149. print("Stored sp: %p\n", (void*) ureg->sp);
  150. }
  151. void trap_handler(Ureg *ureg) {
  152. switch(ureg->cause) {
  153. case CAUSE_MISALIGNED_FETCH:
  154. print_trap_information(ureg);
  155. panic("misaligned fetch, firmware is supposed to do this");
  156. return;
  157. break;
  158. case CAUSE_ILLEGAL_INSTRUCTION:
  159. print_trap_information(ureg);
  160. panic("illegal instruction, going to die");
  161. return;
  162. break;
  163. case CAUSE_BREAKPOINT:
  164. print_trap_information(ureg);
  165. panic("can't handle breakpoints yet\n");
  166. return;
  167. break;
  168. case CAUSE_FAULT_FETCH:
  169. case CAUSE_FAULT_LOAD:
  170. case CAUSE_FAULT_STORE:
  171. if (0) print_trap_information(ureg);
  172. faultarch(ureg);
  173. return;
  174. break;
  175. case CAUSE_USER_ECALL:
  176. case CAUSE_HYPERVISOR_ECALL:
  177. case CAUSE_MACHINE_ECALL:
  178. print_trap_information(ureg);
  179. panic("Can't do ecalls here");
  180. return;
  181. break;
  182. case CAUSE_MISALIGNED_LOAD:
  183. print("hgroup 2\n");
  184. print_trap_information(ureg);
  185. panic("misaligned LOAD, we don't do these");
  186. return;
  187. break;
  188. case CAUSE_MISALIGNED_STORE:
  189. print_trap_information(ureg);
  190. panic("misaligned STORE, we don't do these");
  191. return;
  192. break;
  193. default:
  194. print_trap_information(ureg);
  195. panic("WTF\n");
  196. return;
  197. break;
  198. }
  199. }
  200. int
  201. intrdisable(void* vector)
  202. {
  203. Vctl *v, *x, **ll;
  204. //extern int ioapicintrdisable(int);
  205. ilock(&vctllock);
  206. v = vector;
  207. if(v == nil || vctl[v->vno] != v)
  208. panic("intrdisable: v %#p", v);
  209. for(ll = vctl+v->vno; x = *ll; ll = &x->next)
  210. if(v == x)
  211. break;
  212. if(x != v)
  213. panic("intrdisable: v %#p", v);
  214. if(v->mask)
  215. v->mask(&v->Vkey, 1);
  216. v->f(nil, v->a);
  217. *ll = v->next;
  218. panic("ioapicintrdisable");
  219. //ioapicintrdisable(v->vno);
  220. iunlock(&vctllock);
  221. free(v);
  222. return 0;
  223. }
  224. static int32_t
  225. irqallocread(Chan* c, void *vbuf, int32_t n, int64_t offset)
  226. {
  227. char *buf, *p, str[2*(11+1)+2*(20+1)+(KNAMELEN+1)+(8+1)+1];
  228. int m, vno;
  229. int32_t oldn;
  230. Intrtime *t;
  231. Vctl *v;
  232. if(n < 0 || offset < 0)
  233. error(Ebadarg);
  234. oldn = n;
  235. buf = vbuf;
  236. for(vno=0; vno<nelem(vctl); vno++){
  237. for(v=vctl[vno]; v; v=v->next){
  238. t = intrtimes + vno;
  239. m = snprint(str, sizeof str, "%11d %11d %20llu %20llu %-*.*s %.*s\n",
  240. vno, v->Vkey.irq, t->count, t->cycles, 8, 8, v->type, KNAMELEN, v->name);
  241. if(m <= offset) /* if do not want this, skip entry */
  242. offset -= m;
  243. else{
  244. /* skip offset bytes */
  245. m -= offset;
  246. p = str+offset;
  247. offset = 0;
  248. /* write at most max(n,m) bytes */
  249. if(m > n)
  250. m = n;
  251. memmove(buf, p, m);
  252. n -= m;
  253. buf += m;
  254. if(n == 0)
  255. return oldn;
  256. }
  257. }
  258. }
  259. return oldn - n;
  260. }
  261. void
  262. trapenable(int vno, void (*f)(Ureg*, void*), void* a, char *name)
  263. {
  264. Vctl *v;
  265. if(vno < 0 || vno >= 256)
  266. panic("trapenable: vno %d\n", vno);
  267. v = malloc(sizeof(Vctl));
  268. v->type = "trap";
  269. v->Vkey.tbdf = -1;
  270. v->f = f;
  271. v->a = a;
  272. strncpy(v->name, name, KNAMELEN);
  273. v->name[KNAMELEN-1] = 0;
  274. ilock(&vctllock);
  275. v->next = vctl[vno];
  276. vctl[vno] = v;
  277. iunlock(&vctllock);
  278. }
  279. #if 0
  280. static void
  281. nmienable(void)
  282. {
  283. panic("nmienable");
  284. }
  285. #endif
  286. static void riscvtimer(struct Ureg *u, void *_)
  287. {
  288. timerintr(u, 0);
  289. }
  290. void
  291. trapinit(void)
  292. {
  293. // basically done in firmware.
  294. addarchfile("irqalloc", 0444, irqallocread, nil);
  295. intrenable(5, riscvtimer, nil, 0, "timer");
  296. }
  297. /*
  298. * keep interrupt service times and counts
  299. */
  300. void
  301. intrtime(int vno)
  302. {
  303. Proc *up = externup();
  304. uint64_t diff, x;
  305. x = perfticks();
  306. diff = x - machp()->perf.intrts;
  307. machp()->perf.intrts = x;
  308. machp()->perf.inintr += diff;
  309. if(up == nil && machp()->perf.inidle > diff)
  310. machp()->perf.inidle -= diff;
  311. intrtimes[vno].cycles += diff;
  312. intrtimes[vno].count++;
  313. }
  314. static void
  315. pmcnop(Mach *m)
  316. {
  317. }
  318. void (*_pmcupdate)(Mach *m) = pmcnop;
  319. /* go to user space */
  320. void
  321. kexit(Ureg* u)
  322. {
  323. Proc *up = externup();
  324. uint64_t t;
  325. Tos *tos;
  326. Mach *mp;
  327. /*
  328. * precise time accounting, kernel exit
  329. * initialized in exec, sysproc.c
  330. */
  331. tos = (Tos*)(USTKTOP-sizeof(Tos));
  332. if (0) print("USTKTOP %p sizeof(Tos) %d tos %p\n", (void *)USTKTOP, sizeof(Tos), tos);
  333. cycles(&t);
  334. if (1) {
  335. if (0) print("tos is %p, &tos->kcycles is %p, up is %p\n", tos, &tos->kcycles, up);
  336. tos->kcycles += t - up->kentry;
  337. tos->pcycles = up->pcycles;
  338. tos->pid = up->pid;
  339. if (up->ac != nil)
  340. mp = up->ac;
  341. else
  342. mp = machp();
  343. if (0) print("kexit: mp is %p\n", mp);
  344. tos->core = mp->machno;
  345. if (0) print("kexit: mp is %p\n", mp);
  346. tos->nixtype = mp->NIX.nixtype;
  347. if (0) print("kexit: mp is %p\n", mp);
  348. //_pmcupdate(m);
  349. /*
  350. * The process may change its core.
  351. * Be sure it has the right cyclefreq.
  352. */
  353. tos->cyclefreq = mp->cyclefreq;
  354. if (0) print("kexit: mp is %p\n", mp);
  355. }
  356. if (0) print("kexit: done\n");
  357. }
  358. void
  359. kstackok(void)
  360. {
  361. Proc *up = externup();
  362. if(up == nil){
  363. uintptr_t *stk = (uintptr_t*)machp()->stack;
  364. if(*stk != STACKGUARD)
  365. panic("trap: mach %d machstk went through bottom %p\n", machp()->machno, machp()->stack);
  366. } else {
  367. uintptr_t *stk = (uintptr_t*)up->kstack;
  368. if(*stk != STACKGUARD)
  369. panic("trap: proc %d kstack went through bottom %p\n", up->pid, up->kstack);
  370. }
  371. }
  372. void
  373. _trap(Ureg *ureg)
  374. {
  375. if (0) msg("+trap\n");
  376. if (0) print("_trap\n");
  377. /*
  378. * If it's a real trap in this core, then we want to
  379. * use the hardware cr2 register.
  380. * We cannot do this in trap() because application cores
  381. * would update m->cr2 with their cr2 values upon page faults,
  382. * and then call trap().
  383. * If we do this in trap(), we would overwrite that with our own cr2.
  384. */
  385. switch(ureg->cause){
  386. case CAUSE_FAULT_FETCH:
  387. ureg->ftype = FT_EXEC;
  388. machp()->MMU.badaddr = ureg->badaddr;
  389. break;
  390. case CAUSE_FAULT_LOAD:
  391. ureg->ftype = FT_READ;
  392. machp()->MMU.badaddr = ureg->badaddr;
  393. break;
  394. case CAUSE_FAULT_STORE:
  395. ureg->ftype = FT_WRITE;
  396. machp()->MMU.badaddr = ureg->badaddr;
  397. break;
  398. }
  399. trap(ureg);
  400. }
  401. void consread(void)
  402. {
  403. int c;
  404. if (0) print("consrad\n");
  405. c = getchar();
  406. if (c >= 0) {
  407. if (0) print("WROTE '%c'\n", c);
  408. void kbdputsc(int data, int _);
  409. kbdputsc(c, 0);
  410. }
  411. }
  412. static int lastvno;
  413. /*
  414. * All traps come here. It is slower to have all traps call trap()
  415. * rather than directly vectoring the handler. However, this avoids a
  416. * lot of code duplication and possible bugs. The only exception is
  417. * VectorSYSCALL.
  418. * Trap is called with interrupts disabled via interrupt-gates.
  419. */
  420. void
  421. trap(Ureg *ureg)
  422. {
  423. int clockintr, vno, user, interrupt;
  424. // cache the previous vno to see what might be causing
  425. // trouble
  426. vno = ureg->cause & ~InterruptMask;
  427. interrupt = !! (ureg->cause & InterruptMask);
  428. //print("T 0x%llx", ureg->cause);
  429. Mach *m =machp();
  430. //if (sce > scx) iprint("====================");
  431. lastvno = vno;
  432. if (m < (Mach *)(1ULL<<63))
  433. die("bogus mach");
  434. Proc *up = externup();
  435. char buf[ERRMAX];
  436. Vctl *ctl, *v;
  437. machp()->perf.intrts = perfticks();
  438. user = userureg(ureg);
  439. if(user && (machp()->NIX.nixtype == NIXTC)){
  440. if (0)print("call cycles\n");
  441. up->dbgreg = ureg;
  442. cycles(&up->kentry);
  443. if (0)print("done\n");
  444. }
  445. clockintr = interrupt && vno == SupervisorTimer;
  446. if (0 && clockintr) print("C");
  447. //print("clockintr %d\n", clockintr);
  448. //_pmcupdate(machp());
  449. if (!interrupt){
  450. if (0) print("trap_handler\n");
  451. trap_handler(ureg);
  452. } else {
  453. write_csr(sip, 0);
  454. //print("check vno %d\n", vno);
  455. if(ctl = vctl[vno]){
  456. if(ctl->isintr){
  457. machp()->intr++;
  458. machp()->lastintr = ctl->Vkey.irq;
  459. }else
  460. if(up)
  461. up->nqtrap++;
  462. if(ctl->isr){
  463. ctl->isr(vno);
  464. if(islo())print("trap %d: isr %p enabled interrupts\n", vno, ctl->isr);
  465. }
  466. for(v = ctl; v != nil; v = v->next){
  467. if(v->f){
  468. if (0) print("F");
  469. v->f(ureg, v->a);
  470. if(islo())print("trap %d: ctlf %p enabled interrupts\n", vno, v->f);
  471. }
  472. }
  473. if(ctl->eoi){
  474. ctl->eoi(vno);
  475. if(islo())print("trap %d: eoi %p enabled interrupts\n", vno, ctl->eoi);
  476. }
  477. intrtime(vno);
  478. if(ctl->isintr){
  479. if (clockintr)
  480. oprof_alarm_handler(ureg);
  481. if(up && !clockintr)
  482. preempted();
  483. }
  484. } else if(vno < nelem(excname) && user){
  485. panic("OOR\n");
  486. spllo();
  487. snprint(buf, sizeof buf, "sys: trap: %s", excname[vno]);
  488. postnote(up, 1, buf, NDebug);
  489. } else if ((interrupt && vno > LastInterrupt) || (vno > LastTrap)) {
  490. panic("UNK\n");
  491. /*
  492. * An unknown interrupt.
  493. */
  494. iprint("cpu%d: spurious interrupt %d, last %d\n",
  495. machp()->machno, vno, machp()->lastintr);
  496. intrtime(vno);
  497. if(user)
  498. kexit(ureg);
  499. return;
  500. } else {
  501. #if 0
  502. if(vno == VectorNMI){
  503. nmienable();
  504. if(machp()->machno != 0){
  505. iprint("cpu%d: PC %#llx\n",
  506. machp()->machno, ureg->ip);
  507. for(;;);
  508. }
  509. }
  510. #endif
  511. if (0) dumpregs(ureg);
  512. if(!user){
  513. ureg->sp = PTR2UINT(&ureg->sp);
  514. dumpstackwithureg(ureg);
  515. }
  516. if(vno < nelem(excname))
  517. panic("%s", excname[vno]);
  518. panic("unknown trap/intr: %d\n", vno);
  519. }
  520. }
  521. splhi();
  522. /* delaysched set because we held a lock or because our quantum ended */
  523. if(up && up->delaysched && clockintr){
  524. #if 0
  525. if(0)
  526. if(user && up->ac == nil && up->nqtrap == 0 && up->nqsyscall == 0){
  527. if(!waserror()){
  528. up->ac = getac(up, -1);
  529. poperror();
  530. runacore();
  531. return;
  532. }
  533. }
  534. #endif
  535. sched();
  536. splhi();
  537. }
  538. //print("DUN\n");
  539. if(user){
  540. if(up && up->procctl || up->nnote)
  541. notify(ureg);
  542. print("K");
  543. kexit(ureg);
  544. }
  545. //print("ALL DONE TRAP\n");
  546. }
  547. /*
  548. * Dump general registers.
  549. */
  550. void
  551. dumpgpr(Ureg* ureg)
  552. {
  553. Proc *up = externup();
  554. if(up != nil)
  555. print("cpu%d: registers for %s %d\n",
  556. machp()->machno, up->text, up->pid);
  557. else
  558. print("cpu%d: registers for kernel\n", machp()->machno);
  559. print("ip %#llx\n", ureg->ip);
  560. print("sp %#llx\n", ureg->sp);
  561. print("gp %#llx\n", ureg->gp);
  562. print("tp %#llx\n", ureg->tp);
  563. print("t0 %#llx\n", ureg->t0);
  564. print("t1 %#llx\n", ureg->t1);
  565. print("t2 %#llx\n", ureg->t2);
  566. print("s0 %#llx\n", ureg->s0);
  567. print("s1 %#llx\n", ureg->s1);
  568. print("a0 %#llx\n", ureg->a0);
  569. print("a1 %#llx\n", ureg->a1);
  570. print("a2 %#llx\n", ureg->a2);
  571. print("a3 %#llx\n", ureg->a3);
  572. print("a4 %#llx\n", ureg->a4);
  573. print("a5 %#llx\n", ureg->a5);
  574. print("a6 %#llx\n", ureg->a6);
  575. print("a7 %#llx\n", ureg->a7);
  576. print("s2 %#llx\n", ureg->s2);
  577. print("s3 %#llx\n", ureg->s3);
  578. print("s4 %#llx\n", ureg->s4);
  579. print("s5 %#llx\n", ureg->s5);
  580. print("s6 %#llx\n", ureg->s6);
  581. print("s7 %#llx\n", ureg->s7);
  582. print("s8 %#llx\n", ureg->s8);
  583. print("s9 %#llx\n", ureg->s9);
  584. print("s10 %#llx\n", ureg->s10);
  585. print("s11 %#llx\n", ureg->s11);
  586. print("t3 %#llx\n", ureg->t3);
  587. print("t4 %#llx\n", ureg->t4);
  588. print("t5 %#llx\n", ureg->t5);
  589. print("t6 %#llx\n", ureg->t6);
  590. print("status %#llx\n", ureg->status);
  591. print("epc %#llx\n", ureg->epc);
  592. print("badaddr %#llx\n", ureg->badaddr);
  593. print("cause %#llx\n", ureg->cause);
  594. print("insnn %#llx\n", ureg->insnn);
  595. print("bp %#llx\n", ureg->bp);
  596. print("ftype %#llx\n", ureg->ftype);
  597. print("m\t%#16.16p\nup\t%#16.16p\n", machp(), up);
  598. }
  599. void
  600. dumpregs(Ureg* ureg)
  601. {
  602. dumpgpr(ureg);
  603. }
  604. /*
  605. * Fill in enough of Ureg to get a stack trace, and call a function.
  606. * Used by debugging interface rdb.
  607. */
  608. void
  609. callwithureg(void (*fn)(Ureg*))
  610. {
  611. Ureg ureg;
  612. ureg.ip = getcallerpc();
  613. ureg.sp = PTR2UINT(&fn);
  614. fn(&ureg);
  615. }
  616. static void
  617. dumpstackwithureg(Ureg* ureg)
  618. {
  619. Proc *up = externup();
  620. uintptr_t l, v, i, estack;
  621. // extern char etext;
  622. int x;
  623. if (0) { //if((s = getconf("*nodumpstack")) != nil && atoi(s) != 0){
  624. iprint("dumpstack disabled\n");
  625. return;
  626. }
  627. iprint("dumpstack\n");
  628. x = 0;
  629. //x += iprint("ktrace 9%s %#p %#p\n", strrchr(conffile, '/')+1, ureg->ip, ureg->sp);
  630. i = 0;
  631. if(up != nil
  632. // && (uintptr)&l >= (uintptr)up->kstack
  633. && (uintptr_t)&l <= (uintptr_t)up->kstack+KSTACK)
  634. estack = (uintptr_t)up->kstack+KSTACK;
  635. else if((uintptr_t)&l >= machp()->stack && (uintptr_t)&l <= machp()->stack+MACHSTKSZ)
  636. estack = machp()->stack+MACHSTKSZ;
  637. else{
  638. if(up != nil)
  639. iprint("&up->kstack %#p &l %#p\n", up->kstack, &l);
  640. else
  641. iprint("&m %#p &l %#p\n", machp(), &l);
  642. return;
  643. }
  644. x += iprint("estackx %#p\n", estack);
  645. for(l = (uintptr_t)&l; l < estack; l += sizeof(uintptr_t)){
  646. v = *(uintptr_t*)l;
  647. if((KTZERO < v && v < (uintptr_t)&etext)
  648. || ((uintptr_t)&l < v && v < estack) || estack-l < 256){
  649. x += iprint("%#16.16p=%#16.16p ", l, v);
  650. i++;
  651. }
  652. if(i == 2){
  653. i = 0;
  654. x += iprint("\n");
  655. }
  656. }
  657. if(i)
  658. iprint("\n");
  659. }
  660. void
  661. dumpstack(void)
  662. {
  663. callwithureg(dumpstackwithureg);
  664. }
  665. #if 0
  666. static void
  667. debugbpt(Ureg* ureg, void* v)
  668. {
  669. Proc *up = externup();
  670. char buf[ERRMAX];
  671. if(up == 0)
  672. panic("kernel bpt");
  673. /* restore pc to instruction that caused the trap */
  674. ureg->ip--;
  675. sprint(buf, "sys: breakpoint");
  676. postnote(up, 1, buf, NDebug);
  677. }
  678. static void
  679. doublefault(Ureg* ureg, void* v)
  680. {
  681. iprint("badaddr %p\n", read_csr(sbadaddr));
  682. panic("double fault");
  683. }
  684. static void
  685. unexpected(Ureg *ureg, void* v)
  686. {
  687. iprint("unexpected trap %llu; ignoring\n", ureg->cause);
  688. }
  689. static void
  690. expected(Ureg* ureg, void* v)
  691. {
  692. }
  693. #endif
  694. /*static*/
  695. void
  696. faultarch(Ureg* ureg)
  697. {
  698. Proc *up = externup();
  699. uint64_t addr;
  700. int ftype = ureg->ftype, user, insyscall;
  701. char buf[ERRMAX];
  702. addr = ureg->badaddr;
  703. user = userureg(ureg);
  704. if(!user && mmukmapsync(addr))
  705. return;
  706. /*
  707. * There must be a user context.
  708. * If not, the usual problem is causing a fault during
  709. * initialisation before the system is fully up.
  710. */
  711. if(up == nil){
  712. panic("fault with up == nil; pc %#llx addr %#llx\n",
  713. ureg->ip, addr);
  714. }
  715. insyscall = up->insyscall;
  716. up->insyscall = 1;
  717. if (0) msg("call fault\n");
  718. if(fault(addr, ureg->ip, ftype) < 0){
  719. iprint("could not %s fault %p\n", faulttypes[ftype], addr);
  720. /*
  721. * It is possible to get here with !user if, for example,
  722. * a process was in a system call accessing a shared
  723. * segment but was preempted by another process which shrunk
  724. * or deallocated the shared segment; when the original
  725. * process resumes it may fault while in kernel mode.
  726. * No need to panic this case, post a note to the process
  727. * and unwind the error stack. There must be an error stack
  728. * (up->nerrlab != 0) if this is a system call, if not then
  729. * the game's a bogey.
  730. */
  731. if(!user && (!insyscall || up->nerrlab == 0))
  732. panic("fault: %#llx\n", addr);
  733. sprint(buf, "sys: trap: fault %s addr=%#llx",
  734. faulttypes[ftype], addr);
  735. postnote(up, 1, buf, NDebug);
  736. if(insyscall)
  737. error(buf);
  738. }
  739. up->insyscall = insyscall;
  740. }
  741. /*
  742. * return the userpc the last exception happened at
  743. */
  744. uintptr_t
  745. userpc(Ureg* ureg)
  746. {
  747. Proc *up = externup();
  748. if(ureg == nil)
  749. ureg = up->dbgreg;
  750. return ureg->ip;
  751. }
  752. /* This routine must save the values of registers the user is not permitted
  753. * to write from devproc and then restore the saved values before returning.
  754. * TODO: fix this because the segment registers are wrong for 64-bit mode.
  755. */
  756. void
  757. setregisters(Ureg* ureg, char* pureg, char* uva, int n)
  758. {
  759. #if 0
  760. uint64_t cs, flags, ss;
  761. ss = ureg->ss;
  762. flags = ureg->flags;
  763. cs = ureg->cs;
  764. memmove(pureg, uva, n);
  765. ureg->cs = cs;
  766. ureg->flags = (ureg->flags & 0x00ff) | (flags & 0xff00);
  767. ureg->ss = ss;
  768. #endif
  769. }
  770. /* Give enough context in the ureg to produce a kernel stack for
  771. * a sleeping process
  772. */
  773. void
  774. setkernur(Ureg* ureg, Proc* p)
  775. {
  776. ureg->ip = p->sched.pc;
  777. ureg->sp = p->sched.sp+BY2SE;
  778. }
  779. uintptr_t
  780. dbgpc(Proc *p)
  781. {
  782. Ureg *ureg;
  783. ureg = p->dbgreg;
  784. if(ureg == 0)
  785. return 0;
  786. return ureg->ip;
  787. }