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); */
20FUNC_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
39skip_gpr_lc:
40	ld r3, STACK_FRAME_PARAM(2)(sp)
41	cmpdi	r3, 0
42	beq	skip_fpu_lc
43	bl load_fpu
44skip_fpu_lc:
45	ld r3, STACK_FRAME_PARAM(3)(sp)
46	cmpdi r3, 0
47	beq	skip_vmx_lc
48	bl load_vmx
49skip_vmx_lc:
50	ld r3, STACK_FRAME_PARAM(4)(sp)
51	cmpdi	r3, 0
52	beq	skip_vsx_lc
53	bl load_vsx
54skip_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
70skip_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
77skip_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
84skip_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
91skip_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
110FUNC_END(tm_signal_self_context_load)
111