Query regarding x86_64 purgatory and IA32-e compatibility mode
Eric W. Biederman
ebiederm at xmission.com
Thu Oct 25 23:14:58 EDT 2012
Vivek Goyal <vgoyal at redhat.com> writes:
> Hi Eric,
>
> I am reading up x86_64 purgatory code to understand how transition to
> 32bit protected mode happens.
>
> My understanding is that we enter in purgatory_start (setup-x86_64.S).
> Then we jump to entry64 in entry64.S.
>
> We run following code in arch/x86_64/entry64.S
>
> movq $stack_init, %rsp
> pushq $0x10 /* CS */
> pushq $new_cs_exit
> lretq
> new_cs_exit:
>
> /* Load the registers */
> movq rax(%rip), %rax
> movq rbx(%rip), %rbx
> movq rcx(%rip), %rcx
> movq rdx(%rip), %rdx
> movq rsi(%rip), %rsi
> movq rdi(%rip), %rdi
> movq rsp(%rip), %rsp
> movq rbp(%rip), %rbp
> movq r8(%rip), %r8
> movq r9(%rip), %r9
> movq r10(%rip), %r10
> movq r11(%rip), %r11
> movq r12(%rip), %r12
> movq r13(%rip), %r13
> movq r14(%rip), %r14
> movq r15(%rip), %r15
>
> Will above lretq call not switch us in compatibility mode (from 64bit
> mode)? We have taken a long jump and our new CS seems to have L bit
> 0.
> Following is our gdt.
>
> gdt: /* 0x00 unusable segment
> * 0x08 unused
> * so use them as the gdt ptr
> */
> .word gdt_end - gdt - 1
> .quad gdt
> .word 0, 0, 0
>
> /* 0x10 4GB flat code segment */
> .word 0xFFFF, 0x0000, 0x9A00, 0x00AF
>
> /* 0x18 4GB flat data segment */
> .word 0xFFFF, 0x0000, 0x9200, 0x00CF
> gdt_end:
>
> I see that bit 21 in second doubleword is 0. IIUC, that means that we
> will switch to compatibility mode. If yes, we are still continuing to
> use 64bit instructions and continue to access registers (rip, r8-15)
> which are available in 64bit mode only. Is this correct? How does this
> work?
/* 0x10 4GB flat code segment */
.word 0xFFFF, 0x0000, 0x9A00, 0x00AF
The high 16bits of that are:
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
0 0 0 0 0 0 0 0 1 0 1 0 1 1 1 1
Since L is bit 21 I read that as L=1.
I don't know how you see L=1 there.
The transition happens in entry64-32.S
We get there via:
jmp *rip(%rip)
The default value of rip is entry32.
That is where we clear bit 21 in
ljmp *lm_exit_addr(%rip)
Eric
More information about the kexec
mailing list