Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-8]: src/sys/arch Pull up the following revisions, requested by ma...



details:   https://anonhg.NetBSD.org/src/rev/03c9a258c122
branches:  netbsd-8
changeset: 434774:03c9a258c122
user:      martin <martin%NetBSD.org@localhost>
date:      Thu Mar 22 16:59:03 2018 +0000

description:
Pull up the following revisions, requested by maxv in ticket #652:

        sys/arch/amd64/amd64/amd64_trap.S       upto 1.39 (partial, patch)
        sys/arch/amd64/amd64/db_machdep.c       1.6 (patch)
        sys/arch/amd64/amd64/genassym.cf        1.65,1.66,1.67 (patch)
        sys/arch/amd64/amd64/locore.S           upto 1.159 (partial, patch)
        sys/arch/amd64/amd64/machdep.c          1.299-1.302 (patch)
        sys/arch/amd64/amd64/trap.c             upto 1.113 (partial, patch)
        sys/arch/amd64/amd64/amd64/vector.S     upto 1.61 (partial, patch)
        sys/arch/amd64/conf/GENERIC             1.477,1.478 (patch)
        sys/arch/amd64/conf/kern.ldscript       1.26 (patch)
        sys/arch/amd64/include/frameasm.h       upto 1.37 (partial, patch)
        sys/arch/amd64/include/param.h          1.25 (patch)
        sys/arch/amd64/include/pmap.h           1.41,1.43,1.44 (patch)
        sys/arch/x86/conf/files.x86             1.91,1.93 (patch)
        sys/arch/x86/include/cpu.h              1.88,1.89 (patch)
        sys/arch/x86/include/pmap.h             1.75 (patch)
        sys/arch/x86/x86/cpu.c                  1.144,1.146,1.148,1.149 (patch)
        sys/arch/x86/x86/pmap.c                 upto 1.289 (partial, patch)
        sys/arch/x86/x86/vm_machdep.c           1.31,1.32 (patch)
        sys/arch/x86/x86/x86_machdep.c          1.104,1.106,1.108 (patch)
        sys/arch/x86/x86/svs.c                  1.1-1.14
        sys/arch/xen/conf/files.compat          1.30 (patch)

Backport SVS. Not enabled yet.

diffstat:

 sys/arch/amd64/amd64/amd64_trap.S |  182 ++++++--
 sys/arch/amd64/amd64/db_machdep.c |    8 +-
 sys/arch/amd64/amd64/genassym.cf  |    9 +-
 sys/arch/amd64/amd64/locore.S     |  342 ++++++++++++-----
 sys/arch/amd64/amd64/machdep.c    |    8 +-
 sys/arch/amd64/amd64/trap.c       |   94 +----
 sys/arch/amd64/amd64/vector.S     |  136 ++++--
 sys/arch/amd64/conf/GENERIC       |    7 +-
 sys/arch/amd64/conf/kern.ldscript |    8 +-
 sys/arch/amd64/include/frameasm.h |   77 +++-
 sys/arch/amd64/include/param.h    |    6 +-
 sys/arch/amd64/include/pmap.h     |    8 +-
 sys/arch/x86/conf/files.x86       |    5 +-
 sys/arch/x86/include/cpu.h        |   16 +-
 sys/arch/x86/include/pmap.h       |    6 +-
 sys/arch/x86/x86/cpu.c            |   23 +-
 sys/arch/x86/x86/pmap.c           |   48 +-
 sys/arch/x86/x86/svs.c            |  753 ++++++++++++++++++++++++++++++++++++++
 sys/arch/x86/x86/vm_machdep.c     |   13 +-
 sys/arch/x86/x86/x86_machdep.c    |   21 +-
 sys/arch/xen/conf/files.compat    |    3 +-
 21 files changed, 1427 insertions(+), 346 deletions(-)

diffs (truncated from 2517 to 300 lines):

diff -r 9da148222348 -r 03c9a258c122 sys/arch/amd64/amd64/amd64_trap.S
--- a/sys/arch/amd64/amd64/amd64_trap.S Thu Mar 22 16:38:31 2018 +0000
+++ b/sys/arch/amd64/amd64/amd64_trap.S Thu Mar 22 16:59:03 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: amd64_trap.S,v 1.5.6.1 2018/03/07 14:50:56 martin Exp $        */
+/*     $NetBSD: amd64_trap.S,v 1.5.6.2 2018/03/22 16:59:03 martin Exp $        */
 
 /*
  * Copyright (c) 1998, 2007, 2008, 2017 The NetBSD Foundation, Inc.
@@ -95,13 +95,19 @@
 #define        PRE_TRAP
 #endif
 
+#define TRAPENTRY                      \
+       INTRENTRY                       ; \
+       jmp     .Lalltraps_noentry
+
 #define        TRAP_NJ(a)      PRE_TRAP ; pushq $(a)
 #define        ZTRAP_NJ(a)     PRE_TRAP ; pushq $0 ; pushq $(a)
-#define        TRAP(a)         TRAP_NJ(a) ; jmp _C_LABEL(alltraps)
-#define        ZTRAP(a)        ZTRAP_NJ(a) ; jmp _C_LABEL(alltraps)
+#define        TRAP(a)         TRAP_NJ(a) ; TRAPENTRY
+#define        ZTRAP(a)        ZTRAP_NJ(a) ; TRAPENTRY
 
        .text
 
+       TEXT_USER_BEGIN
+
 IDTVEC(trap00)
        ZTRAP(T_DIVIDE)
 IDTVEC_END(trap00)
@@ -128,6 +134,7 @@
        ZTRAP_NJ(T_NMI)
        subq    $TF_REGSIZE,%rsp
        INTR_SAVE_GPRS
+       SVS_ENTER_ALTSTACK
        cld
        movw    %gs,TF_GS(%rsp)
        movw    %fs,TF_FS(%rsp)
@@ -143,6 +150,7 @@
        movq    %rsp,%rdi
        incq    CPUVAR(NTRAP)
        call    _C_LABEL(nmitrap)
+       SVS_LEAVE_ALTSTACK
        swapgs
        jmp     .Lnmileave
 
@@ -150,6 +158,7 @@
        movq    %rsp,%rdi
        incq    CPUVAR(NTRAP)
        call    _C_LABEL(nmitrap)
+       SVS_LEAVE_ALTSTACK
 
 .Lnmileave:
        INTR_RESTORE_GPRS
@@ -221,6 +230,7 @@
        TRAP_NJ(T_DOUBLEFLT)
        subq    $TF_REGSIZE,%rsp
        INTR_SAVE_GPRS
+       SVS_ENTER_ALTSTACK
        testb   $SEL_UPL,TF_CS(%rsp)
        jz      1f
        swapgs
@@ -235,6 +245,7 @@
        incq    CPUVAR(NTRAP)
        call    _C_LABEL(doubletrap)
 
+       SVS_LEAVE_ALTSTACK
        INTR_RESTORE_GPRS
 
        testb   $SEL_UPL,TF_CS(%rsp)
@@ -260,22 +271,22 @@
  * equivalent of iret, if it does this code would be needed
  * in order to copy the user segment registers into the fault frame.
  */
-#define check_swapgs alltraps
+#define kernuser_reenter alltraps
 #endif
 
 IDTVEC(trap11)         /* #NP() Segment not present */
        TRAP_NJ(T_SEGNPFLT)
-       jmp     check_swapgs
+       jmp     kernuser_reenter
 IDTVEC_END(trap11)
 
 IDTVEC(trap12)         /* #SS() Stack exception */
        TRAP_NJ(T_STKFLT)
-       jmp     check_swapgs
+       jmp     kernuser_reenter
 IDTVEC_END(trap12)
 
 IDTVEC(trap13)         /* #GP() General protection */
        TRAP_NJ(T_PROTFLT)
-       jmp     check_swapgs
+       jmp     kernuser_reenter
 IDTVEC_END(trap13)
 
 IDTVEC(trap14)
@@ -352,68 +363,135 @@
        jmp     .Lalltraps_checkusr
 IDTVEC_END(intrspurious)
 
-
-/*
- * trap() calls here when it detects a fault in INTRFASTEXIT (loading the
- * segment registers or during the iret itself). The address of the (possibly
- * reconstructed) user trap frame is passed as an argument.
- *
- * Typically the code will have raised a SIGSEGV which will be actioned
- * by the code below.
- */
-       .type   _C_LABEL(trap_return_fault_return), @function
-LABEL(trap_return_fault_return)
-       mov     %rdi,%rsp               /* frame for user return */
-#ifdef DIAGNOSTIC
-       /* We can't recover the saved %rbx, so suppress warning */
-       movl    CPUVAR(ILEVEL),%ebx
-#endif
-       jmp     .Lalltraps_checkusr
-END(trap_return_fault_return)
-
-#ifndef check_swapgs
+#ifndef kernuser_reenter
 /*
  * We need to worry about traps in kernel mode while the kernel %gs isn't
- * loaded. These are either faults on iretq during return to user or loads to
- * %gs.
+ * loaded. When such traps happen, we have CPL=0 and %gs=userland, and we
+ * must perform an additional swapgs to get %gs=kernel.
+ */
+
+#define TF_SMALL(val, reg)             (val - TF_REGSIZE)(reg)
+#define TF_SMALL_REGPUSHED(val, reg)   (val - (TF_REGSIZE - 8))(reg)
+
+/*
+ * It is possible that we received a trap in kernel mode, but with the user
+ * context loaded. There are three cases where this can happen:
+ *
+ *  o Execution of IRETQ.
+ *  o Reload of ES.
+ *  o Reload of DS.
+ *
+ * When this happens, the kernel is re-entered in kernel mode, but the
+ * previous context is in kernel mode too.
+ *
+ * We have two iret frames in the stack. In the first one, we also pushed
+ * 'trapno' and 'err'. The 'rsp' field points to the outer iret frame:
+ *
+ * +---------------------------------------------------+
+ * | trapno | err | rip | cs=ring0 | rflags | rsp | ss |
+ * +-------------------------------------------|-------+
+ *                                             |
+ *           +---------------------------------+
+ *           |
+ *           |    +------------------------------------+
+ *           +--> | rip | cs=ring3 | rflags | rsp | ss |
+ *                +------------------------------------+
+ *
+ * We perform a three-step procedure:
  *
- * When such traps happen, we have CPL=0 and %gs=userland, and we must perform
- * an additional swapgs to get %gs=kernel.
+ *  o We update RSP to point to the outer frame. This outer frame is in the
+ *    same stack as the current frame, and likely just after the current
+ *    frame.
+ *
+ *  o We push, in this outer frame, the 'err' and 'trapno' fields of the
+ *    CURRENT frame.
+ *
+ *  o We do a normal INTRENTRY. Now that RSP points to the outer frame,
+ *    everything behaves as if we had received a trap from the outer frame,
+ *    that is to say, from userland directly.
+ *
+ * Finally, we jump to 'calltrap' and handle the trap smoothly.
+ *
+ * Two notes regarding SVS:
+ *
+ *  o With SVS, we will receive the trap while the user page tables are
+ *    loaded. That's not a problem, we don't touch anything unmapped here.
+ *
+ *  o With SVS, when the user page tables are loaded, the stack is really
+ *    small, and can contain only one trapframe structure. Therefore, in
+ *    intrfastexit, we must save the GPRs and pop their part of the stack
+ *    right away. If we weren't doing that, and the reload of ES faulted for
+ *    example, then the CPU would try to push an iret frame on the current
+ *    stack (nested), and would double-fault because it touches the redzone
+ *    below the stack (see the documentation in x86/x86/svs.c). By popping
+ *    the GPR part of the stack, we leave enough stack for the CPU to push
+ *    an iret frame, and for us to push one 8-byte register (%rdi) too.
  */
-NENTRY(check_swapgs)
-       INTRENTRY_L(3f,1:)
-2:
+       _ALIGN_TEXT
+LABEL(kernuser_reenter)
+       testb   $SEL_UPL,TF_SMALL(TF_CS, %rsp)
+       jz      .Lkernelmode
+
+.Lnormal_entry:
+       INTRENTRY
        sti
        jmp     calltrap
-3:
-       /*
-        * Trap in kernel mode.
-        */
+
+.Lkernelmode:
+       /* We will clobber %rdi */
+       pushq   %rdi
+
        /* Case 1: fault on iretq? */
-       movq    TF_RIP(%rsp),%rax
-       cmpw    $0xcf48,(%rax)          /* Faulting instruction is iretq ? */
-       jne     5f                      /* Jump if not */
-       movq    TF_RSP(%rsp),%rax       /* Must read %rsp, may be a pad word */
-       testb   $SEL_UPL,8(%rax)        /* Check %cs of outer iret frame */
-       je      2b                      /* jump if iret was to kernel  */
-       jmp     1b                      /* to user - must restore %gs */
+       leaq    do_iret(%rip),%rdi
+       cmpq    %rdi,TF_SMALL_REGPUSHED(TF_RIP, %rsp)
+       jne     5f
+       movq    TF_SMALL_REGPUSHED(TF_RSP, %rsp),%rdi   /* get %rsp */
+       testb   $SEL_UPL,8(%rdi)        /* check %cs of outer iret frame */
+       je      .Lnormal_entry          /* jump if iret was to kernel  */
+       jmp     .Lkernelmode_but_user   /* to user - must restore %gs */
 5:
 
-       /* Case 2: move to %gs? */
-       movw    (%rax),%ax
-       andb    $070,%ah                /* mask mod/rm from mod/reg/rm */
-       cmpw    $0x8e+050*256,%ax       /* Any move to %gs (reg 5) */
-       jne     2b                      /* No - normal kernel fault */
-       jmp     1b                      /* Yes - restore %gs */
-END(check_swapgs)
+       /* Case 2: move to %es? */
+       leaq    do_mov_es(%rip),%rdi
+       cmpq    %rdi,TF_SMALL_REGPUSHED(TF_RIP, %rsp)
+       je      .Lkernelmode_but_user
+
+       /* Case 3: move to %ds? */
+       leaq    do_mov_ds(%rip),%rdi
+       cmpq    %rdi,TF_SMALL_REGPUSHED(TF_RIP, %rsp)
+       je      .Lkernelmode_but_user
+
+       /* None of the above cases: normal kernel fault */
+       popq    %rdi
+       jmp     .Lnormal_entry
+
+.Lkernelmode_but_user:
+       /*
+        * Here we have %rdi pushed on the stack, hence 8+.
+        */
+       movq    %rsp,%rdi
+       movq    TF_SMALL_REGPUSHED(TF_RSP, %rsp),%rsp
+
+       /* Push tf_err and tf_trapno */
+       pushq   8+8(%rdi)       /* 8+8(%rdi) = current TF_ERR */
+       pushq   8+0(%rdi)       /* 8+0(%rdi) = current TF_TRAPNO */
+
+       /* Restore %rdi */
+       movq    (%rdi),%rdi
+
+       jmp     .Lnormal_entry
+END(kernuser_reenter)
 #endif
 
+       TEXT_USER_END
+
 /*
  * All traps go through here. Call the generic trap handler, and
  * check for ASTs afterwards.
  */
 NENTRY(alltraps)
        INTRENTRY
+.Lalltraps_noentry:
        STI(si)
 
 calltrap:
diff -r 9da148222348 -r 03c9a258c122 sys/arch/amd64/amd64/db_machdep.c
--- a/sys/arch/amd64/amd64/db_machdep.c Thu Mar 22 16:38:31 2018 +0000
+++ b/sys/arch/amd64/amd64/db_machdep.c Thu Mar 22 16:59:03 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: db_machdep.c,v 1.4 2012/10/03 17:43:22 riastradh Exp $ */
+/*     $NetBSD: db_machdep.c,v 1.4.30.1 2018/03/22 16:59:03 martin Exp $       */
 
 /* 
  * Mach Operating System
@@ -26,7 +26,7 @@
  * rights to redistribute these changes.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_machdep.c,v 1.4 2012/10/03 17:43:22 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_machdep.c,v 1.4.30.1 2018/03/22 16:59:03 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -213,11 +213,13 @@
                if (!strcmp(name, "trap")) {
                        *is_trap = TRAP;



Home | Main Index | Thread Index | Old Index