196ae6ea0SThomas Gleixner /* -*- linux-c -*- ------------------------------------------------------- * 296ae6ea0SThomas Gleixner * 396ae6ea0SThomas Gleixner * Copyright (C) 1991, 1992 Linus Torvalds 4f0be6c6aSH. Peter Anvin * Copyright 2007-2008 rPath, Inc. - All Rights Reserved 596ae6ea0SThomas Gleixner * 696ae6ea0SThomas Gleixner * This file is part of the Linux kernel, and is made available under 796ae6ea0SThomas Gleixner * the terms of the GNU General Public License version 2. 896ae6ea0SThomas Gleixner * 996ae6ea0SThomas Gleixner * ----------------------------------------------------------------------- */ 1096ae6ea0SThomas Gleixner 1196ae6ea0SThomas Gleixner /* 12f0be6c6aSH. Peter Anvin * arch/x86/boot/cpu.c 1396ae6ea0SThomas Gleixner * 1496ae6ea0SThomas Gleixner * Check for obligatory CPU features and abort if the features are not 1596ae6ea0SThomas Gleixner * present. 1696ae6ea0SThomas Gleixner */ 1796ae6ea0SThomas Gleixner 1896ae6ea0SThomas Gleixner #include "boot.h" 199def39beSJosh Triplett #ifdef CONFIG_X86_FEATURE_NAMES 20f0be6c6aSH. Peter Anvin #include "cpustr.h" 219def39beSJosh Triplett #endif 22f0be6c6aSH. Peter Anvin 2396ae6ea0SThomas Gleixner static char *cpu_name(int level) 2496ae6ea0SThomas Gleixner { 2596ae6ea0SThomas Gleixner static char buf[6]; 2696ae6ea0SThomas Gleixner 2796ae6ea0SThomas Gleixner if (level == 64) { 2896ae6ea0SThomas Gleixner return "x86-64"; 2996ae6ea0SThomas Gleixner } else { 30c7d624d1SDave Jones if (level == 15) 31c7d624d1SDave Jones level = 6; 3296ae6ea0SThomas Gleixner sprintf(buf, "i%d86", level); 3396ae6ea0SThomas Gleixner return buf; 3496ae6ea0SThomas Gleixner } 3596ae6ea0SThomas Gleixner } 3696ae6ea0SThomas Gleixner 379def39beSJosh Triplett static void show_cap_strs(u32 *err_flags) 3896ae6ea0SThomas Gleixner { 3996ae6ea0SThomas Gleixner int i, j; 409def39beSJosh Triplett #ifdef CONFIG_X86_FEATURE_NAMES 419def39beSJosh Triplett const unsigned char *msg_strs = (const unsigned char *)x86_cap_strs; 4296ae6ea0SThomas Gleixner for (i = 0; i < NCAPINTS; i++) { 4396ae6ea0SThomas Gleixner u32 e = err_flags[i]; 4496ae6ea0SThomas Gleixner for (j = 0; j < 32; j++) { 4597fc0555SH. Peter Anvin if (msg_strs[0] < i || 4697fc0555SH. Peter Anvin (msg_strs[0] == i && msg_strs[1] < j)) { 47f0be6c6aSH. Peter Anvin /* Skip to the next string */ 4897fc0555SH. Peter Anvin msg_strs += 2; 4997fc0555SH. Peter Anvin while (*msg_strs++) 5097fc0555SH. Peter Anvin ; 51f0be6c6aSH. Peter Anvin } 52f0be6c6aSH. Peter Anvin if (e & 1) { 5397fc0555SH. Peter Anvin if (msg_strs[0] == i && 5497fc0555SH. Peter Anvin msg_strs[1] == j && 5597fc0555SH. Peter Anvin msg_strs[2]) 5697fc0555SH. Peter Anvin printf("%s ", msg_strs+2); 57f0be6c6aSH. Peter Anvin else 5896ae6ea0SThomas Gleixner printf("%d:%d ", i, j); 59f0be6c6aSH. Peter Anvin } 6096ae6ea0SThomas Gleixner e >>= 1; 6196ae6ea0SThomas Gleixner } 6296ae6ea0SThomas Gleixner } 639def39beSJosh Triplett #else 649def39beSJosh Triplett for (i = 0; i < NCAPINTS; i++) { 659def39beSJosh Triplett u32 e = err_flags[i]; 669def39beSJosh Triplett for (j = 0; j < 32; j++) { 679def39beSJosh Triplett if (e & 1) 689def39beSJosh Triplett printf("%d:%d ", i, j); 699def39beSJosh Triplett e >>= 1; 709def39beSJosh Triplett } 719def39beSJosh Triplett } 729def39beSJosh Triplett #endif 739def39beSJosh Triplett } 749def39beSJosh Triplett 759def39beSJosh Triplett int validate_cpu(void) 769def39beSJosh Triplett { 779def39beSJosh Triplett u32 *err_flags; 789def39beSJosh Triplett int cpu_level, req_level; 799def39beSJosh Triplett 809def39beSJosh Triplett check_cpu(&cpu_level, &req_level, &err_flags); 819def39beSJosh Triplett 829def39beSJosh Triplett if (cpu_level < req_level) { 839def39beSJosh Triplett printf("This kernel requires an %s CPU, ", 849def39beSJosh Triplett cpu_name(req_level)); 859def39beSJosh Triplett printf("but only detected an %s CPU.\n", 869def39beSJosh Triplett cpu_name(cpu_level)); 879def39beSJosh Triplett return -1; 889def39beSJosh Triplett } 899def39beSJosh Triplett 909def39beSJosh Triplett if (err_flags) { 919def39beSJosh Triplett puts("This kernel requires the following features " 929def39beSJosh Triplett "not present on the CPU:\n"); 939def39beSJosh Triplett show_cap_strs(err_flags); 9496ae6ea0SThomas Gleixner putchar('\n'); 9596ae6ea0SThomas Gleixner return -1; 9696ae6ea0SThomas Gleixner } else { 9796ae6ea0SThomas Gleixner return 0; 9896ae6ea0SThomas Gleixner } 9996ae6ea0SThomas Gleixner } 100