diff options
Diffstat (limited to 'arch/i386/kernel/head.S')
-rw-r--r-- | arch/i386/kernel/head.S | 68 |
1 files changed, 62 insertions, 6 deletions
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index be9d883c62ce..edef5084ce17 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S | |||
@@ -55,6 +55,12 @@ | |||
55 | */ | 55 | */ |
56 | ENTRY(startup_32) | 56 | ENTRY(startup_32) |
57 | 57 | ||
58 | #ifdef CONFIG_PARAVIRT | ||
59 | movl %cs, %eax | ||
60 | testl $0x3, %eax | ||
61 | jnz startup_paravirt | ||
62 | #endif | ||
63 | |||
58 | /* | 64 | /* |
59 | * Set segments to known values. | 65 | * Set segments to known values. |
60 | */ | 66 | */ |
@@ -302,6 +308,7 @@ is386: movl $2,%ecx # set MP | |||
302 | movl %eax,%cr0 | 308 | movl %eax,%cr0 |
303 | 309 | ||
304 | call check_x87 | 310 | call check_x87 |
311 | call setup_pda | ||
305 | lgdt cpu_gdt_descr | 312 | lgdt cpu_gdt_descr |
306 | lidt idt_descr | 313 | lidt idt_descr |
307 | ljmp $(__KERNEL_CS),$1f | 314 | ljmp $(__KERNEL_CS),$1f |
@@ -312,12 +319,15 @@ is386: movl $2,%ecx # set MP | |||
312 | movl %eax,%ds | 319 | movl %eax,%ds |
313 | movl %eax,%es | 320 | movl %eax,%es |
314 | 321 | ||
315 | xorl %eax,%eax # Clear FS/GS and LDT | 322 | xorl %eax,%eax # Clear FS and LDT |
316 | movl %eax,%fs | 323 | movl %eax,%fs |
317 | movl %eax,%gs | ||
318 | lldt %ax | 324 | lldt %ax |
325 | |||
326 | movl $(__KERNEL_PDA),%eax | ||
327 | mov %eax,%gs | ||
328 | |||
319 | cld # gcc2 wants the direction flag cleared at all times | 329 | cld # gcc2 wants the direction flag cleared at all times |
320 | pushl %eax # fake return address | 330 | pushl $0 # fake return address for unwinder |
321 | #ifdef CONFIG_SMP | 331 | #ifdef CONFIG_SMP |
322 | movb ready, %cl | 332 | movb ready, %cl |
323 | movb $1, ready | 333 | movb $1, ready |
@@ -346,6 +356,23 @@ check_x87: | |||
346 | ret | 356 | ret |
347 | 357 | ||
348 | /* | 358 | /* |
359 | * Point the GDT at this CPU's PDA. On boot this will be | ||
360 | * cpu_gdt_table and boot_pda; for secondary CPUs, these will be | ||
361 | * that CPU's GDT and PDA. | ||
362 | */ | ||
363 | setup_pda: | ||
364 | /* get the PDA pointer */ | ||
365 | movl start_pda, %eax | ||
366 | |||
367 | /* slot the PDA address into the GDT */ | ||
368 | mov cpu_gdt_descr+2, %ecx | ||
369 | mov %ax, (__KERNEL_PDA+0+2)(%ecx) /* base & 0x0000ffff */ | ||
370 | shr $16, %eax | ||
371 | mov %al, (__KERNEL_PDA+4+0)(%ecx) /* base & 0x00ff0000 */ | ||
372 | mov %ah, (__KERNEL_PDA+4+3)(%ecx) /* base & 0xff000000 */ | ||
373 | ret | ||
374 | |||
375 | /* | ||
349 | * setup_idt | 376 | * setup_idt |
350 | * | 377 | * |
351 | * sets up a idt with 256 entries pointing to | 378 | * sets up a idt with 256 entries pointing to |
@@ -465,6 +492,33 @@ ignore_int: | |||
465 | #endif | 492 | #endif |
466 | iret | 493 | iret |
467 | 494 | ||
495 | #ifdef CONFIG_PARAVIRT | ||
496 | startup_paravirt: | ||
497 | cld | ||
498 | movl $(init_thread_union+THREAD_SIZE),%esp | ||
499 | |||
500 | /* We take pains to preserve all the regs. */ | ||
501 | pushl %edx | ||
502 | pushl %ecx | ||
503 | pushl %eax | ||
504 | |||
505 | /* paravirt.o is last in link, and that probe fn never returns */ | ||
506 | pushl $__start_paravirtprobe | ||
507 | 1: | ||
508 | movl 0(%esp), %eax | ||
509 | pushl (%eax) | ||
510 | movl 8(%esp), %eax | ||
511 | call *(%esp) | ||
512 | popl %eax | ||
513 | |||
514 | movl 4(%esp), %eax | ||
515 | movl 8(%esp), %ecx | ||
516 | movl 12(%esp), %edx | ||
517 | |||
518 | addl $4, (%esp) | ||
519 | jmp 1b | ||
520 | #endif | ||
521 | |||
468 | /* | 522 | /* |
469 | * Real beginning of normal "text" segment | 523 | * Real beginning of normal "text" segment |
470 | */ | 524 | */ |
@@ -484,6 +538,8 @@ ENTRY(empty_zero_page) | |||
484 | * This starts the data section. | 538 | * This starts the data section. |
485 | */ | 539 | */ |
486 | .data | 540 | .data |
541 | ENTRY(start_pda) | ||
542 | .long boot_pda | ||
487 | 543 | ||
488 | ENTRY(stack_start) | 544 | ENTRY(stack_start) |
489 | .long init_thread_union+THREAD_SIZE | 545 | .long init_thread_union+THREAD_SIZE |
@@ -525,7 +581,7 @@ idt_descr: | |||
525 | 581 | ||
526 | # boot GDT descriptor (later on used by CPU#0): | 582 | # boot GDT descriptor (later on used by CPU#0): |
527 | .word 0 # 32 bit align gdt_desc.address | 583 | .word 0 # 32 bit align gdt_desc.address |
528 | cpu_gdt_descr: | 584 | ENTRY(cpu_gdt_descr) |
529 | .word GDT_ENTRIES*8-1 | 585 | .word GDT_ENTRIES*8-1 |
530 | .long cpu_gdt_table | 586 | .long cpu_gdt_table |
531 | 587 | ||
@@ -584,8 +640,8 @@ ENTRY(cpu_gdt_table) | |||
584 | .quad 0x00009a000000ffff /* 0xc0 APM CS 16 code (16 bit) */ | 640 | .quad 0x00009a000000ffff /* 0xc0 APM CS 16 code (16 bit) */ |
585 | .quad 0x004092000000ffff /* 0xc8 APM DS data */ | 641 | .quad 0x004092000000ffff /* 0xc8 APM DS data */ |
586 | 642 | ||
587 | .quad 0x0000920000000000 /* 0xd0 - ESPFIX 16-bit SS */ | 643 | .quad 0x00c0920000000000 /* 0xd0 - ESPFIX SS */ |
588 | .quad 0x0000000000000000 /* 0xd8 - unused */ | 644 | .quad 0x00cf92000000ffff /* 0xd8 - PDA */ |
589 | .quad 0x0000000000000000 /* 0xe0 - unused */ | 645 | .quad 0x0000000000000000 /* 0xe0 - unused */ |
590 | .quad 0x0000000000000000 /* 0xe8 - unused */ | 646 | .quad 0x0000000000000000 /* 0xe8 - unused */ |
591 | .quad 0x0000000000000000 /* 0xf0 - unused */ | 647 | .quad 0x0000000000000000 /* 0xf0 - unused */ |