root/arch/ppc/mm/fault.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. DataAccessException
  2. InstructionAccessException
  3. do_page_fault
  4. va_to_phys

   1 /*
   2  *  ARCH/ppc/mm/fault.c
   3  *
   4  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
   5  *  Ported to PPC by Gary Thomas
   6  */
   7 
   8 #include <linux/config.h>
   9 #include <linux/signal.h>
  10 #include <linux/sched.h>
  11 #include <linux/head.h>
  12 #include <linux/kernel.h>
  13 #include <linux/errno.h>
  14 #include <linux/string.h>
  15 #include <linux/types.h>
  16 #include <linux/ptrace.h>
  17 #include <linux/mman.h>
  18 #include <linux/mm.h>
  19 
  20 #include <asm/page.h>
  21 #include <asm/pgtable.h>
  22 
  23 extern void die_if_kernel(char *, struct pt_regs *, long);
  24 extern void do_page_fault(struct pt_regs *, unsigned long, unsigned long);
  25 
  26 #if 0
  27 #define SHOW_FAULTS
  28 #endif
  29 
  30 void
  31 DataAccessException(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
  32 {
  33   pgd_t *dir;
  34   pmd_t *pmd;
  35   pte_t *pte;
  36   int tries, mode = 0;
  37   if (user_mode(regs)) mode |= 0x04;
  38   if (regs->dsisr & 0x02000000) mode |= 0x02;  /* Load/store */
  39   if (regs->dsisr & 0x08000000) mode |= 0x01;  /* Protection violation */
  40 #if 0
  41   /*#ifdef SHOW_FAULTS*/
  42   printk("Data Access Fault - Loc: %x, DSISR: %x, PC: %x", regs->dar, regs->dsisr, regs->nip);
  43   printk(" PR: %d\n", regs->msr &&(1<<14));
  44 #endif
  45   if (mode & 0x01)
  46   {
  47 #if 0
  48     printk("Write Protect Fault - Loc: %x, DSISR: %x, PC: %x\n", regs->dar, regs->dsisr, regs->nip);
  49 #endif
  50     do_page_fault(regs, regs->dar, mode);
  51     return;
  52   }
  53   for (tries = 0;  tries < 1;  tries++)
  54   {
  55     dir = pgd_offset(current->mm, regs->dar & PAGE_MASK);
  56     if (dir)
  57     {
  58       pmd = pmd_offset(dir, regs->dar & PAGE_MASK);
  59       if (pmd && pmd_present(*pmd))
  60       {
  61         pte = pte_offset(pmd, regs->dar & PAGE_MASK);
  62         if (pte && pte_present(*pte))
  63         {
  64 #if 0
  65           printk("Page mapped - PTE: %x[%x]\n", pte, *(long *)pte);
  66 #endif
  67           MMU_hash_page(&current->tss, regs->dar & PAGE_MASK, pte);
  68           return;
  69         }
  70       }
  71     } else
  72     {
  73       printk("No PGD\n");
  74     }
  75     do_page_fault(regs, regs->dar, mode);
  76   }
  77 }
  78 
  79 void
  80 InstructionAccessException(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
  81 {
  82   pgd_t *dir;
  83   pmd_t *pmd;
  84   pte_t *pte;
  85   int tries, mode = 0;
  86 #if 0
  87   panic("Instruction Access Fault - Loc: %x, DSISR: %x, PC: %x\n", regs->dar, regs->dsisr, regs->nip);
  88 #endif  
  89   if (user_mode(regs)) mode |= 0x04;
  90   if (regs->dsisr & 0x02000000) mode |= 0x02;  /* Load/store */
  91   if (regs->dsisr & 0x08000000) mode |= 0x01;  /* Protection violation */
  92   if (mode & 0x01)
  93   {
  94     do_page_fault(regs, regs->dar, mode);
  95     return;
  96   }
  97   for (tries = 0;  tries < 1;  tries++)
  98   {
  99     dir = pgd_offset(current->mm, regs->dar & PAGE_MASK);
 100     if (dir)
 101     {
 102       pmd = pmd_offset(dir, regs->dar & PAGE_MASK);
 103       if (pmd && pmd_present(*pmd))
 104       {
 105         pte = pte_offset(pmd, regs->dar & PAGE_MASK);
 106         if (pte && pte_present(*pte))
 107         {
 108 #if 0
 109           printk("Page mapped - PTE: %x[%x]\n", pte, *(long *)pte);
 110 #endif
 111           MMU_hash_page(&current->tss, regs->dar & PAGE_MASK, pte);
 112           return;
 113         }
 114       }
 115     } else
 116     {
 117 #if 1
 118   panic("No PGD Instruction Access Fault - Loc: %x, DSISR: %x, PC: %x\n", regs->dar, regs->dsisr, regs->nip);
 119 #endif  
 120       printk("No PGD\n");
 121     }
 122     do_page_fault(regs, regs->dar, mode);
 123   }
 124 }
 125 
 126 /*
 127  * This routine handles page faults.  It determines the address,
 128  * and the problem, and then passes it off to one of the appropriate
 129  * routines.
 130  *
 131  * The error_code parameter just the same as in the i386 version:
 132  *
 133  *      bit 0 == 0 means no page found, 1 means protection fault
 134  *      bit 1 == 0 means read, 1 means write
 135  *      bit 2 == 0 means kernel, 1 means user-mode
 136  */
 137 void do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
 138 {
 139   struct vm_area_struct * vma;
 140   unsigned long page;
 141 /*  printk("\ndo_page_fault()\n");*/
 142 #if 1
 143   for (vma = current->mm->mmap ; ; vma = vma->vm_next)
 144   {
 145     if (!vma)
 146     {
 147 #if 0 /* mfisk */
 148         {   struct vm_area_struct * mmp;
 149 
 150           for(mmp=current->mm->mmap; mmp; mmp=mmp->vm_next) {
 151             printk("notinmap: current: %x; mm: %x; mmap: %x; vma: %x to %x flags: %x\n",
 152                    current, current->mm, mmp, mmp->vm_start, mmp->vm_end, mmp->vm_flags);
 153           }
 154         }
 155 #endif
 156        panic("do_page_fault()  !vma \n");
 157       panic("not in map: ip = %x; current=%x; mm=%x; mmap=%x; address = %x error_code = %x\n",
 158             regs->nip, current, current->mm, current->mm->mmap, address, error_code);
 159       goto bad_area;
 160     }
 161     if (vma->vm_end > address)
 162       break;
 163   }
 164 #else
 165   vma = find_vma(current, address);
 166   if (!vma)
 167     goto bad_area;
 168 #endif
 169   if (vma->vm_start <= address){
 170     goto good_area;
 171   }
 172   if (!(vma->vm_flags & VM_GROWSDOWN))
 173   {
 174     panic("stack\n");
 175     goto bad_area;
 176   }
 177   if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur)
 178   {    panic("stack 2\n");
 179     goto bad_area;
 180      }
 181   vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
 182   vma->vm_start = (address & PAGE_MASK);
 183   
 184   /*
 185    * Ok, we have a good vm_area for this memory access, so
 186    * we can handle it..
 187    */
 188 good_area:
 189   /*
 190    * was it a write?
 191    */
 192   if (error_code & 2) {
 193     if (!(vma->vm_flags & VM_WRITE))
 194     {
 195       panic("\ndo_page_fault()  write\n");
 196       panic("\ndo_page_fault() write! current: %x, address:%x, vm_flags: %x, mm: %x; vma(%x) %x to %x\n",
 197             current,address,vma->vm_flags,current->mm,vma,vma->vm_start,vma->vm_end);
 198       goto bad_area;
 199     }
 200   } else {
 201     /* read with protection fault? */
 202     if (error_code & 1)
 203     {
 204       panic("do_page_fault()  error code thing\n");         
 205       goto bad_area;
 206     }
 207     if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
 208     {
 209 #if 0
 210       _printk("vma = %x\n", vma);
 211       _printk("vma->vm_flags = %x\n", vma->vm_flags);      
 212       _printk("VM_READ = %x VM_EXEC = %x\n",VM_READ,VM_EXEC);
 213 #endif
 214 #if 0
 215       printk("vma = %x VM_READ = %x VM_EXEC = %x\n",
 216              vma, VM_READ,VM_EXEC);
 217       printk("vma->vm_start = %x vma->vm_end = %d\n",
 218              vma->vm_start, vma->vm_end);
 219       printk("error_code = %x\n", error_code);      
 220       printk("regs = %x\n", regs);
 221       printk("vma->vm_flags = %x\n", vma->vm_flags);
 222 #endif
 223 /*      printk("do_page_fault()  multi thing\n"); */
 224       goto bad_area; 
 225     }
 226   }
 227   handle_mm_fault(vma, address, error_code & 2); 
 228   return;
 229   
 230   /*
 231    * Something tried to access memory that isn't in our memory map..
 232    * Fix it, but check if it's kernel or user first..
 233    */
 234 bad_area:
 235   if (user_mode(regs)) {
 236     panic("Task: %x, PC: %x, bad area! - Addr: %x\n", current, regs->nip, address);
 237     send_sig(SIGSEGV, current, 1);
 238     return;
 239   }
 240 #if 0
 241   panic("\nKERNEL! Task: %x, PC: %x, bad area! - Addr: %x, PGDIR: %x\n",
 242          current, regs->nip, address, current->tss.pg_tables);
 243 #else
 244   panic("\nKERNELmm! current: %x, address:%x, vm_flags: %x, mm: %x; vma(%x) %x to %x\n",
 245         current,address,vma->vm_flags,current->mm,vma,vma->vm_start,vma->vm_end);
 246 #endif
 247   
 248   while (1) ;
 249 }
 250 
 251 va_to_phys(unsigned long address)
     /* [previous][next][first][last][top][bottom][index][help] */
 252 {
 253   pgd_t *dir;
 254   pmd_t *pmd;
 255   pte_t *pte;
 256   dir = pgd_offset(current->mm, address & PAGE_MASK);
 257   if (dir)
 258   {
 259     pmd = pmd_offset(dir, address & PAGE_MASK);
 260     if (pmd && pmd_present(*pmd))
 261     {
 262       pte = pte_offset(pmd, address & PAGE_MASK);
 263       if (pte && pte_present(*pte))
 264       {
 265         return(pte_page(*pte) | (address & ~(PAGE_MASK-1)));
 266       }
 267     } else
 268     {
 269       return (0);
 270     }
 271   } else
 272   {
 273     return (0);
 274   }
 275 }
 276 
 277 
 278 
 279 
 280 
 281 
 282 
 283 
 284 
 285 
 286 
 287 
 288 

/* [previous][next][first][last][top][bottom][index][help] */