setup_32.c 25.3 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 *  Copyright (C) 1995  Linus Torvalds
 *
 *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
 *
 *  Memory region support
 *	David Parsons <orc@pell.chi.il.us>, July-August 1999
 *
 *  Added E820 sanitization routine (removes overlapping memory regions);
 *  Brian Moyle <bmoyle@mvista.com>, February 2001
 *
 * Moved CPU detection code to cpu/${cpu}.c
 *    Patrick Mochel <mochel@osdl.org>, March 2002
 *
 *  Provisions for empty E820 memory regions (reported by certain BIOSes).
 *  Alex Achenbach <xela@slit.de>, December 2002.
 *
 */

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

#include <linux/sched.h>
#include <linux/mm.h>
26
#include <linux/mmzone.h>
27
#include <linux/screen_info.h>
L
Linus Torvalds 已提交
28 29 30 31 32 33 34 35 36 37 38 39 40 41
#include <linux/ioport.h>
#include <linux/acpi.h>
#include <linux/apm_bios.h>
#include <linux/initrd.h>
#include <linux/bootmem.h>
#include <linux/seq_file.h>
#include <linux/console.h>
#include <linux/mca.h>
#include <linux/root_dev.h>
#include <linux/highmem.h>
#include <linux/module.h>
#include <linux/efi.h>
#include <linux/init.h>
#include <linux/edd.h>
42
#include <linux/iscsi_ibft.h>
L
Linus Torvalds 已提交
43
#include <linux/nodemask.h>
44
#include <linux/kexec.h>
45
#include <linux/crash_dump.h>
46
#include <linux/dmi.h>
D
Dave Hansen 已提交
47
#include <linux/pfn.h>
48
#include <linux/pci.h>
49
#include <linux/init_ohci1394_dma.h>
50
#include <linux/kvm_para.h>
51

L
Linus Torvalds 已提交
52
#include <video/edid.h>
53

54
#include <asm/mtrr.h>
55
#include <asm/apic.h>
L
Linus Torvalds 已提交
56 57
#include <asm/e820.h>
#include <asm/mpspec.h>
58
#include <asm/mmzone.h>
L
Linus Torvalds 已提交
59 60 61
#include <asm/setup.h>
#include <asm/arch_hooks.h>
#include <asm/sections.h>
62
#include <asm/dmi.h>
L
Linus Torvalds 已提交
63 64 65
#include <asm/io_apic.h>
#include <asm/ist.h>
#include <asm/io.h>
66
#include <asm/vmi.h>
67
#include <setup_arch.h>
68
#include <asm/bios_ebda.h>
B
Bernhard Walle 已提交
69
#include <asm/cacheflush.h>
70
#include <asm/processor.h>
71
#include <asm/efi.h>
Y
Yinghai Lu 已提交
72
#include <asm/bugs.h>
L
Linus Torvalds 已提交
73 74 75 76

/* This value is set up by the early boot code to point to the value
   immediately after the boot time page tables.  It contains a *physical*
   address, and must not be in the .bss segment! */
77
unsigned long init_pg_tables_start __initdata = ~0UL;
L
Linus Torvalds 已提交
78 79 80 81 82
unsigned long init_pg_tables_end __initdata = ~0UL;

/*
 * Machine setup..
 */
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 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
static struct resource data_resource = {
	.name	= "Kernel data",
	.start	= 0,
	.end	= 0,
	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
};

static struct resource code_resource = {
	.name	= "Kernel code",
	.start	= 0,
	.end	= 0,
	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
};

static struct resource bss_resource = {
	.name	= "Kernel bss",
	.start	= 0,
	.end	= 0,
	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
};

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

