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