1 2/** 3 * Low level multiprocessor boot code 4 */ 5 6#define KERNEL_BASE 0xFFFF800000000000 7#define LOWMEM(_x) (_x - KERNEL_BASE) 8#define MPLOWMEM(_x) (_x - KERNEL_BASE + 0x7000) 9 10.extern bootpgtbl1 11.extern stack 12.extern Machine_InitAP 13 14.text 15 16/** 17 * mpstart_begin -- 18 * 19 * Support processors start executing here in 16-bit compat mode. 20 */ 21.code16 22.globl mpstart_begin 23mpstart_begin: 24 // Disable interrupts 25 cli 26 27 // Initialize the segment registers to 0, which is an offset in 16-bit mode 28 xorw %ax, %ax 29 movw %ax, %ds 30 movw %ax, %es 31 movw %ax, %fs 32 movw %ax, %gs 33 34 // Load 32-bit GDT 35 lgdt (mpstartgdtdesc32 - mpstart_begin + 0x7000) 36 37 movl %cr0, %eax 38 orl 0x00000011, %eax 39 movl %eax, %cr0 40 41 // Long jump to reload the code segment switching us into 32-bit mode 42 ljmp $0x08, $(mpstart_enter32 - mpstart_begin + 0x7000) 43 44 nop 45 nop 46 47 // Now we're in 32-bit mode 48.code32 49mpstart_enter32: 50 nop 51 nop 52 53 // Initialize segment registers 54 movw $0x10, %ax 55 movw %ax, %ds 56 movw %ax, %es 57 movw %ax, %fs 58 movw %ax, %gs 59 60 // Setup stack 61 movw %ax,%ss 62 movl $0x7000, %esp 63 64 // Reset EFLAGS 65 pushl $0x0 66 popf 67 68 // Set CR4 69 movl %cr4, %eax 70 orl $0x0000006A0, %eax 71 movl %eax, %cr4 72 73 // Temporary Page Table 74 movl $LOWMEM(bootpgtbl1), %eax 75 movl %eax, %cr3 76 77 // Set EFER 78 movl $0xC0000080, %ecx 79 rdmsr 80 orl $0x0900, %eax 81 wrmsr 82 83 // Load 64-bit GDT 84 movl $LOWMEM(mpstartgdtdesc), %eax 85 lgdt (%eax) 86 87 // Set CR0 88 movl %cr0, %eax 89 // QEMU seems to set cr0 with garbage 90 andl $0x1FF5FFC0, %eax 91 orl $0x8005002B, %eax 92 movl %eax, %cr0 93 94 // Long jump again to swithc us into 64-bit mode 95 movl $LOWMEM(mpstart_enter64ptr), %edi 96 ljmp *(%edi) 97 98 nop 99 nop 100 101 // Now we're playing with power 102.code64 103mpstart_enter64: 104 nop 105 nop 106 107 // Jump into the high memory address where the kernel should execute 108 movq $LOWMEM(mpstart_high64ptr), %rdi 109 jmp *(%rdi) 110 111 nop 112 nop 113 114mpstart_high64: 115 nop 116 nop 117 118 // Load Initial CPU State 119 movq (0x6F00), %rax 120 movq (0x6F08), %rbx 121 movq %rax, %cr3 122 movq %rbx, %rsp 123 124 call Machine_InitAP 125 126 // If we get here something went wrong so we write HALT to the display 1271: 128 movw $(0x5000 + 'H'), (0xB8098) 129 movw $(0x5000 + 'A'), (0xB809A) 130 movw $(0x5000 + 'L'), (0xB809C) 131 movw $(0x5000 + 'T'), (0xB809E) 132 jmp 1b 133 134.p2align 4 135mpstart_enter64ptr: 136.long LOWMEM(mpstart_enter64) 137.word 0x08 138 139.p2align 4 140mpstart_high64ptr: 141.quad mpstart_high64 142 143/** 144 * 32-bit GDT Table 145 */ 146.p2align 12 147mpstartgdt32: 148.quad 0x0000000000000000 /* Null */ 149.quad 0x00CF9A000000FFFF /* Temporary CS */ 150.quad 0x00CF92000000FFFF /* Temporary DS */ 151.quad 0x0000000000000000 152.quad 0x0000000000000000 153.quad 0x0000000000000000 154.quad 0x0000000000000000 155.quad 0x0000000000000000 156 157.p2align 4 158mpstartgdtdesc32: 159.word 0x003F 160.long LOWMEM(mpstartgdt32) 161 162.p2align 12 163mpstartgdt: 164.quad 0x0000000000000000 /* Null */ 165.quad 0x00AF9C000000FFFF /* Kernel CS */ 166.quad 0x00CF92000000FFFF /* Kernel DS */ 167.quad 0x0000000000000000 168.quad 0x0000000000000000 169.quad 0x0000000000000000 170.quad 0x0000000000000000 171.quad 0x0000000000000000 172 173.p2align 4 174.quad 0x0 175mpstartgdtdesc: 176.word 0x003F 177.quad LOWMEM(mpstartgdt) 178 179.globl mpstart_end 180mpstart_end: 181 182// Boot stack 183//.globl mpstack 184//.comm mpstack, STACK_SIZE 185 186