Hi Laszlo Thanks for the investigation. Maybe I am wrong, but I would like to point out this piece of code works fine on IA real platform. We also have other piece of code to jump from 64bit to 16bit directly, which works fine also.
I just checked IA32 manual, for far return, detail below: (error handling are removed) Would you please help to check if the emulator follow IA32 manual to do the mode switch? =================================== (* IA-32e Mode *) IF (PE = 1 and VM = 0 and IA32_EFER.LMA = 1) and instruction = far return GOTO IA-32E-MODE-RETURN-SAME-PRIVILEGE-LEVEL IA-32E-MODE-RETURN-SAME-PRIVILEGE-LEVEL: IF OperandSize = 32 THEN EIP <- Pop(); CS <- Pop(); (* 32-bit pop, high-order 16 bits discarded *) ELSE IF OperandSize = 16 THEN EIP <- Pop(); EIP <- EIP AND 0000FFFFH; CS <- Pop(); (* 16-bit pop *) ELSE (* OperandSize = 64 *) RIP <- Pop(); CS <- Pop(); (* 64-bit pop, high-order 48 bits discarded *) FI; FI; IF instruction has immediate operand THEN (* Release parameters from stack *) IF StackAddressSize = 32 THEN ESP <- ESP + SRC; ELSE IF StackAddressSize = 16 THEN SP <- SP + SRC; ELSE (* StackAddressSize = 64 *) RSP <- RSP + SRC; FI; FI; FI; =================================== -----Original Message----- From: Laszlo Ersek [mailto:ler...@redhat.com] Sent: Thursday, December 05, 2013 5:47 AM To: edk2-devel@lists.sourceforge.net Cc: Yao, Jiewen Subject: Re: [edk2] please clarify "PcdDxeIplSwitchToLongMode" On 12/04/13 06:46, Laszlo Ersek wrote: >>> OVMF S3 resume [...] The place where it unexpectedly reboots now is >>> the following sequence (from >>> MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.S): >>> >>> ASM_GLOBAL ASM_PFX(AsmTransferControl) >>> ASM_PFX(AsmTransferControl): >>> # rcx S3WakingVector :DWORD >>> # rdx AcpiLowMemoryBase :DWORD >>> lea _AsmTransferControl_al_0000(%rip), %eax >>> movq $0x2800000000, %r8 >>> orq %r8, %rax >>> pushq %rax >>> shrd $20, %ecx, %ebx >>> andl $0x0f, %ecx >>> movw %cx, %bx >>> movl %ebx, jmp_addr(%rip) >>> lret <-------------- here >>> _AsmTransferControl_al_0000: >>> .byte 0x0b8, 0x30, 0 # mov ax, 30h as selector >>> movl %eax, %ds >>> movl %eax, %es >>> movl %eax, %fs >>> movl %eax, %gs >>> movl %eax, %ss >>> movq %cr0, %rax >>> movq %cr4, %rbx >>> .byte 0x66 >>> andl $0x7ffffffe, %eax >>> andb $0xdf, %bl >>> movq %rax, %cr0 >>> .byte 0x66 >>> movl $0x0c0000080, %ecx >>> rdmsr >>> andb $0xfe, %ah >>> wrmsr >>> movq %rbx, %cr4 >>> .byte 0x0ea # jmp far jmp_addr >>> jmp_addr: >>> .long 0 >>> >>> The idea is to simply follow through AsmTransferControl_al_0000, but >>> flip CS to 0x28 at that point. [...] >>> The GDT entry at/for 0x28 is >>> >>> UINT32 LimitLow : 16 == 0xFFFF >>> UINT32 BaseLow : 16 == 0 >>> UINT32 BaseMid : 8 == 0 >>> UINT32 Type : 4 == 0xB /* = Code, Execute/Read, accessed */ >>> UINT32 System : 1 == 1 /* = code or data */ >>> UINT32 Dpl : 2 == 0 >>> UINT32 Present : 1 == 1 >>> UINT32 LimitHigh : 4 == 0xF >>> UINT32 Software : 1 == 0 /* this bit is freely usable */ >>> UINT32 Reserved : 1 == 0 /* = exec'd in compat (32bit) mode */ >>> UINT32 DefaultSize : 1 == 0 /* = 16-bit def. addr & op size */ >>> UINT32 Granularity : 1 == 1 /* = limit in 4KB units */ >>> UINT32 BaseHigh : 8 == 0 > > (note: the GDT entries are in > "UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c") The problem is the DefaultSize flag (== 0 in the above descriptor). The descriptor at 0x10 only differs in the DefaultSize bit (== 1 in there), and the lret instruction works with that as expected. When the lret is executed, the processor is still in IA-32e mode and apparently doesn't accept a code segment where the default address and operand size is 16-bit. We probably need to clear only the L flag at first (64-bit code segment, called "Reserved" above), by selecting the 0x10 descriptor. Then, in 32-bit code, bring the CPU out of IA-32e (the assembly in the rest of AsmTransferControl seems to aim at that), and then we can probably select the 0x28 descriptor, changing the default operand/address size to 16 bits. I guess. Laszlo ------------------------------------------------------------------------------ Sponsored by Intel(R) XDK Develop, test and display web and hybrid apps with a single code base. Download it for free now! http://pubads.g.doubleclick.net/gampad/clk?id=111408631&iu=/4140/ostg.clktrk _______________________________________________ edk2-devel mailing list edk2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/edk2-devel