|  | /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ | 
|  |  | 
|  | /* | 
|  | * RSEQ_SIG uses the trap4 instruction. As Linux does not make use of the | 
|  | * access-register mode nor the linkage stack this instruction will always | 
|  | * cause a special-operation exception (the trap-enabled bit in the DUCT | 
|  | * is and will stay 0). The instruction pattern is | 
|  | *	b2 ff 0f ff	trap4	4095(%r0) | 
|  | */ | 
|  | #define RSEQ_SIG	0xB2FF0FFF | 
|  |  | 
|  | #define rseq_smp_mb()	__asm__ __volatile__ ("bcr 15,0" ::: "memory") | 
|  | #define rseq_smp_rmb()	rseq_smp_mb() | 
|  | #define rseq_smp_wmb()	rseq_smp_mb() | 
|  |  | 
|  | #define rseq_smp_load_acquire(p)					\ | 
|  | __extension__ ({							\ | 
|  | rseq_unqual_scalar_typeof(*(p)) ____p1 = RSEQ_READ_ONCE(*(p));	\ | 
|  | rseq_barrier();							\ | 
|  | ____p1;								\ | 
|  | }) | 
|  |  | 
|  | #define rseq_smp_acquire__after_ctrl_dep()	rseq_smp_rmb() | 
|  |  | 
|  | #define rseq_smp_store_release(p, v)					\ | 
|  | do {									\ | 
|  | rseq_barrier();							\ | 
|  | RSEQ_WRITE_ONCE(*(p), v);					\ | 
|  | } while (0) | 
|  |  | 
|  | #ifdef __s390x__ | 
|  |  | 
|  | #define LONG_L			"lg" | 
|  | #define LONG_S			"stg" | 
|  | #define LONG_LT_R		"ltgr" | 
|  | #define LONG_CMP		"cg" | 
|  | #define LONG_CMP_R		"cgr" | 
|  | #define LONG_ADDI		"aghi" | 
|  | #define LONG_ADD_R		"agr" | 
|  |  | 
|  | #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags,			\ | 
|  | start_ip, post_commit_offset, abort_ip)	\ | 
|  | ".pushsection __rseq_cs, \"aw\"\n\t"			\ | 
|  | ".balign 32\n\t"					\ | 
|  | __rseq_str(label) ":\n\t"				\ | 
|  | ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \ | 
|  | ".quad " __rseq_str(start_ip) ", " __rseq_str(post_commit_offset) ", " __rseq_str(abort_ip) "\n\t" \ | 
|  | ".popsection\n\t"					\ | 
|  | ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t"		\ | 
|  | ".quad " __rseq_str(label) "b\n\t"			\ | 
|  | ".popsection\n\t" | 
|  |  | 
|  | /* | 
|  | * Exit points of a rseq critical section consist of all instructions outside | 
|  | * of the critical section where a critical section can either branch to or | 
|  | * reach through the normal course of its execution. The abort IP and the | 
|  | * post-commit IP are already part of the __rseq_cs section and should not be | 
|  | * explicitly defined as additional exit points. Knowing all exit points is | 
|  | * useful to assist debuggers stepping over the critical section. | 
|  | */ | 
|  | #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip)			\ | 
|  | ".pushsection __rseq_exit_point_array, \"aw\"\n\t"	\ | 
|  | ".quad " __rseq_str(start_ip) ", " __rseq_str(exit_ip) "\n\t" \ | 
|  | ".popsection\n\t" | 
|  |  | 
|  | #elif __s390__ | 
|  |  | 
|  | #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags,			\ | 
|  | start_ip, post_commit_offset, abort_ip)	\ | 
|  | ".pushsection __rseq_cs, \"aw\"\n\t"			\ | 
|  | ".balign 32\n\t"					\ | 
|  | __rseq_str(label) ":\n\t"				\ | 
|  | ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \ | 
|  | ".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) "\n\t" \ | 
|  | ".popsection\n\t"					\ | 
|  | ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t"		\ | 
|  | ".long 0x0, " __rseq_str(label) "b\n\t"			\ | 
|  | ".popsection\n\t" | 
|  |  | 
|  | /* | 
|  | * Exit points of a rseq critical section consist of all instructions outside | 
|  | * of the critical section where a critical section can either branch to or | 
|  | * reach through the normal course of its execution. The abort IP and the | 
|  | * post-commit IP are already part of the __rseq_cs section and should not be | 
|  | * explicitly defined as additional exit points. Knowing all exit points is | 
|  | * useful to assist debuggers stepping over the critical section. | 
|  | */ | 
|  | #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip)			\ | 
|  | ".pushsection __rseq_exit_point_array, \"aw\"\n\t"	\ | 
|  | ".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(exit_ip) "\n\t" \ | 
|  | ".popsection\n\t" | 
|  |  | 
|  | #define LONG_L			"l" | 
|  | #define LONG_S			"st" | 
|  | #define LONG_LT_R		"ltr" | 
|  | #define LONG_CMP		"c" | 
|  | #define LONG_CMP_R		"cr" | 
|  | #define LONG_ADDI		"ahi" | 
|  | #define LONG_ADD_R		"ar" | 
|  |  | 
|  | #endif | 
|  |  | 
|  | #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \ | 
|  | __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip,		\ | 
|  | (post_commit_ip - start_ip), abort_ip) | 
|  |  | 
|  | #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs)		\ | 
|  | RSEQ_INJECT_ASM(1)					\ | 
|  | "larl %%r0, " __rseq_str(cs_label) "\n\t"		\ | 
|  | LONG_S " %%r0, %[" __rseq_str(rseq_cs) "]\n\t"		\ | 
|  | __rseq_str(label) ":\n\t" | 
|  |  | 
|  | #define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label)		\ | 
|  | RSEQ_INJECT_ASM(2)					\ | 
|  | "c %[" __rseq_str(cpu_id) "], %[" __rseq_str(current_cpu_id) "]\n\t" \ | 
|  | "jnz " __rseq_str(label) "\n\t" | 
|  |  | 
|  | #define RSEQ_ASM_DEFINE_ABORT(label, teardown, abort_label)		\ | 
|  | ".pushsection __rseq_failure, \"ax\"\n\t"		\ | 
|  | ".long " __rseq_str(RSEQ_SIG) "\n\t"			\ | 
|  | __rseq_str(label) ":\n\t"				\ | 
|  | teardown						\ | 
|  | "jg %l[" __rseq_str(abort_label) "]\n\t"		\ | 
|  | ".popsection\n\t" | 
|  |  | 
|  | #define RSEQ_ASM_DEFINE_CMPFAIL(label, teardown, cmpfail_label)		\ | 
|  | ".pushsection __rseq_failure, \"ax\"\n\t"		\ | 
|  | __rseq_str(label) ":\n\t"				\ | 
|  | teardown						\ | 
|  | "jg %l[" __rseq_str(cmpfail_label) "]\n\t"		\ | 
|  | ".popsection\n\t" | 
|  |  | 
|  | /* Per-cpu-id indexing. */ | 
|  |  | 
|  | #define RSEQ_TEMPLATE_CPU_ID | 
|  | #define RSEQ_TEMPLATE_MO_RELAXED | 
|  | #include "rseq-s390-bits.h" | 
|  | #undef RSEQ_TEMPLATE_MO_RELAXED | 
|  |  | 
|  | #define RSEQ_TEMPLATE_MO_RELEASE | 
|  | #include "rseq-s390-bits.h" | 
|  | #undef RSEQ_TEMPLATE_MO_RELEASE | 
|  | #undef RSEQ_TEMPLATE_CPU_ID | 
|  |  | 
|  | /* Per-mm-cid indexing. */ | 
|  |  | 
|  | #define RSEQ_TEMPLATE_MM_CID | 
|  | #define RSEQ_TEMPLATE_MO_RELAXED | 
|  | #include "rseq-s390-bits.h" | 
|  | #undef RSEQ_TEMPLATE_MO_RELAXED | 
|  |  | 
|  | #define RSEQ_TEMPLATE_MO_RELEASE | 
|  | #include "rseq-s390-bits.h" | 
|  | #undef RSEQ_TEMPLATE_MO_RELEASE | 
|  | #undef RSEQ_TEMPLATE_MM_CID | 
|  |  | 
|  | /* APIs which are not based on cpu ids. */ | 
|  |  | 
|  | #define RSEQ_TEMPLATE_CPU_ID_NONE | 
|  | #define RSEQ_TEMPLATE_MO_RELAXED | 
|  | #include "rseq-s390-bits.h" | 
|  | #undef RSEQ_TEMPLATE_MO_RELAXED | 
|  | #undef RSEQ_TEMPLATE_CPU_ID_NONE |