197873a3dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 296ae6ea0SThomas Gleixner /* -*- linux-c -*- ------------------------------------------------------- * 396ae6ea0SThomas Gleixner * 496ae6ea0SThomas Gleixner * Copyright (C) 1991, 1992 Linus Torvalds 5f0be6c6aSH. Peter Anvin * Copyright 2007-2008 rPath, Inc. - All Rights Reserved 696ae6ea0SThomas Gleixner * 796ae6ea0SThomas Gleixner * ----------------------------------------------------------------------- */ 896ae6ea0SThomas Gleixner 996ae6ea0SThomas Gleixner /* 10f0be6c6aSH. Peter Anvin * arch/x86/boot/cpu.c 1196ae6ea0SThomas Gleixner * 1296ae6ea0SThomas Gleixner * Check for obligatory CPU features and abort if the features are not 1396ae6ea0SThomas Gleixner * present. 1496ae6ea0SThomas Gleixner */ 1596ae6ea0SThomas Gleixner 1696ae6ea0SThomas Gleixner #include "boot.h" 179def39beSJosh Triplett #ifdef CONFIG_X86_FEATURE_NAMES 18f0be6c6aSH. Peter Anvin #include "cpustr.h" 199def39beSJosh Triplett #endif 20f0be6c6aSH. Peter Anvin 2196ae6ea0SThomas Gleixner static char *cpu_name(int level) 2296ae6ea0SThomas Gleixner { 2396ae6ea0SThomas Gleixner static char buf[6]; 2496ae6ea0SThomas Gleixner 2596ae6ea0SThomas Gleixner if (level == 64) { 2696ae6ea0SThomas Gleixner return "x86-64"; 2796ae6ea0SThomas Gleixner } else { 28c7d624d1SDave Jones if (level == 15) 29c7d624d1SDave Jones level = 6; 3096ae6ea0SThomas Gleixner sprintf(buf, "i%d86", level); 3196ae6ea0SThomas Gleixner return buf; 3296ae6ea0SThomas Gleixner } 3396ae6ea0SThomas Gleixner } 3496ae6ea0SThomas Gleixner 359def39beSJosh Triplett static void show_cap_strs(u32 *err_flags) 3696ae6ea0SThomas Gleixner { 3796ae6ea0SThomas Gleixner int i, j; 389def39beSJosh Triplett #ifdef CONFIG_X86_FEATURE_NAMES 399def39beSJosh Triplett const unsigned char *msg_strs = (const unsigned char *)x86_cap_strs; 4096ae6ea0SThomas Gleixner for (i = 0; i < NCAPINTS; i++) { 4196ae6ea0SThomas Gleixner u32 e = err_flags[i]; 4296ae6ea0SThomas Gleixner for (j = 0; j < 32; j++) { 4397fc0555SH. Peter Anvin if (msg_strs[0] < i || 4497fc0555SH. Peter Anvin (msg_strs[0] == i && msg_strs[1] < j)) { 45f0be6c6aSH. Peter Anvin /* Skip to the next string */ 4697fc0555SH. Peter Anvin msg_strs += 2; 4797fc0555SH. Peter Anvin while (*msg_strs++) 4897fc0555SH. Peter Anvin ; 49f0be6c6aSH. Peter Anvin } 50f0be6c6aSH. Peter Anvin if (e & 1) { 5197fc0555SH. Peter Anvin if (msg_strs[0] == i && 5297fc0555SH. Peter Anvin msg_strs[1] == j && 5397fc0555SH. Peter Anvin msg_strs[2]) 5497fc0555SH. Peter Anvin printf("%s ", msg_strs+2); 55f0be6c6aSH. Peter Anvin else 5696ae6ea0SThomas Gleixner printf("%d:%d ", i, j); 57f0be6c6aSH. Peter Anvin } 5896ae6ea0SThomas Gleixner e >>= 1; 5996ae6ea0SThomas Gleixner } 6096ae6ea0SThomas Gleixner } 619def39beSJosh Triplett #else 629def39beSJosh Triplett for (i = 0; i < NCAPINTS; i++) { 639def39beSJosh Triplett u32 e = err_flags[i]; 649def39beSJosh Triplett for (j = 0; j < 32; j++) { 659def39beSJosh Triplett if (e & 1) 669def39beSJosh Triplett printf("%d:%d ", i, j); 679def39beSJosh Triplett e >>= 1; 689def39beSJosh Triplett } 699def39beSJosh Triplett } 709def39beSJosh Triplett #endif 719def39beSJosh Triplett } 729def39beSJosh Triplett 739def39beSJosh Triplett int validate_cpu(void) 749def39beSJosh Triplett { 759def39beSJosh Triplett u32 *err_flags; 769def39beSJosh Triplett int cpu_level, req_level; 779def39beSJosh Triplett 789def39beSJosh Triplett check_cpu(&cpu_level, &req_level, &err_flags); 799def39beSJosh Triplett 809def39beSJosh Triplett if (cpu_level < req_level) { 819def39beSJosh Triplett printf("This kernel requires an %s CPU, ", 829def39beSJosh Triplett cpu_name(req_level)); 839def39beSJosh Triplett printf("but only detected an %s CPU.\n", 849def39beSJosh Triplett cpu_name(cpu_level)); 859def39beSJosh Triplett return -1; 869def39beSJosh Triplett } 879def39beSJosh Triplett 889def39beSJosh Triplett if (err_flags) { 899def39beSJosh Triplett puts("This kernel requires the following features " 909def39beSJosh Triplett "not present on the CPU:\n"); 919def39beSJosh Triplett show_cap_strs(err_flags); 9296ae6ea0SThomas Gleixner putchar('\n'); 9396ae6ea0SThomas Gleixner return -1; 94e4a84be6SDave Hansen } else if (check_knl_erratum()) { 95e4a84be6SDave Hansen return -1; 9696ae6ea0SThomas Gleixner } else { 9796ae6ea0SThomas Gleixner return 0; 9896ae6ea0SThomas Gleixner } 9996ae6ea0SThomas Gleixner } 100