acrn hypervisor源码分析 - 第一节

最开始启动的话,是从hypervisor/arch/x86/boot/cpu_primary.S开始。

  1. .global cpu_primary_start_32 进入cpu_primary_start_32函数
  2. 不懂MULTBOOT magic number是什么意思。大概系统上电后,multboot magic number会首先自动存放到eax和ebx寄存器里面。然后通过movl放到内存指定位置。
	/* save the MULTBOOT magic number & MBI */
    movl    %eax, (boot_regs)
    movl    %ebx, (boot_regs+4)
  
	.global boot_regs
    boot_regs:
    .long   0x00000000
    .long   0x00000000
  1. call cpu_primary_save_32 进入cpu_primary_save_32函数。保存部分寄存器到内存指定位置。
	/* save context from 32bit mode */
    lea     boot_context, %eax
    sgdt    BOOT_CTX_GDT_OFFSET(%eax)
    sidt    BOOT_CTX_IDT_OFFSET(%eax)
    str     BOOT_CTX_TR_SEL_OFFSET(%eax)
    sldt    BOOT_CTX_LDT_SEL_OFFSET(%eax)
    movl    %cr0, %ecx
    movl    %ecx, BOOT_CTX_CR0_OFFSET(%eax)
    movl    %cr3, %ecx
    movl    %ecx, BOOT_CTX_CR3_OFFSET(%eax)
    movl    %cr4, %ecx
    movl    %ecx, BOOT_CTX_CR4_OFFSET(%eax)
    mov     %cs, %cx
    mov     %cx,  BOOT_CTX_CS_SEL_OFFSET(%eax)
    lar     %ecx, %ecx
    /* CS AR start from bit 8 */
    shr     $8, %ecx
    /* Clear Limit field, bit 8-11 */
    andl    $0x0000f0ff, %ecx
    mov     %ecx, BOOT_CTX_CS_AR_OFFSET(%eax)

    /* Save CS limit field */
    mov     %cs, %cx
    xor     %edx, %edx
    lsl     %ecx, %edx
    mov     %edx, BOOT_CTX_CS_LIMIT_OFFSET(%eax)

    mov     %es,  BOOT_CTX_ES_SEL_OFFSET(%eax)
    mov     %ss,  BOOT_CTX_SS_SEL_OFFSET(%eax)
    mov     %ds,  BOOT_CTX_DS_SEL_OFFSET(%eax)
    mov     %fs,  BOOT_CTX_FS_SEL_OFFSET(%eax)
    mov     %gs,  BOOT_CTX_GS_SEL_OFFSET(%eax)
    ret

内存位置是通过boot_context变量指定的。

boot_context:
    .rept   SIZE_OF_BOOT_CTX
    .byte 0x00
    .endr
  1. 关中断和令DF=0(https://www.cnblogs.com/baozou/articles/4581507.html)
    /* Disable interrupts */
    cli

    /* Clear direction flag */
    cld
  1. long mode就是可以执行64位的指令和访问64位的寄存器。rdmsr是读取msr寄存器(每一个cpu型号特有的寄存器组,高32位放在edx,低32位放在eax)。随后跳转到cpu_primary_start_64
    /* detect whether it is in long mode
     *
     *     0xc0000080 = MSR_IA32_EFER
     */
    movl    $0xc0000080, %ecx
    rdmsr
    /* 0x400 = MSR_IA32_EFER_LMA_BIT */
    test     $0x400, %eax

    /* jump to 64bit entry if it is already in long mode */
    jne      cpu_primary_start_64
  1. 这个和32时一样,保存magic number。首先通过lea将boot_regs的有效地址加载到rax,然后把edi和esi的内容保存到rax指向的内存中。最后执行cpu_primary_save_64函数。

不知道boot_regs(%rip)如何理解?
不知道为什么32位是eax和ebx,64位则是edi和esi?

cpu_primary_start_64:
    /* save the MULTBOOT magic number & MBI */
    lea     boot_regs(%rip), %rax
    movl    %edi, (%rax)
    movl    %esi, 4(%rax)

    /* Save boot context from 64bit mode */
    call cpu_primary_save_64
  1. 和32位的保存操作有点类似
cpu_primary_save_64:
    /* save context from 64bit mode */
    lea     boot_context(%rip), %r8
    sgdt    BOOT_CTX_GDT_OFFSET(%r8)
    sidt    BOOT_CTX_IDT_OFFSET(%r8)
    str     BOOT_CTX_TR_SEL_OFFSET(%r8)
    sldt    BOOT_CTX_LDT_SEL_OFFSET(%r8)
    mov     %cr0, %rcx
    mov     %rcx, BOOT_CTX_CR0_OFFSET(%r8)
    mov     %cr3, %rcx
    mov     %rcx, BOOT_CTX_CR3_OFFSET(%r8)
    mov     %cr4, %rcx
    mov     %rcx, BOOT_CTX_CR4_OFFSET(%r8)
    mov     %cs, %cx
    mov     %cx,  BOOT_CTX_CS_SEL_OFFSET(%r8)
    lar     %ecx, %ecx
    /* CS AR start from bit 8 */
    shr     $8, %ecx
    /* Clear Limit field, bit 8-11 */
    andl    $0x0000f0ff, %ecx
    mov     %ecx, BOOT_CTX_CS_AR_OFFSET(%r8)

    /* Save CS limit field */
    mov     %cs, %cx
    xor     %edx, %edx
    lsl     %ecx, %edx
    mov     %edx, BOOT_CTX_CS_LIMIT_OFFSET(%r8)

    mov     %es,  BOOT_CTX_ES_SEL_OFFSET(%r8)
    mov     %ss,  BOOT_CTX_SS_SEL_OFFSET(%r8)
    mov     %ds,  BOOT_CTX_DS_SEL_OFFSET(%r8)
    mov     %fs,  BOOT_CTX_FS_SEL_OFFSET(%r8)
    mov     %gs,  BOOT_CTX_GS_SEL_OFFSET(%r8)
    /* 0xc0000080 = MSR_IA32_EFER */
    movl    $0xc0000080, %ecx
    rdmsr
    movl    %eax, BOOT_CTX_EFER_LOW_OFFSET(%r8)
    movl    %edx, BOOT_CTX_EFER_HIGH_OFFSET(%r8)
    ret
  1. 接着按顺序执行primary_start_long_mode函数,开始是使rsp对齐一个page。最后调用relocate,重定位hypervisor镜像。
primary_start_long_mode:

    /* Initialize temporary stack pointer */
    lea     ld_bss_end(%rip), %rsp
    /*0x1000 = PAGE_SIZE*/
    add     $0x1000,%rsp
    /* 16 = CPU_STACK_ALIGN */
    and     $(~(16 - 1)),%rsp

    /*
     * Fix up the .rela sections
     * Notes: this includes the fixup to IDT tables and temporary
     *     page tables
     */
    call relocate

你可能感兴趣的:(汇编,acrn,hypervisor)