blob: 816203d57e11cc92c84f6efde45be46f74bbe2e5 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/arch/x86-64/kernel/setup.c
3 *
4 * Copyright (C) 1995 Linus Torvalds
5 *
6 * Nov 2001 Dave Jones <davej@suse.de>
7 * Forked from i386 setup code.
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 */
9
10/*
11 * This file handles the architecture-dependent parts of initialization
12 */
13
14#include <linux/errno.h>
15#include <linux/sched.h>
16#include <linux/kernel.h>
17#include <linux/mm.h>
18#include <linux/stddef.h>
19#include <linux/unistd.h>
20#include <linux/ptrace.h>
21#include <linux/slab.h>
22#include <linux/user.h>
23#include <linux/a.out.h>
24#include <linux/tty.h>
25#include <linux/ioport.h>
26#include <linux/delay.h>
27#include <linux/config.h>
28#include <linux/init.h>
29#include <linux/initrd.h>
30#include <linux/highmem.h>
31#include <linux/bootmem.h>
32#include <linux/module.h>
33#include <asm/processor.h>
34#include <linux/console.h>
35#include <linux/seq_file.h>
Vivek Goyalaac04b32006-01-09 20:51:47 -080036#include <linux/crash_dump.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/root_dev.h>
38#include <linux/pci.h>
39#include <linux/acpi.h>
40#include <linux/kallsyms.h>
41#include <linux/edd.h>
Matt Tolentinobbfceef2005-06-23 00:08:07 -070042#include <linux/mmzone.h>
Eric W. Biederman5f5609d2005-06-25 14:58:04 -070043#include <linux/kexec.h>
Venkatesh Pallipadi95235ca2005-12-02 10:43:20 -080044#include <linux/cpufreq.h>
Andi Kleene9928672006-01-11 22:43:33 +010045#include <linux/dmi.h>
Muli Ben-Yehuda17a941d2006-01-11 22:44:42 +010046#include <linux/dma-mapping.h>
Andi Kleen681558f2006-03-25 16:29:46 +010047#include <linux/ctype.h>
Matt Tolentinobbfceef2005-06-23 00:08:07 -070048
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <asm/mtrr.h>
50#include <asm/uaccess.h>
51#include <asm/system.h>
52#include <asm/io.h>
53#include <asm/smp.h>
54#include <asm/msr.h>
55#include <asm/desc.h>
56#include <video/edid.h>
57#include <asm/e820.h>
58#include <asm/dma.h>
59#include <asm/mpspec.h>
60#include <asm/mmu_context.h>
61#include <asm/bootsetup.h>
62#include <asm/proto.h>
63#include <asm/setup.h>
64#include <asm/mach_apic.h>
65#include <asm/numa.h>
Muli Ben-Yehuda17a941d2006-01-11 22:44:42 +010066#include <asm/swiotlb.h>
Andi Kleen2bc04142005-11-05 17:25:53 +010067#include <asm/sections.h>
Andi Kleenf2d3efe2006-03-25 16:30:22 +010068#include <asm/dmi.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070069
70/*
71 * Machine setup..
72 */
73
Ravikiran G Thirumalai6c231b72005-09-06 15:17:45 -070074struct cpuinfo_x86 boot_cpu_data __read_mostly;
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
76unsigned long mmu_cr4_features;
77
78int acpi_disabled;
79EXPORT_SYMBOL(acpi_disabled);
Len Brown888ba6c2005-08-24 12:07:20 -040080#ifdef CONFIG_ACPI
Linus Torvalds1da177e2005-04-16 15:20:36 -070081extern int __initdata acpi_ht;
82extern acpi_interrupt_flags acpi_sci_flags;
83int __initdata acpi_force = 0;
84#endif
85
86int acpi_numa __initdata;
87
Linus Torvalds1da177e2005-04-16 15:20:36 -070088/* Boot loader ID as an integer, for the benefit of proc_dointvec */
89int bootloader_type;
90
91unsigned long saved_video_mode;
92
Andi Kleenf2d3efe2006-03-25 16:30:22 +010093/*
94 * Early DMI memory
95 */
96int dmi_alloc_index;
97char dmi_alloc_data[DMI_MAX_DATA];
98
Linus Torvalds1da177e2005-04-16 15:20:36 -070099/*
100 * Setup options
101 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102struct screen_info screen_info;
103struct sys_desc_table_struct {
104 unsigned short length;
105 unsigned char table[0];
106};
107
108struct edid_info edid_info;
109struct e820map e820;
110
111extern int root_mountflags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
113char command_line[COMMAND_LINE_SIZE];
114
115struct resource standard_io_resources[] = {
116 { .name = "dma1", .start = 0x00, .end = 0x1f,
117 .flags = IORESOURCE_BUSY | IORESOURCE_IO },
118 { .name = "pic1", .start = 0x20, .end = 0x21,
119 .flags = IORESOURCE_BUSY | IORESOURCE_IO },
120 { .name = "timer0", .start = 0x40, .end = 0x43,
121 .flags = IORESOURCE_BUSY | IORESOURCE_IO },
122 { .name = "timer1", .start = 0x50, .end = 0x53,
123 .flags = IORESOURCE_BUSY | IORESOURCE_IO },
124 { .name = "keyboard", .start = 0x60, .end = 0x6f,
125 .flags = IORESOURCE_BUSY | IORESOURCE_IO },
126 { .name = "dma page reg", .start = 0x80, .end = 0x8f,
127 .flags = IORESOURCE_BUSY | IORESOURCE_IO },
128 { .name = "pic2", .start = 0xa0, .end = 0xa1,
129 .flags = IORESOURCE_BUSY | IORESOURCE_IO },
130 { .name = "dma2", .start = 0xc0, .end = 0xdf,
131 .flags = IORESOURCE_BUSY | IORESOURCE_IO },
132 { .name = "fpu", .start = 0xf0, .end = 0xff,
133 .flags = IORESOURCE_BUSY | IORESOURCE_IO }
134};
135
136#define STANDARD_IO_RESOURCES \
137 (sizeof standard_io_resources / sizeof standard_io_resources[0])
138
139#define IORESOURCE_RAM (IORESOURCE_BUSY | IORESOURCE_MEM)
140
141struct resource data_resource = {
142 .name = "Kernel data",
143 .start = 0,
144 .end = 0,
145 .flags = IORESOURCE_RAM,
146};
147struct resource code_resource = {
148 .name = "Kernel code",
149 .start = 0,
150 .end = 0,
151 .flags = IORESOURCE_RAM,
152};
153
154#define IORESOURCE_ROM (IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM)
155
156static struct resource system_rom_resource = {
157 .name = "System ROM",
158 .start = 0xf0000,
159 .end = 0xfffff,
160 .flags = IORESOURCE_ROM,
161};
162
163static struct resource extension_rom_resource = {
164 .name = "Extension ROM",
165 .start = 0xe0000,
166 .end = 0xeffff,
167 .flags = IORESOURCE_ROM,
168};
169
170static struct resource adapter_rom_resources[] = {
171 { .name = "Adapter ROM", .start = 0xc8000, .end = 0,
172 .flags = IORESOURCE_ROM },
173 { .name = "Adapter ROM", .start = 0, .end = 0,
174 .flags = IORESOURCE_ROM },
175 { .name = "Adapter ROM", .start = 0, .end = 0,
176 .flags = IORESOURCE_ROM },
177 { .name = "Adapter ROM", .start = 0, .end = 0,
178 .flags = IORESOURCE_ROM },
179 { .name = "Adapter ROM", .start = 0, .end = 0,
180 .flags = IORESOURCE_ROM },
181 { .name = "Adapter ROM", .start = 0, .end = 0,
182 .flags = IORESOURCE_ROM }
183};
184
185#define ADAPTER_ROM_RESOURCES \
186 (sizeof adapter_rom_resources / sizeof adapter_rom_resources[0])
187
188static struct resource video_rom_resource = {
189 .name = "Video ROM",
190 .start = 0xc0000,
191 .end = 0xc7fff,
192 .flags = IORESOURCE_ROM,
193};
194
195static struct resource video_ram_resource = {
196 .name = "Video RAM area",
197 .start = 0xa0000,
198 .end = 0xbffff,
199 .flags = IORESOURCE_RAM,
200};
201
202#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
203
204static int __init romchecksum(unsigned char *rom, unsigned long length)
205{
206 unsigned char *p, sum = 0;
207
208 for (p = rom; p < rom + length; p++)
209 sum += *p;
210 return sum == 0;
211}
212
213static void __init probe_roms(void)
214{
215 unsigned long start, length, upper;
216 unsigned char *rom;
217 int i;
218
219 /* video rom */
220 upper = adapter_rom_resources[0].start;
221 for (start = video_rom_resource.start; start < upper; start += 2048) {
222 rom = isa_bus_to_virt(start);
223 if (!romsignature(rom))
224 continue;
225
226 video_rom_resource.start = start;
227
228 /* 0 < length <= 0x7f * 512, historically */
229 length = rom[2] * 512;
230
231 /* if checksum okay, trust length byte */
232 if (length && romchecksum(rom, length))
233 video_rom_resource.end = start + length - 1;
234
235 request_resource(&iomem_resource, &video_rom_resource);
236 break;
237 }
238
239 start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
240 if (start < upper)
241 start = upper;
242
243 /* system rom */
244 request_resource(&iomem_resource, &system_rom_resource);
245 upper = system_rom_resource.start;
246
247 /* check for extension rom (ignore length byte!) */
248 rom = isa_bus_to_virt(extension_rom_resource.start);
249 if (romsignature(rom)) {
250 length = extension_rom_resource.end - extension_rom_resource.start + 1;
251 if (romchecksum(rom, length)) {
252 request_resource(&iomem_resource, &extension_rom_resource);
253 upper = extension_rom_resource.start;
254 }
255 }
256
257 /* check for adapter roms on 2k boundaries */
258 for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) {
259 rom = isa_bus_to_virt(start);
260 if (!romsignature(rom))
261 continue;
262
263 /* 0 < length <= 0x7f * 512, historically */
264 length = rom[2] * 512;
265
266 /* but accept any length that fits if checksum okay */
267 if (!length || start + length > upper || !romchecksum(rom, length))
268 continue;
269
270 adapter_rom_resources[i].start = start;
271 adapter_rom_resources[i].end = start + length - 1;
272 request_resource(&iomem_resource, &adapter_rom_resources[i]);
273
274 start = adapter_rom_resources[i++].end & ~2047UL;
275 }
276}
277
Andi Kleen681558f2006-03-25 16:29:46 +0100278/* Check for full argument with no trailing characters */
279static int fullarg(char *p, char *arg)
280{
281 int l = strlen(arg);
282 return !memcmp(p, arg, l) && (p[l] == 0 || isspace(p[l]));
283}
284
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285static __init void parse_cmdline_early (char ** cmdline_p)
286{
287 char c = ' ', *to = command_line, *from = COMMAND_LINE;
288 int len = 0;
akpm@osdl.org69cda7b2006-01-09 20:51:46 -0800289 int userdef = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 for (;;) {
292 if (c != ' ')
293 goto next_char;
294
295#ifdef CONFIG_SMP
296 /*
297 * If the BIOS enumerates physical processors before logical,
298 * maxcpus=N at enumeration-time can be used to disable HT.
299 */
300 else if (!memcmp(from, "maxcpus=", 8)) {
301 extern unsigned int maxcpus;
302
303 maxcpus = simple_strtoul(from + 8, NULL, 0);
304 }
305#endif
Len Brown888ba6c2005-08-24 12:07:20 -0400306#ifdef CONFIG_ACPI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 /* "acpi=off" disables both ACPI table parsing and interpreter init */
Andi Kleen681558f2006-03-25 16:29:46 +0100308 if (fullarg(from,"acpi=off"))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 disable_acpi();
310
Andi Kleen681558f2006-03-25 16:29:46 +0100311 if (fullarg(from, "acpi=force")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 /* add later when we do DMI horrors: */
313 acpi_force = 1;
314 acpi_disabled = 0;
315 }
316
317 /* acpi=ht just means: do ACPI MADT parsing
318 at bootup, but don't enable the full ACPI interpreter */
Andi Kleen681558f2006-03-25 16:29:46 +0100319 if (fullarg(from, "acpi=ht")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 if (!acpi_force)
321 disable_acpi();
322 acpi_ht = 1;
323 }
Andi Kleen681558f2006-03-25 16:29:46 +0100324 else if (fullarg(from, "pci=noacpi"))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 acpi_disable_pci();
Andi Kleen681558f2006-03-25 16:29:46 +0100326 else if (fullarg(from, "acpi=noirq"))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 acpi_noirq_set();
328
Andi Kleen681558f2006-03-25 16:29:46 +0100329 else if (fullarg(from, "acpi_sci=edge"))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 acpi_sci_flags.trigger = 1;
Andi Kleen681558f2006-03-25 16:29:46 +0100331 else if (fullarg(from, "acpi_sci=level"))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 acpi_sci_flags.trigger = 3;
Andi Kleen681558f2006-03-25 16:29:46 +0100333 else if (fullarg(from, "acpi_sci=high"))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 acpi_sci_flags.polarity = 1;
Andi Kleen681558f2006-03-25 16:29:46 +0100335 else if (fullarg(from, "acpi_sci=low"))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 acpi_sci_flags.polarity = 3;
337
338 /* acpi=strict disables out-of-spec workarounds */
Andi Kleen681558f2006-03-25 16:29:46 +0100339 else if (fullarg(from, "acpi=strict")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 acpi_strict = 1;
341 }
Andi Kleen22999242005-04-16 15:25:17 -0700342#ifdef CONFIG_X86_IO_APIC
Andi Kleen681558f2006-03-25 16:29:46 +0100343 else if (fullarg(from, "acpi_skip_timer_override"))
Andi Kleen22999242005-04-16 15:25:17 -0700344 acpi_skip_timer_override = 1;
345#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346#endif
347
Andi Kleen681558f2006-03-25 16:29:46 +0100348 if (fullarg(from, "disable_timer_pin_1"))
Chuck Ebbert66759a02005-09-12 18:49:25 +0200349 disable_timer_pin_1 = 1;
Andi Kleen681558f2006-03-25 16:29:46 +0100350 if (fullarg(from, "enable_timer_pin_1"))
Chuck Ebbert66759a02005-09-12 18:49:25 +0200351 disable_timer_pin_1 = -1;
352
Andi Kleend1530d82006-04-07 19:49:42 +0200353 if (fullarg(from, "nolapic") || fullarg(from, "disableapic")) {
354 clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 disable_apic = 1;
Andi Kleend1530d82006-04-07 19:49:42 +0200356 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
Andi Kleen681558f2006-03-25 16:29:46 +0100358 if (fullarg(from, "noapic"))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 skip_ioapic_setup = 1;
360
Andi Kleen681558f2006-03-25 16:29:46 +0100361 if (fullarg(from,"apic")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 skip_ioapic_setup = 0;
363 ioapic_force = 1;
364 }
365
366 if (!memcmp(from, "mem=", 4))
367 parse_memopt(from+4, &from);
368
akpm@osdl.org69cda7b2006-01-09 20:51:46 -0800369 if (!memcmp(from, "memmap=", 7)) {
370 /* exactmap option is for used defined memory */
371 if (!memcmp(from+7, "exactmap", 8)) {
372#ifdef CONFIG_CRASH_DUMP
373 /* If we are doing a crash dump, we
374 * still need to know the real mem
375 * size before original memory map is
376 * reset.
377 */
378 saved_max_pfn = e820_end_of_ram();
379#endif
380 from += 8+7;
381 end_pfn_map = 0;
382 e820.nr_map = 0;
383 userdef = 1;
384 }
385 else {
386 parse_memmapopt(from+7, &from);
387 userdef = 1;
388 }
389 }
390
Matt Tolentino2b976902005-06-23 00:08:06 -0700391#ifdef CONFIG_NUMA
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 if (!memcmp(from, "numa=", 5))
393 numa_setup(from+5);
394#endif
395
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 if (!memcmp(from,"iommu=",6)) {
397 iommu_setup(from+6);
398 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399
Andi Kleen681558f2006-03-25 16:29:46 +0100400 if (fullarg(from,"oops=panic"))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 panic_on_oops = 1;
402
403 if (!memcmp(from, "noexec=", 7))
404 nonx_setup(from + 7);
405
Eric W. Biederman5f5609d2005-06-25 14:58:04 -0700406#ifdef CONFIG_KEXEC
407 /* crashkernel=size@addr specifies the location to reserve for
408 * a crash kernel. By reserving this memory we guarantee
409 * that linux never set's it up as a DMA target.
410 * Useful for holding code to do something appropriate
411 * after a kernel panic.
412 */
413 else if (!memcmp(from, "crashkernel=", 12)) {
414 unsigned long size, base;
415 size = memparse(from+12, &from);
416 if (*from == '@') {
417 base = memparse(from+1, &from);
418 /* FIXME: Do I want a sanity check
419 * to validate the memory range?
420 */
421 crashk_res.start = base;
422 crashk_res.end = base + size - 1;
423 }
424 }
425#endif
426
Vivek Goyalaac04b32006-01-09 20:51:47 -0800427#ifdef CONFIG_PROC_VMCORE
428 /* elfcorehdr= specifies the location of elf core header
429 * stored by the crashed kernel. This option will be passed
430 * by kexec loader to the capture kernel.
431 */
432 else if(!memcmp(from, "elfcorehdr=", 11))
433 elfcorehdr_addr = memparse(from+11, &from);
434#endif
Andi Kleene2c03882006-02-26 04:18:46 +0100435
Brian Magnusond5176122006-02-27 04:02:04 +0100436#ifdef CONFIG_HOTPLUG_CPU
Andi Kleene2c03882006-02-26 04:18:46 +0100437 else if (!memcmp(from, "additional_cpus=", 16))
438 setup_additional_cpus(from+16);
439#endif
440
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 next_char:
442 c = *(from++);
443 if (!c)
444 break;
445 if (COMMAND_LINE_SIZE <= ++len)
446 break;
447 *(to++) = c;
448 }
akpm@osdl.org69cda7b2006-01-09 20:51:46 -0800449 if (userdef) {
450 printk(KERN_INFO "user-defined physical RAM map:\n");
451 e820_print_map("user");
452 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 *to = '\0';
454 *cmdline_p = command_line;
455}
456
Matt Tolentino2b976902005-06-23 00:08:06 -0700457#ifndef CONFIG_NUMA
Matt Tolentinobbfceef2005-06-23 00:08:07 -0700458static void __init
459contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460{
Matt Tolentinobbfceef2005-06-23 00:08:07 -0700461 unsigned long bootmap_size, bootmap;
462
Matt Tolentinobbfceef2005-06-23 00:08:07 -0700463 bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
464 bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size);
465 if (bootmap == -1L)
466 panic("Cannot find bootmem map of size %ld\n",bootmap_size);
467 bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
468 e820_bootmem_free(NODE_DATA(0), 0, end_pfn << PAGE_SHIFT);
469 reserve_bootmem(bootmap, bootmap_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470}
471#endif
472
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
474struct edd edd;
475#ifdef CONFIG_EDD_MODULE
476EXPORT_SYMBOL(edd);
477#endif
478/**
479 * copy_edd() - Copy the BIOS EDD information
480 * from boot_params into a safe place.
481 *
482 */
483static inline void copy_edd(void)
484{
485 memcpy(edd.mbr_signature, EDD_MBR_SIGNATURE, sizeof(edd.mbr_signature));
486 memcpy(edd.edd_info, EDD_BUF, sizeof(edd.edd_info));
487 edd.mbr_signature_nr = EDD_MBR_SIG_NR;
488 edd.edd_info_nr = EDD_NR;
489}
490#else
491static inline void copy_edd(void)
492{
493}
494#endif
495
496#define EBDA_ADDR_POINTER 0x40E
Andi Kleenac71d122006-05-08 15:17:28 +0200497
498unsigned __initdata ebda_addr;
499unsigned __initdata ebda_size;
500
501static void discover_ebda(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502{
Andi Kleenac71d122006-05-08 15:17:28 +0200503 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 * there is a real-mode segmented pointer pointing to the
505 * 4K EBDA area at 0x40E
506 */
Andi Kleenac71d122006-05-08 15:17:28 +0200507 ebda_addr = *(unsigned short *)EBDA_ADDR_POINTER;
508 ebda_addr <<= 4;
509
510 ebda_size = *(unsigned short *)(unsigned long)ebda_addr;
511
512 /* Round EBDA up to pages */
513 if (ebda_size == 0)
514 ebda_size = 1;
515 ebda_size <<= 10;
516 ebda_size = round_up(ebda_size + (ebda_addr & ~PAGE_MASK), PAGE_SIZE);
517 if (ebda_size > 64*1024)
518 ebda_size = 64*1024;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519}
520
521void __init setup_arch(char **cmdline_p)
522{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 unsigned long kernel_end;
524
525 ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 screen_info = SCREEN_INFO;
527 edid_info = EDID_INFO;
528 saved_video_mode = SAVED_VIDEO_MODE;
529 bootloader_type = LOADER_TYPE;
530
531#ifdef CONFIG_BLK_DEV_RAM
532 rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
533 rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
534 rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
535#endif
536 setup_memory_region();
537 copy_edd();
538
539 if (!MOUNT_ROOT_RDONLY)
540 root_mountflags &= ~MS_RDONLY;
541 init_mm.start_code = (unsigned long) &_text;
542 init_mm.end_code = (unsigned long) &_etext;
543 init_mm.end_data = (unsigned long) &_edata;
544 init_mm.brk = (unsigned long) &_end;
545
546 code_resource.start = virt_to_phys(&_text);
547 code_resource.end = virt_to_phys(&_etext)-1;
548 data_resource.start = virt_to_phys(&_etext);
549 data_resource.end = virt_to_phys(&_edata)-1;
550
551 parse_cmdline_early(cmdline_p);
552
553 early_identify_cpu(&boot_cpu_data);
554
555 /*
556 * partially used pages are not usable - thus
557 * we are rounding upwards:
558 */
559 end_pfn = e820_end_of_ram();
Andi Kleen1f502492006-03-25 16:29:58 +0100560 num_physpages = end_pfn; /* for pfn_valid */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561
562 check_efer();
563
Andi Kleenac71d122006-05-08 15:17:28 +0200564 discover_ebda();
565
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
567
Andi Kleenf2d3efe2006-03-25 16:30:22 +0100568 dmi_scan_machine();
569
Siddha, Suresh Bf6c2e332005-11-05 17:25:53 +0100570 zap_low_mappings(0);
571
Len Brown888ba6c2005-08-24 12:07:20 -0400572#ifdef CONFIG_ACPI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 /*
574 * Initialize the ACPI boot-time table parser (gets the RSDP and SDT).
575 * Call this early for SRAT node setup.
576 */
577 acpi_boot_table_init();
578#endif
579
580#ifdef CONFIG_ACPI_NUMA
581 /*
582 * Parse SRAT to discover nodes.
583 */
584 acpi_numa_init();
585#endif
586
Matt Tolentino2b976902005-06-23 00:08:06 -0700587#ifdef CONFIG_NUMA
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 numa_initmem_init(0, end_pfn);
589#else
Matt Tolentinobbfceef2005-06-23 00:08:07 -0700590 contig_initmem_init(0, end_pfn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591#endif
592
593 /* Reserve direct mapping */
594 reserve_bootmem_generic(table_start << PAGE_SHIFT,
595 (table_end - table_start) << PAGE_SHIFT);
596
597 /* reserve kernel */
598 kernel_end = round_up(__pa_symbol(&_end),PAGE_SIZE);
599 reserve_bootmem_generic(HIGH_MEMORY, kernel_end - HIGH_MEMORY);
600
601 /*
602 * reserve physical page 0 - it's a special BIOS page on many boxes,
603 * enabling clean reboots, SMP operation, laptop functions.
604 */
605 reserve_bootmem_generic(0, PAGE_SIZE);
606
607 /* reserve ebda region */
Andi Kleenac71d122006-05-08 15:17:28 +0200608 if (ebda_addr)
609 reserve_bootmem_generic(ebda_addr, ebda_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610
611#ifdef CONFIG_SMP
612 /*
613 * But first pinch a few for the stack/trampoline stuff
614 * FIXME: Don't need the extra page at 4K, but need to fix
615 * trampoline before removing it. (see the GDT stuff)
616 */
617 reserve_bootmem_generic(PAGE_SIZE, PAGE_SIZE);
618
619 /* Reserve SMP trampoline */
620 reserve_bootmem_generic(SMP_TRAMPOLINE_BASE, PAGE_SIZE);
621#endif
622
623#ifdef CONFIG_ACPI_SLEEP
624 /*
625 * Reserve low memory region for sleep support.
626 */
627 acpi_reserve_bootmem();
628#endif
629#ifdef CONFIG_X86_LOCAL_APIC
630 /*
631 * Find and reserve possible boot-time SMP configuration:
632 */
633 find_smp_config();
634#endif
635#ifdef CONFIG_BLK_DEV_INITRD
636 if (LOADER_TYPE && INITRD_START) {
637 if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) {
638 reserve_bootmem_generic(INITRD_START, INITRD_SIZE);
639 initrd_start =
640 INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
641 initrd_end = initrd_start+INITRD_SIZE;
642 }
643 else {
644 printk(KERN_ERR "initrd extends beyond end of memory "
645 "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
646 (unsigned long)(INITRD_START + INITRD_SIZE),
647 (unsigned long)(end_pfn << PAGE_SHIFT));
648 initrd_start = 0;
649 }
650 }
651#endif
Eric W. Biederman5f5609d2005-06-25 14:58:04 -0700652#ifdef CONFIG_KEXEC
653 if (crashk_res.start != crashk_res.end) {
Amul Shah00212fe2006-06-25 05:49:31 -0700654 reserve_bootmem_generic(crashk_res.start,
Eric W. Biederman5f5609d2005-06-25 14:58:04 -0700655 crashk_res.end - crashk_res.start + 1);
656 }
657#endif
Eric W. Biederman0d317fb2005-08-06 13:47:36 -0600658
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 paging_init();
660
661 check_ioapic();
662
Ashok Raj51f62e12006-03-25 16:29:28 +0100663 /*
664 * set this early, so we dont allocate cpu0
665 * if MADT list doesnt list BSP first
666 * mpparse.c/MP_processor_info() allocates logical cpu numbers.
667 */
668 cpu_set(0, cpu_present_map);
Len Brown888ba6c2005-08-24 12:07:20 -0400669#ifdef CONFIG_ACPI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 /*
671 * Read APIC and some other early information from ACPI tables.
672 */
673 acpi_boot_init();
674#endif
675
Ravikiran Thirumalai05b3cbd2006-01-11 22:45:36 +0100676 init_cpu_to_node();
677
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678#ifdef CONFIG_X86_LOCAL_APIC
679 /*
680 * get boot-time SMP configuration:
681 */
682 if (smp_found_config)
683 get_smp_config();
684 init_apic_mappings();
685#endif
686
687 /*
688 * Request address space for all standard RAM and ROM resources
689 * and also for regions reported as reserved by the e820.
690 */
691 probe_roms();
692 e820_reserve_resources();
693
694 request_resource(&iomem_resource, &video_ram_resource);
695
696 {
697 unsigned i;
698 /* request I/O space for devices used on all i[345]86 PCs */
699 for (i = 0; i < STANDARD_IO_RESOURCES; i++)
700 request_resource(&ioport_resource, &standard_io_resources[i]);
701 }
702
Andi Kleena1e97782005-04-16 15:25:12 -0700703 e820_setup_gap();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704
Andi Kleena813ce42006-06-26 13:57:22 +0200705#ifdef CONFIG_IOMMU
Jon Mason5b7b6442006-02-03 21:51:59 +0100706 iommu_hole_init();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707#endif
708
709#ifdef CONFIG_VT
710#if defined(CONFIG_VGA_CONSOLE)
711 conswitchp = &vga_con;
712#elif defined(CONFIG_DUMMY_CONSOLE)
713 conswitchp = &dummy_con;
714#endif
715#endif
716}
717
Ashok Raje6982c62005-06-25 14:54:58 -0700718static int __cpuinit get_model_name(struct cpuinfo_x86 *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719{
720 unsigned int *v;
721
Andi Kleenebfcaa92005-04-16 15:25:18 -0700722 if (c->extended_cpuid_level < 0x80000004)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 return 0;
724
725 v = (unsigned int *) c->x86_model_id;
726 cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
727 cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
728 cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
729 c->x86_model_id[48] = 0;
730 return 1;
731}
732
733
Ashok Raje6982c62005-06-25 14:54:58 -0700734static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735{
736 unsigned int n, dummy, eax, ebx, ecx, edx;
737
Andi Kleenebfcaa92005-04-16 15:25:18 -0700738 n = c->extended_cpuid_level;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739
740 if (n >= 0x80000005) {
741 cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);
742 printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",
743 edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
744 c->x86_cache_size=(ecx>>24)+(edx>>24);
745 /* On K8 L1 TLB is inclusive, so don't count it */
746 c->x86_tlbsize = 0;
747 }
748
749 if (n >= 0x80000006) {
750 cpuid(0x80000006, &dummy, &ebx, &ecx, &edx);
751 ecx = cpuid_ecx(0x80000006);
752 c->x86_cache_size = ecx >> 16;
753 c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff);
754
755 printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
756 c->x86_cache_size, ecx & 0xFF);
757 }
758
759 if (n >= 0x80000007)
760 cpuid(0x80000007, &dummy, &dummy, &dummy, &c->x86_power);
761 if (n >= 0x80000008) {
762 cpuid(0x80000008, &eax, &dummy, &dummy, &dummy);
763 c->x86_virt_bits = (eax >> 8) & 0xff;
764 c->x86_phys_bits = eax & 0xff;
765 }
766}
767
Andi Kleen3f098c22005-09-12 18:49:24 +0200768#ifdef CONFIG_NUMA
769static int nearby_node(int apicid)
770{
771 int i;
772 for (i = apicid - 1; i >= 0; i--) {
773 int node = apicid_to_node[i];
774 if (node != NUMA_NO_NODE && node_online(node))
775 return node;
776 }
777 for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
778 int node = apicid_to_node[i];
779 if (node != NUMA_NO_NODE && node_online(node))
780 return node;
781 }
782 return first_node(node_online_map); /* Shouldn't happen */
783}
784#endif
785
Andi Kleen63518642005-04-16 15:25:16 -0700786/*
787 * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
788 * Assumes number of cores is a power of two.
789 */
790static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
791{
792#ifdef CONFIG_SMP
Andi Kleen29422832005-05-16 21:53:26 -0700793 int cpu = smp_processor_id();
Andi Kleenb41e2932005-05-20 14:27:55 -0700794 unsigned bits;
Andi Kleen3f098c22005-09-12 18:49:24 +0200795#ifdef CONFIG_NUMA
796 int node = 0;
Ravikiran G Thirumalai60c1bc82006-03-25 16:30:04 +0100797 unsigned apicid = hard_smp_processor_id();
Andi Kleen3f098c22005-09-12 18:49:24 +0200798#endif
Andi Kleenfaee9a52006-06-26 13:56:10 +0200799 unsigned ecx = cpuid_ecx(0x80000008);
Andi Kleenb41e2932005-05-20 14:27:55 -0700800
Andi Kleenfaee9a52006-06-26 13:56:10 +0200801 c->x86_max_cores = (ecx & 0xff) + 1;
802
803 /* CPU telling us the core id bits shift? */
804 bits = (ecx >> 12) & 0xF;
805
806 /* Otherwise recompute */
807 if (bits == 0) {
808 while ((1 << bits) < c->x86_max_cores)
809 bits++;
810 }
Andi Kleenb41e2932005-05-20 14:27:55 -0700811
812 /* Low order bits define the core id (index of core in socket) */
813 cpu_core_id[cpu] = phys_proc_id[cpu] & ((1 << bits)-1);
814 /* Convert the APIC ID into the socket ID */
Ravikiran G Thirumalai60c1bc82006-03-25 16:30:04 +0100815 phys_proc_id[cpu] = phys_pkg_id(bits);
Andi Kleen63518642005-04-16 15:25:16 -0700816
817#ifdef CONFIG_NUMA
Andi Kleen3f098c22005-09-12 18:49:24 +0200818 node = phys_proc_id[cpu];
819 if (apicid_to_node[apicid] != NUMA_NO_NODE)
820 node = apicid_to_node[apicid];
821 if (!node_online(node)) {
822 /* Two possibilities here:
823 - The CPU is missing memory and no node was created.
824 In that case try picking one from a nearby CPU
825 - The APIC IDs differ from the HyperTransport node IDs
826 which the K8 northbridge parsing fills in.
827 Assume they are all increased by a constant offset,
828 but in the same order as the HT nodeids.
829 If that doesn't result in a usable node fall back to the
830 path for the previous case. */
831 int ht_nodeid = apicid - (phys_proc_id[0] << bits);
832 if (ht_nodeid >= 0 &&
833 apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
834 node = apicid_to_node[ht_nodeid];
835 /* Pick a nearby node */
836 if (!node_online(node))
837 node = nearby_node(apicid);
838 }
Andi Kleen69d81fc2005-11-05 17:25:53 +0100839 numa_set_node(cpu, node);
Andi Kleena1586082005-05-16 21:53:21 -0700840
Andi Kleen77d910f2006-03-25 16:29:34 +0100841 printk(KERN_INFO "CPU %d/%x(%d) -> Node %d -> Core %d\n",
842 cpu, apicid, c->x86_max_cores, node, cpu_core_id[cpu]);
Andi Kleen3f098c22005-09-12 18:49:24 +0200843#endif
Andi Kleen63518642005-04-16 15:25:16 -0700844#endif
845}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
847static int __init init_amd(struct cpuinfo_x86 *c)
848{
849 int r;
Andi Kleen7bcd3f32006-02-03 21:51:02 +0100850 unsigned level;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851
Linus Torvaldsbc5e8fd2005-09-17 15:41:04 -0700852#ifdef CONFIG_SMP
853 unsigned long value;
854
Andi Kleen7d318d72005-09-29 22:05:55 +0200855 /*
856 * Disable TLB flush filter by setting HWCR.FFDIS on K8
857 * bit 6 of msr C001_0015
858 *
859 * Errata 63 for SH-B3 steppings
860 * Errata 122 for all steppings (F+ have it disabled by default)
861 */
862 if (c->x86 == 15) {
863 rdmsrl(MSR_K8_HWCR, value);
864 value |= 1 << 6;
865 wrmsrl(MSR_K8_HWCR, value);
866 }
Linus Torvaldsbc5e8fd2005-09-17 15:41:04 -0700867#endif
868
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
870 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
871 clear_bit(0*32+31, &c->x86_capability);
872
Andi Kleen7bcd3f32006-02-03 21:51:02 +0100873 /* On C+ stepping K8 rep microcode works well for copy/memset */
874 level = cpuid_eax(1);
875 if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58))
876 set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
877
Andi Kleen18bd0572006-04-20 02:36:45 +0200878 /* Enable workaround for FXSAVE leak */
879 if (c->x86 >= 6)
880 set_bit(X86_FEATURE_FXSAVE_LEAK, &c->x86_capability);
881
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 r = get_model_name(c);
883 if (!r) {
884 switch (c->x86) {
885 case 15:
886 /* Should distinguish Models here, but this is only
887 a fallback anyways. */
888 strcpy(c->x86_model_id, "Hammer");
889 break;
890 }
891 }
892 display_cacheinfo(c);
893
Andi Kleen130951c2006-01-11 22:42:02 +0100894 /* c->x86_power is 8000_0007 edx. Bit 8 is constant TSC */
895 if (c->x86_power & (1<<8))
896 set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
897
Andi Kleenfaee9a52006-06-26 13:56:10 +0200898 /* Multi core CPU? */
899 if (c->extended_cpuid_level >= 0x80000008)
Andi Kleen63518642005-04-16 15:25:16 -0700900 amd_detect_cmp(c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
Andi Kleen240cd6a2006-06-26 13:56:13 +0200902 /* Fix cpuid4 emulation for more */
903 num_cache_leaves = 3;
904
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 return r;
906}
907
Ashok Raje6982c62005-06-25 14:54:58 -0700908static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909{
910#ifdef CONFIG_SMP
911 u32 eax, ebx, ecx, edx;
Siddha, Suresh B94605ef2005-11-05 17:25:54 +0100912 int index_msb, core_bits;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 int cpu = smp_processor_id();
Siddha, Suresh B94605ef2005-11-05 17:25:54 +0100914
915 cpuid(1, &eax, &ebx, &ecx, &edx);
916
Siddha, Suresh B94605ef2005-11-05 17:25:54 +0100917
Andi Kleen63518642005-04-16 15:25:16 -0700918 if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 return;
920
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 smp_num_siblings = (ebx & 0xff0000) >> 16;
Siddha, Suresh B94605ef2005-11-05 17:25:54 +0100922
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 if (smp_num_siblings == 1) {
924 printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
Siddha, Suresh B94605ef2005-11-05 17:25:54 +0100925 } else if (smp_num_siblings > 1 ) {
926
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 if (smp_num_siblings > NR_CPUS) {
928 printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
929 smp_num_siblings = 1;
930 return;
931 }
Siddha, Suresh B94605ef2005-11-05 17:25:54 +0100932
933 index_msb = get_count_order(smp_num_siblings);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 phys_proc_id[cpu] = phys_pkg_id(index_msb);
Siddha, Suresh B94605ef2005-11-05 17:25:54 +0100935
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
937 phys_proc_id[cpu]);
Andi Kleen3dd9d512005-04-16 15:25:15 -0700938
Siddha, Suresh B94605ef2005-11-05 17:25:54 +0100939 smp_num_siblings = smp_num_siblings / c->x86_max_cores;
Andi Kleen3dd9d512005-04-16 15:25:15 -0700940
Siddha, Suresh B94605ef2005-11-05 17:25:54 +0100941 index_msb = get_count_order(smp_num_siblings) ;
Andi Kleen3dd9d512005-04-16 15:25:15 -0700942
Siddha, Suresh B94605ef2005-11-05 17:25:54 +0100943 core_bits = get_count_order(c->x86_max_cores);
Andi Kleen3dd9d512005-04-16 15:25:15 -0700944
Siddha, Suresh B94605ef2005-11-05 17:25:54 +0100945 cpu_core_id[cpu] = phys_pkg_id(index_msb) &
946 ((1 << core_bits) - 1);
947
948 if (c->x86_max_cores > 1)
Andi Kleen3dd9d512005-04-16 15:25:15 -0700949 printk(KERN_INFO "CPU: Processor Core ID: %d\n",
950 cpu_core_id[cpu]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 }
952#endif
953}
954
Andi Kleen3dd9d512005-04-16 15:25:15 -0700955/*
956 * find out the number of processor cores on the die
957 */
Ashok Raje6982c62005-06-25 14:54:58 -0700958static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c)
Andi Kleen3dd9d512005-04-16 15:25:15 -0700959{
960 unsigned int eax;
961
962 if (c->cpuid_level < 4)
963 return 1;
964
965 __asm__("cpuid"
966 : "=a" (eax)
967 : "0" (4), "c" (0)
968 : "bx", "dx");
969
970 if (eax & 0x1f)
971 return ((eax >> 26) + 1);
972 else
973 return 1;
974}
975
Andi Kleendf0cc262005-09-12 18:49:24 +0200976static void srat_detect_node(void)
977{
978#ifdef CONFIG_NUMA
Ravikiran G Thirumalaiddea7be2005-10-03 10:36:28 -0700979 unsigned node;
Andi Kleendf0cc262005-09-12 18:49:24 +0200980 int cpu = smp_processor_id();
981
982 /* Don't do the funky fallback heuristics the AMD version employs
983 for now. */
Ravikiran G Thirumalaiddea7be2005-10-03 10:36:28 -0700984 node = apicid_to_node[hard_smp_processor_id()];
Andi Kleendf0cc262005-09-12 18:49:24 +0200985 if (node == NUMA_NO_NODE)
Daniel Yeisley0d015322006-05-30 22:47:57 +0200986 node = first_node(node_online_map);
Andi Kleen69d81fc2005-11-05 17:25:53 +0100987 numa_set_node(cpu, node);
Andi Kleendf0cc262005-09-12 18:49:24 +0200988
989 if (acpi_numa > 0)
990 printk(KERN_INFO "CPU %d -> Node %d\n", cpu, node);
991#endif
992}
993
Ashok Raje6982c62005-06-25 14:54:58 -0700994static void __cpuinit init_intel(struct cpuinfo_x86 *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995{
996 /* Cache sizes */
997 unsigned n;
998
999 init_intel_cacheinfo(c);
Andi Kleenebfcaa92005-04-16 15:25:18 -07001000 n = c->extended_cpuid_level;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 if (n >= 0x80000008) {
1002 unsigned eax = cpuid_eax(0x80000008);
1003 c->x86_virt_bits = (eax >> 8) & 0xff;
1004 c->x86_phys_bits = eax & 0xff;
Shaohua Liaf9c1422005-11-05 17:25:54 +01001005 /* CPUID workaround for Intel 0F34 CPU */
1006 if (c->x86_vendor == X86_VENDOR_INTEL &&
1007 c->x86 == 0xF && c->x86_model == 0x3 &&
1008 c->x86_mask == 0x4)
1009 c->x86_phys_bits = 36;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 }
1011
1012 if (c->x86 == 15)
1013 c->x86_cache_alignment = c->x86_clflush_size * 2;
Andi Kleen39b3a792006-01-11 22:42:45 +01001014 if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
1015 (c->x86 == 0x6 && c->x86_model >= 0x0e))
Andi Kleenc29601e2005-04-16 15:25:05 -07001016 set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
Andi Kleenc818a182006-01-11 22:45:24 +01001017 set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
Siddha, Suresh B94605ef2005-11-05 17:25:54 +01001018 c->x86_max_cores = intel_num_cpu_cores(c);
Andi Kleendf0cc262005-09-12 18:49:24 +02001019
1020 srat_detect_node();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021}
1022
Adrian Bunk672289e2005-09-10 00:27:21 -07001023static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024{
1025 char *v = c->x86_vendor_id;
1026
1027 if (!strcmp(v, "AuthenticAMD"))
1028 c->x86_vendor = X86_VENDOR_AMD;
1029 else if (!strcmp(v, "GenuineIntel"))
1030 c->x86_vendor = X86_VENDOR_INTEL;
1031 else
1032 c->x86_vendor = X86_VENDOR_UNKNOWN;
1033}
1034
1035struct cpu_model_info {
1036 int vendor;
1037 int family;
1038 char *model_names[16];
1039};
1040
1041/* Do some early cpuid on the boot CPU to get some parameter that are
1042 needed before check_bugs. Everything advanced is in identify_cpu
1043 below. */
Ashok Raje6982c62005-06-25 14:54:58 -07001044void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045{
1046 u32 tfms;
1047
1048 c->loops_per_jiffy = loops_per_jiffy;
1049 c->x86_cache_size = -1;
1050 c->x86_vendor = X86_VENDOR_UNKNOWN;
1051 c->x86_model = c->x86_mask = 0; /* So far unknown... */
1052 c->x86_vendor_id[0] = '\0'; /* Unset */
1053 c->x86_model_id[0] = '\0'; /* Unset */
1054 c->x86_clflush_size = 64;
1055 c->x86_cache_alignment = c->x86_clflush_size;
Siddha, Suresh B94605ef2005-11-05 17:25:54 +01001056 c->x86_max_cores = 1;
Andi Kleenebfcaa92005-04-16 15:25:18 -07001057 c->extended_cpuid_level = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 memset(&c->x86_capability, 0, sizeof c->x86_capability);
1059
1060 /* Get vendor name */
1061 cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
1062 (unsigned int *)&c->x86_vendor_id[0],
1063 (unsigned int *)&c->x86_vendor_id[8],
1064 (unsigned int *)&c->x86_vendor_id[4]);
1065
1066 get_cpu_vendor(c);
1067
1068 /* Initialize the standard set of capabilities */
1069 /* Note that the vendor-specific code below might override */
1070
1071 /* Intel-defined flags: level 0x00000001 */
1072 if (c->cpuid_level >= 0x00000001) {
1073 __u32 misc;
1074 cpuid(0x00000001, &tfms, &misc, &c->x86_capability[4],
1075 &c->x86_capability[0]);
1076 c->x86 = (tfms >> 8) & 0xf;
1077 c->x86_model = (tfms >> 4) & 0xf;
1078 c->x86_mask = tfms & 0xf;
Suresh Siddhaf5f786d2005-11-05 17:25:53 +01001079 if (c->x86 == 0xf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 c->x86 += (tfms >> 20) & 0xff;
Suresh Siddhaf5f786d2005-11-05 17:25:53 +01001081 if (c->x86 >= 0x6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 c->x86_model += ((tfms >> 16) & 0xF) << 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 if (c->x86_capability[0] & (1<<19))
1084 c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 } else {
1086 /* Have CPUID level 0 only - unheard of */
1087 c->x86 = 4;
1088 }
Andi Kleena1586082005-05-16 21:53:21 -07001089
1090#ifdef CONFIG_SMP
Andi Kleenb41e2932005-05-20 14:27:55 -07001091 phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
Andi Kleena1586082005-05-16 21:53:21 -07001092#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093}
1094
1095/*
1096 * This does the hard work of actually picking apart the CPU stuff...
1097 */
Ashok Raje6982c62005-06-25 14:54:58 -07001098void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099{
1100 int i;
1101 u32 xlvl;
1102
1103 early_identify_cpu(c);
1104
1105 /* AMD-defined flags: level 0x80000001 */
1106 xlvl = cpuid_eax(0x80000000);
Andi Kleenebfcaa92005-04-16 15:25:18 -07001107 c->extended_cpuid_level = xlvl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 if ((xlvl & 0xffff0000) == 0x80000000) {
1109 if (xlvl >= 0x80000001) {
1110 c->x86_capability[1] = cpuid_edx(0x80000001);
H. Peter Anvin5b7abc62005-05-01 08:58:49 -07001111 c->x86_capability[6] = cpuid_ecx(0x80000001);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 }
1113 if (xlvl >= 0x80000004)
1114 get_model_name(c); /* Default name */
1115 }
1116
1117 /* Transmeta-defined flags: level 0x80860001 */
1118 xlvl = cpuid_eax(0x80860000);
1119 if ((xlvl & 0xffff0000) == 0x80860000) {
1120 /* Don't set x86_cpuid_level here for now to not confuse. */
1121 if (xlvl >= 0x80860001)
1122 c->x86_capability[2] = cpuid_edx(0x80860001);
1123 }
1124
Siddha, Suresh B1e9f28f2006-03-27 01:15:22 -08001125 c->apicid = phys_pkg_id(0);
1126
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 /*
1128 * Vendor-specific initialization. In this section we
1129 * canonicalize the feature flags, meaning if there are
1130 * features a certain CPU supports which CPUID doesn't
1131 * tell us, CPUID claiming incorrect flags, or other bugs,
1132 * we handle them here.
1133 *
1134 * At the end of this section, c->x86_capability better
1135 * indicate the features this CPU genuinely supports!
1136 */
1137 switch (c->x86_vendor) {
1138 case X86_VENDOR_AMD:
1139 init_amd(c);
1140 break;
1141
1142 case X86_VENDOR_INTEL:
1143 init_intel(c);
1144 break;
1145
1146 case X86_VENDOR_UNKNOWN:
1147 default:
1148 display_cacheinfo(c);
1149 break;
1150 }
1151
1152 select_idle_routine(c);
1153 detect_ht(c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
1155 /*
1156 * On SMP, boot_cpu_data holds the common feature set between
1157 * all CPUs; so make sure that we indicate which features are
1158 * common between the CPUs. The first time this routine gets
1159 * executed, c == &boot_cpu_data.
1160 */
1161 if (c != &boot_cpu_data) {
1162 /* AND the already accumulated flags with these */
1163 for (i = 0 ; i < NCAPINTS ; i++)
1164 boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
1165 }
1166
1167#ifdef CONFIG_X86_MCE
1168 mcheck_init(c);
1169#endif
Shaohua Li3b520b22005-07-07 17:56:38 -07001170 if (c == &boot_cpu_data)
1171 mtrr_bp_init();
1172 else
1173 mtrr_ap_init();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174#ifdef CONFIG_NUMA
Andi Kleen3019e8e2005-07-28 21:15:28 -07001175 numa_add_cpu(smp_processor_id());
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176#endif
1177}
1178
1179
Ashok Raje6982c62005-06-25 14:54:58 -07001180void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181{
1182 if (c->x86_model_id[0])
1183 printk("%s", c->x86_model_id);
1184
1185 if (c->x86_mask || c->cpuid_level >= 0)
1186 printk(" stepping %02x\n", c->x86_mask);
1187 else
1188 printk("\n");
1189}
1190
1191/*
1192 * Get CPU information for use by the procfs.
1193 */
1194
1195static int show_cpuinfo(struct seq_file *m, void *v)
1196{
1197 struct cpuinfo_x86 *c = v;
1198
1199 /*
1200 * These flag bits must match the definitions in <asm/cpufeature.h>.
1201 * NULL means this bit is undefined or reserved; either way it doesn't
1202 * have meaning as far as Linux is concerned. Note that it's important
1203 * to realize there is a difference between this table and CPUID -- if
1204 * applications want to get the raw CPUID data, they should access
1205 * /dev/cpu/<cpu_nr>/cpuid instead.
1206 */
1207 static char *x86_cap_flags[] = {
1208 /* Intel-defined */
1209 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
1210 "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
1211 "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
1212 "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL,
1213
1214 /* AMD-defined */
Zwane Mwaikambo3c3b73b2005-05-01 08:58:51 -07001215 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
1217 NULL, NULL, NULL, NULL, "nx", NULL, "mmxext", NULL,
Andi Kleen3f98bc42006-01-11 22:42:51 +01001218 NULL, "fxsr_opt", "rdtscp", NULL, NULL, "lm", "3dnowext", "3dnow",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
1220 /* Transmeta-defined */
1221 "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
1222 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1223 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1224 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1225
1226 /* Other (Linux-defined) */
Andi Kleen622dcaf2005-05-16 21:53:26 -07001227 "cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL,
Andi Kleenc29601e2005-04-16 15:25:05 -07001228 "constant_tsc", NULL, NULL,
Gerd Hoffmannd167a512006-06-26 13:56:16 +02001229 "up", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1231 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1232
1233 /* Intel-defined (#2) */
Andi Kleen9d95dd82006-03-25 16:31:22 +01001234 "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 "tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL,
1236 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1237 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1238
H. Peter Anvin5b7abc62005-05-01 08:58:49 -07001239 /* VIA/Cyrix/Centaur-defined */
1240 NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
1241 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1242 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1243 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1244
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 /* AMD-defined (#2) */
Andi Kleen3f98bc42006-01-11 22:42:51 +01001246 "lahf_lm", "cmp_legacy", "svm", NULL, "cr8_legacy", NULL, NULL, NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1248 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
H. Peter Anvin5b7abc62005-05-01 08:58:49 -07001249 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 };
1251 static char *x86_power_flags[] = {
1252 "ts", /* temperature sensor */
1253 "fid", /* frequency id control */
1254 "vid", /* voltage id control */
1255 "ttp", /* thermal trip */
1256 "tm",
Andi Kleen3f98bc42006-01-11 22:42:51 +01001257 "stc",
1258 NULL,
Andi Kleen39b3a792006-01-11 22:42:45 +01001259 /* nothing */ /* constant_tsc - moved to flags */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 };
1261
1262
1263#ifdef CONFIG_SMP
1264 if (!cpu_online(c-cpu_data))
1265 return 0;
1266#endif
1267
1268 seq_printf(m,"processor\t: %u\n"
1269 "vendor_id\t: %s\n"
1270 "cpu family\t: %d\n"
1271 "model\t\t: %d\n"
1272 "model name\t: %s\n",
1273 (unsigned)(c-cpu_data),
1274 c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
1275 c->x86,
1276 (int)c->x86_model,
1277 c->x86_model_id[0] ? c->x86_model_id : "unknown");
1278
1279 if (c->x86_mask || c->cpuid_level >= 0)
1280 seq_printf(m, "stepping\t: %d\n", c->x86_mask);
1281 else
1282 seq_printf(m, "stepping\t: unknown\n");
1283
1284 if (cpu_has(c,X86_FEATURE_TSC)) {
Venkatesh Pallipadi95235ca2005-12-02 10:43:20 -08001285 unsigned int freq = cpufreq_quick_get((unsigned)(c-cpu_data));
1286 if (!freq)
1287 freq = cpu_khz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
Venkatesh Pallipadi95235ca2005-12-02 10:43:20 -08001289 freq / 1000, (freq % 1000));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 }
1291
1292 /* Cache size */
1293 if (c->x86_cache_size >= 0)
1294 seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
1295
1296#ifdef CONFIG_SMP
Siddha, Suresh B94605ef2005-11-05 17:25:54 +01001297 if (smp_num_siblings * c->x86_max_cores > 1) {
Andi Kleendb468682005-04-16 15:24:51 -07001298 int cpu = c - cpu_data;
1299 seq_printf(m, "physical id\t: %d\n", phys_proc_id[cpu]);
Siddha, Suresh B94605ef2005-11-05 17:25:54 +01001300 seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[cpu]));
Siddha, Suresh Bd31ddaa2005-04-16 15:25:20 -07001301 seq_printf(m, "core id\t\t: %d\n", cpu_core_id[cpu]);
Siddha, Suresh B94605ef2005-11-05 17:25:54 +01001302 seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
Andi Kleendb468682005-04-16 15:24:51 -07001303 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304#endif
1305
1306 seq_printf(m,
1307 "fpu\t\t: yes\n"
1308 "fpu_exception\t: yes\n"
1309 "cpuid level\t: %d\n"
1310 "wp\t\t: yes\n"
1311 "flags\t\t:",
1312 c->cpuid_level);
1313
1314 {
1315 int i;
1316 for ( i = 0 ; i < 32*NCAPINTS ; i++ )
Akinobu Mita3d1712c2006-03-24 03:15:11 -08001317 if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 seq_printf(m, " %s", x86_cap_flags[i]);
1319 }
1320
1321 seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
1322 c->loops_per_jiffy/(500000/HZ),
1323 (c->loops_per_jiffy/(5000/HZ)) % 100);
1324
1325 if (c->x86_tlbsize > 0)
1326 seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize);
1327 seq_printf(m, "clflush size\t: %d\n", c->x86_clflush_size);
1328 seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment);
1329
1330 seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n",
1331 c->x86_phys_bits, c->x86_virt_bits);
1332
1333 seq_printf(m, "power management:");
1334 {
1335 unsigned i;
1336 for (i = 0; i < 32; i++)
1337 if (c->x86_power & (1 << i)) {
Andi Kleen3f98bc42006-01-11 22:42:51 +01001338 if (i < ARRAY_SIZE(x86_power_flags) &&
1339 x86_power_flags[i])
1340 seq_printf(m, "%s%s",
1341 x86_power_flags[i][0]?" ":"",
1342 x86_power_flags[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 else
1344 seq_printf(m, " [%d]", i);
1345 }
1346 }
Andi Kleen3dd9d512005-04-16 15:25:15 -07001347
Siddha, Suresh Bd31ddaa2005-04-16 15:25:20 -07001348 seq_printf(m, "\n\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 return 0;
1351}
1352
1353static void *c_start(struct seq_file *m, loff_t *pos)
1354{
1355 return *pos < NR_CPUS ? cpu_data + *pos : NULL;
1356}
1357
1358static void *c_next(struct seq_file *m, void *v, loff_t *pos)
1359{
1360 ++*pos;
1361 return c_start(m, pos);
1362}
1363
1364static void c_stop(struct seq_file *m, void *v)
1365{
1366}
1367
1368struct seq_operations cpuinfo_op = {
1369 .start =c_start,
1370 .next = c_next,
1371 .stop = c_stop,
1372 .show = show_cpuinfo,
1373};
Andi Kleene9928672006-01-11 22:43:33 +01001374
Mikael Pettersson160bd182006-05-01 12:16:18 -07001375#ifdef CONFIG_INPUT_PCSPKR
1376#include <linux/platform_device.h>
1377static __init int add_pcspkr(void)
1378{
1379 struct platform_device *pd;
1380 int ret;
1381
1382 pd = platform_device_alloc("pcspkr", -1);
1383 if (!pd)
1384 return -ENOMEM;
1385
1386 ret = platform_device_add(pd);
1387 if (ret)
1388 platform_device_put(pd);
1389
1390 return ret;
1391}
1392device_initcall(add_pcspkr);
1393#endif