entry.S
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:41k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: entry.S,v 1.170 2001/11/13 00:57:05 davem Exp $
  2.  * arch/sparc/kernel/entry.S:  Sparc trap low-level entry points.
  3.  *
  4.  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  5.  * Copyright (C) 1996 Eddie C. Dost   (ecd@skynet.be)
  6.  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
  7.  * Copyright (C) 1996-1999 Jakub Jelinek   (jj@sunsite.mff.cuni.cz)
  8.  * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au)
  9.  */
  10. #include <linux/config.h>
  11. #include <linux/errno.h>
  12. #include <asm/head.h>
  13. #include <asm/asi.h>
  14. #include <asm/smp.h>
  15. #include <asm/kgdb.h>
  16. #include <asm/contregs.h>
  17. #include <asm/ptrace.h>
  18. #include <asm/psr.h>
  19. #include <asm/cprefix.h>
  20. #include <asm/vaddrs.h>
  21. #include <asm/memreg.h>
  22. #include <asm/page.h>
  23. #ifdef CONFIG_SUN4
  24. #include <asm/pgtsun4.h>
  25. #else
  26. #include <asm/pgtsun4c.h>
  27. #endif
  28. #include <asm/winmacro.h>
  29. #include <asm/signal.h>
  30. #include <asm/obio.h>
  31. #include <asm/mxcc.h>
  32. #include <asm/asmmacro.h>
  33. #define curptr      g6
  34. #define NR_SYSCALLS 256      /* Each OS is different... */
  35. /* First, KGDB low level things.  This is a rewrite
  36.  * of the routines found in the sparc-stub.c asm() statement
  37.  * from the gdb distribution.  This is also dual-purpose
  38.  * as a software trap for userlevel programs.
  39.  */
  40. .data
  41. .align 4
  42. in_trap_handler:
  43. .word 0
  44. .text
  45. .align 4
  46. ! This function is called when any SPARC trap (except window overflow or
  47. ! underflow) occurs.  It makes sure that the invalid register window is still
  48. ! available before jumping into C code.  It will also restore the world if you
  49. ! return from handle_exception.
  50. .globl C_LABEL(trap_low)
  51. C_LABEL(trap_low):
  52. rd %wim, %l3
  53. SAVE_ALL
  54. sethi %hi(in_trap_handler), %l4
  55. ld [%lo(in_trap_handler) + %l4], %l5
  56. inc %l5
  57. st %l5, [%lo(in_trap_handler) + %l4]
  58. /* Make sure kgdb sees the same state we just saved. */
  59. LOAD_PT_GLOBALS(sp)
  60. LOAD_PT_INS(sp)
  61. ld [%sp + REGWIN_SZ + PT_Y], %l4
  62. ld [%sp + REGWIN_SZ + PT_WIM], %l3
  63. ld [%sp + REGWIN_SZ + PT_PSR], %l0
  64. ld [%sp + REGWIN_SZ + PT_PC], %l1
  65. ld [%sp + REGWIN_SZ + PT_NPC], %l2
  66. rd %tbr, %l5 /* Never changes... */
  67. /* Make kgdb exception frame. */
  68. sub %sp,(16+1+6+1+72)*4,%sp ! Make room for input & locals
  69.   ! + hidden arg + arg spill
  70. ! + doubleword alignment
  71. ! + registers[72] local var
  72. SAVE_KGDB_GLOBALS(sp)
  73. SAVE_KGDB_INS(sp)
  74. SAVE_KGDB_SREGS(sp, l4, l0, l3, l5, l1, l2)
  75. /* We are increasing PIL, so two writes. */
  76. or %l0, PSR_PIL, %l0
  77. wr %l0, 0, %psr
  78. WRITE_PAUSE
  79. wr %l0, PSR_ET, %psr
  80. WRITE_PAUSE
  81. call C_LABEL(handle_exception)
  82.  add %sp, REGWIN_SZ, %o0 ! Pass address of registers
  83. /* Load new kgdb register set. */
  84. LOAD_KGDB_GLOBALS(sp)
  85. LOAD_KGDB_INS(sp)
  86. LOAD_KGDB_SREGS(sp, l4, l0, l3, l5, l1, l2)
  87. wr      %l4, 0x0, %y
  88. sethi %hi(in_trap_handler), %l4
  89. ld [%lo(in_trap_handler) + %l4], %l5
  90. dec %l5
  91. st %l5, [%lo(in_trap_handler) + %l4]
  92. add %sp,(16+1+6+1+72)*4,%sp ! Undo the kgdb trap frame.
  93. /* Now take what kgdb did and place it into the pt_regs
  94.  * frame which SparcLinux RESTORE_ALL understands.,
  95.  */
  96. STORE_PT_INS(sp)
  97. STORE_PT_GLOBALS(sp)
  98. STORE_PT_YREG(sp, g2)
  99. STORE_PT_PRIV(sp, l0, l1, l2)
  100. RESTORE_ALL
  101. #ifdef CONFIG_BLK_DEV_FD
  102. .text
  103. .align 4
  104. .globl C_LABEL(floppy_hardint)
  105. C_LABEL(floppy_hardint):
  106. /*
  107.  * This code cannot touch registers %l0 %l1 and %l2
  108.  * because SAVE_ALL depends on their values. It depends
  109.  * on %l3 also, but we regenerate it before a call.
  110.  * Other registers are:
  111.  * %l3 -- base address of fdc registers
  112.  * %l4 -- pdma_vaddr
  113.  * %l5 -- scratch for ld/st address
  114.  * %l6 -- pdma_size
  115.  * %l7 -- scratch [floppy byte, ld/st address, aux. data]
  116.  */
  117. /* Do we have work to do? */
  118. sethi %hi(C_LABEL(doing_pdma)), %l7
  119. ld [%l7 + %lo(C_LABEL(doing_pdma))], %l7
  120. cmp %l7, 0
  121. be floppy_dosoftint
  122.  nop
  123. /* Load fdc register base */
  124. sethi %hi(C_LABEL(fdc_status)), %l3
  125. ld [%l3 + %lo(C_LABEL(fdc_status))], %l3
  126. /* Setup register addresses */
  127. sethi %hi(C_LABEL(pdma_vaddr)), %l5 ! transfer buffer
  128. ld [%l5 + %lo(C_LABEL(pdma_vaddr))], %l4
  129. sethi %hi(C_LABEL(pdma_size)), %l5 ! bytes to go
  130. ld [%l5 + %lo(C_LABEL(pdma_size))], %l6
  131. next_byte:
  132.    ldub [%l3], %l7
  133. andcc %l7, 0x80, %g0 ! Does fifo still have data
  134. bz floppy_fifo_emptied ! fifo has been emptied...
  135.  andcc %l7, 0x20, %g0 ! in non-dma mode still?
  136. bz floppy_overrun ! nope, overrun
  137.  andcc %l7, 0x40, %g0 ! 0=write 1=read
  138. bz floppy_write
  139.  sub %l6, 0x1, %l6
  140. /* Ok, actually read this byte */
  141. ldub [%l3 + 1], %l7
  142. orcc %g0, %l6, %g0
  143. stb %l7, [%l4]
  144. bne next_byte
  145.  add %l4, 0x1, %l4
  146. b floppy_tdone
  147.  nop
  148. floppy_write:
  149. /* Ok, actually write this byte */
  150. ldub [%l4], %l7
  151. orcc %g0, %l6, %g0
  152. stb %l7, [%l3 + 1]
  153. bne next_byte
  154.  add %l4, 0x1, %l4
  155. /* fall through... */
  156. floppy_tdone:
  157. sethi %hi(C_LABEL(pdma_vaddr)), %l5
  158. st %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
  159. sethi %hi(C_LABEL(pdma_size)), %l5
  160. st %l6, [%l5 + %lo(C_LABEL(pdma_size))]
  161. /* Flip terminal count pin */
  162. set C_LABEL(auxio_register), %l7
  163. ld [%l7], %l7
  164. set C_LABEL(sparc_cpu_model), %l5
  165. ld [%l5], %l5
  166. subcc   %l5, 1, %g0 /* enum { sun4c = 1 }; */
  167. be 1f
  168.  ldub [%l7], %l5
  169. or %l5, 0xc2, %l5
  170. stb %l5, [%l7]
  171. andn    %l5, 0x02, %l5
  172. b 2f
  173.  nop
  174. 1:
  175. or      %l5, 0xf4, %l5
  176. stb     %l5, [%l7]
  177. andn    %l5, 0x04, %l5
  178. 2:
  179. /* Kill some time so the bits set */
  180. WRITE_PAUSE
  181. WRITE_PAUSE
  182. stb     %l5, [%l7]
  183. /* Prevent recursion */
  184. sethi %hi(C_LABEL(doing_pdma)), %l7
  185. b floppy_dosoftint
  186.  st %g0, [%l7 + %lo(C_LABEL(doing_pdma))]
  187. /* We emptied the FIFO, but we haven't read everything
  188.  * as of yet.  Store the current transfer address and
  189.  * bytes left to read so we can continue when the next
  190.  * fast IRQ comes in.
  191.  */
  192. floppy_fifo_emptied:
  193. sethi %hi(C_LABEL(pdma_vaddr)), %l5
  194. st %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
  195. sethi %hi(C_LABEL(pdma_size)), %l7
  196. st %l6, [%l7 + %lo(C_LABEL(pdma_size))]
  197. /* Restore condition codes */
  198. wr %l0, 0x0, %psr
  199. WRITE_PAUSE
  200. jmp %l1
  201. rett %l2
  202. floppy_overrun:
  203. sethi %hi(C_LABEL(pdma_vaddr)), %l5
  204. st %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
  205. sethi %hi(C_LABEL(pdma_size)), %l5
  206. st %l6, [%l5 + %lo(C_LABEL(pdma_size))]
  207. /* Prevent recursion */
  208. sethi %hi(C_LABEL(doing_pdma)), %l7
  209. st %g0, [%l7 + %lo(C_LABEL(doing_pdma))]
  210. /* fall through... */
  211. floppy_dosoftint:
  212. rd %wim, %l3
  213. SAVE_ALL
  214. /* Set all IRQs off. */
  215. or %l0, PSR_PIL, %l4
  216. wr %l4, 0x0, %psr
  217. WRITE_PAUSE
  218. wr %l4, PSR_ET, %psr
  219. WRITE_PAUSE
  220. mov 11, %o0 ! floppy irq level (unused anyway)
  221. mov %g0, %o1 ! devid is not used in fast interrupts
  222. call C_LABEL(sparc_floppy_irq)
  223.  add %sp, REGWIN_SZ, %o2 ! struct pt_regs *regs
  224. RESTORE_ALL
  225. #endif /* (CONFIG_BLK_DEV_FD) */
  226. /* Bad trap handler */
  227. .globl bad_trap_handler
  228. bad_trap_handler:
  229. SAVE_ALL
  230. wr %l0, PSR_ET, %psr
  231. WRITE_PAUSE
  232. mov %l7, %o0 ! trap number
  233. mov %l0, %o1 ! psr
  234. call C_LABEL(do_hw_interrupt)
  235.  mov %l1, %o2 ! pc
  236. RESTORE_ALL
  237. /* For now all IRQ's not registered get sent here. handler_irq() will
  238.  * see if a routine is registered to handle this interrupt and if not
  239.  * it will say so on the console.
  240.  */
  241. .align 4
  242. .globl real_irq_entry, patch_handler_irq
  243. real_irq_entry:
  244. SAVE_ALL
  245. #ifdef CONFIG_SMP
  246. .globl patchme_maybe_smp_msg
  247. cmp %l7, 12
  248. patchme_maybe_smp_msg:
  249. bgu maybe_smp4m_msg
  250.  nop
  251. #endif
  252. real_irq_continue:
  253. or %l0, PSR_PIL, %g2
  254. wr %g2, 0x0, %psr
  255. WRITE_PAUSE
  256. wr %g2, PSR_ET, %psr
  257. WRITE_PAUSE
  258. mov %l7, %o0 ! irq level
  259. patch_handler_irq:
  260. call C_LABEL(handler_irq)
  261.  add %sp, REGWIN_SZ, %o1 ! pt_regs ptr
  262. or %l0, PSR_PIL, %g2 ! restore PIL after handler_irq
  263. wr %g2, PSR_ET, %psr ! keep ET up
  264. WRITE_PAUSE
  265. RESTORE_ALL
  266. #ifdef CONFIG_SMP
  267. /* SMP per-cpu ticker interrupts are handled specially. */
  268. smp4m_ticker:
  269. bne real_irq_continue+4
  270.  or %l0, PSR_PIL, %g2
  271. wr %g2, 0x0, %psr
  272. WRITE_PAUSE
  273. wr %g2, PSR_ET, %psr
  274. WRITE_PAUSE
  275. call C_LABEL(smp4m_percpu_timer_interrupt)
  276.  add %sp, REGWIN_SZ, %o0
  277. wr %l0, PSR_ET, %psr
  278. WRITE_PAUSE
  279. RESTORE_ALL
  280. /* Here is where we check for possible SMP IPI passed to us
  281.  * on some level other than 15 which is the NMI and only used
  282.  * for cross calls.  That has a separate entry point below.
  283.  */
  284. maybe_smp4m_msg:
  285. GET_PROCESSOR_MID(o3, o2)
  286. set C_LABEL(sun4m_interrupts), %l5
  287. ld [%l5], %o5
  288. sethi %hi(0x60000000), %o4
  289. sll %o3, 12, %o3
  290. ld [%o5 + %o3], %o1
  291. andcc %o1, %o4, %g0
  292. be,a smp4m_ticker
  293.  cmp %l7, 14
  294. cmp %l7, 13
  295. add %o5, %o3, %o5
  296. bne,a 1f
  297.  sethi %hi(0x40000000), %o2
  298. sethi %hi(0x20000000), %o2
  299. 1:
  300. st %o2, [%o5 + 0x4]
  301. WRITE_PAUSE
  302. ld [%o5], %g0
  303. WRITE_PAUSE
  304. or %l0, PSR_PIL, %l4
  305. wr %l4, 0x0, %psr
  306. WRITE_PAUSE
  307. wr %l4, PSR_ET, %psr
  308. WRITE_PAUSE
  309. cmp %l7, 13
  310. bne 2f
  311.  nop
  312. call C_LABEL(smp_reschedule_irq)
  313.  add %o7, 8, %o7
  314. 2:
  315. call C_LABEL(smp_stop_cpu_irq)
  316.  nop
  317. RESTORE_ALL
  318. .align 4
  319. .globl linux_trap_ipi15_sun4m
  320. linux_trap_ipi15_sun4m:
  321. SAVE_ALL
  322. sethi %hi(0x80000000), %o2
  323. GET_PROCESSOR_MID(o0, o1)
  324. set C_LABEL(sun4m_interrupts), %l5
  325. ld [%l5], %o5
  326. sll %o0, 12, %o0
  327. add %o5, %o0, %o5
  328. ld [%o5], %o3
  329. andcc %o3, %o2, %g0
  330. be 1f ! Must be an NMI async memory error
  331.  st %o2, [%o5 + 4]
  332. WRITE_PAUSE
  333. ld [%o5], %g0
  334. WRITE_PAUSE
  335. or %l0, PSR_PIL, %l4
  336. wr %l4, 0x0, %psr
  337. WRITE_PAUSE
  338. wr %l4, PSR_ET, %psr
  339. WRITE_PAUSE
  340. call C_LABEL(smp4m_cross_call_irq)
  341.  nop
  342. b ret_trap_lockless_ipi
  343.  clr %l6
  344. 1:
  345. /* NMI async memory error handling. */
  346. sethi %hi(0x80000000), %l4
  347. sethi %hi(0x4000), %o3
  348. sub %o5, %o0, %o5
  349. add %o5, %o3, %l5
  350. st %l4, [%l5 + 0xc]
  351. WRITE_PAUSE
  352. ld [%l5], %g0
  353. WRITE_PAUSE
  354. or %l0, PSR_PIL, %l4
  355. wr %l4, 0x0, %psr
  356. WRITE_PAUSE
  357. wr %l4, PSR_ET, %psr
  358. WRITE_PAUSE
  359. call C_LABEL(sun4m_nmi)
  360.  nop
  361. st %l4, [%l5 + 0x8]
  362. WRITE_PAUSE
  363. ld [%l5], %g0
  364. WRITE_PAUSE
  365. RESTORE_ALL
  366. .globl smp4d_ticker
  367. /* SMP per-cpu ticker interrupts are handled specially. */
  368. smp4d_ticker:
  369. SAVE_ALL
  370. or %l0, PSR_PIL, %g2
  371. sethi %hi(CC_ICLR), %o0
  372. sethi %hi(1 << 14), %o1
  373. or %o0, %lo(CC_ICLR), %o0
  374. stha %o1, [%o0] ASI_M_MXCC /* Clear PIL 14 in MXCC's ICLR */
  375. wr %g2, 0x0, %psr
  376. WRITE_PAUSE
  377. wr %g2, PSR_ET, %psr
  378. WRITE_PAUSE
  379. call C_LABEL(smp4d_percpu_timer_interrupt)
  380.  add %sp, REGWIN_SZ, %o0
  381. wr %l0, PSR_ET, %psr
  382. WRITE_PAUSE
  383. RESTORE_ALL
  384. .align 4
  385. .globl linux_trap_ipi15_sun4d
  386. linux_trap_ipi15_sun4d:
  387. SAVE_ALL
  388. sethi %hi(CC_BASE), %o4
  389. sethi %hi(MXCC_ERR_ME|MXCC_ERR_PEW|MXCC_ERR_ASE|MXCC_ERR_PEE), %o2
  390. or %o4, (CC_EREG - CC_BASE), %o0
  391. ldda [%o0] ASI_M_MXCC, %o0
  392. andcc %o0, %o2, %g0
  393. bne 1f
  394.  sethi %hi(BB_STAT2), %o2
  395. lduba [%o2] ASI_M_CTL, %o2
  396. andcc %o2, BB_STAT2_MASK, %g0
  397. bne 2f
  398.  or %o4, (CC_ICLR - CC_BASE), %o0
  399. sethi %hi(1 << 15), %o1
  400. stha %o1, [%o0] ASI_M_MXCC /* Clear PIL 15 in MXCC's ICLR */
  401. or %l0, PSR_PIL, %l4
  402. wr %l4, 0x0, %psr
  403. WRITE_PAUSE
  404. wr %l4, PSR_ET, %psr
  405. WRITE_PAUSE
  406. call C_LABEL(smp4d_cross_call_irq)
  407.  nop
  408. b ret_trap_lockless_ipi
  409.  clr %l6
  410. 1: /* MXCC error */
  411. 2: /* BB error */
  412. /* Disable PIL 15 */
  413. set CC_IMSK, %l4
  414. lduha [%l4] ASI_M_MXCC, %l5
  415. sethi %hi(1 << 15), %l7
  416. or %l5, %l7, %l5
  417. stha %l5, [%l4] ASI_M_MXCC
  418. /* FIXME */
  419. 1: b,a 1b
  420. #endif /* CONFIG_SMP */
  421. /* This routine handles illegal instructions and privileged
  422.  * instruction attempts from user code.
  423.  */
  424. .align 4
  425. .globl bad_instruction
  426. bad_instruction:
  427. sethi %hi(0xc1f80000), %l4
  428. ld [%l1], %l5
  429. sethi %hi(0x81d80000), %l7
  430. and %l5, %l4, %l5
  431. cmp %l5, %l7
  432. be 1f
  433. SAVE_ALL
  434. wr %l0, PSR_ET, %psr ! re-enable traps
  435. WRITE_PAUSE
  436. add %sp, REGWIN_SZ, %o0
  437. mov %l1, %o1
  438. mov %l2, %o2
  439. call C_LABEL(do_illegal_instruction)
  440.  mov %l0, %o3
  441. RESTORE_ALL
  442. 1: /* unimplemented flush - just skip */
  443. jmpl %l2, %g0
  444.  rett %l2 + 4
  445. .align 4
  446. .globl priv_instruction
  447. priv_instruction:
  448. SAVE_ALL
  449. wr %l0, PSR_ET, %psr
  450. WRITE_PAUSE
  451. add %sp, REGWIN_SZ, %o0
  452. mov %l1, %o1
  453. mov %l2, %o2
  454. call C_LABEL(do_priv_instruction)
  455.  mov %l0, %o3
  456. RESTORE_ALL
  457. /* This routine handles unaligned data accesses. */
  458. .align 4
  459. .globl mna_handler
  460. mna_handler:
  461. andcc %l0, PSR_PS, %g0
  462. be mna_fromuser
  463.  nop
  464. SAVE_ALL
  465. wr %l0, PSR_ET, %psr
  466. WRITE_PAUSE
  467. ld [%l1], %o1
  468. call C_LABEL(kernel_unaligned_trap)
  469.  add %sp, REGWIN_SZ, %o0
  470. RESTORE_ALL
  471. mna_fromuser:
  472. SAVE_ALL
  473. wr %l0, PSR_ET, %psr ! re-enable traps
  474. WRITE_PAUSE
  475. ld [%l1], %o1
  476. call C_LABEL(user_unaligned_trap)
  477.  add %sp, REGWIN_SZ, %o0
  478. RESTORE_ALL
  479. /* This routine handles floating point disabled traps. */
  480. .align 4
  481. .globl fpd_trap_handler
  482. fpd_trap_handler:
  483. SAVE_ALL
  484. wr %l0, PSR_ET, %psr ! re-enable traps
  485. WRITE_PAUSE
  486. add %sp, REGWIN_SZ, %o0
  487. mov %l1, %o1
  488. mov %l2, %o2
  489. call C_LABEL(do_fpd_trap)
  490.  mov %l0, %o3
  491. RESTORE_ALL
  492. /* This routine handles Floating Point Exceptions. */
  493. .align 4
  494. .globl fpe_trap_handler
  495. fpe_trap_handler:
  496. set fpsave_magic, %l5
  497. cmp %l1, %l5
  498. be 1f
  499.  sethi %hi(C_LABEL(fpsave)), %l5
  500. or %l5, %lo(C_LABEL(fpsave)), %l5
  501. cmp %l1, %l5
  502. bne 2f
  503.  sethi %hi(fpsave_catch2), %l5
  504. or %l5, %lo(fpsave_catch2), %l5
  505. wr %l0, 0x0, %psr
  506. WRITE_PAUSE
  507. jmp %l5
  508.  rett %l5 + 4
  509. 1:
  510. sethi %hi(fpsave_catch), %l5
  511. or %l5, %lo(fpsave_catch), %l5
  512. wr %l0, 0x0, %psr
  513. WRITE_PAUSE
  514. jmp %l5
  515.  rett %l5 + 4
  516. 2:
  517. SAVE_ALL
  518. wr %l0, PSR_ET, %psr ! re-enable traps
  519. WRITE_PAUSE
  520. add %sp, REGWIN_SZ, %o0
  521. mov %l1, %o1
  522. mov %l2, %o2
  523. call C_LABEL(do_fpe_trap)
  524.  mov %l0, %o3
  525. RESTORE_ALL
  526. /* This routine handles Tag Overflow Exceptions. */
  527. .align 4
  528. .globl do_tag_overflow
  529. do_tag_overflow:
  530. SAVE_ALL
  531. wr %l0, PSR_ET, %psr ! re-enable traps
  532. WRITE_PAUSE
  533. add %sp, REGWIN_SZ, %o0
  534. mov %l1, %o1
  535. mov %l2, %o2
  536. call C_LABEL(handle_tag_overflow)
  537.  mov %l0, %o3
  538. RESTORE_ALL
  539. /* This routine handles Watchpoint Exceptions. */
  540. .align 4
  541. .globl do_watchpoint
  542. do_watchpoint:
  543. SAVE_ALL
  544. wr %l0, PSR_ET, %psr ! re-enable traps
  545. WRITE_PAUSE
  546. add %sp, REGWIN_SZ, %o0
  547. mov %l1, %o1
  548. mov %l2, %o2
  549. call C_LABEL(handle_watchpoint)
  550.  mov %l0, %o3
  551. RESTORE_ALL
  552. /* This routine handles Register Access Exceptions. */
  553. .align 4
  554. .globl do_reg_access
  555. do_reg_access:
  556. SAVE_ALL
  557. wr %l0, PSR_ET, %psr ! re-enable traps
  558. WRITE_PAUSE
  559. add %sp, REGWIN_SZ, %o0
  560. mov %l1, %o1
  561. mov %l2, %o2
  562. call C_LABEL(handle_reg_access)
  563.  mov %l0, %o3
  564. RESTORE_ALL
  565. /* This routine handles Co-Processor Disabled Exceptions. */
  566. .align 4
  567. .globl do_cp_disabled
  568. do_cp_disabled:
  569. SAVE_ALL
  570. wr %l0, PSR_ET, %psr ! re-enable traps
  571. WRITE_PAUSE
  572. add %sp, REGWIN_SZ, %o0
  573. mov %l1, %o1
  574. mov %l2, %o2
  575. call C_LABEL(handle_cp_disabled)
  576.  mov %l0, %o3
  577. RESTORE_ALL
  578. /* This routine handles Co-Processor Exceptions. */
  579. .align 4
  580. .globl do_cp_exception
  581. do_cp_exception:
  582. SAVE_ALL
  583. wr %l0, PSR_ET, %psr ! re-enable traps
  584. WRITE_PAUSE
  585. add %sp, REGWIN_SZ, %o0
  586. mov %l1, %o1
  587. mov %l2, %o2
  588. call C_LABEL(handle_cp_exception)
  589.  mov %l0, %o3
  590. RESTORE_ALL
  591. /* This routine handles Hardware Divide By Zero Exceptions. */
  592. .align 4
  593. .globl do_hw_divzero
  594. do_hw_divzero:
  595. SAVE_ALL
  596. wr %l0, PSR_ET, %psr ! re-enable traps
  597. WRITE_PAUSE
  598. add %sp, REGWIN_SZ, %o0
  599. mov %l1, %o1
  600. mov %l2, %o2
  601. call C_LABEL(handle_hw_divzero)
  602.  mov %l0, %o3
  603. RESTORE_ALL
  604. .align 4
  605. .globl do_flush_windows
  606. do_flush_windows:
  607. SAVE_ALL
  608. wr %l0, PSR_ET, %psr
  609. WRITE_PAUSE
  610. andcc %l0, PSR_PS, %g0
  611. bne dfw_kernel
  612.  nop
  613. call C_LABEL(flush_user_windows)
  614.  nop
  615. /* Advance over the trap instruction. */
  616. ld [%sp + REGWIN_SZ + PT_NPC], %l1
  617. add %l1, 0x4, %l2
  618. st %l1, [%sp + REGWIN_SZ + PT_PC]
  619. st %l2, [%sp + REGWIN_SZ + PT_NPC]
  620. RESTORE_ALL
  621. .globl flush_patch_one
  622. /* We get these for debugging routines using __builtin_return_address() */
  623. dfw_kernel:
  624. flush_patch_one:
  625. FLUSH_ALL_KERNEL_WINDOWS
  626. /* Advance over the trap instruction. */
  627. ld [%sp + REGWIN_SZ + PT_NPC], %l1
  628. add %l1, 0x4, %l2
  629. st %l1, [%sp + REGWIN_SZ + PT_PC]
  630. st %l2, [%sp + REGWIN_SZ + PT_NPC]
  631. RESTORE_ALL
  632. /* The getcc software trap.  The user wants the condition codes from
  633.  * the %psr in register %g1.
  634.  */
  635. .align 4
  636. .globl getcc_trap_handler
  637. getcc_trap_handler:
  638. srl %l0, 20, %g1 ! give user
  639. and %g1, 0xf, %g1 ! only ICC bits in %psr
  640. jmp %l2 ! advance over trap instruction
  641. rett %l2 + 0x4 ! like this...
  642. /* The setcc software trap.  The user has condition codes in %g1
  643.  * that it would like placed in the %psr.  Be careful not to flip
  644.  * any unintentional bits!
  645.  */
  646. .align 4
  647. .globl setcc_trap_handler
  648. setcc_trap_handler:
  649. sll %g1, 0x14, %l4
  650. set PSR_ICC, %l5
  651. andn %l0, %l5, %l0 ! clear ICC bits in %psr
  652. and %l4, %l5, %l4 ! clear non-ICC bits in user value
  653. or %l4, %l0, %l4 ! or them in... mix mix mix
  654. wr %l4, 0x0, %psr ! set new %psr
  655. WRITE_PAUSE ! TI scumbags...
  656. jmp %l2 ! advance over trap instruction
  657. rett %l2 + 0x4 ! like this...
  658. .align 4
  659. .globl linux_trap_nmi_sun4c
  660. linux_trap_nmi_sun4c:
  661. SAVE_ALL
  662. /* Ugh, we need to clear the IRQ line.  This is now
  663.  * a very sun4c specific trap handler...
  664.  */
  665. sethi %hi(C_LABEL(interrupt_enable)), %l5
  666. ld [%l5 + %lo(C_LABEL(interrupt_enable))], %l5
  667. ldub [%l5], %l6
  668. andn %l6, INTS_ENAB, %l6
  669. stb %l6, [%l5]
  670. /* Now it is safe to re-enable traps without recursion. */
  671. or %l0, PSR_PIL, %l0
  672. wr %l0, PSR_ET, %psr
  673. WRITE_PAUSE
  674. /* Now call the c-code with the pt_regs frame ptr and the
  675.  * memory error registers as arguments.  The ordering chosen
  676.  * here is due to unlatching semantics.
  677.  */
  678. sethi %hi(AC_SYNC_ERR), %o0
  679. add %o0, 0x4, %o0
  680. lda [%o0] ASI_CONTROL, %o2 ! sync vaddr
  681. sub %o0, 0x4, %o0
  682. lda [%o0] ASI_CONTROL, %o1 ! sync error
  683. add %o0, 0xc, %o0
  684. lda [%o0] ASI_CONTROL, %o4 ! async vaddr
  685. sub %o0, 0x4, %o0
  686. lda [%o0] ASI_CONTROL, %o3 ! async error
  687. call C_LABEL(sparc_lvl15_nmi)
  688.  add %sp, REGWIN_SZ, %o0
  689. RESTORE_ALL
  690. .align 4
  691. .globl C_LABEL(invalid_segment_patch1_ff)
  692. .globl C_LABEL(invalid_segment_patch2_ff)
  693. C_LABEL(invalid_segment_patch1_ff): cmp %l4, 0xff
  694. C_LABEL(invalid_segment_patch2_ff): mov 0xff, %l3
  695. .align 4
  696. .globl C_LABEL(invalid_segment_patch1_1ff)
  697. .globl C_LABEL(invalid_segment_patch2_1ff)
  698. C_LABEL(invalid_segment_patch1_1ff): cmp %l4, 0x1ff
  699. C_LABEL(invalid_segment_patch2_1ff): mov 0x1ff, %l3
  700. .align 4
  701. .globl C_LABEL(num_context_patch1_16), C_LABEL(num_context_patch2_16)
  702. C_LABEL(num_context_patch1_16): mov 0x10, %l7
  703. C_LABEL(num_context_patch2_16): mov 0x10, %l7
  704. .align 4
  705. .globl C_LABEL(vac_linesize_patch_32)
  706. C_LABEL(vac_linesize_patch_32): subcc %l7, 32, %l7
  707. .align 4
  708. .globl C_LABEL(vac_hwflush_patch1_on), C_LABEL(vac_hwflush_patch2_on)
  709. /*
  710.  * Ugly, but we cant use hardware flushing on the sun4 and we'd require
  711.  * two instructions (Anton)
  712.  */
  713. #ifdef CONFIG_SUN4
  714. C_LABEL(vac_hwflush_patch1_on): nop
  715. #else
  716. C_LABEL(vac_hwflush_patch1_on): addcc %l7, -PAGE_SIZE, %l7
  717. #endif
  718. C_LABEL(vac_hwflush_patch2_on): sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG
  719. .globl C_LABEL(invalid_segment_patch1), C_LABEL(invalid_segment_patch2)
  720. .globl C_LABEL(num_context_patch1), C_LABEL(num_context_patch2)
  721. .globl C_LABEL(vac_linesize_patch), C_LABEL(vac_hwflush_patch1)
  722. .globl C_LABEL(vac_hwflush_patch2)
  723. .align 4
  724. .globl sun4c_fault
  725. ! %l0 = %psr
  726. ! %l1 = %pc
  727. ! %l2 = %npc
  728. ! %l3 = %wim
  729. ! %l7 = 1 for textfault
  730. ! We want error in %l5, vaddr in %l6
  731. sun4c_fault:
  732. #ifdef CONFIG_SUN4
  733. sethi %hi(C_LABEL(sun4c_memerr_reg)), %l4
  734. ld [%l4+%lo(C_LABEL(sun4c_memerr_reg))], %l4  ! memerr ctrl reg addr
  735. ld [%l4], %l6 ! memerr ctrl reg
  736. ld [%l4 + 4], %l5 ! memerr vaddr reg
  737. andcc %l6, 0x80, %g0 ! check for error type
  738. st %g0, [%l4 + 4] ! clear the error
  739. be 0f ! normal error
  740.  sethi %hi(AC_BUS_ERROR), %l4 ! bus err reg addr
  741. call C_LABEL(prom_halt) ! something weird happened
  742. ! what exactly did happen?
  743. ! what should we do here?
  744. 0: or %l4, %lo(AC_BUS_ERROR), %l4 ! bus err reg addr
  745. lduba [%l4] ASI_CONTROL, %l6 ! bus err reg
  746. cmp    %l7, 1 ! text fault?
  747. be 1f ! yes
  748.  nop
  749. ld     [%l1], %l4 ! load instruction that caused fault
  750. srl %l4, 21, %l4
  751. andcc %l4, 1, %g0 ! store instruction?
  752. be 1f ! no
  753.  sethi %hi(SUN4C_SYNC_BADWRITE), %l4 ! yep
  754. ! %lo(SUN4C_SYNC_BADWRITE) = 0
  755. or %l4, %l6, %l6 ! set write bit to emulate sun4c
  756. 1:
  757. #else
  758. sethi %hi(AC_SYNC_ERR), %l4
  759. add %l4, 0x4, %l6 ! AC_SYNC_VA in %l6
  760. lda [%l6] ASI_CONTROL, %l5 ! Address
  761. lda [%l4] ASI_CONTROL, %l6 ! Error, retained for a bit
  762. #endif
  763. andn %l5, 0xfff, %l5 ! Encode all info into l7
  764. srl %l6, 14, %l4
  765. and %l4, 2, %l4
  766. or %l5, %l4, %l4
  767. or %l4, %l7, %l7 ! l7 = [addr,write,txtfault]
  768. andcc %l0, PSR_PS, %g0
  769. be sun4c_fault_fromuser
  770.  andcc %l7, 1, %g0 ! Text fault?
  771. be 1f
  772.  sethi %hi(KERNBASE), %l4
  773. mov %l1, %l5 ! PC
  774. 1:
  775. cmp %l5, %l4
  776. blu sun4c_fault_fromuser
  777.  sethi %hi(~((1 << SUN4C_REAL_PGDIR_SHIFT) - 1)), %l4
  778. /* If the kernel references a bum kernel pointer, or a pte which
  779.  * points to a non existant page in ram, we will run this code
  780.  * _forever_ and lock up the machine!!!!! So we must check for
  781.  * this condition, the AC_SYNC_ERR bits are what we must examine.
  782.  * Also a parity error would make this happen as well.  So we just
  783.  * check that we are in fact servicing a tlb miss and not some
  784.  * other type of fault for the kernel.
  785.  */
  786. andcc %l6, 0x80, %g0
  787. be sun4c_fault_fromuser
  788.  and %l5, %l4, %l5
  789. /* Test for NULL pte_t * in vmalloc area. */
  790. sethi   %hi(VMALLOC_START), %l4
  791. cmp     %l5, %l4
  792. blu,a   C_LABEL(invalid_segment_patch1)
  793.  lduXa [%l5] ASI_SEGMAP, %l4
  794. sethi   %hi(C_LABEL(swapper_pg_dir)), %l4
  795. srl     %l5, SUN4C_PGDIR_SHIFT, %l6
  796. or      %l4, %lo(C_LABEL(swapper_pg_dir)), %l4
  797. sll     %l6, 2, %l6
  798. ld      [%l4 + %l6], %l4
  799. #ifdef CONFIG_SUN4
  800. sethi %hi(PAGE_MASK), %l6
  801. andcc %l4, %l6, %g0
  802. #else
  803. andcc   %l4, PAGE_MASK, %g0
  804. #endif
  805. be      sun4c_fault_fromuser
  806.  lduXa  [%l5] ASI_SEGMAP, %l4
  807. C_LABEL(invalid_segment_patch1):
  808. cmp %l4, 0x7f
  809. bne 1f
  810.  sethi %hi(C_LABEL(sun4c_kfree_ring)), %l4
  811. or %l4, %lo(C_LABEL(sun4c_kfree_ring)), %l4
  812. ld [%l4 + 0x18], %l3
  813. deccc %l3 ! do we have a free entry?
  814. bcs,a 2f ! no, unmap one.
  815.  sethi %hi(C_LABEL(sun4c_kernel_ring)), %l4
  816. st %l3, [%l4 + 0x18] ! sun4c_kfree_ring.num_entries--
  817. ld [%l4 + 0x00], %l6 ! entry = sun4c_kfree_ring.ringhd.next
  818. st %l5, [%l6 + 0x08] ! entry->vaddr = address
  819. ld [%l6 + 0x00], %l3 ! next = entry->next
  820. ld [%l6 + 0x04], %l7 ! entry->prev
  821. st %l7, [%l3 + 0x04] ! next->prev = entry->prev
  822. st %l3, [%l7 + 0x00] ! entry->prev->next = next
  823. sethi %hi(C_LABEL(sun4c_kernel_ring)), %l4
  824. or %l4, %lo(C_LABEL(sun4c_kernel_ring)), %l4
  825. ! head = &sun4c_kernel_ring.ringhd
  826. ld [%l4 + 0x00], %l7 ! head->next
  827. st %l4, [%l6 + 0x04] ! entry->prev = head
  828. st %l7, [%l6 + 0x00] ! entry->next = head->next
  829. st %l6, [%l7 + 0x04] ! head->next->prev = entry
  830. st %l6, [%l4 + 0x00] ! head->next = entry
  831. ld [%l4 + 0x18], %l3
  832. inc %l3 ! sun4c_kernel_ring.num_entries++
  833. st %l3, [%l4 + 0x18]
  834. b 4f
  835.  ld [%l6 + 0x08], %l5
  836. 2:
  837. or %l4, %lo(C_LABEL(sun4c_kernel_ring)), %l4
  838. ! head = &sun4c_kernel_ring.ringhd
  839. ld [%l4 + 0x04], %l6 ! entry = head->prev
  840. ld [%l6 + 0x08], %l3 ! tmp = entry->vaddr
  841. ! Flush segment from the cache.
  842. #ifdef CONFIG_SUN4
  843. sethi %hi((128 * 1024)), %l7
  844. #else
  845. sethi %hi((64 * 1024)), %l7
  846. #endif
  847. 9:
  848. C_LABEL(vac_hwflush_patch1):
  849. C_LABEL(vac_linesize_patch):
  850. subcc %l7, 16, %l7
  851. bne 9b
  852. C_LABEL(vac_hwflush_patch2):
  853.  sta %g0, [%l3 + %l7] ASI_FLUSHSEG
  854. st %l5, [%l6 + 0x08] ! entry->vaddr = address
  855. ld [%l6 + 0x00], %l5 ! next = entry->next
  856. ld [%l6 + 0x04], %l7 ! entry->prev
  857. st %l7, [%l5 + 0x04] ! next->prev = entry->prev
  858. st %l5, [%l7 + 0x00] ! entry->prev->next = next
  859. st %l4, [%l6 + 0x04] ! entry->prev = head
  860. ld [%l4 + 0x00], %l7 ! head->next
  861. st %l7, [%l6 + 0x00] ! entry->next = head->next
  862. st %l6, [%l7 + 0x04] ! head->next->prev = entry
  863. st %l6, [%l4 + 0x00] ! head->next = entry
  864. mov %l3, %l5 ! address = tmp
  865. 4:
  866. C_LABEL(num_context_patch1):
  867. mov 0x08, %l7
  868. ld [%l6 + 0x08], %l4
  869. ldub [%l6 + 0x0c], %l3
  870. or %l4, %l3, %l4 ! encode new vaddr/pseg into l4
  871. sethi %hi(AC_CONTEXT), %l3
  872. lduba [%l3] ASI_CONTROL, %l6
  873. /* Invalidate old mapping, instantiate new mapping,
  874.  * for each context.  Registers l6/l7 are live across
  875.  * this loop.
  876.  */
  877. 3: deccc %l7
  878. sethi %hi(AC_CONTEXT), %l3
  879. stba %l7, [%l3] ASI_CONTROL
  880. C_LABEL(invalid_segment_patch2):
  881. mov 0x7f, %l3
  882. stXa %l3, [%l5] ASI_SEGMAP
  883. andn %l4, 0x1ff, %l3
  884. bne 3b
  885.  stXa %l4, [%l3] ASI_SEGMAP
  886. sethi %hi(AC_CONTEXT), %l3
  887. stba %l6, [%l3] ASI_CONTROL
  888. andn %l4, 0x1ff, %l5
  889. 1:
  890. sethi %hi(VMALLOC_START), %l4
  891. cmp %l5, %l4
  892. bgeu 1f
  893.  mov 1 << (SUN4C_REAL_PGDIR_SHIFT - PAGE_SHIFT), %l7
  894. sethi %hi(KERNBASE), %l6
  895. sub %l5, %l6, %l4
  896. srl %l4, PAGE_SHIFT, %l4
  897. sethi %hi((SUN4C_PAGE_KERNEL & 0xf4000000)), %l3
  898. or %l3, %l4, %l3
  899. sethi %hi(PAGE_SIZE), %l4
  900. 2:
  901. sta %l3, [%l5] ASI_PTE
  902. deccc %l7
  903. inc %l3
  904. bne 2b
  905.  add %l5, %l4, %l5
  906. b 7f
  907.  sethi %hi(C_LABEL(sun4c_kernel_faults)), %l4
  908. 1:
  909. srl %l5, SUN4C_PGDIR_SHIFT, %l3
  910. sethi %hi(C_LABEL(swapper_pg_dir)), %l4
  911. or %l4, %lo(C_LABEL(swapper_pg_dir)), %l4
  912. sll %l3, 2, %l3
  913. ld [%l4 + %l3], %l4
  914. #ifndef CONFIG_SUN4
  915. and %l4, PAGE_MASK, %l4
  916. #else
  917. sethi %hi(PAGE_MASK), %l6
  918. and %l4, %l6, %l4
  919. #endif
  920. srl %l5, (PAGE_SHIFT - 2), %l6
  921. and %l6, ((SUN4C_PTRS_PER_PTE - 1) << 2), %l6
  922. add %l6, %l4, %l6
  923. sethi %hi(PAGE_SIZE), %l4
  924. 2:
  925. ld [%l6], %l3
  926. deccc %l7
  927. sta %l3, [%l5] ASI_PTE
  928. add %l6, 0x4, %l6
  929. bne 2b
  930.  add %l5, %l4, %l5
  931. sethi %hi(C_LABEL(sun4c_kernel_faults)), %l4
  932. 7:
  933. ld [%l4 + %lo(C_LABEL(sun4c_kernel_faults))], %l3
  934. inc %l3
  935. st %l3, [%l4 + %lo(C_LABEL(sun4c_kernel_faults))]
  936. /* Restore condition codes */
  937. wr %l0, 0x0, %psr
  938. WRITE_PAUSE
  939. jmp %l1
  940.  rett %l2
  941. sun4c_fault_fromuser:
  942. SAVE_ALL
  943.  nop
  944. mov %l7, %o1 ! Decode the info from %l7
  945. mov %l7, %o2
  946. and %o1, 1, %o1 ! arg2 = text_faultp
  947. mov %l7, %o3
  948. and %o2, 2, %o2 ! arg3 = writep
  949. andn %o3, 0xfff, %o3 ! arg4 = faulting address
  950. wr %l0, PSR_ET, %psr
  951. WRITE_PAUSE
  952. call C_LABEL(do_sun4c_fault)
  953.  add %sp, REGWIN_SZ, %o0 ! arg1 = pt_regs ptr
  954. RESTORE_ALL
  955. .align 4
  956. .globl C_LABEL(srmmu_fault)
  957. C_LABEL(srmmu_fault):
  958. mov 0x400, %l5
  959. mov 0x300, %l4
  960. lda [%l5] ASI_M_MMUREGS, %l6 ! read sfar first
  961. lda [%l4] ASI_M_MMUREGS, %l5 ! read sfsr last
  962. andn %l6, 0xfff, %l6
  963. srl %l5, 6, %l5 ! and encode all info into l7
  964. and %l5, 2, %l5
  965. or %l5, %l6, %l6
  966. or %l6, %l7, %l7 ! l7 = [addr,write,txtfault]
  967. SAVE_ALL
  968. mov %l7, %o1
  969. mov %l7, %o2
  970. and %o1, 1, %o1 ! arg2 = text_faultp
  971. mov %l7, %o3
  972. and %o2, 2, %o2 ! arg3 = writep
  973. andn %o3, 0xfff, %o3 ! arg4 = faulting address
  974. wr %l0, PSR_ET, %psr
  975. WRITE_PAUSE
  976. call C_LABEL(do_sparc_fault)
  977.  add %sp, REGWIN_SZ, %o0 ! arg1 = pt_regs ptr
  978. RESTORE_ALL
  979. #ifdef CONFIG_SUNOS_EMUL
  980. /* SunOS uses syscall zero as the 'indirect syscall' it looks
  981.  * like indir_syscall(scall_num, arg0, arg1, arg2...);  etc.
  982.  * This is complete brain damage.
  983.  */
  984. .globl C_LABEL(sunos_indir)
  985. C_LABEL(sunos_indir):
  986. mov %o7, %l4
  987. cmp %o0, NR_SYSCALLS
  988. blu,a 1f
  989.  sll %o0, 0x2, %o0
  990. sethi %hi(C_LABEL(sunos_nosys)), %l6
  991. b 2f
  992.  or %l6, %lo(C_LABEL(sunos_nosys)), %l6
  993. 1:
  994. set C_LABEL(sunos_sys_table), %l7
  995. ld [%l7 + %o0], %l6
  996. 2:
  997. mov %o1, %o0
  998. mov %o2, %o1
  999. mov %o3, %o2
  1000. mov %o4, %o3
  1001. mov %o5, %o4
  1002. call %l6
  1003.  mov %l4, %o7
  1004. #endif
  1005. .align 4
  1006. .globl C_LABEL(sys_nis_syscall)
  1007. C_LABEL(sys_nis_syscall):
  1008. mov %o7, %l5
  1009. add %sp, REGWIN_SZ, %o0 ! pt_regs *regs arg
  1010. call C_LABEL(c_sys_nis_syscall)
  1011.  mov %l5, %o7
  1012. .align 4
  1013. .globl C_LABEL(sys_ptrace)
  1014. C_LABEL(sys_ptrace):
  1015. call C_LABEL(do_ptrace)
  1016.  add %sp, REGWIN_SZ, %o0
  1017. ld [%curptr + AOFF_task_ptrace], %l5
  1018. andcc %l5, 0x02, %g0
  1019. be 1f
  1020.  nop
  1021. call C_LABEL(syscall_trace)
  1022.  nop
  1023. 1:
  1024. RESTORE_ALL
  1025. .align 4
  1026. .globl C_LABEL(sys_execve)
  1027. C_LABEL(sys_execve):
  1028. mov %o7, %l5
  1029. add %sp, REGWIN_SZ, %o0 ! pt_regs *regs arg
  1030. call C_LABEL(sparc_execve)
  1031.  mov %l5, %o7
  1032. .align 4
  1033. .globl C_LABEL(sys_pipe)
  1034. C_LABEL(sys_pipe):
  1035. mov %o7, %l5
  1036. add %sp, REGWIN_SZ, %o0 ! pt_regs *regs arg
  1037. call C_LABEL(sparc_pipe)
  1038.  mov %l5, %o7
  1039. .align 4
  1040. .globl C_LABEL(sys_sigaltstack)
  1041. C_LABEL(sys_sigaltstack):
  1042. mov %o7, %l5
  1043. mov %fp, %o2
  1044. call C_LABEL(do_sigaltstack)
  1045.  mov %l5, %o7
  1046. .align 4
  1047. .globl C_LABEL(sys_sigstack)
  1048. C_LABEL(sys_sigstack):
  1049. mov %o7, %l5
  1050. mov %fp, %o2
  1051. call C_LABEL(do_sys_sigstack)
  1052.  mov %l5, %o7
  1053. .align 4
  1054. .globl C_LABEL(sys_sigpause)
  1055. C_LABEL(sys_sigpause):
  1056. /* Note: %o0 already has correct value... */
  1057. call C_LABEL(do_sigpause)
  1058.  add %sp, REGWIN_SZ, %o1
  1059. ld [%curptr + AOFF_task_ptrace], %l5
  1060. andcc %l5, 0x02, %g0
  1061. be 1f
  1062.  nop
  1063. call C_LABEL(syscall_trace)
  1064.  nop
  1065. 1:
  1066. /* We are returning to a signal handler. */
  1067. RESTORE_ALL
  1068. .align 4
  1069. .globl C_LABEL(sys_sigsuspend)
  1070. C_LABEL(sys_sigsuspend):
  1071. call C_LABEL(do_sigsuspend)
  1072.  add %sp, REGWIN_SZ, %o0
  1073. ld [%curptr + AOFF_task_ptrace], %l5
  1074. andcc %l5, 0x02, %g0
  1075. be 1f
  1076.  nop
  1077. call C_LABEL(syscall_trace)
  1078.  nop
  1079. 1:
  1080. /* We are returning to a signal handler. */
  1081. RESTORE_ALL
  1082. .align 4
  1083. .globl C_LABEL(sys_rt_sigsuspend)
  1084. C_LABEL(sys_rt_sigsuspend):
  1085. /* Note: %o0, %o1 already have correct value... */
  1086. call C_LABEL(do_rt_sigsuspend)
  1087.  add %sp, REGWIN_SZ, %o2
  1088. ld [%curptr + AOFF_task_ptrace], %l5
  1089. andcc %l5, 0x02, %g0
  1090. be 1f
  1091.  nop
  1092. call C_LABEL(syscall_trace)
  1093.  nop
  1094. 1:
  1095. /* We are returning to a signal handler. */
  1096. RESTORE_ALL
  1097. .align 4
  1098. .globl C_LABEL(sys_sigreturn)
  1099. C_LABEL(sys_sigreturn):
  1100. call C_LABEL(do_sigreturn)
  1101.  add %sp, REGWIN_SZ, %o0
  1102. ld [%curptr + AOFF_task_ptrace], %l5
  1103. andcc %l5, 0x02, %g0
  1104. be 1f
  1105.  nop
  1106. call C_LABEL(syscall_trace)
  1107.  nop
  1108. 1:
  1109. /* We don't want to muck with user registers like a
  1110.  * normal syscall, just return.
  1111.  */
  1112. RESTORE_ALL
  1113. .align 4
  1114. .globl C_LABEL(sys_rt_sigreturn)
  1115. C_LABEL(sys_rt_sigreturn):
  1116. call C_LABEL(do_rt_sigreturn)
  1117.  add %sp, REGWIN_SZ, %o0
  1118. ld [%curptr + AOFF_task_ptrace], %l5
  1119. andcc %l5, 0x02, %g0
  1120. be 1f
  1121.  nop
  1122. call C_LABEL(syscall_trace)
  1123.  nop
  1124. 1:
  1125. /* We are returning to a signal handler. */
  1126. RESTORE_ALL
  1127. /* Now that we have a real sys_clone, sys_fork() is
  1128.  * implemented in terms of it.  Our _real_ implementation
  1129.  * of SunOS vfork() will use sys_vfork().
  1130.  *
  1131.  * XXX These three should be consolidated into mostly shared
  1132.  * XXX code just like on sparc64... -DaveM
  1133.  */
  1134. .align 4
  1135. .globl C_LABEL(sys_fork), flush_patch_two
  1136. C_LABEL(sys_fork):
  1137. mov %o7, %l5
  1138. flush_patch_two:
  1139. FLUSH_ALL_KERNEL_WINDOWS;
  1140. rd %psr, %g4
  1141. WRITE_PAUSE
  1142. mov SIGCHLD, %o0 ! arg0: clone flags
  1143. rd %wim, %g5
  1144. WRITE_PAUSE
  1145. mov %fp, %o1 ! arg1: usp
  1146. std %g4, [%curptr + AOFF_task_thread + AOFF_thread_fork_kpsr]
  1147. add %sp, REGWIN_SZ, %o2 ! arg2: pt_regs ptr
  1148. mov 0, %o3
  1149. call C_LABEL(do_fork)
  1150.  mov %l5, %o7
  1151. /* Whee, kernel threads! */
  1152. .globl C_LABEL(sys_clone), flush_patch_three
  1153. C_LABEL(sys_clone):
  1154. mov %o7, %l5
  1155. flush_patch_three:
  1156. FLUSH_ALL_KERNEL_WINDOWS;
  1157. rd %psr, %g4
  1158. WRITE_PAUSE
  1159. /* arg0,1: flags,usp  -- loaded already */
  1160. cmp %o1, 0x0 ! Is new_usp NULL?
  1161. rd %wim, %g5
  1162. WRITE_PAUSE
  1163. be,a 1f
  1164.  mov %fp, %o1 ! yes, use callers usp
  1165. andn %o1, 7, %o1 ! no, align to 8 bytes
  1166. 1:
  1167. std %g4, [%curptr + AOFF_task_thread + AOFF_thread_fork_kpsr]
  1168. add %sp, REGWIN_SZ, %o2 ! arg2: pt_regs ptr
  1169. mov 0, %o3
  1170. call C_LABEL(do_fork)
  1171.  mov %l5, %o7
  1172. /* Whee, real vfork! */
  1173. .globl C_LABEL(sys_vfork), flush_patch_four
  1174. C_LABEL(sys_vfork):
  1175. flush_patch_four:
  1176. FLUSH_ALL_KERNEL_WINDOWS;
  1177. rd %psr, %g4
  1178. WRITE_PAUSE
  1179. rd %wim, %g5
  1180. WRITE_PAUSE
  1181. std %g4, [%curptr + AOFF_task_thread + AOFF_thread_fork_kpsr]
  1182. sethi %hi(0x4000 | 0x0100 | SIGCHLD), %o0
  1183. mov %fp, %o1
  1184. or %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
  1185. sethi %hi(C_LABEL(do_fork)), %l1
  1186. mov 0, %o3
  1187. jmpl %l1 + %lo(C_LABEL(do_fork)), %g0
  1188.  add %sp, REGWIN_SZ, %o2
  1189.         .align  4
  1190. linux_sparc_ni_syscall:
  1191. sethi   %hi(C_LABEL(sys_ni_syscall)), %l7
  1192. b       syscall_is_too_hard
  1193.  or     %l7, %lo(C_LABEL(sys_ni_syscall)), %l7
  1194. linux_fast_syscall:
  1195. andn %l7, 3, %l7
  1196. mov %i0, %o0
  1197. mov %i1, %o1
  1198. mov  %i2, %o2
  1199. jmpl %l7 + %g0, %g0
  1200.  mov %i3, %o3
  1201. linux_syscall_trace:
  1202. call C_LABEL(syscall_trace)
  1203.  nop
  1204. mov %i0, %o0
  1205. mov %i1, %o1
  1206. mov %i2, %o2
  1207. mov %i3, %o3
  1208. b 2f
  1209.  mov %i4, %o4
  1210. .globl C_LABEL(ret_from_fork)
  1211. C_LABEL(ret_from_fork):
  1212. call schedule_tail
  1213.  mov %g3, %o0
  1214. b C_LABEL(ret_sys_call)
  1215.  ld [%sp + REGWIN_SZ + PT_I0], %o0
  1216. /* Linux native and SunOS system calls enter here... */
  1217. .align 4
  1218. .globl linux_sparc_syscall
  1219. linux_sparc_syscall:
  1220. /* Direct access to user regs, must faster. */
  1221. cmp %g1, NR_SYSCALLS
  1222. bgeu linux_sparc_ni_syscall
  1223.  sll %g1, 2, %l4
  1224. ld [%l7 + %l4], %l7
  1225. andcc %l7, 1, %g0
  1226. bne linux_fast_syscall
  1227.  /* Just do first insn from SAVE_ALL in the delay slot */
  1228. .globl syscall_is_too_hard
  1229. syscall_is_too_hard:
  1230. SAVE_ALL_HEAD
  1231.  rd %wim, %l3
  1232. wr %l0, PSR_ET, %psr
  1233. mov %i0, %o0
  1234. mov %i1, %o1
  1235. mov %i2, %o2
  1236. ld [%curptr + AOFF_task_ptrace], %l5
  1237. mov %i3, %o3
  1238. andcc %l5, 0x02, %g0
  1239. mov %i4, %o4
  1240. bne linux_syscall_trace
  1241.  mov %i0, %l5
  1242. 2:
  1243. call %l7
  1244.  mov %i5, %o5
  1245. st %o0, [%sp + REGWIN_SZ + PT_I0]
  1246. .globl C_LABEL(ret_sys_call)
  1247. C_LABEL(ret_sys_call):
  1248. ld [%curptr + AOFF_task_ptrace], %l6
  1249. cmp %o0, -ENOIOCTLCMD
  1250. ld [%sp + REGWIN_SZ + PT_PSR], %g3
  1251. set PSR_C, %g2
  1252. bgeu 1f
  1253.  andcc %l6, 0x02, %l6
  1254. /* System call success, clear Carry condition code. */
  1255. andn %g3, %g2, %g3
  1256. clr %l6
  1257. st %g3, [%sp + REGWIN_SZ + PT_PSR]
  1258. bne linux_syscall_trace2
  1259.  ld [%sp + REGWIN_SZ + PT_NPC], %l1 /* pc = npc */
  1260. add %l1, 0x4, %l2 /* npc = npc+4 */
  1261. st %l1, [%sp + REGWIN_SZ + PT_PC]
  1262. b ret_trap_entry
  1263.  st %l2, [%sp + REGWIN_SZ + PT_NPC]
  1264. 1:
  1265. /* System call failure, set Carry condition code.
  1266.  * Also, get abs(errno) to return to the process.
  1267.  */
  1268. sub %g0, %o0, %o0
  1269. or %g3, %g2, %g3
  1270. st %o0, [%sp + REGWIN_SZ + PT_I0]
  1271. mov 1, %l6
  1272. st %g3, [%sp + REGWIN_SZ + PT_PSR]
  1273. bne linux_syscall_trace2
  1274.  ld [%sp + REGWIN_SZ + PT_NPC], %l1 /* pc = npc */
  1275. add %l1, 0x4, %l2 /* npc = npc+4 */
  1276. st %l1, [%sp + REGWIN_SZ + PT_PC]
  1277. b ret_trap_entry
  1278.  st %l2, [%sp + REGWIN_SZ + PT_NPC]
  1279. linux_syscall_trace2:
  1280. call C_LABEL(syscall_trace)
  1281.  add %l1, 0x4, %l2 /* npc = npc+4 */
  1282. st %l1, [%sp + REGWIN_SZ + PT_PC]
  1283. b ret_trap_entry
  1284.  st %l2, [%sp + REGWIN_SZ + PT_NPC]
  1285. /*
  1286.  * Solaris system calls and indirect system calls enter here.
  1287.          *
  1288.  * I have named the solaris indirect syscalls like that because
  1289.  * it seems like Solaris has some fast path syscalls that can
  1290.  * be handled as indirect system calls. - mig
  1291.  */
  1292. linux_syscall_for_solaris:
  1293. sethi %hi(sys_call_table), %l7
  1294. b linux_sparc_syscall
  1295.  or %l7, %lo(sys_call_table), %l7
  1296. .align 4
  1297. .globl solaris_syscall
  1298. solaris_syscall:
  1299. cmp %g1,59
  1300. be linux_syscall_for_solaris
  1301.  cmp %g1,2
  1302. be linux_syscall_for_solaris
  1303.  cmp    %g1,42
  1304. be      linux_syscall_for_solaris
  1305.  cmp %g1,119
  1306. be,a linux_syscall_for_solaris
  1307.  mov 2, %g1
  1308. 1:
  1309. SAVE_ALL_HEAD
  1310.  rd %wim, %l3
  1311. wr %l0, PSR_ET, %psr
  1312. nop
  1313. nop
  1314. mov %i0, %l5
  1315. call C_LABEL(do_solaris_syscall)
  1316.  add %sp, REGWIN_SZ, %o0
  1317. st %o0, [%sp + REGWIN_SZ + PT_I0]
  1318. set PSR_C, %g2
  1319. cmp %o0, -ENOIOCTLCMD
  1320. bgeu 1f
  1321.  ld [%sp + REGWIN_SZ + PT_PSR], %g3
  1322. /* System call success, clear Carry condition code. */
  1323. andn %g3, %g2, %g3
  1324. clr %l6
  1325. b 2f
  1326.  st %g3, [%sp + REGWIN_SZ + PT_PSR]
  1327. 1:
  1328. /* System call failure, set Carry condition code.
  1329.  * Also, get abs(errno) to return to the process.
  1330.  */
  1331. sub %g0, %o0, %o0
  1332. mov 1, %l6
  1333. st %o0, [%sp + REGWIN_SZ + PT_I0]
  1334. or %g3, %g2, %g3
  1335. st %g3, [%sp + REGWIN_SZ + PT_PSR]
  1336. /* Advance the pc and npc over the trap instruction.
  1337.  * If the npc is unaligned (has a 1 in the lower byte), it means
  1338.  * the kernel does not want us to play magic (ie, skipping over
  1339.  * traps).  Mainly when the Solaris code wants to set some PC and
  1340.  * nPC (setcontext).
  1341.  */
  1342. 2:
  1343. ld [%sp + REGWIN_SZ + PT_NPC], %l1 /* pc  = npc   */
  1344. andcc %l1, 1, %g0
  1345. bne 1f
  1346.  add %l1, 0x4, %l2 /* npc = npc+4 */
  1347. st %l1, [%sp + REGWIN_SZ + PT_PC]
  1348. b ret_trap_entry
  1349.  st %l2, [%sp + REGWIN_SZ + PT_NPC]
  1350. /* kernel knows what it is doing, fixup npc and continue */
  1351. 1:
  1352. sub %l1, 1, %l1
  1353.   b ret_trap_entry
  1354.  st %l1, [%sp + REGWIN_SZ + PT_NPC]
  1355. #ifndef CONFIG_SUNOS_EMUL
  1356. .align 4
  1357. .globl sunos_syscall
  1358. sunos_syscall:
  1359. SAVE_ALL_HEAD
  1360.  rd %wim, %l3
  1361. wr %l0, PSR_ET, %psr
  1362. nop
  1363. nop
  1364. mov %i0, %l5
  1365. call C_LABEL(do_sunos_syscall)
  1366.  add %sp, REGWIN_SZ, %o0
  1367. #endif
  1368. /* {net, open}bsd system calls enter here... */
  1369. .align 4
  1370. .globl bsd_syscall
  1371. bsd_syscall:
  1372. /* Direct access to user regs, must faster. */
  1373. cmp %g1, NR_SYSCALLS
  1374. blu,a 1f
  1375.  sll %g1, 2, %l4
  1376. set C_LABEL(sys_ni_syscall), %l7
  1377. b bsd_is_too_hard
  1378.  nop
  1379. 1:
  1380. ld [%l7 + %l4], %l7
  1381. .globl bsd_is_too_hard
  1382. bsd_is_too_hard:
  1383. rd %wim, %l3
  1384. SAVE_ALL
  1385. wr %l0, PSR_ET, %psr
  1386. WRITE_PAUSE
  1387. 2:
  1388. mov %i0, %o0
  1389. mov %i1, %o1
  1390. mov %i2, %o2
  1391. mov %i0, %l5
  1392. mov %i3, %o3
  1393. mov %i4, %o4
  1394. call %l7
  1395.  mov %i5, %o5
  1396. st %o0, [%sp + REGWIN_SZ + PT_I0]
  1397. set PSR_C, %g2
  1398. cmp %o0, -ENOIOCTLCMD
  1399. bgeu 1f
  1400.  ld [%sp + REGWIN_SZ + PT_PSR], %g3
  1401. /* System call success, clear Carry condition code. */
  1402. andn %g3, %g2, %g3
  1403. clr %l6
  1404. b 2f
  1405.  st %g3, [%sp + REGWIN_SZ + PT_PSR]
  1406. 1:
  1407. /* System call failure, set Carry condition code.
  1408.  * Also, get abs(errno) to return to the process.
  1409.  */
  1410. sub %g0, %o0, %o0
  1411. #if 0 /* XXX todo XXX */
  1412. sethi %hi(C_LABEL(bsd_xlatb_rorl), %o3
  1413. or %o3, %lo(C_LABEL(bsd_xlatb_rorl)), %o3
  1414. sll %o0, 2, %o0
  1415. ld [%o3 + %o0], %o0
  1416. #endif
  1417. mov 1, %l6
  1418. st %o0, [%sp + REGWIN_SZ + PT_I0]
  1419. or %g3, %g2, %g3
  1420. st %g3, [%sp + REGWIN_SZ + PT_PSR]
  1421. /* Advance the pc and npc over the trap instruction. */
  1422. 2:
  1423. ld [%sp + REGWIN_SZ + PT_NPC], %l1 /* pc  = npc   */
  1424. add %l1, 0x4, %l2 /* npc = npc+4 */
  1425. st %l1, [%sp + REGWIN_SZ + PT_PC]
  1426. b ret_trap_entry
  1427.  st %l2, [%sp + REGWIN_SZ + PT_NPC]
  1428. /* Saving and restoring the FPU state is best done from lowlevel code.
  1429.  *
  1430.  * void fpsave(unsigned long *fpregs, unsigned long *fsr,
  1431.  *             void *fpqueue, unsigned long *fpqdepth)
  1432.  */
  1433. .globl C_LABEL(fpsave)
  1434. C_LABEL(fpsave):
  1435. st %fsr, [%o1] ! this can trap on us if fpu is in bogon state
  1436. ld [%o1], %g1
  1437. set 0x2000, %g4
  1438. andcc %g1, %g4, %g0
  1439. be 2f
  1440.  mov 0, %g2
  1441. /* We have an fpqueue to save. */
  1442. 1:
  1443. std %fq, [%o2]
  1444. fpsave_magic:
  1445. st %fsr, [%o1]
  1446. ld [%o1], %g3
  1447. andcc %g3, %g4, %g0
  1448. add %g2, 1, %g2
  1449. bne 1b
  1450.  add %o2, 8, %o2
  1451. 2:
  1452. st %g2, [%o3]
  1453. std %f0, [%o0 + 0x00]
  1454. std %f2, [%o0 + 0x08]
  1455. std %f4, [%o0 + 0x10]
  1456. std %f6, [%o0 + 0x18]
  1457. std %f8, [%o0 + 0x20]
  1458. std %f10, [%o0 + 0x28]
  1459. std %f12, [%o0 + 0x30]
  1460. std %f14, [%o0 + 0x38]
  1461. std %f16, [%o0 + 0x40]
  1462. std %f18, [%o0 + 0x48]
  1463. std %f20, [%o0 + 0x50]
  1464. std %f22, [%o0 + 0x58]
  1465. std %f24, [%o0 + 0x60]
  1466. std %f26, [%o0 + 0x68]
  1467. std %f28, [%o0 + 0x70]
  1468. retl
  1469.  std %f30, [%o0 + 0x78]
  1470. /* Thanks for Theo Deraadt and the authors of the Sprite/netbsd/openbsd
  1471.  * code for pointing out this possible deadlock, while we save state
  1472.  * above we could trap on the fsr store so our low level fpu trap
  1473.  * code has to know how to deal with this.
  1474.  */
  1475. fpsave_catch:
  1476. b fpsave_magic + 4
  1477.  st %fsr, [%o1]
  1478. fpsave_catch2:
  1479. b C_LABEL(fpsave) + 4
  1480.  st %fsr, [%o1]
  1481. /* void fpload(unsigned long *fpregs, unsigned long *fsr); */
  1482. .globl C_LABEL(fpload)
  1483. C_LABEL(fpload):
  1484. ldd [%o0 + 0x00], %f0
  1485. ldd [%o0 + 0x08], %f2
  1486. ldd [%o0 + 0x10], %f4
  1487. ldd [%o0 + 0x18], %f6
  1488. ldd [%o0 + 0x20], %f8
  1489. ldd [%o0 + 0x28], %f10
  1490. ldd [%o0 + 0x30], %f12
  1491. ldd [%o0 + 0x38], %f14
  1492. ldd [%o0 + 0x40], %f16
  1493. ldd [%o0 + 0x48], %f18
  1494. ldd [%o0 + 0x50], %f20
  1495. ldd [%o0 + 0x58], %f22
  1496. ldd [%o0 + 0x60], %f24
  1497. ldd [%o0 + 0x68], %f26
  1498. ldd [%o0 + 0x70], %f28
  1499. ldd [%o0 + 0x78], %f30
  1500. ld [%o1], %fsr
  1501. retl
  1502.  nop
  1503. .globl C_LABEL(udelay)
  1504. C_LABEL(udelay):
  1505. save %sp, -REGWIN_SZ, %sp
  1506. mov %i0, %o0
  1507. sethi %hi(0x10c6), %o1
  1508. call .umul
  1509.  or %o1, %lo(0x10c6), %o1
  1510. #ifndef CONFIG_SMP
  1511. sethi %hi(C_LABEL(loops_per_jiffy)), %o3
  1512. call .umul
  1513.  ld [%o3 + %lo(C_LABEL(loops_per_jiffy))], %o1
  1514. #else
  1515. GET_PROCESSOR_OFFSET(o4, o2)
  1516. set C_LABEL(cpu_data), %o3
  1517. call .umul
  1518.  ld [%o3 + %o4], %o1
  1519. #endif
  1520. call .umul
  1521.  mov 100, %o0
  1522. cmp %o0, 0x0
  1523. 1:
  1524. bne 1b
  1525.  subcc %o0, 1, %o0
  1526. ret
  1527. restore
  1528. /* Handle a software breakpoint */
  1529. /* We have to inform parent that child has stopped */
  1530. .align 4
  1531. .globl breakpoint_trap
  1532. breakpoint_trap:
  1533. rd %wim,%l3
  1534. SAVE_ALL
  1535. wr  %l0, PSR_ET, %psr
  1536. WRITE_PAUSE
  1537. st %i0, [%sp + REGWIN_SZ + PT_G0] ! for restarting syscalls
  1538. call C_LABEL(sparc_breakpoint)
  1539.  add %sp, REGWIN_SZ, %o0
  1540. RESTORE_ALL
  1541. .align 4
  1542. .globl C_LABEL(__handle_exception), flush_patch_exception
  1543. C_LABEL(__handle_exception):
  1544. flush_patch_exception:
  1545. FLUSH_ALL_KERNEL_WINDOWS;
  1546. ldd [%o0], %o6
  1547. jmpl %o7 + 0xc, %g0 ! see asm-sparc/processor.h
  1548.  mov 1, %g1 ! signal EFAULT condition
  1549. .align 4
  1550. .globl C_LABEL(kill_user_windows), kuw_patch1_7win
  1551. .globl kuw_patch1
  1552. kuw_patch1_7win: sll %o3, 6, %o3
  1553. /* No matter how much overhead this routine has in the worst
  1554.  * case scenerio, it is several times better than taking the
  1555.  * traps with the old method of just doing flush_user_windows().
  1556.  */
  1557. C_LABEL(kill_user_windows):
  1558. ld [%g6 + AOFF_task_thread + AOFF_thread_uwinmask], %o0 ! get current umask
  1559. orcc %g0, %o0, %g0 ! if no bits set, we are done
  1560. be 3f ! nothing to do
  1561.  rd %psr, %o5 ! must clear interrupts
  1562. or %o5, PSR_PIL, %o4 ! or else that could change
  1563. wr %o4, 0x0, %psr ! the uwinmask state
  1564. WRITE_PAUSE ! burn them cycles
  1565. 1:
  1566. ld [%g6 + AOFF_task_thread + AOFF_thread_uwinmask], %o0 ! get consistant state
  1567. orcc %g0, %o0, %g0 ! did an interrupt come in?
  1568. be 4f ! yep, we are done
  1569.  rd %wim, %o3 ! get current wim
  1570. srl %o3, 1, %o4 ! simulate a save
  1571. kuw_patch1:
  1572. sll %o3, 7, %o3 ! compute next wim
  1573. or %o4, %o3, %o3 ! result
  1574. andncc %o0, %o3, %o0 ! clean this bit in umask
  1575. bne kuw_patch1 ! not done yet
  1576.  srl %o3, 1, %o4 ! begin another save simulation
  1577. wr %o3, 0x0, %wim ! set the new wim
  1578. st %g0, [%g6 + AOFF_task_thread + AOFF_thread_uwinmask] ! clear uwinmask
  1579. 4:
  1580. wr %o5, 0x0, %psr ! re-enable interrupts
  1581. WRITE_PAUSE ! burn baby burn
  1582. 3:
  1583. retl ! return
  1584.  st %g0, [%g6 + AOFF_task_thread + AOFF_thread_w_saved] ! no windows saved
  1585. .align 4
  1586. .globl C_LABEL(restore_current)
  1587. C_LABEL(restore_current):
  1588. LOAD_CURRENT(g6, o0)
  1589. retl
  1590.  nop
  1591. #ifdef CONFIG_PCI
  1592. #include <asm/pcic.h>
  1593. .align 4
  1594. .globl linux_trap_ipi15_pcic
  1595. linux_trap_ipi15_pcic:
  1596. rd %wim, %l3
  1597. SAVE_ALL
  1598. /*
  1599.  * First deactivate NMI
  1600.  * or we cannot drop ET, cannot get window spill traps.
  1601.  * The busy loop is necessary because the PIO error
  1602.  * sometimes does not go away quickly and we trap again.
  1603.  */
  1604. sethi %hi(C_LABEL(pcic_regs)), %o1
  1605. ld [%o1 + %lo(C_LABEL(pcic_regs))], %o2
  1606. ! Get pending status for printouts later.
  1607. ld [%o2 + PCI_SYS_INT_PENDING], %o0
  1608. mov PCI_SYS_INT_PENDING_CLEAR_ALL, %o1
  1609. stb %o1, [%o2 + PCI_SYS_INT_PENDING_CLEAR]
  1610. 1:
  1611. ld [%o2 + PCI_SYS_INT_PENDING], %o1
  1612. andcc %o1, ((PCI_SYS_INT_PENDING_PIO|PCI_SYS_INT_PENDING_PCI)>>24), %g0
  1613. bne 1b
  1614.  nop
  1615. or %l0, PSR_PIL, %l4
  1616. wr %l4, 0x0, %psr
  1617. WRITE_PAUSE
  1618. wr %l4, PSR_ET, %psr
  1619. WRITE_PAUSE
  1620. call C_LABEL(pcic_nmi)
  1621.  add %sp, REGWIN_SZ, %o1 ! struct pt_regs *regs
  1622. RESTORE_ALL
  1623. .globl C_LABEL(pcic_nmi_trap_patch)
  1624. C_LABEL(pcic_nmi_trap_patch):
  1625. sethi %hi(linux_trap_ipi15_pcic), %l3
  1626. jmpl %l3 + %lo(linux_trap_ipi15_pcic), %g0
  1627.  rd %psr, %l0
  1628. .word 0
  1629. #endif /* CONFIG_PCI */
  1630. /* End of entry.S */