Author: kib
Date: Tue Nov  8 09:51:55 2016
New Revision: 308438
URL: https://svnweb.freebsd.org/changeset/base/308438

Log:
  MFC r307866:
  Handle broadcast NMIs.
  
  MFC r307880:
  Follow-up to r307866.
  
  MFC r308030:
  Use correct cpu id in the banner.

Modified:
  stable/11/sys/amd64/amd64/trap.c
  stable/11/sys/i386/i386/trap.c
  stable/11/sys/kern/subr_smp.c
  stable/11/sys/x86/include/x86_smp.h
  stable/11/sys/x86/include/x86_var.h
  stable/11/sys/x86/x86/cpu_machdep.c
  stable/11/sys/x86/x86/mp_x86.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/amd64/amd64/trap.c
==============================================================================
--- stable/11/sys/amd64/amd64/trap.c    Tue Nov  8 08:09:48 2016        
(r308437)
+++ stable/11/sys/amd64/amd64/trap.c    Tue Nov  8 09:51:55 2016        
(r308438)
@@ -144,14 +144,6 @@ static char *trap_msg[] = {
        "DTrace pid return trap",               /* 32 T_DTRACE_RET */
 };
 
-#ifdef KDB
-static int kdb_on_nmi = 1;
-SYSCTL_INT(_machdep, OID_AUTO, kdb_on_nmi, CTLFLAG_RWTUN,
-       &kdb_on_nmi, 0, "Go to KDB on NMI");
-#endif
-static int panic_on_nmi = 1;
-SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RWTUN,
-       &panic_on_nmi, 0, "Panic on NMI");
 static int prot_fault_translation;
 SYSCTL_INT(_machdep, OID_AUTO, prot_fault_translation, CTLFLAG_RWTUN,
     &prot_fault_translation, 0,
@@ -377,21 +369,7 @@ trap(struct trapframe *frame)
 
 #ifdef DEV_ISA
                case T_NMI:
-                       /* machine/parity/power fail/"kitchen sink" faults */
-                       if (isa_nmi(frame->tf_err) == 0) {
-#ifdef KDB
-                               /*
-                                * NMI can be hooked up to a pushbutton
-                                * for debugging.
-                                */
-                               if (kdb_on_nmi) {
-                                       printf ("NMI ... going to debugger\n");
-                                       kdb_trap(type, 0, frame);
-                               }
-#endif /* KDB */
-                               goto userout;
-                       } else if (panic_on_nmi)
-                               panic("NMI indicates hardware failure");
+                       nmi_handle_intr(type, frame);
                        break;
 #endif /* DEV_ISA */
 
@@ -563,22 +541,8 @@ trap(struct trapframe *frame)
 
 #ifdef DEV_ISA
                case T_NMI:
-                       /* machine/parity/power fail/"kitchen sink" faults */
-                       if (isa_nmi(frame->tf_err) == 0) {
-#ifdef KDB
-                               /*
-                                * NMI can be hooked up to a pushbutton
-                                * for debugging.
-                                */
-                               if (kdb_on_nmi) {
-                                       printf ("NMI ... going to debugger\n");
-                                       kdb_trap(type, 0, frame);
-                               }
-#endif /* KDB */
-                               goto out;
-                       } else if (panic_on_nmi == 0)
-                               goto out;
-                       /* FALLTHROUGH */
+                       nmi_handle_intr(type, frame);
+                       goto out;
 #endif /* DEV_ISA */
                }
 

Modified: stable/11/sys/i386/i386/trap.c
==============================================================================
--- stable/11/sys/i386/i386/trap.c      Tue Nov  8 08:09:48 2016        
(r308437)
+++ stable/11/sys/i386/i386/trap.c      Tue Nov  8 09:51:55 2016        
(r308438)
@@ -158,14 +158,6 @@ static char *trap_msg[] = {
 int has_f00f_bug = 0;          /* Initialized so that it can be patched. */
 #endif
 
-#ifdef KDB
-static int kdb_on_nmi = 1;
-SYSCTL_INT(_machdep, OID_AUTO, kdb_on_nmi, CTLFLAG_RWTUN,
-       &kdb_on_nmi, 0, "Go to KDB on NMI");
-#endif
-static int panic_on_nmi = 1;
-SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RWTUN,
-       &panic_on_nmi, 0, "Panic on NMI");
 static int prot_fault_translation = 0;
 SYSCTL_INT(_machdep, OID_AUTO, prot_fault_translation, CTLFLAG_RW,
        &prot_fault_translation, 0, "Select signal to deliver on protection 
fault");
@@ -467,21 +459,7 @@ user_trctrap_out:
                        }
                        goto userout;
 #else /* !POWERFAIL_NMI */
