x86: fix fault_msg nul termination
[sfrench/cifs-2.6.git] / arch / x86 / kernel / head_32.S
index 9150ca9b5f809285e987d1ed84db3b353357ae16..74d87ea85b5cdfa360a10a5b79ba33a8e38a60e5 100644 (file)
@@ -9,6 +9,7 @@
 
 .text
 #include <linux/threads.h>
+#include <linux/init.h>
 #include <linux/linkage.h>
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/thread_info.h>
 #include <asm/asm-offsets.h>
 #include <asm/setup.h>
+#include <asm/processor-flags.h>
+
+/* Physical address */
+#define pa(X) ((X) - __PAGE_OFFSET)
 
 /*
  * References to members of the new_cpu_data structure.
  */
 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_PAGEALLOC
+LOW_PAGES = LOW_PAGES + 0x1000000
+#endif
+
 #if PTRS_PER_PMD > 1
 PAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PMD) + PTRS_PER_PGD
 #else
@@ -70,25 +84,29 @@ INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + (PAGE_TABLE_SIZE + ALLOCATOR_SLOP)*PAGE_
  */
 .section .text.head,"ax",@progbits
 ENTRY(startup_32)
+       /* 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.
  */
-       cld
-       lgdt boot_gdt_descr - __PAGE_OFFSET
+       lgdt pa(boot_gdt_descr)
        movl $(__BOOT_DS),%eax
        movl %eax,%ds
        movl %eax,%es
        movl %eax,%fs
        movl %eax,%gs
+2:
 
 /*
  * Clear BSS first so that there are no surprises...
- * No need to cld as DF is already clear from cld above...
  */
+       cld
        xorl %eax,%eax
-       movl $__bss_start - __PAGE_OFFSET,%edi
-       movl $__bss_stop - __PAGE_OFFSET,%ecx
+       movl $pa(__bss_start),%edi
+       movl $pa(__bss_stop),%ecx
        subl %edi,%ecx
        shrl $2,%ecx
        rep ; stosl
@@ -100,25 +118,52 @@ ENTRY(startup_32)
  * (kexec on panic case). Hence copy out the parameters before initializing
  * page tables.
  */
-       movl $(boot_params - __PAGE_OFFSET),%edi
+       movl $pa(boot_params),%edi
        movl $(PARAM_SIZE/4),%ecx
        cld
        rep
        movsl
-       movl boot_params - __PAGE_OFFSET + NEW_CL_POINTER,%esi
+       movl pa(boot_params) + NEW_CL_POINTER,%esi
        andl %esi,%esi
-       jnz 2f                  # New command line protocol
-       cmpw $(OLD_CL_MAGIC),OLD_CL_MAGIC_ADDR
-       jne 1f
-       movzwl OLD_CL_OFFSET,%esi
-       addl $(OLD_CL_BASE_ADDR),%esi
-2:
-       movl $(boot_command_line - __PAGE_OFFSET),%edi
+       jz 1f                   # No comand line
+       movl $pa(boot_command_line),%edi
        movl $(COMMAND_LINE_SIZE/4),%ecx
        rep
        movsl
 1:
 
+#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 */
+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
@@ -126,16 +171,68 @@ ENTRY(startup_32)
  * 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...
+ * Note that the stack is not yet set up!
  */
+#define PTE_ATTR       0x007           /* PRESENT+RW+USER */
+#define PDE_ATTR       0x067           /* PRESENT+RW+USER+DIRTY+ACCESSED */
+#define PGD_ATTR       0x001           /* PRESENT (no other attributes) */
+
+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.
+        *
+        * Note the upper half of each PMD or PTE are always zero at
+        * this stage.
+        */
+
+#define KPMDS ((0x100000000-__PAGE_OFFSET) >> 30) /* Number of kernel PMDs */
+
+       xorl %ebx,%ebx                          /* %ebx is kept at zero */
+
+       movl $pa(pg0), %edi
+       movl $pa(swapper_pg_pmd), %edx
+       movl $PTE_ATTR, %eax
+10:
+       leal PDE_ATTR(%edi),%ecx                /* Create PMD entry */
+       movl %ecx,(%edx)                        /* Store PMD entry */
+                                               /* Upper half already zero */
+       addl $8,%edx
+       movl $512,%ecx
+11:
+       stosl
+       xchgl %eax,%ebx
+       stosl
+       xchgl %eax,%ebx
+       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.
+        */
+       leal (INIT_MAP_BEYOND_END+PTE_ATTR)(%edi),%ebp
+       cmpl %ebp,%eax
+       jb 10b
+1:
+       movl %edi,pa(init_pg_tables_end)
+
+       /* Do early initialization of the fixmap area */
+       movl $pa(swapper_pg_fixmap)+PDE_ATTR,%eax
+       movl %eax,pa(swapper_pg_pmd+0x1000*KPMDS-8)
+#else  /* Not PAE */
+
 page_pde_offset = (__PAGE_OFFSET >> 20);
 
-       movl $(pg0 - __PAGE_OFFSET), %edi
-       movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
-       movl $0x007, %eax                       /* 0x007 = PRESENT+RW+USER */
+       movl $pa(pg0), %edi
+       movl $pa(swapper_pg_dir), %edx
+       movl $PTE_ATTR, %eax
 10:
