summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2019-03-27 09:43:53 +0000
committerJohn Levon <john.levon@joyent.com>2019-03-27 09:44:19 +0000
commitdc238736b55afd3a593354a3a7233204ca25b27c (patch)
tree04204895aae0eb6d7e95288427a73141028b745a
parent5ffb784f5a3c76e1a0dfe2349748d3a9a8f33082 (diff)
downloadillumos-joyent-dc238736b55afd3a593354a3a7233204ca25b27c.tar.gz
OS-7675 would like a way to set NMI behavior at boot
Reviewed by: Robert Mustacchi <rm@joyent.com> Approved by: Robert Mustacchi <rm@joyent.com>
-rw-r--r--usr/src/uts/i86pc/io/pcplusmp/apic_common.c41
-rw-r--r--usr/src/uts/i86pc/os/fakebop.c18
-rw-r--r--usr/src/uts/i86pc/os/mlsetup.c20
-rw-r--r--usr/src/uts/i86pc/sys/apic_common.h10
-rw-r--r--usr/src/uts/intel/sys/bootconf.h4
5 files changed, 78 insertions, 15 deletions
diff --git a/usr/src/uts/i86pc/io/pcplusmp/apic_common.c b/usr/src/uts/i86pc/io/pcplusmp/apic_common.c
index 30644ad12a..b1a0b9c3d0 100644
--- a/usr/src/uts/i86pc/io/pcplusmp/apic_common.c
+++ b/usr/src/uts/i86pc/io/pcplusmp/apic_common.c
@@ -23,7 +23,7 @@
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
- * Copyright 2018 Joyent, Inc.
+ * Copyright 2019, Joyent, Inc.
* Copyright (c) 2016, 2017 by Delphix. All rights reserved.
*/
@@ -808,6 +808,8 @@ gethrtime_again:
void
apic_nmi_intr(caddr_t arg, struct regs *rp)
{
+ int action = nmi_action;
+
if (apic_shutdown_processors) {
apic_disable_local_apic();
return;
@@ -819,18 +821,41 @@ apic_nmi_intr(caddr_t arg, struct regs *rp)
return;
apic_num_nmis++;
- if (apic_kmdb_on_nmi && psm_debugger()) {
- debug_enter("NMI received: entering kmdb\n");
- } else if (apic_panic_on_nmi) {
- /* Keep panic from entering kmdb. */
- nopanicdebug = 1;
- panic("NMI received\n");
- } else {
+ /*
+ * "nmi_action" always over-rides the older way of doing this, unless we
+ * can't actually drop into kmdb when requested.
+ */
+ if (action == NMI_ACTION_KMDB && !psm_debugger())
+ action = NMI_ACTION_UNSET;
+
+ if (action == NMI_ACTION_UNSET) {
+ if (apic_kmdb_on_nmi && psm_debugger())
+ action = NMI_ACTION_KMDB;
+ else if (apic_panic_on_nmi)
+ action = NMI_ACTION_PANIC;
+ else
+ action = NMI_ACTION_IGNORE;
+ }
+
+ switch (action) {
+ case NMI_ACTION_IGNORE:
/*
* prom_printf is the best shot we have of something which is
* problem free from high level/NMI type of interrupts
*/
prom_printf("NMI received\n");
+ break;
+
+ case NMI_ACTION_PANIC:
+ /* Keep panic from entering kmdb. */
+ nopanicdebug = 1;
+ panic("NMI received\n");
+ break;
+
+ case NMI_ACTION_KMDB:
+ default:
+ debug_enter("NMI received: entering kmdb\n");
+ break;
}
lock_clear(&apic_nmi_lock);
diff --git a/usr/src/uts/i86pc/os/fakebop.c b/usr/src/uts/i86pc/os/fakebop.c
index 7bbd6b369f..8ba2e74681 100644
--- a/usr/src/uts/i86pc/os/fakebop.c
+++ b/usr/src/uts/i86pc/os/fakebop.c
@@ -2915,10 +2915,8 @@ boot_compinfo(int fd, struct compinfo *cbp)
return (0);
}
-#define BP_MAX_STRLEN 32
-
/*
- * Get value for given boot property
+ * Get an integer value for given boot property
*/
int
bootprop_getval(const char *prop_name, u_longlong_t *prop_value)
@@ -2928,7 +2926,7 @@ bootprop_getval(const char *prop_name, u_longlong_t *prop_value)
u_longlong_t value;
boot_prop_len = BOP_GETPROPLEN(bootops, prop_name);
- if (boot_prop_len < 0 || boot_prop_len > sizeof (str) ||
+ if (boot_prop_len < 0 || boot_prop_len >= sizeof (str) ||
BOP_GETPROP(bootops, prop_name, str) < 0 ||
kobj_getvalue(str, &value) == -1)
return (-1);
@@ -2938,3 +2936,15 @@ bootprop_getval(const char *prop_name, u_longlong_t *prop_value)
return (0);
}
+
+int
+bootprop_getstr(const char *prop_name, char *buf, size_t buflen)
+{
+ int boot_prop_len = BOP_GETPROPLEN(bootops, prop_name);
+
+ if (boot_prop_len < 0 || boot_prop_len >= buflen ||
+ BOP_GETPROP(bootops, prop_name, buf) < 0)
+ return (-1);
+
+ return (0);
+}
diff --git a/usr/src/uts/i86pc/os/mlsetup.c b/usr/src/uts/i86pc/os/mlsetup.c
index 7c17aab541..94d4695141 100644
--- a/usr/src/uts/i86pc/os/mlsetup.c
+++ b/usr/src/uts/i86pc/os/mlsetup.c
@@ -23,7 +23,7 @@
*
* Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
- * Copyright 2018 Joyent, Inc.
+ * Copyright 2019, Joyent, Inc.
*/
/*
* Copyright (c) 2010, Intel Corporation.
@@ -61,6 +61,8 @@
#include <sys/archsystm.h>
#include <sys/promif.h>
#include <sys/pci_cfgspace.h>
+#include <sys/apic.h>
+#include <sys/apic_common.h>
#include <sys/bootvfs.h>
#include <sys/tsc.h>
#ifdef __xpv
@@ -79,6 +81,8 @@ extern uint32_t cpuid_feature_ecx_exclude;
extern uint32_t cpuid_feature_edx_include;
extern uint32_t cpuid_feature_edx_exclude;
+int nmi_action = NMI_ACTION_UNSET;
+
/*
* Set console mode
*/
@@ -103,6 +107,7 @@ void
mlsetup(struct regs *rp)
{
u_longlong_t prop_value;
+ char prop_str[BP_MAX_STRLEN];
extern struct classfuncs sys_classfuncs;
extern disp_t cpu0_disp;
extern char t0stack[];
@@ -149,6 +154,19 @@ mlsetup(struct regs *rp)
cpuid_feature_edx_exclude = (uint32_t)prop_value;
#if !defined(__xpv)
+ if (bootprop_getstr("nmi", prop_str, sizeof (prop_str)) == 0) {
+ if (strcmp(prop_str, "ignore") == 0) {
+ nmi_action = NMI_ACTION_IGNORE;
+ } else if (strcmp(prop_str, "panic") == 0) {
+ nmi_action = NMI_ACTION_PANIC;
+ } else if (strcmp(prop_str, "kmdb") == 0) {
+ nmi_action = NMI_ACTION_KMDB;
+ } else {
+ prom_printf("unix: ignoring unknown nmi=%s\n",
+ prop_str);
+ }
+ }
+
/*
* Check to see if KPTI has been explicitly enabled or disabled.
* We have to check this before init_desctbls().
diff --git a/usr/src/uts/i86pc/sys/apic_common.h b/usr/src/uts/i86pc/sys/apic_common.h
index 03e851a4dc..58b9bb93a6 100644
--- a/usr/src/uts/i86pc/sys/apic_common.h
+++ b/usr/src/uts/i86pc/sys/apic_common.h
@@ -23,7 +23,7 @@
* Copyright (c) 2017 by Delphix. All rights reserved.
*/
/*
- * Copyright 2018 Joyent, Inc.
+ * Copyright 2019, Joyent, Inc.
*/
#ifndef _SYS_APIC_COMMON_H
@@ -155,7 +155,6 @@ extern lock_t apic_nmi_lock;
extern lock_t apic_error_lock;
/* Patchable global variables. */
-extern int apic_kmdb_on_nmi; /* 0 - no, 1 - yes enter kmdb */
extern uint32_t apic_divide_reg_init; /* 0 - divide by 2 */
extern apic_intrmap_ops_t *apic_vt_ops;
@@ -202,6 +201,13 @@ extern int apic_msix_enable;
extern uint32_t apic_get_localapicid(uint32_t cpuid);
extern uchar_t apic_get_ioapicid(uchar_t ioapicindex);
+#define NMI_ACTION_UNSET (0)
+#define NMI_ACTION_PANIC (1)
+#define NMI_ACTION_IGNORE (2)
+#define NMI_ACTION_KMDB (3)
+
+extern int nmi_action;
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/intel/sys/bootconf.h b/usr/src/uts/intel/sys/bootconf.h
index 27a89206cf..f0ade9d94d 100644
--- a/usr/src/uts/intel/sys/bootconf.h
+++ b/usr/src/uts/intel/sys/bootconf.h
@@ -23,6 +23,7 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2016 Nexenta Systems, Inc.
+ * Copyright 2019, Joyent, Inc.
*/
#ifndef _SYS_BOOTCONF_H
@@ -46,6 +47,8 @@
extern "C" {
#endif
+#define BP_MAX_STRLEN 32
+
/*
* Boot property names
*/
@@ -243,6 +246,7 @@ extern void bop_panic(const char *, ...)
extern void boot_prop_finish(void);
extern int bootprop_getval(const char *, u_longlong_t *);
+extern int bootprop_getstr(const char *, char *, size_t);
/*
* Back door to fakebop.c to get physical memory allocated.