1 /* Copyright (C) 2004,2005,2006 Andi Kleen, SuSE Labs.
2    Copyright (C) 2008 Intel Corporation
3    Authors: Andi Kleen, Ying Huang
4    Decode IA32/x86-64 machine check events in /dev/mcelog.
5 
6    mcelog is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public
8    License as published by the Free Software Foundation; version
9    2.
10 
11    mcelog is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    General Public License for more details.
15 
16    You should find a copy of v2 of the GNU General Public License somewhere
17    on your Linux system; if not, write to the Free Software Foundation,
18    Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
19 
20 #define _GNU_SOURCE 1
21 #include <sys/fcntl.h>
22 #include <sys/ioctl.h>
23 #ifdef __Linux__
24 #include <asm/types.h>
25 #include <asm/ioctls.h>
26 #include <linux/limits.h>
27 #endif
28 #ifdef __FreeBSD__
29 #include <sys/types.h>
30 #include <sys/queue.h>
31 #include <sys/sysctl.h>
32 #include <machine/cpufunc.h>
33 #include <machine/cputypes.h>
34 #include <machine/specialreg.h>
35 #include <err.h>
36 #include <kvm.h>
37 #include <limits.h>
38 #endif
39 #undef CPU_P4
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <syslog.h>
45 #include <ctype.h>
46 #include <poll.h>
47 #include <time.h>
48 #include <getopt.h>
49 #include <errno.h>
50 #include <stddef.h>
51 #include <assert.h>
52 #include <signal.h>
53 #include <pwd.h>
54 #include <fnmatch.h>
55 #include "mcelog.h"
56 #include "paths.h"
57 #include "k8.h"
58 #include "intel.h"
59 #include "p4.h"
60 #include "dmi.h"
61 #include "dimm.h"
62 #include "tsc.h"
63 #include "version.h"
64 #include "config.h"
65 #include "memutil.h"
66 #include "eventloop.h"
67 #include "memdb.h"
68 #include "server.h"
69 #include "trigger.h"
70 #include "client.h"
71 #include "msg.h"
72 #include "yellow.h"
73 #include "page.h"
74 #include "bus.h"
75 #include "unknown.h"
76 
77 struct mca_record {
78 	uint64_t	mr_status;
79 	uint64_t	mr_addr;
80 	uint64_t	mr_misc;
81 	uint64_t	mr_tsc;
82 	int		mr_apic_id;
83 	int		mr_bank;
84 	uint64_t	mr_mcg_cap;
85 	uint64_t	mr_mcg_status;
86 	int		mr_cpu_id;
87 	int		mr_cpu_vendor_id;
88 	int		mr_cpu;
89 };
90 
91 enum cputype cputype = CPU_GENERIC;
92 
93 #ifdef __Linux__
94 char *logfn = LOG_DEV_FILENAME;
95 #endif
96 
97 int ignore_nodev;
98 int filter_bogus = 1;
99 int cpu_forced;
100 static double cpumhz;
101 static int cpumhz_forced;
102 int ascii_mode;
103 int dump_raw_ascii;
104 int daemon_mode;
105 static char *inputfile;
106 #ifdef __Linux__
107 char *processor_flags;
108 #endif
109 static int foreground;
110 int filter_memory_errors;
111 static struct config_cred runcred = { .uid = -1U, .gid = -1U };
112 static int numerrors;
113 static char pidfile_default[] = PID_FILE;
114 static char logfile_default[] = LOG_FILE;
115 static char *pidfile = pidfile_default;
116 static char *logfile;
117 #ifdef __FreeBSD__
118 static char *execfile;
119 static char *corefile;
120 #endif
121 static int debug_numerrors;
122 int imc_log = -1;
123 static int check_only = 0;
124 int max_corr_err_counters = 4158;
125 
126 static int is_cpu_supported(void);
127 
128 
disclaimer(void)129 static void disclaimer(void)
130 {
131 	Wprintf("Hardware event. This is not a software error.\n");
132 }
133 
extended_bankname(unsigned bank)134 static char *extended_bankname(unsigned bank)
135 {
136 	static char buf[64];
137 	switch (bank) {
138 	case MCE_THERMAL_BANK:
139 		return "THERMAL EVENT";
140 	case MCE_TIMEOUT_BANK:
141 		return "Timeout waiting for exception on other CPUs";
142 	case K8_MCE_THRESHOLD_BASE ... K8_MCE_THRESHOLD_TOP:
143 		return k8_bank_name(bank);
144 
145 		/* add more extended banks here */
146 
147 	case MCE_APEI_BANK:
148 		return "ACPI/APEI reported error";
149 
150 	default:
151 		sprintf(buf, "Undecoded extended event %x", bank);
152 		return buf;
153 	}
154 }
155 
bankname(unsigned bank)156 static char *bankname(unsigned bank)
157 {
158 	static char numeric[64];
159 	if (bank >= MCE_EXTENDED_BANK)
160 		return extended_bankname(bank);
161 
162 	switch (cputype) {
163 	case CPU_K8:
164 		return k8_bank_name(bank);
165 	CASE_INTEL_CPUS:
166 		return intel_bank_name(bank);
167 	/* add banks of other cpu types here */
168 	default:
169 		sprintf(numeric, "BANK %d", bank);
170 		return numeric;
171 	}
172 }
173 
resolveaddr(unsigned long long addr)174 static void resolveaddr(unsigned long long addr)
175 {
176 	if (addr && do_dmi && dmi_forced)
177 		dmi_decodeaddr(addr);
178 	/* Should check for PCI resources here too */
179 }
180 
mce_filter(struct mce * m,unsigned recordlen)181 static int mce_filter(struct mce *m, unsigned recordlen)
182 {
183 	if (!filter_bogus)
184 		return 1;
185 	/* Filter out known broken MCEs */
186 	switch (cputype) {
187 	case CPU_K8:
188 		return mce_filter_k8(m);
189 		/* add more buggy CPUs here */
190 	CASE_INTEL_CPUS:
191 		return mce_filter_intel(m, recordlen);
192 	default:
193 	case CPU_GENERIC:
194 		return 1;
195 	}
196 }
197 
print_tsc(int cpunum,__u64 tsc,unsigned long time)198 static void print_tsc(int cpunum, __u64 tsc, unsigned long time)
199 {
200 	int ret = -1;
201 	char *buf = NULL;
202 
203 	if (cpumhz_forced)
204 		ret = decode_tsc_forced(&buf, cpumhz, tsc);
205 	else if (!time)
206 		ret = decode_tsc_current(&buf, cpunum, cputype, cpumhz, tsc);
207 	Wprintf("TSC %llx %s", tsc, ret >= 0 && buf ? buf : "");
208 	free(buf);
209 }
210 
211 struct cpuid1 {
212 	unsigned stepping : 4;
213 	unsigned model : 4;
214 	unsigned family : 4;
215 	unsigned type : 2;
216 	unsigned res1 : 2;
217 	unsigned ext_model : 4;
218 	unsigned ext_family : 8;
219 	unsigned res2 : 4;
220 };
221 
parse_cpuid(u32 cpuid,u32 * family,u32 * model,u32 * stepping)222 static void parse_cpuid(u32 cpuid, u32 *family, u32 *model, u32 *stepping)
223 {
224 	union {
225 		struct cpuid1 c;
226 		u32 v;
227 	} c;
228 
229 	/* Algorithm from IA32 SDM 2a 3-191 */
230 	c.v = cpuid;
231 	*family = c.c.family;
232 	if (*family == 0xf)
233 		*family += c.c.ext_family;
234 	*model = c.c.model;
235 	if (*family == 6 || *family == 0xf)
236 		*model += c.c.ext_model << 4;
237 	*stepping = c.c.stepping;
238 }
239 
240 #ifdef __Linux__
unparse_cpuid(unsigned family,unsigned model)241 static u32 unparse_cpuid(unsigned family, unsigned model)
242 {
243 	union {
244 		struct cpuid1 c;
245 		u32 v;
246        } c;
247 
248 	c.c.family = family;
249 	if (family >= 0xf) {
250 		c.c.family = 0xf;
251 		c.c.ext_family = family - 0xf;
252 	}
253 	c.c.model = model & 0xf;
254 	if (family == 6 || family == 0xf)
255 		c.c.ext_model = model >> 4;
256 	return c.v;
257 }
258 #endif
259 
260 static char *cputype_name[] = {
261 	[CPU_GENERIC] = "generic CPU",
262 	[CPU_P6OLD] = "Intel PPro/P2/P3/old Xeon",
263 	[CPU_CORE2] = "Intel Core", /* 65nm and 45nm */
264 	[CPU_K8] = "AMD K8 and derivates",
265 	[CPU_P4] = "Intel P4",
266 	[CPU_NEHALEM] = "Intel Xeon 5500 series / Core i3/5/7 (\"Nehalem/Westmere\")",
267 	[CPU_DUNNINGTON] = "Intel Xeon 7400 series",
268 	[CPU_TULSA] = "Intel Xeon 7100 series",
269 	[CPU_INTEL] = "Intel generic architectural MCA",
270 	[CPU_XEON75XX] = "Intel Xeon 7500 series",
271 	[CPU_SANDY_BRIDGE] = "Sandy Bridge", /* Fill in better name */
272 	[CPU_SANDY_BRIDGE_EP] = "Sandy Bridge EP", /* Fill in better name */
273 	[CPU_IVY_BRIDGE] = "Ivy Bridge", /* Fill in better name */
274 	[CPU_IVY_BRIDGE_EPEX] = "Intel Xeon v2 (Ivy Bridge) EP/EX", /* Fill in better name */
275 	[CPU_HASWELL] = "Haswell", /* Fill in better name */
276 	[CPU_HASWELL_EPEX] = "Intel Xeon v3 (Haswell) EP/EX",
277 	[CPU_BROADWELL] = "Broadwell",
278 	[CPU_BROADWELL_DE] = "Intel Xeon (Broadwell) D family",
279 	[CPU_BROADWELL_EPEX] = "Intel Xeon v4 (Broadwell) EP/EX",
280 	[CPU_KNIGHTS_LANDING] = "Knights Landing",
281 	[CPU_KNIGHTS_MILL] = "Knights Mill",
282 	[CPU_ATOM] = "ATOM",
283 	[CPU_SKYLAKE] = "Skylake",
284 	[CPU_SKYLAKE_XEON] = "Skylake server",
285 	[CPU_KABYLAKE] = "Kabylake",
286 	[CPU_DENVERTON] = "Denverton",
287 	[CPU_ICELAKE] = "Icelake",
288 	[CPU_ICELAKE_XEON] = "Icelake server",
289 	[CPU_ICELAKE_DE] = "Icelake server D Family",
290 	[CPU_TREMONT_D] = "Tremont microserver",
291 	[CPU_COMETLAKE] = "Cometlake",
292 	[CPU_TIGERLAKE] = "Tigerlake",
293 	[CPU_ROCKETLAKE] = "Rocketlake",
294 	[CPU_ALDERLAKE] = "Alderlake",
295 	[CPU_LAKEFIELD] = "Lakefield",
296 	[CPU_SAPPHIRERAPIDS] = "Sapphirerapids server",
297 };
298 
299 static struct config_choice cpu_choices[] = {
300 	{ "generic", CPU_GENERIC },
301 	{ "p6old", CPU_P6OLD },
302 	{ "core2", CPU_CORE2 },
303 	{ "k8", CPU_K8 },
304 	{ "p4", CPU_P4 },
305 	{ "dunnington", CPU_DUNNINGTON },
306 	{ "xeon74xx", CPU_DUNNINGTON },
307 	{ "xeon7400", CPU_DUNNINGTON },
308 	{ "xeon5500", CPU_NEHALEM },
309 	{ "xeon5200", CPU_CORE2 },
310 	{ "xeon5000", CPU_P4 },
311 	{ "xeon5100", CPU_CORE2 },
312 	{ "xeon3100", CPU_CORE2 },
313 	{ "xeon3200", CPU_CORE2 },
314 	{ "core_i7", CPU_NEHALEM },
315 	{ "core_i5", CPU_NEHALEM },
316 	{ "core_i3", CPU_NEHALEM },
317 	{ "nehalem", CPU_NEHALEM },
318 	{ "westmere", CPU_NEHALEM },
319 	{ "xeon71xx", CPU_TULSA },
320 	{ "xeon7100", CPU_TULSA },
321 	{ "tulsa", CPU_TULSA },
322 	{ "intel", CPU_INTEL },
323 	{ "xeon75xx", CPU_XEON75XX },
324 	{ "xeon7500", CPU_XEON75XX },
325 	{ "xeon7200", CPU_CORE2 },
326 	{ "xeon7100", CPU_P4 },
327 	{ "sandybridge", CPU_SANDY_BRIDGE }, /* Fill in better name */
328 	{ "sandybridge-ep", CPU_SANDY_BRIDGE_EP }, /* Fill in better name */
329 	{ "ivybridge", CPU_IVY_BRIDGE }, /* Fill in better name */
330 	{ "ivybridge-ep", CPU_IVY_BRIDGE_EPEX },
331 	{ "ivybridge-ex", CPU_IVY_BRIDGE_EPEX },
332 	{ "haswell", CPU_HASWELL }, /* Fill in better name */
333 	{ "haswell-ep", CPU_HASWELL_EPEX },
334 	{ "haswell-ex", CPU_HASWELL_EPEX },
335 	{ "broadwell", CPU_BROADWELL },
336 	{ "broadwell-d", CPU_BROADWELL_DE },
337 	{ "broadwell-ep", CPU_BROADWELL_EPEX },
338 	{ "broadwell-ex", CPU_BROADWELL_EPEX },
339 	{ "knightslanding", CPU_KNIGHTS_LANDING },
340 	{ "knightsmill", CPU_KNIGHTS_MILL },
341 	{ "xeon-v2", CPU_IVY_BRIDGE_EPEX },
342 	{ "xeon-v3", CPU_HASWELL_EPEX },
343 	{ "xeon-v4", CPU_BROADWELL_EPEX },
344 	{ "atom", CPU_ATOM },
345 	{ "skylake", CPU_SKYLAKE },
346 	{ "skylake_server", CPU_SKYLAKE_XEON },
347 	{ "cascadelake_server", CPU_SKYLAKE_XEON },
348 	{ "kabylake", CPU_KABYLAKE },
349 	{ "denverton", CPU_DENVERTON },
350 	{ "icelake_server", CPU_ICELAKE_XEON },
351 	{ "icelake-d", CPU_ICELAKE_DE },
352 	{ "snowridge", CPU_TREMONT_D },
353 	{ "cometlake", CPU_COMETLAKE },
354 	{ "tigerlake", CPU_TIGERLAKE },
355 	{ "rocketlake", CPU_ROCKETLAKE },
356 	{ "alderlake", CPU_ALDERLAKE },
357 	{ "lakefield", CPU_LAKEFIELD },
358 	{ "sapphirerapids_server", CPU_SAPPHIRERAPIDS },
359 	{ NULL }
360 };
361 
print_cputypes(void)362 static void print_cputypes(void)
363 {
364 	struct config_choice *c;
365 	fprintf(stderr, "Valid CPUs:");
366 	for (c = cpu_choices; c->name; c++)
367 		fprintf(stderr, " %s", c->name);
368 	fputc('\n', stderr);
369 }
370 
lookup_cputype(char * name)371 static enum cputype lookup_cputype(char *name)
372 {
373 	struct config_choice *c;
374 	for (c = cpu_choices; c->name; c++) {
375 		if (!strcasecmp(name, c->name))
376 			return c->val;
377 	}
378 	fprintf(stderr, "Unknown CPU type `%s' specified\n", name);
379 	print_cputypes();
380 	exit(1);
381 }
382 
383 static char *vendor[] = {
384 	[0] = "Intel",
385 	[1] = "Cyrix",
386 	[2] = "AMD",
387 	[3] = "UMC",
388 	[4] = "vendor 4",
389 	[5] = "Centaur",
390 	[6] = "vendor 6",
391 	[7] = "Transmeta",
392 	[8] = "NSC"
393 };
394 
395 #ifdef __Linux__
cpuvendor_to_num(char * name)396 static unsigned cpuvendor_to_num(char *name)
397 {
398 	unsigned i;
399 	unsigned v;
400 	char *end;
401 
402 	v = strtoul(name, &end, 0);
403 	if (end > name)
404 		return v;
405 	for (i = 0; i < NELE(vendor); i++)
406 		if (!strcmp(name, vendor[i]))
407 			return i;
408 	return 0;
409 }
410 #endif
411 
cpuvendor_name(u32 cpuvendor)412 static char *cpuvendor_name(u32 cpuvendor)
413 {
414 	return (cpuvendor < NELE(vendor)) ? vendor[cpuvendor] : "Unknown vendor";
415 }
416 
setup_cpuid(u32 cpuvendor,u32 cpuid)417 static enum cputype setup_cpuid(u32 cpuvendor, u32 cpuid)
418 {
419 	u32 family, model, stepping;
420 
421 	parse_cpuid(cpuid, &family, &model, &stepping);
422 
423 	switch (cpuvendor) {
424 	case X86_VENDOR_INTEL:
425 	        return select_intel_cputype(family, model);
426 	case X86_VENDOR_AMD:
427 		if (family >= 15 && family <= 17)
428 			return CPU_K8;
429 		/* FALL THROUGH */
430 	default:
431 		Eprintf("Unknown CPU type vendor %u family %u model %u",
432 			cpuvendor, family, model);
433 		return CPU_GENERIC;
434 	}
435 }
436 
mce_cpuid(struct mce * m)437 static void mce_cpuid(struct mce *m)
438 {
439 	static int warned;
440 	if (m->cpuid) {
441 		enum cputype t = setup_cpuid(m->cpuvendor, m->cpuid);
442 		if (!cpu_forced)
443 			cputype = t;
444 		else if (t != cputype && t != CPU_GENERIC && !warned) {
445 			Eprintf("Forced cputype %s does not match cpu type %s from mcelog\n",
446 				cputype_name[cputype],
447 				cputype_name[t]);
448 			warned = 1;
449 		}
450 	} else if (cputype == CPU_GENERIC && !cpu_forced) {
451 		is_cpu_supported();
452 	}
453 }
454 
mce_prepare(struct mce * m)455 static void mce_prepare(struct mce *m)
456 {
457 	mce_cpuid(m);
458 	if (!m->time)
459 		m->time = time(NULL);
460 }
461 
dump_mce(struct mce * m,unsigned recordlen)462 static void dump_mce(struct mce *m, unsigned recordlen)
463 {
464 	int n;
465 	int ismemerr = 0;
466 	unsigned cpu = m->extcpu ? m->extcpu : m->cpu;
467 
468 	/* should not happen */
469 	if (!m->finished)
470 		Wprintf("not finished?\n");
471 	Wprintf("CPU %d %s ", cpu, bankname(m->bank));
472 	if (m->tsc)
473 		print_tsc(cpu, m->tsc, m->time);
474 	Wprintf("\n");
475 	if (m->ip)
476 		Wprintf("RIP%s %02x:%llx\n",
477 		       !(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "",
478 		       m->cs, m->ip);
479 	n = 0;
480 	if (m->status & MCI_STATUS_MISCV)
481 		n += Wprintf("MISC %llx ", m->misc);
482 	if (m->status & MCI_STATUS_ADDRV)
483 		n += Wprintf("ADDR %llx ", m->addr);
484 	if (n > 0)
485 		Wprintf("\n");
486 	if (m->time) {
487 		time_t t = m->time;
488 		Wprintf("TIME %llu %s", m->time, ctime(&t));
489 	}
490 	switch (cputype) {
491 	case CPU_K8:
492 		decode_k8_mc(m, &ismemerr);
493 		break;
494 	CASE_INTEL_CPUS:
495 		decode_intel_mc(m, cputype, &ismemerr, recordlen);
496 		break;
497 	/* add handlers for other CPUs here */
498 	default:
499 		break;
500 	}
501 	/* decode all status bits here */
502 	Wprintf("STATUS %llx MCGSTATUS %llx\n", m->status, m->mcgstatus);
503 	n = 0;
504 	if (recordlen > offsetof(struct mce, cpuid) && m->mcgcap)
505 		n += Wprintf("MCGCAP %llx ", m->mcgcap);
506 	if (recordlen > offsetof(struct mce, apicid))
507 		n += Wprintf("APICID %x ", m->apicid);
508 	if (recordlen > offsetof(struct mce, socketid))
509 		n += Wprintf("SOCKETID %x ", m->socketid);
510 	if (n > 0)
511 		Wprintf("\n");
512 
513 	if (recordlen > offsetof(struct mce, ppin) && m->ppin)
514 		n += Wprintf("PPIN %llx\n", m->ppin);
515 
516 	if (recordlen > offsetof(struct mce, microcode) && m->microcode)
517 		n += Wprintf("MICROCODE %x\n", m->microcode);
518 
519 	if (recordlen > offsetof(struct mce, cpuid) && m->cpuid) {
520 		u32 fam, mod, step;
521 		parse_cpuid(m->cpuid, &fam, &mod, &step);
522 		Wprintf("CPUID Vendor %s Family %u Model %u Step %u\n",
523 			cpuvendor_name(m->cpuvendor),
524 			fam,
525 			mod,
526 			step);
527 	}
528 	if (cputype != CPU_SANDY_BRIDGE_EP && cputype != CPU_IVY_BRIDGE_EPEX &&
529 	    cputype != CPU_HASWELL_EPEX && cputype != CPU_BROADWELL &&
530 	    cputype != CPU_BROADWELL_DE && cputype != CPU_BROADWELL_EPEX &&
531 	    cputype != CPU_KNIGHTS_LANDING && cputype != CPU_KNIGHTS_MILL &&
532 	    cputype != CPU_SKYLAKE && cputype != CPU_SKYLAKE_XEON &&
533 	    cputype != CPU_KABYLAKE && cputype != CPU_DENVERTON &&
534 	    cputype != CPU_ICELAKE_XEON && cputype != CPU_ICELAKE_DE &&
535 	    cputype != CPU_TREMONT_D && cputype != CPU_COMETLAKE &&
536 	    cputype != CPU_TIGERLAKE && cputype != CPU_ROCKETLAKE &&
537 	    cputype != CPU_ALDERLAKE && cputype != CPU_LAKEFIELD &&
538 	    cputype != CPU_SAPPHIRERAPIDS)
539 		resolveaddr(m->addr);
540 }
541 
dump_mce_raw_ascii(struct mce * m,unsigned recordlen)542 static void dump_mce_raw_ascii(struct mce *m, unsigned recordlen)
543 {
544 	/* should not happen */
545 	if (!m->finished)
546 		Wprintf("not finished?\n");
547 	Wprintf("CPU %u\n", m->extcpu ? m->extcpu : m->cpu);
548 	Wprintf("BANK %d\n", m->bank);
549 	Wprintf("TSC %#llx\n", m->tsc);
550 	Wprintf("RIP %#02x:%#llx\n", m->cs, m->ip);
551 	Wprintf("MISC %#llx\n", m->misc);
552 	Wprintf("ADDR %#llx\n", m->addr);
553 	Wprintf("STATUS %#llx\n", m->status);
554 	Wprintf("MCGSTATUS %#llx\n", m->mcgstatus);
555 	if (recordlen > offsetof(struct mce, cpuid))
556 		Wprintf("PROCESSOR %u:%#x\n", m->cpuvendor, m->cpuid);
557 #define CPRINT(str, field) 				\
558 	if (recordlen > offsetof(struct mce, field))	\
559 		Wprintf(str "\n", m->field)
560 	CPRINT("TIME %llu", time);
561 	CPRINT("SOCKETID %u", socketid);
562 	CPRINT("APICID %u", apicid);
563 	CPRINT("MCGCAP %#llx", mcgcap);
564 #undef CPRINT
565 	Wprintf("\n");
566 }
567 
568 #ifdef __Linux__
is_cpu_supported(void)569 int is_cpu_supported(void)
570 {
571 	enum {
572 		VENDOR = 1,
573 		FAMILY = 2,
574 		MODEL = 4,
575 		MHZ = 8,
576 		FLAGS = 16,
577 		ALL = 0x1f
578 	} seen = 0;
579 	FILE *f;
580 	static int checked;
581 
582 	if (checked)
583 		return 1;
584 	checked = 1;
585 
586 	f = fopen("/proc/cpuinfo","r");
587 	if (f != NULL) {
588 		int family = 0;
589 		int model = 0;
590 		char vendor[64] = { 0 };
591 		char *line = NULL;
592 		size_t linelen = 0;
593 		double mhz;
594 
595 		while (getdelim(&line, &linelen, '\n', f) > 0 && seen != ALL) {
596 			if (sscanf(line, "vendor_id : %63[^\n]", vendor) == 1)
597 				seen |= VENDOR;
598 			if (sscanf(line, "cpu family : %d", &family) == 1)
599 				seen |= FAMILY;
600 			if (sscanf(line, "model : %d", &model) == 1)
601 				seen |= MODEL;
602 			/* We use only Mhz of the first CPU, assuming they are the same
603 			   (there are more sanity checks later to make this not as wrong
604 			   as it sounds) */
605 			if (sscanf(line, "cpu MHz : %lf", &mhz) == 1) {
606 				if (!cpumhz_forced)
607 					cpumhz = mhz;
608 				seen |= MHZ;
609 			}
610 			if (!strncmp(line, "flags", 5) && isspace(line[6])) {
611 				processor_flags = line;
612 				line = NULL;
613 				linelen = 0;
614 				seen |= FLAGS;
615 			}
616 
617 		}
618 		if (seen == ALL) {
619 			if (!strcmp(vendor,"AuthenticAMD")) {
620 				if (family == 15) {
621 					cputype = CPU_K8;
622 				} else if (family >= 16) {
623 					Eprintf("ERROR: AMD Processor family %d: mcelog does not support this processor.  Please use the edac_mce_amd module instead.\n", family);
624 					return 0;
625 				}
626 			} else if (!strcmp(vendor,"HygonGenuine")) {
627 				Eprintf("ERROR: Hygon Processor family %d: mcelog does not support this processor.  Please use the edac_mce_amd module instead.\n", family);
628 				return 0;
629 			} else if (!strcmp(vendor,"GenuineIntel"))
630 				cputype = select_intel_cputype(family, model);
631 			/* Add checks for other CPUs here */
632 		} else {
633 			Eprintf("warning: Cannot parse /proc/cpuinfo\n");
634 		}
635 		fclose(f);
636 		free(line);
637 	} else
638 		Eprintf("warning: Cannot open /proc/cpuinfo\n");
639 
640 	return 1;
641 }
642 #endif
643 
644 #ifdef __FreeBSD__
is_cpu_supported(void)645 int is_cpu_supported(void)
646 {
647 	char vendor[20];
648 	u_int regs[4];
649 	u_int cpu_id;
650 	int family, model;
651 	static int checked;
652 
653 	if (checked)
654 		return 1;
655 
656 	checked = 1;
657 
658 	do_cpuid(0, regs);
659 	((u_int *)vendor)[0] = regs[1];
660 	((u_int *)vendor)[1] = regs[3];
661 	((u_int *)vendor)[2] = regs[2];
662 	vendor[12] = 0;
663 
664 	do_cpuid(1, regs);
665 	cpu_id = regs[0];
666 	family = CPUID_TO_FAMILY(cpu_id);
667 	model = CPUID_TO_MODEL(cpu_id);
668 
669 	if (cpu_forced)
670 		;
671 	else if (!strcmp(vendor,"AuthenticAMD")) {
672 			if (family == 15) {
673 				cputype = CPU_K8;
674 			} else if (family >= 16) {
675 				SYSERRprintf("ERROR: AMD Processor family %d: mcelog does not support this processor.  Please use the edac_mce_amd module instead.\n", family);
676 				return 0;
677 			}
678 		} else if (!strcmp(vendor,"GenuineIntel"))
679 			cputype = select_intel_cputype(family, model);
680 	/* Add checks for other CPUs here */
681 		else
682 		return 1;
683 	return 0;
684 }
685 #endif
686 
687 #ifdef __Linux__
skipspace(char * s)688 static char *skipspace(char *s)
689 {
690 	while (isspace(*s))
691 		++s;
692 	return s;
693 }
694 #endif
695 
696 #ifdef __Linux__
skip_syslog(char * s)697 static char *skip_syslog(char *s)
698 {
699 	char *p;
700 
701 	/* Handle syslog output */
702 	p = strstr(s, "mcelog: ");
703 	if (p)
704 		return p + sizeof("mcelog: ") - 1;
705 	return s;
706 }
707 #endif
708 
709 #ifdef __Linux__
skipgunk(char * s)710 static char *skipgunk(char *s)
711 {
712 	s = skip_syslog(s);
713 
714 	s = skipspace(s);
715 	if (*s == '<') {
716 		s += strcspn(s, ">");
717 		if (*s == '>')
718 			++s;
719 	}
720 	s = skipspace(s);
721 	if (*s == '[') {
722 		s += strcspn(s, "]");
723 		if (*s == ']')
724 			++s;
725 	}
726 
727 	s = skipspace(s);
728 
729 	if (strncmp(s, "mce: [Hardware Error]:", 22) == 0)
730 		s += 22;
731 
732 	return skipspace(s);
733 }
734 #endif
735 
736 #ifdef __Linux__
urange(unsigned val,unsigned lo,unsigned hi)737 static inline int urange(unsigned val, unsigned lo, unsigned hi)
738 {
739 	return val >= lo && val <= hi;
740 }
741 #endif
742 
743 #ifdef __Linux__
is_short(char * name)744 static int is_short(char *name)
745 {
746 	return strlen(name) == 3 &&
747 		isupper(name[0]) &&
748 		islower(name[1]) &&
749 		islower(name[2]);
750 }
751 #endif
752 
753 #ifdef __Linux__
skip_date(char * s)754 static unsigned skip_date(char *s)
755 {
756 	unsigned day, hour, min, year, sec;
757 	char dayname[11];
758 	char month[11];
759 	unsigned next;
760 
761 	if (sscanf(s, "%10s %10s %u %u:%u:%u %u%n",
762 		dayname, month, &day, &hour, &min, &sec, &year, &next) != 7)
763 		return 0;
764 	if (!is_short(dayname) || !is_short(month) || !urange(day, 1, 31) ||
765 		!urange(hour, 0, 24) || !urange(min, 0, 59) || !urange(sec, 0, 59) ||
766 		year < 1900)
767 		return 0;
768 	return next;
769 }
770 #endif
771 
dump_mce_final(struct mce * m,char * symbol,int missing,int recordlen,int dseen)772 static void dump_mce_final(struct mce *m, char *symbol, int missing, int recordlen,
773 			   int dseen)
774 {
775 	m->finished = 1;
776 	if (m->cpuid)
777 		mce_cpuid(m);
778 	if (!dump_raw_ascii) {
779 		if (!dseen)
780 			disclaimer();
781 		dump_mce(m, recordlen);
782 		if (symbol[0])
783 			Wprintf("RIP: %s\n", symbol);
784 		if (missing)
785 			Wprintf("(Fields were incomplete)\n");
786 	} else
787 		dump_mce_raw_ascii(m, recordlen);
788 	flushlog();
789 }
790 
791 #ifdef __Linux__
792 static char *skip_patterns[] = {
793 	"MCA:*",
794 	"MCi_MISC register valid*",
795 	"MC? status*",
796 	"Unsupported new Family*",
797 	"Kernel does not support page offline interface",
798 	NULL
799 };
800 #endif
801 
802 #ifdef __Linux__
match_patterns(char * s,char ** pat)803 static int match_patterns(char *s, char **pat)
804 {
805 	for (; *pat; pat++)
806 		if (!fnmatch(*pat, s, 0))
807 			return 0;
808 	return 1;
809 }
810 #endif
811 
812 #define FIELD(f) \
813 	if (recordlen < endof_field(struct mce, f)) \
814 		recordlen = endof_field(struct mce, f)
815 
816 /* Decode ASCII input for fatal messages */
817 #ifdef __Linux__
decodefatal(FILE * inf)818 static void decodefatal(FILE *inf)
819 {
820 	struct mce m;
821 	char *line = NULL;
822 	size_t linelen = 0;
823 	int missing;
824 	char symbol[100];
825 	int data;
826 	int next;
827 	char *s = NULL;
828 	unsigned cpuvendor;
829 	unsigned recordlen;
830 	int disclaimer_seen;
831 
832 	ascii_mode = 1;
833 	if (do_dmi && dmi_forced)
834 		Wprintf(
835  "WARNING: with --dmi mcelog --ascii must run on the same machine with the\n"
836  "     same BIOS/memory configuration as where the machine check occurred.\n");
837 
838 restart:
839 	missing = 0;
840 	data = 0;
841 	next = 0;
842 	disclaimer_seen = 0;
843 	recordlen = 0;
844 	memset(&m, 0, sizeof(struct mce));
845 	symbol[0] = '\0';
846 	while (next > 0 || getdelim(&line, &linelen, '\n', inf) > 0) {
847 		int n = 0;
848 		char *start;
849 
850 		s = next > 0 ? s + next : line;
851 		s = skipgunk(s);
852 		start = s;
853 		next = 0;
854 
855 		if (!strncmp(s, "CPU ", 4)) {
856 			unsigned cpu = 0, bank = 0;
857 			n = sscanf(s,
858 	       "CPU %u: Machine Check%*[ :Ec-x]%16Lx Bank %d: %016Lx%n",
859 				   &cpu,
860 				   &m.mcgstatus,
861 				   &bank,
862 				   &m.status,
863 				   &next);
864 			if (n == 1) {
865 				n = sscanf(s, "CPU %u BANK %u%n", &cpu, &bank,
866 						&next);
867 				if (n != 2)
868 					n = sscanf(s, "CPU %u %u%n", &cpu,
869 						 &bank, &next);
870 				m.cpu = cpu;
871 				if (n < 2)
872 					missing++;
873 				else {
874 					m.bank = bank;
875 					FIELD(bank);
876 				}
877 			} else if (n <= 0) {
878 				missing++;
879 			} else if (n > 1) {
880 				FIELD(mcgstatus);
881 				m.cpu = cpu;
882 				if (n > 2) {
883 					m.bank = bank;
884 					FIELD(bank);
885 				} else if (n > 3)
886 					FIELD(status);
887 				if (n < 4)
888 					missing++;
889 			}
890 		}
891 		else if (!strncmp(s, "STATUS", 6)) {
892 			if ((n = sscanf(s,"STATUS %llx%n", &m.status, &next)) < 1)
893 				missing++;
894 			else
895 				FIELD(status);
896 		}
897 		else if (!strncmp(s, "MCGSTATUS", 6)) {
898 			if ((n = sscanf(s,"MCGSTATUS %llx%n", &m.mcgstatus, &next)) < 1)
899 				missing++;
900 			else
901 				FIELD(mcgstatus);
902 		}
903 		else if (!strncmp(s, "RIP", 3)) {
904 			unsigned cs = 0;
905 
906 			if (!strncmp(s, "RIP !INEXACT!", 13))
907 				s += 13;
908 			else
909 				s += 3;
910 
911 			n = sscanf(s, "%02x:<%016Lx> {%99s}%n",
912 				   &cs,
913 				   &m.ip,
914 				   symbol, &next);
915 			m.cs = cs;
916 			if (n < 2)
917 				missing++;
918 			else
919 				FIELD(ip);
920 		}
921 		else if (!strncmp(s, "TSC",3)) {
922 			if ((n = sscanf(s, "TSC %llx%n", &m.tsc, &next)) < 1)
923 				missing++;
924 			else
925 				FIELD(tsc);
926 		}
927 		else if (!strncmp(s, "ADDR",4)) {
928 			if ((n = sscanf(s, "ADDR %llx%n", &m.addr, &next)) < 1)
929 				missing++;
930 			else
931 				FIELD(addr);
932 		}
933 		else if (!strncmp(s, "MISC",4)) {
934 			if ((n = sscanf(s, "MISC %llx%n", &m.misc, &next)) < 1)
935 				missing++;
936 			else
937 				FIELD(misc);
938 		}
939 		else if (!strncmp(s, "PROCESSOR", 9)) {
940 			if ((n = sscanf(s, "PROCESSOR %u:%x%n", &cpuvendor, &m.cpuid, &next)) < 2)
941 				missing++;
942 			else {
943 				m.cpuvendor = cpuvendor;
944 				FIELD(cpuid);
945 				FIELD(cpuvendor);
946 			}
947 		}
948 		else if (!strncmp(s, "TIME", 4)) {
949 			if ((n = sscanf(s, "TIME %llu%n", &m.time, &next)) < 1)
950 				missing++;
951 			else
952 				FIELD(time);
953 
954 			next += skip_date(s + next);
955 		}
956 		else if (!strncmp(s, "MCGCAP", 6)) {
957 			if ((n = sscanf(s, "MCGCAP %llx%n", &m.mcgcap, &next)) != 1)
958 				missing++;
959 			else
960 				FIELD(mcgcap);
961 		}
962 		else if (!strncmp(s, "APICID", 6)) {
963 			if ((n = sscanf(s, "APICID %x%n", &m.apicid, &next)) != 1)
964 				missing++;
965 			else
966 				FIELD(apicid);
967 		}
968 		else if (!strncmp(s, "SOCKETID", 8)) {
969 			if ((n = sscanf(s, "SOCKETID %u%n", &m.socketid, &next)) != 1)
970 				missing++;
971 			else
972 				FIELD(socketid);
973 		}
974 		else if (!strncmp(s, "CPUID", 5)) {
975 			unsigned fam, mod;
976 			char vendor[31];
977 
978 			if ((n = sscanf(s, "CPUID Vendor %30s Family %u Model %u\n",
979 					vendor, &fam, &mod)) < 3)
980 				missing++;
981 			else {
982 				m.cpuvendor = cpuvendor_to_num(vendor);
983 				m.cpuid = unparse_cpuid(fam, mod);
984 				FIELD(cpuid);
985 				FIELD(cpuvendor);
986 			}
987 		}
988 		else if (strstr(s, "HARDWARE ERROR"))
989 			disclaimer_seen = 1;
990 		else if (!strncmp(s, "(XEN)", 5)) {
991 			char *w;
992 			unsigned bank, cpu;
993 
994 			if (strstr(s, "The hardware reports a non fatal, correctable incident occurred")) {
995 				w = strstr(s, "CPU");
996 				if (w && sscanf(w, "CPU %d", &cpu)) {
997 					m.cpu = cpu;
998 					FIELD(cpu);
999 				}
1000 			} else if ((n = sscanf(s, "(XEN) Bank %d: %llx at %llx",
1001 						&bank, &m.status, &m.addr) >= 1)) {
1002 				m.bank = bank;
1003 				FIELD(bank);
1004 				if (n >= 2)
1005 					FIELD(status);
1006 				if (n >= 3)
1007 					FIELD(addr);
1008 			}
1009 		}
1010 		else if (!match_patterns(s, skip_patterns))
1011 			n = 0;
1012 		else {
1013 			s = skipspace(s);
1014 			if (*s && data)
1015 				dump_mce_final(&m, symbol, missing, recordlen, disclaimer_seen);
1016 			if (!dump_raw_ascii)
1017 				Wprintf("%s", start);
1018 			if (*s && data)
1019 				goto restart;
1020 		}
1021 		if (n > 0)
1022 			data = 1;
1023 	}
1024 	free(line);
1025 	if (data)
1026 		dump_mce_final(&m, symbol, missing, recordlen, disclaimer_seen);
1027 }
1028 #endif
1029 
1030 #ifdef __FreeBSD__
1031 /*
1032  * Table used to map cpuid vendor strings and FreeBSD CPU vendor IDs
1033  * to Linux cpuvendor values.
1034  */
1035 static struct {
1036 	char *name;
1037 	int vendor_id;
1038 	u_char cpuvendor;
1039 } vendor_ids[] = {
1040 	{ "GenuineIntel", CPU_VENDOR_INTEL, 0 },
1041 	{ "AuthenticAMD", CPU_VENDOR_AMD, 2 },
1042 	{ "CentaurHauls", CPU_VENDOR_CENTAUR, 5 },
1043 #ifdef __i386__
1044 	{ "CyrixInstead", CPU_VENDOR_CYRIX, 1 },
1045 	{ "UMC UMC UMC ", CPU_VENDOR_UMC, 3 },
1046 	{ "GenuineTMx86", CPU_VENDOR_TRANSMETA, 7 },
1047 	{ "Geode by NSC", CPU_VENDOR_NSC, 8 },
1048 #endif
1049 };
1050 
find_cpu_vendor(const char * vendor)1051 static int find_cpu_vendor(const char *vendor)
1052 {
1053 	u_int i;
1054 
1055 	for (i = 0; i < sizeof(vendor_ids) / sizeof(vendor_ids[0]); i++)
1056 		if (strcmp(vendor, vendor_ids[i].name) == 0)
1057 			return (vendor_ids[i].cpuvendor);
1058 	return (0xff);
1059 }
1060 
find_cpu_vendor_id(const char * vendor)1061 static int find_cpu_vendor_id(const char *vendor)
1062 {
1063 	u_int i;
1064 
1065 	for (i = 0; i < sizeof(vendor_ids) / sizeof(vendor_ids[0]); i++)
1066 		if (strcmp(vendor, vendor_ids[i].name) == 0)
1067 			return (vendor_ids[i].vendor_id);
1068 	return (0);
1069 }
1070 
map_cpu_vendor(int vendor_id)1071 static int map_cpu_vendor(int vendor_id)
1072 {
1073 	u_int i;
1074 
1075 	for (i = 0; i < sizeof(vendor_ids) / sizeof(vendor_ids[0]); i++)
1076 		if (vendor_ids[i].vendor_id == vendor_id)
1077 			return (vendor_ids[i].cpuvendor);
1078 	return (0xff);
1079 }
1080 
1081 /* Convert FreeBSD's struct mca_record into a struct mce. */
convert_mca(struct mca_record * mr,struct mce * mce,int live,size_t len)1082 static void convert_mca(struct mca_record *mr, struct mce *mce, int live,
1083     size_t len)
1084 {
1085 	memset(mce, 0, sizeof(*mce));
1086 	mce->status = mr->mr_status;
1087 	mce->misc = mr->mr_misc;
1088 	mce->addr = mr->mr_addr;
1089 	mce->mcgstatus = mr->mr_mcg_status;
1090 	mce->tsc = mr->mr_tsc;
1091 	mce->cpuvendor = map_cpu_vendor(mr->mr_cpu_vendor_id);
1092 	mce->cpuid = mr->mr_cpu_id;
1093 	mce->bank = mr->mr_bank;
1094 	mce->finished = 1;
1095 	mce->extcpu = mr->mr_cpu;
1096 	mce->apicid = mr->mr_apic_id;
1097 	mce->mcgcap = mr->mr_mcg_cap;
1098 
1099 	/*
1100 	 * For older live records (from sysctl), fill in some fields
1101 	 * using registers from the current CPU.
1102 	 */
1103 	if (len < offsetof(struct mca_record, mr_cpu_id) && live) {
1104 		char vendor[20];
1105 		u_int regs[4];
1106 
1107 		do_cpuid(0, regs);
1108 		((u_int *)vendor)[0] = regs[1];
1109 		((u_int *)vendor)[1] = regs[3];
1110 		((u_int *)vendor)[2] = regs[2];
1111 		vendor[12] = 0;
1112 		mce->cpuvendor = find_cpu_vendor(vendor);
1113 
1114 		do_cpuid(1, regs);
1115 		mce->cpuid = regs[0];
1116 	}
1117 }
1118 
1119 /* Decode ASCII input for fatal messages */
decodefatal(FILE * inf)1120 static void decodefatal(FILE *inf)
1121 {
1122 	struct mca_record mr;
1123 	struct mce m;
1124 	long long val, val2;
1125 	char *cp, line[100], *s, symbol[1];
1126 	const char *fmt;
1127 	int cpu, data, old, missing;
1128 	enum rows {
1129 		BANK = 0x1,
1130 		MCG = 0x2,
1131 		VENDOR = 0x4,
1132 		CPU = 0x8,
1133 		ADDR = 0x10,
1134 		MISC = 0x20,
1135 	};
1136 
1137 	symbol[0] = '\0';
1138 	data = 0;
1139 	missing = 0;
1140 	old = 0;
1141 	memset(&mr, 0, sizeof(mr));
1142 	while ((s = fgets(line, sizeof(line), inf)) != NULL) {
1143 		s = strstr(s, "MCA: ");
1144 		if (s == NULL)
1145 			continue;
1146 		s += strlen("MCA: ");
1147 
1148 		if (strncmp(s, "bank", 4) == 0 || strncmp(s, "Bank", 4) == 0) {
1149 			/* Start of a new record, dump the previous one. */
1150 			if (data != 0) {
1151 				/* Require some minimum data. */
1152 				if (data & BANK) {
1153 					if (mr.mr_status & MC_STATUS_ADDRV &&
1154 					    !(data & ADDR))
1155 						missing = 1;
1156 					if (mr.mr_status & MC_STATUS_MISCV &&
1157 					    !(data & MISC))
1158 						missing = 1;
1159 					convert_mca(&mr, &m, 0, sizeof(mr));
1160 					mce_cpuid(&m);
1161 					dump_mce_final(&m, symbol, missing,
1162 					    sizeof(struct mce), 0);
1163 				}
1164 				data = 0;
1165 				missing = 0;
1166 				memset(&mr, 0, sizeof(mr));
1167 			}
1168 
1169 			if (s[0] == 'b') {
1170 				old = 1;
1171 				fmt = "bank %d, status 0x%llx";
1172 			} else {
1173 				old = 0;
1174 				fmt = "Bank %d, Status 0x%llx";
1175 			}
1176 			if (sscanf(s, fmt, &mr.mr_bank, &val) != 2)
1177 				missing = 1;
1178 			else {
1179 				data |= BANK;
1180 				mr.mr_status = val;
1181 			}
1182 		}
1183 		if (strncmp(s, "Global", 6) == 0) {
1184 			if (sscanf(s, "Global Cap 0x%llx, Status 0x%llx", &val,
1185 			    &val2) != 2)
1186 				missing = 1;
1187 			else {
1188 				data |= MCG;
1189 				mr.mr_mcg_cap = val;
1190 				mr.mr_mcg_status = val2;
1191 			}
1192 		}
1193 		if (strncmp(s, "Vendor \"", 8) == 0) {
1194 			s += 8;
1195 			cp = index(s, '"');
1196 			if (cp != NULL) {
1197 				*cp = '\0';
1198 				mr.mr_cpu_vendor_id = find_cpu_vendor_id(s);
1199 				s = cp + 1;
1200 				if (sscanf(s, ", ID 0x%x, APIC ID %d",
1201 				    &mr.mr_cpu_id, &mr.mr_apic_id) != 2)
1202 					missing = 1;
1203 				else
1204 					data |= VENDOR;
1205 			} else
1206 				missing = 1;
1207 		}
1208 		if (strncmp(s, "CPU", 3) == 0) {
1209 			if (sscanf(s, "CPU %d ", &cpu) != 1)
1210 				missing = 1;
1211 			else {
1212 				data |= CPU;
1213 				if (old)
1214 					mr.mr_apic_id = cpu;
1215 				else
1216 					mr.mr_cpu = cpu;
1217 			}
1218 		}
1219 		if (strncmp(s, "Address", 7) == 0) {
1220 			if (sscanf(s, "Address 0x%llx", &val) != 1)
1221 				missing = 1;
1222 			else {
1223 				data |= ADDR;
1224 				mr.mr_addr = val;
1225 			}
1226 		}
1227 		if (strncmp(s, "Misc", 4) == 0) {
1228 			if (sscanf(s, "Misc 0x%llx", &val) != 1)
1229 				missing = 1;
1230 			else {
1231 				data |= MISC;
1232 				mr.mr_misc = val;
1233 			}
1234 		}
1235 	}
1236 
1237 	/* Dump the last record. */
1238 	if (data & BANK) {
1239 		if (mr.mr_status & MC_STATUS_ADDRV && !(data & ADDR))
1240 			missing = 1;
1241 		if (mr.mr_status & MC_STATUS_MISCV && !(data & MISC))
1242 			missing = 1;
1243 		convert_mca(&mr, &m, 0, sizeof(mr));
1244 		mce_cpuid(&m);
1245 		dump_mce_final(&m, symbol, missing, sizeof(struct mce), 0);
1246 	}
1247 }
1248 #endif
1249 
remove_pidfile(void)1250 static void remove_pidfile(void)
1251 {
1252 	unlink(pidfile);
1253 	if (pidfile != pidfile_default)
1254 		free(pidfile);
1255 }
1256 
signal_exit(int sig)1257 static void signal_exit(int sig)
1258 {
1259 	remove_pidfile();
1260 	client_cleanup();
1261 	_exit(EXIT_SUCCESS);
1262 }
1263 
setup_pidfile(char * s)1264 static void setup_pidfile(char *s)
1265 {
1266 	char cwd[PATH_MAX];
1267 	char *c;
1268 
1269 	if (*s != '/') {
1270 		c = getcwd(cwd, PATH_MAX);
1271 		if (!c)
1272 			return;
1273 		xasprintf(&pidfile, "%s/%s", cwd, s);
1274 	} else {
1275 		xasprintf(&pidfile, "%s", s);
1276 	}
1277 
1278 	return;
1279 }
1280 
write_pidfile(void)1281 static void write_pidfile(void)
1282 {
1283 	FILE *f;
1284 	atexit(remove_pidfile);
1285 	signal(SIGTERM, signal_exit);
1286 	signal(SIGINT, signal_exit);
1287 	signal(SIGQUIT, signal_exit);
1288 	f = fopen(pidfile, "w");
1289 	if (!f) {
1290 		Eprintf("Cannot open pidfile `%s'", pidfile);
1291 		return;
1292 	}
1293 	fprintf(f, "%u", getpid());
1294 	fclose(f);
1295 }
1296 
usage(void)1297 void usage(void)
1298 {
1299 	fprintf(stderr,
1300 "Usage:\n"
1301 "\n"
1302 "  mcelog [options]  [mcelogdevice]\n"
1303 "Decode machine check error records from current kernel.\n"
1304 "\n"
1305 "  mcelog [options] --daemon\n"
1306 "Run mcelog in daemon mode, waiting for errors from the kernel.\n"
1307 "\n"
1308 "  mcelog [options] --client\n"
1309 "Query a currently running mcelog daemon for errors\n"
1310 "\n"
1311 "  mcelog [options] --ascii < log\n"
1312 "  mcelog [options] --ascii --file log\n"
1313 "Decode machine check ASCII output from kernel logs\n"
1314 #ifdef __FreeBSD_
1315 "  mcelog [options] -M vmcore -N kernel\n"
1316 "Decode machine check error records from kernel crashdump.\n"
1317 #endif
1318 "\n"
1319 "Options:\n"
1320 "--version           Show the version of mcelog and exit\n"
1321 "--cpu CPU           Set CPU type CPU to decode (see below for valid types)\n"
1322 "--intel-cpu FAMILY,MODEL  Set CPU type for an Intel CPU based on family and model from cpuid\n"
1323 "--k8                Set the CPU to be an AMD K8\n"
1324 "--p4                Set the CPU to be an Intel Pentium4\n"
1325 "--core2             Set the CPU to be an Intel Core2\n"
1326 "--generic           Set the CPU to a generic version\n"
1327 "--cpumhz MHZ        Set CPU Mhz to decode time (output unreliable, not needed on new kernels)\n"
1328 "--raw		     (with --ascii) Dump in raw ASCII format for machine processing\n"
1329 "--daemon            Run in background waiting for events (needs newer kernel)\n"
1330 "--client            Query a currently running mcelog daemon for errors\n"
1331 "--ignorenodev       Exit silently when the device cannot be opened\n"
1332 "--file filename     With --ascii read machine check log from filename instead of stdin\n"
1333 "--logfile filename  Log decoded machine checks in file filename\n"
1334 "--syslog            Log decoded machine checks in syslog (default stdout or syslog for daemon)\n"
1335 "--syslog-error	     Log decoded machine checks in syslog with error level\n"
1336 "--no-syslog         Never log anything to syslog\n"
1337 "--logfile filename  Append log output to logfile instead of stdout\n"
1338 "--dmi               Use SMBIOS information to decode DIMMs (needs root)\n"
1339 "--no-dmi            Don't use SMBIOS information\n"
1340 "--dmi-verbose       Dump SMBIOS information (for debugging)\n"
1341 "--filter            Inhibit known bogus events (default on)\n"
1342 "--no-filter         Don't inhibit known broken events\n"
1343 "--config-file filename Read config information from config file instead of " CONFIG_FILENAME "\n"
1344 "--foreground        Keep in foreground (for debugging)\n"
1345 "--num-errors N      Only process N errors (for testing)\n"
1346 "--pidfile file	     Write pid of daemon into file\n"
1347 "--no-imc-log	     Disable extended iMC logging\n"
1348 "--is-cpu-supported  Exit with return code indicating whether the CPU is supported\n"
1349 "--max-corr-err-counters Max page correctable error counters\n"
1350 "--help	             Display this message.\n"
1351 		);
1352 	printf("\n");
1353 	print_cputypes();
1354 }
1355 
1356 enum options {
1357 	O_LOGFILE = O_COMMON,
1358 	O_K8,
1359 	O_P4,
1360 	O_GENERIC,
1361 	O_CORE2,
1362 	O_INTEL_CPU,
1363 	O_FILTER,
1364 	O_DMI,
1365 	O_NO_DMI,
1366 	O_DMI_VERBOSE,
1367 	O_SYSLOG,
1368 	O_NO_SYSLOG,
1369 	O_CPUMHZ,
1370 	O_SYSLOG_ERROR,
1371 	O_RAW,
1372 	O_DAEMON,
1373 	O_ASCII,
1374 	O_CLIENT,
1375 	O_VERSION,
1376 	O_CONFIG_FILE,
1377 	O_CPU,
1378 	O_FILE,
1379 	O_FOREGROUND,
1380 	O_NUMERRORS,
1381 	O_PIDFILE,
1382 	O_DEBUG_NUMERRORS,
1383 	O_NO_IMC_LOG,
1384 	O_IS_CPU_SUPPORTED,
1385 	O_MAX_CORR_ERR_COUNTERS,
1386 	O_HELP,
1387 };
1388 
1389 static struct option options[] = {
1390 	{ "logfile", 1, NULL, O_LOGFILE },
1391 	{ "k8", 0, NULL, O_K8 },
1392 	{ "p4", 0, NULL, O_P4 },
1393 	{ "generic", 0, NULL, O_GENERIC },
1394 	{ "core2", 0, NULL, O_CORE2 },
1395 	{ "intel-cpu", 1, NULL, O_INTEL_CPU },
1396 	{ "ignorenodev", 0, &ignore_nodev, 1 },
1397 	{ "filter", 0, &filter_bogus, 1 },
1398 	{ "no-filter", 0, &filter_bogus, 0 },
1399 	{ "dmi", 0, NULL, O_DMI },
1400 	{ "no-dmi", 0, NULL, O_NO_DMI },
1401 	{ "dmi-verbose", 1, NULL, O_DMI_VERBOSE },
1402 	{ "syslog", 0, NULL, O_SYSLOG },
1403 	{ "cpumhz", 1, NULL, O_CPUMHZ },
1404 	{ "syslog-error", 0, NULL, O_SYSLOG_ERROR },
1405 	{ "dump-raw-ascii", 0, &dump_raw_ascii, 1 },
1406 	{ "raw", 0, &dump_raw_ascii, 1 },
1407 	{ "no-syslog", 0, NULL, O_NO_SYSLOG },
1408 	{ "daemon", 0, NULL, O_DAEMON },
1409 	{ "ascii", 0, NULL, O_ASCII },
1410 	{ "file", 1, NULL, O_FILE },
1411 	{ "version", 0, NULL, O_VERSION },
1412 	{ "config-file", 1, NULL, O_CONFIG_FILE },
1413 	{ "cpu", 1, NULL, O_CPU },
1414 	{ "foreground", 0, NULL, O_FOREGROUND },
1415 	{ "client", 0, NULL, O_CLIENT },
1416 	{ "num-errors", 1, NULL, O_NUMERRORS },
1417 	{ "pidfile", 1, NULL, O_PIDFILE },
1418 	{ "debug-numerrors", 0, NULL, O_DEBUG_NUMERRORS }, /* undocumented: for testing */
1419 	{ "no-imc-log", 0, NULL, O_NO_IMC_LOG },
1420 	{ "max-corr-err-counters", 1, NULL, O_MAX_CORR_ERR_COUNTERS },
1421 	{ "help", 0, NULL, O_HELP },
1422 	{ "is-cpu-supported", 0, NULL, O_IS_CPU_SUPPORTED },
1423 	{}
1424 };
1425 
modifier(int opt)1426 static int modifier(int opt)
1427 {
1428 	int v;
1429 
1430 	switch (opt) {
1431 	case O_LOGFILE:
1432 		logfile = optarg;
1433 		break;
1434 	case O_K8:
1435 		cputype = CPU_K8;
1436 		cpu_forced = 1;
1437 		break;
1438 	case O_P4:
1439 		cputype = CPU_P4;
1440 		cpu_forced = 1;
1441 		break;
1442 	case O_GENERIC:
1443 		cputype = CPU_GENERIC;
1444 		cpu_forced = 1;
1445 		break;
1446 	case O_CORE2:
1447 		cputype = CPU_CORE2;
1448 		cpu_forced = 1;
1449 		break;
1450 	case O_INTEL_CPU: {
1451 		unsigned fam, mod;
1452 		if (sscanf(optarg, "%i,%i", &fam, &mod) != 2) {
1453 			usage();
1454 			exit(1);
1455 		}
1456 		cputype = select_intel_cputype(fam, mod);
1457 		if (cputype == CPU_GENERIC) {
1458 			fprintf(stderr, "Unknown Intel CPU\n");
1459 			usage();
1460 			exit(1);
1461 		}
1462 		cpu_forced = 1;
1463 		break;
1464 	}
1465 	case O_CPU:
1466 		cputype = lookup_cputype(optarg);
1467 		cpu_forced = 1;
1468 		intel_cpu_init(cputype);
1469 		break;
1470 	case O_DMI:
1471 		do_dmi = 1;
1472 		dmi_forced = 1;
1473 		break;
1474 	case O_NO_DMI:
1475 		dmi_forced = 1;
1476 		do_dmi = 0;
1477 		break;
1478 	case O_DMI_VERBOSE:
1479 		if (sscanf(optarg, "%i", &v) != 1) {
1480 			usage();
1481 			exit(1);
1482 		}
1483 		dmi_set_verbosity(v);
1484 		break;
1485 	case O_SYSLOG:
1486 		openlog("mcelog", 0, LOG_DAEMON);
1487 		syslog_opt = SYSLOG_ALL|SYSLOG_FORCE;
1488 		break;
1489 	case O_NO_SYSLOG:
1490 		syslog_opt = SYSLOG_FORCE;
1491 		break;
1492 	case O_CPUMHZ:
1493 		cpumhz_forced = 1;
1494 		if (sscanf(optarg, "%lf", &cpumhz) != 1) {
1495 			usage();
1496 			exit(1);
1497 		}
1498 		break;
1499 	case O_SYSLOG_ERROR:
1500 		syslog_level = LOG_ERR;
1501 		syslog_opt = SYSLOG_ALL|SYSLOG_FORCE;
1502 		break;
1503 	case O_DAEMON:
1504 		daemon_mode = 1;
1505 		if (!(syslog_opt & SYSLOG_FORCE))
1506 			syslog_opt = SYSLOG_REMARK|SYSLOG_ERROR;
1507 		break;
1508 	case O_FILE:
1509 		inputfile = optarg;
1510 		break;
1511 	case O_FOREGROUND:
1512 		foreground = 1;
1513 		if (!(syslog_opt & SYSLOG_FORCE))
1514 			syslog_opt = SYSLOG_FORCE;
1515 		break;
1516 	case O_NUMERRORS:
1517 		numerrors = atoi(optarg);
1518 		break;
1519 	case O_PIDFILE:
1520 		setup_pidfile(optarg);
1521 		break;
1522 	case O_CONFIG_FILE:
1523 		/* parsed in config.c */
1524 		break;
1525 	case O_DEBUG_NUMERRORS:
1526 		debug_numerrors = 1;
1527 		break;
1528 	case O_NO_IMC_LOG:
1529 		imc_log = 0;
1530 		break;
1531 	case O_MAX_CORR_ERR_COUNTERS:
1532 		max_corr_err_counters = atoi(optarg);
1533 		break;
1534 	case O_IS_CPU_SUPPORTED:
1535 		check_only = 1;
1536 		break;
1537 	case O_HELP:
1538 		usage();
1539 		exit(0);
1540 		break;
1541 #ifdef __FreeBSD__
1542 	case 'M':
1543 		corefile = strdup(optarg);
1544 		break;
1545 	case 'N':
1546 		execfile = strdup(optarg);
1547 		break;
1548 #endif
1549 	case 0:
1550 		break;
1551 	default:
1552 		return 0;
1553 	}
1554 	return 1;
1555 }
1556 
modifier_finish(void)1557 static void modifier_finish(void)
1558 {
1559 	if(!foreground && daemon_mode && !logfile && !(syslog_opt & SYSLOG_LOG)) {
1560 		logfile = logfile_default;
1561 	}
1562 	if (logfile) {
1563 		if (open_logfile(logfile) < 0) {
1564 			if (daemon_mode && !(syslog_opt & SYSLOG_FORCE))
1565 				syslog_opt = SYSLOG_ALL;
1566 			SYSERRprintf("Cannot open logfile %s", logfile);
1567 			if (!daemon_mode)
1568 				exit(1);
1569 		}
1570 	}
1571 }
1572 
argsleft(int ac,char ** av)1573 void argsleft(int ac, char **av)
1574 {
1575 	int opt;
1576 
1577 	while ((opt = getopt_long(ac, av, "", options, NULL)) != -1) {
1578 		if (modifier(opt) != 1) {
1579 			usage();
1580 			exit(1);
1581 		}
1582 	}
1583 }
1584 
no_syslog(void)1585 void no_syslog(void)
1586 {
1587 	if (!(syslog_opt & SYSLOG_FORCE))
1588 		syslog_opt = 0;
1589 }
1590 
combined_modifier(int opt)1591 static int combined_modifier(int opt)
1592 {
1593 	int r = modifier(opt);
1594 	return r;
1595 }
1596 
general_setup(void)1597 static void general_setup(void)
1598 {
1599 #ifdef __Linux__
1600 	trigger_setup();
1601 	yellow_setup();
1602 	bus_setup();
1603 	unknown_setup();
1604 #endif
1605 	config_cred("global", "run-credentials", &runcred);
1606 	if (config_bool("global", "filter-memory-errors") == 1)
1607 		filter_memory_errors = 1;
1608 }
1609 
drop_cred(void)1610 static void drop_cred(void)
1611 {
1612 	if (runcred.uid != -1U && runcred.gid == -1U) {
1613 		struct passwd *pw = getpwuid(runcred.uid);
1614 		if (pw)
1615 			runcred.gid = pw->pw_gid;
1616 	}
1617 	if (runcred.gid != -1U) {
1618 		if (setgid(runcred.gid) < 0)
1619 			SYSERRprintf("Cannot change group to %d", runcred.gid);
1620 	}
1621 	if (runcred.uid != -1U) {
1622 		if (setuid(runcred.uid) < 0)
1623 			SYSERRprintf("Cannot change user to %d", runcred.uid);
1624 	}
1625 }
1626 
1627 #ifdef __Linux__
process(int fd,unsigned recordlen,unsigned loglen,char * buf)1628 static void process(int fd, unsigned recordlen, unsigned loglen, char *buf)
1629 {
1630 	int i;
1631 	int len, count;
1632 	int finish = 0, flags;
1633 
1634 	if (recordlen == 0) {
1635 		Wprintf("no data in mce record\n");
1636 		return;
1637 	}
1638 
1639 	len = read(fd, buf, recordlen * loglen);
1640 	if (len < 0) {
1641 		SYSERRprintf("mcelog read");
1642 		return;
1643 	}
1644 
1645 	count = len / (int)recordlen;
1646 	if (count == (int)loglen) {
1647 		if ((ioctl(fd, MCE_GETCLEAR_FLAGS, &flags) == 0) &&
1648 		    (flags & (1 << MCE_OVERFLOW)))
1649 			Eprintf("Warning: MCE buffer is overflowed.\n");
1650 	}
1651 
1652 	for (i = 0; (i < count) && !finish; i++) {
1653 		struct mce *mce = (struct mce *)(buf + i*recordlen);
1654 		mce_prepare(mce);
1655 		if (numerrors > 0 && --numerrors == 0)
1656 			finish = 1;
1657 		if (!mce_filter(mce, recordlen))
1658 			continue;
1659 		if (!dump_raw_ascii) {
1660 			disclaimer();
1661 			Wprintf("MCE %d\n", i);
1662 			dump_mce(mce, recordlen);
1663 		} else
1664 			dump_mce_raw_ascii(mce, recordlen);
1665 		flushlog();
1666 	}
1667 
1668 	if (debug_numerrors && numerrors <= 0)
1669 		finish = 1;
1670 
1671 	if (recordlen > sizeof(struct mce))  {
1672 		Eprintf("warning: %lu bytes ignored in each record\n",
1673 				(unsigned long)recordlen - sizeof(struct mce));
1674 		Eprintf("consider an update\n");
1675 	}
1676 
1677 	if (finish)
1678 		exit(0);
1679 }
1680 #endif
1681 
1682 #ifdef __FreeBSD__
1683 #ifdef LOCAL_HACK
1684 struct mca_record_old {
1685 	uint64_t	mr_status;
1686 	uint64_t	mr_addr;
1687 	uint64_t	mr_misc;
1688 	uint64_t	mr_tsc;
1689 	int		mr_apic_id;
1690 	int		mr_bank;
1691 };
1692 #endif
1693 
1694 struct mca_record_internal {
1695 	struct mca_record rec;
1696 	int		logged;
1697 	STAILQ_ENTRY(mca_internal) link;
1698 };
1699 
1700 #ifdef LOCAL_HACK
1701 struct mca_record_internal_old {
1702 	struct mca_record_old rec;
1703 	int		logged;
1704 	STAILQ_ENTRY(mca_internal) link;
1705 };
1706 #endif
1707 
1708 static struct nlist nl[] = {
1709 #define	X_MCA_RECORDS		0
1710 	{ .n_name = "_mca_records" },
1711 #ifdef LOCAL_HACK
1712 #define	X_SNAPDATE		1
1713 	{ .n_name = "_snapdate" },
1714 #endif
1715 	{ .n_name = NULL },
1716 };
1717 
1718 static int
kread(kvm_t * kvm,void * kvm_pointer,void * buf,size_t size,size_t offset)1719 kread(kvm_t *kvm, void *kvm_pointer, void *buf, size_t size, size_t offset)
1720 {
1721 	ssize_t ret;
1722 
1723 	ret = kvm_read(kvm, (unsigned long)kvm_pointer + offset, buf, size);
1724 	if (ret < 0 || (size_t)ret != size)
1725 		return (-1);
1726 	return (0);
1727 }
1728 
1729 static int
kread_symbol(kvm_t * kvm,int index,void * buf,size_t size)1730 kread_symbol(kvm_t *kvm, int index, void *buf, size_t size)
1731 {
1732 	ssize_t ret;
1733 
1734 	ret = kvm_read(kvm, nl[index].n_value, buf, size);
1735 	if (ret < 0 || (size_t)ret != size)
1736 		return (-1);
1737 	return (0);
1738 }
1739 
process_kvm(const char * execfile,const char * corefile)1740 static void process_kvm(const char *execfile, const char *corefile)
1741 {
1742 	struct mca_record mr, *mrp;
1743 	struct mce mce;
1744 	char errbuf[_POSIX2_LINE_MAX];
1745 	kvm_t *kvm;
1746 	size_t record_size, link_offset;
1747 	int i;
1748 #ifdef LOCAL_HACK
1749 	int snapdate;
1750 #endif
1751 
1752 	kvm = kvm_openfiles(execfile, corefile, NULL, O_RDONLY, errbuf);
1753 	if (kvm == NULL)
1754 		errx(1, "kvm_openfiles: %s", errbuf);
1755 	if (kvm_nlist(kvm, nl) != 0)
1756 		errx(1, "kvm_nlist: %s", kvm_geterr(kvm));
1757 
1758 #ifdef LOCAL_HACK
1759 	if (kread_symbol(kvm, X_SNAPDATE, &snapdate, sizeof(snapdate)) < 0)
1760 		errx(1, "kvm_read(snapdate) failed");
1761 #endif
1762 	/* stqh_first is the first pointer at this address. */
1763 	if (kread_symbol(kvm, X_MCA_RECORDS, &mrp, sizeof(mrp)) < 0)
1764 		errx(1, "kvm_read(mca_records) failed");
1765 #ifdef LOCAL_HACK
1766 	if (snapdate >= 20100329) {
1767 #endif
1768 		record_size = sizeof(struct mca_record);
1769 		link_offset = __offsetof(struct mca_record_internal,
1770 		    link.stqe_next);
1771 #ifdef LOCAL_HACK
1772 	} else {
1773 		record_size = sizeof(struct mca_record_old);
1774 		link_offset = __offsetof(struct mca_record_internal_old,
1775 		    link.stqe_next);
1776 	}
1777 #endif
1778 
1779 	for (i = 0; mrp != NULL; i++) {
1780 		memset(&mr, 0, sizeof(mr));
1781 		if (kread(kvm, mrp, &mr, record_size, 0) < 0)
1782 			break;
1783 		if (kread(kvm, mrp, &mrp, sizeof(mrp), link_offset) < 0)
1784 			mrp = NULL;
1785 
1786 		convert_mca(&mr, &mce, 1, record_size);
1787 		mce_prepare(&mce);
1788 		if (!mce_filter(&mce, sizeof(struct mce)))
1789 			continue;
1790 		if (!dump_raw_ascii) {
1791 			disclaimer();
1792 			Wprintf("MCE %d\n", i);
1793 			dump_mce(&mce, sizeof(struct mce));
1794 		} else
1795 			dump_mce_raw_ascii(&mce, sizeof(struct mce));
1796 		flushlog();
1797 	}
1798 
1799 	exit(0);
1800 }
1801 
process_live(void)1802 static void process_live(void)
1803 {
1804 	struct mca_record mr;
1805 	struct mce mce;
1806 	int mib[4];
1807 	size_t len;
1808 	int count, finish, i;
1809 
1810 	len = sizeof(count);
1811 	if (sysctlbyname("hw.mca.count", &count, &len, NULL, 0) < 0)
1812 		return;
1813 
1814 	len = 4;
1815 	if (sysctlnametomib("hw.mca.records", mib, &len) < 0)
1816 		return;
1817 
1818 	finish = 0;
1819 	for (i = 0; i < count; i++) {
1820 		mib[3] = i;
1821 		len = sizeof(mr);
1822 		memset(&mr, 0, sizeof(mr));
1823 		if (sysctl(mib, 4, &mr, &len, NULL, 0) < 0) {
1824 			warn("sysctl(hw.mca.records.%d)", i);
1825 			continue;
1826 		}
1827 
1828 		convert_mca(&mr, &mce, 1, len);
1829 		mce_prepare(&mce);
1830 		if (numerrors > 0 && --numerrors == 0)
1831 			finish = 1;
1832 		if (!mce_filter(&mce, sizeof(struct mce)))
1833 			continue;
1834 		if (!dump_raw_ascii) {
1835 			disclaimer();
1836 			Wprintf("MCE %d\n", i);
1837 			dump_mce(&mce, sizeof(struct mce));
1838 		} else
1839 			dump_mce_raw_ascii(&mce, sizeof(struct mce));
1840 		flushlog();
1841 	}
1842 
1843 	if (finish)
1844 		exit(0);
1845 }
1846 #endif
1847 
noargs(int ac,char ** av)1848 static void noargs(int ac, char **av)
1849 {
1850 	if (getopt_long(ac, av, "", options, NULL) != -1) {
1851 		usage();
1852 		exit(1);
1853 	}
1854 }
1855 
parse_config(char ** av)1856 static void parse_config(char **av)
1857 {
1858 	static const char config_fn[] = CONFIG_FILENAME;
1859 	const char *fn = config_file(av, config_fn);
1860 	if (!fn) {
1861 		usage();
1862 		exit(1);
1863 	}
1864 	if (parse_config_file(fn) < 0) {
1865 		/* If it's the default file don't complain if it isn't there */
1866 		if (fn != config_fn) {
1867 			fprintf(stderr, "Cannot open config file %s\n", fn);
1868 			exit(1);
1869 		}
1870 		return;
1871 	}
1872 	config_options(options, combined_modifier);
1873 }
1874 
ascii_command(int ac,char ** av)1875 static void ascii_command(int ac, char **av)
1876 {
1877 	FILE *f = stdin;
1878 
1879 	argsleft(ac, av);
1880 	if (inputfile) {
1881 		f = fopen(inputfile, "r");
1882 		if (!f) {
1883 			fprintf(stderr, "Cannot open input file `%s': %s\n",
1884 				inputfile, strerror(errno));
1885 			exit(1);
1886 		}
1887 		/* f closed by exit */
1888 	}
1889 	no_syslog();
1890 	checkdmi();
1891 	decodefatal(f);
1892 }
1893 
client_command(int ac,char ** av)1894 static void client_command(int ac, char **av)
1895 {
1896 	argsleft(ac, av);
1897 	no_syslog();
1898 	// XXX modifiers
1899 	ask_server("dump all bios\n");
1900 	ask_server("pages\n");
1901 }
1902 
1903 struct mcefd_data {
1904 	unsigned loglen;
1905 	unsigned recordlen;
1906 	char *buf;
1907 };
1908 
1909 #ifdef __Linux__
process_mcefd(struct pollfd * pfd,void * data)1910 static void process_mcefd(struct pollfd *pfd, void *data)
1911 {
1912 	struct mcefd_data *d = (struct mcefd_data *)data;
1913 	assert((pfd->revents & POLLIN) != 0);
1914 	process(pfd->fd, d->recordlen, d->loglen, d->buf);
1915 }
1916 #endif
1917 
handle_sigusr1(int sig)1918 static void handle_sigusr1(int sig)
1919 {
1920 	reopenlog();
1921 }
1922 
main(int ac,char ** av)1923 int main(int ac, char **av)
1924 {
1925 #ifdef __Linux__
1926 	struct mcefd_data d = {};
1927 	int fd;
1928 #endif
1929 	int opt;
1930 	parse_config(av);
1931 
1932 #ifdef __FreeBSD
1933 	while ((opt = getopt_long(ac, av, "M:N:", options, NULL)) != -1) {
1934 #else
1935 	while ((opt = getopt_long(ac, av, "", options, NULL)) != -1) {
1936 #endif
1937 		if (opt == '?') {
1938 			usage();
1939 			exit(1);
1940 		} else if (combined_modifier(opt) > 0) {
1941 			continue;
1942 		} else if (opt == O_ASCII) {
1943 			ascii_command(ac, av);
1944 			exit(0);
1945 		} else if (opt == O_CLIENT) {
1946 			client_command(ac, av);
1947 			exit(0);
1948 		} else if (opt == O_VERSION) {
1949 			noargs(ac, av);
1950 			fprintf(stderr, "mcelog %s\n", MCELOG_VERSION);
1951 			exit(0);
1952 		} else if (opt == 0)
1953 			break;
1954 	}
1955 
1956 	/* before doing anything else let's see if the CPUs are supported */
1957 #ifdef __Linux__
1958 	if (!cpu_forced && !is_cpu_supported()) {
1959 		if (!check_only)
1960 			fprintf(stderr, "CPU is unsupported\n");
1961 		exit(1);
1962 	}
1963 #endif
1964 	if (check_only)
1965 		exit(0);
1966 
1967 	/* If the user didn't tell us not to use iMC logging, check if CPU supports it */
1968 	if (imc_log == -1) {
1969 		switch (cputype) {
1970 		case CPU_SANDY_BRIDGE_EP:
1971 		case CPU_IVY_BRIDGE_EPEX:
1972 		case CPU_HASWELL_EPEX:
1973 			imc_log = 1;
1974 			break;
1975 		default:
1976 			imc_log = 0;
1977 			break;
1978 		}
1979 	}
1980 
1981 	modifier_finish();
1982 #ifdef __Linux__
1983 	if (av[optind])
1984 		logfn = av[optind++];
1985 #endif
1986 	if (av[optind]) {
1987 		usage();
1988 #ifdef __FreeBSD__
1989 	if ((corefile != NULL) ^ (execfile != NULL) ||
1990 	    (corefile != NULL && daemon_mode))
1991 		usage();
1992 #endif
1993 		exit(1);
1994 	}
1995 	checkdmi();
1996 	general_setup();
1997 
1998 #ifdef __Linux__
1999 	fd = open(logfn, O_RDONLY);
2000 	if (fd < 0) {
2001 		if (ignore_nodev)
2002 			exit(0);
2003 		SYSERRprintf("Cannot open `%s'", logfn);
2004 		exit(1);
2005 	}
2006 
2007 	if (ioctl(fd, MCE_GET_RECORD_LEN, &d.recordlen) < 0)
2008 		err("MCE_GET_RECORD_LEN");
2009 	if (ioctl(fd, MCE_GET_LOG_LEN, &d.loglen) < 0)
2010 		err("MCE_GET_LOG_LEN");
2011 
2012 	d.buf = xalloc(d.recordlen * d.loglen);
2013 #endif
2014 	if (daemon_mode) {
2015 		prefill_memdb(do_dmi);
2016 		if (!do_dmi)
2017 			closedmi();
2018 		server_setup();
2019 #ifdef __Linux__
2020 		page_setup();
2021 #endif
2022 		if (imc_log)
2023 			set_imc_log(cputype);
2024 		drop_cred();
2025 #ifdef __Linux__
2026 		register_pollcb(fd, POLLIN, process_mcefd, &d);
2027 #endif
2028 		if (!foreground && daemon(0, need_stdout()) < 0)
2029 			err("daemon");
2030 		if (pidfile)
2031 			write_pidfile();
2032 		signal(SIGUSR1, handle_sigusr1);
2033 #ifdef __Linux__
2034 		event_signal(SIGUSR1);
2035 #endif
2036 		eventloop();
2037 	} else {
2038 #ifdef __Linux__
2039 		process(fd, d.recordlen, d.loglen, d.buf);
2040 #endif
2041 #ifdef __FreeBSD__
2042 		if (corefile != NULL)
2043 			process_kvm(execfile, corefile);
2044 		else
2045 			process_live();
2046 #endif
2047 	}
2048 #ifdef __Linux__
2049 	trigger_wait();
2050 #endif
2051 
2052 	exit(0);
2053 }
2054