setup_64.c 31.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 *  Copyright (C) 1995  Linus Torvalds
 */

/*
 * This file handles the architecture-dependent parts of initialization
 */

#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
#include <linux/a.out.h>
19
#include <linux/screen_info.h>
L
Linus Torvalds 已提交
20 21 22 23 24 25 26 27 28 29
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/initrd.h>
#include <linux/highmem.h>
#include <linux/bootmem.h>
#include <linux/module.h>
#include <asm/processor.h>
#include <linux/console.h>
#include <linux/seq_file.h>
30
#include <linux/crash_dump.h>
L
Linus Torvalds 已提交
31 32 33 34 35
#include <linux/root_dev.h>
#include <linux/pci.h>
#include <linux/acpi.h>
#include <linux/kallsyms.h>
#include <linux/edd.h>
36
#include <linux/mmzone.h>
37
#include <linux/kexec.h>
38
#include <linux/cpufreq.h>
39
#include <linux/dmi.h>
40
#include <linux/dma-mapping.h>
41
#include <linux/ctype.h>
42
#include <linux/uaccess.h>
43

L
Linus Torvalds 已提交
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
#include <asm/mtrr.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/smp.h>
#include <asm/msr.h>
#include <asm/desc.h>
#include <video/edid.h>
#include <asm/e820.h>
#include <asm/dma.h>
#include <asm/mpspec.h>
#include <asm/mmu_context.h>
#include <asm/proto.h>
#include <asm/setup.h>
#include <asm/mach_apic.h>
#include <asm/numa.h>
60
#include <asm/sections.h>
61
#include <asm/dmi.h>
B
Bernhard Walle 已提交
62
#include <asm/cacheflush.h>
63
#include <asm/mce.h>
64
#include <asm/ds.h>
L
Linus Torvalds 已提交
65

66 67 68 69 70 71
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#else
#define ARCH_SETUP
#endif

L
Linus Torvalds 已提交
72 73 74 75
/*
 * Machine setup..
 */

76
struct cpuinfo_x86 boot_cpu_data __read_mostly;
77
EXPORT_SYMBOL(boot_cpu_data);
L
Linus Torvalds 已提交
78 79 80 81 82 83 84 85

unsigned long mmu_cr4_features;

/* Boot loader ID as an integer, for the benefit of proc_dointvec */
int bootloader_type;

unsigned long saved_video_mode;

86 87
int force_mwait __cpuinitdata;

T
Thomas Gleixner 已提交
88
/*
89 90 91 92 93
 * Early DMI memory
 */
int dmi_alloc_index;
char dmi_alloc_data[DMI_MAX_DATA];

L
Linus Torvalds 已提交
94 95 96 97
/*
 * Setup options
 */
struct screen_info screen_info;
98
EXPORT_SYMBOL(screen_info);
L
Linus Torvalds 已提交
99 100 101 102 103 104
struct sys_desc_table_struct {
	unsigned short length;
	unsigned char table[0];
};

struct edid_info edid_info;
105
EXPORT_SYMBOL_GPL(edid_info);
L
Linus Torvalds 已提交
106 107 108

extern int root_mountflags;

109
char __initdata command_line[COMMAND_LINE_SIZE];
L
Linus Torvalds 已提交
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133

