Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86: Support compiling out human-friendly processor feature names

The table mapping CPUID bits to human-readable strings takes up a
non-trivial amount of space, and only exists to support /proc/cpuinfo
and a couple of kernel messages. Since programs depend on the format of
/proc/cpuinfo, force inclusion of the table when building with /proc
support; otherwise, support omitting that table to save space, in which
case the kernel messages will print features numerically instead.

In addition to saving 1408 bytes out of vmlinux, this also saves 1373
bytes out of the uncompressed setup code, which contributes directly to
the size of bzImage.

Signed-off-by: Josh Triplett <josh@joshtriplett.org>

+71 -32
+12
arch/x86/Kconfig
··· 136 136 select HAVE_ACPI_APEI if ACPI 137 137 select HAVE_ACPI_APEI_NMI if ACPI 138 138 select ACPI_LEGACY_TABLES_LOOKUP if ACPI 139 + select X86_FEATURE_NAMES if PROC_FS 139 140 140 141 config INSTRUCTION_DECODER 141 142 def_bool y ··· 313 312 <http://www.tldp.org/docs.html#howto>. 314 313 315 314 If you don't know what to do here, say N. 315 + 316 + config X86_FEATURE_NAMES 317 + bool "Processor feature human-readable names" if EMBEDDED 318 + default y 319 + ---help--- 320 + This option compiles in a table of x86 feature bits and corresponding 321 + names. This is required to support /proc/cpuinfo and a few kernel 322 + messages. You can disable this to save space, at the expense of 323 + making those few kernel messages show numeric feature bits instead. 324 + 325 + If in doubt, say Y. 316 326 317 327 config X86_X2APIC 318 328 bool "Support x2apic"
+5 -2
arch/x86/boot/Makefile
··· 35 35 setup-y += video-bios.o 36 36 37 37 targets += $(setup-y) 38 - hostprogs-y := mkcpustr tools/build 38 + hostprogs-y := tools/build 39 + hostprogs-$(CONFIG_X86_FEATURE_NAMES) += mkcpustr 39 40 40 41 HOST_EXTRACFLAGS += -I$(srctree)/tools/include \ 41 42 -include include/generated/autoconf.h \ 42 43 -D__EXPORTED_HEADERS__ 43 44 45 + ifdef CONFIG_X86_FEATURE_NAMES 44 46 $(obj)/cpu.o: $(obj)/cpustr.h 45 47 46 48 quiet_cmd_cpustr = CPUSTR $@ 47 49 cmd_cpustr = $(obj)/mkcpustr > $@ 48 - targets += cpustr.h 50 + targets += cpustr.h 49 51 $(obj)/cpustr.h: $(obj)/mkcpustr FORCE 50 52 $(call if_changed,cpustr) 53 + endif 51 54 52 55 # --------------------------------------------------------------------------- 53 56
+41 -27
arch/x86/boot/cpu.c
··· 16 16 */ 17 17 18 18 #include "boot.h" 19 + #ifdef CONFIG_X86_FEATURE_NAMES 19 20 #include "cpustr.h" 21 + #endif 20 22 21 23 static char *cpu_name(int level) 22 24 { ··· 34 32 } 35 33 } 36 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 + 37 73 int validate_cpu(void) 38 74 { 39 75 u32 *err_flags; 40 76 int cpu_level, req_level; 41 - const unsigned char *msg_strs; 42 77 43 78 check_cpu(&cpu_level, &req_level, &err_flags); 44 79 ··· 88 49 } 89 50 90 51 if (err_flags) { 91 - int i, j; 92 52 puts("This kernel requires the following features " 93 53 "not present on the CPU:\n"); 94 - 95 - msg_strs = (const unsigned char *)x86_cap_strs; 96 - 97 - for (i = 0; i < NCAPINTS; i++) { 98 - u32 e = err_flags[i]; 99 - 100 - for (j = 0; j < 32; j++) { 101 - if (msg_strs[0] < i || 102 - (msg_strs[0] == i && msg_strs[1] < j)) { 103 - /* Skip to the next string */ 104 - msg_strs += 2; 105 - while (*msg_strs++) 106 - ; 107 - } 108 - if (e & 1) { 109 - if (msg_strs[0] == i && 110 - msg_strs[1] == j && 111 - msg_strs[2]) 112 - printf("%s ", msg_strs+2); 113 - else 114 - printf("%d:%d ", i, j); 115 - } 116 - e >>= 1; 117 - } 118 - } 54 + show_cap_strs(err_flags); 119 55 putchar('\n'); 120 56 return -1; 121 57 } else {
+7
arch/x86/include/asm/cpufeature.h
··· 250 250 #include <asm/asm.h> 251 251 #include <linux/bitops.h> 252 252 253 + #ifdef CONFIG_X86_FEATURE_NAMES 253 254 extern const char * const x86_cap_flags[NCAPINTS*32]; 254 255 extern const char * const x86_power_flags[32]; 256 + #define X86_CAP_FMT "%s" 257 + #define x86_cap_flag(flag) x86_cap_flags[flag] 258 + #else 259 + #define X86_CAP_FMT "%d:%d" 260 + #define x86_cap_flag(flag) ((flag) >> 5), ((flag) & 31) 261 + #endif 255 262 256 263 /* 257 264 * In order to save room, we index into this array by doing
+4 -1
arch/x86/kernel/cpu/Makefile
··· 13 13 CFLAGS_common.o := $(nostackp) 14 14 15 15 obj-y := intel_cacheinfo.o scattered.o topology.o 16 - obj-y += capflags.o powerflags.o common.o 16 + obj-y += common.o 17 17 obj-y += rdrand.o 18 18 obj-y += match.o 19 19 20 20 obj-$(CONFIG_PROC_FS) += proc.o 21 + obj-$(CONFIG_X86_FEATURE_NAMES) += capflags.o powerflags.o 21 22 22 23 obj-$(CONFIG_X86_32) += bugs.o 23 24 obj-$(CONFIG_X86_64) += bugs_64.o ··· 51 50 52 51 obj-$(CONFIG_HYPERVISOR_GUEST) += vmware.o hypervisor.o mshyperv.o 53 52 53 + ifdef CONFIG_X86_FEATURE_NAMES 54 54 quiet_cmd_mkcapflags = MKCAP $@ 55 55 cmd_mkcapflags = $(CONFIG_SHELL) $(srctree)/$(src)/mkcapflags.sh $< $@ 56 56 ··· 60 58 targets += capflags.c 61 59 $(obj)/capflags.c: $(cpufeature) $(src)/mkcapflags.sh FORCE 62 60 $(call if_changed,mkcapflags) 61 + endif
+2 -2
arch/x86/kernel/cpu/common.c
··· 346 346 continue; 347 347 348 348 printk(KERN_WARNING 349 - "CPU: CPU feature %s disabled, no CPUID level 0x%x\n", 350 - x86_cap_flags[df->feature], df->level); 349 + "CPU: CPU feature " X86_CAP_FMT " disabled, no CPUID level 0x%x\n", 350 + x86_cap_flag(df->feature), df->level); 351 351 } 352 352 } 353 353