[aarch64-port-dev ] RFR: Add support for A53 multiply accumulate feature
Edward Nevill
edward.nevill at gmail.com
Tue Dec 2 09:24:31 UTC 2014
Hi,
The following patch adds support for the A53 multiply accumulate feature.
Because the MIDR and REVIDR registers cannot be read at EL0 it parses /proc/cpuinfo to determine whether we might be running on an A53.
One added complication is that even if we are running on an A57 we might at some stage end up on an A53 because we might be part of a BIGlittle system. If you repeatedly cat /proc/cpuinfo on a BIGlittle system you will see the CPU part alternate between 0xd03 (A53) and 0xd07 (A57) depending on which core it just happens to run on when executing the 'cat' command. This is fixed on kernels from 3.19 onwards where it reports the part type on a per core basis rather than one overall part type. In these case we are able to determine that there are both A53 and A57 cores present. However, on pre 3.19 kernels we just use the 'Hardware' field to determine whether it is BIGlittle or not.
OK to push?
Ed.
--- CUT HERE ---
# HG changeset patch
# User enevill
# Date 1417511121 0
# Tue Dec 02 09:05:21 2014 +0000
# Node ID 13aa80e97e9a3d45211772b56b0ef901b8396a07
# Parent f9a67c52dc334a714139dddd36ecc647aacedc0d
Add support for A53 multiply accumulate feature
diff -r f9a67c52dc33 -r 13aa80e97e9a src/cpu/aarch64/vm/aarch64.ad
--- a/src/cpu/aarch64/vm/aarch64.ad Wed Nov 26 15:20:42 2014 +0000
+++ b/src/cpu/aarch64/vm/aarch64.ad Tue Dec 02 09:05:21 2014 +0000
@@ -7911,6 +7911,8 @@
format %{ "madd $dst, $src1, $src2, $src3" %}
ins_encode %{
+ if (VM_Version::cpu_cpuFeatures() & VM_Version::CPU_A53MAC)
+ __ nop();
__ maddw(as_Register($dst$$reg),
as_Register($src1$$reg),
as_Register($src2$$reg),
@@ -7927,6 +7929,8 @@
format %{ "msub $dst, $src1, $src2, $src3" %}
ins_encode %{
+ if (VM_Version::cpu_cpuFeatures() & VM_Version::CPU_A53MAC)
+ __ nop();
__ msubw(as_Register($dst$$reg),
as_Register($src1$$reg),
as_Register($src2$$reg),
@@ -7945,6 +7949,8 @@
format %{ "madd $dst, $src1, $src2, $src3" %}
ins_encode %{
+ if (VM_Version::cpu_cpuFeatures() & VM_Version::CPU_A53MAC)
+ __ nop();
__ madd(as_Register($dst$$reg),
as_Register($src1$$reg),
as_Register($src2$$reg),
@@ -7961,6 +7967,8 @@
format %{ "msub $dst, $src1, $src2, $src3" %}
ins_encode %{
+ if (VM_Version::cpu_cpuFeatures() & VM_Version::CPU_A53MAC)
+ __ nop();
__ msub(as_Register($dst$$reg),
as_Register($src1$$reg),
as_Register($src2$$reg),
diff -r f9a67c52dc33 -r 13aa80e97e9a src/cpu/aarch64/vm/vm_version_aarch64.cpp
--- a/src/cpu/aarch64/vm/vm_version_aarch64.cpp Wed Nov 26 15:20:42 2014 +0000
+++ b/src/cpu/aarch64/vm/vm_version_aarch64.cpp Tue Dec 02 09:05:21 2014 +0000
@@ -60,6 +60,7 @@
int VM_Version::_cpu;
int VM_Version::_model;
+int VM_Version::_revision;
int VM_Version::_stepping;
int VM_Version::_cpuFeatures;
const char* VM_Version::_features_str = "";
@@ -130,6 +131,67 @@
if (auxv & HWCAP_SHA2) strcat(buf, ", sha256");
_features_str = strdup(buf);
+ _cpuFeatures = auxv;
+
+#define IMPLEMENTER "CPU implementer"
+#define PART "CPU part"
+#define REVISION "CPU revision"
+#define HARDWARE "Hardware"
+#define JUNO "Juno"
+#define CPUINFO_BUFSIZE 256
+#define LINE_BUFSIZE 40
+ int fd = open("/proc/cpuinfo", O_RDONLY);
+ if (fd >= 0) {
+ char line[LINE_BUFSIZE];
+ char fbuf[CPUINFO_BUFSIZE], *bp;
+ int line_idx = 0;
+ int n;
+ do {
+ n = read(fd, fbuf, CPUINFO_BUFSIZE);
+ for (int i = 0; i < n; i++) {
+ char c = fbuf[i];
+ if (c == '\n') {
+ char *lp = line;
+ line[line_idx] = 0;
+ while ((c = *lp++) != 0) {
+ if (c == ':') {
+ if (*lp++ == ' ') {
+ if (strncmp(line, HARDWARE, (sizeof HARDWARE)-1) == 0) {
+ if (strncmp(lp, JUNO, sizeof(JUNO)-1) == 0)
+ _cpuFeatures |= CPU_BIGLITTLE;
+ } else if (isdigit(*lp)) {
+ int v = 0;
+ if (lp[0] == '0' && lp[1] == 'x' && isxdigit(lp[2])) {
+ lp += 2;
+ while (isxdigit(c = *lp++))
+ v = v * 16 + (isdigit(c) ? (c-'0') : (toupper(c)-'A'+10));
+ } else {
+ while (isdigit(c = *lp++))
+ v = v * 10 + c-'0';
+ }
+ if (strncmp(line, IMPLEMENTER, (sizeof IMPLEMENTER)-1) == 0)
+ _cpu = v;
+ else if (strncmp(line, PART, (sizeof PART)-1) == 0) {
+ if (_model && _model != v)
+ _cpuFeatures |= CPU_BIGLITTLE;
+ _model = v;
+ } else if (strncmp(line, REVISION, (sizeof REVISION)-1) == 0)
+ _revision = v;
+ }
+ break;
+ }
+ }
+ }
+ line_idx = 0;
+ } else if (line_idx < LINE_BUFSIZE-1)
+ line[line_idx++] = fbuf[i];
+ }
+ } while (n == CPUINFO_BUFSIZE);
+ close(fd);
+ }
+ if (_cpu == CPU_ARM && (_model == CPU_A53 || (_cpuFeatures & CPU_BIGLITTLE &&
+ _model == CPU_A57)) && _revision == 0)
+ _cpuFeatures |= CPU_A53MAC;
if (FLAG_IS_DEFAULT(UseCRC32)) {
UseCRC32 = (auxv & HWCAP_CRC32) != 0;
diff -r f9a67c52dc33 -r 13aa80e97e9a src/cpu/aarch64/vm/vm_version_aarch64.hpp
--- a/src/cpu/aarch64/vm/vm_version_aarch64.hpp Wed Nov 26 15:20:42 2014 +0000
+++ b/src/cpu/aarch64/vm/vm_version_aarch64.hpp Tue Dec 02 09:05:21 2014 +0000
@@ -35,6 +35,7 @@
protected:
static int _cpu;
static int _model;
+ static int _revision;
static int _stepping;
static int _cpuFeatures; // features returned by the "cpuid" instruction
// 0 if this instruction is not available
@@ -50,7 +51,43 @@
static void assert_is_initialized() {
}
+ enum {
+ CPU_ARM = 'A',
+ CPU_BROADCOM = 'B',
+ CPU_CAVIUM = 'C',
+ CPU_DEC = 'D',
+ CPU_INFINEON = 'I',
+ CPU_MOTOTOLA = 'M',
+ CPU_NVIDIA = 'N',
+ CPU_AMCC = 'P',
+ CPU_QUALCOM = 'Q',
+ CPU_MARVELL = 'M',
+ CPU_INTEL = 'i',
+ } cpuFamily;
+
+ enum {
+ CPU_A53 = 0xd03,
+ CPU_A57 = 0xd07,
+ } cpuModel;
+
+ enum {
+ CPU_FP = (1<<0),
+ CPU_ASIMD = (1<<1),
+ CPU_EVTSTRM = (1<<2),
+ CPU_AES = (1<<3),
+ CPU_PMULL = (1<<4),
+ CPU_SHA1 = (1<<5),
+ CPU_SHA2 = (1<<6),
+ CPU_CRC32 = (1<<7),
+ CPU_A53MAC = (1 << 30),
+ CPU_BIGLITTLE= (1 << 31),
+ } cpuFeatureFlags;
+
static const char* cpu_features() { return _features_str; }
+ static int cpu_family() { return _cpu; }
+ static int cpu_model() { return _model; }
+ static int cpu_revision() { return _revision; }
+ static int cpu_cpuFeatures() { return _cpuFeatures; }
};
--- CUT HERE ---
More information about the aarch64-port-dev
mailing list