Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/entry/entry_64_fred.S
26439 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
/*
3
* The actual FRED entry points.
4
*/
5
6
#include <linux/export.h>
7
8
#include <asm/asm.h>
9
#include <asm/fred.h>
10
#include <asm/segment.h>
11
12
#include "calling.h"
13
14
.code64
15
.section .noinstr.text, "ax"
16
17
.macro FRED_ENTER
18
UNWIND_HINT_END_OF_STACK
19
ENDBR
20
PUSH_AND_CLEAR_REGS
21
movq %rsp, %rdi /* %rdi -> pt_regs */
22
.endm
23
24
.macro FRED_EXIT
25
UNWIND_HINT_REGS
26
POP_REGS
27
.endm
28
29
/*
30
* The new RIP value that FRED event delivery establishes is
31
* IA32_FRED_CONFIG & ~FFFH for events that occur in ring 3.
32
* Thus the FRED ring 3 entry point must be 4K page aligned.
33
*/
34
.align 4096
35
36
SYM_CODE_START_NOALIGN(asm_fred_entrypoint_user)
37
FRED_ENTER
38
call fred_entry_from_user
39
SYM_INNER_LABEL(asm_fred_exit_user, SYM_L_GLOBAL)
40
FRED_EXIT
41
1: ERETU
42
43
_ASM_EXTABLE_TYPE(1b, asm_fred_entrypoint_user, EX_TYPE_ERETU)
44
SYM_CODE_END(asm_fred_entrypoint_user)
45
46
/*
47
* The new RIP value that FRED event delivery establishes is
48
* (IA32_FRED_CONFIG & ~FFFH) + 256 for events that occur in
49
* ring 0, i.e., asm_fred_entrypoint_user + 256.
50
*/
51
.org asm_fred_entrypoint_user + 256, 0xcc
52
SYM_CODE_START_NOALIGN(asm_fred_entrypoint_kernel)
53
FRED_ENTER
54
call fred_entry_from_kernel
55
FRED_EXIT
56
ERETS
57
SYM_CODE_END(asm_fred_entrypoint_kernel)
58
59
#if IS_ENABLED(CONFIG_KVM_INTEL)
60
SYM_FUNC_START(asm_fred_entry_from_kvm)
61
ANNOTATE_NOENDBR
62
push %rbp
63
mov %rsp, %rbp
64
65
UNWIND_HINT_SAVE
66
67
/*
68
* Both IRQ and NMI from VMX can be handled on current task stack
69
* because there is no need to protect from reentrancy and the call
70
* stack leading to this helper is effectively constant and shallow
71
* (relatively speaking). Do the same when FRED is active, i.e., no
72
* need to check current stack level for a stack switch.
73
*
74
* Emulate the FRED-defined redzone and stack alignment.
75
*/
76
sub $(FRED_CONFIG_REDZONE_AMOUNT << 6), %rsp
77
and $FRED_STACK_FRAME_RSP_MASK, %rsp
78
79
/*
80
* Start to push a FRED stack frame, which is always 64 bytes:
81
*
82
* +--------+-----------------+
83
* | Bytes | Usage |
84
* +--------+-----------------+
85
* | 63:56 | Reserved |
86
* | 55:48 | Event Data |
87
* | 47:40 | SS + Event Info |
88
* | 39:32 | RSP |
89
* | 31:24 | RFLAGS |
90
* | 23:16 | CS + Aux Info |
91
* | 15:8 | RIP |
92
* | 7:0 | Error Code |
93
* +--------+-----------------+
94
*/
95
push $0 /* Reserved, must be 0 */
96
push $0 /* Event data, 0 for IRQ/NMI */
97
push %rdi /* fred_ss handed in by the caller */
98
push %rbp
99
pushf
100
mov $__KERNEL_CS, %rax
101
push %rax
102
103
/*
104
* Unlike the IDT event delivery, FRED _always_ pushes an error code
105
* after pushing the return RIP, thus the CALL instruction CANNOT be
106
* used here to push the return RIP, otherwise there is no chance to
107
* push an error code before invoking the IRQ/NMI handler.
108
*
109
* Use LEA to get the return RIP and push it, then push an error code.
110
*/
111
lea 1f(%rip), %rax
112
push %rax /* Return RIP */
113
push $0 /* Error code, 0 for IRQ/NMI */
114
115
PUSH_AND_CLEAR_REGS clear_bp=0 unwind_hint=0
116
movq %rsp, %rdi /* %rdi -> pt_regs */
117
call __fred_entry_from_kvm /* Call the C entry point */
118
POP_REGS
119
ERETS
120
1:
121
/*
122
* Objtool doesn't understand what ERETS does, this hint tells it that
123
* yes, we'll reach here and with what stack state. A save/restore pair
124
* isn't strictly needed, but it's the simplest form.
125
*/
126
UNWIND_HINT_RESTORE
127
pop %rbp
128
RET
129
130
SYM_FUNC_END(asm_fred_entry_from_kvm)
131
EXPORT_SYMBOL_GPL(asm_fred_entry_from_kvm);
132
#endif
133
134