fault.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:9k
源码类别:

Linux/Unix编程

开发平台:

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. if (current->pid == 1) {
  182. yield();
  183. goto survive;
  184. }
  185. up_read(&mm->mmap_sem);
  186. printk("VM: killing process %sn", current->comm);
  187. if (user_mode(regs))
  188. do_exit(SIGKILL);
  189. bad_page_fault(regs, address, SIGKILL);
  190. return;
  191. do_sigbus:
  192. up_read(&mm->mmap_sem);
  193. info.si_signo = SIGBUS;
  194. info.si_errno = 0;
  195. info.si_code = BUS_ADRERR;
  196. info.si_addr = (void *)address;
  197. force_sig_info (SIGBUS, &info, current);
  198. if (!user_mode(regs))
  199. bad_page_fault(regs, address, SIGBUS);
  200. }
  201. /*
  202.  * bad_page_fault is called when we have a bad access from the kernel.
  203.  * It is called from do_page_fault above and from some of the procedures
  204.  * in traps.c.
  205.  */
  206. void
  207. bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
  208. {
  209. extern void die(const char *,struct pt_regs *,long);
  210. unsigned long fixup;
  211. /* Are we prepared to handle this fault?  */
  212. if ((fixup = search_exception_table(regs->nip)) != 0) {
  213. regs->nip = fixup;
  214. return;
  215. }
  216. /* kernel has accessed a bad area */
  217. #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
  218. if (debugger_kernel_faults)
  219. debugger(regs);
  220. #endif
  221. die("kernel access of bad area", regs, sig);
  222. }
  223. #ifdef CONFIG_8xx
  224. /* The pgtable.h claims some functions generically exist, but I
  225.  * can't find them......
  226.  */
  227. pte_t *va_to_pte(unsigned long address)
  228. {
  229. pgd_t *dir;
  230. pmd_t *pmd;
  231. pte_t *pte;
  232. struct mm_struct *mm;
  233. if (address < TASK_SIZE)
  234. mm = current->mm;
  235. else
  236. mm = &init_mm;
  237. dir = pgd_offset(mm, address & PAGE_MASK);
  238. if (dir) {
  239. pmd = pmd_offset(dir, address & PAGE_MASK);
  240. if (pmd && pmd_present(*pmd)) {
  241. pte = pte_offset(pmd, address & PAGE_MASK);
  242. if (pte && pte_present(*pte)) {
  243. return(pte);
  244. }
  245. }
  246. else {
  247. return (0);
  248. }
  249. }
  250. else {
  251. return (0);
  252. }
  253. return (0);
  254. }
  255. unsigned long va_to_phys(unsigned long address)
  256. {
  257. pte_t *pte;
  258. pte = va_to_pte(address);
  259. if (pte)
  260. return(((unsigned long)(pte_val(*pte)) & PAGE_MASK) | (address & ~(PAGE_MASK)));
  261. return (0);
  262. }
  263. void
  264. print_8xx_pte(struct mm_struct *mm, unsigned long addr)
  265. {
  266.         pgd_t * pgd;
  267.         pmd_t * pmd;
  268.         pte_t * pte;
  269.         printk(" pte @ 0x%8lx: ", addr);
  270.         pgd = pgd_offset(mm, addr & PAGE_MASK);
  271.         if (pgd) {
  272.                 pmd = pmd_offset(pgd, addr & PAGE_MASK);
  273.                 if (pmd && pmd_present(*pmd)) {
  274.                         pte = pte_offset(pmd, addr & PAGE_MASK);
  275.                         if (pte) {
  276.                                 printk(" (0x%08lx)->(0x%08lx)->0x%08lxn",
  277.                                         (long)pgd, (long)pte, (long)pte_val(*pte));
  278. #define pp ((long)pte_val(*pte))
  279. printk(" RPN: %05lx PP: %lx SPS: %lx SH: %lx "
  280.        "CI: %lx v: %lxn",
  281.        pp>>12,    /* rpn */
  282.        (pp>>10)&3, /* pp */
  283.        (pp>>3)&1, /* small */
  284.        (pp>>2)&1, /* shared */
  285.        (pp>>1)&1, /* cache inhibit */
  286.        pp&1       /* valid */
  287.        );
  288. #undef pp
  289.                         }
  290.                         else {
  291.                                 printk("no pten");
  292.                         }
  293.                 }
  294.                 else {
  295.                         printk("no pmdn");
  296.                 }
  297.         }
  298.         else {
  299.                 printk("no pgdn");
  300.         }
  301. }
  302. int
  303. get_8xx_pte(struct mm_struct *mm, unsigned long addr)
  304. {
  305.         pgd_t * pgd;
  306.         pmd_t * pmd;
  307.         pte_t * pte;
  308.         int     retval = 0;
  309.         pgd = pgd_offset(mm, addr & PAGE_MASK);
  310.         if (pgd) {
  311.                 pmd = pmd_offset(pgd, addr & PAGE_MASK);
  312.                 if (pmd && pmd_present(*pmd)) {
  313.                         pte = pte_offset(pmd, addr & PAGE_MASK);
  314.                         if (pte) {
  315.                                         retval = (int)pte_val(*pte);
  316.                         }
  317.                 }
  318.         }
  319.         return(retval);
  320. }
  321. #endif /* CONFIG_8xx */