1/* 2 * linux/arch/i386/kernel/head.S -- the 32-bit startup code. 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 * 6 * Enhanced CPU detection and feature setting code by Mike Jagdis 7 * and Martin Mares, November 1997. 8 */ 9 10.text 11#include <linux/threads.h> 12#include <linux/linkage.h> 13#include <asm/segment.h> 14#include <asm/page.h> 15#include <asm/pgtable.h> 16#include <asm/desc.h> 17#include <asm/cache.h> 18#include <asm/thread_info.h> 19#include <asm/asm-offsets.h> 20#include <asm/setup.h> 21 22/* 23 * References to members of the new_cpu_data structure. 24 */ 25 26#define X86 new_cpu_data+CPUINFO_x86 27#define X86_VENDOR new_cpu_data+CPUINFO_x86_vendor 28#define X86_MODEL new_cpu_data+CPUINFO_x86_model 29#define X86_MASK new_cpu_data+CPUINFO_x86_mask 30#define X86_HARD_MATH new_cpu_data+CPUINFO_hard_math 31#define X86_CPUID new_cpu_data+CPUINFO_cpuid_level 32#define X86_CAPABILITY new_cpu_data+CPUINFO_x86_capability 33#define X86_VENDOR_ID new_cpu_data+CPUINFO_x86_vendor_id 34 35/* 36 * This is how much memory *in addition to the memory covered up to 37 * and including _end* we need mapped initially. 38 * We need: 39 * - one bit for each possible page, but only in low memory, which means 40 * 2^32/4096/8 = 128K worst case (4G/4G split.) 41 * - enough space to map all low memory, which means 42 * (2^32/4096) / 1024 pages (worst case, non PAE) 43 * (2^32/4096) / 512 + 4 pages (worst case for PAE) 44 * - a few pages for allocator use before the kernel pagetable has 45 * been set up 46 * 47 * Modulo rounding, each megabyte assigned here requires a kilobyte of 48 * memory, which is currently unreclaimed. 49 * 50 * This should be a multiple of a page. 51 */ 52LOW_PAGES = 1<<(32-PAGE_SHIFT_asm) 53 54#if PTRS_PER_PMD > 1 55PAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PMD) + PTRS_PER_PGD 56#else 57PAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PGD) 58#endif 59BOOTBITMAP_SIZE = LOW_PAGES / 8 60ALLOCATOR_SLOP = 4 61 62INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + (PAGE_TABLE_SIZE + ALLOCATOR_SLOP)*PAGE_SIZE_asm 63 64/* 65 * 32-bit kernel entrypoint; only used by the boot CPU. On entry, 66 * %esi points to the real-mode code as a 32-bit pointer. 67 * CS and DS must be 4 GB flat segments, but we don't depend on 68 * any particular GDT layout, because we load our own as soon as we 69 * can. 70 */ 71.section .text.head,"ax",@progbits 72ENTRY(startup_32) 73 74/* 75 * Set segments to known values. 76 */ 77 cld 78 lgdt boot_gdt_descr - __PAGE_OFFSET 79 movl $(__BOOT_DS),%eax 80 movl %eax,%ds 81 movl %eax,%es 82 movl %eax,%fs 83 movl %eax,%gs 84 85/* 86 * Clear BSS first so that there are no surprises... 87 * No need to cld as DF is already clear from cld above... 88 */ 89 xorl %eax,%eax 90 movl $__bss_start - __PAGE_OFFSET,%edi 91 movl $__bss_stop - __PAGE_OFFSET,%ecx 92 subl %edi,%ecx 93 shrl $2,%ecx 94 rep ; stosl 95/* 96 * Copy bootup parameters out of the way. 97 * Note: %esi still has the pointer to the real-mode data. 98 * With the kexec as boot loader, parameter segment might be loaded beyond 99 * kernel image and might not even be addressable by early boot page tables. 100 * (kexec on panic case). Hence copy out the parameters before initializing 101 * page tables. 102 */ 103 movl $(boot_params - __PAGE_OFFSET),%edi 104 movl $(PARAM_SIZE/4),%ecx 105 cld 106 rep 107 movsl 108 movl boot_params - __PAGE_OFFSET + NEW_CL_POINTER,%esi 109 andl %esi,%esi 110 jnz 2f # New command line protocol 111 cmpw $(OLD_CL_MAGIC),OLD_CL_MAGIC_ADDR 112 jne 1f 113 movzwl OLD_CL_OFFSET,%esi 114 addl $(OLD_CL_BASE_ADDR),%esi 1152: 116 movl $(boot_command_line - __PAGE_OFFSET),%edi 117 movl $(COMMAND_LINE_SIZE/4),%ecx 118 rep 119 movsl 1201: 121 122/* 123 * Initialize page tables. This creates a PDE and a set of page 124 * tables, which are located immediately beyond _end. The variable 125 * init_pg_tables_end is set up to point to the first "safe" location. 126 * Mappings are created both at virtual address 0 (identity mapping) 127 * and PAGE_OFFSET for up to _end+sizeof(page tables)+INIT_MAP_BEYOND_END. 128 * 129 * Warning: don't use %esi or the stack in this code. However, %esp 130 * can be used as a GPR if you really need it... 131 */ 132page_pde_offset = (__PAGE_OFFSET >> 20); 133 134 movl $(pg0 - __PAGE_OFFSET), %edi 135 movl $(swapper_pg_dir - __PAGE_OFFSET), %edx 136 movl $0x007, %eax /* 0x007 = PRESENT+RW+USER */ 13710: 138 leal 0x007(%edi),%ecx /* Create PDE entry */ 139 movl %ecx,(%edx) /* Store identity PDE entry */ 140 movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */ 141 addl $4,%edx 142 movl $1024, %ecx 14311: 144 stosl 145 addl $0x1000,%eax 146 loop 11b 147 /* End condition: we must map up to and including INIT_MAP_BEYOND_END */ 148 /* bytes beyond the end of our own page tables; the +0x007 is the attribute bits */ 149 leal (INIT_MAP_BEYOND_END+0x007)(%edi),%ebp 150 cmpl %ebp,%eax 151 jb 10b 152 movl %edi,(init_pg_tables_end - __PAGE_OFFSET) 153 154 xorl %ebx,%ebx /* This is the boot CPU (BSP) */ 155 jmp 3f 156/* 157 * Non-boot CPU entry point; entered from trampoline.S 158 * We can't lgdt here, because lgdt itself uses a data segment, but 159 * we know the trampoline has already loaded the boot_gdt for us. 160 * 161 * If cpu hotplug is not supported then this code can go in init section 162 * which will be freed later 163 */ 164 165#ifdef CONFIG_HOTPLUG_CPU 166.section .text,"ax",@progbits 167#else 168.section .init.text,"ax",@progbits 169#endif 170 171#ifdef CONFIG_SMP 172ENTRY(startup_32_smp) 173 cld 174 movl $(__BOOT_DS),%eax 175 movl %eax,%ds 176 movl %eax,%es 177 movl %eax,%fs 178 movl %eax,%gs 179 180/* 181 * New page tables may be in 4Mbyte page mode and may 182 * be using the global pages. 183 * 184 * NOTE! If we are on a 486 we may have no cr4 at all! 185 * So we do not try to touch it unless we really have 186 * some bits in it to set. This won't work if the BSP 187 * implements cr4 but this AP does not -- very unlikely 188 * but be warned! The same applies to the pse feature 189 * if not equally supported. --macro 190 * 191 * NOTE! We have to correct for the fact that we're 192 * not yet offset PAGE_OFFSET.. 193 */ 194#define cr4_bits mmu_cr4_features-__PAGE_OFFSET 195 movl cr4_bits,%edx 196 andl %edx,%edx 197 jz 6f 198 movl %cr4,%eax # Turn on paging options (PSE,PAE,..) 199 orl %edx,%eax 200 movl %eax,%cr4 201 202 btl $5, %eax # check if PAE is enabled 203 jnc 6f 204 205 /* Check if extended functions are implemented */ 206 movl $0x80000000, %eax 207 cpuid 208 cmpl $0x80000000, %eax 209 jbe 6f 210 mov $0x80000001, %eax 211 cpuid 212 /* Execute Disable bit supported? */ 213 btl $20, %edx 214 jnc 6f 215 216 /* Setup EFER (Extended Feature Enable Register) */ 217 movl $0xc0000080, %ecx 218 rdmsr 219 220 btsl $11, %eax 221 /* Make changes effective */ 222 wrmsr 223 2246: 225 /* This is a secondary processor (AP) */ 226 xorl %ebx,%ebx 227 incl %ebx 228 229#endif /* CONFIG_SMP */ 2303: 231 232/* 233 * Enable paging 234 */ 235 movl $swapper_pg_dir-__PAGE_OFFSET,%eax 236 movl %eax,%cr3 /* set the page table pointer.. */ 237 movl %cr0,%eax 238 orl $0x80000000,%eax 239 movl %eax,%cr0 /* ..and set paging (PG) bit */ 240 ljmp $__BOOT_CS,$1f /* Clear prefetch and normalize %eip */ 2411: 242 /* Set up the stack pointer */ 243 lss stack_start,%esp 244 245 pushl $0 246 popfl 247 248#ifdef CONFIG_SMP 249 andl %ebx,%ebx 250 jz 1f /* Initial CPU cleans BSS */ 251 jmp checkCPUtype 2521: 253#endif /* CONFIG_SMP */ 254 255/* 256 * start system 32-bit setup. We need to re-do some of the things done 257 * in 16-bit mode for the "real" operations. 258 */ 259 call setup_idt 260 261checkCPUtype: 262 263 movl $-1,X86_CPUID # -1 for no CPUID initially 264 265/* check if it is 486 or 386. */ 266 267 movb $3,X86 # at least 386 268 pushfl # push EFLAGS 269 popl %eax # get EFLAGS 270 movl %eax,%ecx # save original EFLAGS 271 xorl $0x240000,%eax # flip AC and ID bits in EFLAGS 272 pushl %eax # copy to EFLAGS 273 popfl # set EFLAGS 274 pushfl # get new EFLAGS 275 popl %eax # put it in eax 276 xorl %ecx,%eax # change in flags 277 pushl %ecx # restore original EFLAGS 278 popfl 279 testl $0x40000,%eax # check if AC bit changed 280 je is386 281 282 movb $4,X86 # at least 486 283 testl $0x200000,%eax # check if ID bit changed 284 je is486 285 286 /* get vendor info */ 287 xorl %eax,%eax # call CPUID with 0 -> return vendor ID 288 cpuid 289 movl %eax,X86_CPUID # save CPUID level 290 movl %ebx,X86_VENDOR_ID # lo 4 chars 291 movl %edx,X86_VENDOR_ID+4 # next 4 chars 292 movl %ecx,X86_VENDOR_ID+8 # last 4 chars 293 294 orl %eax,%eax # do we have processor info as well? 295 je is486 296 297 movl $1,%eax # Use the CPUID instruction to get CPU type 298 cpuid 299 movb %al,%cl # save reg for future use 300 andb $0x0f,%ah # mask processor family 301 movb %ah,X86 302 andb $0xf0,%al # mask model 303 shrb $4,%al 304 movb %al,X86_MODEL 305 andb $0x0f,%cl # mask mask revision 306 movb %cl,X86_MASK 307 movl %edx,X86_CAPABILITY 308 309is486: movl $0x50022,%ecx # set AM, WP, NE and MP 310 jmp 2f 311 312is386: movl $2,%ecx # set MP 3132: movl %cr0,%eax 314 andl $0x80000011,%eax # Save PG,PE,ET 315 orl %ecx,%eax 316 movl %eax,%cr0 317 318 call check_x87 319 lgdt early_gdt_descr 320 lidt idt_descr 321 ljmp $(__KERNEL_CS),$1f 3221: movl $(__KERNEL_DS),%eax # reload all the segment registers 323 movl %eax,%ss # after changing gdt. 324 movl %eax,%fs # gets reset once there's real percpu 325 326 movl $(__USER_DS),%eax # DS/ES contains default USER segment 327 movl %eax,%ds 328 movl %eax,%es 329 330 xorl %eax,%eax # Clear GS and LDT 331 movl %eax,%gs 332 lldt %ax 333 334 cld # gcc2 wants the direction flag cleared at all times 335 pushl $0 # fake return address for unwinder 336#ifdef CONFIG_SMP 337 movb ready, %cl 338 movb $1, ready 339 cmpb $0,%cl # the first CPU calls start_kernel 340 je 1f 341 movl $(__KERNEL_PERCPU), %eax 342 movl %eax,%fs # set this cpu's percpu 343 jmp initialize_secondary # all other CPUs call initialize_secondary 3441: 345#endif /* CONFIG_SMP */ 346 jmp start_kernel 347 348/* 349 * We depend on ET to be correct. This checks for 287/387. 350 */ 351check_x87: 352 movb $0,X86_HARD_MATH 353 clts 354 fninit 355 fstsw %ax 356 cmpb $0,%al 357 je 1f 358 movl %cr0,%eax /* no coprocessor: have to set bits */ 359 xorl $4,%eax /* set EM */ 360 movl %eax,%cr0 361 ret 362 ALIGN 3631: movb $1,X86_HARD_MATH 364 .byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */ 365 ret 366 367/* 368 * setup_idt 369 * 370 * sets up a idt with 256 entries pointing to 371 * ignore_int, interrupt gates. It doesn't actually load 372 * idt - that can be done only after paging has been enabled 373 * and the kernel moved to PAGE_OFFSET. Interrupts 374 * are enabled elsewhere, when we can be relatively 375 * sure everything is ok. 376 * 377 * Warning: %esi is live across this function. 378 */ 379setup_idt: 380 lea ignore_int,%edx 381 movl $(__KERNEL_CS << 16),%eax 382 movw %dx,%ax /* selector = 0x0010 = cs */ 383 movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ 384 385 lea idt_table,%edi 386 mov $256,%ecx 387rp_sidt: 388 movl %eax,(%edi) 389 movl %edx,4(%edi) 390 addl $8,%edi 391 dec %ecx 392 jne rp_sidt 393 394.macro set_early_handler handler,trapno 395 lea \handler,%edx 396 movl $(__KERNEL_CS << 16),%eax 397 movw %dx,%ax 398 movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ 399 lea idt_table,%edi 400 movl %eax,8*\trapno(%edi) 401 movl %edx,8*\trapno+4(%edi) 402.endm 403 404 set_early_handler handler=early_divide_err,trapno=0 405 set_early_handler handler=early_illegal_opcode,trapno=6 406 set_early_handler handler=early_protection_fault,trapno=13 407 set_early_handler handler=early_page_fault,trapno=14 408 409 ret 410 411early_divide_err: 412 xor %edx,%edx 413 pushl $0 /* fake errcode */ 414 jmp early_fault 415 416early_illegal_opcode: 417 movl $6,%edx 418 pushl $0 /* fake errcode */ 419 jmp early_fault 420 421early_protection_fault: 422 movl $13,%edx 423 jmp early_fault 424 425early_page_fault: 426 movl $14,%edx 427 jmp early_fault 428 429early_fault: 430 cld 431#ifdef CONFIG_PRINTK 432 movl $(__KERNEL_DS),%eax 433 movl %eax,%ds 434 movl %eax,%es 435 cmpl $2,early_recursion_flag 436 je hlt_loop 437 incl early_recursion_flag 438 movl %cr2,%eax 439 pushl %eax 440 pushl %edx /* trapno */ 441 pushl $fault_msg 442#ifdef CONFIG_EARLY_PRINTK 443 call early_printk 444#else 445 call printk 446#endif 447#endif 448hlt_loop: 449 hlt 450 jmp hlt_loop 451 452/* This is the default interrupt "handler" :-) */ 453 ALIGN 454ignore_int: 455 cld 456#ifdef CONFIG_PRINTK 457 pushl %eax 458 pushl %ecx 459 pushl %edx 460 pushl %es 461 pushl %ds 462 movl $(__KERNEL_DS),%eax 463 movl %eax,%ds 464 movl %eax,%es 465 cmpl $2,early_recursion_flag 466 je hlt_loop 467 incl early_recursion_flag 468 pushl 16(%esp) 469 pushl 24(%esp) 470 pushl 32(%esp) 471 pushl 40(%esp) 472 pushl $int_msg 473#ifdef CONFIG_EARLY_PRINTK 474 call early_printk 475#else 476 call printk 477#endif 478 addl $(5*4),%esp 479 popl %ds 480 popl %es 481 popl %edx 482 popl %ecx 483 popl %eax 484#endif 485 iret 486 487.section .text 488/* 489 * Real beginning of normal "text" segment 490 */ 491ENTRY(stext) 492ENTRY(_stext) 493 494/* 495 * BSS section 496 */ 497.section ".bss.page_aligned","w" 498ENTRY(swapper_pg_dir) 499 .fill 1024,4,0 500ENTRY(empty_zero_page) 501 .fill 4096,1,0 502 503/* 504 * This starts the data section. 505 */ 506.data 507ENTRY(stack_start) 508 .long init_thread_union+THREAD_SIZE 509 .long __BOOT_DS 510 511ready: .byte 0 512 513early_recursion_flag: 514 .long 0 515 516int_msg: 517 .asciz "Unknown interrupt or fault at EIP %p %p %p\n" 518 519fault_msg: 520 .ascii "Int %d: CR2 %p err %p EIP %p CS %p flags %p\n" 521 .asciz "Stack: %p %p %p %p %p %p %p %p\n" 522 523/* 524 * The IDT and GDT 'descriptors' are a strange 48-bit object 525 * only used by the lidt and lgdt instructions. They are not 526 * like usual segment descriptors - they consist of a 16-bit 527 * segment size, and 32-bit linear address value: 528 */ 529 530.globl boot_gdt_descr 531.globl idt_descr 532 533 ALIGN 534# early boot GDT descriptor (must use 1:1 address mapping) 535 .word 0 # 32 bit align gdt_desc.address 536boot_gdt_descr: 537 .word __BOOT_DS+7 538 .long boot_gdt - __PAGE_OFFSET 539 540 .word 0 # 32-bit align idt_desc.address 541idt_descr: 542 .word IDT_ENTRIES*8-1 # idt contains 256 entries 543 .long idt_table 544 545# boot GDT descriptor (later on used by CPU#0): 546 .word 0 # 32 bit align gdt_desc.address 547ENTRY(early_gdt_descr) 548 .word GDT_ENTRIES*8-1 549 .long per_cpu__gdt_page /* Overwritten for secondary CPUs */ 550 551/* 552 * The boot_gdt must mirror the equivalent in setup.S and is 553 * used only for booting. 554 */ 555 .align L1_CACHE_BYTES 556ENTRY(boot_gdt) 557 .fill GDT_ENTRY_BOOT_CS,8,0 558 .quad 0x00cf9a000000ffff /* kernel 4GB code at 0x00000000 */ 559 .quad 0x00cf92000000ffff /* kernel 4GB data at 0x00000000 */ 560