17d36db35SAvi Kivity 2dfe6cb66SJason Wang#include "apic-defs.h" 3dfe6cb66SJason Wang 4dfe6cb66SJason Wang.globl boot_idt 5dfe6cb66SJason Wangboot_idt = 0 6dfe6cb66SJason Wang 7dfe6cb66SJason Wangipi_vector = 0x20 8dfe6cb66SJason Wang 97407b79bSJason Wangmax_cpus = 64 107d36db35SAvi Kivity 117d36db35SAvi Kivity.bss 127d36db35SAvi Kivity 13dfe6cb66SJason Wang . = . + 4096 * max_cpus 14dfe6cb66SJason Wang .align 16 15dfe6cb66SJason Wangstacktop: 16dfe6cb66SJason Wang 17dfe6cb66SJason Wang . = . + 4096 18dfe6cb66SJason Wang .align 16 19dfe6cb66SJason Wangring0stacktop: 20dfe6cb66SJason Wang 21dfe6cb66SJason Wang.data 22dfe6cb66SJason Wang 23dfe6cb66SJason Wang.align 4096 24dfe6cb66SJason Wangpt: 25dfe6cb66SJason Wangi = 0 26dfe6cb66SJason Wang .rept 1024 27dfe6cb66SJason Wang .long 0x1e7 | (i << 22) 28dfe6cb66SJason Wang i = i + 1 29dfe6cb66SJason Wang .endr 30dfe6cb66SJason Wang 318f4755faSPaolo Bonzini.globl gdt32 32dfe6cb66SJason Wanggdt32: 33dfe6cb66SJason Wang .quad 0 34dfe6cb66SJason Wang .quad 0x00cf9b000000ffff // flat 32-bit code segment 35dfe6cb66SJason Wang .quad 0x00cf93000000ffff // flat 32-bit data segment 368f4755faSPaolo Bonzini .quad 0x00cf1b000000ffff // flat 32-bit code segment, not present 37*10594e42SPaolo Bonzini .quad 0 // TSS for task gates 38*10594e42SPaolo Bonzini .quad 0x008f9b000000FFFF // 16-bit code segment 39*10594e42SPaolo Bonzini .quad 0x008f93000000FFFF // 16-bit data segment 40*10594e42SPaolo Bonzini .quad 0x00cffb000000ffff // 32-bit code segment (user) 41*10594e42SPaolo Bonzini .quad 0x00cff3000000ffff // 32-bit data segment (user) 42*10594e42SPaolo Bonzini .quad 0 // unused 438f4755faSPaolo Bonzini 44*10594e42SPaolo Bonzini .quad 0 // 6 spare selectors 458f4755faSPaolo Bonzini .quad 0 468f4755faSPaolo Bonzini .quad 0 478f4755faSPaolo Bonzini .quad 0 488f4755faSPaolo Bonzini .quad 0 498f4755faSPaolo Bonzini .quad 0 50dfe6cb66SJason Wang 51dfe6cb66SJason Wangtss_descr: 52dfe6cb66SJason Wang .rept max_cpus 53dfe6cb66SJason Wang .quad 0x000089000000ffff // 32-bit avail tss 54dfe6cb66SJason Wang .endr 55dfe6cb66SJason Wanggdt32_end: 56dfe6cb66SJason Wang 57dfe6cb66SJason Wangi = 0 588f4755faSPaolo Bonzini.globl tss 59dfe6cb66SJason Wangtss: 60dfe6cb66SJason Wang .rept max_cpus 61dfe6cb66SJason Wang .long 0 62dfe6cb66SJason Wang .long ring0stacktop - i * 4096 63dfe6cb66SJason Wang .long 16 64dfe6cb66SJason Wang .quad 0, 0 65dfe6cb66SJason Wang .quad 0, 0, 0, 0, 0, 0, 0, 0 66dfe6cb66SJason Wang .long 0, 0, 0 67dfe6cb66SJason Wang i = i + 1 68dfe6cb66SJason Wang .endr 69dfe6cb66SJason Wangtss_end: 70dfe6cb66SJason Wang 71dfe6cb66SJason Wangidt_descr: 72dfe6cb66SJason Wang .word 16 * 256 - 1 73dfe6cb66SJason Wang .long boot_idt 74dfe6cb66SJason Wang 757d36db35SAvi Kivity.section .init 767d36db35SAvi Kivity 77dfe6cb66SJason Wang.code32 78dfe6cb66SJason Wang 797d36db35SAvi Kivitymb_magic = 0x1BADB002 807d36db35SAvi Kivitymb_flags = 0x0 817d36db35SAvi Kivity 827d36db35SAvi Kivity # multiboot header 837d36db35SAvi Kivity .long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) 84ea7d43d0SAvi Kivitymb_cmdline = 16 857d36db35SAvi Kivity 86dfe6cb66SJason WangMSR_GS_BASE = 0xc0000101 87dfe6cb66SJason Wang 88dfe6cb66SJason Wang.macro setup_percpu_area 89dfe6cb66SJason Wang lea -4096(%esp), %eax 90dfe6cb66SJason Wang mov $0, %edx 91dfe6cb66SJason Wang mov $MSR_GS_BASE, %ecx 92dfe6cb66SJason Wang wrmsr 93dfe6cb66SJason Wang.endm 94dfe6cb66SJason Wang 957d36db35SAvi Kivity.globl start 967d36db35SAvi Kivitystart: 9793dd2aa3SAndrew Jones push %ebx 9893dd2aa3SAndrew Jones call setup_get_initrd 993c7d322eSAndrew Jones call setup_environ 100ea7d43d0SAvi Kivity mov mb_cmdline(%ebx), %eax 101ea7d43d0SAvi Kivity mov %eax, __args 102ea7d43d0SAvi Kivity call __setup_args 103dfe6cb66SJason Wang mov $stacktop, %esp 104dfe6cb66SJason Wang setup_percpu_area 105dfe6cb66SJason Wang call prepare_32 106dfe6cb66SJason Wang jmpl $8, $start32 107dfe6cb66SJason Wang 108dfe6cb66SJason Wangprepare_32: 109dfe6cb66SJason Wang lgdtl gdt32_descr 110dfe6cb66SJason Wang 111dfe6cb66SJason Wang mov %cr4, %eax 112dfe6cb66SJason Wang bts $4, %eax // pse 113dfe6cb66SJason Wang mov %eax, %cr4 114dfe6cb66SJason Wang 115dfe6cb66SJason Wang mov $pt, %eax 116dfe6cb66SJason Wang mov %eax, %cr3 117dfe6cb66SJason Wang 118dfe6cb66SJason Wang mov %cr0, %eax 119dfe6cb66SJason Wang bts $0, %eax 120dfe6cb66SJason Wang bts $31, %eax 121dfe6cb66SJason Wang mov %eax, %cr0 122dfe6cb66SJason Wang ret 123dfe6cb66SJason Wang 124dfe6cb66SJason Wangsmp_stacktop: .long 0xa0000 125dfe6cb66SJason Wang 126dfe6cb66SJason Wangap_start32: 127dfe6cb66SJason Wang mov $0x10, %ax 128dfe6cb66SJason Wang mov %ax, %ds 129dfe6cb66SJason Wang mov %ax, %es 130dfe6cb66SJason Wang mov %ax, %fs 131dfe6cb66SJason Wang mov %ax, %gs 132dfe6cb66SJason Wang mov %ax, %ss 133dfe6cb66SJason Wang mov $-4096, %esp 134dfe6cb66SJason Wang lock/xaddl %esp, smp_stacktop 135dfe6cb66SJason Wang setup_percpu_area 136dfe6cb66SJason Wang call prepare_32 137dfe6cb66SJason Wang call load_tss 138dfe6cb66SJason Wang call enable_apic 139dfe6cb66SJason Wang call enable_x2apic 140dfe6cb66SJason Wang sti 141dfe6cb66SJason Wang nop 142dfe6cb66SJason Wang lock incw cpu_online_count 143dfe6cb66SJason Wang 144dfe6cb66SJason Wang1: hlt 145dfe6cb66SJason Wang jmp 1b 146dfe6cb66SJason Wang 147dfe6cb66SJason Wangstart32: 148dfe6cb66SJason Wang call load_tss 149dfe6cb66SJason Wang call mask_pic_interrupts 150dfe6cb66SJason Wang call enable_apic 151dfe6cb66SJason Wang call smp_init 152dfe6cb66SJason Wang call enable_x2apic 1533c7d322eSAndrew Jones push $__environ 154dfe6cb66SJason Wang push $__argv 155dfe6cb66SJason Wang push __argc 1567d36db35SAvi Kivity call main 1577d36db35SAvi Kivity push %eax 1587d36db35SAvi Kivity call exit 1597d36db35SAvi Kivity 160dfe6cb66SJason Wangload_tss: 161dfe6cb66SJason Wang lidt idt_descr 162dfe6cb66SJason Wang mov $16, %eax 163dfe6cb66SJason Wang mov %ax, %ss 164dfe6cb66SJason Wang mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax 165dfe6cb66SJason Wang mov (%eax), %eax 166dfe6cb66SJason Wang shr $24, %eax 167dfe6cb66SJason Wang mov %eax, %ebx 168dfe6cb66SJason Wang shl $3, %ebx 169dfe6cb66SJason Wang mov $((tss_end - tss) / max_cpus), %edx 170dfe6cb66SJason Wang imul %edx 171dfe6cb66SJason Wang add $tss, %eax 172dfe6cb66SJason Wang mov %ax, tss_descr+2(%ebx) 173dfe6cb66SJason Wang shr $16, %eax 174dfe6cb66SJason Wang mov %al, tss_descr+4(%ebx) 175dfe6cb66SJason Wang shr $8, %eax 176dfe6cb66SJason Wang mov %al, tss_descr+7(%ebx) 177dfe6cb66SJason Wang lea tss_descr-gdt32(%ebx), %eax 178dfe6cb66SJason Wang ltr %ax 179dfe6cb66SJason Wang ret 1807d36db35SAvi Kivity 181dfe6cb66SJason Wangsmp_init: 182dfe6cb66SJason Wang cld 183dfe6cb66SJason Wang lea sipi_entry, %esi 184dfe6cb66SJason Wang xor %edi, %edi 185dfe6cb66SJason Wang mov $(sipi_end - sipi_entry), %ecx 186dfe6cb66SJason Wang rep/movsb 187dfe6cb66SJason Wang mov $APIC_DEFAULT_PHYS_BASE, %eax 188dfe6cb66SJason Wang movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_INIT | APIC_INT_ASSERT), APIC_ICR(%eax) 189dfe6cb66SJason Wang movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_INIT), APIC_ICR(%eax) 190dfe6cb66SJason Wang movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_STARTUP), APIC_ICR(%eax) 191dfe6cb66SJason Wang call fwcfg_get_nb_cpus 192dfe6cb66SJason Wang1: pause 193dfe6cb66SJason Wang cmpw %ax, cpu_online_count 194dfe6cb66SJason Wang jne 1b 195dfe6cb66SJason Wangsmp_init_done: 196dfe6cb66SJason Wang ret 197dfe6cb66SJason Wang 198dfe6cb66SJason Wangcpu_online_count: .word 1 199dfe6cb66SJason Wang 200dfe6cb66SJason Wang.code16 201dfe6cb66SJason Wangsipi_entry: 202dfe6cb66SJason Wang mov %cr0, %eax 203dfe6cb66SJason Wang or $1, %eax 204dfe6cb66SJason Wang mov %eax, %cr0 205dfe6cb66SJason Wang lgdtl gdt32_descr - sipi_entry 206dfe6cb66SJason Wang ljmpl $8, $ap_start32 207dfe6cb66SJason Wang 208dfe6cb66SJason Wanggdt32_descr: 209dfe6cb66SJason Wang .word gdt32_end - gdt32 - 1 210dfe6cb66SJason Wang .long gdt32 211dfe6cb66SJason Wang 212dfe6cb66SJason Wangsipi_end: 213