setup.c 30.8 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
 *  linux/arch/x86-64/kernel/setup.c
 *
 *  Copyright (C) 1995  Linus Torvalds
 *
 *  Nov 2001 Dave Jones <davej@suse.de>
 *  Forked from i386 setup code.
 */

/*
 * 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>
24
#include <linux/screen_info.h>
Linus Torvalds's avatar
Linus Torvalds committed
25
26
27
28
29
30
31
32
33
34
#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>
35
#include <linux/crash_dump.h>
Linus Torvalds's avatar
Linus Torvalds committed
36
37
38
39
40
#include <linux/root_dev.h>
#include <linux/pci.h>
#include <linux/acpi.h>
#include <linux/kallsyms.h>
#include <linux/edd.h>
41
#include <linux/mmzone.h>
42
#include <linux/kexec.h>
43
#include <linux/cpufreq.h>
44
#include <linux/dmi.h>
45
#include <linux/dma-mapping.h>
46
#include <linux/ctype.h>
47

Linus Torvalds's avatar
Linus Torvalds committed
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#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/bootsetup.h>
#include <asm/proto.h>
#include <asm/setup.h>
#include <asm/mach_apic.h>
#include <asm/numa.h>
65
#include <asm/sections.h>
66
#include <asm/dmi.h>
Linus Torvalds's avatar
Linus Torvalds committed
67
68
69
70
71

/*
 * Machine setup..
 */

72
struct cpuinfo_x86 boot_cpu_data __read_mostly;
73
EXPORT_SYMBOL(boot_cpu_data);
Linus Torvalds's avatar
Linus Torvalds committed
74
75
76
77
78
79
80
81
82
83
84
85
86

unsigned long mmu_cr4_features;

int acpi_disabled;
EXPORT_SYMBOL(acpi_disabled);

int acpi_numa __initdata;

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

unsigned long saved_video_mode;

87
88
89
90
91
92
/* 
 * Early DMI memory
 */
int dmi_alloc_index;
char dmi_alloc_data[DMI_MAX_DATA];

Linus Torvalds's avatar
Linus Torvalds committed
93
94
95
96
/*
 * Setup options
 */
struct screen_info screen_info;
97
EXPORT_SYMBOL(screen_info);
Linus Torvalds's avatar
Linus Torvalds committed
98
99
100
101
102
103
struct sys_desc_table_struct {
	unsigned short length;
	unsigned char table[0];
};

struct edid_info edid_info;
104
EXPORT_SYMBOL_GPL(edid_info);
Linus Torvalds's avatar
Linus Torvalds committed
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
struct e820map e820;

extern int root_mountflags;

char command_line[COMMAND_LINE_SIZE];

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 STANDARD_IO_RESOURCES \
	(sizeof standard_io_resources / sizeof standard_io_resources[0])

#define IORESOURCE_RAM (IORESOURCE_BUSY | IORESOURCE_MEM)

struct resource data_resource = {
	.name = "Kernel data",
	.start = 0,
	.end = 0,
	.flags = IORESOURCE_RAM,
};
struct resource code_resource = {
	.name = "Kernel code",
	.start = 0,
	.end = 0,
	.flags = IORESOURCE_RAM,
};

#define IORESOURCE_ROM (IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM)

static struct resource system_rom_resource = {
	.name = "System ROM",
	.start = 0xf0000,
	.end = 0xfffff,
	.flags = IORESOURCE_ROM,
};

static struct resource extension_rom_resource = {
	.name = "Extension ROM",
	.start = 0xe0000,
	.end = 0xeffff,
	.flags = IORESOURCE_ROM,
};

static struct resource adapter_rom_resources[] = {
	{ .name = "Adapter ROM", .start = 0xc8000, .end = 0,
		.flags = IORESOURCE_ROM },
	{ .name = "Adapter ROM", .start = 0, .end = 0,
		.flags = IORESOURCE_ROM },
	{ .name = "Adapter ROM", .start = 0, .end = 0,
		.flags = IORESOURCE_ROM },
	{ .name = "Adapter ROM", .start = 0, .end = 0,
		.flags = IORESOURCE_ROM },
	{ .name = "Adapter ROM", .start = 0, .end = 0,
		.flags = IORESOURCE_ROM },
	{ .name = "Adapter ROM", .start = 0, .end = 0,
		.flags = IORESOURCE_ROM }
};

