diff options
Diffstat (limited to 'arch/x86/kernel/head.c')
| -rw-r--r-- | arch/x86/kernel/head.c | 55 | 
1 files changed, 35 insertions, 20 deletions
diff --git a/arch/x86/kernel/head.c b/arch/x86/kernel/head.c index af0699ba48c..992f442ca15 100644 --- a/arch/x86/kernel/head.c +++ b/arch/x86/kernel/head.c @@ -5,8 +5,6 @@  #include <asm/setup.h>  #include <asm/bios_ebda.h> -#define BIOS_LOWMEM_KILOBYTES 0x413 -  /*   * The BIOS places the EBDA/XBDA at the top of conventional   * memory, and usually decreases the reported amount of @@ -16,17 +14,30 @@   * chipset: reserve a page before VGA to prevent PCI prefetch   * into it (errata #56). Usually the page is reserved anyways,   * unless you have no PS/2 mouse plugged in. + * + * This functions is deliberately very conservative.  Losing + * memory in the bottom megabyte is rarely a problem, as long + * as we have enough memory to install the trampoline.  Using + * memory that is in use by the BIOS or by some DMA device + * the BIOS didn't shut down *is* a big problem.   */ + +#define BIOS_LOWMEM_KILOBYTES	0x413 +#define LOWMEM_CAP		0x9f000U	/* Absolute maximum */ +#define INSANE_CUTOFF		0x20000U	/* Less than this = insane */ +  void __init reserve_ebda_region(void)  {  	unsigned int lowmem, ebda_addr; -	/* To determine the position of the EBDA and the */ -	/* end of conventional memory, we need to look at */ -	/* the BIOS data area. In a paravirtual environment */ -	/* that area is absent. We'll just have to assume */ -	/* that the paravirt case can handle memory setup */ -	/* correctly, without our help. */ +	/* +	 * To determine the position of the EBDA and the +	 * end of conventional memory, we need to look at +	 * the BIOS data area. In a paravirtual environment +	 * that area is absent. We'll just have to assume +	 * that the paravirt case can handle memory setup +	 * correctly, without our help. +	 */  	if (paravirt_enabled())  		return; @@ -37,20 +48,24 @@ void __init reserve_ebda_region(void)  	/* start of EBDA area */  	ebda_addr = get_bios_ebda(); -	/* Fixup: bios puts an EBDA in the top 64K segment */ -	/* of conventional memory, but does not adjust lowmem. */ -	if ((lowmem - ebda_addr) <= 0x10000) -		lowmem = ebda_addr; +	/* +	 * Note: some old Dells seem to need 4k EBDA without +	 * reporting so, so just consider the memory above 0x9f000 +	 * to be off limits (bugzilla 2990). +	 */ + +	/* If the EBDA address is below 128K, assume it is bogus */ +	if (ebda_addr < INSANE_CUTOFF) +		ebda_addr = LOWMEM_CAP; -	/* Fixup: bios does not report an EBDA at all. */ -	/* Some old Dells seem to need 4k anyhow (bugzilla 2990) */ -	if ((ebda_addr == 0) && (lowmem >= 0x9f000)) -		lowmem = 0x9f000; +	/* If lowmem is less than 128K, assume it is bogus */ +	if (lowmem < INSANE_CUTOFF) +		lowmem = LOWMEM_CAP; -	/* Paranoia: should never happen, but... */ -	if ((lowmem == 0) || (lowmem >= 0x100000)) -		lowmem = 0x9f000; +	/* Use the lower of the lowmem and EBDA markers as the cutoff */ +	lowmem = min(lowmem, ebda_addr); +	lowmem = min(lowmem, LOWMEM_CAP); /* Absolute cap */  	/* reserve all memory between lowmem and the 1MB mark */ -	memblock_x86_reserve_range(lowmem, 0x100000, "* BIOS reserved"); +	memblock_reserve(lowmem, 0x100000 - lowmem);  }  | 
