Skip to content

Commit ec2f16f

Browse files
jwrdegoedeIngo Molnar
authored andcommitted
x86/platform/uv: Rework NMI "action" modparam handling
Rework NMI "action" modparam handling: - Replace the uv_nmi_action string with an enum; and - Use sysfs_match_string() for string parsing in param_set_action() No change in functionality intended. Suggested-by: Steve Wahl <[email protected]> Signed-off-by: Hans de Goede <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Tested-by: Steve Wahl <[email protected]> Reviewed-by: Justin Stitt <[email protected]> Reviewed-by: Steve Wahl <[email protected]> Reviewed-by: Andy Shevchenko <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent f0b0d40 commit ec2f16f

File tree

1 file changed

+57
-47
lines changed

1 file changed

+57
-47
lines changed

arch/x86/platform/uv/uv_nmi.c

Lines changed: 57 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/sched.h>
1818
#include <linux/sched/debug.h>
1919
#include <linux/slab.h>
20+
#include <linux/string.h>
2021
#include <linux/clocksource.h>
2122

2223
#include <asm/apic.h>
@@ -178,65 +179,67 @@ module_param_named(debug, uv_nmi_debug, int, 0644);
178179
} while (0)
179180

180181
/* Valid NMI Actions */
181-
#define ACTION_LEN 16
182-
static struct nmi_action {
183-
char *action;
184-
char *desc;
185-
} valid_acts[] = {
186-
{ "kdump", "do kernel crash dump" },
187-
{ "dump", "dump process stack for each cpu" },
188-
{ "ips", "dump Inst Ptr info for each cpu" },
189-
{ "kdb", "enter KDB (needs kgdboc= assignment)" },
190-
{ "kgdb", "enter KGDB (needs gdb target remote)" },
191-
{ "health", "check if CPUs respond to NMI" },
182+
enum action_t {
183+
nmi_act_kdump,
184+
nmi_act_dump,
185+
nmi_act_ips,
186+
nmi_act_kdb,
187+
nmi_act_kgdb,
188+
nmi_act_health,
189+
nmi_act_max
192190
};
193-
typedef char action_t[ACTION_LEN];
194-
static action_t uv_nmi_action = { "dump" };
191+
192+
static const char * const actions[nmi_act_max] = {
193+
[nmi_act_kdump] = "kdump",
194+
[nmi_act_dump] = "dump",
195+
[nmi_act_ips] = "ips",
196+
[nmi_act_kdb] = "kdb",
197+
[nmi_act_kgdb] = "kgdb",
198+
[nmi_act_health] = "health",
199+
};
200+
201+
static const char * const actions_desc[nmi_act_max] = {
202+
[nmi_act_kdump] = "do kernel crash dump",
203+
[nmi_act_dump] = "dump process stack for each cpu",
204+
[nmi_act_ips] = "dump Inst Ptr info for each cpu",
205+
[nmi_act_kdb] = "enter KDB (needs kgdboc= assignment)",
206+
[nmi_act_kgdb] = "enter KGDB (needs gdb target remote)",
207+
[nmi_act_health] = "check if CPUs respond to NMI",
208+
};
209+
210+
static enum action_t uv_nmi_action = nmi_act_dump;
195211

196212
static int param_get_action(char *buffer, const struct kernel_param *kp)
197213
{
198-
return sprintf(buffer, "%s\n", uv_nmi_action);
214+
return sprintf(buffer, "%s\n", actions[uv_nmi_action]);
199215
}
200216

201217
static int param_set_action(const char *val, const struct kernel_param *kp)
202218
{
203-
int i;
204-
int n = ARRAY_SIZE(valid_acts);
205-
char arg[ACTION_LEN];
206-
207-
/* (remove possible '\n') */
208-
strscpy(arg, val, strnchrnul(val, sizeof(arg)-1, '\n') - val + 1);
209-
210-
for (i = 0; i < n; i++)
211-
if (!strcmp(arg, valid_acts[i].action))
212-
break;
219+
int i, n = ARRAY_SIZE(actions);
213220

214-
if (i < n) {
215-
strscpy(uv_nmi_action, arg, sizeof(uv_nmi_action));
216-
pr_info("UV: New NMI action:%s\n", uv_nmi_action);
221+
i = sysfs_match_string(actions, val);
222+
if (i >= 0) {
223+
uv_nmi_action = i;
224+
pr_info("UV: New NMI action:%s\n", actions[i]);
217225
return 0;
218226
}
219227

220-
pr_err("UV: Invalid NMI action:%s, valid actions are:\n", arg);
228+
pr_err("UV: Invalid NMI action. Valid actions are:\n");
221229
for (i = 0; i < n; i++)
222-
pr_err("UV: %-8s - %s\n",
223-
valid_acts[i].action, valid_acts[i].desc);
230+
pr_err("UV: %-8s - %s\n", actions[i], actions_desc[i]);
231+
224232
return -EINVAL;
225233
}
226234

227235
static const struct kernel_param_ops param_ops_action = {
228236
.get = param_get_action,
229237
.set = param_set_action,
230238
};
231-
#define param_check_action(name, p) __param_check(name, p, action_t)
239+
#define param_check_action(name, p) __param_check(name, p, enum action_t)
232240

233241
module_param_named(action, uv_nmi_action, action, 0644);
234242

235-
static inline bool uv_nmi_action_is(const char *action)
236-
{
237-
return (strncmp(uv_nmi_action, action, strlen(action)) == 0);
238-
}
239-
240243
/* Setup which NMI support is present in system */
241244
static void uv_nmi_setup_mmrs(void)
242245
{
@@ -727,10 +730,10 @@ static void uv_nmi_dump_state_cpu(int cpu, struct pt_regs *regs)
727730
if (cpu == 0)
728731
uv_nmi_dump_cpu_ip_hdr();
729732

730-
if (current->pid != 0 || !uv_nmi_action_is("ips"))
733+
if (current->pid != 0 || uv_nmi_action != nmi_act_ips)
731734
uv_nmi_dump_cpu_ip(cpu, regs);
732735

733-
if (uv_nmi_action_is("dump")) {
736+
if (uv_nmi_action == nmi_act_dump) {
734737
pr_info("UV:%sNMI process trace for CPU %d\n", dots, cpu);
735738
show_regs(regs);
736739
}
@@ -798,7 +801,7 @@ static void uv_nmi_dump_state(int cpu, struct pt_regs *regs, int master)
798801
int saved_console_loglevel = console_loglevel;
799802

800803
pr_alert("UV: tracing %s for %d CPUs from CPU %d\n",
801-
uv_nmi_action_is("ips") ? "IPs" : "processes",
804+
uv_nmi_action == nmi_act_ips ? "IPs" : "processes",
802805
atomic_read(&uv_nmi_cpus_in_nmi), cpu);
803806

804807
console_loglevel = uv_nmi_loglevel;
@@ -874,7 +877,7 @@ static inline int uv_nmi_kdb_reason(void)
874877
static inline int uv_nmi_kdb_reason(void)
875878
{
876879
/* Ensure user is expecting to attach gdb remote */
877-
if (uv_nmi_action_is("kgdb"))
880+
if (uv_nmi_action == nmi_act_kgdb)
878881
return 0;
879882

880883
pr_err("UV: NMI error: KDB is not enabled in this kernel\n");
@@ -950,28 +953,35 @@ static int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
950953
master = (atomic_read(&uv_nmi_cpu) == cpu);
951954

952955
/* If NMI action is "kdump", then attempt to do it */
953-
if (uv_nmi_action_is("kdump")) {
956+
if (uv_nmi_action == nmi_act_kdump) {
954957
uv_nmi_kdump(cpu, master, regs);
955958

956959
/* Unexpected return, revert action to "dump" */
957960
if (master)
958-
strscpy(uv_nmi_action, "dump", sizeof(uv_nmi_action));
961+
uv_nmi_action = nmi_act_dump;
959962
}
960963

961964
/* Pause as all CPU's enter the NMI handler */
962965
uv_nmi_wait(master);
963966

964967
/* Process actions other than "kdump": */
965-
if (uv_nmi_action_is("health")) {
968+
switch (uv_nmi_action) {
969+
case nmi_act_health:
966970
uv_nmi_action_health(cpu, regs, master);
967-
} else if (uv_nmi_action_is("ips") || uv_nmi_action_is("dump")) {
971+
break;
972+
case nmi_act_ips:
973+
case nmi_act_dump:
968974
uv_nmi_dump_state(cpu, regs, master);
969-
} else if (uv_nmi_action_is("kdb") || uv_nmi_action_is("kgdb")) {
975+
break;
976+
case nmi_act_kdb:
977+
case nmi_act_kgdb:
970978
uv_call_kgdb_kdb(cpu, regs, master);
971-
} else {
979+
break;
980+
default:
972981
if (master)
973-
pr_alert("UV: unknown NMI action: %s\n", uv_nmi_action);
982+
pr_alert("UV: unknown NMI action: %d\n", uv_nmi_action);
974983
uv_nmi_sync_exit(master);
984+
break;
975985
}
976986

977987
/* Clear per_cpu "in_nmi" flag */

0 commit comments

Comments
 (0)