OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [armnommu/] [mm/] [fault-armv.c] - Diff between revs 1765 and 1782

Only display areas with differences | Details | Blame | View Log

Rev 1765 Rev 1782
/*
/*
 *  linux/arch/arm/mm/fault.c
 *  linux/arch/arm/mm/fault.c
 *
 *
 *  Copyright (C) 1995  Linus Torvalds
 *  Copyright (C) 1995  Linus Torvalds
 *  Modifications for ARM processor (c) 1995, 1996 Russell King
 *  Modifications for ARM processor (c) 1995, 1996 Russell King
 */
 */
 
 
#include <linux/signal.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/head.h>
#include <linux/head.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/mm.h>
 
 
#include <asm/system.h>
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/segment.h>
#include <asm/pgtable.h>
#include <asm/pgtable.h>
 
 
#define FAULT_CODE_READ         0x02
#define FAULT_CODE_READ         0x02
#define FAULT_CODE_USER         0x01
#define FAULT_CODE_USER         0x01
 
 
extern void die_if_kernel(char *msg, struct pt_regs *regs, unsigned int err, unsigned int ret);
extern void die_if_kernel(char *msg, struct pt_regs *regs, unsigned int err, unsigned int ret);
 
 
static void kernel_page_fault (unsigned long addr, int mode, struct pt_regs *regs,
static void kernel_page_fault (unsigned long addr, int mode, struct pt_regs *regs,
                               struct task_struct *tsk, struct mm_struct *mm)
                               struct task_struct *tsk, struct mm_struct *mm)
{
{
        /*
        /*
         * Oops. The kernel tried to access some bad page. We'll have to
         * Oops. The kernel tried to access some bad page. We'll have to
         * terminate things with extreme prejudice.
         * terminate things with extreme prejudice.
         */
         */
        if (addr < PAGE_SIZE)
        if (addr < PAGE_SIZE)
            printk (KERN_ALERT "Unable to handle kernel NULL pointer dereference");
            printk (KERN_ALERT "Unable to handle kernel NULL pointer dereference");
        else
        else
            printk (KERN_ALERT "Unable to handle kernel paging request");
            printk (KERN_ALERT "Unable to handle kernel paging request");
        printk (" at virtual address %08lx\n", addr);
        printk (" at virtual address %08lx\n", addr);
        die_if_kernel ("Oops", regs, mode, SIGKILL);
        die_if_kernel ("Oops", regs, mode, SIGKILL);
        do_exit (SIGKILL);
        do_exit (SIGKILL);
}
}
 
 
static void page_fault (unsigned long addr, int mode, struct pt_regs *regs)
static void page_fault (unsigned long addr, int mode, struct pt_regs *regs)
{
{
        struct task_struct *tsk = current;
        struct task_struct *tsk = current;
        struct mm_struct *mm = tsk->mm;
        struct mm_struct *mm = tsk->mm;
        struct vm_area_struct *vma;
        struct vm_area_struct *vma;
 
 
        if (mode & FAULT_CODE_USER) {
        if (mode & FAULT_CODE_USER) {
                tsk->tss.error_code = mode;
                tsk->tss.error_code = mode;
                tsk->tss.trap_no = 14;
                tsk->tss.trap_no = 14;
                printk ("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n",
                printk ("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n",
                        tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode);
                        tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode);
#ifdef DEBUG
#ifdef DEBUG
                show_regs (regs);
                show_regs (regs);
                c_backtrace (regs->ARM_fp, regs->ARM_cpsr);
                c_backtrace (regs->ARM_fp, regs->ARM_cpsr);
#endif
#endif
                force_sig(SIGSEGV, tsk);
                force_sig(SIGSEGV, tsk);
                return;
                return;
        }
        }
 
 
        kernel_page_fault (addr, mode, regs, tsk, mm);
        kernel_page_fault (addr, mode, regs, tsk, mm);
}
}
 
 
/*
/*
 * Handle a data abort.  Note that we have to handle a range of addresses
 * Handle a data abort.  Note that we have to handle a range of addresses
 * on ARM2/3 for ldm.  If both pages are zero-mapped, then we have to force
 * on ARM2/3 for ldm.  If both pages are zero-mapped, then we have to force
 * a copy-on-write
 * a copy-on-write
 */
 */
