xref: /linux/arch/x86/boot/cpu.c (revision aa23aa55166c2865ac430168c4b9d405cf8c6980)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* -*- linux-c -*- ------------------------------------------------------- *
3  *
4  *   Copyright (C) 1991, 1992 Linus Torvalds
5  *   Copyright 2007-2008 rPath, Inc. - All Rights Reserved
6  *
7  * ----------------------------------------------------------------------- */
8 
9 /*
10  * arch/x86/boot/cpu.c
11  *
12  * Check for obligatory CPU features and abort if the features are not
13  * present.
14  */
15 
16 #include "boot.h"
17 #ifdef CONFIG_X86_FEATURE_NAMES
18 #include "cpustr.h"
19 #endif
20 
21 static char *cpu_name(int level)
22 {
23 	static char buf[6];
24 
25 	if (level == 64) {
26 		return "x86-64";
27 	} else {
28 		if (level == 15)
29 			level = 6;
30 		sprintf(buf, "i%d86", level);
31 		return buf;
32 	}
33 }
34 
35 static void show_cap_strs(u32 *err_flags)
36 {
37 	int i, j;
38 #ifdef CONFIG_X86_FEATURE_NAMES
39 	const unsigned char *msg_strs = (const unsigned char *)x86_cap_strs;
40 	for (i = 0; i < NCAPINTS; i++) {
41 		u32 e = err_flags[i];
42 		for (j = 0; j < 32; j++) {
43 			if (msg_strs[0] < i ||
44 			    (msg_strs[0] == i && msg_strs[1] < j)) {
45 				/* Skip to the next string */
46 				msg_strs += 2;
47 				while (*msg_strs++)
48 					;
49 			}
50 			if (e & 1) {
51 				if (msg_strs[0] == i &&
52 				    msg_strs[1] == j &&
53 				    msg_strs[2])
54 					printf("%s ", msg_strs+2);
55 				else
56 					printf("%d:%d ", i, j);
57 			}
58 			e >>= 1;
59 		}
60 	}
61 #else
62 	for (i = 0; i < NCAPINTS; i++) {
63 		u32 e = err_flags[i];
64 		for (j = 0; j < 32; j++) {
65 			if (e & 1)
66 				printf("%d:%d ", i, j);
67 			e >>= 1;
68 		}
69 	}
70 #endif
71 }
72 
73 int validate_cpu(void)
74 {
75 	u32 *err_flags;
76 	int cpu_level, req_level;
77 
78 	check_cpu(&cpu_level, &req_level, &err_flags);
79 
80 	if (cpu_level < req_level) {
81 		printf("This kernel requires an %s CPU, ",
82 		       cpu_name(req_level));
83 		printf("but only detected an %s CPU.\n",
84 		       cpu_name(cpu_level));
85 		return -1;
86 	}
87 
88 	if (err_flags) {
89 		puts("This kernel requires the following features "
90 		     "not present on the CPU:\n");
91 		show_cap_strs(err_flags);
92 		putchar('\n');
93 		return -1;
94 	} else if (check_knl_erratum()) {
95 		return -1;
96 	} else {
97 		return 0;
98 	}
99 }
100