summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2018-07-06 02:43:02 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2018-07-06 02:43:02 +0000
commitac235f251f6c6b0d60955cd7c520f6ea158e696f (patch)
treed6baf339a7bd1e6461f83671cde1ce4249c5add7
parentdc34ba194236a0a4ab56cc38072db9c25600b331 (diff)
Split trap() into kerntrap() and usertrap(), with all the signal generation
in a compact block in the latter. ok deraadt@ mlarkin@
-rw-r--r--sys/arch/amd64/amd64/db_interface.c3
-rw-r--r--sys/arch/amd64/amd64/trap.c183
-rw-r--r--sys/arch/amd64/amd64/vector.S8
-rw-r--r--sys/arch/amd64/include/cpu.h4
4 files changed, 105 insertions, 93 deletions
diff --git a/sys/arch/amd64/amd64/db_interface.c b/sys/arch/amd64/amd64/db_interface.c
index 8bfe1f45895..e3452bd1e40 100644
--- a/sys/arch/amd64/amd64/db_interface.c
+++ b/sys/arch/amd64/amd64/db_interface.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_interface.c,v 1.32 2018/04/24 20:58:48 guenther Exp $ */
+/* $OpenBSD: db_interface.c,v 1.33 2018/07/06 02:43:01 guenther Exp $ */
/* $NetBSD: db_interface.c,v 1.1 2003/04/26 18:39:27 fvdl Exp $ */
/*
@@ -117,7 +117,6 @@ db_ktrap(int type, int code, db_regs_t *regs)
case T_BPTFLT: /* breakpoint */
case T_TRCTRAP: /* single_step */
case T_NMI: /* NMI */
- case T_NMI|T_USER:
case -1: /* keyboard interrupt */
break;
default:
diff --git a/sys/arch/amd64/amd64/trap.c b/sys/arch/amd64/amd64/trap.c
index e514395e1f5..8c33c0bec26 100644
--- a/sys/arch/amd64/amd64/trap.c
+++ b/sys/arch/amd64/amd64/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.72 2018/07/03 05:45:21 mpi Exp $ */
+/* $OpenBSD: trap.c,v 1.73 2018/07/06 02:43:01 guenther Exp $ */
/* $NetBSD: trap.c,v 1.2 2003/05/04 23:51:56 fvdl Exp $ */
/*-
@@ -92,7 +92,8 @@
#include "isa.h"
int pageflttrap(struct trapframe *, int _usermode);
-void trap(struct trapframe *);
+void kerntrap(struct trapframe *);
+void usertrap(struct trapframe *);
void ast(struct trapframe *);
void syscall(struct trapframe *);
@@ -124,6 +125,7 @@ const int trap_types = nitems(trap_type);
int trapdebug = 0;
#endif
+static void trap_print(struct trapframe *, int _type);
static inline void frame_dump(struct trapframe *_tf, struct proc *_p,
const char *_sig, uint64_t _cr2);
static inline void verify_smap(const char *_func);
@@ -254,30 +256,20 @@ pageflttrap(struct trapframe *frame, int usermode)
/*
- * trap(frame):
+ * kerntrap(frame):
* Exception, fault, and trap interface to BSD kernel. This
* common code is called from assembly language IDT gate entry
* routines that prepare a suitable stack frame, and restore this
* frame after the exception has been processed.
*/
void
-trap(struct trapframe *frame)
+kerntrap(struct trapframe *frame)
{
- struct proc *p = curproc;
int type = (int)frame->tf_trapno;
- union sigval sv;
- int code;
verify_smap(__func__);
uvmexp.traps++;
- debug_trap(frame, p, type);
-
- if (!KERNELMODE(frame->tf_cs, frame->tf_rflags)) {
- type |= T_USER;
- p->p_md.md_regs = frame;
- refreshcreds(p);
- check_stack(p, type);
- }
+ debug_trap(frame, curproc, type);
switch (type) {
@@ -287,16 +279,7 @@ trap(struct trapframe *frame)
if (db_ktrap(type, 0, frame))
return;
#endif
- if (frame->tf_trapno < trap_types)
- printf("fatal %s", trap_type[frame->tf_trapno]);
- else
- printf("unknown trap %ld", (u_long)frame->tf_trapno);
- printf(" in %s mode\n", (type & T_USER) ? "user" : "supervisor");
- printf("trap type %d code %llx rip %llx cs %llx rflags %llx cr2 "
- " %llx cpl %x rsp %llx\n",
- type, frame->tf_err, frame->tf_rip, frame->tf_cs,
- frame->tf_rflags, rcr2(), curcpu()->ci_ilevel, frame->tf_rsp);
-
+ trap_print(frame, type);
panic("trap type %d, code=%llx, pc=%llx",
type, frame->tf_err, frame->tf_rip);
/*NOTREACHED*/
@@ -307,74 +290,16 @@ trap(struct trapframe *frame)
case T_TSSFLT:
goto we_re_toast;
- case T_PROTFLT|T_USER: /* protection fault */
- case T_TSSFLT|T_USER:
- case T_SEGNPFLT|T_USER:
- case T_STKFLT|T_USER:
- frame_dump(frame, p, "BUS", 0);
- sv.sival_ptr = (void *)frame->tf_rip;
- KERNEL_LOCK();
- trapsignal(p, SIGBUS, type & ~T_USER, BUS_OBJERR, sv);
- KERNEL_UNLOCK();
- goto out;
- case T_ALIGNFLT|T_USER:
- sv.sival_ptr = (void *)frame->tf_rip;
- KERNEL_LOCK();
- trapsignal(p, SIGBUS, type & ~T_USER, BUS_ADRALN, sv);
- KERNEL_UNLOCK();
- goto out;
-
- case T_PRIVINFLT|T_USER: /* privileged instruction fault */
- sv.sival_ptr = (void *)frame->tf_rip;
- KERNEL_LOCK();
- trapsignal(p, SIGILL, type & ~T_USER, ILL_PRVOPC, sv);
- KERNEL_UNLOCK();
- goto out;
- case T_FPOPFLT|T_USER: /* impossible without 32bit compat */
- case T_BOUND|T_USER:
- case T_OFLOW|T_USER:
- case T_DNA|T_USER:
- panic("impossible trap");
- case T_DIVIDE|T_USER:
- sv.sival_ptr = (void *)frame->tf_rip;
- KERNEL_LOCK();
- trapsignal(p, SIGFPE, type &~ T_USER, FPE_INTDIV, sv);
- KERNEL_UNLOCK();
- goto out;
-
- case T_ARITHTRAP|T_USER:
- case T_XMM|T_USER:
- code = fputrap(type);
- sv.sival_ptr = (void *)frame->tf_rip;
- KERNEL_LOCK();
- trapsignal(p, SIGFPE, type &~ T_USER, code, sv);
- KERNEL_UNLOCK();
- goto out;
-
case T_PAGEFLT: /* allow page faults in kernel mode */
if (pageflttrap(frame, 0))
return;
goto we_re_toast;
- case T_PAGEFLT|T_USER: /* page fault */
- if (pageflttrap(frame, 1))
- goto out;
- goto we_re_toast;
-
case T_TRCTRAP:
goto we_re_toast;
- case T_BPTFLT|T_USER: /* bpt instruction fault */
- case T_TRCTRAP|T_USER: /* trace trap */
- sv.sival_ptr = (void *)frame->tf_rip;
- KERNEL_LOCK();
- trapsignal(p, SIGTRAP, type &~ T_USER, TRAP_BRKPT, sv);
- KERNEL_UNLOCK();
- break;
-
#if NISA > 0
case T_NMI:
- case T_NMI|T_USER:
#ifdef DDB
/* NMI can be hooked up to a pushbutton for debugging */
printf ("NMI ... going to debugger\n");
@@ -389,13 +314,101 @@ trap(struct trapframe *frame)
return;
#endif /* NISA > 0 */
}
+}
+
+
+/*
+ * usertrap(frame): handler for exceptions, faults, and traps from userspace
+ * This is called from the assembly language IDT gate entries
+ * which prepare a suitable stack frame and restores the CPU state
+ * after the fault has been processed.
+ */
+void
+usertrap(struct trapframe *frame)
+{
+ struct proc *p = curproc;
+ int type = (int)frame->tf_trapno;
+ union sigval sv;
+ int sig, code;
+
+ verify_smap(__func__);
+ uvmexp.traps++;
+ debug_trap(frame, p, type);
+
+ p->p_md.md_regs = frame;
+ refreshcreds(p);
+ check_stack(p, type);
+
+ switch (type) {
+ case T_PROTFLT: /* protection fault */
+ case T_TSSFLT:
+ case T_SEGNPFLT:
+ case T_STKFLT:
+ frame_dump(frame, p, "BUS", 0);
+ sig = SIGBUS;
+ code = BUS_OBJERR;
+ break;
+ case T_ALIGNFLT:
+ sig = SIGBUS;
+ code = BUS_ADRALN;
+ break;
+ case T_PRIVINFLT: /* privileged instruction fault */
+ sig = SIGILL;
+ code = ILL_PRVOPC;
+ break;
+ case T_DIVIDE:
+ sig = SIGFPE;
+ code = FPE_INTDIV;
+ break;
+ case T_ARITHTRAP:
+ case T_XMM: /* real arithmetic exceptions */
+ sig = SIGFPE;
+ code = fputrap(type);
+ break;
+ case T_BPTFLT: /* bpt instruction fault */
+ case T_TRCTRAP: /* trace trap */
+ sig = SIGTRAP;
+ code = TRAP_BRKPT;
+ break;
+
+ case T_PAGEFLT: /* page fault */
+ if (pageflttrap(frame, 1))
+ goto out;
+ /* FALLTHROUGH */
+
+ default:
+ trap_print(frame, type);
+ panic("impossible trap");
+ }
+
+ sv.sival_ptr = (void *)frame->tf_rip;
+ KERNEL_LOCK();
+ trapsignal(p, sig, type, code, sv);
+ KERNEL_UNLOCK();
- if ((type & T_USER) == 0)
- return;
out:
userret(p);
}
+
+static void
+trap_print(struct trapframe *frame, int type)
+{
+ if (type < trap_types)
+ printf("fatal %s", trap_type[type]);
+ else
+ printf("unknown trap %d", type);
+ printf(" in %s mode\n", KERNELMODE(frame->tf_cs, frame->tf_rflags) ?
+ "supervisor" : "user");
+ printf("trap type %d code %llx rip %llx cs %llx rflags %llx cr2 "
+ " %llx cpl %x rsp %llx\n",
+ type, frame->tf_err, frame->tf_rip, frame->tf_cs,
+ frame->tf_rflags, rcr2(), curcpu()->ci_ilevel, frame->tf_rsp);
+ printf("gsbase %p kgsbase %p\n",
+ (void *)rdmsr(MSR_GSBASE), (void *)rdmsr(MSR_KERNELGSBASE));
+}
+
+
static inline void
frame_dump(struct trapframe *tf, struct proc *p, const char *sig, uint64_t cr2)
{
diff --git a/sys/arch/amd64/amd64/vector.S b/sys/arch/amd64/amd64/vector.S
index 1369da1e07c..9ce4fc1e61f 100644
--- a/sys/arch/amd64/amd64/vector.S
+++ b/sys/arch/amd64/amd64/vector.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: vector.S,v 1.68 2018/07/03 20:15:57 guenther Exp $ */
+/* $OpenBSD: vector.S,v 1.69 2018/07/06 02:43:01 guenther Exp $ */
/* $NetBSD: vector.S,v 1.5 2004/06/28 09:13:11 fvdl Exp $ */
/*
@@ -145,7 +145,7 @@ INTRENTRY_LABEL(calltrap_specstk):
cld
SMAP_CLAC
movq %rsp,%rdi
- call trap
+ call _C_LABEL(kerntrap)
movl $MSR_GSBASE,%ecx # restore GS.base
movq %r12,%rax
movq %r13,%rdx
@@ -386,7 +386,7 @@ NENTRY(alltraps_kern)
movl CPUVAR(ILEVEL),%ebx
#endif /* DIAGNOSTIC */
movq %rsp, %rdi
- call _C_LABEL(trap) /* kerntrap */
+ call _C_LABEL(kerntrap)
2: cli
#ifndef DIAGNOSTIC
INTRFASTEXIT
@@ -426,7 +426,7 @@ NENTRY(alltraps_user)
.globl recall_trap
recall_trap:
movq %rsp, %rdi
- call _C_LABEL(trap) /* usertrap */
+ call _C_LABEL(usertrap)
cli
jmp intr_user_exit
END(alltraps_user)
diff --git a/sys/arch/amd64/include/cpu.h b/sys/arch/amd64/include/cpu.h
index 0c38a2ea7d9..f507e7c17bf 100644
--- a/sys/arch/amd64/include/cpu.h
+++ b/sys/arch/amd64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.124 2018/06/19 19:29:52 kettenis Exp $ */
+/* $OpenBSD: cpu.h,v 1.125 2018/07/06 02:43:01 guenther Exp $ */
/* $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $ */
/*-
@@ -319,7 +319,7 @@ void cpu_unidle(struct cpu_info *);
/*
* Give a profiling tick to the current process when the user profiling
* buffer pages are invalid. On the i386, request an ast to send us
- * through trap(), marking the proc as needing a profiling tick.
+ * through usertrap(), marking the proc as needing a profiling tick.
*/
#define need_proftick(p) aston(p)