#define ADAPTER_ROM_RESOURCES \
	(sizeof adapter_rom_resources / sizeof adapter_rom_resources[0])

static struct resource video_rom_resource = {
	.name = "Video ROM",
	.start = 0xc0000,
	.end = 0xc7fff,
	.flags = IORESOURCE_ROM,
};

static struct resource video_ram_resource = {
	.name = "Video RAM area",
	.start = 0xa0000,
	.end = 0xbffff,
	.flags = IORESOURCE_RAM,
};

#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)

static int __init romchecksum(unsigned char *rom, unsigned long length)
{
	unsigned char *p, sum = 0;

	for (p = rom; p < rom + length; p++)
		sum += *p;
	return sum == 0;
}

static void __init probe_roms(void)
{
	unsigned long start, length, upper;
	unsigned char *rom;
	int	      i;

	/* video rom */
	upper = adapter_rom_resources[0].start;
	for (start = video_rom_resource.start; start < upper; start += 2048) {
		rom = isa_bus_to_virt(start);
		if (!romsignature(rom))
			continue;

		video_rom_resource.start = start;

		/* 0 < length <= 0x7f * 512, historically */
		length = rom[2] * 512;

		/* if checksum okay, trust length byte */
		if (length && romchecksum(rom, length))
			video_rom_resource.end = start + length - 1;

		request_resource(&iomem_resource, &video_rom_resource);
		break;
			}

	start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
	if (start < upper)
		start = upper;

	/* system rom */
	request_resource(&iomem_resource, &system_rom_resource);
	upper = system_rom_resource.start;

	/* check for extension rom (ignore length byte!) */
	rom = isa_bus_to_virt(extension_rom_resource.start);
	if (romsignature(rom)) {
		length = extension_rom_resource.end - extension_rom_resource.start + 1;
		if (romchecksum(rom, length)) {
			request_resource(&iomem_resource, &extension_rom_resource);
			upper = extension_rom_resource.start;
		}
	}

	/* check for adapter roms on 2k boundaries */
	for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) {
		rom = isa_bus_to_virt(start);
		if (!romsignature(rom))
			continue;

		/* 0 < length <= 0x7f * 512, historically */
		length = rom[2] * 512;

		/* but accept any length that fits if checksum okay */
		if (!length || start + length > upper || !romchecksum(rom, length))
			continue;

		adapter_rom_resources[i].start = start;
		adapter_rom_resources[i].end = start + length - 1;
		request_resource(&iomem_resource, &adapter_rom_resources[i]);

		start = adapter_rom_resources[i++].end & ~2047UL;
	}
}

274
275
276
277
278
279
#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)
280
{
281
282
283
284
285
	char *end;
	if (!arg)
		return -EINVAL;
	elfcorehdr_addr = memparse(arg, &end);
	return end > arg ? 0 : -EINVAL;
286
}
287
early_param("elfcorehdr", setup_elfcorehdr);
288
#endif
289

290
#ifndef CONFIG_NUMA
291
292
static void __init
contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
Linus Torvalds's avatar
Linus Torvalds committed
293
{
294
295
296
297
298
299
300
301
302
	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)
		panic("Cannot find bootmem map of size %ld\n",bootmap_size);
	bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
	e820_bootmem_free(NODE_DATA(0), 0, end_pfn << PAGE_SHIFT);
	reserve_bootmem(bootmap, bootmap_size);
Linus Torvalds's avatar
Linus Torvalds committed
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
} 
#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)
{
     memcpy(edd.mbr_signature, EDD_MBR_SIGNATURE, sizeof(edd.mbr_signature));
     memcpy(edd.edd_info, EDD_BUF, sizeof(edd.edd_info));
     edd.mbr_signature_nr = EDD_MBR_SIG_NR;
     edd.edd_info_nr = EDD_NR;
}
#else
static inline void copy_edd(void)
{
}
#endif

