1 /* SPDX-License-Identifier: GPL-2.0 */
3 * The actual FRED entry points.
6 #include <linux/export.h>
10 #include <asm/segment.h>
15 .section .noinstr.text, "ax"
18 UNWIND_HINT_END_OF_STACK
21 movq %rsp, %rdi /* %rdi -> pt_regs */
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.
36 SYM_CODE_START_NOALIGN(asm_fred_entrypoint_user)
38 call fred_entry_from_user
39 SYM_INNER_LABEL(asm_fred_exit_user, SYM_L_GLOBAL)
43 _ASM_EXTABLE_TYPE(1b, asm_fred_entrypoint_user, EX_TYPE_ERETU)
44 SYM_CODE_END(asm_fred_entrypoint_user)
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.
51 .org asm_fred_entrypoint_user + 256, 0xcc
52 SYM_CODE_START_NOALIGN(asm_fred_entrypoint_kernel)
54 call fred_entry_from_kernel
57 SYM_CODE_END(asm_fred_entrypoint_kernel)
59 #if IS_ENABLED(CONFIG_KVM_INTEL)
60 SYM_FUNC_START(asm_fred_entry_from_kvm)
67 * Both IRQ and NMI from VMX can be handled on current task stack
68 * because there is no need to protect from reentrancy and the call
69 * stack leading to this helper is effectively constant and shallow
70 * (relatively speaking). Do the same when FRED is active, i.e., no
71 * need to check current stack level for a stack switch.
73 * Emulate the FRED-defined redzone and stack alignment.
75 sub $(FRED_CONFIG_REDZONE_AMOUNT << 6), %rsp
76 and $FRED_STACK_FRAME_RSP_MASK, %rsp
79 * Start to push a FRED stack frame, which is always 64 bytes:
81 * +--------+-----------------+
83 * +--------+-----------------+
84 * | 63:56 | Reserved |
85 * | 55:48 | Event Data |
86 * | 47:40 | SS + Event Info |
89 * | 23:16 | CS + Aux Info |
91 * | 7:0 | Error Code |
92 * +--------+-----------------+
94 push $0 /* Reserved, must be 0 */
95 push $0 /* Event data, 0 for IRQ/NMI */
96 push %rdi /* fred_ss handed in by the caller */
99 mov $__KERNEL_CS, %rax
103 * Unlike the IDT event delivery, FRED _always_ pushes an error code
104 * after pushing the return RIP, thus the CALL instruction CANNOT be
105 * used here to push the return RIP, otherwise there is no chance to
106 * push an error code before invoking the IRQ/NMI handler.
108 * Use LEA to get the return RIP and push it, then push an error code.
111 push %rax /* Return RIP */
112 push $0 /* Error code, 0 for IRQ/NMI */
114 PUSH_AND_CLEAR_REGS clear_bp=0 unwind_hint=0
115 movq %rsp, %rdi /* %rdi -> pt_regs */
116 call __fred_entry_from_kvm /* Call the C entry point */
121 * Objtool doesn't understand what ERETS does, this hint tells it that
122 * yes, we'll reach here and with what stack state. A save/restore pair
123 * isn't strictly needed, but it's the simplest form.
129 SYM_FUNC_END(asm_fred_entry_from_kvm)
130 EXPORT_SYMBOL_GPL(asm_fred_entry_from_kvm);