/*1* Asm versions of Xen pv-ops, suitable for either direct use or2* inlining. The inline versions are the same as the direct-use3* versions, with the pre- and post-amble chopped off.4*5* This code is encoded for size rather than absolute efficiency, with6* a view to being able to inline as much as possible.7*8* We only bother with direct forms (ie, vcpu in pda) of the9* operations here; the indirect forms are better handled in C, since10* they're generally too large to inline anyway.11*/1213#include <asm/errno.h>14#include <asm/percpu.h>15#include <asm/processor-flags.h>16#include <asm/segment.h>1718#include <xen/interface/xen.h>1920#include "xen-asm.h"2122ENTRY(xen_adjust_exception_frame)23mov 8+0(%rsp), %rcx24mov 8+8(%rsp), %r1125ret $162627hypercall_iret = hypercall_page + __HYPERVISOR_iret * 3228/*29* Xen64 iret frame:30*31* ss32* rsp33* rflags34* cs35* rip <-- standard iret frame36*37* flags38*39* rcx }40* r11 }<-- pushed by hypercall page41* rsp->rax }42*/43ENTRY(xen_iret)44pushq $0451: jmp hypercall_iret46ENDPATCH(xen_iret)47RELOC(xen_iret, 1b+1)4849/*50* sysexit is not used for 64-bit processes, so it's only ever used to51* return to 32-bit compat userspace.52*/53ENTRY(xen_sysexit)54pushq $__USER32_DS55pushq %rcx56pushq $X86_EFLAGS_IF57pushq $__USER32_CS58pushq %rdx5960pushq $0611: jmp hypercall_iret62ENDPATCH(xen_sysexit)63RELOC(xen_sysexit, 1b+1)6465ENTRY(xen_sysret64)66/*67* We're already on the usermode stack at this point, but68* still with the kernel gs, so we can easily switch back69*/70movq %rsp, PER_CPU_VAR(old_rsp)71movq PER_CPU_VAR(kernel_stack), %rsp7273pushq $__USER_DS74pushq PER_CPU_VAR(old_rsp)75pushq %r1176pushq $__USER_CS77pushq %rcx7879pushq $VGCF_in_syscall801: jmp hypercall_iret81ENDPATCH(xen_sysret64)82RELOC(xen_sysret64, 1b+1)8384ENTRY(xen_sysret32)85/*86* We're already on the usermode stack at this point, but87* still with the kernel gs, so we can easily switch back88*/89movq %rsp, PER_CPU_VAR(old_rsp)90movq PER_CPU_VAR(kernel_stack), %rsp9192pushq $__USER32_DS93pushq PER_CPU_VAR(old_rsp)94pushq %r1195pushq $__USER32_CS96pushq %rcx9798pushq $0991: jmp hypercall_iret100ENDPATCH(xen_sysret32)101RELOC(xen_sysret32, 1b+1)102103/*104* Xen handles syscall callbacks much like ordinary exceptions, which105* means we have:106* - kernel gs107* - kernel rsp108* - an iret-like stack frame on the stack (including rcx and r11):109* ss110* rsp111* rflags112* cs113* rip114* r11115* rsp->rcx116*117* In all the entrypoints, we undo all that to make it look like a118* CPU-generated syscall/sysenter and jump to the normal entrypoint.119*/120121.macro undo_xen_syscall122mov 0*8(%rsp), %rcx123mov 1*8(%rsp), %r11124mov 5*8(%rsp), %rsp125.endm126127/* Normal 64-bit system call target */128ENTRY(xen_syscall_target)129undo_xen_syscall130jmp system_call_after_swapgs131ENDPROC(xen_syscall_target)132133#ifdef CONFIG_IA32_EMULATION134135/* 32-bit compat syscall target */136ENTRY(xen_syscall32_target)137undo_xen_syscall138jmp ia32_cstar_target139ENDPROC(xen_syscall32_target)140141/* 32-bit compat sysenter target */142ENTRY(xen_sysenter_target)143undo_xen_syscall144jmp ia32_sysenter_target145ENDPROC(xen_sysenter_target)146147#else /* !CONFIG_IA32_EMULATION */148149ENTRY(xen_syscall32_target)150ENTRY(xen_sysenter_target)151lea 16(%rsp), %rsp /* strip %rcx, %r11 */152mov $-ENOSYS, %rax153pushq $0154jmp hypercall_iret155ENDPROC(xen_syscall32_target)156ENDPROC(xen_sysenter_target)157158#endif /* CONFIG_IA32_EMULATION */159160161