/* SPDX-License-Identifier: GPL-2.0 */ /* * Asm versions of Xen pv-ops, suitable for direct use. * * We only bother with direct forms (ie, vcpu in percpu data) of the * operations here; the indirect forms are better handled in C.
*/
.pushsection .noinstr.text, "ax" /* * PV hypercall interface to the hypervisor. * * Called via inline asm(), so better preserve %rcx and %r11. * * Input: * %eax: hypercall number * %rdi, %rsi, %rdx, %r10, %r8: args 1..5 for the hypercall * Output: %rax
*/
SYM_FUNC_START(xen_hypercall_pv)
ANNOTATE_NOENDBR
push %rcx
push %r11
UNWIND_HINT_SAVE
syscall
UNWIND_HINT_RESTORE
pop %r11
pop %rcx
RET
SYM_FUNC_END(xen_hypercall_pv)
/* * Disabling events is simply a matter of making the event mask * non-zero.
*/
SYM_FUNC_START(xen_irq_disable_direct)
ENDBR
movb $1, PER_CPU_VAR(xen_vcpu_info + XEN_vcpu_info_mask)
RET
SYM_FUNC_END(xen_irq_disable_direct)
/* * Force an event check by making a hypercall, but preserve regs * before making the call.
*/
SYM_FUNC_START(check_events)
FRAME_BEGIN
push %rax
push %rcx
push %rdx
push %rsi
push %rdi
push %r8
push %r9
push %r10
push %r11
call xen_force_evtchn_callback
pop %r11
pop %r10
pop %r9
pop %r8
pop %rdi
pop %rsi
pop %rdx
pop %rcx
pop %rax
FRAME_END
RET
SYM_FUNC_END(check_events)
/* * Enable events. This clears the event mask and tests the pending * event status with one and operation. If there are pending events, * then enter the hypervisor to get them handled.
*/
SYM_FUNC_START(xen_irq_enable_direct)
ENDBR
FRAME_BEGIN /* Unmask events */
movb $0, PER_CPU_VAR(xen_vcpu_info + XEN_vcpu_info_mask)
/* * Preempt here doesn't matter because that will deal with any * pending interrupts. The pending check may end up being run * on the wrong CPU, but that doesn't hurt.
*/
/* Test for pending */
testb $0xff, PER_CPU_VAR(xen_vcpu_info + XEN_vcpu_info_pending)
jz 1f
call check_events
1:
FRAME_END
RET
SYM_FUNC_END(xen_irq_enable_direct)
/* * (xen_)save_fl is used to get the current interrupt enable status. * Callers expect the status to be in X86_EFLAGS_IF, and other bits * may be set in the return value. We take advantage of this by * making sure that X86_EFLAGS_IF has the right value (and other bits * in that byte are 0), but other bits in the return value are * undefined. We need to toggle the state of the bit, because Xen and * x86 use opposite senses (mask vs enable).
*/
SYM_FUNC_START(xen_save_fl_direct)
ENDBR
testb $0xff, PER_CPU_VAR(xen_vcpu_info + XEN_vcpu_info_mask)
setz %ah
addb %ah, %ah
RET
SYM_FUNC_END(xen_save_fl_direct)
.macro xen_pv_trap name
SYM_CODE_START(xen_\name)
UNWIND_HINT_ENTRY
ENDBR
pop %rcx
pop %r11
jmp \name
SYM_CODE_END(xen_\name)
_ASM_NOKPROBE(xen_\name)
.endm
/* * XEN pv doesn't use trampoline stack, PER_CPU_VAR(cpu_tss_rw + TSS_sp0) is * also the kernel stack. Reusing swapgs_restore_regs_and_return_to_usermode() * in XEN pv would cause %rsp to move up to the top of the kernel stack and * leave the IRET frame below %rsp, which is dangerous to be corrupted if #NMI * interrupts. And swapgs_restore_regs_and_return_to_usermode() pushing the IRET * frame at the same address is useless.
*/
SYM_CODE_START(xenpv_restore_regs_and_return_to_usermode)
UNWIND_HINT_REGS
POP_REGS
/* stackleak_erase() can work safely on the kernel stack. */
STACKLEAK_ERASE_NOCLOBBER
/* * Xen handles syscall callbacks much like ordinary exceptions, which * means we have: * - kernel gs * - kernel rsp * - an iret-like stack frame on the stack (including rcx and r11): * ss * rsp * rflags * cs * rip * r11 * rsp->rcx
*/
/* Normal 64-bit system call target */
SYM_CODE_START(xen_entry_SYSCALL_64)
UNWIND_HINT_ENTRY
ENDBR
popq %rcx
popq %r11
/* * Neither Xen nor the kernel really knows what the old SS and * CS were. The kernel expects __USER_DS and __USER_CS, so * report those values even though Xen will guess its own values.
*/
movq $__USER_DS, 4*8(%rsp)
movq $__USER_CS, 1*8(%rsp)
/* * Neither Xen nor the kernel really knows what the old SS and * CS were. The kernel expects __USER_DS and __USER32_CS, so * report those values even though Xen will guess its own values.
*/
movq $__USER_DS, 4*8(%rsp)
movq $__USER32_CS, 1*8(%rsp)
/* 32-bit compat sysenter target */
SYM_CODE_START(xen_entry_SYSENTER_compat)
UNWIND_HINT_ENTRY
ENDBR /* * NB: Xen is polite and clears TF from EFLAGS for us. This means * that we don't need to guard against single step exceptions here.
*/
popq %rcx
popq %r11
/* * Neither Xen nor the kernel really knows what the old SS and * CS were. The kernel expects __USER_DS and __USER32_CS, so * report those values even though Xen will guess its own values.
*/
movq $__USER_DS, 4*8(%rsp)
movq $__USER32_CS, 1*8(%rsp)
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.