Question

I read the code of xen and find the code below. But I don't know the meaning of it. Is it the code which initializes idt and gdt? Is it the code that jumps from real mode to protected mode? If it is, where is the physical address of gdt and idt? Hvmloader.c :

asm (
    "    .text                       \n"
    "    .globl _start               \n"
    "_start:                         \n"
    /* C runtime kickoff. */
    "    cld                         \n"
    "    cli                         \n"
    "    lgdt gdt_desr               \n"
    "    mov  $"STR(SEL_DATA32)",%ax \n"
    "    mov  %ax,%ds                \n"
    "    mov  %ax,%es                \n"
    "    mov  %ax,%fs                \n"
    "    mov  %ax,%gs                \n"
    "    mov  %ax,%ss                \n"
    "    ljmp $"STR(SEL_CODE32)",$1f \n"
    "1:  movl $stack_top,%esp        \n"
    "    movl %esp,%ebp              \n"
    "    call main                   \n"
    /* Relocate real-mode trampoline to 0x0. */
    "    mov  $trampoline_start,%esi \n"
    "    xor  %edi,%edi              \n"
    "    mov  $trampoline_end,%ecx   \n"
    "    sub  %esi,%ecx              \n"
    "    rep  movsb                  \n"
    /* Load real-mode compatible segment state (base 0x0000, limit 0xffff). */
    "    mov  $"STR(SEL_DATA16)",%ax \n"
    "    mov  %ax,%ds                \n"
    "    mov  %ax,%es                \n"
    "    mov  %ax,%fs                \n"
    "    mov  %ax,%gs                \n"
    "    mov  %ax,%ss                \n"
    /* Initialise all 32-bit GPRs to zero. */
    "    xor  %eax,%eax              \n"
    "    xor  %ebx,%ebx              \n"
    "    xor  %ecx,%ecx              \n"
    "    xor  %edx,%edx              \n"
    "    xor  %esp,%esp              \n"
    "    xor  %ebp,%ebp              \n"
    "    xor  %esi,%esi              \n"
    "    xor  %edi,%edi              \n"
    /* Enter real mode, reload all segment registers and IDT. */
    "    ljmp $"STR(SEL_CODE16)",$0x0\n"
    "trampoline_start: .code16       \n"
    "    mov  %eax,%cr0              \n"
    "    ljmp $0,$1f-trampoline_start\n"
    "1:  mov  %ax,%ds                \n"
    "    mov  %ax,%es                \n"
    "    mov  %ax,%fs                \n"
    "    mov  %ax,%gs                \n"
    "    mov  %ax,%ss                \n"
    "    lidt 1f-trampoline_start    \n"
    "    ljmp $0xf000,$0xfff0        \n"
    "1:  .word 0x3ff,0,0             \n"
    "trampoline_end:   .code32       \n"
    "                                \n"
    "gdt_desr:                       \n"
    "    .word gdt_end - gdt - 1     \n"
    "    .long gdt                   \n"
    "                                \n"
    "    .align 8                    \n"
    "gdt:                            \n"
    "    .quad 0x0000000000000000    \n"
    "    .quad 0x008f9a000000ffff    \n" /* Ring 0 16b code, base 0 limit 4G */
    "    .quad 0x008f92000000ffff    \n" /* Ring 0 16b data, base 0 limit 4G */
    "    .quad 0x00cf9a000000ffff    \n" /* Ring 0 32b code, base 0 limit 4G */
    "    .quad 0x00cf92000000ffff    \n" /* Ring 0 32b data, base 0 limit 4G */
    "    .quad 0x00af9a000000ffff    \n" /* Ring 0 64b code */
    "gdt_end:                        \n"
    "                                \n"
    "    .bss                        \n"
    "    .align    8                 \n"
    "stack:                          \n"
    "    .skip    0x4000             \n"
    "stack_top:                      \n"
    "    .text                       \n"
    );

Thanks.

Was it helpful?

Solution

From the beginning of the code:

cld - clear direction flag.

cli - clear interrupt flag to mask interrupts.

lgdt gdt_desr - loads the value of gdt_desr into gdt. Look for gdt_desr in the source code to find out the value loaded to gdt.

"    mov  $"STR(SEL_DATA32)",%ax \n"
"    mov  %ax,%ds                \n"
"    mov  %ax,%es                \n"
"    mov  %ax,%fs                \n"
"    mov  %ax,%gs                \n"
"    mov  %ax,%ss                \n"

Store the value STR(SEL_DATA32) into ax, and then from ax to ds, es, fs, gs and ss (to all segment registers except cs).

"    ljmp $"STR(SEL_CODE32)",$1f \n"

Does a long jump / far jump to STR(SEL_CODE32):0x1f, practically sets cs to STR(SEL_CODE32) and eip to 0x1f.

If this is a a 32-bit code segment, the processor goes into 32-bit protected mode. See Stackoverflow question: bootloader - switching processor to protected mode. However, I don't see here the code used to set the PE bit of cr0 register as in the above example and in Wikipedia article on protected mode.

After that line of code cs:eip moves to that address (STR(SEL_CODE32):0x1f) not shown in this piece of code, so I can't say what happens then. It may continue on the next line too if cs:eip points there (if that's the jump address). Anyway, the rest of the code and comments looks like the code used to switch from protected mode back to real mode.

Intruction lidt 1f-trampoline_start loads the value of 1f-trampoline_start into idt, so to get to know the actual value used, search the source for if-trampoline_start.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top