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