#define EBDA_ADDR_POINTER 0x40E
330
331
332
333
334

unsigned __initdata ebda_addr;
unsigned __initdata ebda_size;

static void discover_ebda(void)
Linus Torvalds's avatar
Linus Torvalds committed
335
{
336
	/*
Linus Torvalds's avatar
Linus Torvalds committed
337
338
339
	 * there is a real-mode segmented pointer pointing to the 
	 * 4K EBDA area at 0x40E
	 */
340
341
342
343
344
345
346
347
348
349
350
351
	ebda_addr = *(unsigned short *)EBDA_ADDR_POINTER;
	ebda_addr <<= 4;

	ebda_size = *(unsigned short *)(unsigned long)ebda_addr;

	/* 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;
Linus Torvalds's avatar
Linus Torvalds committed
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
}

void __init setup_arch(char **cmdline_p)
{
 	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
 	screen_info = SCREEN_INFO;
	edid_info = EDID_INFO;
	saved_video_mode = SAVED_VIDEO_MODE;
	bootloader_type = LOADER_TYPE;

#ifdef CONFIG_BLK_DEV_RAM
	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
#endif
	setup_memory_region();
	copy_edd();

	if (!MOUNT_ROOT_RDONLY)
		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;

	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;

	early_identify_cpu(&boot_cpu_data);

384
385
386
387
388
389
	strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
	*cmdline_p = command_line;

	parse_early_param();

	finish_e820_parsing();
390

Linus Torvalds's avatar
Linus Torvalds committed
391
392
393
394
395
	/*
	 * partially used pages are not usable - thus
	 * we are rounding upwards:
	 */
	end_pfn = e820_end_of_ram();
396
	num_physpages = end_pfn;
Linus Torvalds's avatar
Linus Torvalds committed
397
398
399

	check_efer();

400
401
	discover_ebda();

Linus Torvalds's avatar
Linus Torvalds committed
402
403
	init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));

404
405
	dmi_scan_machine();

406
407
	zap_low_mappings(0);

Len Brown's avatar
Len Brown committed
408
#ifdef CONFIG_ACPI
Linus Torvalds's avatar
Linus Torvalds committed
409
410
411
412
413
414
415
	/*
	 * Initialize the ACPI boot-time table parser (gets the RSDP and SDT).
	 * Call this early for SRAT node setup.
	 */
	acpi_boot_table_init();
#endif

416
417
418
419
420
	/* 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;

Linus Torvalds's avatar
Linus Torvalds committed
421
422
423
424
425
426
427
#ifdef CONFIG_ACPI_NUMA
	/*
	 * Parse SRAT to discover nodes.
	 */
	acpi_numa_init();
#endif

428
#ifdef CONFIG_NUMA
Linus Torvalds's avatar
Linus Torvalds committed
429
430
	numa_initmem_init(0, end_pfn); 
#else
431
	contig_initmem_init(0, end_pfn);
Linus Torvalds's avatar
Linus Torvalds committed
432
433
434
435
436
437
438
#endif

	/* Reserve direct mapping */
	reserve_bootmem_generic(table_start << PAGE_SHIFT, 
				(table_end - table_start) << PAGE_SHIFT);

	/* reserve kernel */
439
440
	reserve_bootmem_generic(__pa_symbol(&_text),
				__pa_symbol(&_end) - __pa_symbol(&_text));
Linus Torvalds's avatar
Linus Torvalds committed
441
442
443
444
445
446
447
448

	/*
	 * 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 */
449
450
	if (ebda_addr)
		reserve_bootmem_generic(ebda_addr, ebda_size);
Linus Torvalds's avatar
Linus Torvalds committed
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490

