xref: /OK3568_Linux_fs/kernel/tools/testing/selftests/powerpc/tm/tm-signal.S (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0-or-later */
2*4882a593Smuzhiyun/*
3*4882a593Smuzhiyun * Copyright 2015, Cyril Bur, IBM Corp.
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun#include "basic_asm.h"
7*4882a593Smuzhiyun#include "gpr_asm.h"
8*4882a593Smuzhiyun#include "fpu_asm.h"
9*4882a593Smuzhiyun#include "vmx_asm.h"
10*4882a593Smuzhiyun#include "vsx_asm.h"
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun/*
13*4882a593Smuzhiyun * Large caveat here being that the caller cannot expect the
14*4882a593Smuzhiyun * signal to always be sent! The hardware can (AND WILL!) abort
15*4882a593Smuzhiyun * the transaction between the tbegin and the tsuspend (however
16*4882a593Smuzhiyun * unlikely it seems or infrequently it actually happens).
17*4882a593Smuzhiyun * You have been warned.
18*4882a593Smuzhiyun */
19*4882a593Smuzhiyun/* long tm_signal_self(pid_t pid, long *gprs, double *fps, vector *vms, vector *vss); */
20*4882a593SmuzhiyunFUNC_START(tm_signal_self_context_load)
21*4882a593Smuzhiyun	PUSH_BASIC_STACK(512)
22*4882a593Smuzhiyun	/*
23*4882a593Smuzhiyun	 * Don't strictly need to save and restore as it depends on if
24*4882a593Smuzhiyun	 * we're going to use them, however this reduces messy logic
25*4882a593Smuzhiyun	 */
26*4882a593Smuzhiyun	PUSH_VMX(STACK_FRAME_LOCAL(5,0),r8)
27*4882a593Smuzhiyun	PUSH_FPU(512)
28*4882a593Smuzhiyun	PUSH_NVREGS_BELOW_FPU(512)
29*4882a593Smuzhiyun	std r3, STACK_FRAME_PARAM(0)(sp) /* pid */
30*4882a593Smuzhiyun	std r4, STACK_FRAME_PARAM(1)(sp) /* gps */
31*4882a593Smuzhiyun	std r5, STACK_FRAME_PARAM(2)(sp) /* fps */
32*4882a593Smuzhiyun	std r6, STACK_FRAME_PARAM(3)(sp) /* vms */
33*4882a593Smuzhiyun	std r7, STACK_FRAME_PARAM(4)(sp) /* vss */
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun	ld r3, STACK_FRAME_PARAM(1)(sp)
36*4882a593Smuzhiyun	cmpdi r3, 0
37*4882a593Smuzhiyun	beq skip_gpr_lc
38*4882a593Smuzhiyun	bl load_gpr
39*4882a593Smuzhiyunskip_gpr_lc:
40*4882a593Smuzhiyun	ld r3, STACK_FRAME_PARAM(2)(sp)
41*4882a593Smuzhiyun	cmpdi	r3, 0
42*4882a593Smuzhiyun	beq	skip_fpu_lc
43*4882a593Smuzhiyun	bl load_fpu
44*4882a593Smuzhiyunskip_fpu_lc:
45*4882a593Smuzhiyun	ld r3, STACK_FRAME_PARAM(3)(sp)
46*4882a593Smuzhiyun	cmpdi r3, 0
47*4882a593Smuzhiyun	beq	skip_vmx_lc
48*4882a593Smuzhiyun	bl load_vmx
49*4882a593Smuzhiyunskip_vmx_lc:
50*4882a593Smuzhiyun	ld r3, STACK_FRAME_PARAM(4)(sp)
51*4882a593Smuzhiyun	cmpdi	r3, 0
52*4882a593Smuzhiyun	beq	skip_vsx_lc
53*4882a593Smuzhiyun	bl load_vsx
54*4882a593Smuzhiyunskip_vsx_lc:
55*4882a593Smuzhiyun	/*
56*4882a593Smuzhiyun	 * Set r3 (return value) before tbegin. Use the pid as a known
57*4882a593Smuzhiyun	 * 'all good' return value, zero is used to indicate a non-doomed
58*4882a593Smuzhiyun	 * transaction.
59*4882a593Smuzhiyun	 */
60*4882a593Smuzhiyun	ld	r3, STACK_FRAME_PARAM(0)(sp)
61*4882a593Smuzhiyun	tbegin.
62*4882a593Smuzhiyun	beq	1f
63*4882a593Smuzhiyun	tsuspend. /* Can't enter a syscall transactionally */
64*4882a593Smuzhiyun	ld	r3, STACK_FRAME_PARAM(1)(sp)
65*4882a593Smuzhiyun	cmpdi	r3, 0
66*4882a593Smuzhiyun	beq skip_gpr_lt
67*4882a593Smuzhiyun	/* Get the second half of the array */
68*4882a593Smuzhiyun	addi	r3, r3, 8 * 18
69*4882a593Smuzhiyun	bl load_gpr
70*4882a593Smuzhiyunskip_gpr_lt:
71*4882a593Smuzhiyun	ld r3, STACK_FRAME_PARAM(2)(sp)
72*4882a593Smuzhiyun	cmpdi	r3, 0
73*4882a593Smuzhiyun	beq	skip_fpu_lt
74*4882a593Smuzhiyun	/* Get the second half of the array */
75*4882a593Smuzhiyun	addi	r3, r3, 8 * 18
76*4882a593Smuzhiyun	bl load_fpu
77*4882a593Smuzhiyunskip_fpu_lt:
78*4882a593Smuzhiyun	ld r3, STACK_FRAME_PARAM(3)(sp)
79*4882a593Smuzhiyun	cmpdi r3, 0
80*4882a593Smuzhiyun	beq	skip_vmx_lt
81*4882a593Smuzhiyun	/* Get the second half of the array */
82*4882a593Smuzhiyun	addi	r3, r3, 16 * 12
83*4882a593Smuzhiyun	bl load_vmx
84*4882a593Smuzhiyunskip_vmx_lt:
85*4882a593Smuzhiyun	ld r3, STACK_FRAME_PARAM(4)(sp)
86*4882a593Smuzhiyun	cmpdi	r3, 0
87*4882a593Smuzhiyun	beq	skip_vsx_lt
88*4882a593Smuzhiyun	/* Get the second half of the array */
89*4882a593Smuzhiyun	addi	r3, r3, 16 * 12
90*4882a593Smuzhiyun	bl load_vsx
91*4882a593Smuzhiyunskip_vsx_lt:
92*4882a593Smuzhiyun	li	r0, 37 /* sys_kill */
93*4882a593Smuzhiyun	ld r3, STACK_FRAME_PARAM(0)(sp) /* pid */
94*4882a593Smuzhiyun	li r4, 10 /* SIGUSR1 */
95*4882a593Smuzhiyun	sc /* Taking the signal will doom the transaction */
96*4882a593Smuzhiyun	tabort. 0
97*4882a593Smuzhiyun	tresume. /* Be super sure we abort */
98*4882a593Smuzhiyun	/*
99*4882a593Smuzhiyun	 * This will cause us to resume doomed transaction and cause
100*4882a593Smuzhiyun	 * hardware to cleanup, we'll end up at 1: anything between
101*4882a593Smuzhiyun	 * tresume. and 1: shouldn't ever run.
102*4882a593Smuzhiyun	 */
103*4882a593Smuzhiyun	li r3, 0
104*4882a593Smuzhiyun	1:
105*4882a593Smuzhiyun	POP_VMX(STACK_FRAME_LOCAL(5,0),r4)
106*4882a593Smuzhiyun	POP_FPU(512)
107*4882a593Smuzhiyun	POP_NVREGS_BELOW_FPU(512)
108*4882a593Smuzhiyun	POP_BASIC_STACK(512)
109*4882a593Smuzhiyun	blr
110*4882a593SmuzhiyunFUNC_END(tm_signal_self_context_load)
111