patch-2.1.51 linux/arch/ppc/mm/fault.c

Next file: linux/arch/ppc/mm/init.c
Previous file: linux/arch/ppc/mm/Makefile
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.50/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c
@@ -1,8 +1,12 @@
 /*
  *  arch/ppc/mm/fault.c
  *
- *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
- *  Ported to PPC by Gary Thomas
+ *  PowerPC version 
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ *  Derived from "arch/i386/mm/fault.c"
+ *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+ *
  *  Modified by Cort Dougan and Paul Mackerras.
  *
  *  This program is free software; you can redistribute it and/or
@@ -26,40 +30,42 @@
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/mmu.h>
 #include <asm/mmu_context.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
 
-#ifdef CONFIG_PMAC
+#ifdef CONFIG_XMON
+extern void xmon(struct pt_regs *);
 extern void (*xmon_fault_handler)(void);
-#endif
-
-/* the linux norm for the function name is show_regs() so
-   make it call dump_regs() on the mac -- Cort */
-#ifdef CONFIG_PMAC 
-#define show_regs dump_regs
+extern int xmon_dabr_match(struct pt_regs *);
+int xmon_kernel_faults;
 #endif
 
 extern void die_if_kernel(char *, struct pt_regs *, long);
 void bad_page_fault(struct pt_regs *, unsigned long);
 void do_page_fault(struct pt_regs *, unsigned long, unsigned long);
-void print_pte(struct _PTE);
 
-void do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long error_code)     
+/*
+ * The error_code parameter is DSISR for a data fault, SRR1 for
+ * an instruction fault.
+ */
+void do_page_fault(struct pt_regs *regs, unsigned long address,
+		   unsigned long error_code)
 {
-	struct task_struct *tsk = current;
-	extern unsigned _end[];
 	struct vm_area_struct * vma;
 	struct mm_struct *mm = current->mm;
-	pgd_t *dir;
-	pmd_t *pmd;
-	pte_t *pte;
-	
-	/*printk("do_page_fault() %s/%d addr %x nip %x regs %x error %x\n",
-	       current->comm,current->pid,address,regs->nip,regs,error_code);*/
-#ifdef CONFIG_PMAC
+
+#ifdef CONFIG_XMON
 	if (xmon_fault_handler && regs->trap == 0x300) {
 		xmon_fault_handler();
 		return;
 	}
+	if (error_code & 0x00400000) {
+		/* DABR match */
+		if (xmon_dabr_match(regs))
+			return;
+	}
 #endif
 	if (in_interrupt()) {
 		static int complained;
@@ -68,14 +74,18 @@
 			printk("page fault in interrupt handler, addr=%lx\n",
 			       address);
 			show_regs(regs);
+#ifdef CONFIG_XMON
+			if (xmon_kernel_faults)
+				xmon(regs);
+#endif
 		}
 	}
-	if (current == NULL)
-		goto bad_area;
-	
-do_page:
+	if (current == NULL) {
+		bad_page_fault(regs, address);
+		return;
+	}
 	down(&mm->mmap_sem);
-	vma = find_vma(tsk->mm, address);
+	vma = find_vma(mm, address);
 	if (!vma)
 		goto bad_area;
 	if (vma->vm_start <= address)
@@ -84,7 +94,7 @@
 		goto bad_area;
 	if (expand_stack(vma, address))
 		goto bad_area;
-  
+
 good_area:
 	if (error_code & 0xb5700000)
 		/* an error such as lwarx to I/O controller space,
@@ -98,67 +108,45 @@
 	/* a read */
 	} else {
 		/* protection fault */
-		if ( error_code & 0x08000000 )
+		if (error_code & 0x08000000)
 			goto bad_area;
 		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
 			goto bad_area;
 	}
 	handle_mm_fault(current, vma, address, error_code & 0x02000000);
-        up(&mm->mmap_sem);
-	/*printk("do_page_fault() return %s/%d addr %x msr %x\n",
-	      current->comm,current->pid,address,regs->msr);*/
-	/* not needed since flush_page_to_ram() works */
-#if 0
-	flush_page(address);
-#endif
+	up(&mm->mmap_sem);
 	return;
-  
+
 bad_area:
-	up(&current->mm->mmap_sem);
+	up(&mm->mmap_sem);
 	bad_page_fault(regs, address);
 }
 
-
 void
 bad_page_fault(struct pt_regs *regs, unsigned long address)
 {
-	extern unsigned int probingmem;
-	struct task_struct *tsk = current;
 	unsigned long fixup;
-	
+
+	if (user_mode(regs)) {
+		force_sig(SIGSEGV, current);
+		return;
+	}
 	
 	/* Are we prepared to handle this fault?  */
 	if ((fixup = search_exception_table(regs->nip)) != 0) {
-		if ( user_mode(regs) )
-			printk("Exception from user mode\n");
-#if 0    
-		printk(KERN_DEBUG "Exception at %lx (%lx)\n", regs->nip, fixup);
-#endif    
 		regs->nip = fixup;
 		return;
 	}
 
-	if ( user_mode(regs) )
-	{
-		force_sig(SIGSEGV, tsk);
-		return;
-	}
-  
-bad_kernel_access:
-	/* make sure it's not a bootup probe test */
-	if ( probingmem )
-	{
-		probingmem = 0;
-		return;
-	}
 	/* kernel has accessed a bad area */
 	show_regs(regs);
-	print_backtrace( regs->gpr[1] );
-#ifdef CONFIG_PMAC
-	xmon(regs);
+	print_backtrace( (unsigned long *)regs->gpr[1] );
+#ifdef CONFIG_XMON
+	if (xmon_kernel_faults)
+		xmon(regs);
 #endif
-	panic("kernel access of bad area\n pc %x address %X tsk %s/%d",
-	      regs->nip,address,tsk->comm,tsk->pid);
+	panic("kernel access of bad area\n pc %lx address %lX tsk %s/%d",
+	      regs->nip,address,current->comm,current->pid);
 }
 
 unsigned long va_to_phys(unsigned long address)
@@ -189,6 +177,10 @@
 	return (0);
 }
 
+#if 0
+/*
+ * Misc debugging functions.  Please leave them here. -- Cort
+ */
 void print_pte(struct _PTE p)
 {
 	printk(
@@ -210,7 +202,8 @@
 	for ( ptr = Hash ; ptr < Hash_end ; ptr++ )
 	{
 		if ( ptr->rpn == (address>>12) )
-			printk("phys %08X -> va ???\n",
+			printk("phys %08lX -> va ???\n",
 			       address);
 	}
 }
+#endif

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov