trap.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. /*
  2. * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
  3. * The President and Fellows of Harvard College.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the University nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. #include <types.h>
  30. #include <signal.h>
  31. #include <lib.h>
  32. #include <mips/specialreg.h>
  33. #include <mips/trapframe.h>
  34. #include <cpu.h>
  35. #include <spl.h>
  36. #include <thread.h>
  37. #include <current.h>
  38. #include <vm.h>
  39. #include <mainbus.h>
  40. #include <syscall.h>
  41. /* in exception.S */
  42. extern void asm_usermode(struct trapframe *tf);
  43. /* called only from assembler, so not declared in a header */
  44. void mips_trap(struct trapframe *tf);
  45. /* Names for trap codes */
  46. #define NTRAPCODES 13
  47. static const char *const trapcodenames[NTRAPCODES] = {
  48. "Interrupt",
  49. "TLB modify trap",
  50. "TLB miss on load",
  51. "TLB miss on store",
  52. "Address error on load",
  53. "Address error on store",
  54. "Bus error on code",
  55. "Bus error on data",
  56. "System call",
  57. "Break instruction",
  58. "Illegal instruction",
  59. "Coprocessor unusable",
  60. "Arithmetic overflow",
  61. };
  62. /*
  63. * Function called when user-level code hits a fatal fault.
  64. */
  65. static
  66. void
  67. kill_curthread(vaddr_t epc, unsigned code, vaddr_t vaddr)
  68. {
  69. int sig = 0;
  70. KASSERT(code < NTRAPCODES);
  71. switch (code)
  72. {
  73. case EX_IRQ:
  74. case EX_IBE:
  75. case EX_DBE:
  76. case EX_SYS:
  77. /* should not be seen */
  78. KASSERT(0);
  79. sig = SIGABRT;
  80. break;
  81. case EX_MOD:
  82. sig = SIGSEGV;
  83. sys__exit(-2);
  84. break;
  85. case EX_TLBL:
  86. case EX_TLBS:
  87. sig = SIGSEGV;
  88. break;
  89. case EX_ADEL:
  90. case EX_ADES:
  91. sig = SIGBUS;
  92. break;
  93. case EX_BP:
  94. sig = SIGTRAP;
  95. break;
  96. case EX_RI:
  97. sig = SIGILL;
  98. break;
  99. case EX_CPU:
  100. sig = SIGSEGV;
  101. break;
  102. case EX_OVF:
  103. sig = SIGFPE;
  104. break;
  105. }
  106. /*
  107. * You will probably want to change this.
  108. */
  109. kprintf("Fatal user mode trap %u sig %d (%s, epc 0x%x, vaddr 0x%x)\n",
  110. code, sig, trapcodenames[code], epc, vaddr);
  111. panic("I don't know how to handle this\n");
  112. }
  113. /*
  114. * General trap (exception) handling function for mips.
  115. * This is called by the assembly-language exception handler once
  116. * the trapframe has been set up.
  117. */
  118. void
  119. mips_trap(struct trapframe *tf)
  120. {
  121. uint32_t code;
  122. bool isutlb, iskern;
  123. int spl;
  124. /* The trap frame is supposed to be 37 registers long. */
  125. KASSERT(sizeof(struct trapframe)==(37*4));
  126. /*
  127. * Extract the exception code info from the register fields.
  128. */
  129. code = (tf->tf_cause & CCA_CODE) >> CCA_CODESHIFT;
  130. isutlb = (tf->tf_cause & CCA_UTLB) != 0;
  131. iskern = (tf->tf_status & CST_KUp) == 0;
  132. KASSERT(code < NTRAPCODES);
  133. /* Make sure we haven't run off our stack */
  134. if (curthread != NULL && curthread->t_stack != NULL) {
  135. KASSERT((vaddr_t)tf > (vaddr_t)curthread->t_stack);
  136. KASSERT((vaddr_t)tf < (vaddr_t)(curthread->t_stack
  137. + STACK_SIZE));
  138. }
  139. /* Interrupt? Call the interrupt handler and return. */
  140. if (code == EX_IRQ) {
  141. int old_in;
  142. bool doadjust;
  143. old_in = curthread->t_in_interrupt;
  144. curthread->t_in_interrupt = 1;
  145. /*
  146. * The processor has turned interrupts off; if the
  147. * currently recorded interrupt state is interrupts on
  148. * (spl of 0), adjust the recorded state to match, and
  149. * restore after processing the interrupt.
  150. *
  151. * How can we get an interrupt if the recorded state
  152. * is interrupts off? Well, as things currently stand
  153. * when the CPU finishes idling it flips interrupts on
  154. * and off to allow things to happen, but leaves
  155. * curspl high while doing so.
  156. *
  157. * While we're here, assert that the interrupt
  158. * handling code hasn't leaked a spinlock or an
  159. * splhigh().
  160. */
  161. if (curthread->t_curspl == 0) {
  162. KASSERT(curthread->t_curspl == 0);
  163. KASSERT(curthread->t_iplhigh_count == 0);
  164. curthread->t_curspl = IPL_HIGH;
  165. curthread->t_iplhigh_count++;
  166. doadjust = true;
  167. }
  168. else {
  169. doadjust = false;
  170. }
  171. mainbus_interrupt(tf);
  172. if (doadjust) {
  173. KASSERT(curthread->t_curspl == IPL_HIGH);
  174. KASSERT(curthread->t_iplhigh_count == 1);
  175. curthread->t_iplhigh_count--;
  176. curthread->t_curspl = 0;
  177. }
  178. curthread->t_in_interrupt = old_in;
  179. goto done2;
  180. }
  181. /*
  182. * The processor turned interrupts off when it took the trap.
  183. *
  184. * While we're in the kernel, and not actually handling an
  185. * interrupt, restore the interrupt state to where it was in
  186. * the previous context, which may be low (interrupts on).
  187. *
  188. * Do this by forcing splhigh(), which may do a redundant
  189. * cpu_irqoff() but forces the stored MI interrupt state into
  190. * sync, then restoring the previous state.
  191. */
  192. spl = splhigh();
  193. splx(spl);
  194. /* Syscall? Call the syscall handler and return. */
  195. if (code == EX_SYS) {
  196. /* Interrupts should have been on while in user mode. */
  197. KASSERT(curthread->t_curspl == 0);
  198. KASSERT(curthread->t_iplhigh_count == 0);
  199. DEBUG(DB_SYSCALL, "syscall: #%d, args %x %x %x %x\n",
  200. tf->tf_v0, tf->tf_a0, tf->tf_a1, tf->tf_a2, tf->tf_a3);
  201. syscall(tf);
  202. goto done;
  203. }
  204. /*
  205. * Ok, it wasn't any of the really easy cases.
  206. * Call vm_fault on the TLB exceptions.
  207. * Panic on the bus error exceptions.
  208. */
  209. switch (code) {
  210. case EX_MOD:
  211. if (vm_fault(VM_FAULT_READONLY, tf->tf_vaddr)==0) {
  212. goto done;
  213. }
  214. break;
  215. case EX_TLBL:
  216. if (vm_fault(VM_FAULT_READ, tf->tf_vaddr)==0) {
  217. goto done;
  218. }
  219. break;
  220. case EX_TLBS:
  221. if (vm_fault(VM_FAULT_WRITE, tf->tf_vaddr)==0) {
  222. goto done;
  223. }
  224. break;
  225. case EX_IBE:
  226. case EX_DBE:
  227. /*
  228. * This means you loaded invalid TLB entries, or
  229. * touched invalid parts of the direct-mapped
  230. * segments. These are serious kernel errors, so
  231. * panic.
  232. *
  233. * The MIPS won't even tell you what invalid address
  234. * caused the bus error.
  235. */
  236. panic("Bus error exception, PC=0x%x\n", tf->tf_epc);
  237. break;
  238. }
  239. /*
  240. * If we get to this point, it's a fatal fault - either it's
  241. * one of the other exceptions, like illegal instruction, or
  242. * it was a page fault we couldn't handle.
  243. */
  244. if (!iskern) {
  245. /*
  246. * Fatal fault in user mode.
  247. * Kill the current user process.
  248. */
  249. kill_curthread(tf->tf_epc, code, tf->tf_vaddr);
  250. goto done;
  251. }
  252. /*
  253. * Fatal fault in kernel mode.
  254. *
  255. * If pcb_badfaultfunc is set, we do not panic; badfaultfunc is
  256. * set by copyin/copyout and related functions to signify that
  257. * the addresses they're accessing are userlevel-supplied and
  258. * not trustable. What we actually want to do is resume
  259. * execution at the function pointed to by badfaultfunc. That's
  260. * going to be "copyfail" (see copyinout.c), which longjmps
  261. * back to copyin/copyout or wherever and returns EFAULT.
  262. *
  263. * Note that we do not just *call* this function, because that
  264. * won't necessarily do anything. We want the control flow
  265. * that is currently executing in copyin (or whichever), and
  266. * is stopped while we process the exception, to *teleport* to
  267. * copyfail.
  268. *
  269. * This is accomplished by changing tf->tf_epc and returning
  270. * from the exception handler.
  271. */
  272. if (curthread != NULL &&
  273. curthread->t_machdep.tm_badfaultfunc != NULL) {
  274. tf->tf_epc = (vaddr_t) curthread->t_machdep.tm_badfaultfunc;
  275. goto done;
  276. }
  277. /*
  278. * Really fatal kernel-mode fault.
  279. */
  280. kprintf("panic: Fatal exception %u (%s) in kernel mode\n", code,
  281. trapcodenames[code]);
  282. kprintf("panic: EPC 0x%x, exception vaddr 0x%x\n",
  283. tf->tf_epc, tf->tf_vaddr);
  284. panic("I can't handle this... I think I'll just die now...\n");
  285. done:
  286. /*
  287. * Turn interrupts off on the processor, without affecting the
  288. * stored interrupt state.
  289. */
  290. cpu_irqoff();
  291. done2:
  292. /*
  293. * The boot thread can get here (e.g. on interrupt return) but
  294. * since it doesn't go to userlevel, it can't be returning to
  295. * userlevel, so there's no need to set cputhreads[] and
  296. * cpustacks[]. Just return.
  297. */
  298. if (curthread->t_stack == NULL) {
  299. return;
  300. }
  301. cputhreads[curcpu->c_number] = (vaddr_t)curthread;
  302. cpustacks[curcpu->c_number] = (vaddr_t)curthread->t_stack + STACK_SIZE;
  303. /*
  304. * This assertion will fail if either
  305. * (1) curthread->t_stack is corrupted, or
  306. * (2) the trap frame is somehow on the wrong kernel stack.
  307. *
  308. * If cpustacks[] is corrupted, the next trap back to the
  309. * kernel will (most likely) hang the system, so it's better
  310. * to find out now.
  311. */
  312. KASSERT(SAME_STACK(cpustacks[curcpu->c_number]-1, (vaddr_t)tf));
  313. }
  314. /*
  315. * Function for entering user mode.
  316. *
  317. * This should not be used by threads returning from traps - they
  318. * should just return from mips_trap(). It should be used by threads
  319. * entering user mode for the first time - whether the child thread in
  320. * a fork(), or into a brand-new address space after exec(), or when
  321. * starting the first userlevel program.
  322. *
  323. * It works by jumping into the exception return code.
  324. *
  325. * mips_usermode is common code for this. It cannot usefully be called
  326. * outside the mips port, but should be called from one of the
  327. * following places:
  328. * - enter_new_process, for use by exec and equivalent.
  329. * - enter_forked_process, in syscall.c, for use by fork.
  330. */
  331. void
  332. mips_usermode(struct trapframe *tf)
  333. {
  334. /*
  335. * Interrupts should be off within the kernel while entering
  336. * user mode. However, while in user mode, interrupts should
  337. * be on. To interact properly with the spl-handling logic
  338. * above, we explicitly call spl0() and then call cpu_irqoff().
  339. */
  340. spl0();
  341. cpu_irqoff();
  342. cputhreads[curcpu->c_number] = (vaddr_t)curthread;
  343. cpustacks[curcpu->c_number] = (vaddr_t)curthread->t_stack + STACK_SIZE;
  344. /*
  345. * This assertion will fail if either
  346. * (1) cpustacks[] is corrupted, or
  347. * (2) the trap frame is not on our own kernel stack, or
  348. * (3) the boot thread tries to enter user mode.
  349. *
  350. * If cpustacks[] is corrupted, the next trap back to the
  351. * kernel will (most likely) hang the system, so it's better
  352. * to find out now.
  353. *
  354. * It's necessary for the trap frame used here to be on the
  355. * current thread's own stack. It cannot correctly be on
  356. * either another thread's stack or in the kernel heap.
  357. * (Exercise: why?)
  358. */
  359. KASSERT(SAME_STACK(cpustacks[curcpu->c_number]-1, (vaddr_t)tf));
  360. /*
  361. * This actually does it. See exception.S.
  362. */
  363. asm_usermode(tf);
  364. }
  365. /*
  366. * enter_new_process: go to user mode after loading an executable.
  367. *
  368. * Performs the necessary initialization so that the user program will
  369. * get the arguments supplied in argc/argv (note that argv must be a
  370. * user-level address), and begin executing at the specified entry
  371. * point. The stack pointer is initialized from the stackptr
  372. * argument. Note that passing argc/argv may use additional stack
  373. * space on some other platforms (but not on mips).
  374. *
  375. * Works by creating an ersatz trapframe.
  376. */
  377. void
  378. enter_new_process(int argc, userptr_t argv, vaddr_t stack, vaddr_t entry)
  379. {
  380. struct trapframe tf;
  381. bzero(&tf, sizeof(tf));
  382. tf.tf_status = CST_IRQMASK | CST_IEp | CST_KUp;
  383. tf.tf_epc = entry;
  384. tf.tf_a0 = argc;
  385. tf.tf_a1 = (vaddr_t)argv;
  386. tf.tf_sp = stack;
  387. mips_usermode(&tf);
  388. }