Xen源代码分析(二)——trampoline.s

    汇编文件trampoline.s,主要工作为进入实模式,读取内存,磁盘,视频信息然后再次进入保护模式装入新的GDT(gdt_table),英文注释了很大部分,很容易理解。下面的代码注释中,从标号0开始运行,然后是标号1   

 .code16

/* NB. bootsym() is only usable in real mode, or via BOOT_PSEUDORM_DS. */

#undef bootsym

/*bootsym(s)定义的是s的相对位置*/

#define bootsym(s) ((s)-trampoline_start)

 

#define bootsym_rel(sym, off, opnd...)     \

        bootsym(sym),##opnd;               \

111:;                                      \

        .pushsection .trampoline_rel, "a"; \

        .long 111b - (off) - .;            \

        .popsection

 

#define bootsym_segrel(sym, off)           \

        $0,$bootsym(sym);                  \

111:;                                      \

        .pushsection .trampoline_seg, "a"; \

        .long 111b - (off) - .;            \

        .popsection

 

        .globl trampoline_realmode_entry

trampoline_realmode_entry:

        mov     %cs,%ax

        mov     %ax,%ds

        movb    $0xA5,bootsym(trampoline_cpu_started)

        cld

        cli

        lidt    bootsym(idt_48)

        lgdt    bootsym(gdt_48)

        mov     $1,%bl                    # EBX != 0 indicates we are an AP

        xor     %ax, %ax

        inc     %ax

        lmsw    %ax                       # CR0.PE = 1 (enter protected mode)

        ljmpl   $BOOT_CS32,$bootsym_rel(trampoline_protmode_entry,6)

 

idt_48: .word   0, 0, 0 # base = limit = 0

gdt_48: .word   6*8-1

        .long   bootsym_rel(trampoline_gdt,4)

trampoline_gdt:

        /* 0x0000: unused */

        .quad   0x0000000000000000

        /* 0x0008: ring 0 code, 32-bit mode */

        .quad   0x00cf9a000000ffff

        /* 0x0010: ring 0 code, 64-bit mode */

        .quad   0x00af9a000000ffff

        /* 0x0018: ring 0 data */

        .quad   0x00cf92000000ffff

        /* 0x0020: real-mode code @ BOOT_TRAMPOLINE */

        .long   0x0000ffff

        .long   0x00009a00

        /* 0x0028: real-mode data @ BOOT_TRAMPOLINE */

        .long   0x0000ffff

        .long   0x00009200

 

        .pushsection .trampoline_rel, "a"

        .long   trampoline_gdt + BOOT_PSEUDORM_CS + 2 - .

        .long   trampoline_gdt + BOOT_PSEUDORM_DS + 2 - .

        .popsection

 

        .globl cpuid_ext_features

cpuid_ext_features:

        .long   0

 

        .globl trampoline_xen_phys_start

trampoline_xen_phys_start:

        .long   0

 

        .globl trampoline_cpu_started

trampoline_cpu_started:

        .byte   0

 

        .code32

        /*1: 从实模式跳转到这里运行,也就是正式进入保护模式*/

trampoline_protmode_entry:

        /* Set up a few descriptors: on entry only CS is guaranteed good. */

        mov     $BOOT_DS,%eax

        mov     %eax,%ds

        mov     %eax,%es

 

        /* Set up FPU. */

        fninit

 

        /* Initialise CR4. */

        mov     $X86_CR4_PAE,%ecx

        mov     %ecx,%cr4

 

        /* Load pagetable base register. */

        mov     $sym_phys(idle_pg_table),%eax

        add     bootsym_rel(trampoline_xen_phys_start,4,%eax)

        mov     %eax,%cr3

 

        /* Set up EFER (Extended Feature Enable Register). */

        mov     bootsym_rel(cpuid_ext_features,4,%edi)

        test    $0x20100800,%edi /* SYSCALL/SYSRET, No Execute, Long Mode? */

        jz      .Lskip_efer

        movl    $MSR_EFER,%ecx

        rdmsr

#if CONFIG_PAGING_LEVELS == 4

        btsl    $_EFER_LME,%eax /* Long Mode      */

        btsl    $_EFER_SCE,%eax /* SYSCALL/SYSRET */

#endif

        btl     $20,%edi        /* No Execute?    */

        jnc     1f

        btsl    $_EFER_NX,%eax  /* No Execute     */

1:      wrmsr

.Lskip_efer:

 

        mov     $0x80050033,%eax /* hi-to-lo: PG,AM,WP,NE,ET,MP,PE */

        mov     %eax,%cr0

        jmp     1f

1:

 

