d'Oh! Mystery solved. Working through the `info registers' output you
sent helped me see what was happening. The system I'm working with had
a buggy printf: in particular, it was parsing but effectively throwing
away the `l' in a %ld or %lx specifier, so my attempts to print GDT
entries with %lx were giving misleading results. (Yes, I realize I
should have been using EFI's Print routine - lesson learned...) I
apologize for the confusion.

I appreciate all the pointers from you and Andrew. I feel I have a
much better handle on all this now.

Thanks,
Brett S.


On Tue, Jun 7, 2016 at 11:15 AM, Laszlo Ersek <[email protected]> wrote:
> On 06/07/16 17:35, Andrew Fish wrote:
>>
>>> On Jun 7, 2016, at 8:31 AM, Brett Stahlman <[email protected]> wrote:
>>>
>>> Ah. I think I may have found the answer to at least part of my
>>> question, but would appreciate if someone could confirm...
>>>
>>> Section 2.3.4 of the UEFI spec states:
>>> "Selectors are set to be flat and are otherwise not used."
>>>
>>> Section 3.2.4 of the Intel processor spec (Vol. 3A 3-7) states:
>>> "In 64-bit mode, segmentation is generally (but not completely)
>>> disabled, creating a
>>> flat 64-bit linear-address space... Note that the processor does not
>>> perform segment limit checks at runtime in 64-bit mode."
>>>
>>> So if I'm reading all this correctly... The value of the fields
>>> governing the interpretation of the segment limits (e.g., L and D/B)
>>> are "don't cares" in IA32e 64-bit mode. But what about fields not
>>> directly related to limit checks: e.g., P (Present) flag, and DPL
>>> (Descriptor Privilege Level)? Do their values not matter either?
>>>
>>
>> Brett,
>>
>> Yes you only need valid entries for segments that are used. If I'm 
>> remembering correctly you can use the index in the segment registers to map 
>> to the GDT entry.
>
> Right, here's the output of the "info registers" QEMU monitor command,
> while standing in the setup browser in OVMF:
>
> RAX=00000000bfdbbcf0 RBX=00000000beafdc84 RCX=00000000bf645a98 
> RDX=0000000000000000
> RSI=00000000bff5d588 RDI=00000000bff99fb0 RBP=00000000bff5d350 
> RSP=00000000bff5d328
> R8 =0000000000000000 R9 =0000000000000001 R10=0000000000000064 
> R11=0000000000000040
> R12=0000000000000000 R13=0000000000000000 R14=0000000000000000 
> R15=0000000000000000
> RIP=00000000bfdbbcf1 RFL=00000206 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=1
> ES =0030 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
> CS =0038 0000000000000000 ffffffff 00a09b00 DPL=0 CS64 [-RA]
> SS =0030 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
> DS =0030 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
> FS =0030 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
> GS =0030 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
> LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
> TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
> GDT=     00000000bfeea698 00000047
> IDT=     00000000bf646018 00000fff
> CR0=80000033 CR2=0000000000000000 CR3=00000000bfefc000 CR4=00000668
> DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 
> DR3=0000000000000000
> DR6=00000000ffff0ff0 DR7=0000000000000400
> EFER=0000000000000500
> FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
> FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
> FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
> FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
> FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
> XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
> XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
> XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
> XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
> XMM08=00000000000000000000000000000000 XMM09=00000000000000000000000000000000
> XMM10=00000000000000000000000000000000 XMM11=00000000000000000000000000000000
> XMM12=00000000000000000000000000000000 XMM13=00000000000000000000000000000000
> XMM14=00000000000000000000000000000000 XMM15=00000000000000000000000000000000
>
> CS points to offset 0x38 in the GDT, and the other segment registers
> (data and stack) all point to the entry at offset 0x30.
>
> * For the DXE Core, the GDT is set up in
> "MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c":
>
> //
> // Global Descriptor Table (GDT)
> //
> GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT gGdtEntries[] = {
> /* selector { Global Segment Descriptor                              } */
> /* 0x00 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}}, 
> //null descriptor
> /* 0x08 */  {{0xffff, 0,  0,  0x2,  1,  0,  1,  0xf,  0,  0, 1,  1,  0}}, 
> //linear data segment descriptor
> /* 0x10 */  {{0xffff, 0,  0,  0xf,  1,  0,  1,  0xf,  0,  0, 1,  1,  0}}, 
> //linear code segment descriptor
> /* 0x18 */  {{0xffff, 0,  0,  0x3,  1,  0,  1,  0xf,  0,  0, 1,  1,  0}}, 
> //system data segment descriptor
> /* 0x20 */  {{0xffff, 0,  0,  0xa,  1,  0,  1,  0xf,  0,  0, 1,  1,  0}}, 
> //system code segment descriptor
> /* 0x28 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}}, 
> //spare segment descriptor
> /* 0x30 */  {{0xffff, 0,  0,  0x2,  1,  0,  1,  0xf,  0,  0, 1,  1,  0}}, 
> //system data segment descriptor
> /* 0x38 */  {{0xffff, 0,  0,  0xa,  1,  0,  1,  0xf,  0,  1, 0,  1,  0}}, 
> //system code segment descriptor
> /* 0x40 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}}, 
> //spare segment descriptor
> };
>
> * For the DXE phase, the GDT is set up by the CpuDxe driver, in its
> entry point. It uses the GDT entries at offsets LINEAR_DATA64_SEL (0x30)
> and LINEAR_CODE64_SEL (0x38) in the same vein; see
> InitGlobalDescriptorTable() in "UefiCpuPkg/CpuDxe/CpuGdt.c". And, the
> byte-limit (= limit in units * unit granularity) is never raised above
> 4GB, I think.
>
> I believe the settings from this driver are the ones visible in the
> above "info registers" output.
>
> * In SMM, the GDT is managed by UefiCpuPkg/PiSmmCpuDxeSmm, and it also
> seems to store the GDT entry that describes the long mode code segment
> at offset 0x38 (LONG_MODE_CS) in the GDT.
>
> So 0x38 appears to be an edk2 convention for the offset of the
> descriptor that describes the 64-bit code segment.
>
> Related commit:
> - https://github.com/tianocore/edk2/commit/0d4c1db81aab
>
> Related emails preceding that commit:
> - http://thread.gmane.org/gmane.comp.bios.edk2.devel/3509/focus=3568
> - http://thread.gmane.org/gmane.comp.bios.edk2.devel/3509/focus=3605
> - http://thread.gmane.org/gmane.comp.bios.edk2.devel/3571
>
> Thanks
> Laszlo
>
>>> On Tue, Jun 7, 2016 at 8:46 AM, Brett Stahlman <[email protected]> 
>>> wrote:
>>>> Just inside my 64-bit x64 EFI boot loader, I print out the contents of
>>>> the GDT to see how it was initialized by the firmware. I've tried
>>>> running the boot loader both in QEMU (OVMF) and VMware ESXi. In both
>>>> cases, the first 5 descriptors after the leading null descriptor look
>>>> like this:
>>>>
>>>> 0x000000000000ffff
>>>>
>>>> Note all the leading zeroes: in particular, flags such as D/B and L
>>>> being clear seem to suggest a GDT that's inappropriate for 64-bit long
>>>> mode. I've verified by looking at CR* registers and such that the
>>>> firmware has indeed placed me in IA32e "long mode" with identity
>>>> paging. This is what I would expect, in light of section 2.3.4 in the
>>>> UEFI spec. But why does the GDT have all leading 0's?
>>>>
>>>> Thanks,
>>>> Brett S.
>>> _______________________________________________
>>> edk2-devel mailing list
>>> [email protected]
>>> https://lists.01.org/mailman/listinfo/edk2-devel
>>
>> _______________________________________________
>> edk2-devel mailing list
>> [email protected]
>> https://lists.01.org/mailman/listinfo/edk2-devel
>>
>
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to