xref: /openbmc/linux/arch/x86/kernel/head32.c (revision a4c81cf6)
1700efc1bSEric W. Biederman /*
2700efc1bSEric W. Biederman  *  linux/arch/i386/kernel/head32.c -- prepare to run common code
3700efc1bSEric W. Biederman  *
4700efc1bSEric W. Biederman  *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
5700efc1bSEric W. Biederman  *  Copyright (C) 2007 Eric Biederman <ebiederm@xmission.com>
6700efc1bSEric W. Biederman  */
7700efc1bSEric W. Biederman 
8700efc1bSEric W. Biederman #include <linux/init.h>
9700efc1bSEric W. Biederman #include <linux/start_kernel.h>
10700efc1bSEric W. Biederman 
11a4c81cf6SYinghai Lu #include <asm/setup.h>
12a4c81cf6SYinghai Lu #include <asm/sections.h>
13a4c81cf6SYinghai Lu #include <asm/e820.h>
14a4c81cf6SYinghai Lu #include <asm/bios_ebda.h>
15a4c81cf6SYinghai Lu 
16a4c81cf6SYinghai Lu #define BIOS_LOWMEM_KILOBYTES 0x413
17a4c81cf6SYinghai Lu 
18a4c81cf6SYinghai Lu /*
19a4c81cf6SYinghai Lu  * The BIOS places the EBDA/XBDA at the top of conventional
20a4c81cf6SYinghai Lu  * memory, and usually decreases the reported amount of
21a4c81cf6SYinghai Lu  * conventional memory (int 0x12) too. This also contains a
22a4c81cf6SYinghai Lu  * workaround for Dell systems that neglect to reserve EBDA.
23a4c81cf6SYinghai Lu  * The same workaround also avoids a problem with the AMD768MPX
24a4c81cf6SYinghai Lu  * chipset: reserve a page before VGA to prevent PCI prefetch
25a4c81cf6SYinghai Lu  * into it (errata #56). Usually the page is reserved anyways,
26a4c81cf6SYinghai Lu  * unless you have no PS/2 mouse plugged in.
27a4c81cf6SYinghai Lu  */
28a4c81cf6SYinghai Lu static void __init reserve_ebda_region(void)
29a4c81cf6SYinghai Lu {
30a4c81cf6SYinghai Lu 	unsigned int lowmem, ebda_addr;
31a4c81cf6SYinghai Lu 
32a4c81cf6SYinghai Lu 	/* To determine the position of the EBDA and the */
33a4c81cf6SYinghai Lu 	/* end of conventional memory, we need to look at */
34a4c81cf6SYinghai Lu 	/* the BIOS data area. In a paravirtual environment */
35a4c81cf6SYinghai Lu 	/* that area is absent. We'll just have to assume */
36a4c81cf6SYinghai Lu 	/* that the paravirt case can handle memory setup */
37a4c81cf6SYinghai Lu 	/* correctly, without our help. */
38a4c81cf6SYinghai Lu 	if (paravirt_enabled())
39a4c81cf6SYinghai Lu 		return;
40a4c81cf6SYinghai Lu 
41a4c81cf6SYinghai Lu 	/* end of low (conventional) memory */
42a4c81cf6SYinghai Lu 	lowmem = *(unsigned short *)__va(BIOS_LOWMEM_KILOBYTES);
43a4c81cf6SYinghai Lu 	lowmem <<= 10;
44a4c81cf6SYinghai Lu 
45a4c81cf6SYinghai Lu 	/* start of EBDA area */
46a4c81cf6SYinghai Lu 	ebda_addr = get_bios_ebda();
47a4c81cf6SYinghai Lu 
48a4c81cf6SYinghai Lu 	/* Fixup: bios puts an EBDA in the top 64K segment */
49a4c81cf6SYinghai Lu 	/* of conventional memory, but does not adjust lowmem. */
50a4c81cf6SYinghai Lu 	if ((lowmem - ebda_addr) <= 0x10000)
51a4c81cf6SYinghai Lu 		lowmem = ebda_addr;
52a4c81cf6SYinghai Lu 
53a4c81cf6SYinghai Lu 	/* Fixup: bios does not report an EBDA at all. */
54a4c81cf6SYinghai Lu 	/* Some old Dells seem to need 4k anyhow (bugzilla 2990) */
55a4c81cf6SYinghai Lu 	if ((ebda_addr == 0) && (lowmem >= 0x9f000))
56a4c81cf6SYinghai Lu 		lowmem = 0x9f000;
57a4c81cf6SYinghai Lu 
58a4c81cf6SYinghai Lu 	/* Paranoia: should never happen, but... */
59a4c81cf6SYinghai Lu 	if ((lowmem == 0) || (lowmem >= 0x100000))
60a4c81cf6SYinghai Lu 		lowmem = 0x9f000;
61a4c81cf6SYinghai Lu 
62a4c81cf6SYinghai Lu 	/* reserve all memory between lowmem and the 1MB mark */
63a4c81cf6SYinghai Lu 	reserve_early(lowmem, 0x100000, "BIOS reserved");
64a4c81cf6SYinghai Lu }
65a4c81cf6SYinghai Lu 
66700efc1bSEric W. Biederman void __init i386_start_kernel(void)
67700efc1bSEric W. Biederman {
68a4c81cf6SYinghai Lu 	reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS");
69a4c81cf6SYinghai Lu 
70a4c81cf6SYinghai Lu #ifdef CONFIG_BLK_DEV_INITRD
71a4c81cf6SYinghai Lu 	/* Reserve INITRD */
72a4c81cf6SYinghai Lu 	if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
73a4c81cf6SYinghai Lu 		u64 ramdisk_image = boot_params.hdr.ramdisk_image;
74a4c81cf6SYinghai Lu 		u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
75a4c81cf6SYinghai Lu 		u64 ramdisk_end   = ramdisk_image + ramdisk_size;
76a4c81cf6SYinghai Lu 		reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
77a4c81cf6SYinghai Lu 	}
78a4c81cf6SYinghai Lu #endif
79a4c81cf6SYinghai Lu 	reserve_early(__pa_symbol(&_end), init_pg_tables_end, "INIT_PG_TABLE");
80a4c81cf6SYinghai Lu 
81a4c81cf6SYinghai Lu 	reserve_ebda_region();
82a4c81cf6SYinghai Lu 
83a4c81cf6SYinghai Lu 	/*
84a4c81cf6SYinghai Lu 	 * At this point everything still needed from the boot loader
85a4c81cf6SYinghai Lu 	 * or BIOS or kernel text should be early reserved or marked not
86a4c81cf6SYinghai Lu 	 * RAM in e820. All other memory is free game.
87a4c81cf6SYinghai Lu 	 */
88a4c81cf6SYinghai Lu 
89700efc1bSEric W. Biederman 	start_kernel();
90700efc1bSEric W. Biederman }
91