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