On 06/07/16 17:35, Andrew Fish wrote:
> 
>> On Jun 7, 2016, at 8:31 AM, Brett Stahlman <brettstahl...@gmail.com> 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 <brettstahl...@gmail.com> 
>> 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
>> edk2-devel@lists.01.org
>> https://lists.01.org/mailman/listinfo/edk2-devel
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
> 

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to