]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - arch/x86/kernel/head_32.S
Merge branch 'master' into tk71
[mv-sheeva.git] / arch / x86 / kernel / head_32.S
index fa8c1b8e09fb9f65b832c1fb15c84ee4c39b6336..767d6c43de372297daffc57ef3960d5b3c2a97ac 100644 (file)
 #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
 #endif
 
+/* Number of possible pages in the lowmem region */
+LOWMEM_PAGES = (((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT)
+       
 /* Enough space to fit pagetables for the low memory linear map */
-MAPPING_BEYOND_END = \
-       PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT
+MAPPING_BEYOND_END = PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT
 
 /*
  * Worst-case size of the kernel mapping we need to make:
- * the worst-case size of the kernel itself, plus the extra we need
- * to map for the linear map.
+ * a relocatable kernel can live anywhere in lowmem, so we need to be able
+ * to map all of lowmem.
  */
-KERNEL_PAGES = (KERNEL_IMAGE_SIZE + MAPPING_BEYOND_END)>>PAGE_SHIFT
+KERNEL_PAGES = LOWMEM_PAGES
 
 INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm
 RESERVE_BRK(pagetables, INIT_MAP_SIZE)
@@ -83,6 +85,8 @@ RESERVE_BRK(pagetables, INIT_MAP_SIZE)
  */
 __HEAD
 ENTRY(startup_32)
+       movl pa(stack_start),%ecx
+       
        /* test KEEP_SEGMENTS flag to see if the bootloader is asking
                us to not reload segments */
        testb $(1<<6), BP_loadflags(%esi)
@@ -97,7 +101,9 @@ ENTRY(startup_32)
        movl %eax,%es
        movl %eax,%fs
        movl %eax,%gs
+       movl %eax,%ss
 2:
+       leal -__PAGE_OFFSET(%ecx),%esp
 
 /*
  * Clear BSS first so that there are no surprises...
@@ -124,7 +130,7 @@ ENTRY(startup_32)
        movsl
        movl pa(boot_params) + NEW_CL_POINTER,%esi
        andl %esi,%esi
-       jz 1f                   # No comand line
+       jz 1f                   # No command line
        movl $pa(boot_command_line),%edi
        movl $(COMMAND_LINE_SIZE/4),%ecx
        rep
@@ -137,59 +143,22 @@ ENTRY(startup_32)
        movl %eax, pa(olpc_ofw_pgd)
 #endif
 
-#ifdef CONFIG_PARAVIRT
-       /* This is can only trip for a broken bootloader... */
-       cmpw $0x207, pa(boot_params + BP_version)
-       jb default_entry
-
-       /* Paravirt-compatible boot parameters.  Look to see what architecture
-               we're booting under. */
-       movl pa(boot_params + BP_hardware_subarch), %eax
-       cmpl $num_subarch_entries, %eax
-       jae bad_subarch
-
-       movl pa(subarch_entries)(,%eax,4), %eax
-       subl $__PAGE_OFFSET, %eax
-       jmp *%eax
-
-bad_subarch:
-WEAK(lguest_entry)
-WEAK(xen_entry)
-       /* Unknown implementation; there's really
-          nothing we can do at this point. */
-       ud2a
-
-       __INITDATA
-
-subarch_entries:
-       .long default_entry             /* normal x86/PC */
-       .long lguest_entry              /* lguest hypervisor */
-       .long xen_entry                 /* Xen hypervisor */
-       .long default_entry             /* Moorestown MID */
-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 __brk_base.  The variable
  * _brk_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.
- *
- * Note that the stack is not yet set up!
  */
-default_entry:
 #ifdef CONFIG_X86_PAE
 
        /*
-        * In PAE mode swapper_pg_dir is statically defined to contain enough
-        * entries to cover the VMSPLIT option (that is the top 1, 2 or 3
-        * entries). The identity mapping is handled by pointing two PGD
-        * entries to the first kernel PMD.
+        * In PAE mode initial_page_table is statically defined to contain
+        * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3
+        * entries). The identity mapping is handled by pointing two PGD entries
+        * to the first kernel PMD.
         *
-        * Note the upper half of each PMD or PTE are always zero at
-        * this stage.
+        * Note the upper half of each PMD or PTE are always zero at this stage.
         */
 
 #define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */
@@ -197,7 +166,7 @@ default_entry:
        xorl %ebx,%ebx                          /* %ebx is kept at zero */
 
        movl $pa(__brk_base), %edi
-       movl $pa(swapper_pg_pmd), %edx
+       movl $pa(initial_pg_pmd), %edx
        movl $PTE_IDENT_ATTR, %eax
 10:
        leal PDE_IDENT_ATTR(%edi),%ecx          /* Create PMD entry */
@@ -226,14 +195,14 @@ default_entry:
        movl %eax, pa(max_pfn_mapped)
 
        /* Do early initialization of the fixmap area */
-       movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax
-       movl %eax,pa(swapper_pg_pmd+0x1000*KPMDS-8)
+       movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+       movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8)
 #else  /* Not PAE */
 
 page_pde_offset = (__PAGE_OFFSET >> 20);
 
        movl $pa(__brk_base), %edi
-       movl $pa(swapper_pg_dir), %edx
+       movl $pa(initial_page_table), %edx
        movl $PTE_IDENT_ATTR, %eax
 10:
        leal PDE_IDENT_ATTR(%edi),%ecx          /* Create PDE entry */
@@ -257,10 +226,45 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
        movl %eax, pa(max_pfn_mapped)
 
        /* Do early initialization of the fixmap area */
-       movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax
-       movl %eax,pa(swapper_pg_dir+0xffc)
+       movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+       movl %eax,pa(initial_page_table+0xffc)
 #endif
-       jmp 3f
+
+#ifdef CONFIG_PARAVIRT
+       /* This is can only trip for a broken bootloader... */
+       cmpw $0x207, pa(boot_params + BP_version)
+       jb default_entry
+
+       /* Paravirt-compatible boot parameters.  Look to see what architecture
+               we're booting under. */
+       movl pa(boot_params + BP_hardware_subarch), %eax
+       cmpl $num_subarch_entries, %eax
+       jae bad_subarch
+
+       movl pa(subarch_entries)(,%eax,4), %eax
+       subl $__PAGE_OFFSET, %eax
+       jmp *%eax
+
+bad_subarch:
+WEAK(lguest_entry)
+WEAK(xen_entry)
+       /* Unknown implementation; there's really
+          nothing we can do at this point. */
+       ud2a
+
+       __INITDATA
+
+subarch_entries:
+       .long default_entry             /* normal x86/PC */
+       .long lguest_entry              /* lguest hypervisor */
+       .long xen_entry                 /* Xen hypervisor */
+       .long default_entry             /* Moorestown MID */
+num_subarch_entries = (. - subarch_entries) / 4
+.previous
+#else
+       jmp default_entry
+#endif /* CONFIG_PARAVIRT */
+
 /*
  * Non-boot CPU entry point; entered from trampoline.S
  * We can't lgdt here, because lgdt itself uses a data segment, but
@@ -280,8 +284,11 @@ ENTRY(startup_32_smp)
        movl %eax,%es
        movl %eax,%fs
        movl %eax,%gs
+       movl pa(stack_start),%ecx
+       movl %eax,%ss
+       leal -__PAGE_OFFSET(%ecx),%esp
 #endif /* CONFIG_SMP */
-3:
+default_entry:
 
 /*
  *     New page tables may be in 4Mbyte page mode and may
@@ -315,6 +322,10 @@ ENTRY(startup_32_smp)
        subl $0x80000001, %eax
        cmpl $(0x8000ffff-0x80000001), %eax
        ja 6f
+
+       /* Clear bogus XD_DISABLE bits */
+       call verify_cpu
+
        mov $0x80000001, %eax
        cpuid
        /* Execute Disable bit supported? */
@@ -334,15 +345,15 @@ ENTRY(startup_32_smp)
 /*
  * Enable paging
  */
-       movl pa(initial_page_table), %eax
+       movl $pa(initial_page_table), %eax
        movl %eax,%cr3          /* set the page table pointer.. */
        movl %cr0,%eax
        orl  $X86_CR0_PG,%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
+       /* Shift the stack pointer to a virtual address */
+       addl $__PAGE_OFFSET, %esp
 
 /*
  * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
@@ -354,9 +365,7 @@ ENTRY(startup_32_smp)
 
 #ifdef CONFIG_SMP
        cmpb $0, ready
-       jz  1f                          /* Initial CPU cleans BSS */
-       jmp checkCPUtype
-1:
+       jnz checkCPUtype
 #endif /* CONFIG_SMP */
 
 /*
@@ -464,14 +473,7 @@ is386:     movl $2,%ecx            # set MP
 
        cld                     # gcc2 wants the direction flag cleared at all times
        pushl $0                # fake return address for unwinder
-#ifdef CONFIG_SMP
-       movb ready, %cl
        movb $1, ready
-       cmpb $0,%cl             # the first CPU calls start_kernel
-       je   1f
-       movl (stack_start), %esp
-1:
-#endif /* CONFIG_SMP */
        jmp *(initial_code)
 
 /*
@@ -610,12 +612,12 @@ ignore_int:
 #endif
        iret
 
+#include "verify_cpu.S"
+
        __REFDATA
 .align 4
 ENTRY(initial_code)
        .long i386_start_kernel
-ENTRY(initial_page_table)
-       .long pa(swapper_pg_dir)
 
 /*
  * BSS section
@@ -623,20 +625,18 @@ ENTRY(initial_page_table)
 __PAGE_ALIGNED_BSS
        .align PAGE_SIZE_asm
 #ifdef CONFIG_X86_PAE
-swapper_pg_pmd:
+initial_pg_pmd:
        .fill 1024*KPMDS,4,0
 #else
-ENTRY(swapper_pg_dir)
+ENTRY(initial_page_table)
        .fill 1024,4,0
 #endif
-swapper_pg_fixmap:
-       .fill 1024,4,0
-#ifdef CONFIG_X86_TRAMPOLINE
-ENTRY(trampoline_pg_dir)
+initial_pg_fixmap:
        .fill 1024,4,0
-#endif
 ENTRY(empty_zero_page)
        .fill 4096,1,0
+ENTRY(swapper_pg_dir)
+       .fill 1024,4,0
 
 /*
  * This starts the data section.
@@ -645,20 +645,20 @@ ENTRY(empty_zero_page)
 __PAGE_ALIGNED_DATA
        /* Page-aligned for the benefit of paravirt? */
        .align PAGE_SIZE_asm
-ENTRY(swapper_pg_dir)
-       .long   pa(swapper_pg_pmd+PGD_IDENT_ATTR),0     /* low identity map */
+ENTRY(initial_page_table)
+       .long   pa(initial_pg_pmd+PGD_IDENT_ATTR),0     /* low identity map */
 # if KPMDS == 3
-       .long   pa(swapper_pg_pmd+PGD_IDENT_ATTR),0
-       .long   pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0
-       .long   pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x2000),0
+       .long   pa(initial_pg_pmd+PGD_IDENT_ATTR),0
+       .long   pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0
+       .long   pa(initial_pg_pmd+PGD_IDENT_ATTR+0x2000),0
 # elif KPMDS == 2
        .long   0,0
-       .long   pa(swapper_pg_pmd+PGD_IDENT_ATTR),0
-       .long   pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0
+       .long   pa(initial_pg_pmd+PGD_IDENT_ATTR),0
+       .long   pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0
 # elif KPMDS == 1
        .long   0,0
        .long   0,0
-       .long   pa(swapper_pg_pmd+PGD_IDENT_ATTR),0
+       .long   pa(initial_pg_pmd+PGD_IDENT_ATTR),0
 # else
 #  error "Kernel PMDs should be 1, 2 or 3"
 # endif
@@ -666,15 +666,15 @@ ENTRY(swapper_pg_dir)
 #endif
 
 .data
+.balign 4
 ENTRY(stack_start)
        .long init_thread_union+THREAD_SIZE
-       .long __BOOT_DS
-
-ready: .byte 0
 
 early_recursion_flag:
        .long 0
 
+ready: .byte 0
+
 int_msg:
        .asciz "Unknown interrupt or fault at: %p %p %p\n"