Source-Changes-HG archive

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

[src/trunk]: src/sys/arch Handle NMIs correctly when SVS is enabled. We store...



details:   https://anonhg.NetBSD.org/src/rev/35542b3298f1
branches:  trunk
changeset: 363134:35542b3298f1
user:      maxv <maxv%NetBSD.org@localhost>
date:      Thu Jul 12 19:48:16 2018 +0000

description:
Handle NMIs correctly when SVS is enabled. We store the kernel's CR3 at the
top of the NMI stack, and we unconditionally switch to it, because we don't
know with which page tables we received the NMI. Hotpatch the whole thing as
usual.

This restores the ability to use PMCs on Intel CPUs.

diffstat:

 sys/arch/amd64/amd64/amd64_trap.S |   8 ++++----
 sys/arch/amd64/amd64/locore.S     |  22 +++++++++++++++++++++-
 sys/arch/amd64/amd64/machdep.c    |  16 ++++++++++++----
 sys/arch/amd64/include/frameasm.h |  20 +++++++++++++++++++-
 sys/arch/x86/x86/svs.c            |  28 ++++++++++++++++++++++++++--
 5 files changed, 82 insertions(+), 12 deletions(-)

diffs (287 lines):

diff -r c1cfb94364b2 -r 35542b3298f1 sys/arch/amd64/amd64/amd64_trap.S
--- a/sys/arch/amd64/amd64/amd64_trap.S Thu Jul 12 18:39:09 2018 +0000
+++ b/sys/arch/amd64/amd64/amd64_trap.S Thu Jul 12 19:48:16 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: amd64_trap.S,v 1.42 2018/05/25 15:33:56 maxv Exp $     */
+/*     $NetBSD: amd64_trap.S,v 1.43 2018/07/12 19:48:16 maxv Exp $     */
 
 /*
  * Copyright (c) 1998, 2007, 2008, 2017 The NetBSD Foundation, Inc.
@@ -254,7 +254,6 @@
        subq    $TF_REGSIZE,%rsp
        INTR_SAVE_GPRS
        IBRS_ENTER
-       SVS_ENTER_ALTSTACK
        cld
        SMAP_ENABLE
        movw    %gs,TF_GS(%rsp)
@@ -262,6 +261,8 @@
        movw    %es,TF_ES(%rsp)
        movw    %ds,TF_DS(%rsp)
 
+       SVS_ENTER_NMI
+
        movl    $MSR_GSBASE,%ecx
        rdmsr
        cmpl    $VM_MIN_KERNEL_ADDRESS_HIGH32,%edx
@@ -271,7 +272,6 @@
        movq    %rsp,%rdi
        incq    CPUVAR(NTRAP)
        call    _C_LABEL(nmitrap)
-       SVS_LEAVE_ALTSTACK
        swapgs
        jmp     .Lnmileave
 
@@ -279,9 +279,9 @@
        movq    %rsp,%rdi
        incq    CPUVAR(NTRAP)
        call    _C_LABEL(nmitrap)
-       SVS_LEAVE_ALTSTACK
 
 .Lnmileave:
+       SVS_LEAVE_NMI
        IBRS_LEAVE
        INTR_RESTORE_GPRS
        addq    $TF_REGSIZE+16,%rsp
diff -r c1cfb94364b2 -r 35542b3298f1 sys/arch/amd64/amd64/locore.S
--- a/sys/arch/amd64/amd64/locore.S     Thu Jul 12 18:39:09 2018 +0000
+++ b/sys/arch/amd64/amd64/locore.S     Thu Jul 12 19:48:16 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: locore.S,v 1.169 2018/07/09 18:52:04 maxv Exp $        */
+/*     $NetBSD: locore.S,v 1.170 2018/07/12 19:48:16 maxv Exp $        */
 
 /*
  * Copyright-o-rama!
@@ -1633,6 +1633,13 @@
 1234:
 LABEL(svs_enter_altstack_end)
 
+LABEL(svs_enter_nmi)
+       movq    %cr3,%rax
+       movq    %rax,(FRAMESIZE+1*8)(%rsp)      /* nmistore->scratch */
+       movq    (FRAMESIZE+0*8)(%rsp),%rax      /* nmistore->cr3 */
+       movq    %rax,%cr3
+LABEL(svs_enter_nmi_end)
+
 LABEL(svs_leave)
        testb   $SEL_UPL,TF_CS(%rsp)
        jz      1234f
@@ -1650,6 +1657,11 @@
 1234:
 LABEL(svs_leave_altstack_end)
 
+LABEL(svs_leave_nmi)
+       movq    (FRAMESIZE+1*8)(%rsp),%rax      /* nmistore->scratch */
+       movq    %rax,%cr3
+LABEL(svs_leave_nmi_end)
+
 LABEL(nosvs_enter)
        NOSVS_ENTER
 LABEL(nosvs_enter_end)
