📄 head_32.s
字号:
/* * linux/arch/i386/kernel/head.S -- the 32-bit startup code. * * Copyright (C) 1991, 1992 Linus Torvalds * * Enhanced CPU detection and feature setting code by Mike Jagdis * and Martin Mares, November 1997. */.text#include <linux/threads.h>#include <linux/linkage.h>#include <asm/segment.h>#include <asm/page.h>#include <asm/pgtable.h>#include <asm/desc.h>#include <asm/cache.h>#include <asm/thread_info.h>#include <asm/asm-offsets.h>#include <asm/setup.h>/* * References to members of the new_cpu_data structure. */#define X86 new_cpu_data+CPUINFO_x86#define X86_VENDOR new_cpu_data+CPUINFO_x86_vendor#define X86_MODEL new_cpu_data+CPUINFO_x86_model#define X86_MASK new_cpu_data+CPUINFO_x86_mask#define X86_HARD_MATH new_cpu_data+CPUINFO_hard_math#define X86_CPUID new_cpu_data+CPUINFO_cpuid_level#define X86_CAPABILITY new_cpu_data+CPUINFO_x86_capability#define X86_VENDOR_ID new_cpu_data+CPUINFO_x86_vendor_id/* * This is how much memory *in addition to the memory covered up to * and including _end* we need mapped initially. * We need: * - one bit for each possible page, but only in low memory, which means * 2^32/4096/8 = 128K worst case (4G/4G split.) * - enough space to map all low memory, which means * (2^32/4096) / 1024 pages (worst case, non PAE) * (2^32/4096) / 512 + 4 pages (worst case for PAE) * - a few pages for allocator use before the kernel pagetable has * been set up * * Modulo rounding, each megabyte assigned here requires a kilobyte of * memory, which is currently unreclaimed. * * This should be a multiple of a page. */LOW_PAGES = 1<<(32-PAGE_SHIFT_asm)/* * To preserve the DMA pool in PAGEALLOC kernels, we'll allocate * pagetables from above the 16MB DMA limit, so we'll have to set * up pagetables 16MB more (worst-case): */#ifdef CONFIG_DEBUG_PAGEALLOCLOW_PAGES = LOW_PAGES + 0x1000000#endif#if PTRS_PER_PMD > 1PAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PMD) + PTRS_PER_PGD#elsePAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PGD)#endifBOOTBITMAP_SIZE = LOW_PAGES / 8ALLOCATOR_SLOP = 4INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + (PAGE_TABLE_SIZE + ALLOCATOR_SLOP)*PAGE_SIZE_asm/* * 32-bit kernel entrypoint; only used by the boot CPU. On entry, * %esi points to the real-mode code as a 32-bit pointer. * CS and DS must be 4 GB flat segments, but we don't depend on * any particular GDT layout, because we load our own as soon as we * can. */.section .text.head,"ax",@progbitsENTRY(startup_32) /* check to see if KEEP_SEGMENTS flag is meaningful */ cmpw $0x207, BP_version(%esi) jb 1f /* test KEEP_SEGMENTS flag to see if the bootloader is asking us to not reload segments */ testb $(1<<6), BP_loadflags(%esi) jnz 2f/* * Set segments to known values. */1: lgdt boot_gdt_descr - __PAGE_OFFSET movl $(__BOOT_DS),%eax movl %eax,%ds movl %eax,%es movl %eax,%fs movl %eax,%gs2:/* * Clear BSS first so that there are no surprises... */ cld xorl %eax,%eax movl $__bss_start - __PAGE_OFFSET,%edi movl $__bss_stop - __PAGE_OFFSET,%ecx subl %edi,%ecx shrl $2,%ecx rep ; stosl/* * Copy bootup parameters out of the way. * Note: %esi still has the pointer to the real-mode data. * With the kexec as boot loader, parameter segment might be loaded beyond * kernel image and might not even be addressable by early boot page tables. * (kexec on panic case). Hence copy out the parameters before initializing * page tables. */ movl $(boot_params - __PAGE_OFFSET),%edi movl $(PARAM_SIZE/4),%ecx cld rep movsl movl boot_params - __PAGE_OFFSET + NEW_CL_POINTER,%esi andl %esi,%esi jz 1f # No comand line movl $(boot_command_line - __PAGE_OFFSET),%edi movl $(COMMAND_LINE_SIZE/4),%ecx rep movsl1:#ifdef CONFIG_PARAVIRT cmpw $0x207, (boot_params + BP_version - __PAGE_OFFSET) jb default_entry /* Paravirt-compatible boot parameters. Look to see what architecture we're booting under. */ movl (boot_params + BP_hardware_subarch - __PAGE_OFFSET), %eax cmpl $num_subarch_entries, %eax jae bad_subarch movl subarch_entries - __PAGE_OFFSET(,%eax,4), %eax subl $__PAGE_OFFSET, %eax jmp *%eaxbad_subarch:WEAK(lguest_entry)WEAK(xen_entry) /* Unknown implementation; there's really nothing we can do at this point. */ ud2a.datasubarch_entries: .long default_entry /* normal x86/PC */ .long lguest_entry /* lguest hypervisor */ .long xen_entry /* Xen hypervisor */num_subarch_entries = (. - subarch_entries) / 4.previous#endif /* CONFIG_PARAVIRT *//* * Initialize page tables. This creates a PDE and a set of page * tables, which are located immediately beyond _end. The variable * init_pg_tables_end is set up to point to the first "safe" location. * Mappings are created both at virtual address 0 (identity mapping) * and PAGE_OFFSET for up to _end+sizeof(page tables)+INIT_MAP_BEYOND_END. * * Warning: don't use %esi or the stack in this code. However, %esp * can be used as a GPR if you really need it... */page_pde_offset = (__PAGE_OFFSET >> 20);default_entry: movl $(pg0 - __PAGE_OFFSET), %edi movl $(swapper_pg_dir - __PAGE_OFFSET), %edx movl $0x007, %eax /* 0x007 = PRESENT+RW+USER */10: leal 0x007(%edi),%ecx /* Create PDE entry */ movl %ecx,(%edx) /* Store identity PDE entry */ movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */ addl $4,%edx movl $1024, %ecx11: stosl addl $0x1000,%eax loop 11b /* End condition: we must map up to and including INIT_MAP_BEYOND_END */ /* bytes beyond the end of our own page tables; the +0x007 is the attribute bits */ leal (INIT_MAP_BEYOND_END+0x007)(%edi),%ebp cmpl %ebp,%eax jb 10b movl %edi,(init_pg_tables_end - __PAGE_OFFSET) /* Do an early initialization of the fixmap area */ movl $(swapper_pg_dir - __PAGE_OFFSET), %edx movl $(swapper_pg_pmd - __PAGE_OFFSET), %eax addl $0x67, %eax /* 0x67 == _PAGE_TABLE */ movl %eax, 4092(%edx) xorl %ebx,%ebx /* This is the boot CPU (BSP) */ jmp 3f/* * Non-boot CPU entry point; entered from trampoline.S * We can't lgdt here, because lgdt itself uses a data segment, but * we know the trampoline has already loaded the boot_gdt for us. * * If cpu hotplug is not supported then this code can go in init section * which will be freed later */#ifndef CONFIG_HOTPLUG_CPU.section .init.text,"ax",@progbits#endif#ifdef CONFIG_SMPENTRY(startup_32_smp) cld movl $(__BOOT_DS),%eax movl %eax,%ds movl %eax,%es movl %eax,%fs movl %eax,%gs/* * New page tables may be in 4Mbyte page mode and may * be using the global pages. * * NOTE! If we are on a 486 we may have no cr4 at all! * So we do not try to touch it unless we really have * some bits in it to set. This won't work if the BSP * implements cr4 but this AP does not -- very unlikely * but be warned! The same applies to the pse feature * if not equally supported. --macro * * NOTE! We have to correct for the fact that we're * not yet offset PAGE_OFFSET.. */#define cr4_bits mmu_cr4_features-__PAGE_OFFSET movl cr4_bits,%edx andl %edx,%edx jz 6f movl %cr4,%eax # Turn on paging options (PSE,PAE,..) orl %edx,%eax movl %eax,%cr4 btl $5, %eax # check if PAE is enabled jnc 6f /* Check if extended functions are implemented */ movl $0x80000000, %eax cpuid cmpl $0x80000000, %eax jbe 6f mov $0x80000001, %eax cpuid /* Execute Disable bit supported? */ btl $20, %edx jnc 6f /* Setup EFER (Extended Feature Enable Register) */ movl $0xc0000080, %ecx rdmsr btsl $11, %eax /* Make changes effective */ wrmsr6: /* This is a secondary processor (AP) */ xorl %ebx,%ebx incl %ebx#endif /* CONFIG_SMP */3:/* * Enable paging */ movl $swapper_pg_dir-__PAGE_OFFSET,%eax movl %eax,%cr3 /* set the page table pointer.. */ movl %cr0,%eax orl $0x80000000,%eax movl %eax,%cr0 /* ..and set paging (PG) bit */ ljmp $__BOOT_CS,$1f /* Clear prefetch and normalize %eip */1: /* Set up the stack pointer */ lss stack_start,%esp/* * Initialize eflags. Some BIOS's leave bits like NT set. This would * confuse the debugger if this code is traced. * XXX - best to initialize before switching to protected mode. */ pushl $0 popfl#ifdef CONFIG_SMP andl %ebx,%ebx jz 1f /* Initial CPU cleans BSS */ jmp checkCPUtype1:#endif /* CONFIG_SMP *//* * start system 32-bit setup. We need to re-do some of the things done * in 16-bit mode for the "real" operations. */ call setup_idtcheckCPUtype: movl $-1,X86_CPUID # -1 for no CPUID initially
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -