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/959c2ad4aa83
branches:  trunk
changeset: 826423:959c2ad4aa83
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 7f93206b2df7 -r 959c2ad4aa83 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 7f93206b2df7 -r 959c2ad4aa83 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