struct resource standard_io_resources[] = {
	{ .name = "dma1", .start = 0x00, .end = 0x1f,
		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
	{ .name = "pic1", .start = 0x20, .end = 0x21,
		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
	{ .name = "timer0", .start = 0x40, .end = 0x43,
		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
	{ .name = "timer1", .start = 0x50, .end = 0x53,
		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
	{ .name = "keyboard", .start = 0x60, .end = 0x6f,
		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
	{ .name = "dma page reg", .start = 0x80, .end = 0x8f,
		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
	{ .name = "pic2", .start = 0xa0, .end = 0xa1,
		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
	{ .name = "dma2", .start = 0xc0, .end = 0xdf,
		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
	{ .name = "fpu", .start = 0xf0, .end = 0xff,
		.flags = IORESOURCE_BUSY | IORESOURCE_IO }
};

#define IORESOURCE_RAM (IORESOURCE_BUSY | IORESOURCE_MEM)

134
static struct resource data_resource = {
L
Linus Torvalds 已提交
135 136 137 138 139
	.name = "Kernel data",
	.start = 0,
	.end = 0,
	.flags = IORESOURCE_RAM,
};
140
static struct resource code_resource = {
L
Linus Torvalds 已提交
141 142 143 144 145
	.name = "Kernel code",
	.start = 0,
	.end = 0,
	.flags = IORESOURCE_RAM,
};
146
static struct resource bss_resource = {
B
Bernhard Walle 已提交
147 148 149 150 151
	.name = "Kernel bss",
	.start = 0,
	.end = 0,
	.flags = IORESOURCE_RAM,
};
L
Linus Torvalds 已提交
152

153 154
static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c);

155 156 157 158 159 160
#ifdef CONFIG_PROC_VMCORE
/* elfcorehdr= specifies the location of elf core header
 * stored by the crashed kernel. This option will be passed
 * by kexec loader to the capture kernel.
 */
static int __init setup_elfcorehdr(char *arg)
161
{
162 163 164 165 166
	char *end;
	if (!arg)
		return -EINVAL;
	elfcorehdr_addr = memparse(arg, &end);
	return end > arg ? 0 : -EINVAL;
167
}
168
early_param("elfcorehdr", setup_elfcorehdr);
169 170
#endif

171
#ifndef CONFIG_NUMA
172 173
static void __init
contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
L
Linus Torvalds 已提交
174
{
175 176 177 178 179
	unsigned long bootmap_size, bootmap;

	bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
	bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size);
	if (bootmap == -1L)
T
Thomas Gleixner 已提交
180
		panic("Cannot find bootmem map of size %ld\n", bootmap_size);
181
	bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
182 183
	e820_register_active_regions(0, start_pfn, end_pfn);
	free_bootmem_with_active_regions(0, end_pfn);
184
	reserve_bootmem(bootmap, bootmap_size);
T
Thomas Gleixner 已提交
185
}
L
Linus Torvalds 已提交
186 187 188 189 190 191 192 193 194 195 196 197 198 199
#endif

#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
struct edd edd;
#ifdef CONFIG_EDD_MODULE
EXPORT_SYMBOL(edd);
#endif
/**
 * copy_edd() - Copy the BIOS EDD information
 *              from boot_params into a safe place.
 *
 */
static inline void copy_edd(void)
{
200 201 202 203 204
     memcpy(edd.mbr_signature, boot_params.edd_mbr_sig_buffer,
	    sizeof(edd.mbr_signature));
     memcpy(edd.edd_info, boot_params.eddbuf, sizeof(edd.edd_info));
     edd.mbr_signature_nr = boot_params.edd_mbr_sig_buf_entries;
     edd.edd_info_nr = boot_params.eddbuf_entries;
L
Linus Torvalds 已提交
205 206 207 208 209 210 211
}
#else
static inline void copy_edd(void)
{
}
#endif

212 213 214 215 216 217 218
#ifdef CONFIG_KEXEC
static void __init reserve_crashkernel(void)
{
	unsigned long long free_mem;
	unsigned long long crash_size, crash_base;
	int ret;

T
Thomas Gleixner 已提交
219 220
	free_mem =
		((unsigned long long)max_low_pfn - min_low_pfn) << PAGE_SHIFT;
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243

	ret = parse_crashkernel(boot_command_line, free_mem,
			&crash_size, &crash_base);
	if (ret == 0 && crash_size) {
		if (crash_base > 0) {
			printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
					"for crashkernel (System RAM: %ldMB)\n",
					(unsigned long)(crash_size >> 20),
					(unsigned long)(crash_base >> 20),
					(unsigned long)(free_mem >> 20));
			crashk_res.start = crash_base;
			crashk_res.end   = crash_base + crash_size - 1;
			reserve_bootmem(crash_base, crash_size);
		} else
			printk(KERN_INFO "crashkernel reservation failed - "
					"you have to specify a base address\n");
	}
}
#else
static inline void __init reserve_crashkernel(void)
{}
#endif

L
Linus Torvalds 已提交
244
#define EBDA_ADDR_POINTER 0x40E
245 246 247 248 249

unsigned __initdata ebda_addr;
unsigned __initdata ebda_size;

static void discover_ebda(void)
L
Linus Torvalds 已提交
250
{
251
	/*
T
Thomas Gleixner 已提交
252
	 * there is a real-mode segmented pointer pointing to the
L
Linus Torvalds 已提交
253 254
	 * 4K EBDA area at 0x40E
	 */
255
	ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER);
256 257 258 259 260 261 262 263 264 265
	/*
	 * There can be some situations, like paravirtualized guests,
	 * in which there is no available ebda information. In such
	 * case, just skip it
	 */
	if (!ebda_addr) {
		ebda_size = 0;
		return;
	}

266 267
	ebda_addr <<= 4;

268
	ebda_size = *(unsigned short *)__va(ebda_addr);
269 270 271 272 273 274 275 276

	/* Round EBDA up to pages */
	if (ebda_size == 0)
		ebda_size = 1;
	ebda_size <<= 10;
	ebda_size = round_up(ebda_size + (ebda_addr & ~PAGE_MASK), PAGE_SIZE);
	if (ebda_size > 64*1024)
		ebda_size = 64*1024;
L
Linus Torvalds 已提交
277 278
}

279 280 281 282 283 284
/* Overridden in paravirt.c if CONFIG_PARAVIRT */
void __attribute__((weak)) memory_setup(void)
{
       machine_specific_memory_setup();
}

L
Linus Torvalds 已提交
285 286
void __init setup_arch(char **cmdline_p)
{
T
Thomas Gleixner 已提交
287 288
	unsigned i;

289
	printk(KERN_INFO "Command line: %s\n", boot_command_line);
290

291 292 293 294 295
	ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev);
	screen_info = boot_params.screen_info;
	edid_info = boot_params.edid_info;
	saved_video_mode = boot_params.hdr.vid_mode;
	bootloader_type = boot_params.hdr.type_of_loader;
L
Linus Torvalds 已提交
296 297

#ifdef CONFIG_BLK_DEV_RAM
298 299 300
	rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK;
	rd_prompt = ((boot_params.hdr.ram_size & RAMDISK_PROMPT_FLAG) != 0);
	rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0);
L
Linus Torvalds 已提交
301
#endif
302 303 304 305

	ARCH_SETUP

	memory_setup();
L
Linus Torvalds 已提交
306 307
	copy_edd();

308
	if (!boot_params.hdr.root_flags)
L
Linus Torvalds 已提交
309 310 311 312 313 314
		root_mountflags &= ~MS_RDONLY;
	init_mm.start_code = (unsigned long) &_text;
	init_mm.end_code = (unsigned long) &_etext;
	init_mm.end_data = (unsigned long) &_edata;
	init_mm.brk = (unsigned long) &_end;

315 316 317 318
	code_resource.start = virt_to_phys(&_text);
	code_resource.end = virt_to_phys(&_etext)-1;
	data_resource.start = virt_to_phys(&_etext);
	data_resource.end = virt_to_phys(&_edata)-1;
B
Bernhard Walle 已提交
319 320
	bss_resource.start = virt_to_phys(&__bss_start);
	bss_resource.end = virt_to_phys(&__bss_stop)-1;
L
Linus Torvalds 已提交
321 322 323

	early_identify_cpu(&boot_cpu_data);

324
	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
325 326 327 328 329
	*cmdline_p = command_line;

	parse_early_param();

	finish_e820_parsing();
330

331
	e820_register_active_regions(0, 0, -1UL);
L
Linus Torvalds 已提交
332 333 334 335 336
	/*
	 * partially used pages are not usable - thus
	 * we are rounding upwards:
	 */
	end_pfn = e820_end_of_ram();
337
	num_physpages = end_pfn;
L
Linus Torvalds 已提交
338 339 340

	check_efer();

341 342
	discover_ebda();

L
Linus Torvalds 已提交
343 344
	init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));

345 346
	dmi_scan_machine();

347 348
	io_delay_init();

349 350 351 352 353
#ifdef CONFIG_SMP
	/* setup to use the static apicid table during kernel startup */
	x86_cpu_to_apicid_ptr = (void *)&x86_cpu_to_apicid_init;
#endif

L
Len Brown 已提交
354
#ifdef CONFIG_ACPI
L
Linus Torvalds 已提交
355 356 357 358 359 360 361
	/*
	 * Initialize the ACPI boot-time table parser (gets the RSDP and SDT).
	 * Call this early for SRAT node setup.
	 */
	acpi_boot_table_init();
#endif

362 363 364 365 366
	/* How many end-of-memory variables you have, grandma! */
	max_low_pfn = end_pfn;
	max_pfn = end_pfn;
	high_memory = (void *)__va(end_pfn * PAGE_SIZE - 1) + 1;

367 368 369
	/* Remove active ranges so rediscovery with NUMA-awareness happens */
	remove_all_active_ranges();

L
Linus Torvalds 已提交
370 371 372 373 374 375 376
#ifdef CONFIG_ACPI_NUMA
	/*
	 * Parse SRAT to discover nodes.
	 */
	acpi_numa_init();
#endif

377
#ifdef CONFIG_NUMA
T
Thomas Gleixner 已提交
378
	numa_initmem_init(0, end_pfn);
L
Linus Torvalds 已提交
379
#else
380
	contig_initmem_init(0, end_pfn);
L
Linus Torvalds 已提交
381 382 383
#endif