#ifdef CONFIG_SMP
	/*
	 * But first pinch a few for the stack/trampoline stuff
	 * FIXME: Don't need the extra page at 4K, but need to fix
	 * trampoline before removing it. (see the GDT stuff)
	 */
	reserve_bootmem_generic(PAGE_SIZE, PAGE_SIZE);

	/* Reserve SMP trampoline */
	reserve_bootmem_generic(SMP_TRAMPOLINE_BASE, PAGE_SIZE);
#endif

#ifdef CONFIG_ACPI_SLEEP
       /*
        * Reserve low memory region for sleep support.
        */
       acpi_reserve_bootmem();
#endif
	/*
	 * Find and reserve possible boot-time SMP configuration:
	 */
	find_smp_config();
#ifdef CONFIG_BLK_DEV_INITRD
	if (LOADER_TYPE && INITRD_START) {
		if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) {
			reserve_bootmem_generic(INITRD_START, INITRD_SIZE);
			initrd_start =
				INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
			initrd_end = initrd_start+INITRD_SIZE;
		}
		else {
			printk(KERN_ERR "initrd extends beyond end of memory "
			    "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
			    (unsigned long)(INITRD_START + INITRD_SIZE),
			    (unsigned long)(end_pfn << PAGE_SHIFT));
			initrd_start = 0;
		}
	}
#endif
491
492
#ifdef CONFIG_KEXEC
	if (crashk_res.start != crashk_res.end) {
493
		reserve_bootmem_generic(crashk_res.start,
494
495
496
			crashk_res.end - crashk_res.start + 1);
	}
#endif
497

Linus Torvalds's avatar
Linus Torvalds committed
498
499
	paging_init();

500
	early_quirks();
Linus Torvalds's avatar
Linus Torvalds committed
501

502
503
504
505
506
507
	/*
	 * 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);
Len Brown's avatar
Len Brown committed
508
#ifdef CONFIG_ACPI
Linus Torvalds's avatar
Linus Torvalds committed
509
510
511
512
513
514
	/*
	 * Read APIC and some other early information from ACPI tables.
	 */
	acpi_boot_init();
#endif

515
516
	init_cpu_to_node();

Linus Torvalds's avatar
Linus Torvalds committed
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
	/*
	 * get boot-time SMP configuration:
	 */
	if (smp_found_config)
		get_smp_config();
	init_apic_mappings();

	/*
	 * Request address space for all standard RAM and ROM resources
	 * and also for regions reported as reserved by the e820.
	 */
	probe_roms();
	e820_reserve_resources(); 

	request_resource(&iomem_resource, &video_ram_resource);

	{
	unsigned i;
	/* request I/O space for devices used on all i[345]86 PCs */
	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
		request_resource(&ioport_resource, &standard_io_resources[i]);
	}

540
	e820_setup_gap();
Linus Torvalds's avatar
Linus Torvalds committed
541
542
543
544
545
546
547
548
549
550

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

551
static int __cpuinit get_model_name(struct cpuinfo_x86 *c)
Linus Torvalds's avatar
Linus Torvalds committed
552
553
554
{
	unsigned int *v;

555
	if (c->extended_cpuid_level < 0x80000004)
Linus Torvalds's avatar
Linus Torvalds committed
556
557
558
559
560
561
562
563
564
565
566
		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;
}


567
static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
Linus Torvalds's avatar
Linus Torvalds committed
568
569
570
{
	unsigned int n, dummy, eax, ebx, ecx, edx;

571
	n = c->extended_cpuid_level;
Linus Torvalds's avatar
Linus Torvalds committed
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600

	if (n >= 0x80000005) {
		cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);
		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);
		/* 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)
		cpuid(0x80000007, &dummy, &dummy, &dummy, &c->x86_power); 
	if (n >= 0x80000008) {
		cpuid(0x80000008, &eax, &dummy, &dummy, &dummy); 
		c->x86_virt_bits = (eax >> 8) & 0xff;
		c->x86_phys_bits = eax & 0xff;
	}
}

601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
#ifdef CONFIG_NUMA
static int nearby_node(int apicid)
{
	int i;
	for (i = apicid - 1; i >= 0; i--) {
		int node = apicid_to_node[i];
		if (node != NUMA_NO_NODE && node_online(node))
			return node;
	}
	for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
		int node = apicid_to_node[i];
		if (node != NUMA_NO_NODE && node_online(node))
			return node;
	}
	return first_node(node_online_map); /* Shouldn't happen */
}
#endif