static struct resource standard_io_resources[] = { {
	.name	= "dma1",
	.start	= 0x0000,
	.end	= 0x001f,
	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
}, {
	.name	= "pic1",
	.start	= 0x0020,
	.end	= 0x0021,
	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
}, {
	.name   = "timer0",
	.start	= 0x0040,
	.end    = 0x0043,
	.flags  = IORESOURCE_BUSY | IORESOURCE_IO
}, {
	.name   = "timer1",
	.start  = 0x0050,
	.end    = 0x0053,
	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
}, {
	.name	= "keyboard",
	.start	= 0x0060,
134 135 136 137 138 139
	.end	= 0x0060,
	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
}, {
	.name	= "keyboard",
	.start	= 0x0064,
	.end	= 0x0064,
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
}, {
	.name	= "dma page reg",
	.start	= 0x0080,
	.end	= 0x008f,
	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
}, {
	.name	= "pic2",
	.start	= 0x00a0,
	.end	= 0x00a1,
	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
}, {
	.name	= "dma2",
	.start	= 0x00c0,
	.end	= 0x00df,
	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
}, {
	.name	= "fpu",
	.start	= 0x00f0,
	.end	= 0x00ff,
	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
} };
L
Linus Torvalds 已提交
162 163

/* cpu data as detected by the assembly code in head.S */
164
struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
L
Linus Torvalds 已提交
165
/* common cpu data for all cpus */
166
struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
167
EXPORT_SYMBOL(boot_cpu_data);
L
Linus Torvalds 已提交
168

169 170
unsigned int def_to_bigsmp;

171
#ifndef CONFIG_X86_PAE
L
Linus Torvalds 已提交
172
unsigned long mmu_cr4_features;
173 174 175
#else
unsigned long mmu_cr4_features = X86_CR4_PAE;
#endif
L
Linus Torvalds 已提交
176 177 178 179 180 181 182 183 184 185 186 187

/* for MCA, but anyone else can use it if they want */
unsigned int machine_id;
unsigned int machine_submodel_id;
unsigned int BIOS_revision;

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

/* user-defined highmem size */
static unsigned int highmem_pages = -1;

188 189 190 191 192 193
/*
 * Early DMI memory
 */
int dmi_alloc_index;
char dmi_alloc_data[DMI_MAX_DATA];

L
Linus Torvalds 已提交
194 195 196 197
/*
 * Setup options
 */
struct screen_info screen_info;
198
EXPORT_SYMBOL(screen_info);
L
Linus Torvalds 已提交
199
struct apm_info apm_info;
200
EXPORT_SYMBOL(apm_info);
L
Linus Torvalds 已提交
201
struct edid_info edid_info;
202
EXPORT_SYMBOL_GPL(edid_info);
L
Linus Torvalds 已提交
203
struct ist_info ist_info;
204 205 206 207
#if defined(CONFIG_X86_SPEEDSTEP_SMI) || \
	defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
EXPORT_SYMBOL(ist_info);
#endif
L
Linus Torvalds 已提交
208 209 210 211

extern void early_cpu_init(void);
extern int root_mountflags;

212
unsigned long saved_video_mode;
L
Linus Torvalds 已提交
213

214
#define RAMDISK_IMAGE_START_MASK	0x07FF
L
Linus Torvalds 已提交
215
#define RAMDISK_PROMPT_FLAG		0x8000
216
#define RAMDISK_LOAD_FLAG		0x4000
L
Linus Torvalds 已提交
217

218
static char __initdata command_line[COMMAND_LINE_SIZE];
L
Linus Torvalds 已提交
219

220
#ifndef CONFIG_DEBUG_BOOT_PARAMS
221
struct boot_params __initdata boot_params;
222 223 224
#else
struct boot_params boot_params;
#endif
L
Linus Torvalds 已提交
225 226 227 228 229 230 231 232 233 234 235 236 237

#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)
{
238 239 240 241 242
     memcpy(edd.mbr_signature, boot_params.edd_mbr_sig_buffer,
	    sizeof(edd.mbr_signature));
     memcpy(edd.edd_info, boot_params.eddbuf, sizeof(edd.edd_info));
     edd.mbr_signature_nr = boot_params.edd_mbr_sig_buf_entries;
     edd.edd_info_nr = boot_params.eddbuf_entries;
L
Linus Torvalds 已提交
243 244 245 246 247 248 249
}
#else
static inline void copy_edd(void)
{
}
#endif

250 251 252 253 254 255 256 257
#ifdef CONFIG_PROC_VMCORE
/* elfcorehdr= specifies the location of elf core header
 * stored by the crashed kernel.
 */
