1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
| /* SPDX-License-Identifier: GPL-2.0-or-later */
| /*
| * Copyright 2015, Cyril Bur, IBM Corp.
| */
|
| #include "basic_asm.h"
| #include "vmx_asm.h"
|
| # Should be safe from C, only touches r4, r5 and v0,v1,v2
| FUNC_START(check_vmx)
| PUSH_BASIC_STACK(32)
| mr r4,r3
| li r3,1 # assume a bad result
| li r5,0
| lvx v0,r5,r4
| vcmpequd. v1,v0,v20
| vmr v2,v1
|
| addi r5,r5,16
| lvx v0,r5,r4
| vcmpequd. v1,v0,v21
| vand v2,v2,v1
|
| addi r5,r5,16
| lvx v0,r5,r4
| vcmpequd. v1,v0,v22
| vand v2,v2,v1
|
| addi r5,r5,16
| lvx v0,r5,r4
| vcmpequd. v1,v0,v23
| vand v2,v2,v1
|
| addi r5,r5,16
| lvx v0,r5,r4
| vcmpequd. v1,v0,v24
| vand v2,v2,v1
|
| addi r5,r5,16
| lvx v0,r5,r4
| vcmpequd. v1,v0,v25
| vand v2,v2,v1
|
| addi r5,r5,16
| lvx v0,r5,r4
| vcmpequd. v1,v0,v26
| vand v2,v2,v1
|
| addi r5,r5,16
| lvx v0,r5,r4
| vcmpequd. v1,v0,v27
| vand v2,v2,v1
|
| addi r5,r5,16
| lvx v0,r5,r4
| vcmpequd. v1,v0,v28
| vand v2,v2,v1
|
| addi r5,r5,16
| lvx v0,r5,r4
| vcmpequd. v1,v0,v29
| vand v2,v2,v1
|
| addi r5,r5,16
| lvx v0,r5,r4
| vcmpequd. v1,v0,v30
| vand v2,v2,v1
|
| addi r5,r5,16
| lvx v0,r5,r4
| vcmpequd. v1,v0,v31
| vand v2,v2,v1
|
| li r5,STACK_FRAME_LOCAL(0,0)
| stvx v2,r5,sp
| ldx r0,r5,sp
| cmpdi r0,0xffffffffffffffff
| bne 1f
| li r3,0
| 1: POP_BASIC_STACK(32)
| blr
| FUNC_END(check_vmx)
|
| # Safe from C
| FUNC_START(test_vmx)
| # r3 holds pointer to where to put the result of fork
| # r4 holds pointer to the pid
| # v20-v31 are non-volatile
| PUSH_BASIC_STACK(512)
| std r3,STACK_FRAME_PARAM(0)(sp) # Address of varray
| std r4,STACK_FRAME_PARAM(1)(sp) # address of pid
| PUSH_VMX(STACK_FRAME_LOCAL(2,0),r4)
|
| bl load_vmx
| nop
|
| li r0,__NR_fork
| sc
| # Pass the result of fork back to the caller
| ld r9,STACK_FRAME_PARAM(1)(sp)
| std r3,0(r9)
|
| ld r3,STACK_FRAME_PARAM(0)(sp)
| bl check_vmx
| nop
|
| POP_VMX(STACK_FRAME_LOCAL(2,0),r4)
| POP_BASIC_STACK(512)
| blr
| FUNC_END(test_vmx)
|
| # int preempt_vmx(vector int *varray, int *threads_starting, int *running)
| # On starting will (atomically) decrement threads_starting as a signal that
| # the VMX have been loaded with varray. Will proceed to check the validity of
| # the VMX registers while running is not zero.
| FUNC_START(preempt_vmx)
| PUSH_BASIC_STACK(512)
| std r3,STACK_FRAME_PARAM(0)(sp) # vector int *varray
| std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting
| std r5,STACK_FRAME_PARAM(2)(sp) # int *running
| # VMX need to write to 16 byte aligned addresses, skip STACK_FRAME_LOCAL(3,0)
| PUSH_VMX(STACK_FRAME_LOCAL(4,0),r4)
|
| bl load_vmx
| nop
|
| sync
| # Atomic DEC
| ld r3,STACK_FRAME_PARAM(1)(sp)
| 1: lwarx r4,0,r3
| addi r4,r4,-1
| stwcx. r4,0,r3
| bne- 1b
|
| 2: ld r3,STACK_FRAME_PARAM(0)(sp)
| bl check_vmx
| nop
| cmpdi r3,0
| bne 3f
| ld r4,STACK_FRAME_PARAM(2)(sp)
| ld r5,0(r4)
| cmpwi r5,0
| bne 2b
|
| 3: POP_VMX(STACK_FRAME_LOCAL(4,0),r4)
| POP_BASIC_STACK(512)
| blr
| FUNC_END(preempt_vmx)
|
|