#if defined(__x86_64__)

 

        /* Now in compatibility mode. Long-jump into 64-bit mode. */

        ljmp    $BOOT_CS64,$bootsym_rel(start64,6)

 

        .code64

start64:

        /* Jump to high mappings. */

        mov     high_start(%rip),%rax

        jmpq    *%rax

 

high_start:

        .quad   __high_start

 

#else /* !defined(__x86_64__) */

 

        /* Install relocated selectors. */

lgdt    gdt_descr/*正式装载初始化后的GDT,这里装入的GDT为汇编期间最终的GDT,在x86_32.s中定义*/

        mov     $(__HYPERVISOR_DS),%eax

        mov     %eax,%ds

        mov     %eax,%es

        mov     %eax,%fs

        mov     %eax,%gs

        mov     %eax,%ss

        /*长跳转到x86_32.s的入口__high_start,该变量在head.s中定义,为x86_32.s的入口,x86_32.s

        head.s中以包含的方式调用*/

        ljmp    $(__HYPERVISOR_CS),$__high_start

 

#endif

 

        .code32

/*0: head.sret指令跳转后首先到达这里开始执行,32位代码,此时还处在保护模式下*/

trampoline_boot_cpu_entry:

        cmpb    $0,bootsym_rel(skip_realmode,5)

        jnz     .Lskip_realmode

 

        /* Load pseudo-real-mode segments. */

        mov     $BOOT_PSEUDORM_DS,%eax

        mov     %eax,%ds

        mov     %eax,%es

        mov     %eax,%fs

        mov     %eax,%gs

        mov     %eax,%ss

 

        /* Switch to pseudo-rm CS, enter real mode, and flush insn queue. */

        mov     %cr0,%eax

        dec     %eax

        /*通过下面两个长跳转切换到实模式*/

        ljmp    $BOOT_PSEUDORM_CS,$bootsym(1f)

        .code16

1:      mov     %eax,%cr0                 # CR0.PE = 0 (leave protected mode)

 

        /* Load proper real-mode values into %cs, %ds, %es and %ss. */

        ljmp    bootsym_segrel(1f,2)

1:      mov     %cs,%ax

        mov     %ax,%ds

        mov     %ax,%es

        mov     %ax,%ss

 

        /* Initialise stack pointer and IDT, and enable irqs. */

        xor     %sp,%sp

        lidt    bootsym(rm_idt)/*加载IDT*/

        sti

 

#if defined(__x86_64__)

        /*

         * Declare that our target operating mode is long mode.

         * Initialise 32-bit registers since some buggy BIOSes depend on it.

         */

        movl    $0xec00,%eax      # declare target operating mode

        movl    $0x0002,%ebx      # long mode

        int     $0x15

#endif

 

        /*

         * Do real-mode work:

         *  1. Get memory map.

         *  2. Get Enhanced Disk Drive (EDD) information.

         *  3. Set video mode.

         */

         /*获得内存信息,该函数于mem.s中调用,内存信息存放于e820map变量中,

         类似Linux内核的处理方式,调用0x15号中断*/

        call    get_memory_map

        /*调用于edd.s*/

        call    get_edd

            /*调用于video.s*/

        call    video

 

        /* Disable irqs before returning to protected mode. */

        cli

 

        /* Reset GDT and IDT. Some BIOSes clobber GDTR. */

        lidt    bootsym(idt_48)

        lgdt    bootsym(gdt_48)

 

        /* Enter protected mode, and flush insn queue. */

        xor     %ax,%ax

        inc     %ax

        lmsw    %ax                       # CR0.PE = 1 (enter protected mode)

 

        /* Load proper protected-mode values into all segment registers. */

                   /*跳转到32位代码,为进入保护模式做准备*/

        ljmpl   $BOOT_CS32,$bootsym_rel(1f,6)

        .code32

1:      mov     $BOOT_DS,%eax

        mov     %eax,%ds

        mov     %eax,%es

        mov     %eax,%fs

        mov     %eax,%gs

        mov     %eax,%ss

 

.Lskip_realmode:

        /* EBX == 0 indicates we are the BP (Boot Processor). */

        xor     %ebx,%ebx

 

        /* Jump to the common bootstrap entry point. */

        jmp     trampoline_protmode_entry/*跳转到保护模式入口*/

 

skip_realmode:

        .byte   0

 

rm_idt: .word   256*4-1, 0, 0

/*这三部分的内容不再这里详细写了*/

#include "mem.S"

#include "edd.S"

#include "video.S"

#include "wakeup.S"

 

你可能感兴趣的:(Xen源代码分析(二)——trampoline.s)