-                       /* machine/parity/power fail/"kitchen sink" faults */
-                       if (isa_nmi(frame->tf_err) == 0) {
-#ifdef KDB
-                               /*
-                                * NMI can be hooked up to a pushbutton
-                                * for debugging.
-                                */
-                               if (kdb_on_nmi) {
-                                       printf ("NMI ... going to debugger\n");
-                                       kdb_trap(type, 0, frame);
-                               }
-#endif /* KDB */
-                               goto userout;
-                       } else if (panic_on_nmi)
-                               panic("NMI indicates hardware failure");
+                       nmi_handle_intr(type, frame);
                        break;
 #endif /* POWERFAIL_NMI */
 #endif /* DEV_ISA */
@@ -730,22 +708,8 @@ kernel_trctrap:
                        }
                        goto out;
 #else /* !POWERFAIL_NMI */
-                       /* machine/parity/power fail/"kitchen sink" faults */
-                       if (isa_nmi(frame->tf_err) == 0) {
-#ifdef KDB
-                               /*
-                                * NMI can be hooked up to a pushbutton
-                                * for debugging.
-                                */
-                               if (kdb_on_nmi) {
-                                       printf ("NMI ... going to debugger\n");
-                                       kdb_trap(type, 0, frame);
-                               }
-#endif /* KDB */
-                               goto out;
-                       } else if (panic_on_nmi == 0)
-                               goto out;
-                       /* FALLTHROUGH */
+                       nmi_handle_intr(type, frame);
+                       goto out;
 #endif /* POWERFAIL_NMI */
 #endif /* DEV_ISA */
                }

Modified: stable/11/sys/kern/subr_smp.c
==============================================================================
--- stable/11/sys/kern/subr_smp.c       Tue Nov  8 08:09:48 2016        
(r308437)
+++ stable/11/sys/kern/subr_smp.c       Tue Nov  8 09:51:55 2016        
(r308438)
@@ -209,6 +209,11 @@ forward_signal(struct thread *td)
  *   1: ok
  *
  */
+#if defined(__amd64__) || defined(__i386__)
+#define        X86     1
+#else
+#define        X86     0
+#endif
 static int
 generic_stop_cpus(cpuset_t map, u_int type)
 {
@@ -220,12 +225,11 @@ generic_stop_cpus(cpuset_t map, u_int ty
        volatile cpuset_t *cpus;
 
        KASSERT(
-#if defined(__amd64__) || defined(__i386__)
-           type == IPI_STOP || type == IPI_STOP_HARD || type == IPI_SUSPEND,
-#else
-           type == IPI_STOP || type == IPI_STOP_HARD,
+           type == IPI_STOP || type == IPI_STOP_HARD
+#if X86
+           || type == IPI_SUSPEND
 #endif
-           ("%s: invalid stop type", __func__));
+           , ("%s: invalid stop type", __func__));
 
        if (!smp_started)
                return (0);
@@ -233,7 +237,7 @@ generic_stop_cpus(cpuset_t map, u_int ty
        CTR2(KTR_SMP, "stop_cpus(%s) with %u type",
            cpusetobj_strprint(cpusetbuf, &map), type);
 
-#if defined(__amd64__) || defined(__i386__)
+#if X86
        /*
         * When suspending, ensure there are are no IPIs in progress.
         * IPIs that have been issued, but not yet delivered (e.g.
@@ -245,6 +249,9 @@ generic_stop_cpus(cpuset_t map, u_int ty
                mtx_lock_spin(&smp_ipi_mtx);
 #endif
 
+#if X86
+       if (!nmi_is_broadcast || nmi_kdb_lock == 0) {
+#endif
        if (stopping_cpu != PCPU_GET(cpuid))
                while (atomic_cmpset_int(&stopping_cpu, NOCPU,
                    PCPU_GET(cpuid)) == 0)
@@ -253,8 +260,11 @@ generic_stop_cpus(cpuset_t map, u_int ty
 
        /* send the stop IPI to all CPUs in map */
        ipi_selected(map, type);
+#if X86
+       }
+#endif
 
-#if defined(__amd64__) || defined(__i386__)
+#if X86
        if (type == IPI_SUSPEND)
                cpus = &suspended_cpus;
        else
@@ -272,7 +282,7 @@ generic_stop_cpus(cpuset_t map, u_int ty
                }
        }
 
-#if defined(__amd64__) || defined(__i386__)
+#if X86
        if (type == IPI_SUSPEND)
                mtx_unlock_spin(&smp_ipi_mtx);
 #endif
@@ -295,7 +305,7 @@ stop_cpus_hard(cpuset_t map)
        return (generic_stop_cpus(map, IPI_STOP_HARD));
 }
 