619
620
621
622
623
624
625
/*
 * 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
626
	unsigned bits;
627
#ifdef CONFIG_NUMA
628
	int cpu = smp_processor_id();
629
	int node = 0;
630
	unsigned apicid = hard_smp_processor_id();
631
#endif
632
	unsigned ecx = cpuid_ecx(0x80000008);
633

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

636
637
638
639
640
641
642
643
	/* 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++;
	}
644
645

	/* Low order bits define the core id (index of core in socket) */
646
	c->cpu_core_id = c->phys_proc_id & ((1 << bits)-1);
647
	/* Convert the APIC ID into the socket ID */
648
	c->phys_proc_id = phys_pkg_id(bits);
649
650

#ifdef CONFIG_NUMA
651
  	node = c->phys_proc_id;
652
653
654
655
656
657
658
659
660
661
662
663
 	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.  */
664
 		int ht_nodeid = apicid - (cpu_data[0].phys_proc_id << bits);
665
666
667
668
669
670
671
 		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);
 	}
672
	numa_set_node(cpu, node);
673

674
	printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
675
676
677
#endif
#endif
}
Linus Torvalds's avatar
Linus Torvalds committed
678

679
static void __init init_amd(struct cpuinfo_x86 *c)
Linus Torvalds's avatar
Linus Torvalds committed
680
{
681
	unsigned level;
Linus Torvalds's avatar
Linus Torvalds committed
682

683
684
685
#ifdef CONFIG_SMP
	unsigned long value;

686
687
688
689
690
691
692
693
694
695
696
697
	/*
	 * Disable TLB flush filter by setting HWCR.FFDIS on K8
	 * bit 6 of msr C001_0015
 	 *
	 * 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);
	}
698
699
#endif

Linus Torvalds's avatar
Linus Torvalds committed
700
701
702
703
	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
	clear_bit(0*32+31, &c->x86_capability);
	
704
705
706
707
708
	/* On C+ stepping K8 rep microcode works well for copy/memset */
	level = cpuid_eax(1);
	if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58))
		set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);

709
710
711
712
	/* Enable workaround for FXSAVE leak */
	if (c->x86 >= 6)
		set_bit(X86_FEATURE_FXSAVE_LEAK, &c->x86_capability);

713
714
	level = get_model_name(c);
	if (!level) {
Linus Torvalds's avatar
Linus Torvalds committed
715
716
717
718
719
720
721
722
723
724
		switch (c->x86) { 
		case 15:
			/* Should distinguish Models here, but this is only
			   a fallback anyways. */
			strcpy(c->x86_model_id, "Hammer");
			break; 
		} 
	} 
	display_cacheinfo(c);

725
726
727
728
	/* c->x86_power is 8000_0007 edx. Bit 8 is constant TSC */
	if (c->x86_power & (1<<8))
		set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);

729
730
	/* Multi core CPU? */
	if (c->extended_cpuid_level >= 0x80000008)
731
		amd_detect_cmp(c);
Linus Torvalds's avatar
Linus Torvalds committed
732

733
734
	/* Fix cpuid4 emulation for more */
	num_cache_leaves = 3;
Linus Torvalds's avatar
Linus Torvalds committed
735
736
}

