PageRenderTime 314ms CodeModel.GetById 41ms RepoModel.GetById 1ms app.codeStats 0ms

/sys/mips/mips/exception.S

https://github.com/okuoku/freebsd-head
Assembly | 1201 lines | 1185 code | 16 blank | 0 comment | 10 complexity | 393792000ff60aa3ae5204b35b4b3648 MD5 | raw file
  1. /* $OpenBSD: locore.S,v 1.18 1998/09/15 10:58:53 pefo Exp $ */
  2. /*-
  3. * Copyright (c) 1992, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * This code is derived from software contributed to Berkeley by
  7. * Digital Equipment Corporation and Ralph Campbell.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 4. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. *
  33. * Copyright (C) 1989 Digital Equipment Corporation.
  34. * Permission to use, copy, modify, and distribute this software and
  35. * its documentation for any purpose and without fee is hereby granted,
  36. * provided that the above copyright notice appears in all copies.
  37. * Digital Equipment Corporation makes no representations about the
  38. * suitability of this software for any purpose. It is provided "as is"
  39. * without express or implied warranty.
  40. *
  41. * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s,
  42. * v 1.1 89/07/11 17:55:04 nelson Exp SPRITE (DECWRL)
  43. * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s,
  44. * v 9.2 90/01/29 18:00:39 shirriff Exp SPRITE (DECWRL)
  45. * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
  46. * v 1.1 89/07/10 14:27:41 nelson Exp SPRITE (DECWRL)
  47. * from: @(#)locore.s 8.5 (Berkeley) 1/4/94
  48. * JNPR: exception.S,v 1.5 2007/01/08 04:58:37 katta
  49. * $FreeBSD$
  50. */
  51. /*
  52. * Contains code that is the first executed at boot time plus
  53. * assembly language support routines.
  54. */
  55. #include "opt_cputype.h"
  56. #include "opt_ddb.h"
  57. #include <machine/asm.h>
  58. #include <machine/cpu.h>
  59. #include <machine/regnum.h>
  60. #include <machine/cpuregs.h>
  61. #include <machine/pte.h>
  62. #include "opt_cputype.h"
  63. #include "assym.s"
  64. .set noreorder # Noreorder is default style!
  65. /*
  66. * Reasonable limit
  67. */
  68. #define INTRCNT_COUNT 128
  69. /*
  70. *----------------------------------------------------------------------------
  71. *
  72. * MipsTLBMiss --
  73. *
  74. * Vector code for the TLB-miss exception vector 0x80000000.
  75. *
  76. * This code is copied to the TLB exception vector address to
  77. * which the CPU jumps in response to an exception or a TLB miss.
  78. * NOTE: This code must be position independent!!!
  79. *
  80. *
  81. */
  82. VECTOR(MipsTLBMiss, unknown)
  83. .set push
  84. .set noat
  85. j MipsDoTLBMiss
  86. MFC0 k0, MIPS_COP_0_BAD_VADDR # get the fault address
  87. .set pop
  88. VECTOR_END(MipsTLBMiss)
  89. /*
  90. *----------------------------------------------------------------------------
  91. *
  92. * MipsDoTLBMiss --
  93. *
  94. * This is the real TLB Miss Handler code.
  95. * 'segbase' points to the base of the segment table for user processes.
  96. *
  97. * Don't check for invalid pte's here. We load them as well and
  98. * let the processor trap to load the correct value after service.
  99. *----------------------------------------------------------------------------
  100. */
  101. .set push
  102. .set noat
  103. MipsDoTLBMiss:
  104. bltz k0, 1f #02: k0<0 -> 1f (kernel fault)
  105. PTR_SRL k0, k0, SEGSHIFT - PTRSHIFT #03: k0=seg offset (almost)
  106. GET_CPU_PCPU(k1)
  107. PTR_L k1, PC_SEGBASE(k1)
  108. beqz k1, 2f #05: make sure segbase is not null
  109. andi k0, k0, PDEPTRMASK #06: k0=seg offset
  110. PTR_ADDU k1, k0, k1 #07: k1=seg entry address
  111. PTR_L k1, 0(k1) #08: k1=seg entry
  112. MFC0 k0, MIPS_COP_0_BAD_VADDR #09: k0=bad address (again)
  113. beq k1, zero, 2f #0a: ==0 -- no page table
  114. #ifdef __mips_n64
  115. PTR_SRL k0, PDRSHIFT - PTRSHIFT # k0=VPN
  116. andi k0, k0, PDEPTRMASK # k0=pde offset
  117. PTR_ADDU k1, k0, k1 # k1=pde entry address
  118. PTR_L k1, 0(k1) # k1=pde entry
  119. MFC0 k0, MIPS_COP_0_BAD_VADDR # k0=bad address (again)
  120. beq k1, zero, 2f # ==0 -- no page table
  121. #endif
  122. PTR_SRL k0, PAGE_SHIFT - PTESHIFT #0b: k0=VPN (aka va>>10)
  123. andi k0, k0, PTE2MASK #0c: k0=page tab offset
  124. PTR_ADDU k1, k1, k0 #0d: k1=pte address
  125. PTE_L k0, 0(k1) #0e: k0=lo0 pte
  126. PTE_L k1, PTESIZE(k1) #0f: k1=lo0 pte
  127. CLEAR_PTE_SWBITS(k0)
  128. PTE_MTC0 k0, MIPS_COP_0_TLB_LO0 #12: lo0 is loaded
  129. COP0_SYNC
  130. CLEAR_PTE_SWBITS(k1)
  131. PTE_MTC0 k1, MIPS_COP_0_TLB_LO1 #15: lo1 is loaded
  132. COP0_SYNC
  133. tlbwr #1a: write to tlb
  134. HAZARD_DELAY
  135. eret #1f: retUrn from exception
  136. 1: j MipsTLBMissException #20: kernel exception
  137. nop #21: branch delay slot
  138. 2: j SlowFault #22: no page table present
  139. nop #23: branch delay slot
  140. .set pop
  141. /*
  142. * This code is copied to the general exception vector address to
  143. * handle all execptions except RESET and TLBMiss.
  144. * NOTE: This code must be position independent!!!
  145. */
  146. VECTOR(MipsException, unknown)
  147. /*
  148. * Find out what mode we came from and jump to the proper handler.
  149. */
  150. .set noat
  151. mfc0 k0, MIPS_COP_0_STATUS # Get the status register
  152. mfc0 k1, MIPS_COP_0_CAUSE # Get the cause register value.
  153. and k0, k0, SR_KSU_USER # test for user mode
  154. # sneaky but the bits are
  155. # with us........
  156. sll k0, k0, 3 # shift user bit for cause index
  157. and k1, k1, MIPS3_CR_EXC_CODE # Mask out the cause bits.
  158. or k1, k1, k0 # change index to user table
  159. #if defined(__mips_n64)
  160. PTR_SLL k1, k1, 1 # shift to get 8-byte offset
  161. #endif
  162. 1:
  163. PTR_LA k0, _C_LABEL(machExceptionTable) # get base of the jump table
  164. PTR_ADDU k0, k0, k1 # Get the address of the
  165. # function entry. Note that
  166. # the cause is already
  167. # shifted left by 2 bits so
  168. # we dont have to shift.
  169. PTR_L k0, 0(k0) # Get the function address
  170. nop
  171. j k0 # Jump to the function.
  172. nop
  173. .set at
  174. VECTOR_END(MipsException)
  175. /*
  176. * We couldn't find a TLB entry.
  177. * Find out what mode we came from and call the appropriate handler.
  178. */
  179. SlowFault:
  180. .set noat
  181. mfc0 k0, MIPS_COP_0_STATUS
  182. nop
  183. and k0, k0, SR_KSU_USER
  184. bne k0, zero, _C_LABEL(MipsUserGenException)
  185. nop
  186. .set at
  187. /*
  188. * Fall though ...
  189. */
  190. /*----------------------------------------------------------------------------
  191. *
  192. * MipsKernGenException --
  193. *
  194. * Handle an exception from kernel mode.
  195. *
  196. * Results:
  197. * None.
  198. *
  199. * Side effects:
  200. * None.
  201. *
  202. *----------------------------------------------------------------------------
  203. */
  204. #define SAVE_REG(reg, offs, base) \
  205. REG_S reg, CALLFRAME_SIZ + (SZREG * offs) (base)
  206. #if defined(CPU_CNMIPS)
  207. #define CLEAR_STATUS \
  208. mfc0 a0, MIPS_COP_0_STATUS ;\
  209. li a2, (MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX) ; \
  210. or a0, a0, a2 ; \
  211. li a2, ~(MIPS_SR_INT_IE | MIPS_SR_EXL | SR_KSU_USER) ; \
  212. and a0, a0, a2 ; \
  213. mtc0 a0, MIPS_COP_0_STATUS ; \
  214. ITLBNOPFIX
  215. #elif defined(CPU_RMI) || defined(CPU_NLM)
  216. #define CLEAR_STATUS \
  217. mfc0 a0, MIPS_COP_0_STATUS ;\
  218. li a2, (MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_COP_2_BIT) ; \
  219. or a0, a0, a2 ; \
  220. li a2, ~(MIPS_SR_INT_IE | MIPS_SR_EXL | SR_KSU_USER) ; \
  221. and a0, a0, a2 ; \
  222. mtc0 a0, MIPS_COP_0_STATUS ; \
  223. ITLBNOPFIX
  224. #else
  225. #define CLEAR_STATUS \
  226. mfc0 a0, MIPS_COP_0_STATUS ;\
  227. li a2, ~(MIPS_SR_INT_IE | MIPS_SR_EXL | SR_KSU_USER) ; \
  228. and a0, a0, a2 ; \
  229. mtc0 a0, MIPS_COP_0_STATUS ; \
  230. ITLBNOPFIX
  231. #endif
  232. /*
  233. * Save CPU and CP0 register state.
  234. *
  235. * This is straightforward except for saving the exception program
  236. * counter. The ddb backtrace code looks for the first instruction
  237. * matching the form "sw ra, (off)sp" to figure out the address of the
  238. * calling function. So we must make sure that we save the exception
  239. * PC by staging it through 'ra' as opposed to any other register.
  240. */
  241. #define SAVE_CPU \
  242. SAVE_REG(AT, AST, sp) ;\
  243. .set at ; \
  244. SAVE_REG(v0, V0, sp) ;\
  245. SAVE_REG(v1, V1, sp) ;\
  246. SAVE_REG(a0, A0, sp) ;\
  247. SAVE_REG(a1, A1, sp) ;\
  248. SAVE_REG(a2, A2, sp) ;\
  249. SAVE_REG(a3, A3, sp) ;\
  250. SAVE_REG(t0, T0, sp) ;\
  251. SAVE_REG(t1, T1, sp) ;\
  252. SAVE_REG(t2, T2, sp) ;\
  253. SAVE_REG(t3, T3, sp) ;\
  254. SAVE_REG(ta0, TA0, sp) ;\
  255. SAVE_REG(ta1, TA1, sp) ;\
  256. SAVE_REG(ta2, TA2, sp) ;\
  257. SAVE_REG(ta3, TA3, sp) ;\
  258. SAVE_REG(t8, T8, sp) ;\
  259. SAVE_REG(t9, T9, sp) ;\
  260. SAVE_REG(gp, GP, sp) ;\
  261. SAVE_REG(s0, S0, sp) ;\
  262. SAVE_REG(s1, S1, sp) ;\
  263. SAVE_REG(s2, S2, sp) ;\
  264. SAVE_REG(s3, S3, sp) ;\
  265. SAVE_REG(s4, S4, sp) ;\
  266. SAVE_REG(s5, S5, sp) ;\
  267. SAVE_REG(s6, S6, sp) ;\
  268. SAVE_REG(s7, S7, sp) ;\
  269. SAVE_REG(s8, S8, sp) ;\
  270. mflo v0 ;\
  271. mfhi v1 ;\
  272. mfc0 a0, MIPS_COP_0_STATUS ;\
  273. mfc0 a1, MIPS_COP_0_CAUSE ;\
  274. MFC0 a2, MIPS_COP_0_BAD_VADDR;\
  275. MFC0 a3, MIPS_COP_0_EXC_PC ;\
  276. SAVE_REG(v0, MULLO, sp) ;\
  277. SAVE_REG(v1, MULHI, sp) ;\
  278. SAVE_REG(a0, SR, sp) ;\
  279. SAVE_REG(a1, CAUSE, sp) ;\
  280. SAVE_REG(a2, BADVADDR, sp) ;\
  281. move t0, ra ;\
  282. move ra, a3 ;\
  283. SAVE_REG(ra, PC, sp) ;\
  284. move ra, t0 ;\
  285. SAVE_REG(ra, RA, sp) ;\
  286. PTR_ADDU v0, sp, KERN_EXC_FRAME_SIZE ;\
  287. SAVE_REG(v0, SP, sp) ;\
  288. CLEAR_STATUS ;\
  289. PTR_ADDU a0, sp, CALLFRAME_SIZ ;\
  290. ITLBNOPFIX
  291. #define RESTORE_REG(reg, offs, base) \
  292. REG_L reg, CALLFRAME_SIZ + (SZREG * offs) (base)
  293. #define RESTORE_CPU \
  294. CLEAR_STATUS ;\
  295. RESTORE_REG(k0, SR, sp) ;\
  296. RESTORE_REG(t0, MULLO, sp) ;\
  297. RESTORE_REG(t1, MULHI, sp) ;\
  298. mtlo t0 ;\
  299. mthi t1 ;\
  300. MTC0 v0, MIPS_COP_0_EXC_PC ;\
  301. .set noat ;\
  302. RESTORE_REG(AT, AST, sp) ;\
  303. RESTORE_REG(v0, V0, sp) ;\
  304. RESTORE_REG(v1, V1, sp) ;\
  305. RESTORE_REG(a0, A0, sp) ;\
  306. RESTORE_REG(a1, A1, sp) ;\
  307. RESTORE_REG(a2, A2, sp) ;\
  308. RESTORE_REG(a3, A3, sp) ;\
  309. RESTORE_REG(t0, T0, sp) ;\
  310. RESTORE_REG(t1, T1, sp) ;\
  311. RESTORE_REG(t2, T2, sp) ;\
  312. RESTORE_REG(t3, T3, sp) ;\
  313. RESTORE_REG(ta0, TA0, sp) ;\
  314. RESTORE_REG(ta1, TA1, sp) ;\
  315. RESTORE_REG(ta2, TA2, sp) ;\
  316. RESTORE_REG(ta3, TA3, sp) ;\
  317. RESTORE_REG(t8, T8, sp) ;\
  318. RESTORE_REG(t9, T9, sp) ;\
  319. RESTORE_REG(s0, S0, sp) ;\
  320. RESTORE_REG(s1, S1, sp) ;\
  321. RESTORE_REG(s2, S2, sp) ;\
  322. RESTORE_REG(s3, S3, sp) ;\
  323. RESTORE_REG(s4, S4, sp) ;\
  324. RESTORE_REG(s5, S5, sp) ;\
  325. RESTORE_REG(s6, S6, sp) ;\
  326. RESTORE_REG(s7, S7, sp) ;\
  327. RESTORE_REG(s8, S8, sp) ;\
  328. RESTORE_REG(gp, GP, sp) ;\
  329. RESTORE_REG(ra, RA, sp) ;\
  330. PTR_ADDU sp, sp, KERN_EXC_FRAME_SIZE;\
  331. mtc0 k0, MIPS_COP_0_STATUS
  332. /*
  333. * The kernel exception stack contains 18 saved general registers,
  334. * the status register and the multiply lo and high registers.
  335. * In addition, we set this up for linkage conventions.
  336. */
  337. #define KERN_REG_SIZE (NUMSAVEREGS * SZREG)
  338. #define KERN_EXC_FRAME_SIZE (CALLFRAME_SIZ + KERN_REG_SIZE + 16)
  339. NNON_LEAF(MipsKernGenException, KERN_EXC_FRAME_SIZE, ra)
  340. .set noat
  341. PTR_SUBU sp, sp, KERN_EXC_FRAME_SIZE
  342. .mask 0x80000000, (CALLFRAME_RA - KERN_EXC_FRAME_SIZE)
  343. /*
  344. * Save CPU state, building 'frame'.
  345. */
  346. SAVE_CPU
  347. /*
  348. * Call the exception handler. a0 points at the saved frame.
  349. */
  350. PTR_LA gp, _C_LABEL(_gp)
  351. PTR_LA k0, _C_LABEL(trap)
  352. jalr k0
  353. REG_S a3, CALLFRAME_RA + KERN_REG_SIZE(sp) # for debugging
  354. /*
  355. * Update interrupt mask in saved status register
  356. * Some of interrupts could be disabled by
  357. * intr filters if interrupts are enabled later
  358. * in trap handler
  359. */
  360. mfc0 a0, MIPS_COP_0_STATUS
  361. and a0, a0, MIPS_SR_INT_MASK
  362. RESTORE_REG(a1, SR, sp)
  363. and a1, a1, ~MIPS_SR_INT_MASK
  364. or a1, a1, a0
  365. SAVE_REG(a1, SR, sp)
  366. RESTORE_CPU # v0 contains the return address.
  367. sync
  368. eret
  369. .set at
  370. END(MipsKernGenException)
  371. #define SAVE_U_PCB_REG(reg, offs, base) \
  372. REG_S reg, U_PCB_REGS + (SZREG * offs) (base)
  373. #define RESTORE_U_PCB_REG(reg, offs, base) \
  374. REG_L reg, U_PCB_REGS + (SZREG * offs) (base)
  375. /*----------------------------------------------------------------------------
  376. *
  377. * MipsUserGenException --
  378. *
  379. * Handle an exception from user mode.
  380. *
  381. * Results:
  382. * None.
  383. *
  384. * Side effects:
  385. * None.
  386. *
  387. *----------------------------------------------------------------------------
  388. */
  389. NNON_LEAF(MipsUserGenException, CALLFRAME_SIZ, ra)
  390. .set noat
  391. .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
  392. /*
  393. * Save all of the registers except for the kernel temporaries in u.u_pcb.
  394. */
  395. GET_CPU_PCPU(k1)
  396. PTR_L k1, PC_CURPCB(k1)
  397. SAVE_U_PCB_REG(AT, AST, k1)
  398. .set at
  399. SAVE_U_PCB_REG(v0, V0, k1)
  400. SAVE_U_PCB_REG(v1, V1, k1)
  401. SAVE_U_PCB_REG(a0, A0, k1)
  402. mflo v0
  403. SAVE_U_PCB_REG(a1, A1, k1)
  404. SAVE_U_PCB_REG(a2, A2, k1)
  405. SAVE_U_PCB_REG(a3, A3, k1)
  406. SAVE_U_PCB_REG(t0, T0, k1)
  407. mfhi v1
  408. SAVE_U_PCB_REG(t1, T1, k1)
  409. SAVE_U_PCB_REG(t2, T2, k1)
  410. SAVE_U_PCB_REG(t3, T3, k1)
  411. SAVE_U_PCB_REG(ta0, TA0, k1)
  412. mfc0 a0, MIPS_COP_0_STATUS # First arg is the status reg.
  413. SAVE_U_PCB_REG(ta1, TA1, k1)
  414. SAVE_U_PCB_REG(ta2, TA2, k1)
  415. SAVE_U_PCB_REG(ta3, TA3, k1)
  416. SAVE_U_PCB_REG(s0, S0, k1)
  417. mfc0 a1, MIPS_COP_0_CAUSE # Second arg is the cause reg.
  418. SAVE_U_PCB_REG(s1, S1, k1)
  419. SAVE_U_PCB_REG(s2, S2, k1)
  420. SAVE_U_PCB_REG(s3, S3, k1)
  421. SAVE_U_PCB_REG(s4, S4, k1)
  422. MFC0 a2, MIPS_COP_0_BAD_VADDR # Third arg is the fault addr
  423. SAVE_U_PCB_REG(s5, S5, k1)
  424. SAVE_U_PCB_REG(s6, S6, k1)
  425. SAVE_U_PCB_REG(s7, S7, k1)
  426. SAVE_U_PCB_REG(t8, T8, k1)
  427. MFC0 a3, MIPS_COP_0_EXC_PC # Fourth arg is the pc.
  428. SAVE_U_PCB_REG(t9, T9, k1)
  429. SAVE_U_PCB_REG(gp, GP, k1)
  430. SAVE_U_PCB_REG(sp, SP, k1)
  431. SAVE_U_PCB_REG(s8, S8, k1)
  432. PTR_SUBU sp, k1, CALLFRAME_SIZ # switch to kernel SP
  433. SAVE_U_PCB_REG(ra, RA, k1)
  434. SAVE_U_PCB_REG(v0, MULLO, k1)
  435. SAVE_U_PCB_REG(v1, MULHI, k1)
  436. SAVE_U_PCB_REG(a0, SR, k1)
  437. SAVE_U_PCB_REG(a1, CAUSE, k1)
  438. SAVE_U_PCB_REG(a2, BADVADDR, k1)
  439. SAVE_U_PCB_REG(a3, PC, k1)
  440. REG_S a3, CALLFRAME_RA(sp) # for debugging
  441. PTR_LA gp, _C_LABEL(_gp) # switch to kernel GP
  442. # Turn off fpu and enter kernel mode
  443. and t0, a0, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS3_SR_KSU_MASK | MIPS_SR_INT_IE)
  444. #if defined(CPU_CNMIPS)
  445. or t0, t0, (MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX | MIPS_SR_PX)
  446. #elif defined(CPU_RMI) || defined(CPU_NLM)
  447. or t0, t0, (MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_COP_2_BIT)
  448. #endif
  449. mtc0 t0, MIPS_COP_0_STATUS
  450. PTR_ADDU a0, k1, U_PCB_REGS
  451. ITLBNOPFIX
  452. /*
  453. * Call the exception handler.
  454. */
  455. PTR_LA k0, _C_LABEL(trap)
  456. jalr k0
  457. nop
  458. /*
  459. * Restore user registers and return.
  460. * First disable interrupts and set exeption level.
  461. */
  462. DO_AST
  463. CLEAR_STATUS
  464. /*
  465. * The use of k1 for storing the PCB pointer must be done only
  466. * after interrupts are disabled. Otherwise it will get overwritten
  467. * by the interrupt code.
  468. */
  469. GET_CPU_PCPU(k1)
  470. PTR_L k1, PC_CURPCB(k1)
  471. /*
  472. * Update interrupt mask in saved status register
  473. * Some of interrupts could be enabled by ithread
  474. * scheduled by ast()
  475. */
  476. mfc0 a0, MIPS_COP_0_STATUS
  477. and a0, a0, MIPS_SR_INT_MASK
  478. RESTORE_U_PCB_REG(a1, SR, k1)
  479. and a1, a1, ~MIPS_SR_INT_MASK
  480. or a1, a1, a0
  481. SAVE_U_PCB_REG(a1, SR, k1)
  482. RESTORE_U_PCB_REG(t0, MULLO, k1)
  483. RESTORE_U_PCB_REG(t1, MULHI, k1)
  484. mtlo t0
  485. mthi t1
  486. RESTORE_U_PCB_REG(a0, PC, k1)
  487. RESTORE_U_PCB_REG(v0, V0, k1)
  488. MTC0 a0, MIPS_COP_0_EXC_PC # set return address
  489. RESTORE_U_PCB_REG(v1, V1, k1)
  490. RESTORE_U_PCB_REG(a0, A0, k1)
  491. RESTORE_U_PCB_REG(a1, A1, k1)
  492. RESTORE_U_PCB_REG(a2, A2, k1)
  493. RESTORE_U_PCB_REG(a3, A3, k1)
  494. RESTORE_U_PCB_REG(t0, T0, k1)
  495. RESTORE_U_PCB_REG(t1, T1, k1)
  496. RESTORE_U_PCB_REG(t2, T2, k1)
  497. RESTORE_U_PCB_REG(t3, T3, k1)
  498. RESTORE_U_PCB_REG(ta0, TA0, k1)
  499. RESTORE_U_PCB_REG(ta1, TA1, k1)
  500. RESTORE_U_PCB_REG(ta2, TA2, k1)
  501. RESTORE_U_PCB_REG(ta3, TA3, k1)
  502. RESTORE_U_PCB_REG(s0, S0, k1)
  503. RESTORE_U_PCB_REG(s1, S1, k1)
  504. RESTORE_U_PCB_REG(s2, S2, k1)
  505. RESTORE_U_PCB_REG(s3, S3, k1)
  506. RESTORE_U_PCB_REG(s4, S4, k1)
  507. RESTORE_U_PCB_REG(s5, S5, k1)
  508. RESTORE_U_PCB_REG(s6, S6, k1)
  509. RESTORE_U_PCB_REG(s7, S7, k1)
  510. RESTORE_U_PCB_REG(t8, T8, k1)
  511. RESTORE_U_PCB_REG(t9, T9, k1)
  512. RESTORE_U_PCB_REG(gp, GP, k1)
  513. RESTORE_U_PCB_REG(sp, SP, k1)
  514. RESTORE_U_PCB_REG(k0, SR, k1)
  515. RESTORE_U_PCB_REG(s8, S8, k1)
  516. RESTORE_U_PCB_REG(ra, RA, k1)
  517. .set noat
  518. RESTORE_U_PCB_REG(AT, AST, k1)
  519. mtc0 k0, MIPS_COP_0_STATUS # still exception level
  520. ITLBNOPFIX
  521. sync
  522. eret
  523. .set at
  524. END(MipsUserGenException)
  525. /*----------------------------------------------------------------------------
  526. *
  527. * MipsKernIntr --
  528. *
  529. * Handle an interrupt from kernel mode.
  530. * Interrupts use the standard kernel stack.
  531. * switch_exit sets up a kernel stack after exit so interrupts won't fail.
  532. *
  533. * Results:
  534. * None.
  535. *
  536. * Side effects:
  537. * None.
  538. *
  539. *----------------------------------------------------------------------------
  540. */
  541. NNON_LEAF(MipsKernIntr, KERN_EXC_FRAME_SIZE, ra)
  542. .set noat
  543. PTR_SUBU sp, sp, KERN_EXC_FRAME_SIZE
  544. .mask 0x80000000, (CALLFRAME_RA - KERN_EXC_FRAME_SIZE)
  545. /*
  546. * Save CPU state, building 'frame'.
  547. */
  548. SAVE_CPU
  549. /*
  550. * Call the interrupt handler. a0 points at the saved frame.
  551. */
  552. PTR_LA gp, _C_LABEL(_gp)
  553. PTR_LA k0, _C_LABEL(cpu_intr)
  554. jalr k0
  555. REG_S a3, CALLFRAME_RA + KERN_REG_SIZE(sp) # for debugging
  556. /*
  557. * Update interrupt mask in saved status register
  558. * Some of interrupts could be disabled by
  559. * intr filters if interrupts are enabled later
  560. * in trap handler
  561. */
  562. mfc0 a0, MIPS_COP_0_STATUS
  563. and a0, a0, MIPS_SR_INT_MASK
  564. RESTORE_REG(a1, SR, sp)
  565. and a1, a1, ~MIPS_SR_INT_MASK
  566. or a1, a1, a0
  567. SAVE_REG(a1, SR, sp)
  568. REG_L v0, CALLFRAME_RA + KERN_REG_SIZE(sp)
  569. RESTORE_CPU # v0 contains the return address.
  570. sync
  571. eret
  572. .set at
  573. END(MipsKernIntr)
  574. /*----------------------------------------------------------------------------
  575. *
  576. * MipsUserIntr --
  577. *
  578. * Handle an interrupt from user mode.
  579. * Note: we save minimal state in the u.u_pcb struct and use the standard
  580. * kernel stack since there has to be a u page if we came from user mode.
  581. * If there is a pending software interrupt, then save the remaining state
  582. * and call softintr(). This is all because if we call switch() inside
  583. * interrupt(), not all the user registers have been saved in u.u_pcb.
  584. *
  585. * Results:
  586. * None.
  587. *
  588. * Side effects:
  589. * None.
  590. *
  591. *----------------------------------------------------------------------------
  592. */
  593. NNON_LEAF(MipsUserIntr, CALLFRAME_SIZ, ra)
  594. .set noat
  595. .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
  596. /*
  597. * Save the relevant user registers into the u.u_pcb struct.
  598. * We don't need to save s0 - s8 because the compiler does it for us.
  599. */
  600. GET_CPU_PCPU(k1)
  601. PTR_L k1, PC_CURPCB(k1)
  602. SAVE_U_PCB_REG(AT, AST, k1)
  603. .set at
  604. SAVE_U_PCB_REG(v0, V0, k1)
  605. SAVE_U_PCB_REG(v1, V1, k1)
  606. SAVE_U_PCB_REG(a0, A0, k1)
  607. SAVE_U_PCB_REG(a1, A1, k1)
  608. SAVE_U_PCB_REG(a2, A2, k1)
  609. SAVE_U_PCB_REG(a3, A3, k1)
  610. SAVE_U_PCB_REG(t0, T0, k1)
  611. SAVE_U_PCB_REG(t1, T1, k1)
  612. SAVE_U_PCB_REG(t2, T2, k1)
  613. SAVE_U_PCB_REG(t3, T3, k1)
  614. SAVE_U_PCB_REG(ta0, TA0, k1)
  615. SAVE_U_PCB_REG(ta1, TA1, k1)
  616. SAVE_U_PCB_REG(ta2, TA2, k1)
  617. SAVE_U_PCB_REG(ta3, TA3, k1)
  618. SAVE_U_PCB_REG(t8, T8, k1)
  619. SAVE_U_PCB_REG(t9, T9, k1)
  620. SAVE_U_PCB_REG(gp, GP, k1)
  621. SAVE_U_PCB_REG(sp, SP, k1)
  622. SAVE_U_PCB_REG(ra, RA, k1)
  623. /*
  624. * save remaining user state in u.u_pcb.
  625. */
  626. SAVE_U_PCB_REG(s0, S0, k1)
  627. SAVE_U_PCB_REG(s1, S1, k1)
  628. SAVE_U_PCB_REG(s2, S2, k1)
  629. SAVE_U_PCB_REG(s3, S3, k1)
  630. SAVE_U_PCB_REG(s4, S4, k1)
  631. SAVE_U_PCB_REG(s5, S5, k1)
  632. SAVE_U_PCB_REG(s6, S6, k1)
  633. SAVE_U_PCB_REG(s7, S7, k1)
  634. SAVE_U_PCB_REG(s8, S8, k1)
  635. mflo v0 # get lo/hi late to avoid stall
  636. mfhi v1
  637. mfc0 a0, MIPS_COP_0_STATUS
  638. mfc0 a1, MIPS_COP_0_CAUSE
  639. MFC0 a3, MIPS_COP_0_EXC_PC
  640. SAVE_U_PCB_REG(v0, MULLO, k1)
  641. SAVE_U_PCB_REG(v1, MULHI, k1)
  642. SAVE_U_PCB_REG(a0, SR, k1)
  643. SAVE_U_PCB_REG(a1, CAUSE, k1)
  644. SAVE_U_PCB_REG(a3, PC, k1) # PC in a3, note used later!
  645. PTR_SUBU sp, k1, CALLFRAME_SIZ # switch to kernel SP
  646. PTR_LA gp, _C_LABEL(_gp) # switch to kernel GP
  647. # Turn off fpu, disable interrupts, set kernel mode kernel mode, clear exception level.
  648. and t0, a0, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS_SR_INT_IE | MIPS3_SR_KSU_MASK)
  649. #ifdef CPU_CNMIPS
  650. or t0, t0, (MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX | MIPS_SR_PX)
  651. #elif defined(CPU_RMI) || defined(CPU_NLM)
  652. or t0, t0, (MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_COP_2_BIT)
  653. #endif
  654. mtc0 t0, MIPS_COP_0_STATUS
  655. ITLBNOPFIX
  656. PTR_ADDU a0, k1, U_PCB_REGS
  657. /*
  658. * Call the interrupt handler.
  659. */
  660. PTR_LA k0, _C_LABEL(cpu_intr)
  661. jalr k0
  662. REG_S a3, CALLFRAME_RA(sp) # for debugging
  663. /*
  664. * Enable interrupts before doing ast().
  665. *
  666. * On SMP kernels the AST processing might trigger IPI to other processors.
  667. * If that processor is also doing AST processing with interrupts disabled
  668. * then we may deadlock.
  669. */
  670. mfc0 a0, MIPS_COP_0_STATUS
  671. or a0, a0, MIPS_SR_INT_IE
  672. mtc0 a0, MIPS_COP_0_STATUS
  673. ITLBNOPFIX
  674. /*
  675. * DO_AST enabled interrupts
  676. */
  677. DO_AST
  678. /*
  679. * Restore user registers and return.
  680. */
  681. CLEAR_STATUS
  682. GET_CPU_PCPU(k1)
  683. PTR_L k1, PC_CURPCB(k1)
  684. /*
  685. * Update interrupt mask in saved status register
  686. * Some of interrupts could be disabled by
  687. * intr filters
  688. */
  689. mfc0 a0, MIPS_COP_0_STATUS
  690. and a0, a0, MIPS_SR_INT_MASK
  691. RESTORE_U_PCB_REG(a1, SR, k1)
  692. and a1, a1, ~MIPS_SR_INT_MASK
  693. or a1, a1, a0
  694. SAVE_U_PCB_REG(a1, SR, k1)
  695. RESTORE_U_PCB_REG(s0, S0, k1)
  696. RESTORE_U_PCB_REG(s1, S1, k1)
  697. RESTORE_U_PCB_REG(s2, S2, k1)
  698. RESTORE_U_PCB_REG(s3, S3, k1)
  699. RESTORE_U_PCB_REG(s4, S4, k1)
  700. RESTORE_U_PCB_REG(s5, S5, k1)
  701. RESTORE_U_PCB_REG(s6, S6, k1)
  702. RESTORE_U_PCB_REG(s7, S7, k1)
  703. RESTORE_U_PCB_REG(s8, S8, k1)
  704. RESTORE_U_PCB_REG(t0, MULLO, k1)
  705. RESTORE_U_PCB_REG(t1, MULHI, k1)
  706. RESTORE_U_PCB_REG(t2, PC, k1)
  707. mtlo t0
  708. mthi t1
  709. MTC0 t2, MIPS_COP_0_EXC_PC # set return address
  710. RESTORE_U_PCB_REG(v0, V0, k1)
  711. RESTORE_U_PCB_REG(v1, V1, k1)
  712. RESTORE_U_PCB_REG(a0, A0, k1)
  713. RESTORE_U_PCB_REG(a1, A1, k1)
  714. RESTORE_U_PCB_REG(a2, A2, k1)
  715. RESTORE_U_PCB_REG(a3, A3, k1)
  716. RESTORE_U_PCB_REG(t0, T0, k1)
  717. RESTORE_U_PCB_REG(t1, T1, k1)
  718. RESTORE_U_PCB_REG(t2, T2, k1)
  719. RESTORE_U_PCB_REG(t3, T3, k1)
  720. RESTORE_U_PCB_REG(ta0, TA0, k1)
  721. RESTORE_U_PCB_REG(ta1, TA1, k1)
  722. RESTORE_U_PCB_REG(ta2, TA2, k1)
  723. RESTORE_U_PCB_REG(ta3, TA3, k1)
  724. RESTORE_U_PCB_REG(t8, T8, k1)
  725. RESTORE_U_PCB_REG(t9, T9, k1)
  726. RESTORE_U_PCB_REG(gp, GP, k1)
  727. RESTORE_U_PCB_REG(k0, SR, k1)
  728. RESTORE_U_PCB_REG(sp, SP, k1)
  729. RESTORE_U_PCB_REG(ra, RA, k1)
  730. .set noat
  731. RESTORE_U_PCB_REG(AT, AST, k1)
  732. mtc0 k0, MIPS_COP_0_STATUS # SR with EXL set.
  733. ITLBNOPFIX
  734. sync
  735. eret
  736. .set at
  737. END(MipsUserIntr)
  738. NLEAF(MipsTLBInvalidException)
  739. .set push
  740. .set noat
  741. .set noreorder
  742. MFC0 k0, MIPS_COP_0_BAD_VADDR
  743. PTR_LI k1, VM_MAXUSER_ADDRESS
  744. sltu k1, k0, k1
  745. bnez k1, 1f
  746. nop
  747. /* Kernel address. */
  748. lui k1, %hi(kernel_segmap) # k1=hi of segbase
  749. b 2f
  750. PTR_L k1, %lo(kernel_segmap)(k1) # k1=segment tab base
  751. 1: /* User address. */
  752. GET_CPU_PCPU(k1)
  753. PTR_L k1, PC_SEGBASE(k1)
  754. 2: /* Validate page directory pointer. */
  755. beqz k1, 3f
  756. nop
  757. PTR_SRL k0, SEGSHIFT - PTRSHIFT # k0=seg offset (almost)
  758. beq k1, zero, MipsKernGenException # ==0 -- no seg tab
  759. andi k0, k0, PDEPTRMASK #06: k0=seg offset
  760. PTR_ADDU k1, k0, k1 # k1=seg entry address
  761. PTR_L k1, 0(k1) # k1=seg entry
  762. /* Validate page table pointer. */
  763. beqz k1, 3f
  764. nop
  765. #ifdef __mips_n64
  766. MFC0 k0, MIPS_COP_0_BAD_VADDR
  767. PTR_SRL k0, PDRSHIFT - PTRSHIFT # k0=pde offset (almost)
  768. beq k1, zero, MipsKernGenException # ==0 -- no pde tab
  769. andi k0, k0, PDEPTRMASK # k0=pde offset
  770. PTR_ADDU k1, k0, k1 # k1=pde entry address
  771. PTR_L k1, 0(k1) # k1=pde entry
  772. /* Validate pde table pointer. */
  773. beqz k1, 3f
  774. nop
  775. #endif
  776. MFC0 k0, MIPS_COP_0_BAD_VADDR # k0=bad address (again)
  777. PTR_SRL k0, PAGE_SHIFT - PTESHIFT # k0=VPN
  778. andi k0, k0, PTEMASK # k0=page tab offset
  779. PTR_ADDU k1, k1, k0 # k1=pte address
  780. PTE_L k0, 0(k1) # k0=this PTE
  781. /* Validate page table entry. */
  782. andi k0, PTE_V
  783. beqz k0, 3f
  784. nop
  785. /* Check whether this is an even or odd entry. */
  786. andi k0, k1, PTESIZE
  787. bnez k0, odd_page
  788. nop
  789. PTE_L k0, 0(k1)
  790. PTE_L k1, PTESIZE(k1)
  791. CLEAR_PTE_SWBITS(k0)
  792. PTE_MTC0 k0, MIPS_COP_0_TLB_LO0
  793. COP0_SYNC
  794. CLEAR_PTE_SWBITS(k1)
  795. PTE_MTC0 k1, MIPS_COP_0_TLB_LO1
  796. COP0_SYNC
  797. b tlb_insert_entry
  798. nop
  799. odd_page:
  800. PTE_L k0, -PTESIZE(k1)
  801. PTE_L k1, 0(k1)
  802. CLEAR_PTE_SWBITS(k0)
  803. PTE_MTC0 k0, MIPS_COP_0_TLB_LO0
  804. COP0_SYNC
  805. CLEAR_PTE_SWBITS(k1)
  806. PTE_MTC0 k1, MIPS_COP_0_TLB_LO1
  807. COP0_SYNC
  808. tlb_insert_entry:
  809. tlbp
  810. HAZARD_DELAY
  811. mfc0 k0, MIPS_COP_0_TLB_INDEX
  812. bltz k0, tlb_insert_random
  813. nop
  814. tlbwi
  815. eret
  816. ssnop
  817. tlb_insert_random:
  818. tlbwr
  819. eret
  820. ssnop
  821. 3:
  822. /*
  823. * Branch to the comprehensive exception processing.
  824. */
  825. mfc0 k1, MIPS_COP_0_STATUS
  826. andi k1, k1, SR_KSU_USER
  827. bnez k1, _C_LABEL(MipsUserGenException)
  828. nop
  829. /*
  830. * Check for kernel stack overflow.
  831. */
  832. GET_CPU_PCPU(k1)
  833. PTR_L k0, PC_CURTHREAD(k1)
  834. PTR_L k0, TD_KSTACK(k0)
  835. sltu k0, k0, sp
  836. bnez k0, _C_LABEL(MipsKernGenException)
  837. nop
  838. /*
  839. * Kernel stack overflow.
  840. *
  841. * Move to a valid stack before we call panic. We use the boot stack
  842. * for this purpose.
  843. */
  844. GET_CPU_PCPU(k1)
  845. lw k1, PC_CPUID(k1)
  846. sll k1, k1, PAGE_SHIFT + 1
  847. PTR_LA k0, _C_LABEL(pcpu_space)
  848. PTR_ADDU k0, PAGE_SIZE * 2
  849. PTR_ADDU k0, k0, k1
  850. /*
  851. * Stash the original value of 'sp' so we can update trapframe later.
  852. * We assume that SAVE_CPU does not trash 'k1'.
  853. */
  854. move k1, sp
  855. move sp, k0
  856. PTR_SUBU sp, sp, KERN_EXC_FRAME_SIZE
  857. move k0, ra
  858. move ra, zero
  859. REG_S ra, CALLFRAME_RA(sp) /* stop the ddb backtrace right here */
  860. REG_S zero, CALLFRAME_SP(sp)
  861. move ra, k0
  862. SAVE_CPU
  863. /*
  864. * Now restore the value of 'sp' at the time of the tlb exception in
  865. * the trapframe.
  866. */
  867. SAVE_REG(k1, SP, sp)
  868. /*
  869. * Squelch any more overflow checks by setting the stack base to 0.
  870. */
  871. GET_CPU_PCPU(k1)
  872. PTR_L k0, PC_CURTHREAD(k1)
  873. PTR_S zero, TD_KSTACK(k0)
  874. move a1, a0
  875. PANIC("kernel stack overflow - trapframe at %p")
  876. /*
  877. * This nop is necessary so that the 'ra' remains within the bounds
  878. * of this handler. Otherwise the ddb backtrace code will think that
  879. * the panic() was called from MipsTLBMissException.
  880. */
  881. nop
  882. .set pop
  883. END(MipsTLBInvalidException)
  884. /*----------------------------------------------------------------------------
  885. *
  886. * MipsTLBMissException --
  887. *
  888. * Handle a TLB miss exception from kernel mode in kernel space.
  889. * The BaddVAddr, Context, and EntryHi registers contain the failed
  890. * virtual address.
  891. *
  892. * Results:
  893. * None.
  894. *
  895. * Side effects:
  896. * None.
  897. *
  898. *----------------------------------------------------------------------------
  899. */
  900. NLEAF(MipsTLBMissException)
  901. .set noat
  902. MFC0 k0, MIPS_COP_0_BAD_VADDR # k0=bad address
  903. PTR_LI k1, VM_MAX_KERNEL_ADDRESS # check fault address against
  904. sltu k1, k1, k0 # upper bound of kernel_segmap
  905. bnez k1, MipsKernGenException # out of bound
  906. lui k1, %hi(kernel_segmap) # k1=hi of segbase
  907. PTR_SRL k0, SEGSHIFT - PTRSHIFT # k0=seg offset (almost)
  908. PTR_L k1, %lo(kernel_segmap)(k1) # k1=segment tab base
  909. beq k1, zero, MipsKernGenException # ==0 -- no seg tab
  910. andi k0, k0, PDEPTRMASK #06: k0=seg offset
  911. PTR_ADDU k1, k0, k1 # k1=seg entry address
  912. PTR_L k1, 0(k1) # k1=seg entry
  913. MFC0 k0, MIPS_COP_0_BAD_VADDR # k0=bad address (again)
  914. beq k1, zero, MipsKernGenException # ==0 -- no page table
  915. #ifdef __mips_n64
  916. PTR_SRL k0, PDRSHIFT - PTRSHIFT # k0=VPN
  917. andi k0, k0, PDEPTRMASK # k0=pde offset
  918. PTR_ADDU k1, k0, k1 # k1=pde entry address
  919. PTR_L k1, 0(k1) # k1=pde entry
  920. MFC0 k0, MIPS_COP_0_BAD_VADDR # k0=bad address (again)
  921. beq k1, zero, MipsKernGenException # ==0 -- no page table
  922. #endif
  923. PTR_SRL k0, PAGE_SHIFT - PTESHIFT # k0=VPN
  924. andi k0, k0, PTE2MASK # k0=page tab offset
  925. PTR_ADDU k1, k1, k0 # k1=pte address
  926. PTE_L k0, 0(k1) # k0=lo0 pte
  927. PTE_L k1, PTESIZE(k1) # k1=lo1 pte
  928. CLEAR_PTE_SWBITS(k0)
  929. PTE_MTC0 k0, MIPS_COP_0_TLB_LO0 # lo0 is loaded
  930. COP0_SYNC
  931. CLEAR_PTE_SWBITS(k1)
  932. PTE_MTC0 k1, MIPS_COP_0_TLB_LO1 # lo1 is loaded
  933. COP0_SYNC
  934. tlbwr # write to tlb
  935. HAZARD_DELAY
  936. eret # return from exception
  937. .set at
  938. END(MipsTLBMissException)
  939. /*----------------------------------------------------------------------------
  940. *
  941. * MipsFPTrap --
  942. *
  943. * Handle a floating point Trap.
  944. *
  945. * MipsFPTrap(statusReg, causeReg, pc)
  946. * unsigned statusReg;
  947. * unsigned causeReg;
  948. * unsigned pc;
  949. *
  950. * Results:
  951. * None.
  952. *
  953. * Side effects:
  954. * None.
  955. *
  956. *----------------------------------------------------------------------------
  957. */
  958. NON_LEAF(MipsFPTrap, CALLFRAME_SIZ, ra)
  959. PTR_SUBU sp, sp, CALLFRAME_SIZ
  960. mfc0 t0, MIPS_COP_0_STATUS
  961. REG_S ra, CALLFRAME_RA(sp)
  962. .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
  963. or t1, t0, MIPS_SR_COP_1_BIT
  964. mtc0 t1, MIPS_COP_0_STATUS
  965. ITLBNOPFIX
  966. cfc1 t1, MIPS_FPU_CSR # stall til FP done
  967. cfc1 t1, MIPS_FPU_CSR # now get status
  968. nop
  969. sll t2, t1, (31 - 17) # unimplemented operation?
  970. bgez t2, 3f # no, normal trap
  971. nop
  972. /*
  973. * We got an unimplemented operation trap so
  974. * fetch the instruction, compute the next PC and emulate the instruction.
  975. */
  976. bgez a1, 1f # Check the branch delay bit.
  977. nop
  978. /*
  979. * The instruction is in the branch delay slot so the branch will have to
  980. * be emulated to get the resulting PC.
  981. */
  982. PTR_S a2, CALLFRAME_SIZ + 8(sp)
  983. GET_CPU_PCPU(a0)
  984. #mips64 unsafe?
  985. PTR_L a0, PC_CURPCB(a0)
  986. PTR_ADDU a0, a0, U_PCB_REGS # first arg is ptr to CPU registers
  987. move a1, a2 # second arg is instruction PC
  988. move a2, t1 # third arg is floating point CSR
  989. PTR_LA t3, _C_LABEL(MipsEmulateBranch) # compute PC after branch
  990. jalr t3 # compute PC after branch
  991. move a3, zero # fourth arg is FALSE
  992. /*
  993. * Now load the floating-point instruction in the branch delay slot
  994. * to be emulated.
  995. */
  996. PTR_L a2, CALLFRAME_SIZ + 8(sp) # restore EXC pc
  997. b 2f
  998. lw a0, 4(a2) # a0 = coproc instruction
  999. /*
  1000. * This is not in the branch delay slot so calculate the resulting
  1001. * PC (epc + 4) into v0 and continue to MipsEmulateFP().
  1002. */
  1003. 1:
  1004. lw a0, 0(a2) # a0 = coproc instruction
  1005. #xxx mips64 unsafe?
  1006. PTR_ADDU v0, a2, 4 # v0 = next pc
  1007. 2:
  1008. GET_CPU_PCPU(t2)
  1009. PTR_L t2, PC_CURPCB(t2)
  1010. SAVE_U_PCB_REG(v0, PC, t2) # save new pc
  1011. /*
  1012. * Check to see if the instruction to be emulated is a floating-point
  1013. * instruction.
  1014. */
  1015. srl a3, a0, MIPS_OPCODE_SHIFT
  1016. beq a3, MIPS_OPCODE_C1, 4f # this should never fail
  1017. nop
  1018. /*
  1019. * Send a floating point exception signal to the current process.
  1020. */
  1021. 3:
  1022. GET_CPU_PCPU(a0)
  1023. PTR_L a0, PC_CURTHREAD(a0) # get current thread
  1024. cfc1 a2, MIPS_FPU_CSR # code = FP execptions
  1025. ctc1 zero, MIPS_FPU_CSR # Clear exceptions
  1026. PTR_LA t3, _C_LABEL(trapsignal)
  1027. jalr t3
  1028. li a1, SIGFPE
  1029. b FPReturn
  1030. nop
  1031. /*
  1032. * Finally, we can call MipsEmulateFP() where a0 is the instruction to emulate.
  1033. */
  1034. 4:
  1035. PTR_LA t3, _C_LABEL(MipsEmulateFP)
  1036. jalr t3
  1037. nop
  1038. /*
  1039. * Turn off the floating point coprocessor and return.
  1040. */
  1041. FPReturn:
  1042. mfc0 t0, MIPS_COP_0_STATUS
  1043. PTR_L ra, CALLFRAME_RA(sp)
  1044. and t0, t0, ~MIPS_SR_COP_1_BIT
  1045. mtc0 t0, MIPS_COP_0_STATUS
  1046. ITLBNOPFIX
  1047. j ra
  1048. PTR_ADDU sp, sp, CALLFRAME_SIZ
  1049. END(MipsFPTrap)
  1050. /*
  1051. * Interrupt counters for vmstat.
  1052. */
  1053. .data
  1054. .globl intrcnt
  1055. .globl sintrcnt
  1056. .globl intrnames
  1057. .globl sintrnames
  1058. intrnames:
  1059. .space INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
  1060. sintrnames:
  1061. #ifdef __mips_n64
  1062. .quad INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
  1063. #else
  1064. .int INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
  1065. #endif
  1066. .align 4
  1067. intrcnt:
  1068. .space INTRCNT_COUNT * 4 * 2
  1069. sintrcnt:
  1070. #ifdef __mips_n64
  1071. .quad INTRCNT_COUNT * 4 * 2
  1072. #else
  1073. .int INTRCNT_COUNT * 4 * 2
  1074. #endif
  1075. /*
  1076. * Vector to real handler in KSEG1.
  1077. */
  1078. .text
  1079. VECTOR(MipsCache, unknown)
  1080. PTR_LA k0, _C_LABEL(MipsCacheException)
  1081. li k1, MIPS_KSEG0_PHYS_MASK
  1082. and k0, k1
  1083. PTR_LI k1, MIPS_KSEG1_START
  1084. or k0, k1
  1085. j k0
  1086. nop
  1087. VECTOR_END(MipsCache)
  1088. .set at
  1089. /*
  1090. * Panic on cache errors. A lot more could be done to recover
  1091. * from some types of errors but it is tricky.
  1092. */
  1093. NESTED_NOPROFILE(MipsCacheException, KERN_EXC_FRAME_SIZE, ra)
  1094. .set noat
  1095. .mask 0x80000000, -4
  1096. PTR_LA k0, _C_LABEL(panic) # return to panic
  1097. PTR_LA a0, 9f # panicstr
  1098. MFC0 a1, MIPS_COP_0_ERROR_PC
  1099. mfc0 a2, MIPS_COP_0_CACHE_ERR # 3rd arg cache error
  1100. MTC0 k0, MIPS_COP_0_ERROR_PC # set return address
  1101. mfc0 k0, MIPS_COP_0_STATUS # restore status
  1102. li k1, MIPS_SR_DIAG_PE # ignore further errors
  1103. or k0, k1
  1104. mtc0 k0, MIPS_COP_0_STATUS # restore status
  1105. COP0_SYNC
  1106. eret
  1107. MSG("cache error @ EPC 0x%x CachErr 0x%x");
  1108. .set at
  1109. END(MipsCacheException)