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