Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  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
 36SYM_CODE_START_NOALIGN(asm_fred_entrypoint_user)
 37	FRED_ENTER
 38	call	fred_entry_from_user
 39SYM_INNER_LABEL(asm_fred_exit_user, SYM_L_GLOBAL)
 40	FRED_EXIT
 411:	ERETU
 42
 43	_ASM_EXTABLE_TYPE(1b, asm_fred_entrypoint_user, EX_TYPE_ERETU)
 44SYM_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
 52SYM_CODE_START_NOALIGN(asm_fred_entrypoint_kernel)
 53	FRED_ENTER
 54	call	fred_entry_from_kernel
 55	FRED_EXIT
 56	ERETS
 57SYM_CODE_END(asm_fred_entrypoint_kernel)
 58
 59#if IS_ENABLED(CONFIG_KVM_INTEL)
 60SYM_FUNC_START(asm_fred_entry_from_kvm)
 61	push %rbp
 62	mov %rsp, %rbp
 63
 64	UNWIND_HINT_SAVE
 65
 66	/*
 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.
 72	 *
 73	 * Emulate the FRED-defined redzone and stack alignment.
 74	 */
 75	sub $(FRED_CONFIG_REDZONE_AMOUNT << 6), %rsp
 76	and $FRED_STACK_FRAME_RSP_MASK, %rsp
 77
 78	/*
 79	 * Start to push a FRED stack frame, which is always 64 bytes:
 80	 *
 81	 * +--------+-----------------+
 82	 * | Bytes  | Usage           |
 83	 * +--------+-----------------+
 84	 * | 63:56  | Reserved        |
 85	 * | 55:48  | Event Data      |
 86	 * | 47:40  | SS + Event Info |
 87	 * | 39:32  | RSP             |
 88	 * | 31:24  | RFLAGS          |
 89	 * | 23:16  | CS + Aux Info   |
 90	 * |  15:8  | RIP             |
 91	 * |   7:0  | Error Code      |
 92	 * +--------+-----------------+
 93	 */
 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 */
 97	push %rbp
 98	pushf
 99	mov $__KERNEL_CS, %rax
100	push %rax
101
102	/*
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.
107	 *
108	 * Use LEA to get the return RIP and push it, then push an error code.
109	 */
110	lea 1f(%rip), %rax
111	push %rax				/* Return RIP */
112	push $0					/* Error code, 0 for IRQ/NMI */
113
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 */
117	POP_REGS
118	ERETS
1191:
120	/*
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.
124	 */
125	UNWIND_HINT_RESTORE
126	pop %rbp
127	RET
128
129SYM_FUNC_END(asm_fred_entry_from_kvm)
130EXPORT_SYMBOL_GPL(asm_fred_entry_from_kvm);
131#endif