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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: fault.c,v 1.122 2001/11/17 07:19:26 davem Exp $
  2.  * fault.c:  Page fault handlers for the Sparc.
  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) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  7.  */
  8. #include <asm/head.h>
  9. #include <linux/string.h>
  10. #include <linux/types.h>
  11. #include <linux/ptrace.h>
  12. #include <linux/mman.h>
  13. #include <linux/threads.h>
  14. #include <linux/kernel.h>
  15. #include <linux/signal.h>
  16. #include <linux/mm.h>
  17. #include <linux/smp.h>
  18. #include <linux/smp_lock.h>
  19. #include <linux/interrupt.h>
  20. #include <asm/system.h>
  21. #include <asm/segment.h>
  22. #include <asm/page.h>
  23. #include <asm/pgtable.h>
  24. #include <asm/memreg.h>
  25. #include <asm/openprom.h>
  26. #include <asm/oplib.h>
  27. #include <asm/smp.h>
  28. #include <asm/traps.h>
  29. #include <asm/kdebug.h>
  30. #include <asm/uaccess.h>
  31. #define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0]))
  32. extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
  33. extern int prom_node_root;
  34. /* At boot time we determine these two values necessary for setting
  35.  * up the segment maps and page table entries (pte's).
  36.  */
  37. int num_segmaps, num_contexts;
  38. int invalid_segment;
  39. /* various Virtual Address Cache parameters we find at boot time... */
  40. int vac_size, vac_linesize, vac_do_hw_vac_flushes;
  41. int vac_entries_per_context, vac_entries_per_segment;
  42. int vac_entries_per_page;
  43. /* Nice, simple, prom library does all the sweating for us. ;) */
  44. int prom_probe_memory (void)
  45. {
  46. register struct linux_mlist_v0 *mlist;
  47. register unsigned long bytes, base_paddr, tally;
  48. register int i;
  49. i = 0;
  50. mlist= *prom_meminfo()->v0_available;
  51. bytes = tally = mlist->num_bytes;
  52. base_paddr = (unsigned long) mlist->start_adr;
  53.   
  54. sp_banks[0].base_addr = base_paddr;
  55. sp_banks[0].num_bytes = bytes;
  56. while (mlist->theres_more != (void *) 0){
  57. i++;
  58. mlist = mlist->theres_more;
  59. bytes = mlist->num_bytes;
  60. tally += bytes;
  61. if (i >= SPARC_PHYS_BANKS-1) {
  62. printk ("The machine has more banks than "
  63. "this kernel can supportn"
  64. "Increase the SPARC_PHYS_BANKS "
  65. "setting (currently %d)n",
  66. SPARC_PHYS_BANKS);
  67. i = SPARC_PHYS_BANKS-1;
  68. break;
  69. }
  70.     
  71. sp_banks[i].base_addr = (unsigned long) mlist->start_adr;
  72. sp_banks[i].num_bytes = mlist->num_bytes;
  73. }
  74. i++;
  75. sp_banks[i].base_addr = 0xdeadbeef;
  76. sp_banks[i].num_bytes = 0;
  77. /* Now mask all bank sizes on a page boundary, it is all we can
  78.  * use anyways.
  79.  */
  80. for(i=0; sp_banks[i].num_bytes != 0; i++)
  81. sp_banks[i].num_bytes &= PAGE_MASK;
  82. return tally;
  83. }
  84. /* Traverse the memory lists in the prom to see how much physical we
  85.  * have.
  86.  */
  87. unsigned long
  88. probe_memory(void)
  89. {
  90. int total;
  91. total = prom_probe_memory();
  92. /* Oh man, much nicer, keep the dirt in promlib. */
  93. return total;
  94. }
  95. extern void sun4c_complete_all_stores(void);
  96. /* Whee, a level 15 NMI interrupt memory error.  Let's have fun... */
  97. asmlinkage void sparc_lvl15_nmi(struct pt_regs *regs, unsigned long serr,
  98. unsigned long svaddr, unsigned long aerr,
  99. unsigned long avaddr)
  100. {
  101. sun4c_complete_all_stores();
  102. printk("FAULT: NMI receivedn");
  103. printk("SREGS: Synchronous Error %08lxn", serr);
  104. printk("       Synchronous Vaddr %08lxn", svaddr);
  105. printk("      Asynchronous Error %08lxn", aerr);
  106. printk("      Asynchronous Vaddr %08lxn", avaddr);
  107. if (sun4c_memerr_reg)
  108. printk("     Memory Parity Error %08lxn", *sun4c_memerr_reg);
  109. printk("REGISTER DUMP:n");
  110. show_regs(regs);
  111. prom_halt();
  112. }
  113. static void unhandled_fault(unsigned long, struct task_struct *,
  114. struct pt_regs *) __attribute__ ((noreturn));
  115. static void unhandled_fault(unsigned long address, struct task_struct *tsk,
  116.                      struct pt_regs *regs)
  117. {
  118. if((unsigned long) address < PAGE_SIZE) {
  119. printk(KERN_ALERT "Unable to handle kernel NULL "
  120.        "pointer dereference");
  121. } else {
  122. printk(KERN_ALERT "Unable to handle kernel paging request "
  123.        "at virtual address %08lxn", address);
  124. }
  125. printk(KERN_ALERT "tsk->{mm,active_mm}->context = %08lxn",
  126. (tsk->mm ? tsk->mm->context : tsk->active_mm->context));
  127. printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %08lxn",
  128. (tsk->mm ? (unsigned long) tsk->mm->pgd :
  129.   (unsigned long) tsk->active_mm->pgd));
  130. die_if_kernel("Oops", regs);
  131. }
  132. asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc, 
  133.     unsigned long address)
  134. {
  135. struct pt_regs regs;
  136. unsigned long g2;
  137. unsigned int insn;
  138. int i;
  139. i = search_exception_table(ret_pc, &g2);
  140. switch (i) {
  141. case 3:
  142. /* load & store will be handled by fixup */
  143. return 3;
  144. case 1:
  145. /* store will be handled by fixup, load will bump out */
  146. /* for _to_ macros */
  147. insn = *((unsigned int *) pc);
  148. if ((insn >> 21) & 1)
  149. return 1;
  150. break;
  151. case 2:
  152. /* load will be handled by fixup, store will bump out */
  153. /* for _from_ macros */
  154. insn = *((unsigned int *) pc);
  155. if (!((insn >> 21) & 1) || ((insn>>19)&0x3f) == 15)
  156. return 2; 
  157. break; 
  158. default:
  159. break;
  160. };
  161. memset(&regs, 0, sizeof (regs));
  162. regs.pc = pc;
  163. regs.npc = pc + 4;
  164. __asm__ __volatile__(
  165. "rd %%psr, %0nt"
  166. "nopnt"
  167. "nopnt"
  168. "nopn" : "=r" (regs.psr));
  169. unhandled_fault(address, current, &regs);
  170. /* Not reached */
  171. return 0;
  172. }
  173. asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
  174.        unsigned long address)
  175. {
  176. struct vm_area_struct *vma;
  177. struct task_struct *tsk = current;
  178. struct mm_struct *mm = tsk->mm;
  179. unsigned int fixup;
  180. unsigned long g2;
  181. siginfo_t info;
  182. int from_user = !(regs->psr & PSR_PS);
  183. if(text_fault)
  184. address = regs->pc;
  185. /*
  186.  * We fault-in kernel-space virtual memory on-demand. The
  187.  * 'reference' page table is init_mm.pgd.
  188.  *
  189.  * NOTE! We MUST NOT take any locks for this case. We may
  190.  * be in an interrupt or a critical region, and should
  191.  * only copy the information from the master page table,
  192.  * nothing more.
  193.  */
  194. if (!ARCH_SUN4C_SUN4 && address >= TASK_SIZE)
  195. goto vmalloc_fault;
  196. info.si_code = SEGV_MAPERR;
  197. /*
  198.  * If we're in an interrupt or have no user
  199.  * context, we must not take the fault..
  200.  */
  201.         if (in_interrupt() || !mm)
  202.                 goto no_context;
  203. down_read(&mm->mmap_sem);
  204. /*
  205.  * The kernel referencing a bad kernel pointer can lock up
  206.  * a sun4c machine completely, so we must attempt recovery.
  207.  */
  208. if(!from_user && address >= PAGE_OFFSET)
  209. goto bad_area;
  210. vma = find_vma(mm, address);
  211. if(!vma)
  212. goto bad_area;
  213. if(vma->vm_start <= address)
  214. goto good_area;
  215. if(!(vma->vm_flags & VM_GROWSDOWN))
  216. goto bad_area;
  217. if(expand_stack(vma, address))
  218. goto bad_area;
  219. /*
  220.  * Ok, we have a good vm_area for this memory access, so
  221.  * we can handle it..
  222.  */
  223. good_area:
  224. info.si_code = SEGV_ACCERR;
  225. if(write) {
  226. if(!(vma->vm_flags & VM_WRITE))
  227. goto bad_area;
  228. } else {
  229. /* Allow reads even for write-only mappings */
  230. if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
  231. goto bad_area;
  232. }
  233. /*
  234.  * If for any reason at all we couldn't handle the fault,
  235.  * make sure we exit gracefully rather than endlessly redo
  236.  * the fault.
  237.  */
  238. switch (handle_mm_fault(mm, vma, address, write)) {
  239. case 1:
  240. current->min_flt++;
  241. break;
  242. case 2:
  243. current->maj_flt++;
  244. break;
  245. case 0:
  246. goto do_sigbus;
  247. default:
  248. goto out_of_memory;
  249. }
  250. up_read(&mm->mmap_sem);
  251. return;
  252. /*
  253.  * Something tried to access memory that isn't in our memory map..
  254.  * Fix it, but check if it's kernel or user first..
  255.  */
  256. bad_area:
  257. up_read(&mm->mmap_sem);
  258. bad_area_nosemaphore:
  259. /* User mode accesses just cause a SIGSEGV */
  260. if(from_user) {
  261. #if 0
  262. printk("Fault whee %s [%d]: segfaults at %08lx pc=%08lxn",
  263.        tsk->comm, tsk->pid, address, regs->pc);
  264. #endif
  265. info.si_signo = SIGSEGV;
  266. info.si_errno = 0;
  267. /* info.si_code set above to make clear whether
  268.    this was a SEGV_MAPERR or SEGV_ACCERR fault.  */
  269. info.si_addr = (void *)address;
  270. info.si_trapno = 0;
  271. force_sig_info (SIGSEGV, &info, tsk);
  272. return;
  273. }
  274. /* Is this in ex_table? */
  275. no_context:
  276. g2 = regs->u_regs[UREG_G2];
  277. if (!from_user && (fixup = search_exception_table (regs->pc, &g2))) {
  278. if (fixup > 10) { /* Values below are reserved for other things */
  279. extern const unsigned __memset_start[];
  280. extern const unsigned __memset_end[];
  281. extern const unsigned __csum_partial_copy_start[];
  282. extern const unsigned __csum_partial_copy_end[];
  283. #ifdef DEBUG_EXCEPTIONS
  284. printk("Exception: PC<%08lx> faddr<%08lx>n", regs->pc, address);
  285. printk("EX_TABLE: insn<%08lx> fixup<%08x> g2<%08lx>n",
  286. regs->pc, fixup, g2);
  287. #endif
  288. if ((regs->pc >= (unsigned long)__memset_start &&
  289.      regs->pc < (unsigned long)__memset_end) ||
  290.     (regs->pc >= (unsigned long)__csum_partial_copy_start &&
  291.      regs->pc < (unsigned long)__csum_partial_copy_end)) {
  292.         regs->u_regs[UREG_I4] = address;
  293. regs->u_regs[UREG_I5] = regs->pc;
  294. }
  295. regs->u_regs[UREG_G2] = g2;
  296. regs->pc = fixup;
  297. regs->npc = regs->pc + 4;
  298. return;
  299. }
  300. }
  301. unhandled_fault (address, tsk, regs);
  302. do_exit(SIGKILL);
  303. /*
  304.  * We ran out of memory, or some other thing happened to us that made
  305.  * us unable to handle the page fault gracefully.
  306.  */
  307. out_of_memory:
  308. up_read(&mm->mmap_sem);
  309. printk("VM: killing process %sn", tsk->comm);
  310. if (from_user)
  311. do_exit(SIGKILL);
  312. goto no_context;
  313. do_sigbus:
  314. up_read(&mm->mmap_sem);
  315. info.si_signo = SIGBUS;
  316. info.si_errno = 0;
  317. info.si_code = BUS_ADRERR;
  318. info.si_addr = (void *)address;
  319. info.si_trapno = 0;
  320. force_sig_info (SIGBUS, &info, tsk);
  321. if (!from_user)
  322. goto no_context;
  323. vmalloc_fault:
  324. {
  325. /*
  326.  * Synchronize this task's top level page-table
  327.  * with the 'reference' page table.
  328.  */
  329. int offset = pgd_index(address);
  330. pgd_t *pgd, *pgd_k;
  331. pmd_t *pmd, *pmd_k;
  332. pgd = tsk->active_mm->pgd + offset;
  333. pgd_k = init_mm.pgd + offset;
  334. if (!pgd_present(*pgd)) {
  335. if (!pgd_present(*pgd_k))
  336. goto bad_area_nosemaphore;
  337. pgd_val(*pgd) = pgd_val(*pgd_k);
  338. return;
  339. }
  340. pmd = pmd_offset(pgd, address);
  341. pmd_k = pmd_offset(pgd_k, address);
  342. if (pmd_present(*pmd) || !pmd_present(*pmd_k))
  343. goto bad_area_nosemaphore;
  344. pmd_val(*pmd) = pmd_val(*pmd_k);
  345. return;
  346. }
  347. }
  348. asmlinkage void do_sun4c_fault(struct pt_regs *regs, int text_fault, int write,
  349.        unsigned long address)
  350. {
  351. extern void sun4c_update_mmu_cache(struct vm_area_struct *,
  352.    unsigned long,pte_t);
  353. extern pte_t *sun4c_pte_offset(pmd_t *,unsigned long);
  354. struct task_struct *tsk = current;
  355. struct mm_struct *mm = tsk->mm;
  356. pgd_t *pgdp;
  357. pte_t *ptep;
  358. if (text_fault) {
  359. address = regs->pc;
  360. } else if (!write &&
  361.    !(regs->psr & PSR_PS)) {
  362. unsigned int insn, *ip;
  363. ip = (unsigned int *)regs->pc;
  364. if (! get_user(insn, ip)) {
  365. if ((insn & 0xc1680000) == 0xc0680000)
  366. write = 1;
  367. }
  368. }
  369. pgdp = pgd_offset(mm, address);
  370. ptep = sun4c_pte_offset((pmd_t *) pgdp, address);
  371. if (pgd_val(*pgdp)) {
  372.     if (write) {
  373. if ((pte_val(*ptep) & (_SUN4C_PAGE_WRITE|_SUN4C_PAGE_PRESENT))
  374.    == (_SUN4C_PAGE_WRITE|_SUN4C_PAGE_PRESENT)) {
  375. unsigned long flags;
  376. *ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_ACCESSED |
  377.       _SUN4C_PAGE_MODIFIED |
  378.       _SUN4C_PAGE_VALID |
  379.       _SUN4C_PAGE_DIRTY);
  380. save_and_cli(flags);
  381. if (sun4c_get_segmap(address) != invalid_segment) {
  382. sun4c_put_pte(address, pte_val(*ptep));
  383. restore_flags(flags);
  384. return;
  385. }
  386. restore_flags(flags);
  387. }
  388.     } else {
  389. if ((pte_val(*ptep) & (_SUN4C_PAGE_READ|_SUN4C_PAGE_PRESENT))
  390.    == (_SUN4C_PAGE_READ|_SUN4C_PAGE_PRESENT)) {
  391. unsigned long flags;
  392. *ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_ACCESSED |
  393.       _SUN4C_PAGE_VALID);
  394. save_and_cli(flags);
  395. if (sun4c_get_segmap(address) != invalid_segment) {
  396. sun4c_put_pte(address, pte_val(*ptep));
  397. restore_flags(flags);
  398. return;
  399. }
  400. restore_flags(flags);
  401. }
  402.     }
  403. }
  404. /* This conditional is 'interesting'. */
  405. if (pgd_val(*pgdp) && !(write && !(pte_val(*ptep) & _SUN4C_PAGE_WRITE))
  406.     && (pte_val(*ptep) & _SUN4C_PAGE_VALID))
  407. /* Note: It is safe to not grab the MMAP semaphore here because
  408.  *       we know that update_mmu_cache() will not sleep for
  409.  *       any reason (at least not in the current implementation)
  410.  *       and therefore there is no danger of another thread getting
  411.  *       on the CPU and doing a shrink_mmap() on this vma.
  412.  */
  413. sun4c_update_mmu_cache (find_vma(current->mm, address), address,
  414. *ptep);
  415. else
  416. do_sparc_fault(regs, text_fault, write, address);
  417. }
  418. /* This always deals with user addresses. */
  419. inline void force_user_fault(unsigned long address, int write)
  420. {
  421. struct vm_area_struct *vma;
  422. struct task_struct *tsk = current;
  423. struct mm_struct *mm = tsk->mm;
  424. siginfo_t info;
  425. info.si_code = SEGV_MAPERR;
  426. #if 0
  427. printk("wf<pid=%d,wr=%d,addr=%08lx>n",
  428.        tsk->pid, write, address);
  429. #endif
  430. down_read(&mm->mmap_sem);
  431. vma = find_vma(mm, address);
  432. if(!vma)
  433. goto bad_area;
  434. if(vma->vm_start <= address)
  435. goto good_area;
  436. if(!(vma->vm_flags & VM_GROWSDOWN))
  437. goto bad_area;
  438. if(expand_stack(vma, address))
  439. goto bad_area;
  440. good_area:
  441. info.si_code = SEGV_ACCERR;
  442. if(write) {
  443. if(!(vma->vm_flags & VM_WRITE))
  444. goto bad_area;
  445. } else {
  446. if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
  447. goto bad_area;
  448. }
  449. if (!handle_mm_fault(mm, vma, address, write))
  450. goto do_sigbus;
  451. up_read(&mm->mmap_sem);
  452. return;
  453. bad_area:
  454. up_read(&mm->mmap_sem);
  455. #if 0
  456. printk("Window whee %s [%d]: segfaults at %08lxn",
  457.        tsk->comm, tsk->pid, address);
  458. #endif
  459. info.si_signo = SIGSEGV;
  460. info.si_errno = 0;
  461. /* info.si_code set above to make clear whether
  462.    this was a SEGV_MAPERR or SEGV_ACCERR fault.  */
  463. info.si_addr = (void *)address;
  464. info.si_trapno = 0;
  465. force_sig_info (SIGSEGV, &info, tsk);
  466. return;
  467. do_sigbus:
  468. up_read(&mm->mmap_sem);
  469. info.si_signo = SIGBUS;
  470. info.si_errno = 0;
  471. info.si_code = BUS_ADRERR;
  472. info.si_addr = (void *)address;
  473. info.si_trapno = 0;
  474. force_sig_info (SIGBUS, &info, tsk);
  475. }
  476. void window_overflow_fault(void)
  477. {
  478. unsigned long sp;
  479. sp = current->thread.rwbuf_stkptrs[0];
  480. if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
  481. force_user_fault(sp + 0x38, 1);
  482. force_user_fault(sp, 1);
  483. }
  484. void window_underflow_fault(unsigned long sp)
  485. {
  486. if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
  487. force_user_fault(sp + 0x38, 0);
  488. force_user_fault(sp, 0);
  489. }
  490. void window_ret_fault(struct pt_regs *regs)
  491. {
  492. unsigned long sp;
  493. sp = regs->u_regs[UREG_FP];
  494. if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
  495. force_user_fault(sp + 0x38, 0);
  496. force_user_fault(sp, 0);
  497. }