xref: /openbmc/linux/arch/x86/um/shared/sysdep/stub_64.h (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
15c48b108SAl Viro /*
25c48b108SAl Viro  * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
35c48b108SAl Viro  * Licensed under the GPL
45c48b108SAl Viro  */
55c48b108SAl Viro 
65c48b108SAl Viro #ifndef __SYSDEP_STUB_H
75c48b108SAl Viro #define __SYSDEP_STUB_H
85c48b108SAl Viro 
95c48b108SAl Viro #include <sysdep/ptrace_user.h>
109f0b4807SJohannes Berg #include <generated/asm-offsets.h>
117ac73fbbSJason A. Donenfeld #include <linux/stddef.h>
125c48b108SAl Viro 
135c48b108SAl Viro #define STUB_MMAP_NR __NR_mmap
145c48b108SAl Viro #define MMAP_OFFSET(o) (o)
155c48b108SAl Viro 
165c48b108SAl Viro #define __syscall_clobber "r11","rcx","memory"
175c48b108SAl Viro #define __syscall "syscall"
185c48b108SAl Viro 
stub_syscall0(long syscall)195c48b108SAl Viro static inline long stub_syscall0(long syscall)
205c48b108SAl Viro {
215c48b108SAl Viro 	long ret;
225c48b108SAl Viro 
235c48b108SAl Viro 	__asm__ volatile (__syscall
245c48b108SAl Viro 		: "=a" (ret)
255c48b108SAl Viro 		: "0" (syscall) : __syscall_clobber );
265c48b108SAl Viro 
275c48b108SAl Viro 	return ret;
285c48b108SAl Viro }
295c48b108SAl Viro 
stub_syscall2(long syscall,long arg1,long arg2)305c48b108SAl Viro static inline long stub_syscall2(long syscall, long arg1, long arg2)
315c48b108SAl Viro {
325c48b108SAl Viro 	long ret;
335c48b108SAl Viro 
345c48b108SAl Viro 	__asm__ volatile (__syscall
355c48b108SAl Viro 		: "=a" (ret)
365c48b108SAl Viro 		: "0" (syscall), "D" (arg1), "S" (arg2) : __syscall_clobber );
375c48b108SAl Viro 
385c48b108SAl Viro 	return ret;
395c48b108SAl Viro }
405c48b108SAl Viro 
stub_syscall3(long syscall,long arg1,long arg2,long arg3)415c48b108SAl Viro static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
425c48b108SAl Viro {
435c48b108SAl Viro 	long ret;
445c48b108SAl Viro 
455c48b108SAl Viro 	__asm__ volatile (__syscall
465c48b108SAl Viro 		: "=a" (ret)
475c48b108SAl Viro 		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3)
485c48b108SAl Viro 		: __syscall_clobber );
495c48b108SAl Viro 
505c48b108SAl Viro 	return ret;
515c48b108SAl Viro }
525c48b108SAl Viro 
stub_syscall4(long syscall,long arg1,long arg2,long arg3,long arg4)535c48b108SAl Viro static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
545c48b108SAl Viro 				 long arg4)
555c48b108SAl Viro {
565c48b108SAl Viro 	long ret;
575c48b108SAl Viro 
585c48b108SAl Viro 	__asm__ volatile ("movq %5,%%r10 ; " __syscall
595c48b108SAl Viro 		: "=a" (ret)
605c48b108SAl Viro 		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
615c48b108SAl Viro 		  "g" (arg4)
625c48b108SAl Viro 		: __syscall_clobber, "r10" );
635c48b108SAl Viro 
645c48b108SAl Viro 	return ret;
655c48b108SAl Viro }
665c48b108SAl Viro 
stub_syscall5(long syscall,long arg1,long arg2,long arg3,long arg4,long arg5)675c48b108SAl Viro static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
685c48b108SAl Viro 				 long arg4, long arg5)
695c48b108SAl Viro {
705c48b108SAl Viro 	long ret;
715c48b108SAl Viro 
725c48b108SAl Viro 	__asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " __syscall
735c48b108SAl Viro 		: "=a" (ret)
745c48b108SAl Viro 		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
755c48b108SAl Viro 		  "g" (arg4), "g" (arg5)
765c48b108SAl Viro 		: __syscall_clobber, "r10", "r8" );
775c48b108SAl Viro 
785c48b108SAl Viro 	return ret;
795c48b108SAl Viro }
805c48b108SAl Viro 
trap_myself(void)815c48b108SAl Viro static inline void trap_myself(void)
825c48b108SAl Viro {
835c48b108SAl Viro 	__asm("int3");
845c48b108SAl Viro }
855c48b108SAl Viro 
remap_stack_and_trap(void)869f0b4807SJohannes Berg static inline void remap_stack_and_trap(void)
875c48b108SAl Viro {
889f0b4807SJohannes Berg 	__asm__ volatile (
899f0b4807SJohannes Berg 		"movq %0,%%rax ;"
909f0b4807SJohannes Berg 		"movq %%rsp,%%rdi ;"
919f0b4807SJohannes Berg 		"andq %1,%%rdi ;"
929f0b4807SJohannes Berg 		"movq %2,%%r10 ;"
939f0b4807SJohannes Berg 		"movq %%rdi,%%r8 ; addq %3,%%r8 ; movq (%%r8),%%r8 ;"
949f0b4807SJohannes Berg 		"movq %%rdi,%%r9 ; addq %4,%%r9 ; movq (%%r9),%%r9 ;"
959f0b4807SJohannes Berg 		__syscall ";"
969f0b4807SJohannes Berg 		"movq %%rsp,%%rdi ; andq %1,%%rdi ;"
979f0b4807SJohannes Berg 		"addq %5,%%rdi ; movq %%rax, (%%rdi) ;"
989f0b4807SJohannes Berg 		"int3"
999f0b4807SJohannes Berg 		: :
1009f0b4807SJohannes Berg 		"g" (STUB_MMAP_NR),
101*6032aca0SJohannes Berg 		"g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1)),
1029f0b4807SJohannes Berg 		"g" (MAP_FIXED | MAP_SHARED),
1039f0b4807SJohannes Berg 		"g" (UML_STUB_FIELD_FD),
1049f0b4807SJohannes Berg 		"g" (UML_STUB_FIELD_OFFSET),
1059f0b4807SJohannes Berg 		"g" (UML_STUB_FIELD_CHILD_ERR),
106*6032aca0SJohannes Berg 		"S" (STUB_DATA_PAGES * UM_KERN_PAGE_SIZE),
1079f0b4807SJohannes Berg 		"d" (PROT_READ | PROT_WRITE)
1089f0b4807SJohannes Berg 		:
1099f0b4807SJohannes Berg 		__syscall_clobber, "r10", "r8", "r9");
1105c48b108SAl Viro }
1115c48b108SAl Viro 
get_stub_data(void)112*6032aca0SJohannes Berg static __always_inline void *get_stub_data(void)
113adf9ae0dSJohannes Berg {
114adf9ae0dSJohannes Berg 	unsigned long ret;
115adf9ae0dSJohannes Berg 
116adf9ae0dSJohannes Berg 	asm volatile (
117adf9ae0dSJohannes Berg 		"movq %%rsp,%0 ;"
118adf9ae0dSJohannes Berg 		"andq %1,%0"
119adf9ae0dSJohannes Berg 		: "=a" (ret)
120*6032aca0SJohannes Berg 		: "g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1)));
121adf9ae0dSJohannes Berg 
122adf9ae0dSJohannes Berg 	return (void *)ret;
123adf9ae0dSJohannes Berg }
1245c48b108SAl Viro #endif
125