	/* Reserve direct mapping */
T
Thomas Gleixner 已提交
384
	reserve_bootmem_generic(table_start << PAGE_SHIFT,
L
Linus Torvalds 已提交
385 386 387
				(table_end - table_start) << PAGE_SHIFT);

	/* reserve kernel */
388 389
	reserve_bootmem_generic(__pa_symbol(&_text),
				__pa_symbol(&_end) - __pa_symbol(&_text));
L
Linus Torvalds 已提交
390 391 392 393 394 395 396 397

	/*
	 * reserve physical page 0 - it's a special BIOS page on many boxes,
	 * enabling clean reboots, SMP operation, laptop functions.
	 */
	reserve_bootmem_generic(0, PAGE_SIZE);

	/* reserve ebda region */
398 399
	if (ebda_addr)
		reserve_bootmem_generic(ebda_addr, ebda_size);
400 401 402 403 404
#ifdef CONFIG_NUMA
	/* reserve nodemap region */
	if (nodemap_addr)
		reserve_bootmem_generic(nodemap_addr, nodemap_size);
#endif
L
Linus Torvalds 已提交
405 406 407

#ifdef CONFIG_SMP
	/* Reserve SMP trampoline */
408
	reserve_bootmem_generic(SMP_TRAMPOLINE_BASE, 2*PAGE_SIZE);
L
Linus Torvalds 已提交
409 410
#endif

L
Len Brown 已提交
411
#ifdef CONFIG_ACPI_SLEEP
L
Linus Torvalds 已提交
412
	/*
T
Thomas Gleixner 已提交
413
	 * Reserve low memory region for sleep support.
L
Linus Torvalds 已提交
414
	 */
T
Thomas Gleixner 已提交
415 416 417 418 419
       acpi_reserve_bootmem();
#endif
       /*
	* Find and reserve possible boot-time SMP configuration:
	*/
L
Linus Torvalds 已提交
420 421
	find_smp_config();
#ifdef CONFIG_BLK_DEV_INITRD
422 423 424 425 426 427 428 429 430 431 432
	if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
		unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
		unsigned long ramdisk_size  = boot_params.hdr.ramdisk_size;
		unsigned long ramdisk_end   = ramdisk_image + ramdisk_size;
		unsigned long end_of_mem    = end_pfn << PAGE_SHIFT;

		if (ramdisk_end <= end_of_mem) {
			reserve_bootmem_generic(ramdisk_image, ramdisk_size);
			initrd_start = ramdisk_image + PAGE_OFFSET;
			initrd_end = initrd_start+ramdisk_size;
		} else {
L
Linus Torvalds 已提交
433
			printk(KERN_ERR "initrd extends beyond end of memory "
434 435
			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
			       ramdisk_end, end_of_mem);
L
Linus Torvalds 已提交
436 437 438 439
			initrd_start = 0;
		}
	}
#endif
440
	reserve_crashkernel();
L
Linus Torvalds 已提交
441 442
	paging_init();

443
	early_quirks();
L
Linus Torvalds 已提交
444

445 446 447 448 449 450
	/*
	 * set this early, so we dont allocate cpu0
	 * if MADT list doesnt list BSP first
	 * mpparse.c/MP_processor_info() allocates logical cpu numbers.
	 */
	cpu_set(0, cpu_present_map);
L
Len Brown 已提交
451
#ifdef CONFIG_ACPI
L
Linus Torvalds 已提交
452 453 454 455 456 457
	/*
	 * Read APIC and some other early information from ACPI tables.
	 */
	acpi_boot_init();
#endif

458 459
	init_cpu_to_node();

L
Linus Torvalds 已提交
460 461 462 463 464 465
	/*
	 * get boot-time SMP configuration:
	 */
	if (smp_found_config)
		get_smp_config();
	init_apic_mappings();
466
	ioapic_init_mappings();
L
Linus Torvalds 已提交
467 468

	/*
A
Andi Kleen 已提交
469
	 * We trust e820 completely. No explicit ROM probing in memory.
T
Thomas Gleixner 已提交
470
	 */
471
	e820_reserve_resources(&code_resource, &data_resource, &bss_resource);
472
	e820_mark_nosave_regions();
L
Linus Torvalds 已提交
473 474

	/* request I/O space for devices used on all i[345]86 PCs */
A
Andi Kleen 已提交
475
	for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
L
Linus Torvalds 已提交
476 477
		request_resource(&ioport_resource, &standard_io_resources[i]);

478
	e820_setup_gap();
L
Linus Torvalds 已提交
479 480 481 482 483 484 485 486 487 488

#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
	conswitchp = &vga_con;
#elif defined(CONFIG_DUMMY_CONSOLE)
	conswitchp = &dummy_con;
#endif
#endif
}