static int __init parse_elfcorehdr(char *arg)
{
	if (!arg)
		return -EINVAL;
258

259 260 261 262 263
	elfcorehdr_addr = memparse(arg, &arg);
	return 0;
}
early_param("elfcorehdr", parse_elfcorehdr);
#endif /* CONFIG_PROC_VMCORE */
L
Linus Torvalds 已提交
264

265 266 267 268 269 270 271 272 273
/*
 * highmem=size forces highmem to be exactly 'size' bytes.
 * This works even on boxes that have no highmem otherwise.
 * This also works to reduce highmem size on bigger boxes.
 */
static int __init parse_highmem(char *arg)
{
	if (!arg)
		return -EINVAL;
274

275 276 277 278
	highmem_pages = memparse(arg, &arg) >> PAGE_SHIFT;
	return 0;
}
early_param("highmem", parse_highmem);
279

280 281 282 283 284 285 286 287 288
/*
 * vmalloc=size forces the vmalloc area to be exactly 'size'
 * bytes. This can be used to increase (or decrease) the
 * vmalloc area - the default is 128m.
 */
static int __init parse_vmalloc(char *arg)
{
	if (!arg)
		return -EINVAL;
289

290 291
	__VMALLOC_RESERVE = memparse(arg, &arg);
	return 0;
L
Linus Torvalds 已提交
292
}
293
early_param("vmalloc", parse_vmalloc);
L
Linus Torvalds 已提交
294

295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
/*
 * reservetop=size reserves a hole at the top of the kernel address space which
 * a hypervisor can load into later.  Needed for dynamically loaded hypervisors,
 * so relocating the fixmap can be done before paging initialization.
 */
static int __init parse_reservetop(char *arg)
{
	unsigned long address;

	if (!arg)
		return -EINVAL;

	address = memparse(arg, &arg);
	reserve_top_address(address);
	return 0;
}
early_param("reservetop", parse_reservetop);

L
Linus Torvalds 已提交
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
/*
 * Determine low and high memory ranges:
 */
unsigned long __init find_max_low_pfn(void)
{
	unsigned long max_low_pfn;

	max_low_pfn = max_pfn;
	if (max_low_pfn > MAXMEM_PFN) {
		if (highmem_pages == -1)
			highmem_pages = max_pfn - MAXMEM_PFN;
		if (highmem_pages + MAXMEM_PFN < max_pfn)
			max_pfn = MAXMEM_PFN + highmem_pages;
		if (highmem_pages + MAXMEM_PFN > max_pfn) {
			printk("only %luMB highmem pages available, ignoring highmem size of %uMB.\n", pages_to_mb(max_pfn - MAXMEM_PFN), pages_to_mb(highmem_pages));
			highmem_pages = 0;
		}
		max_low_pfn = MAXMEM_PFN;
#ifndef CONFIG_HIGHMEM
		/* Maximum memory usable is what is directly addressable */
		printk(KERN_WARNING "Warning only %ldMB will be used.\n",
					MAXMEM>>20);
		if (max_pfn > MAX_NONPAE_PFN)
336
			printk(KERN_WARNING "Use a HIGHMEM64G enabled kernel.\n");
L
Linus Torvalds 已提交
337 338 339 340
		else
			printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
		max_pfn = MAXMEM_PFN;
#else /* !CONFIG_HIGHMEM */
341
#ifndef CONFIG_HIGHMEM64G
L
Linus Torvalds 已提交
342 343 344
		if (max_pfn > MAX_NONPAE_PFN) {
			max_pfn = MAX_NONPAE_PFN;
			printk(KERN_WARNING "Warning only 4GB will be used.\n");
345
			printk(KERN_WARNING "Use a HIGHMEM64G enabled kernel.\n");
L
Linus Torvalds 已提交
346
		}
347
#endif /* !CONFIG_HIGHMEM64G */
L
Linus Torvalds 已提交
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
#endif /* !CONFIG_HIGHMEM */
	} else {
		if (highmem_pages == -1)
			highmem_pages = 0;
#ifdef CONFIG_HIGHMEM
		if (highmem_pages >= max_pfn) {
			printk(KERN_ERR "highmem size specified (%uMB) is bigger than pages available (%luMB)!.\n", pages_to_mb(highmem_pages), pages_to_mb(max_pfn));
			highmem_pages = 0;
		}
		if (highmem_pages) {
			if (max_low_pfn-highmem_pages < 64*1024*1024/PAGE_SIZE){
				printk(KERN_ERR "highmem size %uMB results in smaller than 64MB lowmem, ignoring it.\n", pages_to_mb(highmem_pages));
				highmem_pages = 0;
			}
			max_low_pfn -= highmem_pages;
		}
#else
		if (highmem_pages)
			printk(KERN_ERR "ignoring highmem size on non-highmem kernel!\n");
#endif
	}
	return max_low_pfn;
}

