Home | History | Annotate | Download | only in jni
      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 
     26 static void sigill_handler(int signum __attribute__((unused)))
     27 {
     28     siglongjmp(jmpenv, 1);
     29 }
     30 
     31 static int do_sigsetjmp()
     32 {
     33     return sigsetjmp(jmpenv, 1);
     34 }
     35 
     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__
     67 static void cntvct()
     68 {
     69     asm volatile ( "mrs x0, cntvct_el0" : : : "x0" );
     70 }
     71 
     72 jboolean android_os_cts_CpuInstructions_canReadCntvct(JNIEnv *, jobject)
     73 {
     74     return test_instruction(cntvct);
     75 }
     76 #else
     77 jboolean android_os_cts_CpuInstructions_canReadCntvct(JNIEnv *, jobject)
     78 {
     79     return false;
     80 }
     81 #endif
     82 
     83 #ifdef __arm__
     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 
     91 static void setend()
     92 {
     93     asm volatile (
     94         "setend be" "\n"
     95         "setend le" "\n"
     96     );
     97 }
     98 
     99 static void cp15_dsb()
    100 {
    101     asm volatile ( "mcr p15, 0, %0, c7, c10, 4" : : "r"(0) );
    102 }
    103 
    104 jboolean android_os_cts_CpuInstructions_hasSwp(JNIEnv *, jobject)
    105 {
    106     return test_instruction(swp);
    107 }
    108 
    109 jboolean android_os_cts_CpuInstructions_hasSetend(JNIEnv *, jobject)
    110 {
    111     return test_instruction(setend);
    112 }
    113 
    114 jboolean android_os_cts_CpuInstructions_hasCp15Barriers(JNIEnv *, jobject)
    115 {
    116     return test_instruction(cp15_dsb);
    117 }
    118 #else
    119 jboolean android_os_cts_CpuInstructions_hasSwp(JNIEnv *, jobject)
    120 {
    121     return false;
    122 }
    123 
    124 jboolean android_os_cts_CpuInstructions_hasSetend(JNIEnv *, jobject)
    125 {
    126     return false;
    127 }
    128 
    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 
    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