On 10/29/15 18:30, Kinney, Michael D wrote:
> Laszlo,
> 
> Thanks for the very detailed and complete root cause on this issue.
> I agree that the change you suggest is functional, but I am going to
> recommend a different solution.
> 
> Unfortunately, there are several modules that set up a GDT and it is
> easier from an implementation perspective and for debugging if all
> the modules agree to use the same GDT layout.  It would be even
> better if no modules make any assumptions about GDT layouts, but that
> is a bigger change that we can tackle later.
> 
> The root cause of this specific issue is that the GDT that is set up
> by MdeModulePkg/Core/DxeIplPeim is not the same GDT that is set up by
> UefiCpuPkg /CpuDxe.  And the UefiCpuPkg/PiSmmCpuDxeSmm module has
> some assumptions that the GDT is the one setup by
> MdeModulePkg/Core/DxeIplPeim.  I recommend we update
> UefiCpuPkg/CpuDxe to use the same GDT layout as
> MdeModulePkg/Core/DxeIplPeim and then the changes you found worked
> for PiSmmCpuDxeSmm are not required.
> 
> I will work on a patch for you to test.

I agree this is the best solution. (I didn't know which one of CpuDxe
and DxeIplPeim should prevail in dictating the GDT convention, so I
didn't suggest any unification like this.)

Thanks!
Laszlo

> 
> Mike
> 
>> -----Original Message-----
>> From: edk2-devel [mailto:[email protected]] On Behalf Of
>> Laszlo Ersek
>> Sent: Thursday, October 29, 2015 9:19 AM
>> To: Yao, Jiewen; Kinney, Michael D; Fan, Jeff
>> Cc: Justen, Jordan L; edk2-devel-01
>> Subject: Re: [edk2] about the SMM_S3_RESUME_SMM_64 branch in
>> S3Resume2Pei
>>
>> Hi Jiewen,
>>
>> On 10/29/15 03:28, Yao, Jiewen wrote:
>>> Thanks for the info. I think we might have to dig out why LONG_JUMP fail
>> here.
>>> Most our IA BIOS support Ia32X64 mode, so I am sure it should work.
>>
>> I think I have found the bug.
>>
>> (1)
>> I added a debug patch to OvmfPkg/QuarkPort/CpuS3DataDxe. I'm attaching it
>> for illustration. The debug patch dumps the following information:
>> - the location of the GDT descriptor (that gets loaded into the GDT register)
>> - the contents of the GDT descriptor (i.e., the base and limit of the global
>> descriptor table)
>> - the contents of the GDT entries (the individual segment descriptors)
>>
>> CpuS3DataDxe saves these in AcpiNVS. Later they are saved by
>> PiSmmCpuDxeSmm from AcpiNVS to SMRAM (during boot), and then restored
>>from SMRAM to AcpiNVS (during S3 Resume).
>>
>> The patch dumps these details when the preparation for PiSmmCpuDxeSmm,
>> in AcpiNVS, is ready.
>>
>> Here's the debug output:
>>
>> SaveCpuS3Data: 350: GDT descriptor at 0x7E3E2050
>> SaveCpuS3Data: 353: GDT Base=0x7F706000 Limit=0x3F
>> SaveCpuS3Data: 363: Idx=0x00 Base=0x00000000 Limit=0x00000000 Type=0x0
>> System=0x0 Dpl=0x0 Present=0x0 Software=0x0 LCodeSeg=0x0 DefaultSize=0x0
>> SaveCpuS3Data: 363: Idx=0x08 Base=0x00000000 Limit=0xFFFFFFFF Type=0x3
>> System=0x1 Dpl=0x0 Present=0x1 Software=0x0 LCodeSeg=0x0 DefaultSize=0x1
>> SaveCpuS3Data: 363: Idx=0x10 Base=0x00000000 Limit=0xFFFFFFFF Type=0xB
>> System=0x1 Dpl=0x0 Present=0x1 Software=0x0 LCodeSeg=0x0 DefaultSize=0x1
>> SaveCpuS3Data: 363: Idx=0x18 Base=0x00000000 Limit=0xFFFFFFFF Type=0x2
>> System=0x1 Dpl=0x0 Present=0x1 Software=0x0 LCodeSeg=0x0 DefaultSize=0x1
>> SaveCpuS3Data: 363: Idx=0x20 Base=0x00000000 Limit=0xFFFFFFFF Type=0xA
>> System=0x1 Dpl=0x0 Present=0x1 Software=0x0 LCodeSeg=0x0 DefaultSize=0x1
>> SaveCpuS3Data: 363: Idx=0x28 Base=0x00000000 Limit=0xFFFFFFFF Type=0xB
>> System=0x1 Dpl=0x0 Present=0x1 Software=0x0 LCodeSeg=0x1 DefaultSize=0x0
>> SaveCpuS3Data: 363: Idx=0x30 Base=0x00000000 Limit=0x00000000 Type=0x0
>> System=0x0 Dpl=0x0 Present=0x0 Software=0x0 LCodeSeg=0x0 DefaultSize=0x0
>> SaveCpuS3Data: 363: Idx=0x38 Base=0x00000000 Limit=0x00000000 Type=0x0
>> System=0x0 Dpl=0x0 Present=0x0 Software=0x0 LCodeSeg=0x0 DefaultSize=0x0
>>
>> (Importantly, the debug output is identical between the pure Ia32 build and
>> the Ia32X64 build, except the addresses in the first two lines -- the 
>> location of
>> the GDT descriptor, and the location of the GDT itself.)
>>
>>
>> (2) Now locate the offset (= selector) of the *only* segment that is 
>> advertised
>> as "64-bit code". The LCodeSeg bit-field is 1 only for Idx=0x28.
>>
>>
>> (3) If you examine "UefiCpuPkg/PiSmmCpuDxeSmm/X64/MpFuncs.asm", you
>> can see:
>>
>> LONG_JUMP::
>>
>>        db 67h,  0EAh                 ; far jump
>>        dd 0h                         ; 32-bit offset
>>        dw 38h                        ; 16-bit selector
>>
>> The segment selector is 0x38 here, which not only lacks the LCodeSeg (= long
>> mode code) bit, but it is actually a null-descriptor.
>>
>> So this is the direct cause for the triple fault, but why does it work in 
>> the pure
>> Ia32 case, and what is the *root* cause for the triple fault in the Ia32X64
>> case?
>>
>> We can investigate some more:
>>
>>
>> (4) The DXE IPL PEIM actually sets up the 0x38 segment correctly. In the
>> HandOffToDxeCore() function
>> [MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c], branch
>> "PcdDxeIplSwitchToLongMode", the last statement is:
>>
>>    //
>>    // Go to Long Mode and transfer control to DxeCore.
>>    // Interrupts will not get turned on until the CPU AP is loaded.
>>    // Call x64 drivers passing in single argument, a pointer to the HOBs.
>>    //
>>    AsmEnablePaging64 (
>>      SYS_CODE64_SEL,
>>      DxeCoreEntryPoint,
>>      (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw),
>>      0,
>>      TopOfStack
>>      );
>>
>> where SYS_CODE64_SEL equals 0x38. Because the 64-bit DXE core starts
>> running, segment 0x38 is obviously correctly configured at this point. (See
>> also the "gGdtEntries" array in
>> "MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c" -- the entry at byte
>> offset 0x38 sets the LCodeSeg bit.)
>>
>>
>> (5) *However*, when the CpuDxe driver starts, the InitializeCpu() entry point
>> function does the following:
>>
>> InitializeCpu() [UefiCpuPkg/CpuDxe/CpuDxe.c]
>>
>>  //
>>  // Init GDT for DXE
>>  //
>>  InitGlobalDescriptorTable ();
>>
>>    //
>>    // Initialize all GDT entries
>>    //
>>    CopyMem (gdt, &GdtTemplate, sizeof (GdtTemplate));
>>
>> And the GdtTemplate array [UefiCpuPkg/CpuDxe/CpuGdt.c] is what we can
>> see in the debug dump above!
>>
>> 0x38 corresponds to "SPARE5_SEL" in CpuDxe, and the only long-mode code
>> segment is LINEAR_CODE64_SEL (0x28).
>>
>> In summary, the bug is that CpuDxe sets up a GDT that is incompatible with
>> "UefiCpuPkg/PiSmmCpuDxeSmm/X64/MpFuncs.*".
>>
>>
>> (6) I'm unsure how this could be fixed. *Although* both "gGdtEntries" from
>> the DXE IPL, and "GdtTemplate" from CpuDxe, have one 64-bit code segment
>> each, the segment descriptors are not identical. (For which reason I'm unsure
>> if we can simply point "UefiCpuPkg/PiSmmCpuDxeSmm/X64/MpFuncs.*" to
>> the segment that comes from CpuDxe, when the assembly had been clearly
>> written with the DXE IPL's segment in mind.)
>>
>> There is precisely one difference between them: the one from the DXE IPL has
>> type 0xa (according to the Intel SDM, that means "Execute/Read"), whereas
>> the one from CpuDxe has type 0xb ("Execute/Read, accessed").
>>
>> I guess the "accessed" bit in the segment type is not a critical difference. 
>> Some
>> confirmation would be nice.
>>
>>
>> (7) Side investigation for the pure Ia32 build, and for the protected mode
>> stage of the X64 MpFuncs: for jumping to PMODE_ENTRY, both
>> "Ia32/MpFuncs.asm" and "X64/MpFuncs.asm" use selector 0x20:
>>
>> FLAT32_JUMP::
>>
>>        db 66h,  67h, 0EAh            ; far jump
>>        dd 0h                         ; 32-bit offset
>>        dw 20h                        ; 16-bit selector
>>
>> PMODE_ENTRY::                         ; protected mode entry point
>>
>> Now, the segment identified by selector 0x20 in gGdtEntries (from the DXE
>> IPL) is:
>>
>> /* 0x20 */  {{0xffff, 0,  0,  0xa,  1,  0,  1,  0xf,  0,  0, 1,  1,  0}}, 
>> //system code
>> segment descriptor
>>
>> whereas the segment identified by the same selector 0x20 in GdtTemplate
>> (from CpuDxe) is:
>>
>> SaveCpuS3Data: 363: Idx=0x20 Base=0x00000000 Limit=0xFFFFFFFF Type=0xA
>> System=0x1 Dpl=0x0 Present=0x1 Software=0x0 LCodeSeg=0x0 DefaultSize=0x1
>>
>> which are *exactly* the same.
>>
>> This is the reason why the pure Ia32 build works fine, and also the reason
>> why the Ia32X64 build doesn't blow up in FLAT32_JUMP (only in LONG_JUMP).
>>
>>
>> (8) As far as testing goes, with the following patch in place:
>>
>>> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/MpFuncs.S
>> b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/MpFuncs.S
>>> index d7cbc8c..146b54b 100644
>>> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/MpFuncs.S
>>> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/MpFuncs.S
>>> @@ -120,7 +120,7 @@ LONG_JUMP:
>>>
>>>          .byte 0x67,0xEA               # far jump
>>>          .long 0x0                     # 32-bit offset
>>> -        .word 0x38                    # 16-bit selector
>>> +        .word 0x28                    # 16-bit selector
>>>
>>>  LongModeStart:
>>>
>>
>> the Ia32X64 guest *still* crashes, but it occurs somewhat later now:
>>
>> qemu-system-x86-25660 [000] 20922.542598: kvm_exit:             reason
>> CR_ACCESS rip 0x97077 info 0 0
>> qemu-system-x86-25660 [000] 20922.542598: kvm_cr:               cr_write 0 =
>> 0xe0000011
>> qemu-system-x86-25660 [000] 20922.542601: kvm_entry:            vcpu 1
>>
>> qemu-system-x86-25660 [000] 20922.542602: kvm_exit:             reason
>> TRIPLE_FAULT rip 0x97086 info 0 0
>> qemu-system-x86-25660 [000] 20922.542603: kvm_userspace_exit:   reason
>> KVM_EXIT_SHUTDOWN (8)
>>
>> (9) I *think* this then hits somewhere in here:
>>
>> LongModeStart::
>>
>>        mov         ax,  30h
>>        mov         ds,  ax
>>        mov         es,  ax
>>        mov         ss,  ax
>>
>> Looking again the segment descriptors at the top, the 0x30 selector is just 
>> as
>> invalid -- CpuDxe calls it SPARE4_SEL.
>>
>> Hm... let's see what it used to be in the DXE IPL PEIM... "gGdtEntries" in
>> "MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c":
>>
>> /* 0x30 */  {{0xffff, 0,  0,  0x2,  1,  0,  1,  0xf,  0,  0, 1,  1,  0}}, 
>> //system data
>> segment descriptor
>>
>>From CpuDxe, it seems to match SYS_DATA_SEL == 0x18 precisely:
>>
>> SaveCpuS3Data: 363: Idx=0x18 Base=0x00000000 Limit=0xFFFFFFFF Type=0x2
>> System=0x1 Dpl=0x0 Present=0x1 Software=0x0 LCodeSeg=0x0 DefaultSize=0x1
>>
>> (10) YES! :) With the following cumulative patch:
>>
>>> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/MpFuncs.S
>> b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/MpFuncs.S
>>> index d7cbc8c..6ec6363 100644
>>> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/MpFuncs.S
>>> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/MpFuncs.S
>>> @@ -120,11 +120,11 @@ LONG_JUMP:
>>>
>>>          .byte 0x67,0xEA               # far jump
>>>          .long 0x0                     # 32-bit offset
>>> -        .word 0x38                    # 16-bit selector
>>> +        .word 0x28                    # 16-bit selector
>>>
>>>  LongModeStart:
>>>
>>> -        movw        $0x30,%ax
>>> +        movw        $0x18,%ax
>>>          .byte       0x66
>>>          movw        %ax,%ds
>>>          .byte       0x66
>>
>> S3 resume works in the Ia32X64 build!!! :)
>>
>> This is the final part of the log written during S3 resume:
>>
>>> SmmLockBoxPeiLib RestoreAllLockBoxInPlace - Exit (Success)
>>> S3NvsPageTableAddress - 7DFDE000 (1)
>>> SMM S3 Signature                = 534D4D53
>>> SMM S3 Stack Base               = 7FF8A000
>>> SMM S3 Stack Size               = 8000
>>> SMM S3 Resume Entry Point       = 7FFB5617
>>> SMM S3 CR0                      = 80000033
>>> SMM S3 CR3                      = 7FF84000
>>> SMM S3 CR4                      = 668
>>> SMM S3 Return CS                = 10
>>> SMM S3 Return Entry Point       = 846C69
>>> SMM S3 Return Context1          = 7F6FA000
>>> SMM S3 Return Context2          = 7E039000
>>> SMM S3 Return Stack Pointer     = 81730C
>>> SMM S3 Smst                     = 7FFFDE00
>>> SmmRestoreCpu()
>>> SMM S3 Return CS                = 10
>>> SMM S3 Return Entry Point       = 846C69
>>> SMM S3 Return Context1          = 7F6FA000
>>> SMM S3 Return Context2          = 7E039000
>>> SMM S3 Return Stack Pointer     = 81730C
>>> Call AsmDisablePaging64() to return to S3 Resume in PEI Phase
>>> S3ResumeExecuteBootScript()
>>> Close all SMRAM regions before executing boot script
>>> Lock all SMRAM regions before executing boot script
>>> PeiS3ResumeState - 81D1A8
>>> Enable X64 and transfer control to Standalone Boot Script Executor
>>> S3BootScriptExecute:
>>> TableHeader - 0x7E620000
>>> TableHeader.Version - 0x0001
>>> TableHeader.TableLength - 0x00000045
>>> ExecuteBootScript - 7E62000D
>>> EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE
>>> BootScriptExecuteIoReadWrite - 0x0000B030, 0x00000000FFFFFFFF,
>> 0x0000000000000021
>>> S3BootScriptWidthUint32 - 0x0000B030
>>> S3BootScriptWidthUint32 - 0x0000B030 (0x00000021)
>>> ExecuteBootScript - 7E620024
>>> EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE
>>> BootScriptExecutePciCfgReadWrite - 0x000780A0, 0x000000000000FFFF,
>> 0x0000000000000010
>>> S3BootScriptWidthUint16 - 0x000780A0
>>> S3BootScriptWidthUint16 - 0x000780A0 (0xFFFF)
>>> ExecuteBootScript - 7E620037
>>> EFI_BOOT_SCRIPT_INFORMATION_OPCODE
>>> BootScriptExecuteInformation - 0x7E62003E
>>> BootScriptInformation: DE AD BE EF
>>> ExecuteBootScript - 7E620042
>>> S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE
>>> S3BootScriptDone - Success
>>> Call AsmDisablePaging64() to return to S3 Resume in PEI Phase
>>> Install PPI: 88C9D306-0900-4EB5-8260-3E2DBEDA1F89
>>> Install PPI: 605EA650-C65C-42E1-BA80-91A52AB618C6
>>> Transfer to 16bit OS waking vector - 991D0
>>
>> Do you guys agree that the cumulative patch above is correct? If so, then 
>> I'll
>> extend the fix to cover the MpFuncs.asm file as well (not just MpFuncs.S), 
>> and
>> then submit it as a formal patch.
>>
>> ... With this bug analyzed, we have no more *functional* bugs that would
>> *directly* block the SMM-for-OVMF series. Should we find other bugs, those
>> are now possible to solve incrementally. What remains is:
>> - reaching agreements in the pending debates
>> - addressing patch feedback and securing reviews.
>>
>> Thank you
>> Laszlo
>>
>>
>>>
>>> For "RSM from 64-bit mode ", I have already confirmed with IA32 SDM
>> owner that it is just typo.
>>> RSM should work in 64bit mode, so this patch is unnecessary, I believe.
>>> For debug purpose, you can apply it at first in your branch, just in case 
>>> it is
>> emulator error.
>>>
>>> Have a good night!
>>>
>>> Thank you
>>> Yao Jiewen
>>>
>>> -----Original Message-----
>>> From: edk2-devel [mailto:[email protected]] On Behalf Of
>> Laszlo Ersek
>>> Sent: Thursday, October 29, 2015 9:50 AM
>>> To: Yao, Jiewen; Kinney, Michael D; Fan, Jeff
>>> Cc: edk2-devel-01
>>> Subject: Re: [edk2] about the SMM_S3_RESUME_SMM_64 branch in
>> S3Resume2Pei
>>>
>>> On 10/29/15 02:32, Laszlo Ersek wrote:
>>>> On 10/29/15 01:31, Yao, Jiewen wrote:
>>>>> Hi Ersek
>>>>> I think S3ResumePei supports Ia32 and Ia32X64. It does not support X64.
>> So I believe Ia32X64 crash is a bug somewhere.
>>>>>
>>>>> Since you already run into SmmRestoreCpu(), would you please help to
>> check where is last instruction causing crash?
>>>>
>>>> Sure. The crash occurs on the following call path (starting with
>> SmmRestoreCpu()):
>>>>
>>>> SmmRestoreCpu()
>> [UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c]
>>>>   EarlyInitializeCpu()                 [UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c]
>>>>     SendInitSipiSipiAllExcludingSelf()
>>>> [UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c]
>>>>
>>>> I have a debug print right after the
>>>> SendInitSipiSipiAllExcludingSelf(), and the BSP starts printing it,
>>>> but before the message is completely printed, one of the APs (just
>>>> started) seems to crash the VM.
>>>>
>>>> It is perfectly possible that the ACPI_CPU_DATA structure that
>>>> OvmfPkg/QuarkPort/CpuS3DataDxe collects earlier causes this. Because,
>>>> before EarlyInitializeCpu() calls SendInitSipiSipiAllExcludingSelf(),
>>>> the startup vector is prepared from ACPI_CPU_DATA, in the
>>>> PrepareApStartupVector() function. No clue what goes wrong there.
>>>>
>>>> Let me check the KVM trace though... Okay, I massaged it a little bit
>>>> for easier readability. Here's when VCPU#0 runs
>>>> SendInitSipiSipiAllExcludingSelf():
>>>>
>>>>> kvm_exit:             reason APIC_ACCESS rip 0x7ffc9d7f info 1300 0
>>>>> kvm_emulate_insn:     0:7ffc9d7f: 89 10
>>>>> kvm_mmio:             mmio write len 4 gpa 0xfee00300 val 0xc4697
>>>>> kvm_apic:             apic_write APIC_ICR = 0xc4697
>>>>> kvm_apic_ipi:         dst 0 vec 151 
>>>>> (SIPI|physical|assert|edge|all-but-self)
>>>>> kvm_apic_accept_irq:  apicid 1 vec 151 (SIPI|edge)
>>>>> kvm_apic_accept_irq:  apicid 2 vec 151 (SIPI|edge)
>>>>> kvm_apic_accept_irq:  apicid 3 vec 151 (SIPI|edge)
>>>>> kvm_entry:            vcpu 0
>>>>
>>>>> kvm_exit:             reason APIC_ACCESS rip 0x7ffc9d06 info 300 0
>>>>> kvm_emulate_insn:     0:7ffc9d06: 8b 00
>>>>> kvm_apic:             apic_read APIC_ICR = 0xc4697
>>>>> kvm_mmio:             mmio read len 4 gpa 0xfee00300 val 0xc4697
>>>>> kvm_entry:            vcpu 0
>>>>
>>>>> kvm_exit:             reason APIC_ACCESS rip 0x7ffc9d7f info 1310 0
>>>>> kvm_emulate_insn:     0:7ffc9d7f: 89 10
>>>>> kvm_mmio:             mmio write len 4 gpa 0xfee00310 val 0x0
>>>>> kvm_apic:             apic_write APIC_ICR2 = 0x0
>>>>> kvm_entry:            vcpu 0
>>>>
>>>> And in response, this is how VCPU#1 behaves (I guess this matches
>> "UefiCpuPkg/PiSmmCpuDxeSmm/X64/MpFuncs.asm"?):
>>>>
>>>>> kvm_exit:             reason CR_ACCESS rip 0x35 info 0 0
>>>>> kvm_cr:               cr_write 0 = 0x60000011
>>>>> kvm_entry:            vcpu 1
>>>>
>>>>> kvm_exit:             reason CR_ACCESS rip 0x9705b info 4 0
>>>>> kvm_cr:               cr_write 4 = 0x20
>>>>> kvm_entry:            vcpu 1
>>>>
>>>>> kvm_exit:             reason CR_ACCESS rip 0x9705e info 103 0
>>>>> kvm_cr:               cr_write 3 = 0x7ff83000
>>>>> kvm_entry:            vcpu 1
>>>>
>>>>> kvm_exit:             reason MSR_READ rip 0x97068 info 0 0
>>>>> kvm_msr:              msr_read c0000080 = 0x0
>>>>> kvm_entry:            vcpu 1
>>>>
>>>>> kvm_exit:             reason MSR_WRITE rip 0x9706e info 0 0
>>>>> kvm_msr:              msr_write c0000080 = 0x100
>>>>> kvm_entry:            vcpu 1
>>>>
>>>>> kvm_exit:             reason CR_ACCESS rip 0x97077 info 0 0
>>>>> kvm_cr:               cr_write 0 = 0xe0000011
>>>>> kvm_entry:            vcpu 1
>>>>
>>>>> kvm_exit:             reason TRIPLE_FAULT rip 0x9707a info 0 0
>>>>> kvm_userspace_exit:   reason KVM_EXIT_SHUTDOWN (8)
>>>>
>>>> From counting the bytes in "MpFuncs.asm", and correlating them with
>>>> the RIP values in the trace, I *think* that the triple fault happens
>>>> right here:
>>>>
>>>> LONG_JUMP::
>>>>
>>>>         db 67h,  0EAh                 ; far jump
>>>>         dd 0h                         ; 32-bit offset
>>>>         dw 38h                        ; 16-bit selector
>>>>
>>>> Do you want me to log some values from from PrepareApStartupVector()?
>>>> Like the offset that gets patched in here, or the GDT (to see that
>>>> 0x38 makes sense)... I might have to do that tomorrow ^W after getting
>>>> some sleep however, it's 02:32 AM here.
>>>
>>> FWIW I retested with TCG too (i.e., emulation, not hw virtualization), and
>> the VM crashes the same way.
>>>
>>> Does it matter that I have this patch in my build, temporarily:
>>>
>>>   UefiCpuPkg: PiSmmCpuDxeSmm: do not execute RSM from 64-bit mode
>>>   http://thread.gmane.org/gmane.comp.bios.edk2.devel/3020/focus=3023
>>>
>>> (I don't think it matters at this stage in "MpFuncs.asm", but I should be 
>>> clear
>> about my environment...)
>>>
>>> Thanks
>>> Laszlo
>>>
>>>
>>>>> -----Original Message-----
>>>>> From: Laszlo Ersek [mailto:[email protected]]
>>>>> Sent: Thursday, October 29, 2015 7:59 AM
>>>>> To: Yao, Jiewen; Kinney, Michael D; Fan, Jeff
>>>>> Cc: edk2-devel-01
>>>>> Subject: Re: about the SMM_S3_RESUME_SMM_64 branch in
>> S3Resume2Pei
>>>>>
>>>>> On 10/28/15 23:41, Laszlo Ersek wrote:
>>>>>> On 10/28/15 23:26, Yao, Jiewen wrote:
>>>>>>> Right. It seems S3Resume2Pei does not consider X64 mode. I found at
>> least 3 functions need enhancement on mode transition:
>>>>>>> 1) S3RestoreConfig2() - S3Resume <-> SmmCpu (DXE mode);
>>>>>>> 2) S3ResumeExecuteBootScript() - S3Resume <-> BootScriptExecutor
>>>>>>> (DXE
>>>>>>> mode)
>>>>>>> 3) S3ResumeBootOs() - S3Resume -> OS WakingVector (OS decide).
>>>>>>
>>>>>> In practice at least, these problems appear specific to SMM / SMRAM
>>>>>> usage. When we use OVMF's custom (insecure) LockBoxLib instance, the
>>>>>> X64 build of S3Resume2Pei (actually, a fully X64 build of OVMF)
>>>>>> provides a working S3 feature, including Windows 7 and later guests,
>>>>>> and Linux guests. Even a minimal boot script is executed correctly
>>>>>> (it has just an INFO opcode).
>>>>>>
>>>>>> If I remember correctly, quite a few code paths are possible through
>>>>>> S3Resume2Pei. I don't exactly recall which one is taken in the above
>>>>>> case, but I thought I'd point out that it works very well in practice.
>>>>>> (The fact notwithstanding that the lockbox is not protected from the
>>>>>> runtime guest OS.)
>>>>>>
>>>>>> The pure Ia32 case works well both with and without OVMF's SMM
>> feature.
>>>>>>
>>>>>> I don't recall ever testing S3 with the Ia32X64 build; I plan to do
>>>>>> that soonish.
>>>>>
>>>>> Ia32X64 crashes (with SMM enabled) with the following messages leading
>> up to it:
>>>>>
>>>>> --------
>>>>> SmmLockBoxPeiLib RestoreAllLockBoxInPlace - Exit (Success)
>> S3NvsPageTableAddress - 7DFDE000 (1)
>>>>> SMM S3 Signature                = 534D4D53
>>>>> SMM S3 Stack Base               = 7FF8A000
>>>>> SMM S3 Stack Size               = 8000
>>>>> SMM S3 Resume Entry Point       = 7FFB5617
>>>>> SMM S3 CR0                      = 80000033
>>>>> SMM S3 CR3                      = 7FF84000
>>>>> SMM S3 CR4                      = 668
>>>>> SMM S3 Return CS                = 10
>>>>> SMM S3 Return Entry Point       = 846C69
>>>>> SMM S3 Return Context1          = 7F6FA000
>>>>> SMM S3 Return Context2          = 7E039000
>>>>> SMM S3 Return Stack Pointer     = 81730C
>>>>> SMM S3 Smst                     = 7FFFDE00
>>>>> SmmRestoreCpu()
>>>>> <CRASH>
>>>>> --------
>>>>>
>>>>> If I build without SMM, then Ia32X64 works fine as well.
>>>>>
>>>>> Summary:
>>>>> - without SMM: S3 works in all three of the Ia32, Ia32X64, and X64
>>>>>   OVMF builds
>>>>> - with SMM: Ia32 works, the other two crash.
>>>>>
>>>>> I guess this just confirms what you've already determined from the code.
>>>>> But, at least, it confirms it. :)
>>>>>
>>>>> Thank you all for looking into it!
>>>>> Laszlo
>>>>>
>>>>>
>>>>>>
>>>>>> Thanks,
>>>>>> Laszlo
>>>>>>
>>>>>>> Thank you
>>>>>>> Yao Jiewen
>>>>>>>
>>>>>>> -----Original Message-----
>>>>>>> From: Laszlo Ersek [mailto:[email protected]]
>>>>>>> Sent: Thursday, October 29, 2015 1:34 AM
>>>>>>> To: Kinney, Michael D; Fan, Jeff; Yao, Jiewen
>>>>>>> Cc: edk2-devel-01
>>>>>>> Subject: Re: about the SMM_S3_RESUME_SMM_64 branch in
>> S3Resume2Pei
>>>>>>>
>>>>>>> On 10/28/15 17:54, Kinney, Michael D wrote:
>>>>>>>> Laszlo,
>>>>>>>>
>>>>>>>> I do not believe any X64 PEI testing has not been performed with this
>> module.  We will investigate a fix.
>>>>>>>
>>>>>>> Thank you.
>>>>>>>
>>>>>>> In any case, in OVMF we might be able to use this module nonetheless,
>> with the OvmfPkgIa32X64.dsc build (== 32-bit PEI, 64-bit DXE).
>>>>>>>
>>>>>>> Thanks!
>>>>>>> Laszlo
>>>>>>>
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>>
>>>>>>>> Mike
>>>>>>>>
>>>>>>>>> -----Original Message-----
>>>>>>>>> From: Laszlo Ersek [mailto:[email protected]]
>>>>>>>>> Sent: Wednesday, October 28, 2015 8:57 AM
>>>>>>>>> To: Fan, Jeff; Yao, Jiewen
>>>>>>>>> Cc: edk2-devel-01; Kinney, Michael D
>>>>>>>>> Subject: about the SMM_S3_RESUME_SMM_64 branch in
>> S3Resume2Pei
>>>>>>>>>
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> I have a question about the following code in
>>>>>>>>> "UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c", function
>>>>>>>>> S3RestoreConfig2():
>>>>>>>>>
>>>>>>>>>>     if (SmmS3ResumeState->Signature ==
>> SMM_S3_RESUME_SMM_64) {
>>>>>>>>>>       //
>>>>>>>>>>       // Switch to long mode to complete resume.
>>>>>>>>>>       //
>>>>>>>>>>
>>>>>>>>>>       InterruptStatus = SaveAndDisableInterrupts ();
>>>>>>>>>>       //
>>>>>>>>>>       // Need to make sure the GDT is loaded with values that
>>>>>>>>>> support long
>>>>>>>>> mode and real mode.
>>>>>>>>>>       //
>>>>>>>>>>       AsmWriteGdtr (&mGdt);
>>>>>>>>>>       //
>>>>>>>>>>       // update segment selectors per the new GDT.
>>>>>>>>>>       //
>>>>>>>>>>       AsmSetDataSelectors (DATA_SEGEMENT_SELECTOR);
>>>>>>>>>>       //
>>>>>>>>>>       // Restore interrupt state.
>>>>>>>>>>       //
>>>>>>>>>>       SetInterruptState (InterruptStatus);
>>>>>>>>>>
>>>>>>>>>>       AsmWriteCr3 ((UINTN)SmmS3ResumeState->SmmS3Cr3);
>>>>>>>>>>
>>>>>>>>>>       //
>>>>>>>>>>       // Disable interrupt of Debug timer, since IDT table
>>>>>>>>>> cannot work in long
>>>>>>>>> mode.
>>>>>>>>>>       // NOTE: On x64 platforms, because DisablePaging64() will
>>>>>>>>>> disable
>>>>>>>>> interrupts,
>>>>>>>>>>       // the code in S3ResumeExecuteBootScript() cannot be
>>>>>>>>>> halted by soft
>>>>>>>>> debugger.
>>>>>>>>>>       //
>>>>>>>>>>       SaveAndSetDebugTimerInterrupt (FALSE);
>>>>>>>>>>
>>>>>>>>>>       AsmEnablePaging64 (
>>>>>>>>>>         0x38,
>>>>>>>>>>         SmmS3ResumeState->SmmS3ResumeEntryPoint,
>>>>>>>>>>         (UINT64)(UINTN)AcpiS3Context,
>>>>>>>>>>         0,
>>>>>>>>>>         SmmS3ResumeState->SmmS3StackBase + SmmS3ResumeState-
>>>>>>>>>> SmmS3StackSize
>>>>>>>>>>         );
>>>>>>>>>>     }
>>>>>>>>>
>>>>>>>>> At the end of this block, the AsmEnablePaging64() function is called.
>>>>>>>>> That call results in the following call tree, *if* the module was 
>>>>>>>>> built
>> for X64:
>>>>>>>>>
>>>>>>>>> AsmEnablePaging64()
>> [MdePkg/Library/BaseLib/X86EnablePaging64.c]
>>>>>>>>>  InternalX86EnablePaging64() [MdePkg/Library/BaseLib/X64/Non-
>> existing.c]
>>>>>>>>>    ASSERT (FALSE)
>>>>>>>>>
>>>>>>>>> This is because the InternalX86EnablePaging64() functionality is
>>>>>>>>> unavailable in BaseLib on X64.
>>>>>>>>>
>>>>>>>>> My question: how is this branch in S3RestoreConfig2() supposed to
>>>>>>>>> work *at
>>>>>>>>> all* in an X64 PEI build?
>>>>>>>>>
>>>>>>>>> Thank you,
>>>>>>>>> Laszlo
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>> _______________________________________________
>>> 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