Port-powerpc archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Someone needs to fix pagefault handling



Martin Husemann wrote:

> Unfortunately the ppc code is arranged slightly different than other
> architectures, and additionally I don't know which exception/machine check
> this case affects, I need a volunteer to try, fix, and commit this.

As nobody else did it, I volunteer for OEA. Unfortunately I have no Book-E
or IBM4xx hardware to test (besides a Sam440ep, which still doesn't run
NetBSD).

There are three cases in trap.c where uvm_fault() is handled:
- supervisor (kernel) data access exception
- user data access exception
- user instruction access exception

I implemented it now for user data and instruction accesses, as I understand
you that SIGBUS is only needed for userland and not for the kernel.

The following patch was successfully tested on NetBSD/sandpoint (Kurobox,
PPC 8241):

Index: trap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/powerpc/powerpc/trap.c,v
retrieving revision 1.150
diff -u -r1.150 trap.c
--- trap.c	12 Aug 2014 20:27:10 -0000	1.150
+++ trap.c	15 Mar 2015 00:50:16 -0000
@@ -262,18 +262,29 @@
 			    tf->tf_dar, tf->tf_srr0, tf->tf_dsisr, rv);
 		}
 		KSI_INIT_TRAP(&ksi);
-		ksi.ksi_signo = SIGSEGV;
 		ksi.ksi_trap = EXC_DSI;
 		ksi.ksi_addr = (void *)tf->tf_dar;
-		ksi.ksi_code =
-		    (tf->tf_dsisr & DSISR_PROTECT ? SEGV_ACCERR : SEGV_MAPERR);
-		if (rv == ENOMEM) {
+		switch (rv) {
+		case ENOMEM:
 			printf("UVM: pid %d.%d (%s), uid %d killed: "
 			       "out of swap\n",
 			       p->p_pid, l->l_lid, p->p_comm,
 			       l->l_cred ?
 			       kauth_cred_geteuid(l->l_cred) : -1);
 			ksi.ksi_signo = SIGKILL;
+			break;
+		case EINVAL:
+			ksi.ksi_signo = SIGBUS;
+			ksi.ksi_code = BUS_ADRERR;
+			break;
+		case EACCES:
+			ksi.ksi_signo = SIGSEGV;
+			ksi.ksi_code = SEGV_ACCERR;
+			break;
+		default:
+			ksi.ksi_signo = SIGSEGV;
+			ksi.ksi_code = SEGV_MAPERR;
+			break;
 		}
 		(*p->p_emul->e_trapsignal)(l, &ksi);
 		break;
@@ -323,10 +334,30 @@
 			    tf->tf_srr0, tf->tf_srr1);
 		}
 		KSI_INIT_TRAP(&ksi);
-		ksi.ksi_signo = SIGSEGV;
 		ksi.ksi_trap = EXC_ISI;
 		ksi.ksi_addr = (void *)tf->tf_srr0;
-		ksi.ksi_code = (rv == EACCES ? SEGV_ACCERR : SEGV_MAPERR);
+		switch (rv) {
+		case ENOMEM:
+			printf("UVM: pid %d.%d (%s), uid %d killed: "
+			       "out of swap\n",
+			       p->p_pid, l->l_lid, p->p_comm,
+			       l->l_cred ?
+			       kauth_cred_geteuid(l->l_cred) : -1);
+			ksi.ksi_signo = SIGKILL;
+			break;
+		case EINVAL:
+			ksi.ksi_signo = SIGBUS;
+			ksi.ksi_code = BUS_ADRERR;
+			break;
+		case EACCES:
+			ksi.ksi_signo = SIGSEGV;
+			ksi.ksi_code = SEGV_ACCERR;
+			break;
+		default:
+			ksi.ksi_signo = SIGSEGV;
+			ksi.ksi_code = SEGV_MAPERR;
+			break;
+		}
 		(*p->p_emul->e_trapsignal)(l, &ksi);
 		break;


The test case is now behaving correctly and the system seems stable:

t_mmap (1/1): 9 test cases
    mmap_block: [0.129855s] Skipped: The test case causes a panic (PR kern/38889, kern/46592)
    mmap_err: [0.048220s] Passed.
    mmap_loan: [0.108480s] Passed.
    mmap_prot_1: [0.090278s] Passed.
    mmap_prot_2: [0.054191s] Passed.
    mmap_prot_3: [0.097406s] Passed.
    mmap_truncate: [0.092032s] Passed.
    mmap_truncate_signal: [0.098320s] Passed.
    mmap_va0: [0.048243s] Passed.
[0.825004s]

Summary for 1 test programs:
    8 passed test cases.
    0 failed test cases.
    0 expected failed test cases.
    1 skipped test cases.

-- 
Frank Wille


Home | Main Index | Thread Index | Old Index