blob: ecdb399afbf7ad3296c327e5ea95b2eb046ff457 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.os.cts;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.os.cts.CpuFeatures;
import junit.framework.TestCase;
public class CpuFeaturesTest extends TestCase {
private static void assertHwCap(String name, int hwcaps, int flag) {
assertEquals("Machine does not advertise " + name + " support", flag,
hwcaps & flag);
}
public void testArm64RequiredHwCaps() {
if (!CpuFeatures.isArm64CpuIn32BitMode()) {
return;
}
int hwcaps = CpuFeatures.getHwCaps();
assertFalse("Machine does not support getauxval(AT_HWCAP)",
hwcaps == 0);
assertHwCap("VFP", hwcaps, CpuFeatures.HWCAP_VFP);
assertHwCap("NEON", hwcaps, CpuFeatures.HWCAP_NEON);
assertHwCap("VFPv3", hwcaps, CpuFeatures.HWCAP_VFPv3);
assertHwCap("VFPv4", hwcaps, CpuFeatures.HWCAP_VFPv4);
assertHwCap("IDIVA", hwcaps, CpuFeatures.HWCAP_IDIVA);
assertHwCap("IDIVT", hwcaps, CpuFeatures.HWCAP_IDIVT);
}
private static String getFieldFromCpuinfo(String field) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("/proc/cpuinfo"));
Pattern p = Pattern.compile(field + "\\s*:\\s*(.*)");
try {
String line;
while ((line = br.readLine()) != null) {
Matcher m = p.matcher(line);
if (m.matches()) {
return m.group(1);
}
}
} finally {
br.close();
}
return null;
}
private static List<String> getFeaturesFromCpuinfo() throws IOException {
String features = getFieldFromCpuinfo("Features");
if (features == null)
return null;
return Arrays.asList(features.split("\\s"));
}
private static final String[] armv8RequiredFeatures = {
"half", "thumb", "fastmult", "vfp", "edsp", "neon",
"vfpv3", "tlsi", "vfpv4", "idiva", "idivt" };
private static void assertInCpuinfo(List<String> features,
String feature) {
assertTrue("/proc/cpuinfo does not advertise required feature " + feature + " to 32-bit ARM processes",
features.contains(feature));
}
private static void assertNotInCpuinfo(List<String> features,
String feature) {
assertFalse("/proc/cpuinfo advertises required feature " + feature + " to 64-bit ARM processes",
features.contains(feature));
}
public void testArmCpuinfo() throws IOException {
if (!CpuFeatures.isArmCpu())
return;
String cpuArch = getFieldFromCpuinfo("CPU architecture");
/* When /proc/cpuinfo is read by 32-bit ARM processes, the CPU
* architecture field must be present and contain an integer.
*/
assertNotNull("Failed to read CPU architecture field from /proc/cpuinfo",
cpuArch);
int cpuArchInt = 0;
try {
cpuArchInt = Integer.parseInt(cpuArch);
} catch (NumberFormatException e) {
fail("/proc/cpuinfo reported non-integer CPU architecture " + cpuArch);
}
if (CpuFeatures.isArm64CpuIn32BitMode()) {
assertTrue("/proc/cpuinfo reported 32-bit only CPU architecture " + cpuArchInt + " on ARM64 CPU",
cpuArchInt >= 8);
}
List<String> features = getFeaturesFromCpuinfo();
/* When /proc/cpuinfo is read by 32-bit ARM processes, the Features
* field must be present. On ARMv8+ devices specifically, it must
* include ARMv7-optional features that are now required by ARMv8.
*/
assertNotNull("Failed to read Features field from /proc/cpuinfo",
features);
if (CpuFeatures.isArm64CpuIn32BitMode()) {
for (String feature : armv8RequiredFeatures) {
assertInCpuinfo(features, feature);
}
}
}
public void testArm64Cpuinfo() throws IOException {
if (!CpuFeatures.isArm64Cpu()) {
return;
}
List<String> features = getFeaturesFromCpuinfo();
/* When /proc/cpuinfo is read by 64-bit ARM processes, the Features
* field in /proc/cpuinfo must not include ARMv8-required features.
* This can be satisified either by not listing required features, or by
* not having a Features field at all.
*/
if (features == null) {
return;
}
for (String feature : armv8RequiredFeatures) {
assertNotInCpuinfo(features, feature);
}
}
}