-       leal 0x007(%edi),%ecx                   /* Create PDE entry */
+       leal PDE_ATTR(%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
@@ -144,14 +241,20 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
        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
+       /*
+        * 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+PTE_ATTR)(%edi),%ebp
        cmpl %ebp,%eax
        jb 10b
-       movl %edi,(init_pg_tables_end - __PAGE_OFFSET)
+       movl %edi,pa(init_pg_tables_end)
 
-       xorl %ebx,%ebx                          /* This is the boot CPU (BSP) */
+       /* Do early initialization of the fixmap area */
+       movl $pa(swapper_pg_fixmap)+PDE_ATTR,%eax
+       movl %eax,pa(swapper_pg_dir+0xffc)
+#endif
        jmp 3f
 /*
  * Non-boot CPU entry point; entered from trampoline.S
@@ -166,12 +269,6 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
 .section .init.text,"ax",@progbits
 #endif
 
-       /* Do an early initialization of the fixmap area */
-       movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
-       movl $(swapper_pg_pmd - __PAGE_OFFSET), %eax
-       addl $0x007, %eax                       /* 0x007 = PRESENT+RW+USER */
-       movl %eax, 4092(%edx)
-
 #ifdef CONFIG_SMP
 ENTRY(startup_32_smp)
        cld
@@ -180,6 +277,8 @@ ENTRY(startup_32_smp)
        movl %eax,%es
        movl %eax,%fs
        movl %eax,%gs
+#endif /* CONFIG_SMP */
+3:
 
 /*
  *     New page tables may be in 4Mbyte page mode and may
@@ -195,7 +294,7 @@ ENTRY(startup_32_smp)
  *     NOTE! We have to correct for the fact that we're
  *     not yet offset PAGE_OFFSET..
  */
-#define cr4_bits mmu_cr4_features-__PAGE_OFFSET
+#define cr4_bits pa(mmu_cr4_features)
        movl cr4_bits,%edx
        andl %edx,%edx
        jz 6f
@@ -226,20 +325,14 @@ ENTRY(startup_32_smp)
        wrmsr
 
 6:
-       /* 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 $pa(swapper_pg_dir),%eax
        movl %eax,%cr3          /* set the page table pointer.. */
        movl %cr0,%eax
-       orl $0x80000000,%eax
+       orl  $X86_CR0_PG,%eax
        movl %eax,%cr0          /* ..and set paging (PG) bit */
        ljmp $__BOOT_CS,$1f     /* Clear prefetch and normalize %eip */
 1:
@@ -255,7 +348,7 @@ ENTRY(startup_32_smp)
        popfl
 
 #ifdef CONFIG_SMP
-       andl %ebx,%ebx
+       cmpb $0, ready
        jz  1f                          /* Initial CPU cleans BSS */
        jmp checkCPUtype
 1:
@@ -443,6 +536,7 @@ early_page_fault:
 early_fault:
        cld
 #ifdef CONFIG_PRINTK
+       pusha
        movl $(__KERNEL_DS),%eax
        movl %eax,%ds
        movl %eax,%es
@@ -459,6 +553,7 @@ early_fault:
        call printk
 #endif
 #endif
+       call dump_stack
 hlt_loop:
        hlt
        jmp hlt_loop
@@ -510,16 +605,44 @@ ENTRY(_stext)
  */
 .section ".bss.page_aligned","wa"
        .align PAGE_SIZE_asm
+#ifdef CONFIG_X86_PAE
+swapper_pg_pmd:
+       .fill 1024*KPMDS,4,0
+#else
 ENTRY(swapper_pg_dir)
        .fill 1024,4,0
-ENTRY(swapper_pg_pmd)
+#endif
+swapper_pg_fixmap:
        .fill 1024,4,0
 ENTRY(empty_zero_page)
        .fill 4096,1,0
-
 /*
  * This starts the data section.
  */
+#ifdef CONFIG_X86_PAE
+.section ".data.page_aligned","wa"
+       /* Page-aligned for the benefit of paravirt? */
+       .align PAGE_SIZE_asm
+ENTRY(swapper_pg_dir)
+       .long   pa(swapper_pg_pmd+PGD_ATTR),0           /* low identity map */
+# if KPMDS == 3
+       .long   pa(swapper_pg_pmd+PGD_ATTR),0
+       .long   pa(swapper_pg_pmd+PGD_ATTR+0x1000),0
+       .long   pa(swapper_pg_pmd+PGD_ATTR+0x2000),0
+# elif KPMDS == 2
+       .long   0,0
+       .long   pa(swapper_pg_pmd+PGD_ATTR),0
+       .long   pa(swapper_pg_pmd+PGD_ATTR+0x1000),0
+# elif KPMDS == 1
+       .long   0,0
+       .long   0,0
+       .long   pa(swapper_pg_pmd+PGD_ATTR),0
+# else
+#  error "Kernel PMDs should be 1, 2 or 3"
+# endif
+       .align PAGE_SIZE_asm            /* needs to be page-sized too */
+#endif
+
 .data
 ENTRY(stack_start)
        .long init_thread_union+THREAD_SIZE
@@ -534,8 +657,15 @@ int_msg:
        .asciz "Unknown interrupt or fault at EIP %p %p %p\n"
 
 fault_msg:
-       .ascii "Int %d: CR2 %p  err %p  EIP %p  CS %p  flags %p\n"
-       .asciz "Stack: %p %p %p %p %p %p %p %p\n"
+       .asciz                                                          \
+/* fault info: */      "BUG: Int %d: CR2 %p\n"                         \
+/* pusha regs: */      "     EDI %p  ESI %p  EBP %p  ESP %p\n"         \
+                       "     EBX %p  EDX %p  ECX %p  EAX %p\n"         \
+/* fault frame: */     "     err %p  EIP %p   CS %p  flg %p\n"         \
+                                                                       \
+                       "Stack: %p %p %p %p %p %p %p %p\n"              \
+                       "       %p %p %p %p %p %p %p %p\n"              \
+                       "       %p %p %p %p %p %p %p %p\n"
 
 #include "../../x86/xen/xen-head.S"