372
#ifndef CONFIG_NEED_MULTIPLE_NODES
I
Ingo Molnar 已提交
373
static void __init setup_bootmem_allocator(void);
L
Linus Torvalds 已提交
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
static unsigned long __init setup_memory(void)
{
	/*
	 * partially used pages are not usable - thus
	 * we are rounding upwards:
	 */
	min_low_pfn = PFN_UP(init_pg_tables_end);

	max_low_pfn = find_max_low_pfn();

#ifdef CONFIG_HIGHMEM
	highstart_pfn = highend_pfn = max_pfn;
	if (max_pfn > max_low_pfn) {
		highstart_pfn = max_low_pfn;
	}
389
	memory_present(0, 0, highend_pfn);
L
Linus Torvalds 已提交
390 391
	printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
		pages_to_mb(highend_pfn - highstart_pfn));
392 393 394
	num_physpages = highend_pfn;
	high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
#else
395
	memory_present(0, 0, max_low_pfn);
396 397 398 399 400
	num_physpages = max_low_pfn;
	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
#endif
#ifdef CONFIG_FLATMEM
	max_mapnr = num_physpages;
L
Linus Torvalds 已提交
401 402 403 404 405 406 407 408 409
#endif
	printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
			pages_to_mb(max_low_pfn));

	setup_bootmem_allocator();

	return max_low_pfn;
}

I
Ingo Molnar 已提交
410
static void __init zone_sizes_init(void)
L
Linus Torvalds 已提交
411
{
412 413 414 415 416
	unsigned long max_zone_pfns[MAX_NR_ZONES];
	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
	max_zone_pfns[ZONE_DMA] =
		virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
417
	remove_all_active_ranges();
L
Linus Torvalds 已提交
418
#ifdef CONFIG_HIGHMEM
419
	max_zone_pfns[ZONE_HIGHMEM] = highend_pfn;
420
	e820_register_active_regions(0, 0, highend_pfn);
421
#else
422
	e820_register_active_regions(0, 0, max_low_pfn);
L
Linus Torvalds 已提交
423
#endif
424 425

	free_area_init_nodes(max_zone_pfns);
L
Linus Torvalds 已提交
426 427
}
#else
428
extern unsigned long __init setup_memory(void);
L
Linus Torvalds 已提交
429
extern void zone_sizes_init(void);
430
#endif /* !CONFIG_NEED_MULTIPLE_NODES */
L
Linus Torvalds 已提交
431

432 433 434 435 436 437
#ifdef CONFIG_BLK_DEV_INITRD

static bool do_relocate_initrd = false;

