2008-01-30 13:30:12 +01:00
/*
2005-04-16 15:20:36 -07:00
* Handle the memory map .
* The functions here do the job until bootmem takes over .
2005-05-01 08:58:52 -07:00
*
* Getting sanitize_e820_map ( ) in sync with i386 version by applying change :
* - Provisions for empty E820 memory regions ( reported by certain BIOSes ) .
* Alex Achenbach < xela @ slit . de > , December 2002.
* Venkatesh Pallipadi < venkatesh . pallipadi @ intel . com >
*
2005-04-16 15:20:36 -07:00
*/
# include <linux/kernel.h>
# include <linux/types.h>
# include <linux/init.h>
# include <linux/bootmem.h>
# include <linux/ioport.h>
# include <linux/string.h>
2005-06-25 14:58:04 -07:00
# include <linux/kexec.h>
2005-09-16 19:27:54 -07:00
# include <linux/module.h>
2006-09-25 23:32:46 -07:00
# include <linux/mm.h>
2007-05-06 14:50:43 -07:00
# include <linux/pfn.h>
2008-05-12 15:43:37 +02:00
# include <linux/pci.h>
2005-09-16 19:27:54 -07:00
2006-07-10 04:43:49 -07:00
# include <asm/pgtable.h>
2005-04-16 15:20:36 -07:00
# include <asm/page.h>
# include <asm/e820.h>
# include <asm/proto.h>
2007-10-15 17:13:22 -07:00
# include <asm/setup.h>
2005-11-05 17:25:53 +01:00
# include <asm/sections.h>
2008-01-30 13:30:17 +01:00
# include <asm/kdebug.h>
2008-04-10 23:28:10 +02:00
# include <asm/trampoline.h>
2005-04-16 15:20:36 -07:00
2008-01-30 13:30:12 +01:00
/*
2005-04-16 15:20:36 -07:00
* PFN of last memory page .
*/
2008-01-30 13:30:12 +01:00
unsigned long end_pfn ;
2005-04-16 15:20:36 -07:00
2008-01-30 13:30:12 +01:00
/*
2008-03-21 21:27:10 +01:00
* end_pfn only includes RAM , while max_pfn_mapped includes all e820 entries .
* The direct mapping extends to max_pfn_mapped , so that we can directly access
2005-04-16 15:20:36 -07:00
* apertures , ACPI and other tables without having to play with fixmaps .
2008-01-30 13:30:12 +01:00
*/
2008-03-21 21:27:10 +01:00
unsigned long max_pfn_mapped ;
2005-04-16 15:20:36 -07:00
2005-08-26 18:34:10 -07:00
/*
2005-04-16 15:20:36 -07:00
* Mark e820 reserved areas as busy for the resource manager .
*/
2008-02-22 17:07:16 -08:00
void __init e820_reserve_resources ( void )
2005-04-16 15:20:36 -07:00
{
int i ;
2008-03-20 23:57:21 -07:00
struct resource * res ;
res = alloc_bootmem_low ( sizeof ( struct resource ) * e820 . nr_map ) ;
2005-04-16 15:20:36 -07:00
for ( i = 0 ; i < e820 . nr_map ; i + + ) {
switch ( e820 . map [ i ] . type ) {
case E820_RAM : res - > name = " System RAM " ; break ;
case E820_ACPI : res - > name = " ACPI Tables " ; break ;
case E820_NVS : res - > name = " ACPI Non-volatile Storage " ; break ;
default : res - > name = " reserved " ;
}
res - > start = e820 . map [ i ] . addr ;
res - > end = res - > start + e820 . map [ i ] . size - 1 ;
res - > flags = IORESOURCE_MEM | IORESOURCE_BUSY ;
2008-02-22 17:07:16 -08:00
insert_resource ( & iomem_resource , res ) ;
2008-03-20 23:57:21 -07:00
res + + ;
2005-04-16 15:20:36 -07:00
}
}
2008-01-30 13:30:30 +01:00
static void early_panic ( char * msg )
2005-04-16 15:20:36 -07:00
{
2006-09-26 10:52:37 +02:00
early_printk ( msg ) ;
panic ( msg ) ;
}
2005-04-16 15:20:36 -07:00
2008-01-30 13:31:11 +01:00
/* We're not void only for x86 32-bit compat */
2008-05-14 08:15:28 -07:00
char * __init machine_specific_memory_setup ( void )
2006-09-26 10:52:37 +02:00
{
2008-01-30 13:31:11 +01:00
char * who = " BIOS-e820 " ;
2008-05-14 08:15:46 -07:00
int new_nr ;
2005-04-16 15:20:36 -07:00
/*
* Try to copy the BIOS - supplied E820 - map .
*
* Otherwise fake a memory map ; one section from 0 k - > 640 k ,
* the next section from 1 mb - > appropriate_mem_k
*/
2008-05-14 08:15:46 -07:00
new_nr = boot_params . e820_entries ;
2008-05-14 08:15:34 -07:00
sanitize_e820_map ( boot_params . e820_map ,
ARRAY_SIZE ( boot_params . e820_map ) ,
2008-05-14 08:15:46 -07:00
& new_nr ) ;
boot_params . e820_entries = new_nr ;
2007-10-15 17:13:22 -07:00
if ( copy_e820_map ( boot_params . e820_map , boot_params . e820_entries ) < 0 )
2006-09-26 10:52:37 +02:00
early_panic ( " Cannot find a valid memory map " ) ;
2005-04-16 15:20:36 -07:00
printk ( KERN_INFO " BIOS-provided physical RAM map: \n " ) ;
2008-01-30 13:31:11 +01:00
e820_print_map ( who ) ;
/* In case someone cares... */
return who ;
2005-04-16 15:20:36 -07:00
}
2007-10-21 16:41:55 -07:00
int __init arch_get_ram_range ( int slot , u64 * addr , u64 * size )
{
int i ;
if ( slot < 0 | | slot > = e820 . nr_map )
return - 1 ;
for ( i = slot ; i < e820 . nr_map ; i + + ) {
if ( e820 . map [ i ] . type ! = E820_RAM )
continue ;
break ;
}
if ( i = = e820 . nr_map | | e820 . map [ i ] . addr > ( max_pfn < < PAGE_SHIFT ) )
return - 1 ;
* addr = e820 . map [ i ] . addr ;
* size = min_t ( u64 , e820 . map [ i ] . size + e820 . map [ i ] . addr ,
max_pfn < < PAGE_SHIFT ) - * addr ;
return i + 1 ;
}