Index: sys/amd64/amd64/trap.c =================================================================== --- sys/amd64/amd64/trap.c +++ sys/amd64/amd64/trap.c @@ -111,7 +111,7 @@ void trap_check(struct trapframe *frame); void dblfault_handler(struct trapframe *frame); -static int trap_pfault(struct trapframe *, int); +static int trap_pfault(struct trapframe *, bool, int *, int *); static void trap_fatal(struct trapframe *, vm_offset_t); #ifdef KDTRACE_HOOKS static bool trap_user_dtrace(struct trapframe *, @@ -352,40 +352,11 @@ return; addr = frame->tf_addr; - signo = trap_pfault(frame, TRUE); + trap_pfault(frame, true, &signo, &ucode); if (signo == -1) return; if (signo == 0) goto userret; - if (signo == SIGSEGV) { - ucode = SEGV_MAPERR; - } else if (prot_fault_translation == 0) { - /* - * Autodetect. This check also covers - * the images without the ABI-tag ELF - * note. - */ - if (SV_CURPROC_ABI() == SV_ABI_FREEBSD && - p->p_osrel >= P_OSREL_SIGSEGV) { - signo = SIGSEGV; - ucode = SEGV_ACCERR; - } else { - signo = SIGBUS; - ucode = T_PAGEFLT; - } - } else if (prot_fault_translation == 1) { - /* - * Always compat mode. - */ - signo = SIGBUS; - ucode = T_PAGEFLT; - } else { - /* - * Always SIGSEGV mode. - */ - signo = SIGSEGV; - ucode = SEGV_ACCERR; - } break; case T_DIVIDE: /* integer divide fault */ @@ -440,7 +411,7 @@ ("kernel trap doesn't have ucred")); switch (type) { case T_PAGEFLT: /* page fault */ - (void) trap_pfault(frame, FALSE); + (void) trap_pfault(frame, false, NULL, NULL); return; case T_DNA: @@ -713,7 +684,7 @@ } static int -trap_pfault(struct trapframe *frame, int usermode) +trap_pfault(struct trapframe *frame, bool usermode, int *signo, int *ucode) { struct thread *td; struct proc *p; @@ -776,8 +747,11 @@ /* * Don't allow user-mode faults in kernel address space. */ - if (usermode) - return (SIGSEGV); + if (usermode) { + *signo = SIGSEGV; + *ucode = SEGV_ACCERR; + return (1); + } map = kernel_map; } else { @@ -868,7 +842,40 @@ trap_fatal(frame, eva); return (-1); } - return ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV); + + if (rv == KERN_FAILURE) { + *signo = SIGSEGV; + *ucode = SEGV_MAPERR; + } else if (rv == KERN_RESOURCE_SHORTAGE) { + *signo = SIGBUS; + *ucode = BUS_ADRERR; /* XXX any better choice ? */ + } else if (rv == KERN_INVALID_ADDRESS) { + *signo = SIGBUS; + *ucode = BUS_OBJERR; + } else if (prot_fault_translation == 0) { + /* + * Autodetect. This check also covers + * the images without the ABI-tag ELF + * note. + */ + if (SV_CURPROC_ABI() == SV_ABI_FREEBSD && + p->p_osrel >= P_OSREL_SIGSEGV) { + *signo = SIGSEGV; + *ucode = SEGV_ACCERR; + } else { + *signo = SIGBUS; + *ucode = T_PAGEFLT; + } + } else if (prot_fault_translation == 1) { + /* Always compat mode. */ + *signo = SIGBUS; + *ucode = T_PAGEFLT; + } else { + /* Always SIGSEGV mode. */ + *signo = SIGSEGV; + *ucode = SEGV_ACCERR; + } + return (1); } static void Index: sys/vm/vm_fault.c =================================================================== --- sys/vm/vm_fault.c +++ sys/vm/vm_fault.c @@ -562,6 +562,11 @@ #endif result = vm_fault_hold(map, trunc_page(vaddr), fault_type, fault_flags, NULL); + KASSERT(result == KERN_SUCCESS || result == KERN_FAILURE || + result == KERN_INVALID_ADDRESS || + result == KERN_RESOURCE_SHORTAGE || + result == KERN_PROTECTION_FAILURE, + ("Unknown Mach error %d from vm_fault_hold()", result)); #ifdef KTRACE if (map != kernel_map && KTRPOINT(td, KTR_FAULTEND)) ktrfaultend(result); @@ -787,7 +792,7 @@ fs.object == fs.first_object) { if (fs.pindex >= fs.object->size) { unlock_and_deallocate(&fs); - return (KERN_PROTECTION_FAILURE); + return (KERN_INVALID_ADDRESS); } if (fs.object == fs.first_object &&