737
static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
Linus Torvalds's avatar
Linus Torvalds committed
738
739
740
{
#ifdef CONFIG_SMP
	u32 	eax, ebx, ecx, edx;
741
742
743
744
745
	int 	index_msb, core_bits;

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


746
	if (!cpu_has(c, X86_FEATURE_HT))
Linus Torvalds's avatar
Linus Torvalds committed
747
		return;
748
749
 	if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
		goto out;
Linus Torvalds's avatar
Linus Torvalds committed
750
751

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

Linus Torvalds's avatar
Linus Torvalds committed
753
754
	if (smp_num_siblings == 1) {
		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
755
756
	} else if (smp_num_siblings > 1 ) {

Linus Torvalds's avatar
Linus Torvalds committed
757
758
759
760
761
		if (smp_num_siblings > NR_CPUS) {
			printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
			smp_num_siblings = 1;
			return;
		}
762
763

		index_msb = get_count_order(smp_num_siblings);
764
		c->phys_proc_id = phys_pkg_id(index_msb);
765

766
		smp_num_siblings = smp_num_siblings / c->x86_max_cores;
767

768
769
770
		index_msb = get_count_order(smp_num_siblings) ;

		core_bits = get_count_order(c->x86_max_cores);
771

772
		c->cpu_core_id = phys_pkg_id(index_msb) &
773
					       ((1 << core_bits) - 1);
Linus Torvalds's avatar
Linus Torvalds committed
774
	}
775
776
777
778
779
780
out:
	if ((c->x86_max_cores * smp_num_siblings) > 1) {
		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);
	}

Linus Torvalds's avatar
Linus Torvalds committed
781
782
783
#endif
}

784
785
786
/*
 * find out the number of processor cores on the die
 */
787
static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c)
788
{
789
	unsigned int eax, t;
790
791
792
793

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

794
	cpuid_count(4, 0, &eax, &t, &t, &t);
795
796
797
798
799
800
801

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

802
803
804
static void srat_detect_node(void)
{
#ifdef CONFIG_NUMA
805
	unsigned node;
806
	int cpu = smp_processor_id();
807
	int apicid = hard_smp_processor_id();
808
809
810

	/* Don't do the funky fallback heuristics the AMD version employs
	   for now. */
811
	node = apicid_to_node[apicid];
812
	if (node == NUMA_NO_NODE)
813
		node = first_node(node_online_map);
814
	numa_set_node(cpu, node);
815
816

	if (acpi_numa > 0)
817
		printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
818
819
820
#endif
}

821
static void __cpuinit init_intel(struct cpuinfo_x86 *c)
Linus Torvalds's avatar
Linus Torvalds committed
822
823
824
825
826
{
	/* Cache sizes */
	unsigned n;

	init_intel_cacheinfo(c);
827
828
829
830
831
832
833
	if (c->cpuid_level > 9 ) {
		unsigned eax = cpuid_eax(10);
		/* Check for version and the number of counters */
		if ((eax & 0xff) && (((eax>>8) & 0xff) > 1))
			set_bit(X86_FEATURE_ARCH_PERFMON, &c->x86_capability);
	}

834
	n = c->extended_cpuid_level;
Linus Torvalds's avatar
Linus Torvalds committed
835
836
837
838
	if (n >= 0x80000008) {
		unsigned eax = cpuid_eax(0x80000008);
		c->x86_virt_bits = (eax >> 8) & 0xff;
		c->x86_phys_bits = eax & 0xff;
839
840
841
842
843
		/* 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;
Linus Torvalds's avatar
Linus Torvalds committed
844
845
846
847
	}

	if (c->x86 == 15)
		c->x86_cache_alignment = c->x86_clflush_size * 2;
848
849
	if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
	    (c->x86 == 0x6 && c->x86_model >= 0x0e))
850
		set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
851
	set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
852
 	c->x86_max_cores = intel_num_cpu_cores(c);
853
854

	srat_detect_node();
Linus Torvalds's avatar
Linus Torvalds committed
855
856
}

857
static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
Linus Torvalds's avatar
Linus Torvalds committed
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
{
	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. */
878
void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
Linus Torvalds's avatar
Linus Torvalds committed
879
880
881
882
883
884
885
886
887
888
889
{
	u32 tfms;

	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;
890
	c->x86_max_cores = 1;
891
	c->extended_cpuid_level = 0;
Linus Torvalds's avatar
Linus Torvalds committed
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
	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]);
		
	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;
913
		if (c->x86 == 0xf)
Linus Torvalds's avatar
Linus Torvalds committed
914
			c->x86 += (tfms >> 20) & 0xff;
915
		if (c->x86 >= 0x6)
Linus Torvalds's avatar
Linus Torvalds committed
916
917
918
919
920
921
922
			c->x86_model += ((tfms >> 16) & 0xF) << 4;
		if (c->x86_capability[0] & (1<<19)) 
			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
	} else {
		/* Have CPUID level 0 only - unheard of */
		c->x86 = 4;
	}
923
924

#ifdef CONFIG_SMP
925
	c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
926
#endif
Linus Torvalds's avatar
Linus Torvalds committed
927
928
929
930
931
}

