tlbex-r3k.S
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * TLB exception handling code for R2000/R3000.
  3.  *
  4.  * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
  5.  *
  6.  * Multi-CPU abstraction reworking:
  7.  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  8.  *
  9.  * Further modifications to make this work:
  10.  * Copyright (c) 1998 Harald Koerfgen
  11.  * Copyright (c) 1998, 1999 Gleb Raiko & Vladimir Roganov
  12.  * Copyright (c) 2001 Ralf Baechle
  13.  * Copyright (c) 2001 MIPS Technologies, Inc.
  14.  */
  15. #include <linux/init.h>
  16. #include <asm/asm.h>
  17. #include <asm/current.h>
  18. #include <asm/cachectl.h>
  19. #include <asm/fpregdef.h>
  20. #include <asm/mipsregs.h>
  21. #include <asm/page.h>
  22. #include <asm/pgtable-bits.h>
  23. #include <asm/processor.h>
  24. #include <asm/regdef.h>
  25. #include <asm/stackframe.h>
  26. #define TLB_OPTIMIZE /* If you are paranoid, disable this. */
  27. .text
  28. .set mips1
  29. .set noreorder
  30. __INIT
  31. /* TLB refill, R[23]00 version */
  32. LEAF(except_vec0_r2300)
  33. .set noat
  34. .set mips1
  35. mfc0 k0, CP0_BADVADDR
  36. lw k1, pgd_current # get pgd pointer
  37. srl k0, k0, 22
  38. sll k0, k0, 2
  39. addu k1, k1, k0
  40. mfc0 k0, CP0_CONTEXT
  41. lw k1, (k1)
  42. and k0, k0, 0xffc
  43. addu k1, k1, k0
  44. lw k0, (k1)
  45. nop
  46. mtc0 k0, CP0_ENTRYLO0
  47. mfc0 k1, CP0_EPC
  48. tlbwr
  49. jr k1
  50. rfe
  51. END(except_vec0_r2300)
  52. __FINIT
  53. /* ABUSE of CPP macros 101. */
  54. /* After this macro runs, the pte faulted on is
  55.  * in register PTE, a ptr into the table in which
  56.  * the pte belongs is in PTR.
  57.  */
  58. #define LOAD_PTE(pte, ptr) 
  59. mfc0 pte, CP0_BADVADDR; 
  60. lw ptr, pgd_current; 
  61. srl pte, pte, 22; 
  62. sll pte, pte, 2; 
  63. addu ptr, ptr, pte; 
  64. mfc0 pte, CP0_CONTEXT; 
  65. lw ptr, (ptr); 
  66. andi pte, pte, 0xffc; 
  67. addu ptr, ptr, pte; 
  68. lw pte, (ptr); 
  69. nop;
  70. /* This places the even/odd pte pair in the page
  71.  * table at PTR into ENTRYLO0 and ENTRYLO1 using
  72.  * TMP as a scratch register.
  73.  */
  74. #define PTE_RELOAD(ptr) 
  75. lw ptr, (ptr) ; 
  76. nop ; 
  77. mtc0 ptr, CP0_ENTRYLO0; 
  78. nop;
  79. #define DO_FAULT(write) 
  80. .set noat; 
  81. .set macro; 
  82. SAVE_ALL; 
  83. mfc0 a2, CP0_BADVADDR; 
  84. KMODE; 
  85. .set at; 
  86. move a0, sp; 
  87. jal do_page_fault; 
  88.  li a1, write; 
  89. j ret_from_exception; 
  90.  nop; 
  91. .set noat; 
  92. .set nomacro;
  93. /* Check is PTE is present, if not then jump to LABEL.
  94.  * PTR points to the page table where this PTE is located,
  95.  * when the macro is done executing PTE will be restored
  96.  * with it's original value.
  97.  */
  98. #define PTE_PRESENT(pte, ptr, label) 
  99. andi pte, pte, (_PAGE_PRESENT | _PAGE_READ); 
  100. xori pte, pte, (_PAGE_PRESENT | _PAGE_READ); 
  101. bnez pte, label; 
  102. .set push;       
  103. .set reorder;    
  104.  lw pte, (ptr); 
  105. .set pop;
  106. /* Make PTE valid, store result in PTR. */
  107. #define PTE_MAKEVALID(pte, ptr) 
  108. ori pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); 
  109. sw pte, (ptr);
  110. /* Check if PTE can be written to, if not branch to LABEL.
  111.  * Regardless restore PTE with value from PTR when done.
  112.  */
  113. #define PTE_WRITABLE(pte, ptr, label) 
  114. andi pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); 
  115. xori pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); 
  116. bnez pte, label; 
  117. .set    push;       
  118. .set    reorder;    
  119. lw      pte, (ptr); 
  120. .set    pop;
  121. /* Make PTE writable, update software status bits as well,
  122.  * then store at PTR.
  123.  */
  124. #define PTE_MAKEWRITE(pte, ptr) 
  125. ori pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | 
  126.    _PAGE_VALID | _PAGE_DIRTY); 
  127. sw pte, (ptr);
  128. /*
  129.  * The index register may have the probe fail bit set,
  130.  * because we would trap on access kseg2, i.e. without refill.
  131.  */
  132. #define TLB_WRITE(reg) 
  133. mfc0 reg, CP0_INDEX; 
  134. nop; 
  135. bltz    reg, 1f; 
  136.  nop; 
  137. tlbwi; 
  138. j 2f; 
  139.  nop; 
  140. 1: tlbwr; 
  141. 2:
  142. #define RET(reg) 
  143. mfc0 reg, CP0_EPC; 
  144. nop; 
  145. jr reg; 
  146.  rfe
  147. .set noreorder
  148. .align 5
  149. NESTED(handle_tlbl, PT_SIZE, sp)
  150. .set noat
  151. #ifdef TLB_OPTIMIZE
  152. /* Test present bit in entry. */
  153. LOAD_PTE(k0, k1)
  154.         tlbp
  155.         PTE_PRESENT(k0, k1, nopage_tlbl)
  156.         PTE_MAKEVALID(k0, k1)
  157.         PTE_RELOAD(k1)
  158. TLB_WRITE(k0)
  159. RET(k0)
  160. nopage_tlbl:
  161. #endif
  162. DO_FAULT(0)
  163. END(handle_tlbl)
  164. NESTED(handle_tlbs, PT_SIZE, sp)
  165. .set noat
  166. #ifdef TLB_OPTIMIZE
  167. LOAD_PTE(k0, k1)
  168. tlbp                            # find faulting entry
  169. PTE_WRITABLE(k0, k1, nopage_tlbs)
  170. PTE_MAKEWRITE(k0, k1)
  171. PTE_RELOAD(k1)
  172. TLB_WRITE(k0)
  173. RET(k0)
  174. nopage_tlbs:
  175. #endif
  176. DO_FAULT(1)
  177. END(handle_tlbs)
  178. .align 5
  179. NESTED(handle_mod, PT_SIZE, sp)
  180. .set noat
  181. #ifdef TLB_OPTIMIZE
  182. LOAD_PTE(k0, k1)
  183. tlbp # find faulting entry
  184. andi k0, k0, _PAGE_WRITE
  185. beqz k0, nowrite_mod
  186. .set push
  187. .set    reorder
  188. lw k0, (k1)
  189. .set    pop
  190. /* Present and writable bits set, set accessed and dirty bits. */
  191. PTE_MAKEWRITE(k0, k1)
  192. /* Now reload the entry into the tlb. */
  193. PTE_RELOAD(k1)
  194. tlbwi
  195. RET(k0)
  196. #endif
  197. nowrite_mod:
  198. DO_FAULT(1)
  199. END(handle_mod)