static void __init reserve_initrd(void)
{
438 439 440 441 442
	u64 ramdisk_image = boot_params.hdr.ramdisk_image;
	u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
	u64 ramdisk_end   = ramdisk_image + ramdisk_size;
	u64 end_of_lowmem = max_low_pfn << PAGE_SHIFT;
	u64 ramdisk_here;
443 444 445 446 447

	if (!boot_params.hdr.type_of_loader ||
	    !ramdisk_image || !ramdisk_size)
		return;		/* No initrd provided by bootloader */

448 449
	initrd_start = 0;

450
	if (ramdisk_size >= end_of_lowmem/2) {
451
		free_early(ramdisk_image, ramdisk_end);
452 453 454 455
		printk(KERN_ERR "initrd too large to handle, "
		       "disabling initrd\n");
		return;
	}
456

457 458 459 460
	printk(KERN_INFO "old RAMDISK: %08llx - %08llx\n", ramdisk_image,
			ramdisk_end);


461 462
	if (ramdisk_end <= end_of_lowmem) {
		/* All in lowmem, easy case */
463 464
		/*
		 * don't need to reserve again, already reserved early
465
		 * in i386_start_kernel
466
		 */
467 468 469 470 471 472
		initrd_start = ramdisk_image + PAGE_OFFSET;
		initrd_end = initrd_start+ramdisk_size;
		return;
	}

	/* We need to move the initrd down into lowmem */
473 474 475
	ramdisk_here = find_e820_area(min_low_pfn<<PAGE_SHIFT,
				 end_of_lowmem, ramdisk_size,
				 PAGE_SIZE);
476

477 478 479 480
	if (ramdisk_here == -1ULL)
		panic("Cannot find place for new RAMDISK of size %lld\n",
			 ramdisk_size);

481 482
	/* Note: this includes all the lowmem currently occupied by
	   the initrd, we rely on that fact to keep the data intact. */
483
	reserve_early(ramdisk_here, ramdisk_here + ramdisk_size,
484
			 "NEW RAMDISK");
485 486
	initrd_start = ramdisk_here + PAGE_OFFSET;
	initrd_end   = initrd_start + ramdisk_size;
487 488
	printk(KERN_INFO "Allocated new RAMDISK: %08llx - %08llx\n",
			 ramdisk_here, ramdisk_here + ramdisk_size);
489 490 491 492 493 494 495 496

	do_relocate_initrd = true;
}

#define MAX_MAP_CHUNK	(NR_FIX_BTMAPS << PAGE_SHIFT)

static void __init relocate_initrd(void)
{
497 498 499 500
	u64 ramdisk_image = boot_params.hdr.ramdisk_image;
	u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
	u64 end_of_lowmem = max_low_pfn << PAGE_SHIFT;
	u64 ramdisk_here;
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
	unsigned long slop, clen, mapaddr;
	char *p, *q;

	if (!do_relocate_initrd)
		return;

	ramdisk_here = initrd_start - PAGE_OFFSET;

	q = (char *)initrd_start;

	/* Copy any lowmem portion of the initrd */
	if (ramdisk_image < end_of_lowmem) {
		clen = end_of_lowmem - ramdisk_image;
		p = (char *)__va(ramdisk_image);
		memcpy(q, p, clen);
		q += clen;
517
		/* need to free these low pages...*/
518 519
		printk(KERN_INFO "Freeing old partial RAMDISK %08llx-%08llx\n",
			 ramdisk_image, ramdisk_image + clen - 1);
520
		free_bootmem(ramdisk_image, clen);
521 522 523 524 525 526 527 528 529 530 531
		ramdisk_image += clen;
		ramdisk_size  -= clen;
	}

	/* Copy the highmem portion of the initrd */
	while (ramdisk_size) {
		slop = ramdisk_image & ~PAGE_MASK;
		clen = ramdisk_size;
		if (clen > MAX_MAP_CHUNK-slop)
			clen = MAX_MAP_CHUNK-slop;
		mapaddr = ramdisk_image & PAGE_MASK;
532
		p = early_ioremap(mapaddr, clen+slop);
533
		memcpy(q, p+slop, clen);
534
		early_iounmap(p, clen+slop);
535 536 537 538
		q += clen;
		ramdisk_image += clen;
		ramdisk_size  -= clen;
	}
539
	/* high pages is not converted by early_res_to_bootmem */
540 541 542 543 544
	ramdisk_image = boot_params.hdr.ramdisk_image;
	ramdisk_size  = boot_params.hdr.ramdisk_size;
	printk(KERN_INFO "Copied RAMDISK from %016llx - %016llx to %08llx - %08llx\n",
		ramdisk_image, ramdisk_image + ramdisk_size - 1,
		ramdisk_here, ramdisk_here + ramdisk_size - 1);
Y
Yinghai Lu 已提交
545 546 547

	/* need to free that, otherwise init highmem will reserve it again */
	free_early(ramdisk_image, ramdisk_image+ramdisk_size);
548 549 550 551
}

#endif /* CONFIG_BLK_DEV_INITRD */

