18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright 2015, Cyril Bur, IBM Corp.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include "basic_asm.h"
78c2ecf20Sopenharmony_ci#include "gpr_asm.h"
88c2ecf20Sopenharmony_ci#include "fpu_asm.h"
98c2ecf20Sopenharmony_ci#include "vmx_asm.h"
108c2ecf20Sopenharmony_ci#include "vsx_asm.h"
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci/*
138c2ecf20Sopenharmony_ci * Large caveat here being that the caller cannot expect the
148c2ecf20Sopenharmony_ci * signal to always be sent! The hardware can (AND WILL!) abort
158c2ecf20Sopenharmony_ci * the transaction between the tbegin and the tsuspend (however
168c2ecf20Sopenharmony_ci * unlikely it seems or infrequently it actually happens).
178c2ecf20Sopenharmony_ci * You have been warned.
188c2ecf20Sopenharmony_ci */
198c2ecf20Sopenharmony_ci/* long tm_signal_self(pid_t pid, long *gprs, double *fps, vector *vms, vector *vss); */
208c2ecf20Sopenharmony_ciFUNC_START(tm_signal_self_context_load)
218c2ecf20Sopenharmony_ci	PUSH_BASIC_STACK(512)
228c2ecf20Sopenharmony_ci	/*
238c2ecf20Sopenharmony_ci	 * Don't strictly need to save and restore as it depends on if
248c2ecf20Sopenharmony_ci	 * we're going to use them, however this reduces messy logic
258c2ecf20Sopenharmony_ci	 */
268c2ecf20Sopenharmony_ci	PUSH_VMX(STACK_FRAME_LOCAL(5,0),r8)
278c2ecf20Sopenharmony_ci	PUSH_FPU(512)
288c2ecf20Sopenharmony_ci	PUSH_NVREGS_BELOW_FPU(512)
298c2ecf20Sopenharmony_ci	std r3, STACK_FRAME_PARAM(0)(sp) /* pid */
308c2ecf20Sopenharmony_ci	std r4, STACK_FRAME_PARAM(1)(sp) /* gps */
318c2ecf20Sopenharmony_ci	std r5, STACK_FRAME_PARAM(2)(sp) /* fps */
328c2ecf20Sopenharmony_ci	std r6, STACK_FRAME_PARAM(3)(sp) /* vms */
338c2ecf20Sopenharmony_ci	std r7, STACK_FRAME_PARAM(4)(sp) /* vss */
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	ld r3, STACK_FRAME_PARAM(1)(sp)
368c2ecf20Sopenharmony_ci	cmpdi r3, 0
378c2ecf20Sopenharmony_ci	beq skip_gpr_lc
388c2ecf20Sopenharmony_ci	bl load_gpr
398c2ecf20Sopenharmony_ciskip_gpr_lc:
408c2ecf20Sopenharmony_ci	ld r3, STACK_FRAME_PARAM(2)(sp)
418c2ecf20Sopenharmony_ci	cmpdi	r3, 0
428c2ecf20Sopenharmony_ci	beq	skip_fpu_lc
438c2ecf20Sopenharmony_ci	bl load_fpu
448c2ecf20Sopenharmony_ciskip_fpu_lc:
458c2ecf20Sopenharmony_ci	ld r3, STACK_FRAME_PARAM(3)(sp)
468c2ecf20Sopenharmony_ci	cmpdi r3, 0
478c2ecf20Sopenharmony_ci	beq	skip_vmx_lc
488c2ecf20Sopenharmony_ci	bl load_vmx
498c2ecf20Sopenharmony_ciskip_vmx_lc:
508c2ecf20Sopenharmony_ci	ld r3, STACK_FRAME_PARAM(4)(sp)
518c2ecf20Sopenharmony_ci	cmpdi	r3, 0
528c2ecf20Sopenharmony_ci	beq	skip_vsx_lc
538c2ecf20Sopenharmony_ci	bl load_vsx
548c2ecf20Sopenharmony_ciskip_vsx_lc:
558c2ecf20Sopenharmony_ci	/*
568c2ecf20Sopenharmony_ci	 * Set r3 (return value) before tbegin. Use the pid as a known
578c2ecf20Sopenharmony_ci	 * 'all good' return value, zero is used to indicate a non-doomed
588c2ecf20Sopenharmony_ci	 * transaction.
598c2ecf20Sopenharmony_ci	 */
608c2ecf20Sopenharmony_ci	ld	r3, STACK_FRAME_PARAM(0)(sp)
618c2ecf20Sopenharmony_ci	tbegin.
628c2ecf20Sopenharmony_ci	beq	1f
638c2ecf20Sopenharmony_ci	tsuspend. /* Can't enter a syscall transactionally */
648c2ecf20Sopenharmony_ci	ld	r3, STACK_FRAME_PARAM(1)(sp)
658c2ecf20Sopenharmony_ci	cmpdi	r3, 0
668c2ecf20Sopenharmony_ci	beq skip_gpr_lt
678c2ecf20Sopenharmony_ci	/* Get the second half of the array */
688c2ecf20Sopenharmony_ci	addi	r3, r3, 8 * 18
698c2ecf20Sopenharmony_ci	bl load_gpr
708c2ecf20Sopenharmony_ciskip_gpr_lt:
718c2ecf20Sopenharmony_ci	ld r3, STACK_FRAME_PARAM(2)(sp)
728c2ecf20Sopenharmony_ci	cmpdi	r3, 0
738c2ecf20Sopenharmony_ci	beq	skip_fpu_lt
748c2ecf20Sopenharmony_ci	/* Get the second half of the array */
758c2ecf20Sopenharmony_ci	addi	r3, r3, 8 * 18
768c2ecf20Sopenharmony_ci	bl load_fpu
778c2ecf20Sopenharmony_ciskip_fpu_lt:
788c2ecf20Sopenharmony_ci	ld r3, STACK_FRAME_PARAM(3)(sp)
798c2ecf20Sopenharmony_ci	cmpdi r3, 0
808c2ecf20Sopenharmony_ci	beq	skip_vmx_lt
818c2ecf20Sopenharmony_ci	/* Get the second half of the array */
828c2ecf20Sopenharmony_ci	addi	r3, r3, 16 * 12
838c2ecf20Sopenharmony_ci	bl load_vmx
848c2ecf20Sopenharmony_ciskip_vmx_lt:
858c2ecf20Sopenharmony_ci	ld r3, STACK_FRAME_PARAM(4)(sp)
868c2ecf20Sopenharmony_ci	cmpdi	r3, 0
878c2ecf20Sopenharmony_ci	beq	skip_vsx_lt
888c2ecf20Sopenharmony_ci	/* Get the second half of the array */
898c2ecf20Sopenharmony_ci	addi	r3, r3, 16 * 12
908c2ecf20Sopenharmony_ci	bl load_vsx
918c2ecf20Sopenharmony_ciskip_vsx_lt:
928c2ecf20Sopenharmony_ci	li	r0, 37 /* sys_kill */
938c2ecf20Sopenharmony_ci	ld r3, STACK_FRAME_PARAM(0)(sp) /* pid */
948c2ecf20Sopenharmony_ci	li r4, 10 /* SIGUSR1 */
958c2ecf20Sopenharmony_ci	sc /* Taking the signal will doom the transaction */
968c2ecf20Sopenharmony_ci	tabort. 0
978c2ecf20Sopenharmony_ci	tresume. /* Be super sure we abort */
988c2ecf20Sopenharmony_ci	/*
998c2ecf20Sopenharmony_ci	 * This will cause us to resume doomed transaction and cause
1008c2ecf20Sopenharmony_ci	 * hardware to cleanup, we'll end up at 1: anything between
1018c2ecf20Sopenharmony_ci	 * tresume. and 1: shouldn't ever run.
1028c2ecf20Sopenharmony_ci	 */
1038c2ecf20Sopenharmony_ci	li r3, 0
1048c2ecf20Sopenharmony_ci	1:
1058c2ecf20Sopenharmony_ci	POP_VMX(STACK_FRAME_LOCAL(5,0),r4)
1068c2ecf20Sopenharmony_ci	POP_FPU(512)
1078c2ecf20Sopenharmony_ci	POP_NVREGS_BELOW_FPU(512)
1088c2ecf20Sopenharmony_ci	POP_BASIC_STACK(512)
1098c2ecf20Sopenharmony_ci	blr
1108c2ecf20Sopenharmony_ciFUNC_END(tm_signal_self_context_load)
111