aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/head64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/head64.c')
-rw-r--r--arch/x86/kernel/head64.c45
1 files changed, 27 insertions, 18 deletions
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 38f32e798a99..b684552347df 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -49,33 +49,42 @@ static void __init copy_bootdata(char *real_mode_data)
49 } 49 }
50} 50}
51 51
52#define EBDA_ADDR_POINTER 0x40E 52#define BIOS_EBDA_SEGMENT 0x40E
53#define BIOS_LOWMEM_KILOBYTES 0x413
53 54
55/*
56 * The BIOS places the EBDA/XBDA at the top of conventional
57 * memory, and usually decreases the reported amount of
58 * conventional memory (int 0x12) too.
59 */
54static __init void reserve_ebda(void) 60static __init void reserve_ebda(void)
55{ 61{
56 unsigned ebda_addr, ebda_size; 62 unsigned int lowmem, ebda_addr;
57 63
58 /* 64 /* end of low (conventional) memory */
59 * there is a real-mode segmented pointer pointing to the 65 lowmem = *(unsigned short *)__va(BIOS_LOWMEM_KILOBYTES);
60 * 4K EBDA area at 0x40E 66 lowmem <<= 10;
61 */ 67
62 ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER); 68 /* start of EBDA area */
69 ebda_addr = *(unsigned short *)__va(BIOS_EBDA_SEGMENT);
63 ebda_addr <<= 4; 70 ebda_addr <<= 4;
64 71
65 if (!ebda_addr) 72 /* Fixup: bios puts an EBDA in the top 64K segment */
66 return; 73 /* of conventional memory, but does not adjust lowmem. */
74 if ((lowmem - ebda_addr) <= 0x10000)
75 lowmem = ebda_addr;
67 76
68 ebda_size = *(unsigned short *)__va(ebda_addr); 77 /* Fixup: bios does not report an EBDA at all. */
78 /* Some old Dells seem to need 4k anyhow (bugzilla 2990) */
79 if ((ebda_addr == 0) && (lowmem >= 0x9f000))
80 lowmem = 0x9f000;
69 81
70 /* Round EBDA up to pages */ 82 /* Paranoia: should never happen, but... */
71 if (ebda_size == 0) 83 if (lowmem >= 0x100000)
72 ebda_size = 1; 84 lowmem = 0xa0000;
73 ebda_size <<= 10;
74 ebda_size = round_up(ebda_size + (ebda_addr & ~PAGE_MASK), PAGE_SIZE);
75 if (ebda_size > 64*1024)
76 ebda_size = 64*1024;
77 85
78 reserve_early(ebda_addr, ebda_addr + ebda_size, "EBDA"); 86 /* reserve all memory between lowmem and the 1MB mark */
87 reserve_early(lowmem, 0x100000, "BIOS reserved");
79} 88}
80 89
81void __init x86_64_start_kernel(char * real_mode_data) 90void __init x86_64_start_kernel(char * real_mode_data)