1## @file
2#   This is the assembly code for page fault handler hook.
3#
4# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5#
6# This program and the accompanying materials are
7# licensed and made available under the terms and conditions of the BSD License
8# which accompanies this distribution.  The full text of the license may be found at
9# http://opensource.org/licenses/bsd-license.php
10#
11# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13#
14##
15
16ASM_GLOBAL ASM_PFX(PageFaultHandlerHook)
17ASM_PFX(PageFaultHandlerHook):
18    addq     $-0x10, %rsp
19    # save rax
20    movq     %rax, 0x08(%rsp)
21
22    # pushq    %rax                         # save all volatile registers
23    pushq    %rcx
24    pushq    %rdx
25    pushq    %r8
26    pushq    %r9
27    pushq    %r10
28    pushq    %r11
29    # save volatile fp registers
30    # 68h + 08h(for alignment)
31    addq     $-0x70, %rsp
32    stmxcsr  0x60(%rsp)
33    movdqa   %xmm0, 0x0(%rsp)
34    movdqa   %xmm1, 0x10(%rsp)
35    movdqa   %xmm2, 0x20(%rsp)
36    movdqa   %xmm3, 0x30(%rsp)
37    movdqa   %xmm4, 0x40(%rsp)
38    movdqa   %xmm5, 0x50(%rsp)
39
40    addq     $-0x20, %rsp
41    call     ASM_PFX(PageFaultHandler)
42    addq     $0x20, %rsp
43
44    # load volatile fp registers
45    ldmxcsr  0x60(%rsp)
46    movdqa   0x0(%rsp), %xmm0
47    movdqa   0x10(%rsp), %xmm1
48    movdqa   0x20(%rsp), %xmm2
49    movdqa   0x30(%rsp), %xmm3
50    movdqa   0x40(%rsp), %xmm4
51    movdqa   0x50(%rsp), %xmm5
52    addq     $0x70, %rsp
53
54    popq     %r11
55    popq     %r10
56    popq     %r9
57    popq     %r8
58    popq     %rdx
59    popq     %rcx
60    # popq     %rax                         # restore all volatile registers
61
62    addq     $0x10, %rsp
63
64    # rax returned from PageFaultHandler is NULL or OriginalHandler address
65    # NULL if the page fault is handled by PageFaultHandler
66    # OriginalHandler address if the page fault is not handled by PageFaultHandler
67    testq    %rax, %rax
68
69    # save OriginalHandler address
70    movq     %rax, -0x10(%rsp)
71    # restore rax
72    movq     -0x08(%rsp), %rax
73
74    jz       L1
75
76    # jump to OriginalHandler
77    jmpq     *-0x10(%rsp)
78
79L1:
80    addq     $0x08, %rsp                  # skip error code for PF
81    iretq
82