Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/amd64 Remove useless debug code, and split trap() i...
details: https://anonhg.NetBSD.org/src/rev/3cd441347504
branches: trunk
changeset: 356122:3cd441347504
user: maxv <maxv%NetBSD.org@localhost>
date: Sun Sep 03 08:52:18 2017 +0000
description:
Remove useless debug code, and split trap() into smaller functions, easier
to understand. NMIs take another, faster path now. No functional change
beyond that.
diffstat:
sys/arch/amd64/amd64/amd64_trap.S | 6 +-
sys/arch/amd64/amd64/trap.c | 306 +++++++++++++++----------------------
sys/arch/amd64/conf/ALL | 5 +-
3 files changed, 129 insertions(+), 188 deletions(-)
diffs (truncated from 487 to 300 lines):
diff -r d8a68c8e9ab1 -r 3cd441347504 sys/arch/amd64/amd64/amd64_trap.S
--- a/sys/arch/amd64/amd64/amd64_trap.S Sun Sep 03 06:24:49 2017 +0000
+++ b/sys/arch/amd64/amd64/amd64_trap.S Sun Sep 03 08:52:18 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: amd64_trap.S,v 1.9 2017/08/31 10:30:58 maxv Exp $ */
+/* $NetBSD: amd64_trap.S,v 1.10 2017/09/03 08:52:18 maxv Exp $ */
/*
* Copyright (c) 1998, 2007, 2008, 2017 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
#if 0
#include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: amd64_trap.S,v 1.9 2017/08/31 10:30:58 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: amd64_trap.S,v 1.10 2017/09/03 08:52:18 maxv Exp $");
#endif
/*
@@ -135,7 +135,7 @@
swapgs
movq %rsp,%rdi
incq CPUVAR(NTRAP)
- call _C_LABEL(trap)
+ call _C_LABEL(nmitrap)
swapgs
jmp nmileave
diff -r d8a68c8e9ab1 -r 3cd441347504 sys/arch/amd64/amd64/trap.c
--- a/sys/arch/amd64/amd64/trap.c Sun Sep 03 06:24:49 2017 +0000
+++ b/sys/arch/amd64/amd64/trap.c Sun Sep 03 08:52:18 2017 +0000
@@ -1,11 +1,11 @@
-/* $NetBSD: trap.c,v 1.96 2017/04/24 17:03:43 chs Exp $ */
+/* $NetBSD: trap.c,v 1.97 2017/09/03 08:52:18 maxv Exp $ */
-/*-
- * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
+/*
+ * Copyright (c) 1998, 2000, 2017 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
- * by Charles M. Hannum.
+ * by Charles M. Hannum, and by Maxime Villard.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,7 +29,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-/*-
+/*
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
@@ -63,12 +63,8 @@
* @(#)trap.c 7.4 (Berkeley) 5/13/91
*/
-/*
- * 386 Trap and System call handling
- */
-
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.96 2017/04/24 17:03:43 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.97 2017/09/03 08:52:18 maxv Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
@@ -126,6 +122,7 @@
dtrace_doubletrap_func_t dtrace_doubletrap_func = NULL;
#endif
+void nmitrap(struct trapframe *);
void trap(struct trapframe *);
void trap_return_fault_return(struct trapframe *) __dead;
@@ -154,16 +151,8 @@
};
int trap_types = __arraycount(trap_type);
-#ifdef DEBUG
-int trapdebug = 0;
-#endif
-
#define IDTVEC(name) __CONCAT(X, name)
-#ifdef TRAP_SIGDEBUG
-static void frame_dump(struct trapframe *, struct pcb *);
-#endif
-
static void *
onfault_handler(const struct pcb *pcb, const struct trapframe *tf)
{
@@ -210,6 +199,115 @@
l, l->l_proc->p_pid, l->l_lid, KSTACK_LOWEST_ADDR(l));
}
+void
+nmitrap(struct trapframe *frame)
+{
+ const int type = T_NMI;
+
+ if (nmi_dispatch(frame))
+ return;
+ /* NMI can be hooked up to a pushbutton for debugging */
+ if (kgdb_trap(type, frame))
+ return;
+ if (kdb_trap(type, 0, frame))
+ return;
+ /* machine/parity/power fail/"kitchen sink" faults */
+
+ x86_nmi();
+}
+
+/*
+ * Did we receive in kernel mode a trap that ought to be considered as a user
+ * trap? If this function returns, the answer is no.
+ *
+ * Such traps can be triggered when the kernel fails to return to userland,
+ * because of incorrect segment registers.
+ */
+#ifndef Xen
+static void trap_user_kernelmode(struct trapframe *, int, lwp_t *, proc_t *);
+
+static void
+trap_user_kernelmode(struct trapframe *frame, int type, lwp_t *l, proc_t *p)
+{
+ struct trapframe *vframe;
+ ksiginfo_t ksi;
+
+ if (frame->tf_rip == 0) {
+ /*
+ * Assume that if we jumped to null we probably did it via a
+ * null function pointer, so print the return address.
+ */
+ printf("kernel jumped to null; return addr was %p\n",
+ *(void **)frame->tf_rsp);
+ return;
+ }
+
+ KSI_INIT_TRAP(&ksi);
+ ksi.ksi_signo = SIGSEGV;
+ ksi.ksi_code = SEGV_ACCERR;
+ ksi.ksi_trap = type;
+
+ /*
+ * Get %rsp value before fault - there may be a pad word below the
+ * trap frame.
+ */
+ vframe = (void *)frame->tf_rsp;
+
+ switch (*(uint16_t *)frame->tf_rip) {
+ case 0xcf48: /* iretq */
+ /*
+ * The 'iretq' instruction faulted, so we have the
+ * 'user' registers saved after the kernel
+ * %rip:%cs:%fl:%rsp:%ss of the iret, and below that
+ * the user %rip:%cs:%fl:%rsp:%ss the 'iret' was
+ * processing.
+ * We must copy the user register back over the
+ * kernel fault frame to generate a normal stack
+ * frame (eg for sending a SIGSEGV).
+ */
+ vframe = (void *)((char *)vframe
+ - offsetof(struct trapframe, tf_rip));
+ memmove(vframe, frame, offsetof(struct trapframe, tf_rip));
+ /* Set the faulting address to the user %rip */
+ ksi.ksi_addr = (void *)vframe->tf_rip;
+ break;
+
+ case 0x848e: /* mov 0xa8(%rsp),%es (8e 84 24 a8 00 00 00) */
+ case 0x9c8e: /* mov 0xb0(%rsp),%ds (8e 9c 24 b0 00 00 00) */
+#ifdef USER_LDT
+ case 0xa48e: /* mov 0xa0(%rsp),%fs (8e a4 24 a0 00 00 00) */
+ case 0xac8e: /* mov 0x98(%rsp),%gs (8e ac 24 98 00 00 00) */
+#endif
+ /*
+ * We faulted loading one of the user segment registers.
+ * The stack frame containing the user registers is
+ * still valid and pointed to by tf_rsp.
+ */
+ if (KERNELMODE(vframe->tf_cs, vframe->tf_eflags))
+ return;
+ /* There is no valid address for the fault */
+ break;
+
+ default:
+ return;
+ }
+
+ /* XXX: worry about on-stack trampolines for nested handlers?? */
+ /* Save outer frame for any signal return */
+ l->l_md.md_regs = vframe;
+ (*p->p_emul->e_trapsignal)(l, &ksi);
+ /* Return to user by reloading the user frame */
+ trap_return_fault_return(vframe);
+ /* NOTREACHED */
+}
+#else
+/*
+ * XXX: there has to be an equivalent 'problem' but I (dsl) don't know exactly
+ * what happens! For now panic the kernel.
+ */
+#define trap_user_kernelmode(frame, type, l, p) /* NOTHING */
+#endif
+
/*
* trap(frame): exception, fault, and trap interface to BSD kernel.
*
@@ -231,9 +329,6 @@
extern char fusuintrfailure[], kcopy_fault[];
extern char IDTVEC(osyscall)[];
extern char IDTVEC(syscall32)[];
-#ifndef XEN
- struct trapframe *vframe;
-#endif
ksiginfo_t ksi;
void *onfault;
int type, error;
@@ -252,12 +347,7 @@
}
type = frame->tf_trapno;
-#ifdef DEBUG
- if (trapdebug) {
- trap_print(frame, l);
- }
-#endif
- if (type != T_NMI && !KERNELMODE(frame->tf_cs, frame->tf_rflags)) {
+ if (!KERNELMODE(frame->tf_cs, frame->tf_rflags)) {
type |= T_USER;
l->l_md.md_regs = frame;
LWP_CACHE_CREDS(l, p);
@@ -322,92 +412,9 @@
return;
}
- /*
- * Check for failure during return to user mode.
- * This can happen loading invalid values into the segment
- * registers, or during the 'iret' itself.
- *
- * We do this by looking at the instruction we faulted on.
- * The specific instructions we recognize only happen when
- * returning from a trap, syscall, or interrupt.
- */
-
kernelfault:
-#ifdef XEN
- /*
- * XXX: there has to be an equivalent 'problem'
- * but I (dsl) don't know exactly what happens!
- * For now panic the kernel.
- */
+ trap_user_kernelmode(frame, type, l, p);
goto we_re_toast;
-#else
- KSI_INIT_TRAP(&ksi);
- ksi.ksi_signo = SIGSEGV;
- ksi.ksi_code = SEGV_ACCERR;
- ksi.ksi_trap = type;
-
- /* Get %rsp value before fault - there may be a pad word
- * below the trap frame. */
- vframe = (void *)frame->tf_rsp;
- if (frame->tf_rip == 0) {
- /*
- * Assume that if we jumped to null we
- * probably did it via a null function
- * pointer, so print the return address.
- */
- printf("kernel jumped to null; return addr was %p\n",
- *(void **)frame->tf_rsp);
- goto we_re_toast;
- }
- switch (*(uint16_t *)frame->tf_rip) {
- case 0xcf48: /* iretq */
- /*
- * The 'iretq' instruction faulted, so we have the
- * 'user' registers saved after the kernel
- * %rip:%cs:%fl:%rsp:%ss of the iret, and below that
- * the user %rip:%cs:%fl:%rsp:%ss the 'iret' was
- * processing.
- * We must copy the user register back over the
- * kernel fault frame to generate a normal stack
- * frame (eg for sending a SIGSEGV).
- */
- vframe = (void *)((char *)vframe
- - offsetof(struct trapframe, tf_rip));
- memmove(vframe, frame,
- offsetof(struct trapframe, tf_rip));
- /* Set the faulting address to the user %eip */
- ksi.ksi_addr = (void *)vframe->tf_rip;
- break;
- case 0x848e: /* mov 0xa8(%rsp),%es (8e 84 24 a8 00 00 00) */
- case 0x9c8e: /* mov 0xb0(%rsp),%ds (8e 9c 24 b0 00 00 00) */
-#ifdef USER_LDT
- case 0xa48e: /* mov 0xa0(%rsp),%fs (8e a4 24 a0 00 00 00) */
- case 0xac8e: /* mov 0x98(%rsp),%gs (8e ac 24 98 00 00 00) */
Home |
Main Index |
Thread Index |
Old Index