1700efc1bSEric W. Biederman /* 2700efc1bSEric W. Biederman * linux/arch/i386/kernel/head32.c -- prepare to run common code 3700efc1bSEric W. Biederman * 4700efc1bSEric W. Biederman * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE 5700efc1bSEric W. Biederman * Copyright (C) 2007 Eric Biederman <ebiederm@xmission.com> 6700efc1bSEric W. Biederman */ 7700efc1bSEric W. Biederman 8700efc1bSEric W. Biederman #include <linux/init.h> 9700efc1bSEric W. Biederman #include <linux/start_kernel.h> 10c967da6aSYinghai Lu #include <linux/mm.h> 1172d7c3b3SYinghai Lu #include <linux/memblock.h> 12700efc1bSEric W. Biederman 1387e81786SThomas Gleixner #include <asm/desc.h> 14a4c81cf6SYinghai Lu #include <asm/setup.h> 15a4c81cf6SYinghai Lu #include <asm/sections.h> 1666441bd3SIngo Molnar #include <asm/e820/api.h> 17816c25e7SThomas Gleixner #include <asm/page.h> 18de934103SThomas Gleixner #include <asm/apic.h> 19de934103SThomas Gleixner #include <asm/io_apic.h> 2047a3d5daSThomas Gleixner #include <asm/bios_ebda.h> 21b40827faSBorislav Petkov #include <asm/tlbflush.h> 225dcd14ecSH. Peter Anvin #include <asm/bootparam_utils.h> 2347a3d5daSThomas Gleixner 2447a3d5daSThomas Gleixner static void __init i386_default_early_setup(void) 2547a3d5daSThomas Gleixner { 26421f91d2SUwe Kleine-König /* Initialize 32bit specific setup functions */ 2747a3d5daSThomas Gleixner x86_init.resources.reserve_resources = i386_reserve_resources; 2847a3d5daSThomas Gleixner x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc; 2947a3d5daSThomas Gleixner } 30a4c81cf6SYinghai Lu 312605fc21SAndi Kleen asmlinkage __visible void __init i386_start_kernel(void) 32700efc1bSEric W. Biederman { 331e02ce4cSAndy Lutomirski cr4_init_shadow(); 3487e81786SThomas Gleixner 3587e81786SThomas Gleixner idt_setup_early_handler(); 3687e81786SThomas Gleixner 375dcd14ecSH. Peter Anvin sanitize_boot_params(&boot_params); 385dcd14ecSH. Peter Anvin 398d152e7aSLuis R. Rodriguez x86_early_init_platform_quirks(); 408d152e7aSLuis R. Rodriguez 4147a3d5daSThomas Gleixner /* Call the subarch specific early setup function */ 4247a3d5daSThomas Gleixner switch (boot_params.hdr.hardware_subarch) { 43712b6aa8SKuppuswamy Sathyanarayanan case X86_SUBARCH_INTEL_MID: 44712b6aa8SKuppuswamy Sathyanarayanan x86_intel_mid_early_setup(); 453f4110a4SThomas Gleixner break; 46c751e17bSThomas Gleixner case X86_SUBARCH_CE4100: 47c751e17bSThomas Gleixner x86_ce4100_early_setup(); 48c751e17bSThomas Gleixner break; 4947a3d5daSThomas Gleixner default: 5047a3d5daSThomas Gleixner i386_default_early_setup(); 5147a3d5daSThomas Gleixner break; 5247a3d5daSThomas Gleixner } 53a4c81cf6SYinghai Lu 54700efc1bSEric W. Biederman start_kernel(); 55700efc1bSEric W. Biederman } 561e620f9bSBoris Ostrovsky 571e620f9bSBoris Ostrovsky /* 581e620f9bSBoris Ostrovsky * Initialize page tables. This creates a PDE and a set of page 591e620f9bSBoris Ostrovsky * tables, which are located immediately beyond __brk_base. The variable 601e620f9bSBoris Ostrovsky * _brk_end is set up to point to the first "safe" location. 611e620f9bSBoris Ostrovsky * Mappings are created both at virtual address 0 (identity mapping) 621e620f9bSBoris Ostrovsky * and PAGE_OFFSET for up to _end. 631e620f9bSBoris Ostrovsky * 641e620f9bSBoris Ostrovsky * In PAE mode initial_page_table is statically defined to contain 651e620f9bSBoris Ostrovsky * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3 661e620f9bSBoris Ostrovsky * entries). The identity mapping is handled by pointing two PGD entries 671e620f9bSBoris Ostrovsky * to the first kernel PMD. Note the upper half of each PMD or PTE are 681e620f9bSBoris Ostrovsky * always zero at this stage. 691e620f9bSBoris Ostrovsky */ 701e620f9bSBoris Ostrovsky void __init mk_early_pgtbl_32(void) 711e620f9bSBoris Ostrovsky { 721e620f9bSBoris Ostrovsky #ifdef __pa 731e620f9bSBoris Ostrovsky #undef __pa 741e620f9bSBoris Ostrovsky #endif 751e620f9bSBoris Ostrovsky #define __pa(x) ((unsigned long)(x) - PAGE_OFFSET) 761e620f9bSBoris Ostrovsky pte_t pte, *ptep; 771e620f9bSBoris Ostrovsky int i; 781e620f9bSBoris Ostrovsky unsigned long *ptr; 791e620f9bSBoris Ostrovsky /* Enough space to fit pagetables for the low memory linear map */ 801e620f9bSBoris Ostrovsky const unsigned long limit = __pa(_end) + 811e620f9bSBoris Ostrovsky (PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT); 821e620f9bSBoris Ostrovsky #ifdef CONFIG_X86_PAE 831e620f9bSBoris Ostrovsky pmd_t pl2, *pl2p = (pmd_t *)__pa(initial_pg_pmd); 841e620f9bSBoris Ostrovsky #define SET_PL2(pl2, val) { (pl2).pmd = (val); } 851e620f9bSBoris Ostrovsky #else 861e620f9bSBoris Ostrovsky pgd_t pl2, *pl2p = (pgd_t *)__pa(initial_page_table); 871e620f9bSBoris Ostrovsky #define SET_PL2(pl2, val) { (pl2).pgd = (val); } 881e620f9bSBoris Ostrovsky #endif 891e620f9bSBoris Ostrovsky 901e620f9bSBoris Ostrovsky ptep = (pte_t *)__pa(__brk_base); 911e620f9bSBoris Ostrovsky pte.pte = PTE_IDENT_ATTR; 921e620f9bSBoris Ostrovsky 931e620f9bSBoris Ostrovsky while ((pte.pte & PTE_PFN_MASK) < limit) { 941e620f9bSBoris Ostrovsky 951e620f9bSBoris Ostrovsky SET_PL2(pl2, (unsigned long)ptep | PDE_IDENT_ATTR); 961e620f9bSBoris Ostrovsky *pl2p = pl2; 971e620f9bSBoris Ostrovsky #ifndef CONFIG_X86_PAE 981e620f9bSBoris Ostrovsky /* Kernel PDE entry */ 991e620f9bSBoris Ostrovsky *(pl2p + ((PAGE_OFFSET >> PGDIR_SHIFT))) = pl2; 1001e620f9bSBoris Ostrovsky #endif 1011e620f9bSBoris Ostrovsky for (i = 0; i < PTRS_PER_PTE; i++) { 1021e620f9bSBoris Ostrovsky *ptep = pte; 1031e620f9bSBoris Ostrovsky pte.pte += PAGE_SIZE; 1041e620f9bSBoris Ostrovsky ptep++; 1051e620f9bSBoris Ostrovsky } 1061e620f9bSBoris Ostrovsky 1071e620f9bSBoris Ostrovsky pl2p++; 1081e620f9bSBoris Ostrovsky } 1091e620f9bSBoris Ostrovsky 1101e620f9bSBoris Ostrovsky ptr = (unsigned long *)__pa(&max_pfn_mapped); 1111e620f9bSBoris Ostrovsky /* Can't use pte_pfn() since it's a call with CONFIG_PARAVIRT */ 1121e620f9bSBoris Ostrovsky *ptr = (pte.pte & PTE_PFN_MASK) >> PAGE_SHIFT; 1131e620f9bSBoris Ostrovsky 1141e620f9bSBoris Ostrovsky ptr = (unsigned long *)__pa(&_brk_end); 1151e620f9bSBoris Ostrovsky *ptr = (unsigned long)ptep + PAGE_OFFSET; 1161e620f9bSBoris Ostrovsky } 1171e620f9bSBoris Ostrovsky 118