[if gte mso 9]>

Re: [edk2] LTCG and fixed address pointers.

Subject: Re: [edk2] LTCG and fixed address pointers.

From: "Tian, Feng" <feng.tian@intel.com>

To: "edk2-devel@lists.sourceforge.net" <edk2-devel@lists.sourceforge.net>

Date: 2013-05-23 15:07:38

Hi, Tim

 

It’s weird why I didn’t meet your issue?

 

VariableDxe.c.patch is what I modified to emulate your case.

 

The pcd definition is updated to:

  ## 64-bit Base address of the NV variable range in flash device

  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0xFFE00008|UINT64|0x80000001

 

The CC flag is:

  DEBUG_VS2008x86_X64_CC_FLAGS     = /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1ib2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Gm

The Link flag is:

  DEBUG_VS2008x86_X64_DLINK_FLAGS  = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG

 

[From above build flag, we can know LTO feature is enabled as /GL and /LTCG has been used]

 

The output.txt is the disassembly file of “dmpbin.exe”, in which line 26 ~28, I don’t see the assembly code segment like you shown. (due to 512k mail size limitation, I have to trim some output in output.txt)

 

The disassembly code is:

  0000000000000A12: B8 08 01 E0 FF     mov         eax,0FFE00108h

  0000000000000A17: B9 08 00 E0 FF     mov         ecx,0FFE00008h

  0000000000000A1C: 80 38 00           cmp         byte ptr [rax],0

 

So what build flag are you using?

 

Thanks

Feng

 

From: Tim Lewis [mailto:tim.lewis@insyde.com]
Sent: Thursday, May 23, 2013 09:30
To: edk2-devel@lists.sourceforge.net
Subject: Re: [edk2] LTCG and fixed address pointers.

 

To follow up further, the problem appears to be an encoding error:

 

The bytes for the encoding are below. The value of the PCD was 0x00000000ffe8b00e

 

  0000000000063B24: 44 38 B0 0E B0 E8 FF cmp         byte ptr [rax-174FF2h],r14b

 

44 = extend the R field in the mod R/M byte.

38 = compare

B0 = modrm = [rax+disp32], and r = r14

Disp32 = ffe8b0038

 

Notice that the PCD value is encoded directly as a displacement. But, in 64-bit modes, displacements are sign-extended (see 2.2.1.3 in Vol 2 of the Intel Ref) to 64-bits, which means it acts, -effectively, like a subtraction. For an unsigned integer, it must be encoded with a register. In fact, a few instructions before, you can see:

 

  0000000000063B14: BA 0E B0 E8 FF     mov         edx,0FFE8B00Eh

 

So this would have been better encoded as cmp byte ptr [rax + rdx], r14b

 

Tim

 

 

From: Tim Lewis [mailto:tim.lewis@insyde.com]
Sent: Tuesday, May 21, 2013 9:41 PM
To: edk2-devel@lists.sourceforge.net
Subject: Re: [edk2] LTCG and fixed address pointers.

 

We tried as a UINT64. Same result. Tim

 

From: Tian, Feng [mailto:feng.tian@intel.com]
Sent: Tuesday, May 21, 2013 8:26 PM
To: edk2-devel@lists.sourceforge.net
Subject: Re: [edk2] LTCG and fixed address pointers.

 

How about defining this Pcd as UINT64? We defined PcdPciExpressBaseAddress like this way.

 

So your code should be:

 

In Dec file:

  gXxxTokenSpaceGuid.PcdXxxAddress|0xFFe8B00E|UINT64|0x12345678

 

In C code:

  StrPtr = PcdGet64 (PcdXXX) + 0x100;

 

From: Tim Lewis [mailto:tim.lewis@insyde.com]
Sent: Wednesday, May 22, 2013 01:16
To: edk2-devel@lists.sourceforge.net
Subject: [edk2] LTCG and fixed address pointers.

 

We are having trouble with link-time code generation under Visual Studio when using PCDs to specify a specific address and convert it to a pointer, when accessed from a library. In a library, the FixedAtBuild PCDs (on x64) are defned as extern const UINT32 PcdXXXX; and PcdXXXX contains 0xffe8b00e. The code generated by VS2008/2010/2012 linker shows:

 

xor         r12d,r12d         // r12d = 0

mov         eax,r12d          // eax = r12d == 0  rax = ?

cmp         byte ptr [rax-174FF2h],r12b

 

Notice LTCG is trying to optimize by using a relative offset from 0. “0 – 174ff2” is FFFFFFFFFFE8B00E (not FFe8B00e).

 

The code in question is in the form:

 

CHAR8 *StrPtr;

 

StrPtr = (CHAR8 *)(UINTN) (PcdGet(PcdXXXX) + 0x100))

while (*StrPtr != ‘\0’) {

}

 

We have tried nearly everything we can think of, other than turning off LTCG for the module or even the specific lines. I am worried about what happens with MMIO and other “fixed” addresses. I have tried (CHAR8 *)(UINTN) (UINT32)  and almost every possible combination of typecases on the PCD result and the 0x100, etc. Even did & 0xffffffff. No effect.

 

If I turn off LTCG, it correctly creates a 32-bit address.

 

I haven’t been able to get any response on the MS forums.

 

Anyone have any experience with this?

 

Tim