489
static int __cpuinit get_model_name(struct cpuinfo_x86 *c)
L
Linus Torvalds 已提交
490 491 492
{
	unsigned int *v;

493
	if (c->extended_cpuid_level < 0x80000004)
L
Linus Torvalds 已提交
494 495 496 497 498 499 500 501 502 503 504
		return 0;

	v = (unsigned int *) c->x86_model_id;
	cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
	cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
	cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
	c->x86_model_id[48] = 0;
	return 1;
}


505
static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
L
Linus Torvalds 已提交
506 507 508
{
	unsigned int n, dummy, eax, ebx, ecx, edx;

509
	n = c->extended_cpuid_level;
L
Linus Torvalds 已提交
510 511 512

	if (n >= 0x80000005) {
		cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);
T
Thomas Gleixner 已提交
513 514 515 516
		printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), "
		       "D cache %dK (%d bytes/line)\n",
		       edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
		c->x86_cache_size = (ecx>>24) + (edx>>24);
L
Linus Torvalds 已提交
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
		/* On K8 L1 TLB is inclusive, so don't count it */
		c->x86_tlbsize = 0;
	}

	if (n >= 0x80000006) {
		cpuid(0x80000006, &dummy, &ebx, &ecx, &edx);
		ecx = cpuid_ecx(0x80000006);
		c->x86_cache_size = ecx >> 16;
		c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff);

		printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
		c->x86_cache_size, ecx & 0xFF);
	}

	if (n >= 0x80000007)
T
Thomas Gleixner 已提交
532
		cpuid(0x80000007, &dummy, &dummy, &dummy, &c->x86_power);
L
Linus Torvalds 已提交
533
	if (n >= 0x80000008) {
T
Thomas Gleixner 已提交
534
		cpuid(0x80000008, &eax, &dummy, &dummy, &dummy);
L
Linus Torvalds 已提交
535 536 537 538 539
		c->x86_virt_bits = (eax >> 8) & 0xff;
		c->x86_phys_bits = eax & 0xff;
	}
}

540 541 542
#ifdef CONFIG_NUMA
static int nearby_node(int apicid)
{
T
Thomas Gleixner 已提交
543 544
	int i, node;

545
	for (i = apicid - 1; i >= 0; i--) {
T
Thomas Gleixner 已提交
546
		node = apicid_to_node[i];
547 548 549 550
		if (node != NUMA_NO_NODE && node_online(node))
			return node;
	}
	for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
T
Thomas Gleixner 已提交
551
		node = apicid_to_node[i];
552 553 554 555 556 557 558
		if (node != NUMA_NO_NODE && node_online(node))
			return node;
	}
	return first_node(node_online_map); /* Shouldn't happen */
}
#endif

559 560 561 562 563 564 565
/*
 * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
 * Assumes number of cores is a power of two.
 */
static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
566
	unsigned bits;
567
#ifdef CONFIG_NUMA
568
	int cpu = smp_processor_id();
569
	int node = 0;
570
	unsigned apicid = hard_smp_processor_id();
571
#endif
572
	bits = c->x86_coreid_bits;
573 574

	/* Low order bits define the core id (index of core in socket) */
575
	c->cpu_core_id = c->phys_proc_id & ((1 << bits)-1);
576
	/* Convert the APIC ID into the socket ID */
577
	c->phys_proc_id = phys_pkg_id(bits);
578 579

#ifdef CONFIG_NUMA
T
Thomas Gleixner 已提交
580 581 582 583 584 585 586 587 588 589 590 591 592 593
	node = c->phys_proc_id;
	if (apicid_to_node[apicid] != NUMA_NO_NODE)
		node = apicid_to_node[apicid];
	if (!node_online(node)) {
		/* Two possibilities here:
		   - The CPU is missing memory and no node was created.
		   In that case try picking one from a nearby CPU
		   - The APIC IDs differ from the HyperTransport node IDs
		   which the K8 northbridge parsing fills in.
		   Assume they are all increased by a constant offset,
		   but in the same order as the HT nodeids.
		   If that doesn't result in a usable node fall back to the
		   path for the previous case.  */

594
		int ht_nodeid = apicid - (cpu_data(0).phys_proc_id << bits);
T
Thomas Gleixner 已提交
595 596 597 598 599 600 601 602

		if (ht_nodeid >= 0 &&
		    apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
			node = apicid_to_node[ht_nodeid];
		/* Pick a nearby node */
		if (!node_online(node))
			node = nearby_node(apicid);
	}
603
	numa_set_node(cpu, node);
604

605
	printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
606 607 608
#endif
#endif
}
L
Linus Torvalds 已提交
609

610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
	unsigned bits, ecx;

	/* Multi core CPU? */
	if (c->extended_cpuid_level < 0x80000008)
		return;

	ecx = cpuid_ecx(0x80000008);

	c->x86_max_cores = (ecx & 0xff) + 1;

	/* CPU telling us the core id bits shift? */
	bits = (ecx >> 12) & 0xF;

	/* Otherwise recompute */
	if (bits == 0) {
		while ((1 << bits) < c->x86_max_cores)
			bits++;
	}

	c->x86_coreid_bits = bits;

#endif
}

637 638 639 640 641 642 643 644 645 646 647 648
#define ENABLE_C1E_MASK		0x18000000
#define CPUID_PROCESSOR_SIGNATURE	1
#define CPUID_XFAM		0x0ff00000
#define CPUID_XFAM_K8		0x00000000
#define CPUID_XFAM_10H		0x00100000
#define CPUID_XFAM_11H		0x00200000
#define CPUID_XMOD		0x000f0000
#define CPUID_XMOD_REV_F	0x00040000

/* AMD systems with C1E don't have a working lAPIC timer. Check for that. */
static __cpuinit int amd_apic_timer_broken(void)
{
T
Thomas Gleixner 已提交
649 650
	u32 lo, hi, eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);

651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667
	switch (eax & CPUID_XFAM) {
	case CPUID_XFAM_K8:
		if ((eax & CPUID_XMOD) < CPUID_XMOD_REV_F)
			break;
	case CPUID_XFAM_10H:
	case CPUID_XFAM_11H:
		rdmsr(MSR_K8_ENABLE_C1E, lo, hi);
		if (lo & ENABLE_C1E_MASK)
			return 1;
		break;
	default:
		/* err on the side of caution */
		return 1;
	}
	return 0;
}

