Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142540934
D21566.id61875.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D21566.id61875.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D21566: Improve MD page fault handlers.
Attached
Detach File
Event Timeline
Log In to Comment