Changeset View
Changeset View
Standalone View
Standalone View
sys/i386/i386/trap.c
Show First 20 Lines • Show All 108 Lines • ▼ Show 20 Lines | |||||
#ifdef KDTRACE_HOOKS | #ifdef KDTRACE_HOOKS | ||||
#include <sys/dtrace_bsd.h> | #include <sys/dtrace_bsd.h> | ||||
#endif | #endif | ||||
void trap(struct trapframe *frame); | void trap(struct trapframe *frame); | ||||
void syscall(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); | static void trap_fatal(struct trapframe *, vm_offset_t); | ||||
#ifdef KDTRACE_HOOKS | #ifdef KDTRACE_HOOKS | ||||
static bool trap_user_dtrace(struct trapframe *, | static bool trap_user_dtrace(struct trapframe *, | ||||
int (**hook)(struct trapframe *)); | int (**hook)(struct trapframe *)); | ||||
#endif | #endif | ||||
void dblfault_handler(void); | void dblfault_handler(void); | ||||
extern inthand_t IDTVEC(bpt), IDTVEC(dbg), IDTVEC(int0x80_syscall); | extern inthand_t IDTVEC(bpt), IDTVEC(dbg), IDTVEC(int0x80_syscall); | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | if (res == NULL) | ||||
res = unkn; | res = unkn; | ||||
return (res); | return (res); | ||||
} | } | ||||
#if defined(I586_CPU) && !defined(NO_F00F_HACK) | #if defined(I586_CPU) && !defined(NO_F00F_HACK) | ||||
int has_f00f_bug = 0; /* Initialized so that it can be patched. */ | int has_f00f_bug = 0; /* Initialized so that it can be patched. */ | ||||
#endif | #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; | static int uprintf_signal; | ||||
SYSCTL_INT(_machdep, OID_AUTO, uprintf_signal, CTLFLAG_RW, | SYSCTL_INT(_machdep, OID_AUTO, uprintf_signal, CTLFLAG_RW, | ||||
&uprintf_signal, 0, | &uprintf_signal, 0, | ||||
"Print debugging information on trap signal to ctty"); | "Print debugging information on trap signal to ctty"); | ||||
/* | /* | ||||
* Exception, fault, and trap interface to the FreeBSD kernel. | * Exception, fault, and trap interface to the FreeBSD kernel. | ||||
* This common code is called from assembly language IDT gate entry | * This common code is called from assembly language IDT gate entry | ||||
▲ Show 20 Lines • Show All 195 Lines • ▼ Show 20 Lines | case T_ALIGNFLT: | ||||
break; | break; | ||||
case T_DOUBLEFLT: /* double fault */ | case T_DOUBLEFLT: /* double fault */ | ||||
default: | default: | ||||
signo = SIGBUS; | signo = SIGBUS; | ||||
ucode = BUS_OBJERR; | ucode = BUS_OBJERR; | ||||
break; | break; | ||||
case T_PAGEFLT: /* page fault */ | case T_PAGEFLT: /* page fault */ | ||||
signo = trap_pfault(frame, TRUE, eva); | addr = eva; | ||||
trap_pfault(frame, true, eva, &signo, &ucode); | |||||
markj: Perhaps use `bool` instead since you're changing the function anyway? | |||||
#if defined(I586_CPU) && !defined(NO_F00F_HACK) | #if defined(I586_CPU) && !defined(NO_F00F_HACK) | ||||
if (signo == -2) { | if (signo == -2) { | ||||
/* | /* | ||||
* The f00f hack workaround has triggered, so | * The f00f hack workaround has triggered, so | ||||
* treat the fault as an illegal instruction | * treat the fault as an illegal instruction | ||||
* (T_PRIVINFLT) instead of a page fault. | * (T_PRIVINFLT) instead of a page fault. | ||||
*/ | */ | ||||
type = frame->tf_trapno = T_PRIVINFLT; | type = frame->tf_trapno = T_PRIVINFLT; | ||||
/* Proceed as in that case. */ | /* Proceed as in that case. */ | ||||
ucode = ILL_PRVOPC; | ucode = ILL_PRVOPC; | ||||
signo = SIGILL; | signo = SIGILL; | ||||
break; | break; | ||||
} | } | ||||
#endif | #endif | ||||
if (signo == -1) | if (signo == -1) | ||||
return; | return; | ||||
if (signo == 0) | if (signo == 0) | ||||
goto user; | 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; | break; | ||||
case T_DIVIDE: /* integer divide fault */ | case T_DIVIDE: /* integer divide fault */ | ||||
ucode = FPE_INTDIV; | ucode = FPE_INTDIV; | ||||
signo = SIGFPE; | signo = SIGFPE; | ||||
break; | break; | ||||
#ifdef DEV_ISA | #ifdef DEV_ISA | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
} else { | } else { | ||||
/* kernel trap */ | /* kernel trap */ | ||||
KASSERT(cold || td->td_ucred != NULL, | KASSERT(cold || td->td_ucred != NULL, | ||||
("kernel trap doesn't have ucred")); | ("kernel trap doesn't have ucred")); | ||||
switch (type) { | switch (type) { | ||||
case T_PAGEFLT: /* page fault */ | case T_PAGEFLT: /* page fault */ | ||||
(void) trap_pfault(frame, FALSE, eva); | (void) trap_pfault(frame, false, eva, NULL, NULL); | ||||
return; | return; | ||||
case T_DNA: | case T_DNA: | ||||
if (PCB_USER_FPU(td->td_pcb)) | if (PCB_USER_FPU(td->td_pcb)) | ||||
panic("Unregistered use of FPU in kernel"); | panic("Unregistered use of FPU in kernel"); | ||||
if (npxdna()) | if (npxdna()) | ||||
return; | return; | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 235 Lines • ▼ Show 20 Lines | #endif /* DEV_ISA */ | ||||
trapsignal(td, &ksi); | trapsignal(td, &ksi); | ||||
user: | user: | ||||
userret(td, frame); | userret(td, frame); | ||||
KASSERT(PCB_USER_FPU(td->td_pcb), | KASSERT(PCB_USER_FPU(td->td_pcb), | ||||
("Return from trap with kernel FPU ctx leaked")); | ("Return from trap with kernel FPU ctx leaked")); | ||||
} | } | ||||
static int | 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) | |||||
{ | { | ||||
Done Inline ActionsThe amd64 comment could be used here with the addition of -2 to the list of return values. alc: The amd64 comment could be used here with the addition of -2 to the list of return values. | |||||
struct thread *td; | struct thread *td; | ||||
struct proc *p; | struct proc *p; | ||||
vm_offset_t va; | vm_offset_t va; | ||||
vm_map_t map; | vm_map_t map; | ||||
int rv; | int rv; | ||||
vm_prot_t ftype; | vm_prot_t ftype; | ||||
td = curthread; | td = curthread; | ||||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | #endif | ||||
if (frame->tf_err & PGEX_W) | if (frame->tf_err & PGEX_W) | ||||
ftype = VM_PROT_WRITE; | ftype = VM_PROT_WRITE; | ||||
else if ((frame->tf_err & PGEX_I) && pg_nx != 0) | else if ((frame->tf_err & PGEX_I) && pg_nx != 0) | ||||
ftype = VM_PROT_EXECUTE; | ftype = VM_PROT_EXECUTE; | ||||
else | else | ||||
ftype = VM_PROT_READ; | ftype = VM_PROT_READ; | ||||
/* Fault in the page. */ | /* 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) { | if (rv == KERN_SUCCESS) { | ||||
#ifdef HWPMC_HOOKS | #ifdef HWPMC_HOOKS | ||||
if (ftype == VM_PROT_READ || ftype == VM_PROT_WRITE) { | if (ftype == VM_PROT_READ || ftype == VM_PROT_WRITE) { | ||||
PMC_SOFT_CALL_TF( , , page_fault, all, frame); | PMC_SOFT_CALL_TF( , , page_fault, all, frame); | ||||
if (ftype == VM_PROT_READ) | if (ftype == VM_PROT_READ) | ||||
PMC_SOFT_CALL_TF( , , page_fault, read, | PMC_SOFT_CALL_TF( , , page_fault, read, | ||||
frame); | frame); | ||||
else | else | ||||
PMC_SOFT_CALL_TF( , , page_fault, write, | PMC_SOFT_CALL_TF( , , page_fault, write, | ||||
frame); | frame); | ||||
} | } | ||||
#endif | #endif | ||||
return (0); | return (0); | ||||
} | } | ||||
if (!usermode) { | if (usermode) | ||||
return (1); | |||||
if (td->td_intr_nesting_level == 0 && | if (td->td_intr_nesting_level == 0 && | ||||
curpcb->pcb_onfault != NULL) { | curpcb->pcb_onfault != NULL) { | ||||
frame->tf_eip = (int)curpcb->pcb_onfault; | frame->tf_eip = (int)curpcb->pcb_onfault; | ||||
return (0); | return (0); | ||||
} | } | ||||
trap_fatal(frame, eva); | trap_fatal(frame, eva); | ||||
return (-1); | return (-1); | ||||
} | |||||
return ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV); | |||||
} | } | ||||
static void | static void | ||||
trap_fatal(frame, eva) | trap_fatal(frame, eva) | ||||
struct trapframe *frame; | struct trapframe *frame; | ||||
vm_offset_t eva; | vm_offset_t eva; | ||||
{ | { | ||||
int code, ss, esp; | int code, ss, esp; | ||||
▲ Show 20 Lines • Show All 268 Lines • Show Last 20 Lines |
Perhaps use bool instead since you're changing the function anyway?