> On Jun 7, 2016, at 2:59 PM, Brett Stahlman <brettstahl...@gmail.com> wrote: > > 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. >
Brett, No worries. If you work on firmware long enough Heisenberg like uncertainty always seem to strike at some point. Thanks, Andrew Fish > Thanks, > Brett S. > > > On Tue, Jun 7, 2016 at 11:15 AM, Laszlo Ersek <ler...@redhat.com> wrote: >> 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