asmlinkage void
asmlinkage void
do_DataAbort (unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
do_DataAbort (unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
{
{
        if (user_mode(regs))
        if (user_mode(regs))
                error_code |= FAULT_CODE_USER;
                error_code |= FAULT_CODE_USER;
 
 
#define DIE(signr,nam)\
#define DIE(signr,nam)\
                force_sig(signr, current);\
                force_sig(signr, current);\
                die_if_kernel(nam, regs, fsr, signr);\
                die_if_kernel(nam, regs, fsr, signr);\
                break;
                break;
 
 
        switch (fsr & 15) {
        switch (fsr & 15) {
        case 2:
        case 2:
                DIE(SIGKILL, "Terminal exception")
                DIE(SIGKILL, "Terminal exception")
        case 0:
        case 0:
                DIE(SIGSEGV, "Vector exception")
                DIE(SIGSEGV, "Vector exception")
        case 1:
        case 1:
        case 3:
        case 3:
                DIE(SIGBUS, "Alignment exception")
                DIE(SIGBUS, "Alignment exception")
        case 12:
        case 12:
        case 14:
        case 14:
                DIE(SIGBUS, "External abort on translation")
                DIE(SIGBUS, "External abort on translation")
        case 9:
        case 9:
        case 11:
        case 11:
                DIE(SIGSEGV, "Domain fault")
                DIE(SIGSEGV, "Domain fault")
        case 13:/* permission fault on section */
        case 13:/* permission fault on section */
#ifndef DEBUG
#ifndef DEBUG
                show_regs(regs);
                show_regs(regs);
                {
                {
                        unsigned int i, j, a;
                        unsigned int i, j, a;
                        a = regs->ARM_sp;
                        a = regs->ARM_sp;
                        for (j = 0; j < 10; j++) {
                        for (j = 0; j < 10; j++) {
                                printk ("%08x: ", a);
                                printk ("%08x: ", a);
                                for (i = 0; i < 8; i += 1, a += 4)
                                for (i = 0; i < 8; i += 1, a += 4)
                                        printk ("%08lx ", *(unsigned long *)a);
                                        printk ("%08lx ", *(unsigned long *)a);
                                printk ("\n");
                                printk ("\n");
                        }
                        }
                }
                }
#endif
#endif
                DIE(SIGSEGV, "Permission fault")
                DIE(SIGSEGV, "Permission fault")
 
 
        case 15:/* permission fault on page */
        case 15:/* permission fault on page */
        case 5: /* page-table entry descriptor fault */
        case 5: /* page-table entry descriptor fault */
        case 7: /* first-level descriptor fault */
        case 7: /* first-level descriptor fault */
                page_fault (addr, error_code, regs);
                page_fault (addr, error_code, regs);
                break;
                break;
        case 4:
        case 4:
        case 6:
        case 6:
                DIE(SIGBUS, "External abort on linefetch")
                DIE(SIGBUS, "External abort on linefetch")
        case 8:
        case 8:
        case 10:
        case 10:
                DIE(SIGBUS, "External abort on non-linefetch")
                DIE(SIGBUS, "External abort on non-linefetch")
        }
        }
}
}
 
 
asmlinkage int
asmlinkage int
do_PrefetchAbort (unsigned long addr, struct pt_regs *regs)
do_PrefetchAbort (unsigned long addr, struct pt_regs *regs)
{
{
#if 0
#if 0
        /* does this still apply ? */
        /* does this still apply ? */
        if (the memc mapping for this page exists - can check now...) {
        if (the memc mapping for this page exists - can check now...) {
                printk ("Page in, but got abort (undefined instruction?)\n");
                printk ("Page in, but got abort (undefined instruction?)\n");
                return 0;
                return 0;
        }
        }
#endif
#endif
        page_fault (addr, FAULT_CODE_USER|FAULT_CODE_READ, regs);
        page_fault (addr, FAULT_CODE_USER|FAULT_CODE_READ, regs);
        return 1;
        return 1;
}
}
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.