-#if defined(__amd64__) || defined(__i386__)
+#if X86
 int
 suspend_cpus(cpuset_t map)
 {
@@ -325,20 +335,18 @@ generic_restart_cpus(cpuset_t map, u_int
 #endif
        volatile cpuset_t *cpus;
 
-       KASSERT(
-#if defined(__amd64__) || defined(__i386__)
-           type == IPI_STOP || type == IPI_STOP_HARD || type == IPI_SUSPEND,
-#else
-           type == IPI_STOP || type == IPI_STOP_HARD,
+       KASSERT(type == IPI_STOP || type == IPI_STOP_HARD
+#if X86
+           || type == IPI_SUSPEND
 #endif
-           ("%s: invalid stop type", __func__));
+           , ("%s: invalid stop type", __func__));
 
        if (!smp_started)
-               return 0;
+               return (0);
 
        CTR1(KTR_SMP, "restart_cpus(%s)", cpusetobj_strprint(cpusetbuf, &map));
 
-#if defined(__amd64__) || defined(__i386__)
+#if X86
        if (type == IPI_SUSPEND)
                cpus = &suspended_cpus;
        else
@@ -348,11 +356,17 @@ generic_restart_cpus(cpuset_t map, u_int
        /* signal other cpus to restart */
        CPU_COPY_STORE_REL(&map, &started_cpus);
 
+#if X86
+       if (!nmi_is_broadcast || nmi_kdb_lock == 0) {
+#endif
        /* wait for each to clear its bit */
        while (CPU_OVERLAP(cpus, &map))
                cpu_spinwait();
+#if X86
+       }
+#endif
 
-       return 1;
+       return (1);
 }
 
 int
@@ -362,7 +376,7 @@ restart_cpus(cpuset_t map)
        return (generic_restart_cpus(map, IPI_STOP));
 }
 
-#if defined(__amd64__) || defined(__i386__)
+#if X86
 int
 resume_cpus(cpuset_t map)
 {
@@ -370,6 +384,7 @@ resume_cpus(cpuset_t map)
        return (generic_restart_cpus(map, IPI_SUSPEND));
 }
 #endif
+#undef X86
 
 /*
  * All-CPU rendezvous.  CPUs are signalled, all execute the setup function 

Modified: stable/11/sys/x86/include/x86_smp.h
==============================================================================
--- stable/11/sys/x86/include/x86_smp.h Tue Nov  8 08:09:48 2016        
(r308437)
+++ stable/11/sys/x86/include/x86_smp.h Tue Nov  8 09:51:55 2016        
(r308438)
@@ -45,6 +45,9 @@ extern u_int ipi_page;
 extern u_int ipi_range;
 extern u_int ipi_range_size;
 
+extern int nmi_kdb_lock;
+extern int nmi_is_broadcast;
+
 struct cpu_info {
        int     cpu_present:1;
        int     cpu_bsp:1;

Modified: stable/11/sys/x86/include/x86_var.h
==============================================================================
--- stable/11/sys/x86/include/x86_var.h Tue Nov  8 08:09:48 2016        
(r308437)
+++ stable/11/sys/x86/include/x86_var.h Tue Nov  8 09:51:55 2016        
(r308438)
@@ -85,6 +85,7 @@ struct        reg;
 struct fpreg;
 struct  dbreg;
 struct dumperinfo;
+struct trapframe;
 
 /*
  * The interface type of the interrupt handler entry point cannot be
@@ -107,6 +108,9 @@ bool        fix_cpuid(void);
 void   fillw(int /*u_short*/ pat, void *base, size_t cnt);
 int    is_physical_memory(vm_paddr_t addr);
 int    isa_nmi(int cd);
+void   nmi_call_kdb(u_int cpu, u_int type, struct trapframe *frame);
+void   nmi_call_kdb_smp(u_int type, struct trapframe *frame);
+void   nmi_handle_intr(u_int type, struct trapframe *frame);
 void   pagecopy(void *from, void *to);
 void   printcpuinfo(void);
 int    user_dbreg_trap(void);

Modified: stable/11/sys/x86/x86/cpu_machdep.c
==============================================================================
--- stable/11/sys/x86/x86/cpu_machdep.c Tue Nov  8 08:09:48 2016        
(r308437)
+++ stable/11/sys/x86/x86/cpu_machdep.c Tue Nov  8 09:51:55 2016        
(r308438)
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
 #include "opt_ddb.h"
 #include "opt_inet.h"
 #include "opt_isa.h"
+#include "opt_kdb.h"
 #include "opt_kstack_pages.h"
 #include "opt_maxmem.h"
 #include "opt_mp_watchdog.h"
