| ## @file | |
| # This is the assembly code for transferring to control to OS S3 waking vector | |
| # for X64 platform | |
| # | |
| # Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR> | |
| # | |
| # This program and the accompanying materials 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 | |
| # http://opensource.org/licenses/bsd-license.php | |
| # | |
| # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| # | |
| ## | |
| 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 | |
| _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 | |
| ASM_GLOBAL ASM_PFX(AsmTransferControl32) | |
| ASM_PFX(AsmTransferControl32): | |
| # S3WakingVector :DWORD | |
| # AcpiLowMemoryBase :DWORD | |
| pushq %rbp | |
| movl %esp,%ebp | |
| .byte 0x8d, 0x05 # lea eax, AsmTransferControl16 | |
| ASM_GLOBAL ASM_PFX(AsmFixAddress16) | |
| ASM_PFX(AsmFixAddress16): | |
| .long 0 | |
| pushq $0x28 # CS | |
| pushq %rax | |
| lret | |
| ASM_GLOBAL ASM_PFX(AsmTransferControl16) | |
| ASM_PFX(AsmTransferControl16): | |
| .byte 0xb8,0x30,0 # mov ax, 30h as selector | |
| movw %ax,%ds | |
| movw %ax,%es | |
| movw %ax,%fs | |
| movw %ax,%gs | |
| movw %ax,%ss | |
| movq %cr0, %rax # Get control register 0 | |
| .byte 0x66 | |
| .byte 0x83,0xe0,0xfe # and eax, 0fffffffeh ; Clear PE bit (bit #0) | |
| .byte 0xf,0x22,0xc0 # mov cr0, eax ; Activate real mode | |
| .byte 0xea # jmp far AsmJmpAddr32 | |
| ASM_GLOBAL ASM_PFX(AsmJmpAddr32) | |
| ASM_PFX(AsmJmpAddr32): | |
| .long 0 | |
| ASM_GLOBAL ASM_PFX(PageFaultHandlerHook) | |
| ASM_PFX(PageFaultHandlerHook): | |
| pushq %rax # save all volatile registers | |
| pushq %rcx | |
| pushq %rdx | |
| pushq %r8 | |
| pushq %r9 | |
| pushq %r10 | |
| pushq %r11 | |
| # save volatile fp registers | |
| addq $-0x68, %rsp | |
| stmxcsr 0x60(%rsp) | |
| movdqa %xmm0, 0x0(%rsp) | |
| movdqa %xmm1, 0x10(%rsp) | |
| movdqa %xmm2, 0x20(%rsp) | |
| movdqa %xmm3, 0x30(%rsp) | |
| movdqa %xmm4, 0x40(%rsp) | |
| movdqa %xmm5, 0x50(%rsp) | |
| addq $-0x20, %rsp | |
| call ASM_PFX(PageFaultHandler) | |
| addq $0x20, %rsp | |
| # load volatile fp registers | |
| ldmxcsr 0x60(%rsp) | |
| movdqa 0x0(%rsp), %xmm0 | |
| movdqa 0x10(%rsp), %xmm1 | |
| movdqa 0x20(%rsp), %xmm2 | |
| movdqa 0x30(%rsp), %xmm3 | |
| movdqa 0x40(%rsp), %xmm4 | |
| movdqa 0x50(%rsp), %xmm5 | |
| addq $0x68, %rsp | |
| testb %al, %al | |
| popq %r11 | |
| popq %r10 | |
| popq %r9 | |
| popq %r8 | |
| popq %rdx | |
| popq %rcx | |
| popq %rax # restore all volatile registers | |
| jnz L1 | |
| jmpq *ASM_PFX(mOriginalHandler)(%rip) | |
| L1: | |
| addq $0x08, %rsp # skip error code for PF | |
| iretq |