x86, realmode: fix 64-bit wakeup sequence
[cascardo/linux.git] / arch / x86 / realmode / rm / trampoline_32.S
1 /*
2  *
3  *      Trampoline.S    Derived from Setup.S by Linus Torvalds
4  *
5  *      4 Jan 1997 Michael Chastain: changed to gnu as.
6  *
7  *      This is only used for booting secondary CPUs in SMP machine
8  *
9  *      Entry: CS:IP point to the start of our code, we are
10  *      in real mode with no stack, but the rest of the
11  *      trampoline page to make our stack and everything else
12  *      is a mystery.
13  *
14  *      We jump into arch/x86/kernel/head_32.S.
15  *
16  *      On entry to trampoline_data, the processor is in real mode
17  *      with 16-bit addressing and 16-bit data.  CS has some value
18  *      and IP is zero.  Thus, we load CS to the physical segment
19  *      of the real mode code before doing anything further.
20  *
21  *      The structure real_mode_header includes entries that need
22  *      to be set up before executing this code:
23  *
24  *      startup_32_smp
25  *      boot_gdt
26  */
27
28 #include <linux/linkage.h>
29 #include <linux/init.h>
30 #include <asm/segment.h>
31 #include <asm/page_types.h>
32 #include "realmode.h"
33
34         .text
35         .code16
36
37         .balign PAGE_SIZE
38 ENTRY(trampoline_data)
39         wbinvd                  # Needed for NUMA-Q should be harmless for others
40
41         LJMPW_RM(1f)
42 1:
43         mov     %cs, %ax        # Code and data in the same place
44         mov     %ax, %ds
45
46         cli                     # We should be safe anyway
47
48         movl    startup_32_smp, %eax    # where we need to go
49
50         movl    $0xA5A5A5A5, trampoline_status
51                                 # write marker for master knows we're running
52
53         /*
54          * GDT tables in non default location kernel can be beyond 16MB and
55          * lgdt will not be able to load the address as in real mode default
56          * operand size is 16bit. Use lgdtl instead to force operand size
57          * to 32 bit.
58          */
59         lidtl   boot_idt_descr          # load idt with 0, 0
60         lgdtl   boot_gdt_descr          # load gdt with whatever is appropriate
61
62         movw    $1, %dx                 # protected mode (PE) bit
63         lmsw    %dx                     # into protected mode
64
65         ljmpl   $__BOOT_CS, $pa_startup_32
66
67         .section ".text32","ax"
68         .code32
69 ENTRY(startup_32)                       # note: also used from wakeup_asm.S
70         jmp     *%eax
71
72         .section ".rodata","a"
73
74         .balign 4
75 boot_idt_descr:
76         .word   0                               # idt limit = 0
77         .long   0                               # idt base = 0L
78
79         .data
80
81 boot_gdt_descr:
82         .word   __BOOT_DS + 7                   # gdt limit
83 GLOBAL(boot_gdt)
84         .long   0                               # gdt base
85
86         .bss
87
88         .balign 4
89 GLOBAL(trampoline_status)       .space  4
90 GLOBAL(startup_32_smp)          .space  4