]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/x86/realmode/rm/trampoline_32.S
18cb7fc9fad441f32c1b58b375563417cc525083
[karo-tx-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
33         .text
34         .code16
35         .globl trampoline_data
36
37         .balign PAGE_SIZE
38 trampoline_data:
39         wbinvd                  # Needed for NUMA-Q should be harmless for others
40
41         .byte   0xea            # ljmpw
42         .word   1f              # Offset
43         .word   real_mode_seg   # Segment
44 1:
45         mov     %cs, %ax        # Code and data in the same place
46         mov     %ax, %ds
47
48         cli                     # We should be safe anyway
49
50         movl    $0xA5A5A5A5, trampoline_status
51                                 # write marker for master knows we're running
52
53         /* GDT tables in non default location kernel can be beyond 16MB and
54          * lgdt will not be able to load the address as in real mode default
55          * operand size is 16bit. Use lgdtl instead to force operand size
56          * to 32 bit.
57          */
58
59         lidtl   boot_idt_descr          # load idt with 0, 0
60         lgdtl   boot_gdt_descr          # load gdt with whatever is appropriate
61
62         xor     %ax, %ax
63         inc     %ax                     # protected mode (PE) bit
64         lmsw    %ax                     # into protected mode
65
66         # flush prefetch and jump to startup_32_smp in arch/i386/kernel/head.S
67         ljmpl   *(startup_32_smp)
68
69         .data
70         .globl startup_32_smp, boot_gdt, trampoline_status
71
72 boot_gdt_descr:
73         .word   __BOOT_DS + 7                   # gdt limit
74 boot_gdt:
75         .long   0                               # gdt base
76
77 boot_idt_descr:
78         .word   0                               # idt limit = 0
79         .long   0                               # idt base = 0L
80
81 trampoline_status:
82         .long   0
83
84 startup_32_smp:
85         .long   0x00000000
86         .word   __BOOT_CS, 0