diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2013-02-27 15:46:40 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2013-02-27 16:38:57 -0500 |
commit | 7c10093692ed2e6f318387d96b829320aa0ca64c (patch) | |
tree | f314c7fcd202c7c6e70fff730667f7f09c6f4a0e | |
parent | 058e7b5814534461b0e2468fce5a8f8d2f43c38f (diff) |
x86: Make sure we can boot in the case the BDA contains pure garbage
On non-BIOS platforms it is possible that the BIOS data area contains
garbage instead of being zeroed or something equivalent (firmware
people: we are talking of 1.5K here, so please do the sane thing.)
We need on the order of 20-30K of low memory in order to boot, which
may grow up to < 64K in the future. We probably want to avoid the
lowest of the low memory. At the same time, it seems extremely
unlikely that a legitimate EBDA would ever reach down to the 128K
(which would require it to be over half a megabyte in size.) Thus,
pick 128K as the cutoff for "this is insane, ignore." We may still
end up reserving a bunch of extra memory on the low megabyte, but that
is not really a major issue these days. In the worst case we lose
512K of RAM.
This code really should be merged with trim_bios_range() in
arch/x86/kernel/setup.c, but that is a bigger patch for a later merge
window.
Reported-by: Darren Hart <dvhart@linux.intel.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Cc: Matt Fleming <matt.fleming@intel.com>
Cc: <stable@vger.kernel.org>
Link: http://lkml.kernel.org/n/tip-oebml055yyfm8yxmria09rja@git.kernel.org
-rw-r--r-- | arch/x86/kernel/head.c | 53 |
1 files changed, 34 insertions, 19 deletions
diff --git a/arch/x86/kernel/head.c b/arch/x86/kernel/head.c index 48d9d4ea1020..992f442ca155 100644 --- a/arch/x86/kernel/head.c +++ b/arch/x86/kernel/head.c | |||
@@ -5,8 +5,6 @@ | |||
5 | #include <asm/setup.h> | 5 | #include <asm/setup.h> |
6 | #include <asm/bios_ebda.h> | 6 | #include <asm/bios_ebda.h> |
7 | 7 | ||
8 | #define BIOS_LOWMEM_KILOBYTES 0x413 | ||
9 | |||
10 | /* | 8 | /* |
11 | * The BIOS places the EBDA/XBDA at the top of conventional | 9 | * The BIOS places the EBDA/XBDA at the top of conventional |
12 | * memory, and usually decreases the reported amount of | 10 | * memory, and usually decreases the reported amount of |
@@ -16,17 +14,30 @@ | |||
16 | * chipset: reserve a page before VGA to prevent PCI prefetch | 14 | * chipset: reserve a page before VGA to prevent PCI prefetch |
17 | * into it (errata #56). Usually the page is reserved anyways, | 15 | * into it (errata #56). Usually the page is reserved anyways, |
18 | * unless you have no PS/2 mouse plugged in. | 16 | * unless you have no PS/2 mouse plugged in. |
17 | * | ||
18 | * This functions is deliberately very conservative. Losing | ||
19 | * memory in the bottom megabyte is rarely a problem, as long | ||
20 | * as we have enough memory to install the trampoline. Using | ||
21 | * memory that is in use by the BIOS or by some DMA device | ||
22 | * the BIOS didn't shut down *is* a big problem. | ||
19 | */ | 23 | */ |
24 | |||
25 | #define BIOS_LOWMEM_KILOBYTES 0x413 | ||
26 | #define LOWMEM_CAP 0x9f000U /* Absolute maximum */ | ||
27 | #define INSANE_CUTOFF 0x20000U /* Less than this = insane */ | ||
28 | |||
20 | void __init reserve_ebda_region(void) | 29 | void __init reserve_ebda_region(void) |
21 | { | 30 | { |
22 | unsigned int lowmem, ebda_addr; | 31 | unsigned int lowmem, ebda_addr; |
23 | 32 | ||
24 | /* To determine the position of the EBDA and the */ | 33 | /* |
25 | /* end of conventional memory, we need to look at */ | 34 | * To determine the position of the EBDA and the |
26 | /* the BIOS data area. In a paravirtual environment */ | 35 | * end of conventional memory, we need to look at |
27 | /* that area is absent. We'll just have to assume */ | 36 | * the BIOS data area. In a paravirtual environment |
28 | /* that the paravirt case can handle memory setup */ | 37 | * that area is absent. We'll just have to assume |
29 | /* correctly, without our help. */ | 38 | * that the paravirt case can handle memory setup |
39 | * correctly, without our help. | ||
40 | */ | ||
30 | if (paravirt_enabled()) | 41 | if (paravirt_enabled()) |
31 | return; | 42 | return; |
32 | 43 | ||
@@ -37,19 +48,23 @@ void __init reserve_ebda_region(void) | |||
37 | /* start of EBDA area */ | 48 | /* start of EBDA area */ |
38 | ebda_addr = get_bios_ebda(); | 49 | ebda_addr = get_bios_ebda(); |
39 | 50 | ||
40 | /* Fixup: bios puts an EBDA in the top 64K segment */ | 51 | /* |
41 | /* of conventional memory, but does not adjust lowmem. */ | 52 | * Note: some old Dells seem to need 4k EBDA without |
42 | if ((lowmem - ebda_addr) <= 0x10000) | 53 | * reporting so, so just consider the memory above 0x9f000 |
43 | lowmem = ebda_addr; | 54 | * to be off limits (bugzilla 2990). |
55 | */ | ||
56 | |||
57 | /* If the EBDA address is below 128K, assume it is bogus */ | ||
58 | if (ebda_addr < INSANE_CUTOFF) | ||
59 | ebda_addr = LOWMEM_CAP; | ||
44 | 60 | ||
45 | /* Fixup: bios does not report an EBDA at all. */ | 61 | /* If lowmem is less than 128K, assume it is bogus */ |
46 | /* Some old Dells seem to need 4k anyhow (bugzilla 2990) */ | 62 | if (lowmem < INSANE_CUTOFF) |
47 | if ((ebda_addr == 0) && (lowmem >= 0x9f000)) | 63 | lowmem = LOWMEM_CAP; |
48 | lowmem = 0x9f000; | ||
49 | 64 | ||
50 | /* Paranoia: should never happen, but... */ | 65 | /* Use the lower of the lowmem and EBDA markers as the cutoff */ |
51 | if ((lowmem == 0) || (lowmem >= 0x100000)) | 66 | lowmem = min(lowmem, ebda_addr); |
52 | lowmem = 0x9f000; | 67 | lowmem = min(lowmem, LOWMEM_CAP); /* Absolute cap */ |
53 | 68 | ||
54 | /* reserve all memory between lowmem and the 1MB mark */ | 69 | /* reserve all memory between lowmem and the 1MB mark */ |
55 | memblock_reserve(lowmem, 0x100000 - lowmem); | 70 | memblock_reserve(lowmem, 0x100000 - lowmem); |