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/* 246 * Initialize eflags. Some BIOS's leave bits like NT set. This would 247 * confuse the debugger if this code is traced. 248 * XXX - best to initialize before switching to protected mode. 249 */ 250 pushl $0 251 popfl 252 253#ifdef CONFIG_SMP 254 andl %ebx,%ebx 255 jz 1f /* Initial CPU cleans BSS */ 256 jmp checkCPUtype 2571: 258#endif /* CONFIG_SMP */ 259 260/* 261 * start system 32-bit setup. We need to re-do some of the things done 262 * in 16-bit mode for the "real" operations. 263 */ 264 call setup_idt 265 266checkCPUtype: 267 268 movl $-1,X86_CPUID # -1 for no CPUID initially 269 270/* check if it is 486 or 386. */ 271/* 272 * XXX - this does a lot of unnecessary setup. Alignment checks don't 273 * apply at our cpl of 0 and the stack ought to be aligned already, and 274 * we don't need to preserve eflags. 275 */ 276 277 movb $3,X86 # at least 386 278 pushfl # push EFLAGS 279 popl %eax # get EFLAGS 280 movl %eax,%ecx # save original EFLAGS 281 xorl $0x240000,%eax # flip AC and ID bits in EFLAGS 282 pushl %eax # copy to EFLAGS 283 popfl # set EFLAGS 284 pushfl # get new EFLAGS 285 popl %eax # put it in eax 286 xorl %ecx,%eax # change in flags 287 pushl %ecx # restore original EFLAGS 288 popfl 289 testl $0x40000,%eax # check if AC bit changed 290 je is386 291 292 movb $4,X86 # at least 486 293 testl $0x200000,%eax # check if ID bit changed 294 je is486 295 296 /* get vendor info */ 297 xorl %eax,%eax # call CPUID with 0 -> return vendor ID 298 cpuid 299 movl %eax,X86_CPUID # save CPUID level 300 movl %ebx,X86_VENDOR_ID # lo 4 chars 301 movl %edx,X86_VENDOR_ID+4 # next 4 chars 302 movl %ecx,X86_VENDOR_ID+8 # last 4 chars 303 304 orl %eax,%eax # do we have processor info as well? 305 je is486 306 307 movl $1,%eax # Use the CPUID instruction to get CPU type 308 cpuid 309 movb %al,%cl # save reg for future use 310 andb $0x0f,%ah # mask processor family 311 movb %ah,X86 312 andb $0xf0,%al # mask model 313 shrb $4,%al 314 movb %al,X86_MODEL 315 andb $0x0f,%cl # mask mask revision 316 movb %cl,X86_MASK 317 movl %edx,X86_CAPABILITY 318 319is486: movl $0x50022,%ecx # set AM, WP, NE and MP 320 jmp 2f 321 322is386: movl $2,%ecx # set MP 3232: movl %cr0,%eax 324 andl $0x80000011,%eax # Save PG,PE,ET 325 orl %ecx,%eax 326 movl %eax,%cr0 327 328 call check_x87 329 lgdt early_gdt_descr 330 lidt idt_descr 331 ljmp $(__KERNEL_CS),$1f 3321: movl $(__KERNEL_DS),%eax # reload all the segment registers 333 movl %eax,%ss # after changing gdt. 334 movl %eax,%fs # gets reset once there's real percpu 335 336 movl $(__USER_DS),%eax # DS/ES contains default USER segment 337 movl %eax,%ds 338 movl %eax,%es 339 340 xorl %eax,%eax # Clear GS and LDT 341 movl %eax,%gs 342 lldt %ax 343 344 cld # gcc2 wants the direction flag cleared at all times 345 pushl $0 # fake return address for unwinder 346#ifdef CONFIG_SMP 347 movb ready, %cl 348 movb $1, ready 349 cmpb $0,%cl # the first CPU calls start_kernel 350 je 1f 351 movl $(__KERNEL_PERCPU), %eax 352 movl %eax,%fs # set this cpu's percpu 353 jmp initialize_secondary # all other CPUs call initialize_secondary 3541: 355#endif /* CONFIG_SMP */ 356 jmp start_kernel 357 358/* 359 * We depend on ET to be correct. This checks for 287/387. 360 */ 361check_x87: 362 movb $0,X86_HARD_MATH 363 clts 364 fninit 365 fstsw %ax 366 cmpb $0,%al 367 je 1f 368 movl %cr0,%eax /* no coprocessor: have to set bits */ 369 xorl $4,%eax /* set EM */ 370 movl %eax,%cr0 371 ret 372 ALIGN 3731: movb $1,X86_HARD_MATH 374 .byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */ 375 ret 376 377/* 378 * setup_idt 379 * 380 * sets up a idt with 256 entries pointing to 381 * ignore_int, interrupt gates. It doesn't actually load 382 * idt - that can be done only after paging has been enabled 383 * and the kernel moved to PAGE_OFFSET. Interrupts 384 * are enabled elsewhere, when we can be relatively 385 * sure everything is ok. 386 * 387 * Warning: %esi is live across this function. 388 */ 389setup_idt: 390 lea ignore_int,%edx 391 movl $(__KERNEL_CS << 16),%eax 392 movw %dx,%ax /* selector = 0x0010 = cs */ 393 movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ 394 395 lea idt_table,%edi 396 mov $256,%ecx 397rp_sidt: 398 movl %eax,(%edi) 399 movl %edx,4(%edi) 400 addl $8,%edi 401 dec %ecx 402 jne rp_sidt 403 404.macro set_early_handler handler,trapno 405 lea \handler,%edx 406 movl $(__KERNEL_CS << 16),%eax 407 movw %dx,%ax 408 movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ 409 lea idt_table,%edi 410 movl %eax,8*\trapno(%edi) 411 movl %edx,8*\trapno+4(%edi) 412.endm 413 414 set_early_handler handler=early_divide_err,trapno=0 415 set_early_handler handler=early_illegal_opcode,trapno=6 416 set_early_handler handler=early_protection_fault,trapno=13 417 set_early_handler handler=early_page_fault,trapno=14 418 419 ret 420 421early_divide_err: 422 xor %edx,%edx 423 pushl $0 /* fake errcode */ 424 jmp early_fault 425 426early_illegal_opcode: 427 movl $6,%edx 428 pushl $0 /* fake errcode */ 429 jmp early_fault 430 431early_protection_fault: 432 movl $13,%edx 433 jmp early_fault 434 435early_page_fault: 436 movl $14,%edx 437 jmp early_fault 438 439early_fault: 440 cld 441#ifdef CONFIG_PRINTK 442 movl $(__KERNEL_DS),%eax 443 movl %eax,%ds 444 movl %eax,%es 445 cmpl $2,early_recursion_flag 446 je hlt_loop 447 incl early_recursion_flag 448 movl %cr2,%eax 449 pushl %eax 450 pushl %edx /* trapno */ 451 pushl $fault_msg 452#ifdef CONFIG_EARLY_PRINTK 453 call early_printk 454#else 455 call printk 456#endif 457#endif 458hlt_loop: 459 hlt 460 jmp hlt_loop 461 462/* This is the default interrupt "handler" :-) */ 463 ALIGN 464ignore_int: 465 cld 466#ifdef CONFIG_PRINTK 467 pushl %eax 468 pushl %ecx 469 pushl %edx 470 pushl %es 471 pushl %ds 472 movl $(__KERNEL_DS),%eax 473 movl %eax,%ds 474 movl %eax,%es 475 cmpl $2,early_recursion_flag 476 je hlt_loop 477 incl early_recursion_flag 478 pushl 16(%esp) 479 pushl 24(%esp) 480 pushl 32(%esp) 481 pushl 40(%esp) 482 pushl $int_msg 483#ifdef CONFIG_EARLY_PRINTK 484 call early_printk 485#else 486 call printk 487#endif 488 addl $(5*4),%esp 489 popl %ds 490 popl %es 491 popl %edx 492 popl %ecx 493 popl %eax 494#endif 495 iret 496 497.section .text 498/* 499 * Real beginning of normal "text" segment 500 */ 501ENTRY(stext) 502ENTRY(_stext) 503 504/* 505 * BSS section 506 */ 507.section ".bss.page_aligned","w" 508ENTRY(swapper_pg_dir) 509 .fill 1024,4,0 510ENTRY(empty_zero_page) 511 .fill 4096,1,0 512 513/* 514 * This starts the data section. 515 */ 516.data 517ENTRY(stack_start) 518 .long init_thread_union+THREAD_SIZE 519 .long __BOOT_DS 520 521ready: .byte 0 522 523early_recursion_flag: 524 .long 0 525 526int_msg: 527 .asciz "Unknown interrupt or fault at EIP %p %p %p\n" 528 529fault_msg: 530 .ascii "Int %d: CR2 %p err %p EIP %p CS %p flags %p\n" 531 .asciz "Stack: %p %p %p %p %p %p %p %p\n" 532 533/* 534 * The IDT and GDT 'descriptors' are a strange 48-bit object 535 * only used by the lidt and lgdt instructions. They are not 536 * like usual segment descriptors - they consist of a 16-bit 537 * segment size, and 32-bit linear address value: 538 */ 539 540.globl boot_gdt_descr 541.globl idt_descr 542 543 ALIGN 544# early boot GDT descriptor (must use 1:1 address mapping) 545 .word 0 # 32 bit align gdt_desc.address 546boot_gdt_descr: 547 .word __BOOT_DS+7 548 .long boot_gdt - __PAGE_OFFSET 549 550 .word 0 # 32-bit align idt_desc.address 551idt_descr: 552 .word IDT_ENTRIES*8-1 # idt contains 256 entries 553 .long idt_table 554 555# boot GDT descriptor (later on used by CPU#0): 556 .word 0 # 32 bit align gdt_desc.address 557ENTRY(early_gdt_descr) 558 .word GDT_ENTRIES*8-1 559 .long per_cpu__gdt_page /* Overwritten for secondary CPUs */ 560 561/* 562 * The boot_gdt must mirror the equivalent in setup.S and is 563 * used only for booting. 564 */ 565 .align L1_CACHE_BYTES 566ENTRY(boot_gdt) 567 .fill GDT_ENTRY_BOOT_CS,8,0 568 .quad 0x00cf9a000000ffff /* kernel 4GB code at 0x00000000 */ 569 .quad 0x00cf92000000ffff /* kernel 4GB data at 0x00000000 */ 570

