2008-06-02 14:26:23 +08:00
# include <linux/kernel.h>
# include <linux/init.h>
2010-08-25 13:39:17 -07:00
# include <linux/memblock.h>
2008-06-02 14:26:23 +08:00
# include <asm/setup.h>
# include <asm/bios_ebda.h>
/*
* The BIOS places the EBDA / XBDA at the top of conventional
* memory , and usually decreases the reported amount of
* conventional memory ( int 0x12 ) too . This also contains a
* workaround for Dell systems that neglect to reserve EBDA .
* The same workaround also avoids a problem with the AMD768MPX
* 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 .
2013-02-27 12:46:40 -08:00
*
* 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 .
2008-06-02 14:26:23 +08:00
*/
2013-02-27 12:46:40 -08:00
# define BIOS_LOWMEM_KILOBYTES 0x413
# define LOWMEM_CAP 0x9f000U /* Absolute maximum */
# define INSANE_CUTOFF 0x20000U /* Less than this = insane */
2008-06-02 14:26:23 +08:00
void __init reserve_ebda_region ( void )
{
unsigned int lowmem , ebda_addr ;
2013-02-27 12:46:40 -08:00
/*
* 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 .
*/
2008-06-02 14:26:23 +08:00
if ( paravirt_enabled ( ) )
return ;
/* end of low (conventional) memory */
lowmem = * ( unsigned short * ) __va ( BIOS_LOWMEM_KILOBYTES ) ;
lowmem < < = 10 ;
/* start of EBDA area */
ebda_addr = get_bios_ebda ( ) ;
2013-02-27 12:46:40 -08:00
/*
* Note : some old Dells seem to need 4 k 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 ;
2008-06-02 14:26:23 +08:00
2013-02-27 12:46:40 -08:00
/* If lowmem is less than 128K, assume it is bogus */
if ( lowmem < INSANE_CUTOFF )
lowmem = LOWMEM_CAP ;
2008-06-02 14:26:23 +08:00
2013-02-27 12:46:40 -08:00
/* Use the lower of the lowmem and EBDA markers as the cutoff */
lowmem = min ( lowmem , ebda_addr ) ;
lowmem = min ( lowmem , LOWMEM_CAP ) ; /* Absolute cap */
2008-06-02 14:26:23 +08:00
/* reserve all memory between lowmem and the 1MB mark */
2011-07-12 11:16:06 +02:00
memblock_reserve ( lowmem , 0x100000 - lowmem ) ;
2008-06-02 14:26:23 +08:00
}