diff options
| -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); |