@@ -1658,6 +1670,10 @@
        NOSVS_ENTER_ALTSTACK
 LABEL(nosvs_enter_altstack_end)
 
+LABEL(nosvs_enter_nmi)
+       NOSVS_ENTER_NMI
+LABEL(nosvs_enter_nmi_end)
+
 LABEL(nosvs_leave)
        NOSVS_LEAVE
 LABEL(nosvs_leave_end)
@@ -1665,6 +1681,10 @@
 LABEL(nosvs_leave_altstack)
        NOSVS_LEAVE_ALTSTACK
 LABEL(nosvs_leave_altstack_end)
+
+LABEL(nosvs_leave_nmi)
+       NOSVS_LEAVE_NMI
+LABEL(nosvs_leave_nmi_end)
 #endif
 
        .globl  ibrs_enter, ibrs_enter_end
diff -r c1cfb94364b2 -r 35542b3298f1 sys/arch/amd64/amd64/machdep.c
--- a/sys/arch/amd64/amd64/machdep.c    Thu Jul 12 18:39:09 2018 +0000
+++ b/sys/arch/amd64/amd64/machdep.c    Thu Jul 12 19:48:16 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: machdep.c,v 1.305 2018/06/20 11:49:37 maxv Exp $       */
+/*     $NetBSD: machdep.c,v 1.306 2018/07/12 19:48:16 maxv Exp $       */
 
 /*
  * Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011
@@ -110,7 +110,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.305 2018/06/20 11:49:37 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.306 2018/07/12 19:48:16 maxv Exp $");
 
 #include "opt_modular.h"
 #include "opt_user_ldt.h"
@@ -281,6 +281,11 @@
 
 struct pool x86_dbregspl;
 
+struct nmistore {
+       uint64_t cr3;
+       uint64_t scratch;
+} __packed;
+
 /*
  * Size of memory segments, before any memory is stolen.
  */
@@ -506,6 +511,7 @@
        const cpuid_t cid = cpu_index(ci);
 #endif
        struct cpu_tss *cputss;
+       struct nmistore *store;
        uintptr_t p;
 
 #ifdef __HAVE_PCPU_AREA
@@ -533,13 +539,15 @@
 #endif
        cputss->tss.tss_ist[1] = p + PAGE_SIZE - 16;
 
-       /* NMI */
+       /* NMI - store a structure at the top of the stack */
 #ifdef __HAVE_PCPU_AREA
        p = (vaddr_t)&pcpuarea->ent[cid].ist2;
 #else
        p = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_WIRED|UVM_KMF_ZERO);
 #endif
-       cputss->tss.tss_ist[2] = p + PAGE_SIZE - 16;
+       cputss->tss.tss_ist[2] = p + PAGE_SIZE - sizeof(struct nmistore);
+       store = (struct nmistore *)(p + PAGE_SIZE - sizeof(struct nmistore));
+       store->cr3 = pmap_pdirpa(pmap_kernel(), 0);
 
        /* DB */
 #ifdef __HAVE_PCPU_AREA
diff -r c1cfb94364b2 -r 35542b3298f1 sys/arch/amd64/include/frameasm.h
--- a/sys/arch/amd64/include/frameasm.h Thu Jul 12 18:39:09 2018 +0000
+++ b/sys/arch/amd64/include/frameasm.h Thu Jul 12 19:48:16 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: frameasm.h,v 1.38 2018/03/28 16:02:49 maxv Exp $       */
+/*     $NetBSD: frameasm.h,v 1.39 2018/07/12 19:48:16 maxv Exp $       */
 
 #ifndef _AMD64_MACHINE_FRAMEASM_H
 #define _AMD64_MACHINE_FRAMEASM_H
@@ -46,6 +46,8 @@
 #define HP_NAME_SVS_LEAVE_ALT  8
 #define HP_NAME_IBRS_ENTER     9
 #define HP_NAME_IBRS_LEAVE     10
+#define HP_NAME_SVS_ENTER_NMI  11
+#define HP_NAME_SVS_LEAVE_NMI  12
 
 #define HOTPATCH(name, size) \
 123:                                           ; \
@@ -165,6 +167,22 @@
        HOTPATCH(HP_NAME_SVS_LEAVE_ALT, SVS_LEAVE_ALT_BYTES)    ; \
        NOSVS_LEAVE_ALTSTACK
 
+#define SVS_ENTER_NMI_BYTES    22
+#define NOSVS_ENTER_NMI \
+       .byte 0xEB, (SVS_ENTER_NMI_BYTES-2)     /* jmp */       ; \
+       .fill   (SVS_ENTER_NMI_BYTES-2),1,0xCC
+#define SVS_ENTER_NMI \
+       HOTPATCH(HP_NAME_SVS_ENTER_NMI, SVS_ENTER_NMI_BYTES)    ; \
+       NOSVS_ENTER_NMI
+
+#define SVS_LEAVE_NMI_BYTES    11
+#define NOSVS_LEAVE_NMI \
+       .byte 0xEB, (SVS_LEAVE_NMI_BYTES-2)     /* jmp */       ; \
+       .fill   (SVS_LEAVE_NMI_BYTES-2),1,0xCC
+#define SVS_LEAVE_NMI \
+       HOTPATCH(HP_NAME_SVS_LEAVE_NMI, SVS_LEAVE_NMI_BYTES)    ; \
+       NOSVS_LEAVE_NMI
+
 #else
 #define SVS_ENTER      /* nothing */
 #define SVS_LEAVE      /* nothing */
