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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: SCCS/s.fault.c 1.15 09/24/01 16:35:10 paulus
  3.  */
  4. /*
  5.  *  arch/ppc/mm/fault.c
  6.  *
  7.  *  PowerPC version 
  8.  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  9.  *
  10.  *  Derived from "arch/i386/mm/fault.c"
  11.  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
  12.  *
  13.  *  Modified by Cort Dougan and Paul Mackerras.
  14.  *
  15.  *  This program is free software; you can redistribute it and/or
  16.  *  modify it under the terms of the GNU General Public License
  17.  *  as published by the Free Software Foundation; either version
  18.  *  2 of the License, or (at your option) any later version.
  19.  */
  20. #include <linux/config.h>
  21. #include <linux/signal.h>
  22. #include <linux/sched.h>
  23. #include <linux/kernel.h>
  24. #include <linux/errno.h>
  25. #include <linux/string.h>
  26. #include <linux/types.h>
  27. #include <linux/ptrace.h>
  28. #include <linux/mman.h>
  29. #include <linux/mm.h>
  30. #include <linux/interrupt.h>
  31. #include <asm/page.h>
  32. #include <asm/pgtable.h>
  33. #include <asm/mmu.h>
  34. #include <asm/mmu_context.h>
  35. #include <asm/system.h>
  36. #include <asm/uaccess.h>
  37. #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
  38. extern void (*debugger)(struct pt_regs *);
  39. extern void (*debugger_fault_handler)(struct pt_regs *);
  40. extern int (*debugger_dabr_match)(struct pt_regs *);
  41. int debugger_kernel_faults = 1;
  42. #endif
  43. unsigned long htab_reloads; /* updated by hashtable.S:hash_page() */
  44. unsigned long htab_evicts;  /* updated by hashtable.S:hash_page() */
  45. unsigned long htab_preloads; /* updated by hashtable.S:add_hash_page() */
  46. unsigned long pte_misses; /* updated by do_page_fault() */
  47. unsigned long pte_errors; /* updated by do_page_fault() */
  48. unsigned int probingmem;
  49. extern void die_if_kernel(char *, struct pt_regs *, long);
  50. void bad_page_fault(struct pt_regs *, unsigned long, int sig);
  51. void do_page_fault(struct pt_regs *, unsigned long, unsigned long);
  52. /*
  53.  * For 600- and 800-family processors, the error_code parameter is DSISR
  54.  * for a data fault, SRR1 for an instruction fault. For 400-family processors
  55.  * the error_code parameter is ESR for a data fault, 0 for an instruction
  56.  * fault.
  57.  */
  58. void do_page_fault(struct pt_regs *regs, unsigned long address,
  59.    unsigned long error_code)
  60. {
  61. struct vm_area_struct * vma;
  62. struct mm_struct *mm = current->mm;
  63. siginfo_t info;
  64. int code = SEGV_MAPERR;
  65. #if defined(CONFIG_4xx)
  66. int is_write = error_code & ESR_DST;
  67. #else
  68. int is_write = 0;
  69. /*
  70.  * Fortunately the bit assignments in SRR1 for an instruction
  71.  * fault and DSISR for a data fault are mostly the same for the
  72.  * bits we are interested in.  But there are some bits which
  73.  * indicate errors in DSISR but can validly be set in SRR1.
  74.  */
  75. if (regs->trap == 0x400)
  76. error_code &= 0x48200000;
  77. else
  78. is_write = error_code & 0x02000000;
  79. #endif /* CONFIG_4xx */
  80. #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
  81. if (debugger_fault_handler && regs->trap == 0x300) {
  82. debugger_fault_handler(regs);
  83. return;
  84. }
  85. #if !defined(CONFIG_4xx)
  86. if (error_code & 0x00400000) {
  87. /* DABR match */
  88. if (debugger_dabr_match(regs))
  89. return;
  90. }
  91. #endif /* !CONFIG_4xx */
  92. #endif /* CONFIG_XMON || CONFIG_KGDB */
  93. if (in_interrupt() || mm == NULL) {
  94. bad_page_fault(regs, address, SIGSEGV);
  95. return;
  96. }
  97. down_read(&mm->mmap_sem);
  98. vma = find_vma(mm, address);
  99. if (!vma)
  100. goto bad_area;
  101. if (vma->vm_start <= address)
  102. goto good_area;
  103. if (!(vma->vm_flags & VM_GROWSDOWN))
  104. goto bad_area;
  105. if (expand_stack(vma, address))
  106. goto bad_area;
  107. good_area:
  108. code = SEGV_ACCERR;
  109. #if defined(CONFIG_6xx)
  110. if (error_code & 0x95700000)
  111. /* an error such as lwarx to I/O controller space,
  112.    address matching DABR, eciwx, etc. */
  113. goto bad_area;
  114. #endif /* CONFIG_6xx */
  115. #if defined(CONFIG_8xx)
  116.         /* The MPC8xx seems to always set 0x80000000, which is
  117.          * "undefined".  Of those that can be set, this is the only
  118.          * one which seems bad.
  119.          */
  120. if (error_code & 0x10000000)
  121.                 /* Guarded storage error. */
  122. goto bad_area;
  123. #endif /* CONFIG_8xx */
  124. /* a write */
  125. if (is_write) {
  126. if (!(vma->vm_flags & VM_WRITE))
  127. goto bad_area;
  128. /* a read */
  129. } else {
  130. /* protection fault */
  131. if (error_code & 0x08000000)
  132. goto bad_area;
  133. if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
  134. goto bad_area;
  135. }
  136. /*
  137.  * If for any reason at all we couldn't handle the fault,
  138.  * make sure we exit gracefully rather than endlessly redo
  139.  * the fault.
  140.  */
  141.  survive:
  142.         switch (handle_mm_fault(mm, vma, address, is_write)) {
  143.         case 1:
  144.                 current->min_flt++;
  145.                 break;
  146.         case 2:
  147.                 current->maj_flt++;
  148.                 break;
  149.         case 0:
  150.                 goto do_sigbus;
  151.         default:
  152.                 goto out_of_memory;
  153. }
  154. up_read(&mm->mmap_sem);
  155. /*
  156.  * keep track of tlb+htab misses that are good addrs but
  157.  * just need pte's created via handle_mm_fault()
  158.  * -- Cort
  159.  */
  160. pte_misses++;
  161. return;
  162. bad_area:
  163. up_read(&mm->mmap_sem);
  164. pte_errors++;
  165. /* User mode accesses cause a SIGSEGV */
  166. if (user_mode(regs)) {
  167. info.si_signo = SIGSEGV;
  168. info.si_errno = 0;
  169. info.si_code = code;
  170. info.si_addr = (void *) address;
  171. force_sig_info(SIGSEGV, &info, current);
  172. return;
  173. }
  174. bad_page_fault(regs, address, SIGSEGV);
  175. return;
  176. /*
  177.  * We ran out of memory, or some other thing happened to us that made
  178.  * us unable to handle the page fault gracefully.
  179.  */
  180. out_of_memory:
  181. up_read(&mm->mmap_sem);
  182. if (current->pid == 1) {
  183. current->policy |= SCHED_YIELD;
  184. schedule();
  185. down_read(&mm->mmap_sem);
  186. goto survive;
  187. }
  188. printk("VM: killing process %sn", current->comm);
  189. if (user_mode(regs))
  190. do_exit(SIGKILL);
  191. bad_page_fault(regs, address, SIGKILL);
  192. return;
  193. do_sigbus:
  194. up_read(&mm->mmap_sem);
  195. info.si_signo = SIGBUS;
  196. info.si_errno = 0;
  197. info.si_code = BUS_ADRERR;
  198. info.si_addr = (void *)address;
  199. force_sig_info (SIGBUS, &info, current);
  200. if (!user_mode(regs))
  201. bad_page_fault(regs, address, SIGBUS);
  202. }
  203. /*
  204.  * bad_page_fault is called when we have a bad access from the kernel.
  205.  * It is called from do_page_fault above and from some of the procedures
  206.  * in traps.c.
  207.  */
  208. void
  209. bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
  210. {
  211. extern void die(const char *,struct pt_regs *,long);
  212. unsigned long fixup;
  213. /* Are we prepared to handle this fault?  */
  214. if ((fixup = search_exception_table(regs->nip)) != 0) {
  215. regs->nip = fixup;
  216. return;
  217. }
  218. /* kernel has accessed a bad area */
  219. #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
  220. if (debugger_kernel_faults)
  221. debugger(regs);
  222. #endif
  223. die("kernel access of bad area", regs, sig);
  224. }
  225. #ifdef CONFIG_8xx
  226. /* The pgtable.h claims some functions generically exist, but I
  227.  * can't find them......
  228.  */
  229. pte_t *va_to_pte(unsigned long address)
  230. {
  231. pgd_t *dir;
  232. pmd_t *pmd;
  233. pte_t *pte;
  234. struct mm_struct *mm;
  235. if (address < TASK_SIZE)
  236. mm = current->mm;
  237. else
  238. mm = &init_mm;
  239. dir = pgd_offset(mm, address & PAGE_MASK);
  240. if (dir) {
  241. pmd = pmd_offset(dir, address & PAGE_MASK);
  242. if (pmd && pmd_present(*pmd)) {
  243. pte = pte_offset(pmd, address & PAGE_MASK);
  244. if (pte && pte_present(*pte)) {
  245. return(pte);
  246. }
  247. }
  248. else {
  249. return (0);
  250. }
  251. }
  252. else {
  253. return (0);
  254. }
  255. return (0);
  256. }
  257. unsigned long va_to_phys(unsigned long address)
  258. {
  259. pte_t *pte;
  260. pte = va_to_pte(address);
  261. if (pte)
  262. return(((unsigned long)(pte_val(*pte)) & PAGE_MASK) | (address & ~(PAGE_MASK)));
  263. return (0);
  264. }
  265. void
  266. print_8xx_pte(struct mm_struct *mm, unsigned long addr)
  267. {
  268.         pgd_t * pgd;
  269.         pmd_t * pmd;
  270.         pte_t * pte;
  271.         printk(" pte @ 0x%8lx: ", addr);
  272.         pgd = pgd_offset(mm, addr & PAGE_MASK);
  273.         if (pgd) {
  274.                 pmd = pmd_offset(pgd, addr & PAGE_MASK);
  275.                 if (pmd && pmd_present(*pmd)) {
  276.                         pte = pte_offset(pmd, addr & PAGE_MASK);
  277.                         if (pte) {
  278.                                 printk(" (0x%08lx)->(0x%08lx)->0x%08lxn",
  279.                                         (long)pgd, (long)pte, (long)pte_val(*pte));
  280. #define pp ((long)pte_val(*pte))
  281. printk(" RPN: %05lx PP: %lx SPS: %lx SH: %lx "
  282.        "CI: %lx v: %lxn",
  283.        pp>>12,    /* rpn */
  284.        (pp>>10)&3, /* pp */
  285.        (pp>>3)&1, /* small */
  286.        (pp>>2)&1, /* shared */
  287.        (pp>>1)&1, /* cache inhibit */
  288.        pp&1       /* valid */
  289.        );
  290. #undef pp
  291.                         }
  292.                         else {
  293.                                 printk("no pten");
  294.                         }
  295.                 }
  296.                 else {
  297.                         printk("no pmdn");
  298.                 }
  299.         }
  300.         else {
  301.                 printk("no pgdn");
  302.         }
  303. }
  304. int
  305. get_8xx_pte(struct mm_struct *mm, unsigned long addr)
  306. {
  307.         pgd_t * pgd;
  308.         pmd_t * pmd;
  309.         pte_t * pte;
  310.         int     retval = 0;
  311.         pgd = pgd_offset(mm, addr & PAGE_MASK);
  312.         if (pgd) {
  313.                 pmd = pmd_offset(pgd, addr & PAGE_MASK);
  314.                 if (pmd && pmd_present(*pmd)) {
  315.                         pte = pte_offset(pmd, addr & PAGE_MASK);
  316.                         if (pte) {
  317.                                         retval = (int)pte_val(*pte);
  318.                         }
  319.                 }
  320.         }
  321.         return(retval);
  322. }
  323. #endif /* CONFIG_8xx */