/*
 * This does the hard work of actually picking apart the CPU stuff...
 */
932
void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
Linus Torvalds's avatar
Linus Torvalds committed
933
934
935
936
937
938
939
940
{
	int i;
	u32 xlvl;

	early_identify_cpu(c);

	/* AMD-defined flags: level 0x80000001 */
	xlvl = cpuid_eax(0x80000000);
941
	c->extended_cpuid_level = xlvl;
Linus Torvalds's avatar
Linus Torvalds committed
942
943
944
	if ((xlvl & 0xffff0000) == 0x80000000) {
		if (xlvl >= 0x80000001) {
			c->x86_capability[1] = cpuid_edx(0x80000001);
945
			c->x86_capability[6] = cpuid_ecx(0x80000001);
Linus Torvalds's avatar
Linus Torvalds committed
946
947
948
949
950
951
952
953
954
955
956
957
958
		}
		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);
	}

959
960
	c->apicid = phys_pkg_id(0);

Linus Torvalds's avatar
Linus Torvalds committed
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
	/*
	 * 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);
	detect_ht(c); 

	/*
	 * 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 */
		for (i = 0 ; i < NCAPINTS ; i++)
			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
	}

#ifdef CONFIG_X86_MCE
	mcheck_init(c);
#endif
1004
1005
1006
1007
	if (c == &boot_cpu_data)
		mtrr_bp_init();
	else
		mtrr_ap_init();
Linus Torvalds's avatar
Linus Torvalds committed
1008
#ifdef CONFIG_NUMA
1009
	numa_add_cpu(smp_processor_id());
Linus Torvalds's avatar
Linus Torvalds committed
1010
1011
1012
1013
#endif
}
 

1014
void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
Linus Torvalds's avatar
Linus Torvalds committed
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
{
	if (c->x86_model_id[0])
		printk("%s", c->x86_model_id);

	if (c->x86_mask || c->cpuid_level >= 0) 
		printk(" stepping %02x\n", c->x86_mask);
	else
		printk("\n");
}

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

static int show_cpuinfo(struct seq_file *m, void *v)
{
	struct cpuinfo_x86 *c = v;

	/* 
	 * 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.
	 */
	static char *x86_cap_flags[] = {
		/* Intel-defined */
	        "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", NULL,

		/* AMD-defined */
1049
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Linus Torvalds's avatar
Linus Torvalds committed
1050
1051
		NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, "nx", NULL, "mmxext", NULL,
1052
		NULL, "fxsr_opt", NULL, "rdtscp", NULL, "lm", "3dnowext", "3dnow",
Linus Torvalds's avatar
Linus Torvalds committed
1053
1054
1055
1056
1057
1058
1059
1060

		/* 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) */
1061
		"cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL,
1062
		"constant_tsc", NULL, NULL,
1063
		"up", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Linus Torvalds's avatar
Linus Torvalds committed
1064
1065
1066
1067
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,

		/* Intel-defined (#2) */
1068
		"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
Linus Torvalds's avatar
Linus Torvalds committed
1069
1070
1071
1072
		"tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL,
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,

1073
1074
1075
1076
1077
1078
		/* VIA/Cyrix/Centaur-defined */
		NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,

Linus Torvalds's avatar
Linus Torvalds committed
1079
		/* AMD-defined (#2) */
1080
		"lahf_lm", "cmp_legacy", "svm", NULL, "cr8_legacy", NULL, NULL, NULL,
Linus Torvalds's avatar
Linus Torvalds committed
1081
1082
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1083
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Linus Torvalds's avatar
Linus Torvalds committed
1084
1085
1086
1087
1088
1089
1090
	};
	static char *x86_power_flags[] = { 
		"ts",	/* temperature sensor */
		"fid",  /* frequency id control */
		"vid",  /* voltage id control */
		"ttp",  /* thermal trip */
		"tm",
1091
1092
		"stc",
		NULL,
1093
		/* nothing */	/* constant_tsc - moved to flags */
Linus Torvalds's avatar
Linus Torvalds committed
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
	};


#ifdef CONFIG_SMP
	if (!cpu_online(c-cpu_data))
		return 0;
#endif

	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)(c-cpu_data),
		     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");
	
	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");
	
	if (cpu_has(c,X86_FEATURE_TSC)) {
1119
1120
1121
		unsigned int freq = cpufreq_quick_get((unsigned)(c-cpu_data));
		if (!freq)
			freq = cpu_khz;
Linus Torvalds's avatar
Linus Torvalds committed
1122
		seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
1123
			     freq / 1000, (freq % 1000));
