David: The patch is good. Reviewed-by: Liming Gao <liming....@intel.com>
Thanks Liming -----Original Message----- From: David Woodhouse [mailto:dw...@infradead.org] Sent: Thursday, December 12, 2013 1:27 AM To: Gao, Liming Cc: edk2-devel@lists.sourceforge.net Subject: [PATCH 2/2] MdePkg: First instruction after clearing CR0.PE must be a far jmp. The IA Software Developer's Manual Vol 3A ยง9.9.2 ("Switching Back to Real-Address Mode") sets out the procedure for switching back to 16-bit real mode. We violate this in numerous ways, not least of which is that the first instruction immediately after clearing the PE bit in the CR0 register must be a far JMP. We were doing a bunch of other stuff first, and then a far *RET* instead. That isn't good enough, and was actually causing issues on certain hardware. The other violations also want fixing, but in small incremental commits so that the sequence is fully bisectable. And this is the only one which was actually causing a *problem*. Tested on OVMF and Quark with GCC build; MASM version by manual inspection and comparison with the GCC-built version. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: David Woodhouse <david.woodho...@intel.com> --- MdePkg/Library/BaseLib/Ia32/Thunk16.S | 24 +++++++++----------- MdePkg/Library/BaseLib/Ia32/Thunk16.asm | 40 ++++++++++++++++++++------------- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/MdePkg/Library/BaseLib/Ia32/Thunk16.S b/MdePkg/Library/BaseLib/Ia32/Thunk16.S index 331ea16..185655e 100644 --- a/MdePkg/Library/BaseLib/Ia32/Thunk16.S +++ b/MdePkg/Library/BaseLib/Ia32/Thunk16.S @@ -113,22 +113,18 @@ ASM_PFX(ToUserCode): movw %cx, %es movw %cx, %fs movw %cx, %gs - movl %eax, %cr0 - movl %ebp, %cr4 # real mode starts at next instruction + movl %eax, %cr0 # real mode starts at next instruction + # which (per SDM) *must* be a far JMP. + ljmpw $0,$0 # will be filled in by InternalAsmThunk16 +L_Base: # to point here. + movl %ebp, %cr4 movw %si, %ss # set up 16-bit stack segment xchgl %ebx, %esp # set up 16-bit stack pointer - calll L_Base # push eip -L_Base: - popl %ebp # ebp <- offset L_Base - push (IA32_REGS_SIZE + 2)(%esp) - lea (L_RealMode - L_Base)(%bp), %ax - push %ax - lret -L_RealMode: - mov %dx, %cs:(SavedSs - L_Base)(%bp) - mov %ebx, %cs:(SavedEsp - L_Base)(%bp) - lidtl %cs:(_16Idtr - L_Base)(%bp) + movw IA32_REGS_SIZE(%esp), %bp # get BackToUserCode address from stack + mov %dx, %cs:(SavedSs - ASM_PFX(BackFromUserCode))(%bp) + mov %ebx, %cs:(SavedEsp - ASM_PFX(BackFromUserCode))(%bp) + lidtl %cs:(_16Idtr - ASM_PFX(BackFromUserCode))(%bp) popal pop %ds pop %es @@ -189,6 +185,8 @@ ASM_PFX(InternalAsmThunk16): lea (ASM_PFX(BackFromUserCode) - ASM_PFX(m16Start))(%ecx), %ecx movw %cx, %ax stosl # [edi] <- return address of user code + addl $(L_Base - ASM_PFX(BackFromUserCode)), %eax + movl %eax, (L_Base - SavedCr0 - 4)(%edx) sgdtl (SavedGdt - SavedCr0)(%edx) sidtl 0x24(%esp) movl %cr0, %eax diff --git a/MdePkg/Library/BaseLib/Ia32/Thunk16.asm b/MdePkg/Library/BaseLib/Ia32/Thunk16.asm index 3e84aed..08955d4 100644 --- a/MdePkg/Library/BaseLib/Ia32/Thunk16.asm +++ b/MdePkg/Library/BaseLib/Ia32/Thunk16.asm @@ -157,24 +157,30 @@ _ToUserCode PROC mov es, ecx mov fs, ecx mov gs, ecx - mov cr0, eax - mov cr4, ebp ; real mode starts at next instruction + mov cr0, eax ; real mode starts at next instruction + ; which (per SDM) *must* be a far JMP. + DB 0eah +_RealAddr DW 0,0 ; filled in by InternalAsmThunk16 + + mov cr4, ebp mov ss, esi ; set up 16-bit stack segment xchg sp, bx ; set up 16-bit stack pointer - DB 66h - call @Base ; push eip -@Base: - pop bp ; ebp <- address of @Base - DB 67h ; address size override - push [esp + sizeof (IA32_REGS) + 2] - lea eax, [esi + (@RealMode - @Base)] - push eax - retf -@RealMode: - mov cs:[esi + (SavedSs - @Base)], edx - mov cs:[esi + (SavedEsp - @Base)], bx - DB 66h - lidt fword ptr cs:[esi + (_16Idtr - @Base)] + +; mov bp, [esp + sizeof(IA32_REGS) + DB 67h + mov ebp, [esp + sizeof(IA32_REGS)] ; BackFromUserCode address from stack + +; mov cs:[bp + (SavedSs - _BackFromUserCode)], dx + mov cs:[esi + (SavedSs - _BackFromUserCode)], edx + +; mov cs:[bp + (SavedEsp - _BackFromUserCode)], ebx + DB 2eh, 66h, 89h, 9eh + DW SavedEsp - _BackFromUserCode + +; lidt cs:[bp + (_16Idtr - _BackFromUserCode)] + DB 2eh, 66h, 0fh, 01h, 9eh + DW _16Idtr - _BackFromUserCode + popaw ; popad actually pop ds pop es @@ -230,6 +236,8 @@ InternalAsmThunk16 PROC USES ebp ebx esi edi ds es fs gs lea ecx, [ecx + (_BackFromUserCode - m16Start)] mov ax, cx stosd ; [edi] <- return address of user code + add eax, _RealAddr + 4 - _BackFromUserCode + mov dword ptr [edx + (_RealAddr - SavedCr0)], eax sgdt fword ptr [edx + (SavedGdt - SavedCr0)] sidt fword ptr [esp + 36] ; save IDT stack in argument space mov eax, cr0 -- 1.8.3.1 -- David Woodhouse Open Source Technology Centre david.woodho...@intel.com Intel Corporation ------------------------------------------------------------------------------ Rapidly troubleshoot problems before they affect your business. Most IT organizations don't have a clear picture of how application performance affects their revenue. With AppDynamics, you get 100% visibility into your Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro! http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk _______________________________________________ edk2-devel mailing list edk2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/edk2-devel