1120373Smarcus/* SPDX-License-Identifier: GPL-2.0-or-later */
2120373Smarcus/*
3120373Smarcus * Copyright 2015, Cyril Bur, IBM Corp.
4120373Smarcus */
5120373Smarcus
6120373Smarcus#include "basic_asm.h"
7120373Smarcus#include "gpr_asm.h"
8120373Smarcus#include "fpu_asm.h"
9120373Smarcus#include "vmx_asm.h"
10120373Smarcus#include "vsx_asm.h"
11120373Smarcus
12120373Smarcus/*
13120373Smarcus * Large caveat here being that the caller cannot expect the
14120373Smarcus * signal to always be sent! The hardware can (AND WILL!) abort
15120373Smarcus * the transaction between the tbegin and the tsuspend (however
16120373Smarcus * unlikely it seems or infrequently it actually happens).
17120373Smarcus * You have been warned.
18120373Smarcus */
19120373Smarcus/* long tm_signal_self(pid_t pid, long *gprs, double *fps, vector *vms, vector *vss); */
20120373SmarcusFUNC_START(tm_signal_self_context_load)
21120373Smarcus	PUSH_BASIC_STACK(512)
22120373Smarcus	/*
23120373Smarcus	 * Don't strictly need to save and restore as it depends on if
24120373Smarcus	 * we're going to use them, however this reduces messy logic
25120373Smarcus	 */
26120373Smarcus	PUSH_VMX(STACK_FRAME_LOCAL(5,0),r8)
27120373Smarcus	PUSH_FPU(512)
28120373Smarcus	PUSH_NVREGS_BELOW_FPU(512)
29120373Smarcus	std r3, STACK_FRAME_PARAM(0)(sp) /* pid */
30120373Smarcus	std r4, STACK_FRAME_PARAM(1)(sp) /* gps */
31120373Smarcus	std r5, STACK_FRAME_PARAM(2)(sp) /* fps */
32120373Smarcus	std r6, STACK_FRAME_PARAM(3)(sp) /* vms */
33145921Sglebius	std r7, STACK_FRAME_PARAM(4)(sp) /* vss */
34145921Sglebius
35162674Spiso	ld r3, STACK_FRAME_PARAM(1)(sp)
36162674Spiso	cmpdi r3, 0
37145921Sglebius	beq skip_gpr_lc
38162674Spiso	bl load_gpr
39120373Smarcusskip_gpr_lc:
40145921Sglebius	ld r3, STACK_FRAME_PARAM(2)(sp)
41145921Sglebius	cmpdi	r3, 0
42145921Sglebius	beq	skip_fpu_lc
43120373Smarcus	bl load_fpu
44120373Smarcusskip_fpu_lc:
45120373Smarcus	ld r3, STACK_FRAME_PARAM(3)(sp)
46120373Smarcus	cmpdi r3, 0
47120373Smarcus	beq	skip_vmx_lc
48145921Sglebius	bl load_vmx
49145921Sglebiusskip_vmx_lc:
50162674Spiso	ld r3, STACK_FRAME_PARAM(4)(sp)
51145921Sglebius	cmpdi	r3, 0
52120373Smarcus	beq	skip_vsx_lc
53162674Spiso	bl load_vsx
54145921Sglebiusskip_vsx_lc:
55120373Smarcus	/*
56162674Spiso	 * Set r3 (return value) before tbegin. Use the pid as a known
57162674Spiso	 * 'all good' return value, zero is used to indicate a non-doomed
58162674Spiso	 * transaction.
59162674Spiso	 */
60162674Spiso	ld	r3, STACK_FRAME_PARAM(0)(sp)
61162674Spiso	tbegin.
62162674Spiso	beq	1f
63162674Spiso	tsuspend. /* Can't enter a syscall transactionally */
64162674Spiso	ld	r3, STACK_FRAME_PARAM(1)(sp)
65162674Spiso	cmpdi	r3, 0
66162674Spiso	beq skip_gpr_lt
67162674Spiso	/* Get the second half of the array */
68162674Spiso	addi	r3, r3, 8 * 18
69162674Spiso	bl load_gpr
70162674Spisoskip_gpr_lt:
71162674Spiso	ld r3, STACK_FRAME_PARAM(2)(sp)
72162674Spiso	cmpdi	r3, 0
73162674Spiso	beq	skip_fpu_lt
74162674Spiso	/* Get the second half of the array */
75162674Spiso	addi	r3, r3, 8 * 18
76162674Spiso	bl load_fpu
77162674Spisoskip_fpu_lt:
78162674Spiso	ld r3, STACK_FRAME_PARAM(3)(sp)
79162674Spiso	cmpdi r3, 0
80162674Spiso	beq	skip_vmx_lt
81162674Spiso	/* Get the second half of the array */
82162674Spiso	addi	r3, r3, 16 * 12
83162674Spiso	bl load_vmx
84162674Spisoskip_vmx_lt:
85162674Spiso	ld r3, STACK_FRAME_PARAM(4)(sp)
86162674Spiso	cmpdi	r3, 0
87162674Spiso	beq	skip_vsx_lt
88162674Spiso	/* Get the second half of the array */
89162674Spiso	addi	r3, r3, 16 * 12
90162674Spiso	bl load_vsx
91162674Spisoskip_vsx_lt:
92162674Spiso	li	r0, 37 /* sys_kill */
93162674Spiso	ld r3, STACK_FRAME_PARAM(0)(sp) /* pid */
94162674Spiso	li r4, 10 /* SIGUSR1 */
95162674Spiso	sc /* Taking the signal will doom the transaction */
96162674Spiso	tabort. 0
97162674Spiso	tresume. /* Be super sure we abort */
98162674Spiso	/*
99162674Spiso	 * This will cause us to resume doomed transaction and cause
100162674Spiso	 * hardware to cleanup, we'll end up at 1: anything between
101162674Spiso	 * tresume. and 1: shouldn't ever run.
102162674Spiso	 */
103162674Spiso	li r3, 0
104162674Spiso	1:
105162674Spiso	POP_VMX(STACK_FRAME_LOCAL(5,0),r4)
106162674Spiso	POP_FPU(512)
107162674Spiso	POP_NVREGS_BELOW_FPU(512)
108162674Spiso	POP_BASIC_STACK(512)
109162674Spiso	blr
110162674SpisoFUNC_END(tm_signal_self_context_load)
111162674Spiso