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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: r4k_misc.S,v 1.8 1999/10/09 00:00:58 ralf Exp $
  2.  *
  3.  * r4k_misc.S: Misc. exception handling code for r4k.
  4.  *
  5.  * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
  6.  *
  7.  * Multi-cpu abstraction and reworking:
  8.  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  9.  */
  10. /**************************************************************************
  11.  *  14 Nov, 2000.
  12.  *  Made support for MIPS32 CPUs.
  13.  *
  14.  *  Carsten Langgaard, carstenl@mips.com
  15.  *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
  16.  *************************************************************************/
  17. #include <asm/asm.h>
  18. #include <asm/current.h>
  19. #include <asm/offset.h>
  20. #include <asm/bootinfo.h>
  21. #include <asm/cachectl.h>
  22. #include <asm/fpregdef.h>
  23. #include <asm/mipsregs.h>
  24. #include <asm/page.h>
  25. #include <asm/pgtable.h>
  26. #include <asm/processor.h>
  27. #include <asm/regdef.h>
  28. #include <asm/stackframe.h>
  29. #undef NOTLB_OPTIMIZE /* If you are paranoid, define this. */
  30. /* ABUSE of CPP macros 101. */
  31. /* After this macro runs, the pte faulted on is
  32.  * in register PTE, a ptr into the table in which
  33.  * the pte belongs is in PTR.
  34.  */
  35. #ifdef CONFIG_SMP
  36. #define GET_PGD(scratch, ptr)        
  37. mfc0    ptr, CP0_CONTEXT;    
  38. la      scratch, current_pgd;
  39. srl     ptr, 23;             
  40. sll     ptr, 2;              
  41. addu    ptr, scratch, ptr;   
  42. lw      ptr, (ptr);          
  43. #else
  44. #define GET_PGD(scratch, ptr)    
  45. lw ptr, current_pgd;
  46. #endif
  47. #define LOAD_PTE(pte, ptr) 
  48. GET_PGD(pte, ptr)          
  49. mfc0 pte, CP0_BADVADDR; 
  50. srl pte, pte, 22; 
  51. sll pte, pte, 2; 
  52. addu ptr, ptr, pte; 
  53. mfc0 pte, CP0_BADVADDR; 
  54. lw ptr, (ptr); 
  55. srl pte, pte, 10; 
  56. and pte, pte, 0xffc; 
  57. addu ptr, ptr, pte; 
  58. lw pte, (ptr);
  59. /* This places the even/odd pte pair in the page
  60.  * table at PTR into ENTRYLO0 and ENTRYLO1 using
  61.  * TMP as a scratch register.
  62.  */
  63. #define PTE_RELOAD(ptr, tmp) 
  64. ori ptr, ptr, 0x4; 
  65. xori ptr, ptr, 0x4; 
  66. lw tmp, 4(ptr); 
  67. lw ptr, 0(ptr); 
  68. srl tmp, tmp, 6; 
  69. mtc0 tmp, CP0_ENTRYLO1; 
  70. srl ptr, ptr, 6; 
  71. mtc0 ptr, CP0_ENTRYLO0;
  72. #define DO_FAULT(write) 
  73. .set noat; 
  74. SAVE_ALL; 
  75. mfc0 a2, CP0_BADVADDR; 
  76. STI; 
  77. .set at; 
  78. move a0, sp; 
  79. jal do_page_fault; 
  80.  li a1, write; 
  81. j ret_from_sys_call; 
  82.  nop; 
  83. .set noat;
  84. /* Check is PTE is present, if not then jump to LABEL.
  85.  * PTR points to the page table where this PTE is located,
  86.  * when the macro is done executing PTE will be restored
  87.  * with it's original value.
  88.  */
  89. #define PTE_PRESENT(pte, ptr, label) 
  90. andi pte, pte, (_PAGE_PRESENT | _PAGE_READ); 
  91. xori pte, pte, (_PAGE_PRESENT | _PAGE_READ); 
  92. bnez pte, label; 
  93.  lw pte, (ptr);
  94. /* Make PTE valid, store result in PTR. */
  95. #define PTE_MAKEVALID(pte, ptr) 
  96. ori pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); 
  97. sw pte, (ptr);
  98. /* Check if PTE can be written to, if not branch to LABEL.
  99.  * Regardless restore PTE with value from PTR when done.
  100.  */
  101. #define PTE_WRITABLE(pte, ptr, label) 
  102. andi pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); 
  103. xori pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); 
  104. bnez pte, label; 
  105.  lw pte, (ptr);
  106. /* Make PTE writable, update software status bits as well,
  107.  * then store at PTR.
  108.  */
  109. #define PTE_MAKEWRITE(pte, ptr) 
  110. ori pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | 
  111.    _PAGE_VALID | _PAGE_DIRTY); 
  112. sw pte, (ptr);
  113. .set noreorder
  114. /*
  115.  * From the IDT errata for the QED RM5230 (Nevada), processor revision 1.0:
  116.  * 2. A timing hazard exists for the TLBP instruction.
  117.  *
  118.  *      stalling_instruction
  119.  *      TLBP
  120.  *
  121.  * The JTLB is being read for the TLBP throughout the stall generated by the
  122.  * previous instruction. This is not really correct as the stalling instruction
  123.  * can modify the address used to access the JTLB.  The failure symptom is that
  124.  * the TLBP instruction will use an address created for the stalling instruction
  125.  * and not the address held in C0_ENHI and thus report the wrong results.
  126.  *
  127.  * The software work-around is to not allow the instruction preceding the TLBP
  128.  * to stall - make it an NOP or some other instruction guaranteed not to stall.
  129.  *
  130.  * Errata 2 will not be fixed.  This errata is also on the R5000.
  131.  *
  132.  * As if we MIPS hackers wouldn't know how to nop pipelines happy ...
  133.  */
  134. #define R5K_HAZARD nop
  135. /*
  136.  * Note for many R4k variants tlb probes cannot be executed out
  137.  * of the instruction cache else you get bogus results.
  138.  */
  139. .align 5
  140. NESTED(handle_tlbl, PT_SIZE, sp)
  141. .set noat
  142. invalid_tlbl:
  143. #ifndef NOTLB_OPTIMIZE
  144. /* Test present bit in entry. */
  145. LOAD_PTE(k0, k1)
  146. R5K_HAZARD
  147. tlbp
  148. PTE_PRESENT(k0, k1, nopage_tlbl)
  149. PTE_MAKEVALID(k0, k1)
  150. PTE_RELOAD(k1, k0)
  151. nop
  152. b 1f
  153.  tlbwi
  154. 1:
  155. nop
  156. .set mips3
  157. eret
  158. .set mips0
  159. #endif
  160. nopage_tlbl:
  161. DO_FAULT(0)
  162. END(handle_tlbl)
  163. .align 5
  164. NESTED(handle_tlbs, PT_SIZE, sp)
  165. .set noat
  166. #ifndef NOTLB_OPTIMIZE
  167. LOAD_PTE(k0, k1)
  168. R5K_HAZARD
  169. tlbp # find faulting entry
  170. PTE_WRITABLE(k0, k1, nopage_tlbs)
  171. PTE_MAKEWRITE(k0, k1)
  172. PTE_RELOAD(k1, k0)
  173. nop
  174. b 1f
  175.  tlbwi
  176. 1:
  177. nop
  178. .set mips3
  179. eret
  180. .set mips0
  181. #endif
  182. nopage_tlbs:
  183. DO_FAULT(1)
  184. END(handle_tlbs)
  185. .align 5
  186. NESTED(handle_mod, PT_SIZE, sp)
  187. .set noat
  188. #ifndef NOTLB_OPTIMIZE
  189. LOAD_PTE(k0, k1)
  190. R5K_HAZARD
  191. tlbp # find faulting entry
  192. andi k0, k0, _PAGE_WRITE
  193. beqz k0, nowrite_mod
  194.  lw k0, (k1)
  195. /* Present and writable bits set, set accessed and dirty bits. */
  196. PTE_MAKEWRITE(k0, k1)
  197. #if 0
  198. ori k0, k0, (_PAGE_ACCESSED | _PAGE_DIRTY)
  199. sw k0, (k1)
  200. #endif
  201. /* Now reload the entry into the tlb. */
  202. PTE_RELOAD(k1, k0)
  203. nop
  204. b 1f
  205.  tlbwi
  206. 1:
  207. nop
  208. .set mips3
  209. eret
  210. .set mips0
  211. #endif
  212. nowrite_mod:
  213. DO_FAULT(1)
  214. END(handle_mod)