668
static void __cpuinit init_amd(struct cpuinfo_x86 *c)
L
Linus Torvalds 已提交
669
{
670
	unsigned level;
L
Linus Torvalds 已提交
671

672 673 674
#ifdef CONFIG_SMP
	unsigned long value;

675 676 677
	/*
	 * Disable TLB flush filter by setting HWCR.FFDIS on K8
	 * bit 6 of msr C001_0015
T
Thomas Gleixner 已提交
678
	 *
679 680 681 682 683 684 685 686
	 * Errata 63 for SH-B3 steppings
	 * Errata 122 for all steppings (F+ have it disabled by default)
	 */
	if (c->x86 == 15) {
		rdmsrl(MSR_K8_HWCR, value);
		value |= 1 << 6;
		wrmsrl(MSR_K8_HWCR, value);
	}
687 688
#endif

L
Linus Torvalds 已提交
689 690
	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
691
	clear_bit(0*32+31, (unsigned long *)&c->x86_capability);
T
Thomas Gleixner 已提交
692

693 694
	/* On C+ stepping K8 rep microcode works well for copy/memset */
	level = cpuid_eax(1);
T
Thomas Gleixner 已提交
695 696
	if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) ||
			     level >= 0x0f58))
697
		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
698
	if (c->x86 == 0x10 || c->x86 == 0x11)
699
		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
700

701 702
	/* Enable workaround for FXSAVE leak */
	if (c->x86 >= 6)
703
		set_cpu_cap(c, X86_FEATURE_FXSAVE_LEAK);
704

705 706
	level = get_model_name(c);
	if (!level) {
T
Thomas Gleixner 已提交
707
		switch (c->x86) {
L
Linus Torvalds 已提交
708 709 710 711
		case 15:
			/* Should distinguish Models here, but this is only
			   a fallback anyways. */
			strcpy(c->x86_model_id, "Hammer");
T
Thomas Gleixner 已提交
712 713 714
			break;
		}
	}
L
Linus Torvalds 已提交
715 716
	display_cacheinfo(c);

717 718
	/* c->x86_power is 8000_0007 edx. Bit 8 is constant TSC */
	if (c->x86_power & (1<<8))
719
		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
720

721 722
	/* Multi core CPU? */
	if (c->extended_cpuid_level >= 0x80000008)
723
		amd_detect_cmp(c);
L
Linus Torvalds 已提交
724

725 726 727 728 729
	if (c->extended_cpuid_level >= 0x80000006 &&
		(cpuid_edx(0x80000006) & 0xf000))
		num_cache_leaves = 4;
	else
		num_cache_leaves = 3;
730

731
	if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x11)
732
		set_cpu_cap(c, X86_FEATURE_K8);
733

734
	/* RDTSC can be speculated around */
735
	clear_cpu_cap(c, X86_FEATURE_SYNC_RDTSC);
736 737 738

	/* Family 10 doesn't support C states in MWAIT so don't use it */
	if (c->x86 == 0x10 && !force_mwait)
739
		clear_cpu_cap(c, X86_FEATURE_MWAIT);
740 741 742

	if (amd_apic_timer_broken())
		disable_apic_timer = 1;
L
Linus Torvalds 已提交
743 744
}

745
static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
L
Linus Torvalds 已提交
746 747
{
#ifdef CONFIG_SMP
T
Thomas Gleixner 已提交
748 749
	u32 eax, ebx, ecx, edx;
	int index_msb, core_bits;
750 751 752 753

	cpuid(1, &eax, &ebx, &ecx, &edx);


754
	if (!cpu_has(c, X86_FEATURE_HT))
L
Linus Torvalds 已提交
755
		return;
T
Thomas Gleixner 已提交
756
	if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
757
		goto out;
L
Linus Torvalds 已提交
758 759

	smp_num_siblings = (ebx & 0xff0000) >> 16;
760

L
Linus Torvalds 已提交
761 762
	if (smp_num_siblings == 1) {
		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
T
Thomas Gleixner 已提交
763
	} else if (smp_num_siblings > 1) {
764

L
Linus Torvalds 已提交
765
		if (smp_num_siblings > NR_CPUS) {
T
Thomas Gleixner 已提交
766 767
			printk(KERN_WARNING "CPU: Unsupported number of "
			       "siblings %d", smp_num_siblings);
L
Linus Torvalds 已提交
768 769 770
			smp_num_siblings = 1;
			return;
		}
771 772

		index_msb = get_count_order(smp_num_siblings);
773
		c->phys_proc_id = phys_pkg_id(index_msb);
774

775
		smp_num_siblings = smp_num_siblings / c->x86_max_cores;
776

T
Thomas Gleixner 已提交
777
		index_msb = get_count_order(smp_num_siblings);
778 779

		core_bits = get_count_order(c->x86_max_cores);
780

781
		c->cpu_core_id = phys_pkg_id(index_msb) &
782
					       ((1 << core_bits) - 1);
L
Linus Torvalds 已提交
783
	}
784 785
out:
	if ((c->x86_max_cores * smp_num_siblings) > 1) {
T
Thomas Gleixner 已提交
786 787 788 789
		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
		       c->phys_proc_id);
		printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
		       c->cpu_core_id);
790 791
	}

L
Linus Torvalds 已提交
792 793 794
#endif
}

795 796 797
/*
 * find out the number of processor cores on the die
 */
798
static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c)
799
{
800
	unsigned int eax, t;
801 802 803 804

	if (c->cpuid_level < 4)
		return 1;

805
	cpuid_count(4, 0, &eax, &t, &t, &t);
806 807 808 809 810 811 812

	if (eax & 0x1f)
		return ((eax >> 26) + 1);
	else
		return 1;
}

