xref: /aosp_15_r20/trusty/kernel/lib/syscall/arch/x86/64/syscall.S (revision 344aa361028b423587d4ef3fa52a23d194628137)
1/*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24#include <asm.h>
25
26#define SYSCALL_ENTRY_SIZE    0x08
27#define SYSCALL_STACK_OFF     0x08
28
29/*
30 * Entry state:
31 * %rax: syscall number set by syscall stub
32 * %rdi: 1st argument
33 * %rsi: 2nd argument
34 * %rdx: 3rd argument
35 * %rcx: return address saved by syscall instructions (4th argument in ABI)
36 * %r8: 5th argument (unused?)
37 * %r9: 6th argument (unused?)
38 * %r10: 4th argument copied from %rcx by syscall stub
39 * %r11: flags saved by syscall instructions
40 * %rsp: user-space stack (ignored)
41 * %r15: user-space stack saved by stub
42 */
43FUNCTION (x86_syscall)
44    /* clear user-space controlled stack pointer */
45    xor %esp, %esp
46
47    /* switch to kernel gs */
48    swapgs
49    movq  %gs:SYSCALL_STACK_OFF, %rsp
50
51    sti
52    pushq %rcx /* Ring 3 return address */
53    pushq %r15 /* Ring 3 RSP */
54    movq  %r10, %rcx
55
56    pushq %r11 /* saved flags */
57    subq  $0x8, %rsp /* align stack */
58
59    /* Check if syscall index (%rax) is in range */
60    cmp $nr_syscalls, %rax
61    jae .Lundefined_syscall
62
63    /* Load entry from syscall table */
64    movq syscall_table(,%rax,SYSCALL_ENTRY_SIZE), %rax
65
66    /* Check if syscall entry is NULL */
67    test %rax, %rax
68    jz .Lundefined_syscall
69
70    /* Call syscall handler now in %rax */
71.Lsyscall_addr_ready:
72    call *%rax
73
74    /*
75     * Clear non-callee saved registers to avoid leaking kernel data to
76     * user-space.
77     * Skip floating/vector registers since the kernel is not allowed to use
78     * them.
79     * Skip 4th argument (%rcx) and %r11 since they get overwritten with
80     * user-space pointers or flags below.
81     */
82    xor %edi, %edi /* clear 1st argument/temporary register */
83    xor %esi, %esi /* clear 2nd argument/temporary register */
84    xor %edx, %edx /* clear 3rd argument/temporary register */
85    xor %r8d, %r8d /* clear 5th argument/temporary register */
86    xor %r9d, %r9d /* clear 6th argument/temporary register */
87    xor %r10d, %r10d /* clear temporary register */
88
89    addq  $0x8, %rsp /* remove stack alignment padding */
90    popq %r11 /* saved flags */
91    popq %r15 /* pop RSP */
92    popq %rcx /* pop RIP */
93
94    /*
95     * switch to user gs
96     * Have to make sure there is no interrupt triggered between swapgs and sysexit instructions,
97     * if this happens, GS.base is switch to user level GS.base, but current context is still in
98     * kernel level, it leads to get global states failure on current processor.
99     */
100    cli
101    swapgs
102
103    /*
104     * Clear kernel stack pointer to avoid leaking ASLR info. We don't restore
105     * the user-space stack pointer here, since sysret can trigger a fault and
106     * we don't want that fault handler to use a user-space controlled stack
107     * pointer. A 0 stack pointer will trigger a double fault instead.
108     */
109    xor %esp, %esp
110
111    /*
112     * Exit state:
113     * %rax: return code
114     * %rcx: return address used by sysret instruction
115     * %r11: saved flags used by sysret instruction
116     * %r15: user-space stack used by stub
117     */
118    sysretq
119
120    /*
121     * Use sys_undefined as the syscall handler if the index in %rax is out of
122     * range of the syscall table or if %rax is in range, but the entry in the
123     * syscall table is NULL.
124     */
125.Lundefined_syscall:
126    movq $sys_undefined, %rax
127    jmp .Lsyscall_addr_ready
128