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