L
Linus Torvalds 已提交
552 553
void __init setup_bootmem_allocator(void)
{
554
	int i;
555
	unsigned long bootmap_size, bootmap;
L
Linus Torvalds 已提交
556 557 558
	/*
	 * Initialize the boot-time allocator (with low memory only):
	 */
559 560
	bootmap_size = bootmem_bootmap_pages(max_low_pfn)<<PAGE_SHIFT;
	bootmap = find_e820_area(min_low_pfn<<PAGE_SHIFT,
561
				 max_pfn_mapped<<PAGE_SHIFT, bootmap_size,
562 563 564
				 PAGE_SIZE);
	if (bootmap == -1L)
		panic("Cannot find bootmem map of size %ld\n", bootmap_size);
565
	reserve_early(bootmap, bootmap + bootmap_size, "BOOTMAP");
566 567 568
#ifdef CONFIG_BLK_DEV_INITRD
	reserve_initrd();
#endif
569
	bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, max_low_pfn);
570 571
	printk(KERN_INFO "  mapped low ram: 0 - %08lx\n",
		 max_pfn_mapped<<PAGE_SHIFT);
572 573
	printk(KERN_INFO "  low ram: %08lx - %08lx\n",
		 min_low_pfn<<PAGE_SHIFT, max_low_pfn<<PAGE_SHIFT);
574 575
	printk(KERN_INFO "  bootmap %08lx - %08lx\n",
		 bootmap, bootmap + bootmap_size);
576 577
	for_each_online_node(i)
		free_bootmem_with_active_regions(i, max_low_pfn);
578
	early_res_to_bootmem(0, max_low_pfn<<PAGE_SHIFT);
L
Linus Torvalds 已提交
579 580 581 582 583 584 585 586 587 588 589

}

/*
 * The node 0 pgdat is initialized before all of these because
 * it's needed for bootmem.  node>0 pgdats have their virtual
 * space allocated before the pagetables are in place to access
 * them, so they can't be cleared then.
 *
 * This should all compile down to nothing when NUMA is off.
 */
A
Adrian Bunk 已提交
590
static void __init remapped_pgdat_init(void)
L
Linus Torvalds 已提交
591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
{
	int nid;

	for_each_online_node(nid) {
		if (nid != 0)
			memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
	}
}

#ifdef CONFIG_MCA
static void set_mca_bus(int x)
{
	MCA_bus = x;
}
#else
static void set_mca_bus(int x) { }
#endif

609 610
static void probe_roms(void);

L
Linus Torvalds 已提交
611 612 613 614 615 616 617 618 619
/*
 * Determine if we were loaded by an EFI loader.  If so, then we have also been
 * passed the efi memmap, systab, etc., so we should use these data structures
 * for initialization.  Note, the efi init code path is determined by the
 * global efi_enabled. This allows the same kernel image to be used on existing
 * systems (with a traditional BIOS) as well as on EFI systems.
 */
void __init setup_arch(char **cmdline_p)
{
620
	int i;
L
Linus Torvalds 已提交
621 622 623 624 625
	unsigned long max_low_pfn;

	memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
	pre_setup_arch_hook();
	early_cpu_init();
626
	early_ioremap_init();
627
	reserve_setup_data();
L
Linus Torvalds 已提交
628 629

#ifdef CONFIG_EFI
630
	if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
631
		     "EL32", 4)) {
L
Linus Torvalds 已提交
632
		efi_enabled = 1;
633 634
		efi_reserve_early();
	}
L
Linus Torvalds 已提交
635 636
#endif

637 638 639 640 641
	ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev);
	screen_info = boot_params.screen_info;
	edid_info = boot_params.edid_info;
	apm_info.bios = boot_params.apm_bios_info;
	ist_info = boot_params.ist_info;
642
	saved_video_mode = boot_params.hdr.vid_mode;
643 644 645 646 647
	if( boot_params.sys_desc_table.length != 0 ) {
		set_mca_bus(boot_params.sys_desc_table.table[3] & 0x2);
		machine_id = boot_params.sys_desc_table.table[0];
		machine_submodel_id = boot_params.sys_desc_table.table[1];
		BIOS_revision = boot_params.sys_desc_table.table[2];
L
Linus Torvalds 已提交
648
	}
649
	bootloader_type = boot_params.hdr.type_of_loader;
