1 #include "../bootstrap/cpu.h"
4 unsigned short size
__attribute__((packed
));
5 unsigned long addr
__attribute__((packed
));
9 void *target_ip
__attribute__((packed
));
10 unsigned short target_sel
__attribute__((packed
));
13 extern unsigned long smp_mmu
, smp_arg1
, smp_arg2
, smp_arg3
, smp_arg4
, smp_baseaddr
, smp_sp
, smp_ip
;
16 " .type smpbootstrap_0,@function \n"
19 " /* The config variables will be passed here... Do not execute them */ \n"
23 "smp_arg1: .long 0 \n" /* 0x0004 */
24 "smp_arg2: .long 0 \n" /* 0x0008 */
25 "smp_arg3: .long 0 \n" /* 0x000c */
26 "smp_arg4: .long 0 \n" /* 0x0010 */
27 "smp_mmu: .long 0 \n" /* 0x0014 */
28 "smp_sp: .long 0; .long 0 \n" /* 0x0018 */
29 "smp_ip: .long 0; .long 0 \n" /* 0x0020 */
30 "smp_baseaddr: .long 0 \n"
31 "smp_gdt: .short 0; .short 0; .short 0; .short 0 \n"
32 " .short 0x1000; .short 0x0000; .short 0x9a00; .short 0x0040 \n"
33 " .short 0x1000; .short 0x0000; .short 0x9200; .short 0x0040 \n"
34 "smp_gdt64: .short 0; .short 0; .short 0; .short 0 \n"
35 " .short 0xffff; .short 0x0000; .short 0x9a00; .short 0x00af \n"
36 " .short 0xffff; .short 0x0000; .short 0x9200; .short 0x00af \n"
37 "smp_gdt_sel: .short 23 \n"
39 "smp_gdt64_sel: .short 23 \n"
41 "smp_kernel_target: .long 0; .short 8\n"
44 " mov %cs,%ax \n" /* Find out where the code resides */
46 " movl %eax,%cs:smp_baseaddr \n" /* Store base address of the trampoline */
47 " leal smp_gdt(%eax), %ebx \n" /* Load physical address of 32-bit gdt */
48 " movl %ebx, %cs:smp_gdt_sel+2\n" /* Set up 32-bit gdt address */
49 " leal smp_gdt64(%eax), %ebx \n" /* Load physical address of 64-bit gdt */
50 " movl %ebx, %cs:smp_gdt64_sel+2\n" /* Set up 64-bit gdt address */
51 " leal boot64(%eax), %ebx \n" /* Load physical address of 64-bit code */
52 " movl %ebx, %cs:smp_kernel_target \n" /* Set up 64-bit entry address */
53 " movw %ax, %cs:smp_gdt+10 \n" /* Set base address of 32-bit code segment (bits 0:15) */
54 " movw %ax, %cs:smp_gdt+18 \n" /* Set base address of 32-bit data segment (bits 0:15) */
56 " movb %al, %cs:smp_gdt+12 \n" /* Set base address of 32-bit code segment (bits 16:23) */
57 " movb %al, %cs:smp_gdt+20 \n" /* Set base address of 32-bit data segment (bits 16:23) */
58 " ADDR32 DATA32 lgdt %cs:smp_gdt_sel \n" /* Load gdt */
64 " movl %cr0,%eax \n" /* Enter protected mode */
68 " ljmp $0x8,$2f /* Please note that the %cs segment selector has to have it's base address properly adjusted */ \n"
71 "2: movw $0x10,%ax \n" /* Setup the 32-bit data selectors */
75 " movl $4096-4,%esp \n" /* Stack at the top of this 4K page */
77 " jmp smp_c_trampoline \n");
80 * This tiny procedure sets the complete 64-bit environment up - it loads the descriptors,
81 * enables 64-bit mode, loads MMU tables and trhough paging it activates the 64-bit long mode.
83 * After that it is perfectly safe to jump into the pure 64-bit kernel.
85 static void leave_32bit_mode()
87 unsigned int v1
, v2
, v3
, v4
;
88 asm volatile ("lgdt %0"::"m"(smp_gdt64_sel
));
90 asm volatile ("outb %b0,%w1"::"a"('b'),"Nd"(0x3f8));
93 wrcr(cr4
, _CR4_PAE
| _CR4_PGE
);
95 asm volatile ("outb %b0,%w1"::"a"('c'),"Nd"(0x3f8));
100 asm volatile ("outb %b0,%w1"::"a"('d'),"Nd"(0x3f8));
102 /* enable long mode */
103 rdmsr(EFER
, &v1
, &v2
);
107 asm volatile ("outb %b0,%w1"::"a"('e'),"Nd"(0x3f8));
109 /* enable paging and activate long mode */
110 wrcr(cr0
, _CR0_PG
| _CR0_PE
);
112 static void __attribute__((used
, noreturn
)) smp_c_trampoline()
114 asm volatile ("outb %b0,%w1"::"a"('a'),"Nd"(0x3f8));
117 asm volatile ("outb %b0,%w1"::"a"('f'),"Nd"(0x3f8));
119 asm volatile("ljmp *%0"::"m"(smp_kernel_target
),"b"(smp_baseaddr
),"D"(smp_arg1
),"S"(smp_arg2
),"d"(smp_arg3
),"c"(smp_arg4
));
129 " movq 0x18(%rbx), %rsp \n"
130 " movq 0x20(%rbx), %rax \n"