Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/j9vm31/j9cel4ro64.c
5985 views
1
/*******************************************************************************
2
* Copyright (c) 2021, 2021 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
#include "j9cel4ro64.h"
24
#include <assert.h> /* Required for __gtca() */
25
26
/* Function descriptor of CEL4RO64 runtime call from GTCA control block */
27
typedef void cel4ro64_cwi_func(void*);
28
#pragma linkage (cel4ro64_cwi_func,OS_UPSTACK)
29
#define CEL4RO64_FNPTR ((cel4ro64_cwi_func *)(*(int*)((char*)(*(int*)(((char*)__gtca())+1024))+8)))
30
31
/* CEEPCB_3164 indicator is the 6th bit of PCB's CEEPCBFLAG6 field (byte 84).
32
* CEECAAPCB field is byte 756 of CAA.
33
*
34
* References for AMODE31:
35
* https://www.ibm.com/docs/en/zos/2.4.0?topic=conventions-language-environment-process-control-block
36
* https://www.ibm.com/docs/en/zos/2.4.0?topic=conventions-language-environment-common-anchor-area
37
*/
38
#define CEL4RO64_CEEPCBFLAG6_VALUE *((char *)(*(int *)(((char *)__gtca())+756))+84)
39
#define CEL4RO64_CEEPCB_3164_MASK 0x4
40
41
#pragma linkage (J9VM_STE,OS)
42
float J9VM_STE(void);
43
#pragma linkage (J9VM_STD,OS)
44
double J9VM_STD(void);
45
#pragma linkage (J9VM_LE,OS)
46
void J9VM_LE(float);
47
#pragma linkage (J9VM_LD,OS)
48
void J9VM_LD(double);
49
50
/**
51
* Populate the arguments from argValues in outgoing 64-bit representation based on the types provided.
52
* This routine will zero extend upper 32-bits as necessary.
53
*
54
* @param[in] outgoingArgs The outgoing argument storage area with first 4-bytes as length.
55
* @param[in] argTypes An array of argument types for call.
56
* @param[in] argsValues An uint64_t array of argument values.
57
* @param[in] numArgs Number of arguments.
58
*/
59
static void
60
populateArguments(uint64_t *outgoingArgs, J9_CEL4RO64_ArgType *argTypes, uint64_t *argValues, uint32_t numArgs)
61
{
62
/* First field of outgoingArgs is length member - each argument on 64-bit side is
63
* in an 8-byte slot. Bump outgoingArgs by 4-bytes afterwards.
64
*/
65
uint32_t *lengthPtr = (uint32_t*)outgoingArgs;
66
*lengthPtr = sizeof(uint64_t) * numArgs;
67
outgoingArgs = (uint64_t *)&(lengthPtr[1]);
68
69
for (uint32_t i = 0; i < numArgs; i++) {
70
J9_CEL4RO64_ArgType argType = argTypes[i];
71
jfloat floatArg;
72
jdouble doubleArg;
73
74
switch(argType) {
75
case CEL4RO64_type_jboolean:
76
case CEL4RO64_type_jbyte:
77
case CEL4RO64_type_jchar:
78
case CEL4RO64_type_jshort:
79
case CEL4RO64_type_jint:
80
case CEL4RO64_type_jsize:
81
case CEL4RO64_type_uint32_ptr:
82
outgoingArgs[i] = argValues[i] & 0xFFFFFFFF;
83
break;
84
case CEL4RO64_type_jfloat:
85
/* Note: Float argument requires special handling as the value needs to be loaded into FPR0.
86
* Only set*FloatField JNI functions have a jfloat parameter, so only need to handle
87
* one instance.
88
*/
89
floatArg = *(jfloat *)(&(argValues[i]));
90
/* Ideally, we could have used the following inline asm
91
* but V2R1 xlc does not support that yet.
92
* __asm(" LE 0,%0" : : "m"(floatArg));
93
*/
94
J9VM_LE(floatArg);
95
break;
96
case CEL4RO64_type_jdouble:
97
/* Note: Double argument requires special handling as the value needs to be loaded into FPR0.
98
* Only set*DoubleField JNI functions have a jdouble parameter, so only need to handle
99
* one instance.
100
*/
101
doubleArg = *(jdouble *)(&(argValues[i]));
102
/* Ideally, we could have used the following inline asm
103
* but V2R1 xlc does not support that yet.
104
* __asm(" LD 0,%0" : : "m"(doubleArg));
105
*/
106
J9VM_LD(doubleArg);
107
break;
108
case CEL4RO64_type_jlong:
109
case CEL4RO64_type_jobject:
110
case CEL4RO64_type_jweak:
111
case CEL4RO64_type_jclass:
112
case CEL4RO64_type_jstring:
113
case CEL4RO64_type_jthrowable:
114
case CEL4RO64_type_jarray:
115
case CEL4RO64_type_jmethodID:
116
case CEL4RO64_type_jfieldID:
117
case CEL4RO64_type_JNIEnv64:
118
case CEL4RO64_type_JavaVM64:
119
outgoingArgs[i] = argValues[i];
120
break;
121
default:
122
break;
123
}
124
}
125
}
126
127
/**
128
* Populate the return storage buffer with the appropriate return value from CEL4RO64 call.
129
*
130
* @param[in] controlBlock The outgoing argument storage area.
131
* @param[in] returnType The return type of target function.
132
* @param[in] returnStorage The storage location to store return value.
133
*/
134
static void
135
populateReturnValue(J9_CEL4RO64_controlBlock *controlBlock, J9_CEL4RO64_ArgType returnType, void *returnStorage)
136
{
137
/* Integral and pointer data types <= 64 bits in length are widened to 64 bits and returned in GPR3. */
138
uint64_t GPR3returnValue = controlBlock->gpr3ReturnValue;
139
140
/* Cannot initialize these floating point variables, as it might kill FPR0 which contains the real
141
* return value.
142
*/
143
jfloat floatReturnValue;
144
jdouble doubleReturnValue;
145
146
switch(returnType) {
147
case CEL4RO64_type_jboolean:
148
*((jboolean *)returnStorage) = (jboolean)GPR3returnValue;
149
break;
150
case CEL4RO64_type_jbyte:
151
*((jbyte *)returnStorage) = (jbyte)GPR3returnValue;
152
break;
153
case CEL4RO64_type_jchar:
154
*((jchar *)returnStorage) = (jchar)GPR3returnValue;
155
break;
156
case CEL4RO64_type_jshort:
157
*((jshort *)returnStorage) = (jshort)GPR3returnValue;
158
break;
159
case CEL4RO64_type_jint:
160
case CEL4RO64_type_jsize:
161
*((jint *)returnStorage) = (jint)GPR3returnValue;
162
break;
163
case CEL4RO64_type_jfloat:
164
/* Float return values are returned via FPR0.
165
* Ideally, we could have used the following inline asm
166
* but V2R1 xlc does not support that yet.
167
* __asm(" STE 0,%0" : "=m"(floatReturnValue));
168
*/
169
floatReturnValue = J9VM_STE();
170
*((jfloat *)returnStorage) = floatReturnValue;
171
break;
172
case CEL4RO64_type_jdouble:
173
/* Double return values are returned via FPR0.
174
* Ideally, we could have used the following inline asm
175
* but V2R1 xlc does not support that yet.
176
* __asm(" STD 0,%0" : "=m"(doubleReturnValue));
177
*/
178
doubleReturnValue = J9VM_STD();
179
*((jdouble *)returnStorage) = doubleReturnValue;
180
break;
181
case CEL4RO64_type_jlong:
182
case CEL4RO64_type_jobject:
183
case CEL4RO64_type_jweak:
184
case CEL4RO64_type_jclass:
185
case CEL4RO64_type_jstring:
186
case CEL4RO64_type_jthrowable:
187
case CEL4RO64_type_jarray:
188
case CEL4RO64_type_jmethodID:
189
case CEL4RO64_type_jfieldID:
190
case CEL4RO64_type_JNIEnv64:
191
case CEL4RO64_type_JavaVM64:
192
/* These are all 64-bit types. */
193
*((uint64_t*)returnStorage) = GPR3returnValue;
194
break;
195
case CEL4RO64_type_uint32_ptr:
196
*((uint32_t *)returnStorage) = (uint32_t)GPR3returnValue;
197
break;
198
default:
199
break;
200
}
201
}
202
203
uint32_t
204
j9_cel4ro64_call_function(
205
uint64_t functionDescriptor, J9_CEL4RO64_ArgType *argTypes, uint64_t *argValues, uint32_t numArgs,
206
J9_CEL4RO64_ArgType returnType, void *returnStorage)
207
{
208
uint32_t retcode = J9_CEL4RO64_RETCODE_OK;
209
uint32_t argumentAreaInBytes = (0 == numArgs) ? 0 : (sizeof(uint64_t) * numArgs + sizeof(uint32_t)); /* 8 byte slots + 4 byte length member. */
210
J9_CEL4RO64_controlBlock *controlBlock = NULL;
211
212
/* The CEL4RO64 function may not be available if the LE ++APAR is not installed. */
213
if (!j9_cel4ro64_isSupported()) {
214
fprintf(stderr, "CEL4RO64: %s\n", j9_cel4ro64_get_error_message(J9_CEL4RO64_RETCODE_ERROR_LE_RUNTIME_SUPPORT_NOT_FOUND));
215
return J9_CEL4RO64_RETCODE_ERROR_LE_RUNTIME_SUPPORT_NOT_FOUND;
216
}
217
218
controlBlock = (J9_CEL4RO64_controlBlock *)malloc(sizeof(J9_CEL4RO64_controlBlock) + argumentAreaInBytes);
219
220
if (NULL == controlBlock) {
221
retcode = J9_CEL4RO64_RETCODE_ERROR_STORAGE_ISSUE;
222
fprintf(stderr, "CEL4RO64: malloc failed: %s\n", j9_cel4ro64_get_error_message(retcode));
223
return retcode;
224
}
225
226
/* Initialize the control block members and calculate the various offsets. */
227
controlBlock->version = 1;
228
controlBlock->flags = J9_CEL4RO64_FLAG_EXECUTE_TARGET_FUNC;
229
controlBlock->moduleOffset = sizeof(J9_CEL4RO64_controlBlock);
230
controlBlock->functionOffset = sizeof(J9_CEL4RO64_controlBlock);
231
controlBlock->dllHandle = 0;
232
controlBlock->functionDescriptor = functionDescriptor;
233
234
/* If no arguments, the argumentOffset must be zero. */
235
if (0 == numArgs) {
236
controlBlock->argumentsOffset = 0;
237
} else {
238
uint64_t *argumentsArea = (uint64_t *)((char *)(controlBlock) + sizeof(J9_CEL4RO64_controlBlock));
239
controlBlock->argumentsOffset = sizeof(J9_CEL4RO64_controlBlock);
240
populateArguments(argumentsArea, argTypes, argValues, numArgs);
241
}
242
243
CEL4RO64_FNPTR(controlBlock);
244
retcode = controlBlock->retcode;
245
if ((J9_CEL4RO64_RETCODE_OK == retcode) && (CEL4RO64_type_void != returnType)) {
246
populateReturnValue(controlBlock, returnType, returnStorage);
247
}
248
249
free(controlBlock);
250
return retcode;
251
}
252
253
uint32_t
254
j9_cel4ro64_load_query_call_function(
255
const char* moduleName, const char* functionName, J9_CEL4RO64_ArgType *argTypes,
256
uint64_t *argValues, uint32_t numArgs, J9_CEL4RO64_ArgType returnType, void *returnStorage)
257
{
258
uint32_t retcode = J9_CEL4RO64_RETCODE_OK;
259
uint32_t IPBLength = 0;
260
uint32_t moduleNameLength = strlen(moduleName);
261
uint32_t functionNameLength = strlen(functionName);
262
uint32_t argsLength = sizeof(uint64_t) * numArgs + sizeof(uint32_t); /* 8 byte slots + 4 byte length member. */
263
J9_CEL4RO64_infoBlock *infoBlock = NULL;
264
J9_CEL4RO64_controlBlock *controlBlock = NULL;
265
J9_CEL4RO64_module *moduleBlock = NULL;
266
J9_CEL4RO64_function *functionBlock = NULL;
267
268
/* The CEL4RO64 function may not be available if the LE ++APAR is not installed. */
269
if (!j9_cel4ro64_isSupported()) {
270
fprintf(stderr, "CEL4RO64: %s\n", j9_cel4ro64_get_error_message(J9_CEL4RO64_RETCODE_ERROR_LE_RUNTIME_SUPPORT_NOT_FOUND));
271
return J9_CEL4RO64_RETCODE_ERROR_LE_RUNTIME_SUPPORT_NOT_FOUND;
272
}
273
274
IPBLength = sizeof(J9_CEL4RO64_infoBlock) + moduleNameLength + functionNameLength + argsLength +
275
sizeof(moduleBlock->length) + sizeof(functionBlock->length);
276
infoBlock = (J9_CEL4RO64_infoBlock *) malloc(IPBLength);
277
if (NULL == infoBlock) {
278
retcode = J9_CEL4RO64_RETCODE_ERROR_STORAGE_ISSUE;
279
fprintf(stderr, "CEL4RO64: malloc failed: %s\n", j9_cel4ro64_get_error_message(retcode));
280
return retcode;
281
}
282
283
controlBlock = &(infoBlock->ro64ControlBlock);
284
285
/* Initialize the control block members and calculate the various offsets. */
286
controlBlock->version = 1;
287
controlBlock->flags = J9_CEL4RO64_FLAG_ALL_LOAD_QUERY_EXECUTE;
288
controlBlock->moduleOffset = sizeof(J9_CEL4RO64_controlBlock);
289
if (0 == moduleNameLength) {
290
controlBlock->functionOffset = controlBlock->moduleOffset;
291
} else {
292
controlBlock->functionOffset = controlBlock->moduleOffset + moduleNameLength + sizeof(moduleBlock->length);
293
}
294
295
/* For execute target function operations, we need to ensure args reference is set
296
* up appropriately. If no arguments, argumentsOffset needs to be 0.
297
*/
298
if (0 == argsLength) {
299
controlBlock->argumentsOffset = 0;
300
} else if (0 == functionNameLength) {
301
controlBlock->argumentsOffset = controlBlock->functionOffset;
302
} else {
303
controlBlock->argumentsOffset = controlBlock->functionOffset + functionNameLength + sizeof(functionBlock->length);
304
}
305
306
/* For DLL load operations, we need a module name specified. */
307
moduleBlock = (J9_CEL4RO64_module *)((char *)(controlBlock) + controlBlock->moduleOffset);
308
infoBlock->ro64Module = moduleBlock;
309
moduleBlock->length = moduleNameLength;
310
strncpy(moduleBlock->moduleName, moduleName, moduleNameLength);
311
312
/* For DLL query operations, we need a function name specified. */
313
functionBlock = (J9_CEL4RO64_function *)((char *)(controlBlock) + controlBlock->functionOffset);
314
infoBlock->ro64Function = functionBlock;
315
functionBlock->length = functionNameLength;
316
strncpy(functionBlock->functionName, functionName, functionNameLength);
317
318
/* For execute target function operations, we need to ensure args is set
319
* up appropriately. If no arguments, argumentsOffset needs to be 0.
320
*/
321
if (0 == numArgs) {
322
controlBlock->argumentsOffset = 0;
323
} else {
324
uint64_t *argumentsArea = (uint64_t *)((char *)(controlBlock) + controlBlock->argumentsOffset);
325
populateArguments(argumentsArea, argTypes, argValues, numArgs);
326
}
327
328
CEL4RO64_FNPTR(controlBlock);
329
retcode = controlBlock->retcode;
330
if ((J9_CEL4RO64_RETCODE_OK == retcode) && (CEL4RO64_type_void != returnType)) {
331
populateReturnValue(controlBlock, returnType, returnStorage);
332
}
333
334
free(infoBlock);
335
return retcode;
336
}
337
338
jboolean
339
j9_cel4ro64_isSupported(void)
340
{
341
return (CEL4RO64_CEEPCB_3164_MASK == (CEL4RO64_CEEPCBFLAG6_VALUE & CEL4RO64_CEEPCB_3164_MASK));
342
}
343
344
const char*
345
j9_cel4ro64_get_error_message(int retCode)
346
{
347
const char* errorMessage;
348
switch(retCode) {
349
case J9_CEL4RO64_RETCODE_OK:
350
errorMessage = "No errors detected.";
351
break;
352
case J9_CEL4RO64_RETCODE_ERROR_MULTITHREAD_INVOCATION:
353
errorMessage = "Multi-threaded invocation not supported.";
354
break;
355
case J9_CEL4RO64_RETCODE_ERROR_STORAGE_ISSUE:
356
errorMessage = "Storage issue detected.";
357
break;
358
case J9_CEL4RO64_RETCODE_ERROR_FAILED_AMODE64_ENV:
359
errorMessage = "Failed to initialize AMODE64 environment.";
360
break;
361
case J9_CEL4RO64_RETCODE_ERROR_FAILED_LOAD_TARGET_DLL:
362
errorMessage = "DLL module not found.";
363
break;
364
case J9_CEL4RO64_RETCODE_ERROR_FAILED_QUERY_TARGET_FUNC:
365
errorMessage = "Target function not found.";
366
break;
367
case J9_CEL4RO64_RETCODE_ERROR_LE_RUNTIME_SUPPORT_NOT_FOUND:
368
errorMessage = "CEL4RO64 runtime support not found.";
369
break;
370
default:
371
errorMessage = "Unexpected return code.";
372
break;
373
}
374
return errorMessage;
375
}
376
377