From owner-svn-src-stable-11@freebsd.org Tue Nov 8 09:51:57 2016 Return-Path: Delivered-To: svn-src-stable-11@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 04C73C3662B; Tue, 8 Nov 2016 09:51:57 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C670ACD7; Tue, 8 Nov 2016 09:51:56 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id uA89ptD8032214; Tue, 8 Nov 2016 09:51:55 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id uA89pt4W032207; Tue, 8 Nov 2016 09:51:55 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201611080951.uA89pt4W032207@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Tue, 8 Nov 2016 09:51:55 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r308438 - in stable/11/sys: amd64/amd64 i386/i386 kern x86/include x86/x86 X-SVN-Group: stable-11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-11@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for only the 11-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 08 Nov 2016 09:51:57 -0000 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);