2005-04-17 02:20:36 +04:00
/*
* Copyright ( C ) 1995 Linus Torvalds
*
* Support of BIGMEM added by Gerhard Wichert , Siemens AG , July 1999
*
* Memory region support
* David Parsons < orc @ pell . chi . il . us > , July - August 1999
*
* Added E820 sanitization routine ( removes overlapping memory regions ) ;
* Brian Moyle < bmoyle @ mvista . com > , February 2001
*
* Moved CPU detection code to cpu / $ { cpu } . c
* Patrick Mochel < mochel @ osdl . org > , March 2002
*
* Provisions for empty E820 memory regions ( reported by certain BIOSes ) .
* Alex Achenbach < xela @ slit . de > , December 2002.
*
*/
/*
* This file handles the architecture - dependent parts of initialization
*/
# include <linux/sched.h>
# include <linux/mm.h>
2005-06-23 11:07:57 +04:00
# include <linux/mmzone.h>
2006-07-10 15:44:13 +04:00
# include <linux/screen_info.h>
2005-04-17 02:20:36 +04:00
# include <linux/ioport.h>
# include <linux/acpi.h>
# include <linux/apm_bios.h>
# include <linux/initrd.h>
# include <linux/bootmem.h>
# include <linux/seq_file.h>
# include <linux/console.h>
# include <linux/mca.h>
# include <linux/root_dev.h>
# include <linux/highmem.h>
# include <linux/module.h>
# include <linux/efi.h>
# include <linux/init.h>
# include <linux/edd.h>
# include <linux/nodemask.h>
2005-06-26 01:58:01 +04:00
# include <linux/kexec.h>
2005-06-26 01:58:20 +04:00
# include <linux/crash_dump.h>
2006-01-12 00:43:33 +03:00
# include <linux/dmi.h>
2006-03-27 13:16:04 +04:00
# include <linux/pfn.h>
2005-06-26 01:58:01 +04:00
2005-04-17 02:20:36 +04:00
# include <video/edid.h>
2005-06-26 01:58:01 +04:00
2005-06-26 01:57:41 +04:00
# include <asm/apic.h>
2005-04-17 02:20:36 +04:00
# include <asm/e820.h>
# include <asm/mpspec.h>
2006-09-26 10:31:03 +04:00
# include <asm/mmzone.h>
2005-04-17 02:20:36 +04:00
# include <asm/setup.h>
# include <asm/arch_hooks.h>
# include <asm/sections.h>
# include <asm/io_apic.h>
# include <asm/ist.h>
# include <asm/io.h>
2007-02-13 15:26:21 +03:00
# include <asm/vmi.h>
2006-06-25 16:46:50 +04:00
# include <setup_arch.h>
2005-04-17 02:20:36 +04:00
# include <bios_ebda.h>
2007-10-22 03:42:01 +04:00
# include <asm/cacheflush.h>
2005-04-17 02:20:36 +04:00
/* This value is set up by the early boot code to point to the value
immediately after the boot time page tables . It contains a * physical *
address , and must not be in the . bss segment ! */
unsigned long init_pg_tables_end __initdata = ~ 0UL ;
2007-12-20 01:20:19 +03:00
int disable_pse __cpuinitdata = 0 ;
2005-04-17 02:20:36 +04:00
/*
* Machine setup . .
*/
2006-12-07 04:14:06 +03:00
extern struct resource code_resource ;
extern struct resource data_resource ;
2007-10-22 03:42:01 +04:00
extern struct resource bss_resource ;
2005-04-17 02:20:36 +04:00
/* cpu data as detected by the assembly code in head.S */
2007-01-11 03:52:44 +03:00
struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0 , 0 , 0 , 0 , - 1 , 1 , 0 , 0 , - 1 } ;
2005-04-17 02:20:36 +04:00
/* common cpu data for all cpus */
2005-09-07 02:16:33 +04:00
struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0 , 0 , 0 , 0 , - 1 , 1 , 0 , 0 , - 1 } ;
2005-06-23 11:08:33 +04:00
EXPORT_SYMBOL ( boot_cpu_data ) ;
2005-04-17 02:20:36 +04:00
unsigned long mmu_cr4_features ;
/* for MCA, but anyone else can use it if they want */
unsigned int machine_id ;
unsigned int machine_submodel_id ;
unsigned int BIOS_revision ;
unsigned int mca_pentium_flag ;
/* Boot loader ID as an integer, for the benefit of proc_dointvec */
int bootloader_type ;
/* user-defined highmem size */
static unsigned int highmem_pages = - 1 ;
/*
* Setup options
*/
struct screen_info screen_info ;
2005-06-23 11:08:33 +04:00
EXPORT_SYMBOL ( screen_info ) ;
2005-04-17 02:20:36 +04:00
struct apm_info apm_info ;
2005-06-23 11:08:33 +04:00
EXPORT_SYMBOL ( apm_info ) ;
2005-04-17 02:20:36 +04:00
struct edid_info edid_info ;
2005-09-10 00:04:34 +04:00
EXPORT_SYMBOL_GPL ( edid_info ) ;
2005-04-17 02:20:36 +04:00
struct ist_info ist_info ;
2005-06-23 11:08:33 +04:00
# if defined(CONFIG_X86_SPEEDSTEP_SMI) || \
defined ( CONFIG_X86_SPEEDSTEP_SMI_MODULE )
EXPORT_SYMBOL ( ist_info ) ;
# endif
2005-04-17 02:20:36 +04:00
extern void early_cpu_init ( void ) ;
extern int root_mountflags ;
unsigned long saved_videomode ;
# define RAMDISK_IMAGE_START_MASK 0x07FF
# define RAMDISK_PROMPT_FLAG 0x8000
# define RAMDISK_LOAD_FLAG 0x4000
2007-02-12 11:54:11 +03:00
static char __initdata command_line [ COMMAND_LINE_SIZE ] ;
2005-04-17 02:20:36 +04:00
2007-07-11 23:18:35 +04:00
struct boot_params __initdata boot_params ;
2005-04-17 02:20:36 +04:00
# if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
struct edd edd ;
# ifdef CONFIG_EDD_MODULE
EXPORT_SYMBOL ( edd ) ;
# endif
/**
* copy_edd ( ) - Copy the BIOS EDD information
* from boot_params into a safe place .
*
*/
static inline void copy_edd ( void )
{
2007-10-16 04:13:22 +04:00
memcpy ( edd . mbr_signature , boot_params . edd_mbr_sig_buffer ,
sizeof ( edd . mbr_signature ) ) ;
memcpy ( edd . edd_info , boot_params . eddbuf , sizeof ( edd . edd_info ) ) ;
edd . mbr_signature_nr = boot_params . edd_mbr_sig_buf_entries ;
edd . edd_info_nr = boot_params . eddbuf_entries ;
2005-04-17 02:20:36 +04:00
}
# else
static inline void copy_edd ( void )
{
}
# endif
2006-12-07 04:14:06 +03:00
int __initdata user_defined_memmap = 0 ;
2005-04-17 02:20:36 +04:00
2006-09-26 12:52:32 +04:00
/*
* " mem=nopentium " disables the 4 MB page tables .
* " mem=XXX[kKmM] " defines a memory region from HIGH_MEM
* to < mem > , overriding the bios size .
* " memmap=XXX[KkmM]@XXX[KkmM] " defines a memory region from
* < start > to < start > + < mem > , overriding the bios size .
*
* HPA tells me bootloaders need to parse mem = , so no new
* option should be mem = [ also see Documentation / i386 / boot . txt ]
*/
static int __init parse_mem ( char * arg )
{
if ( ! arg )
return - EINVAL ;
2005-04-17 02:20:36 +04:00
2006-09-26 12:52:32 +04:00
if ( strcmp ( arg , " nopentium " ) = = 0 ) {
clear_bit ( X86_FEATURE_PSE , boot_cpu_data . x86_capability ) ;
disable_pse = 1 ;
} else {
/* If the user specifies memory size, we
* limit the BIOS - provided memory map to
* that size . exactmap can be used to specify
* the exact map . mem = number can be used to
* trim the existing memory map .
2005-04-17 02:20:36 +04:00
*/
2006-09-26 12:52:32 +04:00
unsigned long long mem_size ;
2005-04-17 02:20:36 +04:00
2006-09-26 12:52:32 +04:00
mem_size = memparse ( arg , & arg ) ;
limit_regions ( mem_size ) ;
user_defined_memmap = 1 ;
}
return 0 ;
}
early_param ( " mem " , parse_mem ) ;
2005-04-17 02:20:36 +04:00
2006-09-26 12:52:32 +04:00
# ifdef CONFIG_PROC_VMCORE
/* elfcorehdr= specifies the location of elf core header
* stored by the crashed kernel .
*/
static int __init parse_elfcorehdr ( char * arg )
{
if ( ! arg )
return - EINVAL ;
2005-09-12 20:49:25 +04:00
2006-09-26 12:52:32 +04:00
elfcorehdr_addr = memparse ( arg , & arg ) ;
return 0 ;
}
early_param ( " elfcorehdr " , parse_elfcorehdr ) ;
# endif /* CONFIG_PROC_VMCORE */
2005-04-17 02:20:36 +04:00
2006-09-26 12:52:32 +04:00
/*
* highmem = size forces highmem to be exactly ' size ' bytes .
* This works even on boxes that have no highmem otherwise .
* This also works to reduce highmem size on bigger boxes .
*/
static int __init parse_highmem ( char * arg )
{
if ( ! arg )
return - EINVAL ;
2005-06-26 01:57:41 +04:00
2006-09-26 12:52:32 +04:00
highmem_pages = memparse ( arg , & arg ) > > PAGE_SHIFT ;
return 0 ;
}
early_param ( " highmem " , parse_highmem ) ;
2005-06-26 01:57:41 +04:00
2006-09-26 12:52:32 +04:00
/*
* vmalloc = size forces the vmalloc area to be exactly ' size '
* bytes . This can be used to increase ( or decrease ) the
* vmalloc area - the default is 128 m .
*/
static int __init parse_vmalloc ( char * arg )
{
if ( ! arg )
return - EINVAL ;
2005-06-26 01:58:01 +04:00
2006-09-26 12:52:32 +04:00
__VMALLOC_RESERVE = memparse ( arg , & arg ) ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
2006-09-26 12:52:32 +04:00
early_param ( " vmalloc " , parse_vmalloc ) ;
2005-04-17 02:20:36 +04:00
2006-09-26 10:32:25 +04:00
/*
* reservetop = size reserves a hole at the top of the kernel address space which
* a hypervisor can load into later . Needed for dynamically loaded hypervisors ,
* so relocating the fixmap can be done before paging initialization .
*/
static int __init parse_reservetop ( char * arg )
{
unsigned long address ;
if ( ! arg )
return - EINVAL ;
address = memparse ( arg , & arg ) ;
reserve_top_address ( address ) ;
return 0 ;
}
early_param ( " reservetop " , parse_reservetop ) ;
2005-04-17 02:20:36 +04:00
/*
* Determine low and high memory ranges :
*/
unsigned long __init find_max_low_pfn ( void )
{
unsigned long max_low_pfn ;
max_low_pfn = max_pfn ;
if ( max_low_pfn > MAXMEM_PFN ) {
if ( highmem_pages = = - 1 )
highmem_pages = max_pfn - MAXMEM_PFN ;
if ( highmem_pages + MAXMEM_PFN < max_pfn )
max_pfn = MAXMEM_PFN + highmem_pages ;
if ( highmem_pages + MAXMEM_PFN > max_pfn ) {
printk ( " only %luMB highmem pages available, ignoring highmem size of %uMB. \n " , pages_to_mb ( max_pfn - MAXMEM_PFN ) , pages_to_mb ( highmem_pages ) ) ;
highmem_pages = 0 ;
}
max_low_pfn = MAXMEM_PFN ;
# ifndef CONFIG_HIGHMEM
/* Maximum memory usable is what is directly addressable */
printk ( KERN_WARNING " Warning only %ldMB will be used. \n " ,
MAXMEM > > 20 ) ;
if ( max_pfn > MAX_NONPAE_PFN )
2007-07-21 19:11:13 +04:00
printk ( KERN_WARNING " Use a HIGHMEM64G enabled kernel. \n " ) ;
2005-04-17 02:20:36 +04:00
else
printk ( KERN_WARNING " Use a HIGHMEM enabled kernel. \n " ) ;
max_pfn = MAXMEM_PFN ;
# else /* !CONFIG_HIGHMEM */
2007-07-21 19:11:13 +04:00
# ifndef CONFIG_HIGHMEM64G
2005-04-17 02:20:36 +04:00
if ( max_pfn > MAX_NONPAE_PFN ) {
max_pfn = MAX_NONPAE_PFN ;
printk ( KERN_WARNING " Warning only 4GB will be used. \n " ) ;
2007-07-21 19:11:13 +04:00
printk ( KERN_WARNING " Use a HIGHMEM64G enabled kernel. \n " ) ;
2005-04-17 02:20:36 +04:00
}
2007-07-21 19:11:13 +04:00
# endif /* !CONFIG_HIGHMEM64G */
2005-04-17 02:20:36 +04:00
# endif /* !CONFIG_HIGHMEM */
} else {
if ( highmem_pages = = - 1 )
highmem_pages = 0 ;
# ifdef CONFIG_HIGHMEM
if ( highmem_pages > = max_pfn ) {
printk ( KERN_ERR " highmem size specified (%uMB) is bigger than pages available (%luMB)!. \n " , pages_to_mb ( highmem_pages ) , pages_to_mb ( max_pfn ) ) ;
highmem_pages = 0 ;
}
if ( highmem_pages ) {
if ( max_low_pfn - highmem_pages < 64 * 1024 * 1024 / PAGE_SIZE ) {
printk ( KERN_ERR " highmem size %uMB results in smaller than 64MB lowmem, ignoring it. \n " , pages_to_mb ( highmem_pages ) ) ;
highmem_pages = 0 ;
}
max_low_pfn - = highmem_pages ;
}
# else
if ( highmem_pages )
printk ( KERN_ERR " ignoring highmem size on non-highmem kernel! \n " ) ;
# endif
}
return max_low_pfn ;
}
/*
* workaround for Dell systems that neglect to reserve EBDA
*/
static void __init reserve_ebda_region ( void )
{
unsigned int addr ;
addr = get_bios_ebda ( ) ;
if ( addr )
reserve_bootmem ( addr , PAGE_SIZE ) ;
}
2005-06-23 11:07:57 +04:00
# ifndef CONFIG_NEED_MULTIPLE_NODES
2005-04-17 02:20:36 +04:00
void __init setup_bootmem_allocator ( void ) ;
static unsigned long __init setup_memory ( void )
{
/*
* partially used pages are not usable - thus
* we are rounding upwards :
*/
min_low_pfn = PFN_UP ( init_pg_tables_end ) ;
find_max_pfn ( ) ;
max_low_pfn = find_max_low_pfn ( ) ;
# ifdef CONFIG_HIGHMEM
highstart_pfn = highend_pfn = max_pfn ;
if ( max_pfn > max_low_pfn ) {
highstart_pfn = max_low_pfn ;
}
printk ( KERN_NOTICE " %ldMB HIGHMEM available. \n " ,
pages_to_mb ( highend_pfn - highstart_pfn ) ) ;
2006-09-26 12:52:31 +04:00
num_physpages = highend_pfn ;
high_memory = ( void * ) __va ( highstart_pfn * PAGE_SIZE - 1 ) + 1 ;
# else
num_physpages = max_low_pfn ;
high_memory = ( void * ) __va ( max_low_pfn * PAGE_SIZE - 1 ) + 1 ;
# endif
# ifdef CONFIG_FLATMEM
max_mapnr = num_physpages ;
2005-04-17 02:20:36 +04:00
# endif
printk ( KERN_NOTICE " %ldMB LOWMEM available. \n " ,
pages_to_mb ( max_low_pfn ) ) ;
setup_bootmem_allocator ( ) ;
return max_low_pfn ;
}
void __init zone_sizes_init ( void )
{
2006-10-11 12:20:39 +04:00
unsigned long max_zone_pfns [ MAX_NR_ZONES ] ;
memset ( max_zone_pfns , 0 , sizeof ( max_zone_pfns ) ) ;
max_zone_pfns [ ZONE_DMA ] =
virt_to_phys ( ( char * ) MAX_DMA_ADDRESS ) > > PAGE_SHIFT ;
max_zone_pfns [ ZONE_NORMAL ] = max_low_pfn ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_HIGHMEM
2006-10-11 12:20:39 +04:00
max_zone_pfns [ ZONE_HIGHMEM ] = highend_pfn ;
2006-09-27 12:49:51 +04:00
add_active_range ( 0 , 0 , highend_pfn ) ;
# else
add_active_range ( 0 , 0 , max_low_pfn ) ;
2005-04-17 02:20:36 +04:00
# endif
2006-09-27 12:49:51 +04:00
free_area_init_nodes ( max_zone_pfns ) ;
2005-04-17 02:20:36 +04:00
}
# else
2005-06-23 11:07:57 +04:00
extern unsigned long __init setup_memory ( void ) ;
2005-04-17 02:20:36 +04:00
extern void zone_sizes_init ( void ) ;
2005-06-23 11:07:57 +04:00
# endif /* !CONFIG_NEED_MULTIPLE_NODES */
2005-04-17 02:20:36 +04:00
2007-10-19 10:40:59 +04:00
static inline unsigned long long get_total_mem ( void )
{
unsigned long long total ;
total = max_low_pfn - min_low_pfn ;
# ifdef CONFIG_HIGHMEM
total + = highend_pfn - highstart_pfn ;
# endif
return total < < PAGE_SHIFT ;
}
# ifdef CONFIG_KEXEC
static void __init reserve_crashkernel ( void )
{
unsigned long long total_mem ;
unsigned long long crash_size , crash_base ;
int ret ;
total_mem = get_total_mem ( ) ;
ret = parse_crashkernel ( boot_command_line , total_mem ,
& crash_size , & crash_base ) ;
if ( ret = = 0 & & crash_size > 0 ) {
if ( crash_base > 0 ) {
printk ( KERN_INFO " Reserving %ldMB of memory at %ldMB "
" for crashkernel (System RAM: %ldMB) \n " ,
( unsigned long ) ( crash_size > > 20 ) ,
( unsigned long ) ( crash_base > > 20 ) ,
( unsigned long ) ( total_mem > > 20 ) ) ;
crashk_res . start = crash_base ;
crashk_res . end = crash_base + crash_size - 1 ;
reserve_bootmem ( crash_base , crash_size ) ;
} else
printk ( KERN_INFO " crashkernel reservation failed - "
" you have to specify a base address \n " ) ;
}
}
# else
static inline void __init reserve_crashkernel ( void )
{ }
# endif
2005-04-17 02:20:36 +04:00
void __init setup_bootmem_allocator ( void )
{
unsigned long bootmap_size ;
/*
* Initialize the boot - time allocator ( with low memory only ) :
*/
bootmap_size = init_bootmem ( min_low_pfn , max_low_pfn ) ;
register_bootmem_low_pages ( max_low_pfn ) ;
/*
* Reserve the bootmem bitmap itself as well . We do this in two
* steps ( first step was init_bootmem ( ) ) because this catches
* the ( very unlikely ) case of us accidentally initializing the
* bootmem allocator with an invalid RAM area .
*/
2006-12-07 04:14:03 +03:00
reserve_bootmem ( __pa_symbol ( _text ) , ( PFN_PHYS ( min_low_pfn ) +
bootmap_size + PAGE_SIZE - 1 ) - __pa_symbol ( _text ) ) ;
2005-04-17 02:20:36 +04:00
/*
* reserve physical page 0 - it ' s a special BIOS page on many boxes ,
* enabling clean reboots , SMP operation , laptop functions .
*/
reserve_bootmem ( 0 , PAGE_SIZE ) ;
/* reserve EBDA region, it's a 4K region */
reserve_ebda_region ( ) ;
/* could be an AMD 768MPX 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 . */
if ( boot_cpu_data . x86_vendor = = X86_VENDOR_AMD & &
boot_cpu_data . x86 = = 6 )
reserve_bootmem ( 0xa0000 - 4096 , 4096 ) ;
# ifdef CONFIG_SMP
/*
* But first pinch a few for the stack / trampoline stuff
* FIXME : Don ' t need the extra page at 4 K , but need to fix
* trampoline before removing it . ( see the GDT stuff )
*/
reserve_bootmem ( PAGE_SIZE , PAGE_SIZE ) ;
# endif
2007-07-28 11:33:16 +04:00
# ifdef CONFIG_ACPI_SLEEP
2005-04-17 02:20:36 +04:00
/*
* Reserve low memory region for sleep support .
*/
acpi_reserve_bootmem ( ) ;
# endif
# ifdef CONFIG_X86_FIND_SMP_CONFIG
/*
* Find and reserve possible boot - time SMP configuration :
*/
find_smp_config ( ) ;
# endif
2006-09-26 10:31:03 +04:00
numa_kva_reserve ( ) ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_BLK_DEV_INITRD
2007-10-16 04:13:22 +04:00
if ( boot_params . hdr . type_of_loader & & boot_params . hdr . ramdisk_image ) {
unsigned long ramdisk_image = boot_params . hdr . ramdisk_image ;
unsigned long ramdisk_size = boot_params . hdr . ramdisk_size ;
unsigned long ramdisk_end = ramdisk_image + ramdisk_size ;
unsigned long end_of_lowmem = max_low_pfn < < PAGE_SHIFT ;
if ( ramdisk_end < = end_of_lowmem ) {
reserve_bootmem ( ramdisk_image , ramdisk_size ) ;
initrd_start = ramdisk_image + PAGE_OFFSET ;
initrd_end = initrd_start + ramdisk_size ;
} else {
2005-04-17 02:20:36 +04:00
printk ( KERN_ERR " initrd extends beyond end of memory "
2007-10-16 04:13:22 +04:00
" (0x%08lx > 0x%08lx) \n disabling initrd \n " ,
ramdisk_end , end_of_lowmem ) ;
2005-04-17 02:20:36 +04:00
initrd_start = 0 ;
}
}
# endif
2007-10-19 10:40:59 +04:00
reserve_crashkernel ( ) ;
2005-04-17 02:20:36 +04:00
}
/*
* The node 0 pgdat is initialized before all of these because
* it ' s needed for bootmem . node > 0 pgdats have their virtual
* space allocated before the pagetables are in place to access
* them , so they can ' t be cleared then .
*
* This should all compile down to nothing when NUMA is off .
*/
2007-07-21 19:10:27 +04:00
static void __init remapped_pgdat_init ( void )
2005-04-17 02:20:36 +04:00
{
int nid ;
for_each_online_node ( nid ) {
if ( nid ! = 0 )
memset ( NODE_DATA ( nid ) , 0 , sizeof ( struct pglist_data ) ) ;
}
}
# ifdef CONFIG_MCA
static void set_mca_bus ( int x )
{
MCA_bus = x ;
}
# else
static void set_mca_bus ( int x ) { }
# endif
2006-12-07 04:14:07 +03:00
/* Overridden in paravirt.c if CONFIG_PARAVIRT */
2007-01-11 03:52:44 +03:00
char * __init __attribute__ ( ( weak ) ) memory_setup ( void )
2006-12-07 04:14:07 +03:00
{
return machine_specific_memory_setup ( ) ;
}
2005-04-17 02:20:36 +04:00
/*
* Determine if we were loaded by an EFI loader . If so , then we have also been
* passed the efi memmap , systab , etc . , so we should use these data structures
* for initialization . Note , the efi init code path is determined by the
* global efi_enabled . This allows the same kernel image to be used on existing
* systems ( with a traditional BIOS ) as well as on EFI systems .
*/
void __init setup_arch ( char * * cmdline_p )
{
unsigned long max_low_pfn ;
memcpy ( & boot_cpu_data , & new_cpu_data , sizeof ( new_cpu_data ) ) ;
pre_setup_arch_hook ( ) ;
early_cpu_init ( ) ;
/*
* FIXME : This isn ' t an official loader_type right
* now but does currently work with elilo .
* If we were configured as an EFI kernel , check to make
* sure that we were loaded correctly from elilo and that
* the system table is valid . If not , then initialize normally .
*/
# ifdef CONFIG_EFI
2007-10-16 04:13:22 +04:00
if ( ( boot_params . hdr . type_of_loader = = 0x50 ) & &
boot_params . efi_info . efi_systab )
2005-04-17 02:20:36 +04:00
efi_enabled = 1 ;
# endif
2007-10-16 04:13:22 +04:00
ROOT_DEV = old_decode_dev ( boot_params . hdr . root_dev ) ;
screen_info = boot_params . screen_info ;
edid_info = boot_params . edid_info ;
apm_info . bios = boot_params . apm_bios_info ;
ist_info = boot_params . ist_info ;
saved_videomode = boot_params . hdr . vid_mode ;
if ( boot_params . sys_desc_table . length ! = 0 ) {
set_mca_bus ( boot_params . sys_desc_table . table [ 3 ] & 0x2 ) ;
machine_id = boot_params . sys_desc_table . table [ 0 ] ;
machine_submodel_id = boot_params . sys_desc_table . table [ 1 ] ;
BIOS_revision = boot_params . sys_desc_table . table [ 2 ] ;
2005-04-17 02:20:36 +04:00
}
2007-10-16 04:13:22 +04:00
bootloader_type = boot_params . hdr . type_of_loader ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_BLK_DEV_RAM
2007-10-16 04:13:22 +04:00
rd_image_start = boot_params . hdr . ram_size & RAMDISK_IMAGE_START_MASK ;
rd_prompt = ( ( boot_params . hdr . ram_size & RAMDISK_PROMPT_FLAG ) ! = 0 ) ;
rd_doload = ( ( boot_params . hdr . ram_size & RAMDISK_LOAD_FLAG ) ! = 0 ) ;
2005-04-17 02:20:36 +04:00
# endif
ARCH_SETUP
if ( efi_enabled )
efi_init ( ) ;
else {
printk ( KERN_INFO " BIOS-provided physical RAM map: \n " ) ;
2006-12-07 04:14:07 +03:00
print_memory_map ( memory_setup ( ) ) ;
2005-04-17 02:20:36 +04:00
}
copy_edd ( ) ;
2007-10-16 04:13:22 +04:00
if ( ! boot_params . hdr . root_flags )
2005-04-17 02:20:36 +04:00
root_mountflags & = ~ MS_RDONLY ;
init_mm . start_code = ( unsigned long ) _text ;
init_mm . end_code = ( unsigned long ) _etext ;
init_mm . end_data = ( unsigned long ) _edata ;
init_mm . brk = init_pg_tables_end + PAGE_OFFSET ;
code_resource . start = virt_to_phys ( _text ) ;
code_resource . end = virt_to_phys ( _etext ) - 1 ;
data_resource . start = virt_to_phys ( _etext ) ;
data_resource . end = virt_to_phys ( _edata ) - 1 ;
2007-10-22 03:42:01 +04:00
bss_resource . start = virt_to_phys ( & __bss_start ) ;
bss_resource . end = virt_to_phys ( & __bss_stop ) - 1 ;
2005-04-17 02:20:36 +04:00
2006-09-26 12:52:32 +04:00
parse_early_param ( ) ;
2005-04-17 02:20:36 +04:00
2006-09-26 12:52:32 +04:00
if ( user_defined_memmap ) {
printk ( KERN_INFO " user-defined physical RAM map: \n " ) ;
print_memory_map ( " user " ) ;
2006-03-23 13:59:41 +03:00
}
2006-09-26 12:52:32 +04:00
2007-02-12 11:54:11 +03:00
strlcpy ( command_line , boot_command_line , COMMAND_LINE_SIZE ) ;
2006-09-26 12:52:32 +04:00
* cmdline_p = command_line ;
2006-03-23 13:59:41 +03:00
2005-04-17 02:20:36 +04:00
max_low_pfn = setup_memory ( ) ;
2007-02-13 15:26:21 +03:00
# ifdef CONFIG_VMI
/*
* Must be after max_low_pfn is determined , and before kernel
* pagetables are setup .
*/
vmi_init ( ) ;
# endif
2005-04-17 02:20:36 +04:00
/*
* NOTE : before this point _nobody_ is allowed to allocate
* any memory using the bootmem allocator . Although the
2007-10-20 03:13:56 +04:00
* allocator is now initialised only the first 8 Mb of the kernel
2005-04-17 02:20:36 +04:00
* virtual address space has been mapped . All allocations before
* paging_init ( ) has completed must use the alloc_bootmem_low_pages ( )
* variant ( which allocates DMA ' able memory ) and care must be taken
* not to exceed the 8 Mb limit .
*/
# ifdef CONFIG_SMP
smp_alloc_memory ( ) ; /* AP processor realmode stacks in low memory*/
# endif
paging_init ( ) ;
remapped_pgdat_init ( ) ;
2005-06-23 11:07:57 +04:00
sparse_init ( ) ;
2005-04-17 02:20:36 +04:00
zone_sizes_init ( ) ;
/*
* NOTE : at this point the bootmem allocator is fully available .
*/
2007-07-18 05:37:03 +04:00
paravirt_post_allocator_init ( ) ;
2005-04-17 02:20:36 +04:00
dmi_scan_machine ( ) ;
2008-01-30 15:30:05 +03:00
io_delay_init ( ) ; ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_X86_GENERICARCH
2006-09-26 12:52:32 +04:00
generic_apic_probe ( ) ;
2005-04-17 02:20:36 +04:00
# endif
if ( efi_enabled )
efi_map_memmap ( ) ;
2005-08-24 20:07:20 +04:00
# ifdef CONFIG_ACPI
2005-04-17 02:20:36 +04:00
/*
* Parse the ACPI tables for possible boot - time SMP configuration .
*/
acpi_boot_table_init ( ) ;
2006-06-08 11:43:38 +04:00
# endif
2006-09-26 12:52:41 +04:00
# ifdef CONFIG_PCI
2007-10-19 22:35:03 +04:00
early_quirks ( ) ;
2006-09-26 12:52:41 +04:00
# endif
2006-06-08 11:43:38 +04:00
# ifdef CONFIG_ACPI
2005-04-17 02:20:36 +04:00
acpi_boot_init ( ) ;
2005-09-04 02:56:31 +04:00
# if defined(CONFIG_SMP) && defined(CONFIG_X86_PC)
if ( def_to_bigsmp )
printk ( KERN_WARNING " More than 8 CPUs detected and "
" CONFIG_X86_PC cannot handle it. \n Use "
" CONFIG_X86_GENERICARCH or CONFIG_X86_BIGSMP. \n " ) ;
# endif
# endif
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_X86_LOCAL_APIC
if ( smp_found_config )
get_smp_config ( ) ;
# endif
2006-12-22 12:09:54 +03:00
e820_register_memory ( ) ;
2007-07-21 19:11:09 +04:00
e820_mark_nosave_regions ( ) ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_VT
# if defined(CONFIG_VGA_CONSOLE)
if ( ! efi_enabled | | ( efi_mem_type ( 0xa0000 ) ! = EFI_CONVENTIONAL_MEMORY ) )
conswitchp = & vga_con ;
# elif defined(CONFIG_DUMMY_CONSOLE)
conswitchp = & dummy_con ;
# endif
# endif
}