L
Linus Torvalds 已提交
650 651

#ifdef CONFIG_BLK_DEV_RAM
652 653 654
	rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK;
	rd_prompt = ((boot_params.hdr.ram_size & RAMDISK_PROMPT_FLAG) != 0);
	rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0);
L
Linus Torvalds 已提交
655 656
#endif
	ARCH_SETUP
657

658
	setup_memory_map();
659

L
Linus Torvalds 已提交
660 661
	copy_edd();

662
	if (!boot_params.hdr.root_flags)
L
Linus Torvalds 已提交
663 664 665 666 667 668 669 670 671 672
		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 = init_pg_tables_end + PAGE_OFFSET;

	code_resource.start = virt_to_phys(_text);
	code_resource.end = virt_to_phys(_etext)-1;
	data_resource.start = virt_to_phys(_etext);
	data_resource.end = virt_to_phys(_edata)-1;
B
Bernhard Walle 已提交
673 674
	bss_resource.start = virt_to_phys(&__bss_start);
	bss_resource.end = virt_to_phys(&__bss_stop)-1;
L
Linus Torvalds 已提交
675

676 677
	parse_setup_data();

678
	parse_early_param();
L
Linus Torvalds 已提交
679

680 681 682 683 684
	if (acpi_mps_check()){
		enable_local_apic = -1;
		clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
	}

685
	finish_e820_parsing();
686

687 688 689 690 691 692 693
	probe_roms();

	/* after parse_early_param, so could debug it */
	insert_resource(&iomem_resource, &code_resource);
	insert_resource(&iomem_resource, &data_resource);
	insert_resource(&iomem_resource, &bss_resource);

694
	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
695
	*cmdline_p = command_line;
696

697 698 699
	if (efi_enabled)
		efi_init();

Y
Yinghai Lu 已提交
700 701 702 703 704 705 706 707
	if (ppro_with_ram_bug()) {
		e820_update_range(0x70000000ULL, 0x40000ULL, E820_RAM,
				  E820_RESERVED);
		sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
		printk(KERN_INFO "fixed physical RAM map:\n");
		e820_print_map("bad_ppro");
	}

708 709 710 711 712 713 714
	e820_register_active_regions(0, 0, -1UL);
	/*
	 * partially used pages are not usable - thus
	 * we are rounding upwards:
	 */
	max_pfn = e820_end_of_ram();

Y
Yinghai Lu 已提交
715 716
	/* preallocate 4k for mptable mpc */
	early_reserve_e820_mpc_new();
717 718
	/* update e820 for memory not covered by WB MTRRs */
	mtrr_bp_init();
719 720 721 722 723
	if (mtrr_trim_uncached_memory(max_pfn)) {
		remove_all_active_ranges();
		e820_register_active_regions(0, 0, -1UL);
		max_pfn = e820_end_of_ram();
	}
724

725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740
	dmi_scan_machine();

	io_delay_init();

	/*
	 * Parse the ACPI tables for possible boot-time SMP configuration.
	 */
	acpi_boot_table_init();

#ifdef CONFIG_ACPI_NUMA
        /*
         * Parse SRAT to discover nodes.
         */
        acpi_numa_init();
#endif

741
	max_low_pfn = setup_memory();
742

743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758
#ifdef CONFIG_ACPI_SLEEP
	/*
	 * Reserve low memory region for sleep support.
	 */
	acpi_reserve_bootmem();
#endif
#ifdef CONFIG_X86_FIND_SMP_CONFIG
	/*
	 * Find and reserve possible boot-time SMP configuration:
	 */
	find_smp_config();
#endif
	reserve_crashkernel();

	reserve_ibft_region();

759 760 761 762
#ifdef CONFIG_KVM_CLOCK
	kvmclock_init();
#endif

763 764 765 766 767 768 769
#ifdef CONFIG_VMI
	/*
	 * Must be after max_low_pfn is determined, and before kernel
	 * pagetables are setup.
	 */
	vmi_init();
#endif
770
	kvm_guest_init();
771

