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" 1996ae6ea0SThomas Gleixner #include "bitops.h" 2096ae6ea0SThomas Gleixner #include <asm/cpufeature.h> 2196ae6ea0SThomas Gleixner 22f0be6c6aSH. Peter Anvin #include "cpustr.h" 23f0be6c6aSH. Peter Anvin 2496ae6ea0SThomas Gleixner static char *cpu_name(int level) 2596ae6ea0SThomas Gleixner { 2696ae6ea0SThomas Gleixner static char buf[6]; 2796ae6ea0SThomas Gleixner 2896ae6ea0SThomas Gleixner if (level == 64) { 2996ae6ea0SThomas Gleixner return "x86-64"; 3096ae6ea0SThomas Gleixner } else { 3196ae6ea0SThomas Gleixner sprintf(buf, "i%d86", level); 3296ae6ea0SThomas Gleixner return buf; 3396ae6ea0SThomas Gleixner } 3496ae6ea0SThomas Gleixner } 3596ae6ea0SThomas Gleixner 3696ae6ea0SThomas Gleixner int validate_cpu(void) 3796ae6ea0SThomas Gleixner { 3896ae6ea0SThomas Gleixner u32 *err_flags; 3996ae6ea0SThomas Gleixner int cpu_level, req_level; 40f0be6c6aSH. Peter Anvin const unsigned char *msg_strs; 4196ae6ea0SThomas Gleixner 4296ae6ea0SThomas Gleixner check_cpu(&cpu_level, &req_level, &err_flags); 4396ae6ea0SThomas Gleixner 4496ae6ea0SThomas Gleixner if (cpu_level < req_level) { 4596ae6ea0SThomas Gleixner printf("This kernel requires an %s CPU, ", 4696ae6ea0SThomas Gleixner cpu_name(req_level)); 4796ae6ea0SThomas Gleixner printf("but only detected an %s CPU.\n", 4896ae6ea0SThomas Gleixner cpu_name(cpu_level)); 4996ae6ea0SThomas Gleixner return -1; 5096ae6ea0SThomas Gleixner } 5196ae6ea0SThomas Gleixner 5296ae6ea0SThomas Gleixner if (err_flags) { 5396ae6ea0SThomas Gleixner int i, j; 5496ae6ea0SThomas Gleixner puts("This kernel requires the following features " 5596ae6ea0SThomas Gleixner "not present on the CPU:\n"); 5696ae6ea0SThomas Gleixner 57f0be6c6aSH. Peter Anvin msg_strs = (const unsigned char *)x86_cap_strs; 58f0be6c6aSH. Peter Anvin 5996ae6ea0SThomas Gleixner for (i = 0; i < NCAPINTS; i++) { 6096ae6ea0SThomas Gleixner u32 e = err_flags[i]; 6196ae6ea0SThomas Gleixner 6296ae6ea0SThomas Gleixner for (j = 0; j < 32; j++) { 63f0be6c6aSH. Peter Anvin int n = (i << 5)+j; 64f0be6c6aSH. Peter Anvin if (*msg_strs < n) { 65f0be6c6aSH. Peter Anvin /* Skip to the next string */ 66f0be6c6aSH. Peter Anvin do { 67f0be6c6aSH. Peter Anvin msg_strs++; 68f0be6c6aSH. Peter Anvin } while (*msg_strs); 69f0be6c6aSH. Peter Anvin msg_strs++; 70f0be6c6aSH. Peter Anvin } 71f0be6c6aSH. Peter Anvin if (e & 1) { 72f0be6c6aSH. Peter Anvin if (*msg_strs == n && msg_strs[1]) 73f0be6c6aSH. Peter Anvin printf("%s ", msg_strs+1); 74f0be6c6aSH. Peter Anvin else 7596ae6ea0SThomas Gleixner printf("%d:%d ", i, j); 76f0be6c6aSH. Peter Anvin } 7796ae6ea0SThomas Gleixner e >>= 1; 7896ae6ea0SThomas Gleixner } 7996ae6ea0SThomas Gleixner } 8096ae6ea0SThomas Gleixner putchar('\n'); 8196ae6ea0SThomas Gleixner return -1; 8296ae6ea0SThomas Gleixner } else { 8396ae6ea0SThomas Gleixner return 0; 8496ae6ea0SThomas Gleixner } 8596ae6ea0SThomas Gleixner } 86