813 814 815
static void srat_detect_node(void)
{
#ifdef CONFIG_NUMA
816
	unsigned node;
817
	int cpu = smp_processor_id();
818
	int apicid = hard_smp_processor_id();
819 820 821

	/* Don't do the funky fallback heuristics the AMD version employs
	   for now. */
822
	node = apicid_to_node[apicid];
823
	if (node == NUMA_NO_NODE)
824
		node = first_node(node_online_map);
825
	numa_set_node(cpu, node);
826

A
Andi Kleen 已提交
827
	printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
828 829 830
#endif
}

831
static void __cpuinit init_intel(struct cpuinfo_x86 *c)
L
Linus Torvalds 已提交
832 833 834 835 836
{
	/* Cache sizes */
	unsigned n;

	init_intel_cacheinfo(c);
T
Thomas Gleixner 已提交
837
	if (c->cpuid_level > 9) {
838 839 840
		unsigned eax = cpuid_eax(10);
		/* Check for version and the number of counters */
		if ((eax & 0xff) && (((eax>>8) & 0xff) > 1))
841
			set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON);
842 843
	}

844 845 846
	if (cpu_has_ds) {
		unsigned int l1, l2;
		rdmsr(MSR_IA32_MISC_ENABLE, l1, l2);
847
		if (!(l1 & (1<<11)))
848
			set_cpu_cap(c, X86_FEATURE_BTS);
849
		if (!(l1 & (1<<12)))
850
			set_cpu_cap(c, X86_FEATURE_PEBS);
851 852
	}

853 854 855 856

	if (cpu_has_bts)
		ds_init_intel(c);

857
	n = c->extended_cpuid_level;
L
Linus Torvalds 已提交
858 859 860 861
	if (n >= 0x80000008) {
		unsigned eax = cpuid_eax(0x80000008);
		c->x86_virt_bits = (eax >> 8) & 0xff;
		c->x86_phys_bits = eax & 0xff;
862 863 864 865 866
		/* CPUID workaround for Intel 0F34 CPU */
		if (c->x86_vendor == X86_VENDOR_INTEL &&
		    c->x86 == 0xF && c->x86_model == 0x3 &&
		    c->x86_mask == 0x4)
			c->x86_phys_bits = 36;
L
Linus Torvalds 已提交
867 868 869 870
	}

	if (c->x86 == 15)
		c->x86_cache_alignment = c->x86_clflush_size * 2;
871 872
	if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
	    (c->x86 == 0x6 && c->x86_model >= 0x0e))
873
		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
874
	if (c->x86 == 6)
875
		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
876
	if (c->x86 == 15)
877
		set_cpu_cap(c, X86_FEATURE_SYNC_RDTSC);
878
	else
879
		clear_cpu_cap(c, X86_FEATURE_SYNC_RDTSC);
T
Thomas Gleixner 已提交
880
	c->x86_max_cores = intel_num_cpu_cores(c);
881 882

	srat_detect_node();
L
Linus Torvalds 已提交
883 884
}

885
static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
L
Linus Torvalds 已提交
886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905
{
	char *v = c->x86_vendor_id;

	if (!strcmp(v, "AuthenticAMD"))
		c->x86_vendor = X86_VENDOR_AMD;
	else if (!strcmp(v, "GenuineIntel"))
		c->x86_vendor = X86_VENDOR_INTEL;
	else
		c->x86_vendor = X86_VENDOR_UNKNOWN;
}

struct cpu_model_info {
	int vendor;
	int family;
	char *model_names[16];
};

/* Do some early cpuid on the boot CPU to get some parameter that are
   needed before check_bugs. Everything advanced is in identify_cpu
   below. */
906
static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
L
Linus Torvalds 已提交
907
{
908
	u32 tfms, xlvl;
L
Linus Torvalds 已提交
909 910 911 912 913 914 915 916 917

	c->loops_per_jiffy = loops_per_jiffy;
	c->x86_cache_size = -1;
	c->x86_vendor = X86_VENDOR_UNKNOWN;
	c->x86_model = c->x86_mask = 0;	/* So far unknown... */
	c->x86_vendor_id[0] = '\0'; /* Unset */
	c->x86_model_id[0] = '\0';  /* Unset */
	c->x86_clflush_size = 64;
	c->x86_cache_alignment = c->x86_clflush_size;
918
	c->x86_max_cores = 1;
919
	c->x86_coreid_bits = 0;
920
	c->extended_cpuid_level = 0;
L
Linus Torvalds 已提交
921 922 923 924 925 926 927
	memset(&c->x86_capability, 0, sizeof c->x86_capability);

	/* Get vendor name */
	cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
	      (unsigned int *)&c->x86_vendor_id[0],
	      (unsigned int *)&c->x86_vendor_id[8],
	      (unsigned int *)&c->x86_vendor_id[4]);
T
Thomas Gleixner 已提交
928

L
Linus Torvalds 已提交
929 930 931 932 933 934 935 936 937 938 939 940 941
	get_cpu_vendor(c);

	/* Initialize the standard set of capabilities */
	/* Note that the vendor-specific code below might override */

	/* Intel-defined flags: level 0x00000001 */
	if (c->cpuid_level >= 0x00000001) {
		__u32 misc;
		cpuid(0x00000001, &tfms, &misc, &c->x86_capability[4],
		      &c->x86_capability[0]);
		c->x86 = (tfms >> 8) & 0xf;
		c->x86_model = (tfms >> 4) & 0xf;
		c->x86_mask = tfms & 0xf;
942
		if (c->x86 == 0xf)
L
Linus Torvalds 已提交
943
			c->x86 += (tfms >> 20) & 0xff;
944
		if (c->x86 >= 0x6)
L
Linus Torvalds 已提交
945
			c->x86_model += ((tfms >> 16) & 0xF) << 4;
T
Thomas Gleixner 已提交
946
		if (c->x86_capability[0] & (1<<19))
L
Linus Torvalds 已提交
947 948 949 950 951
			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
	} else {
		/* Have CPUID level 0 only - unheard of */
		c->x86 = 4;
	}
952 953

#ifdef CONFIG_SMP
954
	c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
955
#endif
L
Linus Torvalds 已提交
956 957
	/* AMD-defined flags: level 0x80000001 */
	xlvl = cpuid_eax(0x80000000);
958
	c->extended_cpuid_level = xlvl;
