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