1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <jni.h>
18
19 #if defined(__arm__) || defined(__aarch64__)
20 #include <setjmp.h>
21 #include <signal.h>
22 #include <string.h>
23
24 static sigjmp_buf jmpenv;
25
sigill_handler(int signum)26 static void sigill_handler(int signum __attribute__((unused)))
27 {
28 siglongjmp(jmpenv, 1);
29 }
30
do_sigsetjmp()31 static int do_sigsetjmp()
32 {
33 return sigsetjmp(jmpenv, 1);
34 }
35
test_instruction(void (* func)())36 static jboolean test_instruction(void (*func)())
37 {
38 struct sigaction sigill_act;
39 struct sigaction oldact;
40 int err;
41 jboolean ret = true;
42
43 memset(&sigill_act, 0, sizeof(sigill_act));
44 sigill_act.sa_handler = sigill_handler;
45
46 err = sigaction(SIGILL, &sigill_act, &oldact);
47 if (err) {
48 ret = false;
49 goto err_sigaction;
50 }
51
52 if (do_sigsetjmp()) {
53 ret = false;
54 goto err_segill;
55 }
56
57 func();
58
59 err_segill:
60 sigaction(SIGILL, &oldact, NULL);
61 err_sigaction:
62 return ret;
63 }
64 #endif
65
66 #ifdef __aarch64__
cntvct()67 static void cntvct()
68 {
69 asm volatile ( "mrs x0, cntvct_el0" : : : "x0" );
70 }
71
android_os_cts_CpuInstructions_canReadCntvct(JNIEnv *,jobject)72 jboolean android_os_cts_CpuInstructions_canReadCntvct(JNIEnv *, jobject)
73 {
74 return test_instruction(cntvct);
75 }
76 #else
android_os_cts_CpuInstructions_canReadCntvct(JNIEnv *,jobject)77 jboolean android_os_cts_CpuInstructions_canReadCntvct(JNIEnv *, jobject)
78 {
79 return false;
80 }
81 #endif
82
83 #ifdef __arm__
swp()84 static void swp()
85 {
86 uint32_t dummy = 0;
87 uint32_t *ptr = &dummy;
88 asm volatile ( "swp r0, r0, [%0]" : "+r"(ptr) : : "r0" );
89 }
90
setend()91 static void setend()
92 {
93 asm volatile (
94 "setend be" "\n"
95 "setend le" "\n"
96 );
97 }
98
cp15_dsb()99 static void cp15_dsb()
100 {
101 asm volatile ( "mcr p15, 0, %0, c7, c10, 4" : : "r"(0) );
102 }
103
android_os_cts_CpuInstructions_hasSwp(JNIEnv *,jobject)104 jboolean android_os_cts_CpuInstructions_hasSwp(JNIEnv *, jobject)
105 {
106 return test_instruction(swp);
107 }
108
android_os_cts_CpuInstructions_hasSetend(JNIEnv *,jobject)109 jboolean android_os_cts_CpuInstructions_hasSetend(JNIEnv *, jobject)
110 {
111 return test_instruction(setend);
112 }
113
android_os_cts_CpuInstructions_hasCp15Barriers(JNIEnv *,jobject)114 jboolean android_os_cts_CpuInstructions_hasCp15Barriers(JNIEnv *, jobject)
115 {
116 return test_instruction(cp15_dsb);
117 }
118 #else
android_os_cts_CpuInstructions_hasSwp(JNIEnv *,jobject)119 jboolean android_os_cts_CpuInstructions_hasSwp(JNIEnv *, jobject)
120 {
121 return false;
122 }
123
android_os_cts_CpuInstructions_hasSetend(JNIEnv *,jobject)124 jboolean android_os_cts_CpuInstructions_hasSetend(JNIEnv *, jobject)
125 {
126 return false;
127 }
128
android_os_cts_CpuInstructions_hasCp15Barriers(JNIEnv *,jobject)129 jboolean android_os_cts_CpuInstructions_hasCp15Barriers(JNIEnv *, jobject)
130 {
131 return false;
132 }
133 #endif
134
135 static JNINativeMethod gMethods[] = {
136 { "canReadCntvct", "()Z", (void *)android_os_cts_CpuInstructions_canReadCntvct },
137 { "hasSwp", "()Z", (void *)android_os_cts_CpuInstructions_hasSwp },
138 { "hasSetend", "()Z", (void *)android_os_cts_CpuInstructions_hasSetend },
139 { "hasCp15Barriers", "()Z",
140 (void *)android_os_cts_CpuInstructions_hasCp15Barriers },
141 };
142
register_android_os_cts_CpuInstructions(JNIEnv * env)143 int register_android_os_cts_CpuInstructions(JNIEnv *env)
144 {
145 jclass clazz = env->FindClass("android/os/cts/CpuInstructions");
146
147 return env->RegisterNatives(clazz, gMethods,
148 sizeof(gMethods) / sizeof(JNINativeMethod));
149 }
150