Page MenuHomeFreeBSD

D21566.id61875.diff
No OneTemporary

D21566.id61875.diff

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 *,
@@ -155,10 +155,6 @@
[T_DTRACE_RET] = "DTrace pid return trap",
};
-static int prot_fault_translation;
-SYSCTL_INT(_machdep, OID_AUTO, prot_fault_translation, CTLFLAG_RWTUN,
- &prot_fault_translation, 0,
- "Select signal to deliver on protection fault");
static int uprintf_signal;
SYSCTL_INT(_machdep, OID_AUTO, uprintf_signal, CTLFLAG_RWTUN,
&uprintf_signal, 0,
@@ -352,40 +348,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 +407,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 +680,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 +743,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 {
@@ -843,7 +813,7 @@
ftype = VM_PROT_READ;
/* Fault in the page. */
- rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
+ rv = vm_fault_trap(map, va, ftype, VM_FAULT_NORMAL, signo, ucode);
if (rv == KERN_SUCCESS) {
#ifdef HWPMC_HOOKS
if (ftype == VM_PROT_READ || ftype == VM_PROT_WRITE) {
@@ -858,17 +828,17 @@
#endif
return (0);
}
+
after_vmfault:
- if (!usermode) {
- if (td->td_intr_nesting_level == 0 &&
- curpcb->pcb_onfault != NULL) {
- frame->tf_rip = (long)curpcb->pcb_onfault;
- return (0);
- }
- trap_fatal(frame, eva);
- return (-1);
+ if (usermode)
+ return (1);
+ if (td->td_intr_nesting_level == 0 &&
+ curpcb->pcb_onfault != NULL) {
+ frame->tf_rip = (long)curpcb->pcb_onfault;
+ return (0);
}
- return ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
+ trap_fatal(frame, eva);
+ return (-1);
}
static void
Index: sys/amd64/vmm/vmm.c
===================================================================
--- sys/amd64/vmm/vmm.c
+++ sys/amd64/vmm/vmm.c
@@ -1413,7 +1413,8 @@
}
map = &vm->vmspace->vm_map;
- rv = vm_fault(map, vme->u.paging.gpa, ftype, VM_FAULT_NORMAL);
+ rv = vm_fault_hold(map, vme->u.paging.gpa, ftype, VM_FAULT_NORMAL,
+ NULL);
VCPU_CTR3(vm, vcpuid, "vm_handle_paging rv = %d, gpa = %#lx, "
"ftype = %d", rv, vme->u.paging.gpa, ftype);
Index: sys/i386/i386/trap.c
===================================================================
--- sys/i386/i386/trap.c
+++ sys/i386/i386/trap.c
@@ -114,7 +114,7 @@
void trap(struct trapframe *frame);
void syscall(struct trapframe *frame);
-static int trap_pfault(struct trapframe *, int, vm_offset_t);
+static int trap_pfault(struct trapframe *, bool, vm_offset_t, int *, int *);
static void trap_fatal(struct trapframe *, vm_offset_t);
#ifdef KDTRACE_HOOKS
static bool trap_user_dtrace(struct trapframe *,
@@ -181,9 +181,6 @@
int has_f00f_bug = 0; /* Initialized so that it can be patched. */
#endif
-static int prot_fault_translation = 0;
-SYSCTL_INT(_machdep, OID_AUTO, prot_fault_translation, CTLFLAG_RW,
- &prot_fault_translation, 0, "Select signal to deliver on protection fault");
static int uprintf_signal;
SYSCTL_INT(_machdep, OID_AUTO, uprintf_signal, CTLFLAG_RW,
&uprintf_signal, 0,
@@ -395,7 +392,8 @@
break;
case T_PAGEFLT: /* page fault */
- signo = trap_pfault(frame, TRUE, eva);
+ addr = eva;
+ trap_pfault(frame, true, eva, &signo, &ucode);
#if defined(I586_CPU) && !defined(NO_F00F_HACK)
if (signo == -2) {
/*
@@ -415,37 +413,6 @@
return;
if (signo == 0)
goto user;
-
- 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;
- }
- addr = eva;
break;
case T_DIVIDE: /* integer divide fault */
@@ -517,7 +484,7 @@
("kernel trap doesn't have ucred"));
switch (type) {
case T_PAGEFLT: /* page fault */
- (void) trap_pfault(frame, FALSE, eva);
+ (void) trap_pfault(frame, false, eva, NULL, NULL);
return;
case T_DNA:
@@ -770,7 +737,8 @@
}
static int
-trap_pfault(struct trapframe *frame, int usermode, vm_offset_t eva)
+trap_pfault(struct trapframe *frame, bool usermode, vm_offset_t eva,
+ int *signo, int *ucode)
{
struct thread *td;
struct proc *p;
@@ -878,7 +846,7 @@
ftype = VM_PROT_READ;
/* Fault in the page. */
- rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
+ rv = vm_fault_trap(map, va, ftype, VM_FAULT_NORMAL, signo, ucode);
if (rv == KERN_SUCCESS) {
#ifdef HWPMC_HOOKS
if (ftype == VM_PROT_READ || ftype == VM_PROT_WRITE) {
@@ -893,16 +861,15 @@
#endif
return (0);
}
- if (!usermode) {
- if (td->td_intr_nesting_level == 0 &&
- curpcb->pcb_onfault != NULL) {
- frame->tf_eip = (int)curpcb->pcb_onfault;
- return (0);
- }
- trap_fatal(frame, eva);
- return (-1);
+ if (usermode)
+ return (1);
+ if (td->td_intr_nesting_level == 0 &&
+ curpcb->pcb_onfault != NULL) {
+ frame->tf_eip = (int)curpcb->pcb_onfault;
+ return (0);
}
- return ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
+ trap_fatal(frame, eva);
+ return (-1);
}
static void
Index: sys/vm/vm_extern.h
===================================================================
--- sys/vm/vm_extern.h
+++ sys/vm/vm_extern.h
@@ -85,7 +85,8 @@
int kernacc(void *, int, int);
int useracc(void *, int, int);
-int vm_fault(vm_map_t, vm_offset_t, vm_prot_t, int);
+int vm_fault_trap(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type,
+ int fault_flags, int *signo, int *ucode);
void vm_fault_copy_entry(vm_map_t, vm_map_t, vm_map_entry_t, vm_map_entry_t,
vm_ooffset_t *);
int vm_fault_disable_pagefaults(void);
Index: sys/vm/vm_fault.c
===================================================================
--- sys/vm/vm_fault.c
+++ sys/vm/vm_fault.c
@@ -89,7 +89,9 @@
#include <sys/racct.h>
#include <sys/resourcevar.h>
#include <sys/rwlock.h>
+#include <sys/signalvar.h>
#include <sys/sysctl.h>
+#include <sys/sysent.h>
#include <sys/vmmeter.h>
#include <sys/vnode.h>
#ifdef KTRACE
@@ -529,8 +531,19 @@
return (KERN_SUCCESS);
}
+static int prot_fault_translation;
+SYSCTL_INT(_machdep, OID_AUTO, prot_fault_translation, CTLFLAG_RWTUN,
+ &prot_fault_translation, 0,
+ "Select signal to deliver on protection fault");
+
+/* compat definition to keep common code for signal translation */
+#define UCODE_PAGEFLT 12
+#ifdef T_PAGEFLT
+_Static_assert(UCODE_PAGEFLT == T_PAGEFLT, "T_PAGEFLT");
+#endif
+
/*
- * vm_fault:
+ * vm_fault_trap:
*
* Handle a page fault occurring at the given address,
* requiring the given permissions, in the map specified.
@@ -547,8 +560,8 @@
* Caller may hold no locks.
*/
int
-vm_fault(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type,
- int fault_flags)
+vm_fault_trap(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type,
+ int fault_flags, int *signo, int *ucode)
{
struct thread *td;
int result;
@@ -562,10 +575,49 @@
#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,
+ ("Unexpected Mach error %d from vm_fault_hold()", result));
#ifdef KTRACE
if (map != kernel_map && KTRPOINT(td, KTR_FAULTEND))
ktrfaultend(result);
#endif
+ if (result != KERN_SUCCESS && map != kernel_map) {
+ if (result == KERN_FAILURE) {
+ *signo = SIGSEGV;
+ *ucode = SEGV_MAPERR;
+ } else if (result == KERN_RESOURCE_SHORTAGE) {
+ *signo = SIGBUS;
+ *ucode = BUS_ADRERR; /* XXX any better choice ? */
+ } else if (result == 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 &&
+ curproc->p_osrel >= P_OSREL_SIGSEGV) {
+ *signo = SIGSEGV;
+ *ucode = SEGV_ACCERR;
+ } else {
+ *signo = SIGBUS;
+ *ucode = UCODE_PAGEFLT;
+ }
+ } else if (prot_fault_translation == 1) {
+ /* Always compat mode. */
+ *signo = SIGBUS;
+ *ucode = UCODE_PAGEFLT;
+ } else {
+ /* Always SIGSEGV mode. */
+ *signo = SIGSEGV;
+ *ucode = SEGV_ACCERR;
+ }
+ }
return (result);
}
@@ -787,7 +839,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 &&
Index: sys/vm/vm_map.c
===================================================================
--- sys/vm/vm_map.c
+++ sys/vm/vm_map.c
@@ -3201,8 +3201,9 @@
* Simulate a fault to get the page and enter
* it into the physical map.
*/
- if ((rv = vm_fault(map, faddr, VM_PROT_NONE,
- VM_FAULT_WIRE)) != KERN_SUCCESS)
+ if ((rv = vm_fault_hold(map, faddr,
+ VM_PROT_NONE, VM_FAULT_WIRE, NULL)) !=
+ KERN_SUCCESS)
break;
} while ((faddr += PAGE_SIZE) < saved_end);
vm_map_lock(map);

File Metadata

Mime Type
text/plain
Expires
Wed, Jan 21, 7:17 PM (13 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27817422
Default Alt Text
D21566.id61875.diff (10 KB)

Event Timeline