L
Linus Torvalds 已提交
959 960 961
	if ((xlvl & 0xffff0000) == 0x80000000) {
		if (xlvl >= 0x80000001) {
			c->x86_capability[1] = cpuid_edx(0x80000001);
962
			c->x86_capability[6] = cpuid_ecx(0x80000001);
L
Linus Torvalds 已提交
963 964 965 966 967 968 969 970 971 972 973 974 975
		}
		if (xlvl >= 0x80000004)
			get_model_name(c); /* Default name */
	}

	/* Transmeta-defined flags: level 0x80860001 */
	xlvl = cpuid_eax(0x80860000);
	if ((xlvl & 0xffff0000) == 0x80860000) {
		/* Don't set x86_cpuid_level here for now to not confuse. */
		if (xlvl >= 0x80860001)
			c->x86_capability[2] = cpuid_edx(0x80860001);
	}

976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992
	switch (c->x86_vendor) {
	case X86_VENDOR_AMD:
		early_init_amd(c);
		break;
	}

}

/*
 * This does the hard work of actually picking apart the CPU stuff...
 */
void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
{
	int i;

	early_identify_cpu(c);

993 994
	init_scattered_cpuid_features(c);

995 996
	c->apicid = phys_pkg_id(0);

L
Linus Torvalds 已提交
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
	/*
	 * Vendor-specific initialization.  In this section we
	 * canonicalize the feature flags, meaning if there are
	 * features a certain CPU supports which CPUID doesn't
	 * tell us, CPUID claiming incorrect flags, or other bugs,
	 * we handle them here.
	 *
	 * At the end of this section, c->x86_capability better
	 * indicate the features this CPU genuinely supports!
	 */
	switch (c->x86_vendor) {
	case X86_VENDOR_AMD:
		init_amd(c);
		break;

	case X86_VENDOR_INTEL:
		init_intel(c);
		break;

	case X86_VENDOR_UNKNOWN:
	default:
		display_cacheinfo(c);
		break;
	}

	select_idle_routine(c);
T
Thomas Gleixner 已提交
1023
	detect_ht(c);
L
Linus Torvalds 已提交
1024 1025 1026 1027 1028 1029 1030 1031 1032

	/*
	 * On SMP, boot_cpu_data holds the common feature set between
	 * all CPUs; so make sure that we indicate which features are
	 * common between the CPUs.  The first time this routine gets
	 * executed, c == &boot_cpu_data.
	 */
	if (c != &boot_cpu_data) {
		/* AND the already accumulated flags with these */
T
Thomas Gleixner 已提交
1033
		for (i = 0; i < NCAPINTS; i++)
L
Linus Torvalds 已提交
1034 1035 1036 1037 1038 1039
			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
	}

#ifdef CONFIG_X86_MCE
	mcheck_init(c);
#endif
1040
	if (c != &boot_cpu_data)
S
Shaohua Li 已提交
1041
		mtrr_ap_init();
L
Linus Torvalds 已提交
1042
#ifdef CONFIG_NUMA
1043
	numa_add_cpu(smp_processor_id());
L
Linus Torvalds 已提交
1044 1045 1046
#endif
}

1047
void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
L
Linus Torvalds 已提交
1048 1049
{
	if (c->x86_model_id[0])
T
Thomas Gleixner 已提交
1050
		printk(KERN_INFO "%s", c->x86_model_id);
L
Linus Torvalds 已提交
1051

T
Thomas Gleixner 已提交
1052 1053
	if (c->x86_mask || c->cpuid_level >= 0)
		printk(KERN_CONT " stepping %02x\n", c->x86_mask);
L
Linus Torvalds 已提交
1054
	else
T
Thomas Gleixner 已提交
1055
		printk(KERN_CONT "\n");
L
Linus Torvalds 已提交
1056 1057 1058 1059 1060 1061 1062 1063 1064
}

/*
 *	Get CPU information for use by the procfs.
 */

