root/arch/sparc/mm/fault.c

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

DEFINITIONS

This source file includes following definitions.
  1. prom_probe_memory
  2. probe_memory
  3. sparc_txtmem_error
  4. sparc_text_access_fault
  5. sparc_datamem_error
  6. sparc_data_access_fault
  7. dump_srmmu_fsr
  8. really_bad_srmmu_fault
  9. srmmu_text_access_fault
  10. srmmu_data_access_fault

   1 /* fault.c:  Page fault handlers for the Sparc.
   2  *
   3  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
   4  */
   5 
   6 #include <linux/string.h>
   7 #include <linux/types.h>
   8 #include <linux/ptrace.h>
   9 #include <linux/mman.h>
  10 #include <linux/signal.h>
  11 #include <linux/mm.h>
  12 
  13 #include <asm/system.h>
  14 #include <asm/segment.h>
  15 #include <asm/openprom.h>
  16 #include <asm/idprom.h>
  17 #include <asm/page.h>
  18 #include <asm/pgtable.h>
  19 #include <asm/memreg.h>
  20 #include <asm/openprom.h>
  21 #include <asm/oplib.h>
  22 #include <asm/kdebug.h>
  23 
  24 #define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0]))
  25 
  26 extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
  27 extern int prom_node_root;
  28 
  29 extern void die_if_kernel(char *,struct pt_regs *,long);
  30 
  31 struct linux_romvec *romvec;
  32 
  33 /* foo */
  34 
  35 int tbase_needs_unmapping;
  36 
  37 /* At boot time we determine these two values necessary for setting
  38  * up the segment maps and page table entries (pte's).
  39  */
  40 
  41 int num_segmaps, num_contexts;
  42 int invalid_segment;
  43 
  44 /* various Virtual Address Cache parameters we find at boot time... */
  45 
  46 int vac_size, vac_linesize, vac_do_hw_vac_flushes;
  47 int vac_entries_per_context, vac_entries_per_segment;
  48 int vac_entries_per_page;
  49 
  50 /*
  51  * Define this if things work differently on a i386 and a i486:
  52  * it will (on a i486) warn about kernel memory accesses that are
  53  * done without a 'verify_area(VERIFY_WRITE,..)'
  54  */
  55 #undef CONFIG_TEST_VERIFY_AREA
  56 
  57 /* Nice, simple, prom library does all the sweating for us. ;) */
  58 int prom_probe_memory (void)
     /* [previous][next][first][last][top][bottom][index][help] */
  59 {
  60   register struct linux_mlist_v0 *mlist;
  61   register unsigned long bytes, base_paddr, tally;
  62   register int i;
  63 
  64   i = 0;
  65   mlist= *prom_meminfo()->v0_available;
  66   bytes = tally = mlist->num_bytes;
  67   base_paddr = (unsigned long) mlist->start_adr;
  68   
  69   sp_banks[0].base_addr = base_paddr;
  70   sp_banks[0].num_bytes = bytes;
  71 
  72   while (mlist->theres_more != (void *) 0){
  73     i++;
  74     mlist = mlist->theres_more;
  75     bytes = mlist->num_bytes;
  76     tally += bytes;
  77     if (i >= SPARC_PHYS_BANKS-1) {
  78       printk ("The machine has more banks that this kernel can support\n"
  79               "Increase the SPARC_PHYS_BANKS setting (currently %d)\n",
  80               SPARC_PHYS_BANKS);
  81       i = SPARC_PHYS_BANKS-1;
  82       break;
  83     }
  84     
  85     sp_banks[i].base_addr = (unsigned long) mlist->start_adr;
  86     sp_banks[i].num_bytes = mlist->num_bytes;
  87   }
  88 
  89   i++;
  90   sp_banks[i].base_addr = 0xdeadbeef;
  91   sp_banks[i].num_bytes = 0;
  92 
  93   return tally;
  94 }
  95 
  96 /* Traverse the memory lists in the prom to see how much physical we
  97  * have.
  98  */
  99 unsigned long
 100 probe_memory(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102         int total;
 103 
 104         total = prom_probe_memory();
 105 
 106         /* Oh man, much nicer, keep the dirt in promlib. */
 107         return total;
 108 }
 109 
 110 asmlinkage void sparc_txtmem_error(int type, unsigned long sync_err_reg,
     /* [previous][next][first][last][top][bottom][index][help] */
 111                                    unsigned long sync_vaddr,
 112                                    unsigned long async_err_reg,
 113                                    unsigned long async_vaddr)
 114 {
 115   printk("Aieee, sparc text page access error, halting\n");
 116   printk("type = %d  sync_err_reg = 0x%x  sync_vaddr = 0x%x\n",
 117          type, (unsigned int) sync_err_reg, (unsigned int) sync_vaddr);
 118   printk("async_err_reg = 0x%x  async_vaddr = 0x%x\n",
 119          (unsigned int) async_err_reg, (unsigned int) async_vaddr);
 120   halt();
 121 }
 122 
 123 /* #define DEBUG_SPARC_TEXT_ACCESS_FAULT */
 124 
 125 asmlinkage void sparc_text_access_fault(int type, unsigned long sync_err_reg,
     /* [previous][next][first][last][top][bottom][index][help] */
 126                                         unsigned long sync_vaddr,
 127                                         unsigned long pc, unsigned long psr,
 128                                         struct pt_regs *regs)
 129 {
 130   struct vm_area_struct *vma;
 131   unsigned long address;
 132 
 133   address = sync_vaddr;
 134 #ifdef DEBUG_SPARC_TEXT_ACCESS_FAULT
 135   printk("Text FAULT: address = %08lx  code = %08lx\n",
 136          (unsigned long) address, (unsigned long) sync_err_reg);
 137   printk("PC = %08lx\n", (unsigned long) regs->pc);
 138   SP_ENTER_DEBUGGER;
 139   halt();
 140 #endif
 141   vma = find_vma(current, address);
 142   if(!vma) {
 143     goto bad_area;
 144   }
 145   if(vma->vm_start <= address)
 146     goto good_area;
 147   goto bad_area;
 148 
 149 /*
 150  * Ok, we have a good vm_area for this memory access, so
 151  * we can handle it..
 152  */
 153 good_area:
 154   handle_mm_fault(vma, address, 0);
 155   return;
 156 
 157 /*
 158  * Something tried to access memory that isn't in our memory map..
 159  * Fix it, but check if it's kernel or user first..
 160  */
 161 bad_area:
 162   if((unsigned long) address < PAGE_SIZE) {
 163     printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
 164   } else
 165     printk(KERN_ALERT "Unable to handle kernel paging request");
 166   printk(" at virtual address %08lx\n",address);
 167   printk(KERN_ALERT "current->tss.pgd_ptr = %08lx\n",
 168          (unsigned long) current->tss.pgd_ptr);
 169   halt();
 170 }
 171 
 172 asmlinkage void sparc_datamem_error(int type, unsigned long sync_err_reg,
     /* [previous][next][first][last][top][bottom][index][help] */
 173                                     unsigned long sync_vaddr,
 174                                     unsigned long async_err_reg,
 175                                     unsigned long async_vaddr)
 176 {
 177   printk("Aieee, sparc data page access error, halting\n");
 178   printk("type = %d  sync_err_reg = 0x%x  sync_vaddr = 0x%x\n",
 179          type, (unsigned int) sync_err_reg, (unsigned int) sync_vaddr);
 180   printk("async_err_reg = 0x%x  async_vaddr = 0x%x\n",
 181          (unsigned int) async_err_reg, (unsigned int) async_vaddr);
 182   printk("SYNC PAGE has MMU entry %08lx\n",
 183          (unsigned long) get_pte(sync_vaddr));
 184   halt();
 185 }
 186 
 187 /* #define DEBUG_SPARC_DATA_ACCESS_FAULT */
 188 
 189 asmlinkage void sparc_data_access_fault(int type, unsigned long sync_err_reg,
     /* [previous][next][first][last][top][bottom][index][help] */
 190                                         unsigned long sync_vaddr,
 191                                         unsigned long pc, unsigned long psr,
 192                                         struct pt_regs *regs)
 193 {
 194   struct vm_area_struct *vma;
 195   unsigned long address;
 196   int error_code;
 197 
 198   address = sync_vaddr;
 199 #ifdef DEBUG_SPARC_DATA_ACCESS_FAULT 
 200   printk("Data FAULT: address = %08lx  code = %08lx\n",
 201          (unsigned long) address, (unsigned long) sync_err_reg);
 202   printk("PC = %08lx\n", (unsigned long) regs->pc);
 203   printk("PTE = %08lx\n", (unsigned long) get_pte(address));
 204 #endif
 205   vma = find_vma(current, address);
 206   if(!vma) {
 207 #ifdef DEBUG_SPARC_DATA_ACCESS_FAULT 
 208     printk("NULL VMA\n");
 209 #endif
 210     goto bad_area;
 211   }
 212   if(vma->vm_start <= address)
 213     goto good_area;
 214 
 215   if(!(vma->vm_flags & VM_GROWSDOWN)) {
 216     goto bad_area;
 217   }
 218   if(vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur) {
 219     goto bad_area;
 220   }
 221 
 222   vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
 223   vma->vm_start = (address & PAGE_MASK);
 224 
 225 /*
 226  * Ok, we have a good vm_area for this memory access, so
 227  * we can handle it..
 228  */
 229 good_area:
 230 #ifdef DEBUG_SPARC_DATA_ACCESS_FAULT 
 231   printk("Found good_area\n");
 232 #endif
 233   if((sync_err_reg & SUN4C_SYNC_BADWRITE) &&
 234      (sync_err_reg & SUN4C_SYNC_NPRESENT)) {
 235     if(!(vma->vm_flags & VM_WRITE)) {
 236 #ifdef DEBUG_SPARC_DATA_ACCESS_FAULT 
 237       printk("oops, vma not writable\n");
 238 #endif
 239       goto bad_area;
 240     }
 241   } else {
 242     if(sync_err_reg & SUN4C_SYNC_PROT) {
 243 #ifdef DEBUG_SPARC_DATA_ACCESS_FAULT 
 244       printk("PROT violation\n");
 245 #endif
 246       goto bad_area;
 247     }
 248     if(!(vma->vm_flags & (VM_READ | VM_EXEC))) {
 249 #ifdef DEBUG_SPARC_DATA_ACCESS_FAULT 
 250       printk("vma not readable nor executable\n");
 251 #endif
 252       goto bad_area;
 253     }
 254   }
 255 
 256   if(sync_err_reg & SUN4C_SYNC_BADWRITE)
 257     error_code = 0x2;
 258   else
 259     error_code = 0x0;
 260 
 261 #ifdef DEBUG_SPARC_DATA_ACCESS_FAULT 
 262   printk("calling handle_mm_fault vma=%08lx addr=%08lx code=%d\n",
 263          (unsigned long) vma, (unsigned long) address,
 264          (int) error_code);
 265 #endif
 266   handle_mm_fault(vma, address, error_code);
 267   return;
 268 
 269 /*
 270  * Something tried to access memory that isn't in our memory map..
 271  * Fix it, but check if it's kernel or user first..
 272  */
 273 bad_area:
 274   if (wp_works_ok < 0 && address == 0x0) {
 275           wp_works_ok = 1;
 276           pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_SHARED));
 277           put_pte((unsigned long) 0x0, pg0[0]);
 278           printk("This Sparc honours the WP bit even when in supervisor mode. Good.\n");
 279           return;
 280   }
 281 
 282   if((unsigned long) address < PAGE_SIZE) {
 283     printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
 284   } else
 285     printk(KERN_ALERT "Unable to handle kernel paging request");
 286   printk(" at virtual address %08lx\n",address);
 287   printk(KERN_ALERT "current->tss.pgd_ptr = %08lx\n",
 288          (unsigned long) current->tss.pgd_ptr);
 289   halt();
 290 }
 291 
 292 /* Dump the contents of the SRMMU fsr in a human readable format. */
 293 void
 294 dump_srmmu_fsr(unsigned long fsr)
     /* [previous][next][first][last][top][bottom][index][help] */
 295 {
 296         unsigned long ebe, l, at, ft, fav, ow;
 297 
 298         ebe = (fsr&SRMMU_FSR_EBE_MASK)>>10;
 299         l = (fsr&SRMMU_FSR_L_MASK)>>8;
 300         at = (fsr&SRMMU_FSR_AT_MASK)>>5;
 301         ft = (fsr&SRMMU_FSR_FT_MASK)>>2;
 302         fav = (fsr&SRMMU_FSR_FAV_MASK)>>1;
 303         ow = (fsr&SRMMU_FSR_OW_MASK);
 304 
 305         printk("FSR %08lx: ", fsr);
 306 
 307         /* Ugh, the ebe is arch-dep, have to find out the meanings. */
 308         printk("EBE<%s> ", (ebe == 0 ? "none" : (ebe == 1 ? "bus err" :
 309                                                  (ebe == 2 ? "bus timeout" :
 310                                                   (ebe == 4 ? "uncorrectable err" :
 311                                                    (ebe == 8 ? "undefined err" :
 312                                                     (ebe == 16 ? "parity err" :
 313                                                      (ebe == 24 ? "tsunami parity err" :
 314                                                       (ebe == 32 ? "store buf err" :
 315                                                        (ebe == 64 ? "control space err" :
 316                                                         "VIKING emergency response team"))))))))));
 317         printk("L<%s> ", (l == 0 ? "context table" : (l == 1 ? "level1" :
 318                                                       (l == 2 ? "level2" :
 319                                                        "level3"))));
 320         printk("AT<%s> ", (at == 0 ? "user load" :
 321                            (at == 1 ? "priv load" :
 322                             (at == 2 ? "user rd/exec" :
 323                              (at == 3 ? "priv rd/exec" :
 324                               (at == 4 ? "user store data" :
 325                                (at == 5 ? "priv store data" :
 326                                 (at == 6 ? "user store inst" :
 327                                  "priv store inst"))))))));
 328 
 329         printk("FT<%s> ", (ft == 0 ? "none" :
 330                            (ft == 1 ? "invalid address" :
 331                             (ft == 2 ? "prot violation" :
 332                              (ft == 3 ? "priv violation" :
 333                               (ft == 4 ? "translation error" :
 334                                (ft == 5 ? "bus acc error" :
 335                                 (ft == 6 ? "internal error" :
 336                                  "reserved"))))))));
 337 
 338         printk("FAV<%s> ", (fav == 0 ? "faddr invalid" : "faddr valid"));
 339         printk("OW<%s>\n", (ow == 0 ? "fsr not overwritten" : "fsr overwritten"));
 340 
 341         return;
 342 }
 343 
 344 /* #define DEBUG_SRMMU_TEXT_ACCESS_FAULT */
 345 
 346 void
 347 really_bad_srmmu_fault(int type, unsigned long fstatus, unsigned long faddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 348 {
 349         /* Learn how to handle these later... */
 350         printk("REALLY BAD SRMMU FAULT DETECTED\n");
 351         printk("Bailing out...\n");
 352         dump_srmmu_fsr(fstatus);
 353         prom_halt();
 354         return;
 355 }
 356 
 357 asmlinkage void srmmu_text_access_fault(int type, unsigned long fstatus,
     /* [previous][next][first][last][top][bottom][index][help] */
 358                                         unsigned long faddr,
 359                                         unsigned long pc, unsigned long psr,
 360                                         struct pt_regs *regs)
 361 {
 362   struct vm_area_struct *vma;
 363   unsigned long address;
 364 
 365   /* Check for external bus errors and uncorrectable errors */
 366   if(fstatus&SRMMU_FSR_EBE_MASK)
 367           printk("External Bus Error detected during a text fault.\n");
 368 
 369   /* Check for multiple faults... */
 370   if(fstatus&SRMMU_FSR_OW_MASK && (fstatus&SRMMU_FSR_FT_TRANS)) {
 371           printk("Multiple faults detected in text fault handler\n");
 372           printk("Fault number one: Text fault at addr %08lx", faddr);
 373           printk("Fault number two: Translation Error\n");
 374           printk("Giving up...\n");
 375           prom_halt();
 376   }
 377           
 378   if(fstatus&(SRMMU_FSR_EBE_BERR | SRMMU_FSR_EBE_BTIMEO | SRMMU_FSR_EBE_UNCOR))
 379           really_bad_srmmu_fault(type, fstatus, faddr);
 380 
 381   /* Ok, we should be able to handle it at this point. */
 382 
 383   address = faddr;
 384 #ifdef DEBUG_SRMMU_TEXT_ACCESS_FAULT
 385   printk("Text FAULT: address = %08lx  code = %08lx\n",
 386          (unsigned long) address, (unsigned long) fstatus);
 387   printk("PC = %08lx\n", (unsigned long) regs->pc);
 388   dump_srmmu_fsr(fstatus);
 389   halt();
 390 #endif
 391 
 392   /* Ugh, how often does this happen? ;-( */
 393   if(!(fstatus&SRMMU_FSR_FAV_MASK)) {
 394           printk("Fault address register is INVALID!  Since this is a text\n");
 395           printk("fault I'll use the value of the trapped PC instead...\n");
 396           address = regs->pc;
 397   }
 398 
 399   /* Ugh, I don't wanna know... */
 400 
 401   vma = find_vma(current, address);
 402   if(!vma) {
 403     goto bad_area;
 404   }
 405   if(vma->vm_start <= address)
 406     goto good_area;
 407   goto bad_area;
 408 
 409 /*
 410  * Ok, we have a good vm_area for this memory access, so
 411  * we can handle it..
 412  */
 413 good_area:
 414   do_no_page(vma, address, 0);
 415   return;
 416 
 417 /*
 418  * Something tried to access memory that isn't in our memory map..
 419  * Fix it, but check if it's kernel or user first..
 420  */
 421 bad_area:
 422   if((unsigned long) address < PAGE_SIZE) {
 423     printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
 424   } else
 425     printk(KERN_ALERT "Unable to handle kernel paging request");
 426   printk(" at virtual address %08lx\n",address);
 427   printk(KERN_ALERT "current->tss.pgd_ptr = %08lx\n",
 428          (unsigned long) current->tss.pgd_ptr);
 429   halt();
 430 }
 431 
 432 /* #define DEBUG_SRMMU_DATA_ACCESS_FAULT */
 433 
 434 asmlinkage void srmmu_data_access_fault(int type, unsigned long fstatus,
     /* [previous][next][first][last][top][bottom][index][help] */
 435                                         unsigned long faddr,
 436                                         unsigned long afstatus,
 437                                         unsigned long afaddr,
 438                                         struct pt_regs *regs)
 439 {
 440   struct vm_area_struct *vma;
 441   unsigned long address, pc, psr;
 442   int error_code;
 443 
 444   pc = regs->pc;
 445   psr= regs->psr;
 446   address = faddr;
 447 #ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT 
 448   printk("Data FAULT: address = %08lx  code = %08lx\n",
 449          (unsigned long) address, (unsigned long) fstatus);
 450   printk("PC = %08lx\n", (unsigned long) pc);
 451   printk("afsr = %08lx afaddr = %08lx\n", afstatus, afaddr);
 452   dump_srmmu_fsr(fstatus);
 453 #endif
 454 
 455   /* I figure if I make the panic's look like they came from SunOS or Solaris
 456    * my life will be a lot easier ;-)
 457    */
 458   if(!(fstatus&SRMMU_FSR_FAV_MASK)) {
 459           dump_srmmu_fsr(fstatus);
 460           panic("hat_pteload: Fault address is invalid on a data fault, I'm confused...\n");
 461   }
 462 
 463 #if 0 /* I see this all the time on supersparcs ;-( */
 464   if(fstatus&SRMMU_FSR_OW_MASK) {
 465           dump_srmmu_fsr(fstatus);
 466           panic("hat_pteload: Multiple faults at once, giving up...\n");
 467   }
 468 #endif
 469 
 470   vma = find_vma(current, address);
 471   if(!vma) {
 472 #ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT 
 473     printk("NULL VMA\n");
 474 #endif
 475     goto bad_area;
 476   }
 477   if(vma->vm_start <= address)
 478     goto good_area;
 479 
 480   if(!(vma->vm_flags & VM_GROWSDOWN)) {
 481     goto bad_area;
 482   }
 483   if(vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur) {
 484     goto bad_area;
 485   }
 486 
 487   vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
 488   vma->vm_start = (address & PAGE_MASK);
 489 
 490 /*
 491  * Ok, we have a good vm_area for this memory access, so
 492  * we can handle it..
 493  */
 494 good_area:
 495 #ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT 
 496   printk("Found good_area\n");
 497 #endif
 498   if((fstatus & SUN4C_SYNC_BADWRITE) &&
 499      (fstatus & SUN4C_SYNC_NPRESENT)) {
 500     if(!(vma->vm_flags & VM_WRITE)) {
 501 #ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT 
 502       printk("oops, vma not writable\n");
 503 #endif
 504       goto bad_area;
 505     }
 506   } else {
 507     if(fstatus & SUN4C_SYNC_PROT) {
 508 #ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT 
 509       printk("PROT violation\n");
 510 #endif
 511       goto bad_area;
 512     }
 513     if(!(vma->vm_flags & (VM_READ | VM_EXEC))) {
 514 #ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT 
 515       printk("vma not readable nor executable\n");
 516 #endif
 517       goto bad_area;
 518     }
 519   }
 520 
 521   if(fstatus & SUN4C_SYNC_BADWRITE)
 522     error_code = 0x2;
 523   else
 524     error_code = 0x0;
 525 
 526 #ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT 
 527   printk("calling do_no_page vma=%08lx addr=%08lx code=%d\n",
 528          (unsigned long) vma, (unsigned long) address,
 529          (int) error_code);
 530 #endif
 531   do_no_page(vma, address, error_code);
 532   return;
 533 
 534 /*
 535  * Something tried to access memory that isn't in our memory map..
 536  * Fix it, but check if it's kernel or user first..
 537  */
 538 bad_area:
 539   if (wp_works_ok < 0 && address == 0x0) {
 540           wp_works_ok = 1;
 541           /* Advance the PC and NPC over the test store. */
 542           regs->pc = regs->npc;
 543           regs->npc += 4;
 544           printk("This Sparc honours the WP bit even when in supervisor mode. Good.\n");
 545           return;
 546   }
 547 
 548   if((unsigned long) address < PAGE_SIZE) {
 549     printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
 550   } else
 551     printk(KERN_ALERT "Unable to handle kernel paging request");
 552   printk(" at virtual address %08lx\n",address);
 553   printk(KERN_ALERT "current->tss.pgd_ptr = %08lx\n",
 554          (unsigned long) current->tss.pgd_ptr);
 555   halt();
 556 }

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