trap.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  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) != nil; 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. if (0) print("R");
  289. timerintr(u, 0);
  290. }
  291. void
  292. trapinit(void)
  293. {
  294. // basically done in firmware.
  295. addarchfile("irqalloc", 0444, irqallocread, nil);
  296. intrenable(5, riscvtimer, nil, 0, "timer");
  297. }
  298. /*
  299. * keep interrupt service times and counts
  300. */
  301. void
  302. intrtime(int vno)
  303. {
  304. Proc *up = externup();
  305. uint64_t diff, x;
  306. x = perfticks();
  307. diff = x - machp()->perf.intrts;
  308. machp()->perf.intrts = x;
  309. machp()->perf.inintr += diff;
  310. if(up == nil && machp()->perf.inidle > diff)
  311. machp()->perf.inidle -= diff;
  312. intrtimes[vno].cycles += diff;
  313. intrtimes[vno].count++;
  314. }
  315. static void
  316. pmcnop(Mach *m)
  317. {
  318. }
  319. void (*_pmcupdate)(Mach *m) = pmcnop;
  320. /* go to user space */
  321. void
  322. kexit(Ureg* u)
  323. {
  324. Proc *up = externup();
  325. uint64_t t;
  326. Tos *tos;
  327. Mach *mp;
  328. /*
  329. * precise time accounting, kernel exit
  330. * initialized in exec, sysproc.c
  331. */
  332. tos = (Tos*)(USTKTOP-sizeof(Tos));
  333. if (0) print("USTKTOP %p sizeof(Tos) %d tos %p\n", (void *)USTKTOP, sizeof(Tos), tos);
  334. cycles(&t);
  335. if (1) {
  336. if (0) print("tos is %p, &tos->kcycles is %p, up is %p\n", tos, &tos->kcycles, up);
  337. tos->kcycles += t - up->kentry;
  338. tos->pcycles = up->pcycles;
  339. tos->pid = up->pid;
  340. if (up->ac != nil)
  341. mp = up->ac;
  342. else
  343. mp = machp();
  344. if (0) print("kexit: mp is %p\n", mp);
  345. tos->core = mp->machno;
  346. if (0) print("kexit: mp is %p\n", mp);
  347. tos->nixtype = mp->NIX.nixtype;
  348. if (0) print("kexit: mp is %p\n", mp);
  349. //_pmcupdate(m);
  350. /*
  351. * The process may change its core.
  352. * Be sure it has the right cyclefreq.
  353. */
  354. tos->cyclefreq = mp->cyclefreq;
  355. if (0) print("kexit: mp is %p\n", mp);
  356. }
  357. if (0) print("kexit: done\n");
  358. }
  359. void
  360. kstackok(void)
  361. {
  362. Proc *up = externup();
  363. if(up == nil){
  364. uintptr_t *stk = (uintptr_t*)machp()->stack;
  365. if(*stk != STACKGUARD)
  366. panic("trap: mach %d machstk went through bottom %p\n", machp()->machno, machp()->stack);
  367. } else {
  368. uintptr_t *stk = (uintptr_t*)up->kstack;
  369. if(*stk != STACKGUARD)
  370. panic("trap: proc %d kstack went through bottom %p\n", up->pid, up->kstack);
  371. }
  372. }
  373. void
  374. _trap(Ureg *ureg)
  375. {
  376. if (0) msg("+trap\n");
  377. if (0) print("_trap\n");
  378. /*
  379. * If it's a real trap in this core, then we want to
  380. * use the hardware cr2 register.
  381. * We cannot do this in trap() because application cores
  382. * would update m->cr2 with their cr2 values upon page faults,
  383. * and then call trap().
  384. * If we do this in trap(), we would overwrite that with our own cr2.
  385. */
  386. switch(ureg->cause){
  387. case CAUSE_FAULT_FETCH:
  388. if (0) print("FETCH FAULT %p\n", ureg->ip);
  389. ureg->ftype = FT_EXEC;
  390. machp()->MMU.badaddr = ureg->badaddr;
  391. break;
  392. case CAUSE_FAULT_LOAD:
  393. if (0) print("LOAD FAULT %p\n", ureg->ip);
  394. ureg->ftype = FT_READ;
  395. machp()->MMU.badaddr = ureg->badaddr;
  396. break;
  397. case CAUSE_FAULT_STORE:
  398. if (0) print("STORE FAULT %p\n", ureg->ip);
  399. ureg->ftype = FT_WRITE;
  400. machp()->MMU.badaddr = ureg->badaddr;
  401. break;
  402. }
  403. trap(ureg);
  404. }
  405. void consread(void)
  406. {
  407. int c;
  408. if (0) print("consrad\n");
  409. c = getchar();
  410. if (c > -1) {
  411. if (1) print("WROTE '%02x'\n", c);
  412. void kbdputsc(int data, int _);
  413. kbdputsc(c, 0);
  414. }
  415. }
  416. static int lastvno;
  417. /*
  418. * All traps come here. It is slower to have all traps call trap()
  419. * rather than directly vectoring the handler. However, this avoids a
  420. * lot of code duplication and possible bugs. The only exception is
  421. * VectorSYSCALL.
  422. * Trap is called with interrupts disabled via interrupt-gates.
  423. */
  424. void
  425. trap(Ureg *ureg)
  426. {
  427. int clockintr, vno, user, interrupt;
  428. // cache the previous vno to see what might be causing
  429. // trouble
  430. vno = ureg->cause & ~InterruptMask;
  431. interrupt = !! (ureg->cause & InterruptMask);
  432. //print("T 0x%llx", ureg->cause);
  433. Mach *m =machp();
  434. //if (sce > scx) iprint("====================");
  435. lastvno = vno;
  436. if (m < (Mach *)(1ULL<<63))
  437. die("bogus mach");
  438. Proc *up = externup();
  439. char buf[ERRMAX];
  440. Vctl *ctl, *v;
  441. machp()->perf.intrts = perfticks();
  442. user = userureg(ureg);
  443. if(user && (machp()->NIX.nixtype == NIXTC)){
  444. if (0)print("call cycles\n");
  445. up->dbgreg = ureg;
  446. cycles(&up->kentry);
  447. if (0)print("done\n");
  448. }
  449. clockintr = interrupt && vno == SupervisorTimer;
  450. if (0 && clockintr) print("C");
  451. //print("clockintr %d\n", clockintr);
  452. //_pmcupdate(machp());
  453. if (!interrupt){
  454. if (0) print("trap_handler\n");
  455. trap_handler(ureg);
  456. } else {
  457. write_csr(sip, 0);
  458. //print("check vno %d\n", vno);
  459. if((ctl = vctl[vno]) != nil){
  460. if(ctl->isintr){
  461. machp()->intr++;
  462. machp()->lastintr = ctl->Vkey.irq;
  463. }else
  464. if(up)
  465. up->nqtrap++;
  466. if(ctl->isr){
  467. ctl->isr(vno);
  468. if(islo())print("trap %d: isr %p enabled interrupts\n", vno, ctl->isr);
  469. }
  470. for(v = ctl; v != nil; v = v->next){
  471. if(v->f){
  472. if (0) print("F");
  473. v->f(ureg, v->a);
  474. if(islo())print("trap %d: ctlf %p enabled interrupts\n", vno, v->f);
  475. }
  476. }
  477. if(ctl->eoi){
  478. ctl->eoi(vno);
  479. if(islo())print("trap %d: eoi %p enabled interrupts\n", vno, ctl->eoi);
  480. }
  481. intrtime(vno);
  482. if(ctl->isintr){
  483. if (clockintr)
  484. oprof_alarm_handler(ureg);
  485. if(up && !clockintr)
  486. preempted();
  487. }
  488. } else if(vno < nelem(excname) && user){
  489. panic("OOR\n");
  490. spllo();
  491. snprint(buf, sizeof buf, "sys: trap: %s", excname[vno]);
  492. postnote(up, 1, buf, NDebug);
  493. } else if ((interrupt && vno > LastInterrupt) || (vno > LastTrap)) {
  494. panic("UNK\n");
  495. /*
  496. * An unknown interrupt.
  497. */
  498. iprint("cpu%d: spurious interrupt %d, last %d\n",
  499. machp()->machno, vno, machp()->lastintr);
  500. intrtime(vno);
  501. if(user)
  502. kexit(ureg);
  503. return;
  504. } else {
  505. #if 0
  506. if(vno == VectorNMI){
  507. nmienable();
  508. if(machp()->machno != 0){
  509. iprint("cpu%d: PC %#llx\n",
  510. machp()->machno, ureg->ip);
  511. for(;;);
  512. }
  513. }
  514. #endif
  515. if (0) dumpregs(ureg);
  516. if(!user){
  517. ureg->sp = PTR2UINT(&ureg->sp);
  518. dumpstackwithureg(ureg);
  519. }
  520. if(vno < nelem(excname))
  521. panic("%s", excname[vno]);
  522. panic("unknown trap/intr: %d\n", vno);
  523. }
  524. }
  525. splhi();
  526. /* delaysched set because we held a lock or because our quantum ended */
  527. if(up && up->delaysched && clockintr){
  528. #if 0
  529. if(0)
  530. if(user && up->ac == nil && up->nqtrap == 0 && up->nqsyscall == 0){
  531. if(!waserror()){
  532. up->ac = getac(up, -1);
  533. poperror();
  534. runacore();
  535. return;
  536. }
  537. }
  538. #endif
  539. sched();
  540. splhi();
  541. }
  542. //print("DUN\n");
  543. if(user){
  544. if(up && (up->procctl || up->nnote))
  545. notify(ureg);
  546. kexit(ureg);
  547. }
  548. //print("ALL DONE TRAP\n");
  549. }
  550. /*
  551. * Dump general registers.
  552. */
  553. void
  554. dumpgpr(Ureg* ureg)
  555. {
  556. Proc *up = externup();
  557. if(up != nil)
  558. print("cpu%d: ureg %p, registers for %s %d\n",
  559. machp()->machno, ureg, up->text, up->pid);
  560. else
  561. print("cpu%d: registers for kernel\n", machp()->machno);
  562. print("ip %#llx\n", ureg->ip);
  563. print("sp %#llx\n", ureg->sp);
  564. print("gp %#llx\n", ureg->gp);
  565. print("tp %#llx\n", ureg->tp);
  566. print("t0 %#llx\n", ureg->t0);
  567. print("t1 %#llx\n", ureg->t1);
  568. print("t2 %#llx\n", ureg->t2);
  569. print("s0 %#llx\n", ureg->s0);
  570. print("s1 %#llx\n", ureg->s1);
  571. print("a0 %#llx\n", ureg->a0);
  572. print("a1 %#llx\n", ureg->a1);
  573. print("a2 %#llx\n", ureg->a2);
  574. print("a3 %#llx\n", ureg->a3);
  575. print("a4 %#llx\n", ureg->a4);
  576. print("a5 %#llx\n", ureg->a5);
  577. print("a6 %#llx\n", ureg->a6);
  578. print("a7 %#llx\n", ureg->a7);
  579. print("s2 %#llx\n", ureg->s2);
  580. print("s3 %#llx\n", ureg->s3);
  581. print("s4 %#llx\n", ureg->s4);
  582. print("s5 %#llx\n", ureg->s5);
  583. print("s6 %#llx\n", ureg->s6);
  584. print("s7 %#llx\n", ureg->s7);
  585. print("s8 %#llx\n", ureg->s8);
  586. print("s9 %#llx\n", ureg->s9);
  587. print("s10 %#llx\n", ureg->s10);
  588. print("s11 %#llx\n", ureg->s11);
  589. print("t3 %#llx\n", ureg->t3);
  590. print("t4 %#llx\n", ureg->t4);
  591. print("t5 %#llx\n", ureg->t5);
  592. print("t6 %#llx\n", ureg->t6);
  593. print("status %#llx\n", ureg->status);
  594. print("epc %#llx\n", ureg->epc);
  595. print("badaddr %#llx\n", ureg->badaddr);
  596. print("cause %#llx\n", ureg->cause);
  597. print("insnn %#llx\n", ureg->insnn);
  598. print("bp %#llx\n", ureg->bp);
  599. print("ftype %#llx\n", ureg->ftype);
  600. print("m\t%#16.16p\nup\t%#16.16p\n", machp(), up);
  601. }
  602. void
  603. dumpregs(Ureg* ureg)
  604. {
  605. dumpgpr(ureg);
  606. }
  607. /*
  608. * Fill in enough of Ureg to get a stack trace, and call a function.
  609. * Used by debugging interface rdb.
  610. */
  611. void
  612. callwithureg(void (*fn)(Ureg*))
  613. {
  614. Ureg ureg;
  615. ureg.ip = getcallerpc();
  616. ureg.sp = PTR2UINT(&fn);
  617. fn(&ureg);
  618. }
  619. static void
  620. dumpstackwithureg(Ureg* ureg)
  621. {
  622. Proc *up = externup();
  623. uintptr_t l, v, i, estack;
  624. // extern char etext;
  625. int x;
  626. if (0) { //if((s = getconf("*nodumpstack")) != nil && atoi(s) != 0){
  627. iprint("dumpstack disabled\n");
  628. return;
  629. }
  630. iprint("dumpstack\n");
  631. x = 0;
  632. //x += iprint("ktrace 9%s %#p %#p\n", strrchr(conffile, '/')+1, ureg->ip, ureg->sp);
  633. i = 0;
  634. if(up != nil
  635. // && (uintptr)&l >= (uintptr)up->kstack
  636. && (uintptr_t)&l <= (uintptr_t)up->kstack+KSTACK)
  637. estack = (uintptr_t)up->kstack+KSTACK;
  638. else if((uintptr_t)&l >= machp()->stack && (uintptr_t)&l <= machp()->stack+MACHSTKSZ)
  639. estack = machp()->stack+MACHSTKSZ;
  640. else{
  641. if(up != nil)
  642. iprint("&up->kstack %#p &l %#p\n", up->kstack, &l);
  643. else
  644. iprint("&m %#p &l %#p\n", machp(), &l);
  645. return;
  646. }
  647. x += iprint("estackx %#p\n", estack);
  648. for(l = (uintptr_t)&l; l < estack; l += sizeof(uintptr_t)){
  649. v = *(uintptr_t*)l;
  650. if((KTZERO < v && v < (uintptr_t)&etext)
  651. || ((uintptr_t)&l < v && v < estack) || estack-l < 256){
  652. x += iprint("%#16.16p=%#16.16p ", l, v);
  653. i++;
  654. }
  655. if(i == 2){
  656. i = 0;
  657. x += iprint("\n");
  658. }
  659. }
  660. if(i)
  661. iprint("\n");
  662. }
  663. void
  664. dumpstack(void)
  665. {
  666. callwithureg(dumpstackwithureg);
  667. }
  668. #if 0
  669. static void
  670. debugbpt(Ureg* ureg, void* v)
  671. {
  672. Proc *up = externup();
  673. char buf[ERRMAX];
  674. if(up == 0)
  675. panic("kernel bpt");
  676. /* restore pc to instruction that caused the trap */
  677. ureg->ip--;
  678. sprint(buf, "sys: breakpoint");
  679. postnote(up, 1, buf, NDebug);
  680. }
  681. static void
  682. doublefault(Ureg* ureg, void* v)
  683. {
  684. iprint("badaddr %p\n", read_csr(sbadaddr));
  685. panic("double fault");
  686. }
  687. static void
  688. unexpected(Ureg *ureg, void* v)
  689. {
  690. iprint("unexpected trap %llu; ignoring\n", ureg->cause);
  691. }
  692. static void
  693. expected(Ureg* ureg, void* v)
  694. {
  695. }
  696. #endif
  697. /*static*/
  698. void
  699. faultarch(Ureg* ureg)
  700. {
  701. Proc *up = externup();
  702. uint64_t addr;
  703. int ftype = ureg->ftype, user, insyscall;
  704. char buf[ERRMAX];
  705. addr = ureg->badaddr;
  706. user = userureg(ureg);
  707. if(!user && mmukmapsync(addr))
  708. return;
  709. /*
  710. * There must be a user context.
  711. * If not, the usual problem is causing a fault during
  712. * initialisation before the system is fully up.
  713. */
  714. if(up == nil){
  715. panic("fault with up == nil; pc %#llx addr %#llx\n",
  716. ureg->ip, addr);
  717. }
  718. insyscall = up->insyscall;
  719. up->insyscall = 1;
  720. if (0) msg("call fault\n");
  721. if(fault(addr, ureg->ip, ftype) < 0){
  722. iprint("could not %s fault %p\n", faulttypes[ftype], addr);
  723. /*
  724. * It is possible to get here with !user if, for example,
  725. * a process was in a system call accessing a shared
  726. * segment but was preempted by another process which shrunk
  727. * or deallocated the shared segment; when the original
  728. * process resumes it may fault while in kernel mode.
  729. * No need to panic this case, post a note to the process
  730. * and unwind the error stack. There must be an error stack
  731. * (up->nerrlab != 0) if this is a system call, if not then
  732. * the game's a bogey.
  733. */
  734. if(!user && (!insyscall || up->nerrlab == 0))
  735. panic("fault: %#llx\n", addr);
  736. sprint(buf, "sys: trap: fault %s addr=%#llx",
  737. faulttypes[ftype], addr);
  738. postnote(up, 1, buf, NDebug);
  739. if(insyscall)
  740. error(buf);
  741. }
  742. up->insyscall = insyscall;
  743. }
  744. /*
  745. * return the userpc the last exception happened at
  746. */
  747. uintptr_t
  748. userpc(Ureg* ureg)
  749. {
  750. Proc *up = externup();
  751. if(ureg == nil)
  752. ureg = up->dbgreg;
  753. return ureg->ip;
  754. }
  755. /* This routine must save the values of registers the user is not permitted
  756. * to write from devproc and then restore the saved values before returning.
  757. * TODO: fix this because the segment registers are wrong for 64-bit mode.
  758. */
  759. void
  760. setregisters(Ureg* ureg, char* pureg, char* uva, int n)
  761. {
  762. #if 0
  763. uint64_t cs, flags, ss;
  764. ss = ureg->ss;
  765. flags = ureg->flags;
  766. cs = ureg->cs;
  767. memmove(pureg, uva, n);
  768. ureg->cs = cs;
  769. ureg->flags = (ureg->flags & 0x00ff) | (flags & 0xff00);
  770. ureg->ss = ss;
  771. #endif
  772. }
  773. /* Give enough context in the ureg to produce a kernel stack for
  774. * a sleeping process
  775. */
  776. void
  777. setkernur(Ureg* ureg, Proc* p)
  778. {
  779. ureg->ip = p->sched.pc;
  780. ureg->sp = p->sched.sp+BY2SE;
  781. }
  782. uintptr_t
  783. dbgpc(Proc *p)
  784. {
  785. Ureg *ureg;
  786. ureg = p->dbgreg;
  787. if(ureg == 0)
  788. return 0;
  789. return ureg->ip;
  790. }