diff -r c1cfb94364b2 -r 35542b3298f1 sys/arch/x86/x86/svs.c
--- a/sys/arch/x86/x86/svs.c    Thu Jul 12 18:39:09 2018 +0000
+++ b/sys/arch/x86/x86/svs.c    Thu Jul 12 19:48:16 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: svs.c,v 1.18 2018/04/26 18:54:09 alnsn Exp $   */
+/*     $NetBSD: svs.c,v 1.19 2018/07/12 19:48:16 maxv Exp $    */
 
 /*
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: svs.c,v 1.18 2018/04/26 18:54:09 alnsn Exp $");
+__KERNEL_RCSID(0, "$NetBSD: svs.c,v 1.19 2018/07/12 19:48:16 maxv Exp $");
 
 #include "opt_svs.h"
 
@@ -571,8 +571,10 @@
 {
        extern uint8_t svs_enter, svs_enter_end;
        extern uint8_t svs_enter_altstack, svs_enter_altstack_end;
+       extern uint8_t svs_enter_nmi, svs_enter_nmi_end;
        extern uint8_t svs_leave, svs_leave_end;
        extern uint8_t svs_leave_altstack, svs_leave_altstack_end;
+       extern uint8_t svs_leave_nmi, svs_leave_nmi_end;
        u_long psl, cr0;
        uint8_t *bytes;
        size_t size;
@@ -590,6 +592,11 @@
            (size_t)&svs_enter_altstack;
        x86_hotpatch(HP_NAME_SVS_ENTER_ALT, bytes, size);
 
+       bytes = &svs_enter_nmi;
+       size = (size_t)&svs_enter_nmi_end -
+           (size_t)&svs_enter_nmi;
+       x86_hotpatch(HP_NAME_SVS_ENTER_NMI, bytes, size);
+
        bytes = &svs_leave;
        size = (size_t)&svs_leave_end - (size_t)&svs_leave;
        x86_hotpatch(HP_NAME_SVS_LEAVE, bytes, size);
@@ -599,6 +606,11 @@
            (size_t)&svs_leave_altstack;
        x86_hotpatch(HP_NAME_SVS_LEAVE_ALT, bytes, size);
 
+       bytes = &svs_leave_nmi;
+       size = (size_t)&svs_leave_nmi_end -
+           (size_t)&svs_leave_nmi;
+       x86_hotpatch(HP_NAME_SVS_LEAVE_NMI, bytes, size);
+
        x86_patch_window_close(psl, cr0);
 }
 
@@ -607,8 +619,10 @@
 {
        extern uint8_t nosvs_enter, nosvs_enter_end;
        extern uint8_t nosvs_enter_altstack, nosvs_enter_altstack_end;
+       extern uint8_t nosvs_enter_nmi, nosvs_enter_nmi_end;
        extern uint8_t nosvs_leave, nosvs_leave_end;
        extern uint8_t nosvs_leave_altstack, nosvs_leave_altstack_end;
+       extern uint8_t nosvs_leave_nmi, nosvs_leave_nmi_end;
        u_long psl, cr0;
        uint8_t *bytes;
        size_t size;
@@ -624,6 +638,11 @@
            (size_t)&nosvs_enter_altstack;
        x86_hotpatch(HP_NAME_SVS_ENTER_ALT, bytes, size);
 
+       bytes = &nosvs_enter_nmi;
+       size = (size_t)&nosvs_enter_nmi_end -
+           (size_t)&nosvs_enter_nmi;
+       x86_hotpatch(HP_NAME_SVS_ENTER_NMI, bytes, size);
+
        bytes = &nosvs_leave;
        size = (size_t)&nosvs_leave_end - (size_t)&nosvs_leave;
        x86_hotpatch(HP_NAME_SVS_LEAVE, bytes, size);
@@ -633,6 +652,11 @@
            (size_t)&nosvs_leave_altstack;
        x86_hotpatch(HP_NAME_SVS_LEAVE_ALT, bytes, size);
 
+       bytes = &nosvs_leave_nmi;
+       size = (size_t)&nosvs_leave_nmi_end -
+           (size_t)&nosvs_leave_nmi;
+       x86_hotpatch(HP_NAME_SVS_LEAVE_NMI, bytes, size);
+
        x86_patch_window_close(psl, cr0);
 }
 



Home | Main Index | Thread Index | Old Index