Linus Torvalds's avatar
Linus Torvalds committed
1124
1125
1126
1127
1128
1129
1130
	}

	/* Cache size */
	if (c->x86_cache_size >= 0) 
		seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
	
#ifdef CONFIG_SMP
1131
	if (smp_num_siblings * c->x86_max_cores > 1) {
1132
		int cpu = c - cpu_data;
1133
		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
1134
		seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[cpu]));
1135
		seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
1136
		seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
1137
	}
Linus Torvalds's avatar
Linus Torvalds committed
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
#endif	

	seq_printf(m,
	        "fpu\t\t: yes\n"
	        "fpu_exception\t: yes\n"
	        "cpuid level\t: %d\n"
	        "wp\t\t: yes\n"
	        "flags\t\t:",
		   c->cpuid_level);

	{ 
		int i; 
		for ( i = 0 ; i < 32*NCAPINTS ; i++ )
1151
			if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
Linus Torvalds's avatar
Linus Torvalds committed
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
				seq_printf(m, " %s", x86_cap_flags[i]);
	}
		
	seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
		   c->loops_per_jiffy/(500000/HZ),
		   (c->loops_per_jiffy/(5000/HZ)) % 100);

	if (c->x86_tlbsize > 0) 
		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);

	seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n", 
		   c->x86_phys_bits, c->x86_virt_bits);

	seq_printf(m, "power management:");
	{
		unsigned i;
		for (i = 0; i < 32; i++) 
			if (c->x86_power & (1 << i)) {
1172
1173
1174
1175
1176
				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]);
Linus Torvalds's avatar
Linus Torvalds committed
1177
1178
1179
1180
1181
				else
					seq_printf(m, " [%d]", i);
			}
	}

1182
	seq_printf(m, "\n\n");
Linus Torvalds's avatar
Linus Torvalds committed
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207

	return 0;
}

static void *c_start(struct seq_file *m, loff_t *pos)
{
	return *pos < NR_CPUS ? cpu_data + *pos : NULL;
}

static void *c_next(struct seq_file *m, void *v, loff_t *pos)
{
	++*pos;
	return c_start(m, pos);
}

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

struct seq_operations cpuinfo_op = {
	.start =c_start,
	.next =	c_next,
	.stop =	c_stop,
	.show =	show_cpuinfo,
};
1208

1209
#if defined(CONFIG_INPUT_PCSPKR) || defined(CONFIG_INPUT_PCSPKR_MODULE)
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
#include <linux/platform_device.h>
static __init int add_pcspkr(void)
{
	struct platform_device *pd;
	int ret;

	pd = platform_device_alloc("pcspkr", -1);
	if (!pd)
		return -ENOMEM;

	ret = platform_device_add(pd);
	if (ret)
		platform_device_put(pd);

	return ret;
}
device_initcall(add_pcspkr);
#endif