@@ -526,3 +527,55 @@ idle_sysctl(SYSCTL_HANDLER_ARGS)
 
 SYSCTL_PROC(_machdep, OID_AUTO, idle, CTLTYPE_STRING | CTLFLAG_RW, 0, 0,
     idle_sysctl, "A", "currently selected idle function");
+
+static int panic_on_nmi = 1;
+SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RWTUN,
+    &panic_on_nmi, 0,
+    "Panic on NMI");
+int nmi_is_broadcast = 1;
+SYSCTL_INT(_machdep, OID_AUTO, nmi_is_broadcast, CTLFLAG_RWTUN,
+    &nmi_is_broadcast, 0,
+    "Chipset NMI is broadcast");
+#ifdef KDB
+int kdb_on_nmi = 1;
+SYSCTL_INT(_machdep, OID_AUTO, kdb_on_nmi, CTLFLAG_RWTUN,
+    &kdb_on_nmi, 0,
+    "Go to KDB on NMI");
+#endif
+
+#ifdef DEV_ISA
+void
+nmi_call_kdb(u_int cpu, u_int type, struct trapframe *frame)
+{
+
+       /* machine/parity/power fail/"kitchen sink" faults */
+       if (isa_nmi(frame->tf_err) == 0) {
+#ifdef KDB
+               /*
+                * NMI can be hooked up to a pushbutton for debugging.
+                */
+               if (kdb_on_nmi) {
+                       printf("NMI/cpu%d ... going to debugger\n", cpu);
+                       kdb_trap(type, 0, frame);
+               }
+#endif /* KDB */
+       } else if (panic_on_nmi) {
+               panic("NMI indicates hardware failure");
+       }
+}
+#endif
+
+void
+nmi_handle_intr(u_int type, struct trapframe *frame)
+{
+
+#ifdef DEV_ISA
+#ifdef SMP
+       if (nmi_is_broadcast) {
+               nmi_call_kdb_smp(type, frame);
+               return;
+       }
+#endif
+       nmi_call_kdb(PCPU_GET(cpuid), type, frame);
+#endif
+}

Modified: stable/11/sys/x86/x86/mp_x86.c
==============================================================================
--- stable/11/sys/x86/x86/mp_x86.c      Tue Nov  8 08:09:48 2016        
(r308437)
+++ stable/11/sys/x86/x86/mp_x86.c      Tue Nov  8 09:51:55 2016        
(r308438)
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
 #include "opt_apic.h"
 #endif
 #include "opt_cpu.h"
+#include "opt_isa.h"
 #include "opt_kstack_pages.h"
 #include "opt_pmap.h"
 #include "opt_sched.h"
@@ -140,6 +141,7 @@ int cpu_apic_ids[MAXCPU];
 volatile u_int cpu_ipi_pending[MAXCPU];
 
 static void    release_aps(void *dummy);
+static void    cpustop_handler_post(u_int cpu);
 
 static int     hyperthreading_allowed = 1;
 SYSCTL_INT(_machdep, OID_AUTO, hyperthreading_allowed, CTLFLAG_RDTUN,
@@ -1215,6 +1217,32 @@ ipi_nmi_handler(void)
        return (0);
 }
 
+#ifdef DEV_ISA
+int nmi_kdb_lock;
+
+void
+nmi_call_kdb_smp(u_int type, struct trapframe *frame)
+{
+       int cpu;
+       bool call_post;
+
+       cpu = PCPU_GET(cpuid);
+       if (atomic_cmpset_acq_int(&nmi_kdb_lock, 0, 1)) {
+               nmi_call_kdb(cpu, type, frame);
+               call_post = false;
+       } else {
+               savectx(&stoppcbs[cpu]);
+               CPU_SET_ATOMIC(cpu, &stopped_cpus);
+               while (!atomic_cmpset_acq_int(&nmi_kdb_lock, 0, 1))
+                       ia32_pause();
+               call_post = true;
+       }
+       atomic_store_rel_int(&nmi_kdb_lock, 0);
+       if (call_post)
+               cpustop_handler_post(cpu);
+}
+#endif
+
 /*
  * Handle an IPI_STOP by saving our current context and spinning until we
  * are resumed.
@@ -1235,6 +1263,13 @@ cpustop_handler(void)
        while (!CPU_ISSET(cpu, &started_cpus))
            ia32_pause();
 
+       cpustop_handler_post(cpu);
+}
+
+static void
+cpustop_handler_post(u_int cpu)
+{
+
        CPU_CLR_ATOMIC(cpu, &started_cpus);
        CPU_CLR_ATOMIC(cpu, &stopped_cpus);
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to