Save segment registers on stack in case the thunk code assembly calls CF9 soft reset and the x64 registers get cleared.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8124 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
qhuang8 2009-04-17 07:47:08 +00:00
parent 0fe43214e3
commit 1e4371671b
2 changed files with 73 additions and 52 deletions

View File

@ -1,6 +1,6 @@
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# #
# Copyright (c) 2006 - 2008, Intel Corporation # Copyright (c) 2006 - 2009, Intel Corporation
# All rights reserved. This program and the accompanying materials # All rights reserved. This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License # are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at # which accompanies this distribution. The full text of the license may be found at
@ -18,6 +18,7 @@
# Real mode thunk # Real mode thunk
# #
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
#include <EdkIIGlueBase.h> #include <EdkIIGlueBase.h>
.globl ASM_PFX(m16Start) .globl ASM_PFX(m16Start)
@ -51,7 +52,7 @@
ASM_PFX(m16Size): .word ASM_PFX(InternalAsmThunk16) - ASM_PFX(m16Start) ASM_PFX(m16Size): .word ASM_PFX(InternalAsmThunk16) - ASM_PFX(m16Start)
ASM_PFX(mThunk16Attr): .word _ThunkAttr - ASM_PFX(m16Start) ASM_PFX(mThunk16Attr): .word _ThunkAttr - ASM_PFX(m16Start)
ASM_PFX(m16Gdt): .word _NullSeg - ASM_PFX(m16Start) ASM_PFX(m16Gdt): .word ASM_PFX(NullSeg) - ASM_PFX(m16Start)
ASM_PFX(m16GdtrBase): .word _16GdtrBase - ASM_PFX(m16Start) ASM_PFX(m16GdtrBase): .word _16GdtrBase - ASM_PFX(m16Start)
ASM_PFX(mTransition): .word _EntryPoint - ASM_PFX(m16Start) ASM_PFX(mTransition): .word _EntryPoint - ASM_PFX(m16Start)
@ -78,8 +79,8 @@ ASM_PFX(BackFromUserCode):
.byte 0x16 # push ss .byte 0x16 # push ss
.byte 0xe # push cs .byte 0xe # push cs
.byte 0x66 .byte 0x66
call @Base # push eip call L_Base # push eip
@Base: L_Base:
.byte 0x66 .byte 0x66
pushq $0 # reserved high order 32 bits of EFlags pushq $0 # reserved high order 32 bits of EFlags
.byte 0x66, 0x9c # pushfd actually .byte 0x66, 0x9c # pushfd actually
@ -92,17 +93,17 @@ ASM_PFX(BackFromUserCode):
.byte 0x66,0xba # mov edx, imm32 .byte 0x66,0xba # mov edx, imm32
_ThunkAttr: .space 4 _ThunkAttr: .space 4
testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15, %dl testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15, %dl
jz @1 jz L_1
movl $0x15cd2401,%eax # mov ax, 2401h & int 15h movl $0x15cd2401,%eax # mov ax, 2401h & int 15h
cli # disable interrupts cli # disable interrupts
jnc @2 jnc L_2
@1: L_1:
testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL, %dl testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL, %dl
jz @2 jz L_2
inb $0x92,%al inb $0x92,%al
orb $2,%al orb $2,%al
outb %al, $0x92 # deactivate A20M# outb %al, $0x92 # deactivate A20M#
@2: L_2:
movl %ss,%eax movl %ss,%eax
lea IA32_REGS_SIZE(%esp), %bp lea IA32_REGS_SIZE(%esp), %bp
# #
@ -115,9 +116,9 @@ _ThunkAttr: .space 4
addw %ax,%bp # add ebp, eax addw %ax,%bp # add ebp, eax
movw %cs,%ax movw %cs,%ax
shlw $4,%ax shlw $4,%ax
lea (@64BitCode - @Base)(%ebx, %eax), %ax lea (L_64BitCode - L_Base)(%ebx, %eax), %ax
.byte 0x66,0x2e,0x89,0x87 # mov cs:[bx + (@64Eip - @Base)], eax .byte 0x66,0x2e,0x89,0x87 # mov cs:[bx + (L_64Eip - L_Base)], eax
.word @64Eip - @Base .word L_64Eip - L_Base
.byte 0x66,0xb8 # mov eax, imm32 .byte 0x66,0xb8 # mov eax, imm32
SavedCr4: .space 4 SavedCr4: .space 4
movq %rax, %cr4 movq %rax, %cr4
@ -125,7 +126,7 @@ SavedCr4: .space 4
# rdi in the instruction below is indeed bx in 16-bit code # rdi in the instruction below is indeed bx in 16-bit code
# #
.byte 0x66,0x2e # 2eh is "cs:" segment override .byte 0x66,0x2e # 2eh is "cs:" segment override
lgdt (SavedGdt - @Base)(%rdi) lgdt (SavedGdt - L_Base)(%rdi)
.byte 0x66 .byte 0x66
movl $0xc0000080,%ecx movl $0xc0000080,%ecx
rdmsr rdmsr
@ -134,17 +135,20 @@ SavedCr4: .space 4
.byte 0x66,0xb8 # mov eax, imm32 .byte 0x66,0xb8 # mov eax, imm32
SavedCr0: .space 4 SavedCr0: .space 4
movq %rax, %cr0 movq %rax, %cr0
.byte 0x66,0xea # jmp far cs:@64Bit .byte 0x66,0xea # jmp far cs:L_64Bit
@64Eip: .space 4 L_64Eip: .space 4
SavedCs: .space 2 SavedCs: .space 2
@64BitCode: L_64BitCode:
movq %r8, %rsp .byte 0x90
.byte 0x67,0xbc # mov esp, imm32
SavedSp: .space 4 # restore stack
nop
ret ret
_EntryPoint: .long ASM_PFX(ToUserCode) - ASM_PFX(m16Start) _EntryPoint: .long ASM_PFX(ToUserCode) - ASM_PFX(m16Start)
.word CODE16 .word CODE16
_16Gdtr: .word GDT_SIZE - 1 _16Gdtr: .word GDT_SIZE - 1
_16GdtrBase: .quad _NullSeg _16GdtrBase: .quad ASM_PFX(NullSeg)
_16Idtr: .word 0x3ff _16Idtr: .word 0x3ff
.long 0 .long 0
@ -169,16 +173,16 @@ ASM_PFX(ToUserCode):
movl %esi,%ss # set up 16-bit stack segment movl %esi,%ss # set up 16-bit stack segment
movw %bx,%sp # set up 16-bit stack pointer movw %bx,%sp # set up 16-bit stack pointer
.byte 0x66 # make the following call 32-bit .byte 0x66 # make the following call 32-bit
call @Base1 # push eip call L_Base1 # push eip
@Base1: L_Base1:
popw %bp # ebp <- address of @Base1 popw %bp # ebp <- address of L_Base1
pushq (IA32_REGS_SIZE + 2)(%esp) pushq (IA32_REGS_SIZE + 2)(%esp)
lea 0x0c(%rsi), %eax lea 0x0c(%rsi), %eax
pushq %rax pushq %rax
lret # execution begins at next instruction lret # execution begins at next instruction
@RealMode: L_RealMode:
.byte 0x66,0x2e # CS and operand size override .byte 0x66,0x2e # CS and operand size override
lidt (_16Idtr - @Base1)(%rsi) lidt (_16Idtr - L_Base1)(%rsi)
.byte 0x66,0x61 # popad .byte 0x66,0x61 # popad
.byte 0x1f # pop ds .byte 0x1f # pop ds
.byte 0x7 # pop es .byte 0x7 # pop es
@ -189,26 +193,26 @@ ASM_PFX(ToUserCode):
.byte 0x66 # make the following retf 32-bit .byte 0x66 # make the following retf 32-bit
lret # transfer control to user code lret # transfer control to user code
.equ CODE16, ASM_PFX(16Code) - . .equ CODE16, ASM_PFX(_16Code) - .
.equ DATA16, ASM_PFX(16Data) - . .equ DATA16, ASM_PFX(_16Data) - .
.equ DATA32, ASM_PFX(32Data) - . .equ DATA32, ASM_PFX(_32Data) - .
_NullSeg: .quad 0 ASM_PFX(NullSeg): .quad 0
ASM_PFX(16Code): ASM_PFX(_16Code):
.word -1 .word -1
.word 0 .word 0
.byte 0 .byte 0
.byte 0x9b .byte 0x9b
.byte 0x8f # 16-bit segment, 4GB limit .byte 0x8f # 16-bit segment, 4GB limit
.byte 0 .byte 0
ASM_PFX(16Data): ASM_PFX(_16Data):
.word -1 .word -1
.word 0 .word 0
.byte 0 .byte 0
.byte 0x93 .byte 0x93
.byte 0x8f # 16-bit segment, 4GB limit .byte 0x8f # 16-bit segment, 4GB limit
.byte 0 .byte 0
ASM_PFX(32Data): ASM_PFX(_32Data):
.word -1 .word -1
.word 0 .word 0
.byte 0 .byte 0
@ -226,7 +230,6 @@ ASM_PFX(32Data):
# IN OUT VOID *Transition # IN OUT VOID *Transition
# ); # );
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# MISMATCH: "InternalAsmThunk16 PROC USES rbp rbx rsi rdi"
.globl ASM_PFX(InternalAsmThunk16) .globl ASM_PFX(InternalAsmThunk16)
ASM_PFX(InternalAsmThunk16): ASM_PFX(InternalAsmThunk16):
@ -235,9 +238,13 @@ ASM_PFX(InternalAsmThunk16):
pushq %rsi pushq %rsi
pushq %rdi pushq %rdi
movl %ds, %r10d # r9 ~ r11 are not accessible in 16-bit movq %ds, %rbx
movl %es, %r11d # so use them for saving seg registers pushq %rbx # Save ds segment register on the stack
movl %ss, %r9d movq %es, %rbx
pushq %rbx # Save es segment register on the stack
movq %ss, %rbx
pushq %rbx # Save ss segment register on the stack
.byte 0x0f, 0xa0 #push fs .byte 0x0f, 0xa0 #push fs
.byte 0x0f, 0xa8 #push gs .byte 0x0f, 0xa8 #push gs
movq %rcx, %rsi movq %rcx, %rsi
@ -258,7 +265,7 @@ ASM_PFX(InternalAsmThunk16):
lea (_BackFromUserCode - ASM_PFX(m16Start))(%rdx), %ax lea (_BackFromUserCode - ASM_PFX(m16Start))(%rdx), %ax
stosl # [edi] <- return address of user code stosl # [edi] <- return address of user code
sgdt (SavedGdt - SavedCr4)(%rcx) sgdt (SavedGdt - SavedCr4)(%rcx)
sidt 0x38(%rsp) sidt 0x50(%rsp)
movq %cr0, %rax movq %cr0, %rax
movl %eax, (SavedCr0 - SavedCr4)(%rcx) movl %eax, (SavedCr0 - SavedCr4)(%rcx)
andl $0x7ffffffe,%eax # clear PE, PG bits andl $0x7ffffffe,%eax # clear PE, PG bits
@ -272,22 +279,26 @@ ASM_PFX(InternalAsmThunk16):
movl %edx,%ss movl %edx,%ss
pushfq pushfq
lea -8(%rdx), %edx lea -8(%rdx), %edx
lea @RetFromRealMode, %r8 lea L_RetFromRealMode, %r8
pushq %r8 pushq %r8
movl %cs, %r8d movl %cs, %r8d
movw %r8w, (SavedCs - SavedCr4)(%rcx) movw %r8w, (SavedCs - SavedCr4)(%rcx)
movq %rsp, %r8 movl %esp, (SavedSp - SavedCr4)(%rcx)
.byte 0xff, 0x69 # jmp (_EntryPoint - SavedCr4)(%rcx) .byte 0xff, 0x69 # jmp (_EntryPoint - SavedCr4)(%rcx)
.byte _EntryPoint - SavedCr4 .byte _EntryPoint - SavedCr4
@RetFromRealMode: L_RetFromRealMode:
popfq popfq
lidt 0x38(%rsp) lidt 0x50(%rsp)
lea -IA32_REGS_SIZE(%rbp), %eax lea -IA32_REGS_SIZE(%rbp), %eax
.byte 0x0f, 0xa9 # pop gs .byte 0x0f, 0xa9 # pop gs
.byte 0x0f, 0xa1 # pop fs .byte 0x0f, 0xa1 # pop fs
movl %r9d, %ss
movl %r11d, %es popq %rbx
movl %r10d, %ds movq %rbx, %ss
popq %rbx
movq %rbx, %es
popq %rbx
movq %rbx, %ds
popq %rdi popq %rdi
popq %rsi popq %rsi