static int show_cpuinfo(struct seq_file *m, void *v)
{
	struct cpuinfo_x86 *c = v;
T
Thomas Gleixner 已提交
1065
	int cpu = 0, i;
L
Linus Torvalds 已提交
1066

T
Thomas Gleixner 已提交
1067
	/*
L
Linus Torvalds 已提交
1068 1069 1070 1071 1072 1073 1074
	 * These flag bits must match the definitions in <asm/cpufeature.h>.
	 * NULL means this bit is undefined or reserved; either way it doesn't
	 * have meaning as far as Linux is concerned.  Note that it's important
	 * to realize there is a difference between this table and CPUID -- if
	 * applications want to get the raw CPUID data, they should access
	 * /dev/cpu/<cpu_nr>/cpuid instead.
	 */
J
Jan Beulich 已提交
1075
	static const char *const x86_cap_flags[] = {
L
Linus Torvalds 已提交
1076
		/* Intel-defined */
T
Thomas Gleixner 已提交
1077 1078 1079 1080
		"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
		"cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
		"pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
		"fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
L
Linus Torvalds 已提交
1081 1082

		/* AMD-defined */
1083
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
L
Linus Torvalds 已提交
1084 1085
		NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, "nx", NULL, "mmxext", NULL,
1086 1087
		NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm",
		"3dnowext", "3dnow",
L
Linus Torvalds 已提交
1088 1089 1090 1091 1092 1093 1094 1095

		/* Transmeta-defined */
		"recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,

		/* Other (Linux-defined) */
1096 1097 1098 1099 1100
		"cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
		NULL, NULL, NULL, NULL,
		"constant_tsc", "up", NULL, "arch_perfmon",
		"pebs", "bts", NULL, "sync_rdtsc",
		"rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
L
Linus Torvalds 已提交
1101 1102 1103
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,

		/* Intel-defined (#2) */
1104
		"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
1105
		"tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
1106
		NULL, NULL, "dca", "sse4_1", "sse4_2", NULL, NULL, "popcnt",
L
Linus Torvalds 已提交
1107 1108
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,

1109 1110
		/* VIA/Cyrix/Centaur-defined */
		NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
1111
		"ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL, NULL,
1112 1113 1114
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,

L
Linus Torvalds 已提交
1115
		/* AMD-defined (#2) */
1116 1117 1118 1119
		"lahf_lm", "cmp_legacy", "svm", "extapic",
		"cr8_legacy", "abm", "sse4a", "misalignsse",
		"3dnowprefetch", "osvw", "ibs", "sse5",
		"skinit", "wdt", NULL, NULL,
L
Linus Torvalds 已提交
1120
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1121
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1122 1123 1124 1125 1126 1127

		/* Auxiliary (Linux-defined) */
		"ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
L
Linus Torvalds 已提交
1128
	};
J
Jan Beulich 已提交
1129
	static const char *const x86_power_flags[] = {
L
Linus Torvalds 已提交
1130 1131 1132 1133 1134
		"ts",	/* temperature sensor */
		"fid",  /* frequency id control */
		"vid",  /* voltage id control */
		"ttp",  /* thermal trip */
		"tm",
1135
		"stc",
1136 1137
		"100mhzsteps",
		"hwpstate",
1138 1139
		"",	/* tsc invariant mapped to constant_tsc */
		/* nothing */
L
Linus Torvalds 已提交
1140 1141 1142 1143
	};


#ifdef CONFIG_SMP
1144
	cpu = c->cpu_index;
L
Linus Torvalds 已提交
1145 1146
#endif

T
Thomas Gleixner 已提交
1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157
	seq_printf(m, "processor\t: %u\n"
		   "vendor_id\t: %s\n"
		   "cpu family\t: %d\n"
		   "model\t\t: %d\n"
		   "model name\t: %s\n",
		   (unsigned)cpu,
		   c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
		   c->x86,
		   (int)c->x86_model,
		   c->x86_model_id[0] ? c->x86_model_id : "unknown");

L
Linus Torvalds 已提交
1158 1159 1160 1161
	if (c->x86_mask || c->cpuid_level >= 0)
		seq_printf(m, "stepping\t: %d\n", c->x86_mask);
	else
		seq_printf(m, "stepping\t: unknown\n");
T
Thomas Gleixner 已提交
1162 1163

	if (cpu_has(c, X86_FEATURE_TSC)) {
1164
		unsigned int freq = cpufreq_quick_get((unsigned)cpu);
T
Thomas Gleixner 已提交
1165

1166 1167
		if (!freq)
			freq = cpu_khz;
L
Linus Torvalds 已提交
1168
		seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
T
Thomas Gleixner 已提交
1169
			   freq / 1000, (freq % 1000));
L
Linus Torvalds 已提交
1170 1171 1172
	}

	/* Cache size */
T
Thomas Gleixner 已提交
1173
	if (c->x86_cache_size >= 0)
L
Linus Torvalds 已提交
1174
		seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
T
Thomas Gleixner 已提交
1175

L
Linus Torvalds 已提交
1176
#ifdef CONFIG_SMP
1177
	if (smp_num_siblings * c->x86_max_cores > 1) {
1178
		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
1179 1180
		seq_printf(m, "siblings\t: %d\n",
			       cpus_weight(per_cpu(cpu_core_map, cpu)));
1181
		seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
1182
		seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
1183
	}
T
Thomas Gleixner 已提交
1184
#endif
L
Linus Torvalds 已提交
1185 1186

	seq_printf(m,
T
Thomas Gleixner 已提交
1187 1188 1189 1190 1191
		   "fpu\t\t: yes\n"
		   "fpu_exception\t: yes\n"
		   "cpuid level\t: %d\n"
		   "wp\t\t: yes\n"
		   "flags\t\t:",
L
Linus Torvalds 已提交
1192 1193
		   c->cpuid_level);

T
Thomas Gleixner 已提交
1194 1195 1196 1197
	for (i = 0; i < 32*NCAPINTS; i++)
		if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
			seq_printf(m, " %s", x86_cap_flags[i]);

L
Linus Torvalds 已提交
1198 1199 1200 1201
	seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
		   c->loops_per_jiffy/(500000/HZ),
		   (c->loops_per_jiffy/(5000/HZ)) % 100);

T
Thomas Gleixner 已提交
1202
	if (c->x86_tlbsize > 0)
L
Linus Torvalds 已提交
1203 1204 1205 1206
		seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize);
	seq_printf(m, "clflush size\t: %d\n", c->x86_clflush_size);
	seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment);

T
Thomas Gleixner 已提交
1207
	seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n",
L
Linus Torvalds 已提交
1208 1209 1210
		   c->x86_phys_bits, c->x86_virt_bits);

	seq_printf(m, "power management:");
T
Thomas Gleixner 已提交
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220
	for (i = 0; i < 32; i++) {
		if (c->x86_power & (1 << i)) {
			if (i < ARRAY_SIZE(x86_power_flags) &&
			    x86_power_flags[i])
				seq_printf(m, "%s%s",
					   x86_power_flags[i][0]?" ":"",
					   x86_power_flags[i]);
			else
				seq_printf(m, " [%d]", i);
		}
L
Linus Torvalds 已提交
1221 1222
	}

1223
	seq_printf(m, "\n\n");
L
Linus Torvalds 已提交
1224 1225 1226 1227 1228 1229

	return 0;
}

static void *c_start(struct seq_file *m, loff_t *pos)
{
1230
	if (*pos == 0)	/* just in case, cpu 0 is not the first */
1231 1232
		*pos = first_cpu(cpu_online_map);
	if ((*pos) < NR_CPUS && cpu_online(*pos))
1233 1234
		return &cpu_data(*pos);
	return NULL;
L
Linus Torvalds 已提交
1235 1236 1237 1238
}

static void *c_next(struct seq_file *m, void *v, loff_t *pos)
{
1239
	*pos = next_cpu(*pos, cpu_online_map);
L
Linus Torvalds 已提交
1240 1241 1242 1243 1244 1245 1246 1247
	return c_start(m, pos);
}

static void c_stop(struct seq_file *m, void *v)
{
}

struct seq_operations cpuinfo_op = {
T
Thomas Gleixner 已提交
1248
	.start = c_start,
L
Linus Torvalds 已提交
1249 1250 1251 1252
	.next =	c_next,
	.stop =	c_stop,
	.show =	show_cpuinfo,
};