L
Linus Torvalds 已提交
772 773 774
	/*
	 * NOTE: before this point _nobody_ is allowed to allocate
	 * any memory using the bootmem allocator.  Although the
S
Simon Arlott 已提交
775
	 * allocator is now initialised only the first 8Mb of the kernel
L
Linus Torvalds 已提交
776 777 778 779 780 781 782
	 * virtual address space has been mapped.  All allocations before
	 * paging_init() has completed must use the alloc_bootmem_low_pages()
	 * variant (which allocates DMA'able memory) and care must be taken
	 * not to exceed the 8Mb limit.
	 */

	paging_init();
783 784 785 786 787 788 789 790 791 792

	/*
	 * NOTE: On x86-32, only from this point on, fixmaps are ready for use.
	 */

#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
	if (init_ohci1394_dma_early)
		init_ohci1394_dma_on_all_controllers();
#endif

L
Linus Torvalds 已提交
793 794 795 796
	/*
	 * NOTE: at this point the bootmem allocator is fully available.
	 */

797 798 799 800
#ifdef CONFIG_BLK_DEV_INITRD
	relocate_initrd();
#endif

Y
Yinghai Lu 已提交
801 802 803 804
	remapped_pgdat_init();
	sparse_init();
	zone_sizes_init();

805 806
	paravirt_post_allocator_init();

L
Linus Torvalds 已提交
807
#ifdef CONFIG_X86_GENERICARCH
808
	generic_apic_probe();
809
#endif
L
Linus Torvalds 已提交
810

811
	early_quirks();
812

L
Linus Torvalds 已提交
813
	acpi_boot_init();
814

815 816 817 818
#if defined(CONFIG_X86_MPPARSE) || defined(CONFIG_X86_VISWS)
	if (smp_found_config)
		get_smp_config();
#endif
819 820 821 822 823 824
#if defined(CONFIG_SMP) && defined(CONFIG_X86_PC)
	if (def_to_bigsmp)
		printk(KERN_WARNING "More than 8 CPUs detected and "
			"CONFIG_X86_PC cannot handle it.\nUse "
			"CONFIG_X86_GENERICARCH or CONFIG_X86_BIGSMP.\n");
#endif
L
Linus Torvalds 已提交
825

826
	e820_reserve_resources();
827
	e820_mark_nosave_regions(max_low_pfn);
L
Linus Torvalds 已提交
828

829 830 831 832 833 834 835
	request_resource(&iomem_resource, &video_ram_resource);
	/* request I/O space for devices used on all i[345]86 PCs */
	for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
		request_resource(&ioport_resource, &standard_io_resources[i]);

	e820_setup_gap();

L
Linus Torvalds 已提交
836 837 838 839 840 841 842 843 844
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
	if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
		conswitchp = &vga_con;
#elif defined(CONFIG_DUMMY_CONSOLE)
	conswitchp = &dummy_con;
#endif
#endif
}
845

846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918
static struct resource system_rom_resource = {
	.name	= "System ROM",
	.start	= 0xf0000,
	.end	= 0xfffff,
	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
};

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

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

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

#define ROMSIGNATURE 0xaa55

static int __init romsignature(const unsigned char *rom)
{
	const unsigned short * const ptr = (const unsigned short *)rom;
	unsigned short sig;

	return probe_kernel_address(ptr, sig) == 0 && sig == ROMSIGNATURE;
}

static int __init romchecksum(const unsigned char *rom, unsigned long length)
{
	unsigned char sum, c;

	for (sum = 0; length && probe_kernel_address(rom++, c) == 0; length--)
		sum += c;
	return !length && !sum;
}

static void __init probe_roms(void)
919
{
920 921 922
	const unsigned char *rom;
	unsigned long start, length, upper;
	unsigned char c;
923 924
	int i;

925 926 927 928 929 930
	/* 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;
931

932
		video_rom_resource.start = start;
933

934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 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
		if (probe_kernel_address(rom + 2, c) != 0)
			continue;

		/* 0 < length <= 0x7f * 512, historically */
		length = c * 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 < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += 2048) {
		rom = isa_bus_to_virt(start);
		if (!romsignature(rom))
			continue;

		if (probe_kernel_address(rom + 2, c) != 0)
			continue;

		/* 0 < length <= 0x7f * 512, historically */
		length = c * 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;
	}
988 989
}