patch-2.4.21 linux-2.4.21/arch/x86_64/mm/fault.c

Next file: linux-2.4.21/arch/x86_64/mm/init.c
Previous file: linux-2.4.21/arch/x86_64/lib/usercopy.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.20/arch/x86_64/mm/fault.c linux-2.4.21/arch/x86_64/mm/fault.c
@@ -30,9 +30,6 @@
 #include <asm/proto.h>
 #include <asm/kdebug.h>
 
-spinlock_t pcrash_lock; 
-int crashing_cpu;
-
 extern spinlock_t console_lock, timerlist_lock;
 
 void bust_spinlocks(int yes)
@@ -60,29 +57,41 @@
 	}
 }
 
+static int bad_address(void *p) 
+{ 
+	unsigned long dummy;
+	return __get_user(dummy, (unsigned long *)p);
+} 
+
 void dump_pagetable(unsigned long address)
 {
-	static char *name[] = { "PML4", "PGD", "PDE", "PTE" }; 
-	int i, shift;
-	unsigned long page;
-
-	shift = 9+9+9+12;
-	address &= ~0xFFFF000000000000UL;
-	asm("movq %%cr3,%0" : "=r" (page)); 
-	for (i = 0; i < 4; i++) { 	
-		unsigned long *padr = (unsigned long *) __va(page); 
-		padr += (address >> shift) & 0x1FFU;
-		if (__get_user(page, padr)) { 
-			printk("%s: bad %p\n", name[i], padr); 
-			break;
-		}
-		printk("%s: %016lx ", name[i], page); 
-		if ((page & (1 | (1<<7))) != 1) /* Not present or 2MB page */
-			break;
-		page &= ~0xFFFUL;
-		shift -= (i == 0) ? 12 : 9;
-	} 
+	pml4_t *pml4;
+	asm("movq %%cr3,%0" : "=r" (pml4));
+
+	pml4 = __va((unsigned long)pml4 & PHYSICAL_PAGE_MASK); 
+	pml4 += pml4_index(address);
+	printk("PML4 %lx ", pml4_val(*pml4));
+	if (bad_address(pml4)) goto bad;
+	if (!pml4_present(*pml4)) goto ret; 
+
+	pgd_t *pgd = __pgd_offset_k((pgd_t *)pml4_page(*pml4), address); 
+	if (bad_address(pgd)) goto bad;
+	printk("PGD %lx ", pgd_val(*pgd)); 
+	if (!pgd_present(*pgd))	goto ret;
+
+	pmd_t *pmd = pmd_offset(pgd, address); 
+	if (bad_address(pmd)) goto bad;
+	printk("PMD %lx ", pmd_val(*pmd));
+	if (!pmd_present(*pmd))	goto ret;	 
+
+	pte_t *pte = pte_offset(pmd, address);
+	if (bad_address(pte)) goto bad;
+	printk("PTE %lx", pte_val(*pte)); 
+ret:
 	printk("\n");
+	return;
+bad:
+	printk("BAD\n");
 }
 
 int page_fault_trace; 
@@ -112,15 +121,18 @@
 	/* get the address */
 	__asm__("movq %%cr2,%0":"=r" (address));
 
+	if (regs->eflags & X86_EFLAGS_IF)
+		__sti();
+
 #ifdef CONFIG_CHECKING
 	if (page_fault_trace) 
-		printk("pfault %d rip:%lx rsp:%lx cs:%lu ss:%lu addr %lx error %lx\n",
-		       stack_smp_processor_id(), regs->rip,regs->rsp,regs->cs,
-			   regs->ss,address,error_code); 
+		printk("pagefault rip:%lx rsp:%lx cs:%lu ss:%lu address %lx error %lx\n",
+		       regs->rip,regs->rsp,regs->cs,regs->ss,address,error_code); 
+
 
 	{ 
 		unsigned long gs; 
-		struct x8664_pda *pda = cpu_pda + stack_smp_processor_id(); 
+		struct x8664_pda *pda = cpu_pda + safe_smp_processor_id(); 
 		rdmsrl(MSR_GS_BASE, gs); 
 		if (gs != (unsigned long)pda) { 
 			wrmsrl(MSR_GS_BASE, pda); 
@@ -217,14 +229,11 @@
 
 	/* User mode accesses just cause a SIGSEGV */
 	if (error_code & 4) {
-		if (exception_trace) {
-#if 1
-			dump_pagetable(address);
-#endif	
+		if (exception_trace) 
 			printk("%s[%d]: segfault at %016lx rip %016lx rsp %016lx error %lx\n",
 					current->comm, current->pid, address, regs->rip,
 					regs->rsp, error_code);
-		}
+	
 		tsk->thread.cr2 = address;
 		tsk->thread.error_code = error_code;
 		tsk->thread.trap_no = 14;
@@ -256,14 +265,6 @@
 	console_verbose();
 	bust_spinlocks(1); 
 
-	if (!in_interrupt()) { 
-		if (!spin_trylock(&pcrash_lock)) { 
-			if (crashing_cpu != smp_processor_id()) 
-				spin_lock(&pcrash_lock);  		    
-		} 
-		crashing_cpu = smp_processor_id();
-	} 
-
 	if (address < PAGE_SIZE)
 		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
 	else
@@ -272,14 +273,7 @@
 	printk(" printing rip:\n");
 	printk("%016lx\n", regs->rip);
 	dump_pagetable(address);
-
 	die("Oops", regs, error_code);
-
-	if (!in_interrupt()) { 
-		crashing_cpu = -1;  /* small harmless window */ 
-		spin_unlock(&pcrash_lock);
-	}
-
 	bust_spinlocks(0); 
 	do_exit(SIGKILL);
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)