View File

@ -138,7 +138,10 @@ SavedCr0 DD ?
@64Eip DD ? @64Eip DD ?
SavedCs DW ? SavedCs DW ?
@64BitCode: @64BitCode:
mov rsp, r8 ; restore stack db 090h
db 067h, 0bch ; mov esp, imm32
SavedSp DD ? ; restore stack
nop
ret ret
_BackFromUserCode ENDP _BackFromUserCode ENDP
@ -228,9 +231,13 @@ GDT_SIZE = $ - _NullSeg
; ); ; );
;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------
InternalAsmThunk16 PROC USES rbp rbx rsi rdi InternalAsmThunk16 PROC USES rbp rbx rsi rdi
mov r10d, ds ; r9 ~ r11 are not accessible in 16-bit mov rbx, ds
mov r11d, es ; so use them for saving seg registers push rbx ; Save ds segment register on the stack
mov r9d, ss mov rbx, es
push rbx ; Save es segment register on the stack
mov rbx, ss
push rbx ; Save ss segment register on the stack
push fs push fs
push gs push gs
mov rsi, rcx mov rsi, rcx
@ -250,7 +257,7 @@ InternalAsmThunk16 PROC USES rbp rbx rsi rdi
lea ax, [rdx + (_BackFromUserCode - m16Start)] ; offset address lea ax, [rdx + (_BackFromUserCode - m16Start)] ; offset address
stosd ; [edi] <- return address of user code stosd ; [edi] <- return address of user code
sgdt fword ptr [rcx + (SavedGdt - SavedCr4)] sgdt fword ptr [rcx + (SavedGdt - SavedCr4)]
sidt fword ptr [rsp + 38h] ; save IDT stack in argument space sidt fword ptr [rsp + 50h] ; save IDT stack in argument space
mov rax, cr0 mov rax, cr0
mov [rcx + (SavedCr0 - SavedCr4)], eax mov [rcx + (SavedCr0 - SavedCr4)], eax
and eax, 7ffffffeh ; clear PE, PG bits and eax, 7ffffffeh ; clear PE, PG bits
@ -268,17 +275,20 @@ InternalAsmThunk16 PROC USES rbp rbx rsi rdi
push r8 push r8
mov r8d, cs mov r8d, cs
mov [rcx + (SavedCs - SavedCr4)], r8w mov [rcx + (SavedCs - SavedCr4)], r8w
mov r8, rsp mov [rcx + (SavedSp - SavedCr4)], esp
jmp fword ptr [rcx + (_EntryPoint - SavedCr4)] jmp fword ptr [rcx + (_EntryPoint - SavedCr4)]
@RetFromRealMode: @RetFromRealMode:
popfq popfq
lidt fword ptr [rsp + 38h] ; restore protected mode IDTR lidt fword ptr [rsp + 50h] ; restore protected mode IDTR
lea eax, [rbp - sizeof (IA32_REGS)] lea eax, [rbp - sizeof (IA32_REGS)]
pop gs pop gs
pop fs pop fs
mov ss, r9d pop rbx
mov es, r11d mov ss, rbx
mov ds, r10d pop rbx
mov es, rbx
pop rbx
mov ds, rbx
ret ret
InternalAsmThunk16 ENDP InternalAsmThunk16 ENDP