diff options
author | David S. Miller <davem@davemloft.net> | 2012-08-16 16:41:04 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-08-18 23:02:36 -0700 |
commit | 6f859c0e96f0737a543610a189d12420c569110f (patch) | |
tree | a3623aa1d8eb1aa356357ba37197aa2d4aaa9503 /arch/sparc/kernel | |
parent | 6dab7ede9390d4d937cb89feca932e4fd575d2da (diff) | |
download | linux-6f859c0e96f0737a543610a189d12420c569110f.tar.bz2 |
sparc64: Add detection for features new in SPARC-T4.
Compare and branch, pause, and the various new cryptographic opcodes.
We advertise the crypto opcodes to userspace using one hwcap bit,
HWCAP_SPARC_CRYPTO.
This essentially indicates that the %cfr register can be interrograted
and used to determine exactly which crypto opcodes are available on
the current cpu.
We use the %cfr register to report all of the crypto opcodes available
in the bootup CPU caps log message, and via /proc/cpuinfo.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel')
-rw-r--r-- | arch/sparc/kernel/setup_64.c | 67 |
1 files changed, 55 insertions, 12 deletions
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index 1414d16712b2..0800e71d8a88 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c @@ -340,7 +340,12 @@ static const char *hwcaps[] = { */ "mul32", "div32", "fsmuld", "v8plus", "popc", "vis", "vis2", "ASIBlkInit", "fmaf", "vis3", "hpc", "random", "trans", "fjfmau", - "ima", "cspare", + "ima", "cspare", "pause", "cbcond", +}; + +static const char *crypto_hwcaps[] = { + "aes", "des", "kasumi", "camellia", "md5", "sha1", "sha256", + "sha512", "mpmul", "montmul", "montsqr", "crc32c", }; void cpucap_info(struct seq_file *m) @@ -357,27 +362,61 @@ void cpucap_info(struct seq_file *m) printed++; } } + if (caps & HWCAP_SPARC_CRYPTO) { + unsigned long cfr; + + __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr)); + for (i = 0; i < ARRAY_SIZE(crypto_hwcaps); i++) { + unsigned long bit = 1UL << i; + if (cfr & bit) { + seq_printf(m, "%s%s", + printed ? "," : "", crypto_hwcaps[i]); + printed++; + } + } + } seq_putc(m, '\n'); } +static void __init report_one_hwcap(int *printed, const char *name) +{ + if ((*printed) == 0) + printk(KERN_INFO "CPU CAPS: ["); + printk(KERN_CONT "%s%s", + (*printed) ? "," : "", name); + if (++(*printed) == 8) { + printk(KERN_CONT "]\n"); + *printed = 0; + } +} + +static void __init report_crypto_hwcaps(int *printed) +{ + unsigned long cfr; + int i; + + __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr)); + + for (i = 0; i < ARRAY_SIZE(crypto_hwcaps); i++) { + unsigned long bit = 1UL << i; + if (cfr & bit) + report_one_hwcap(printed, crypto_hwcaps[i]); + } +} + static void __init report_hwcaps(unsigned long caps) { int i, printed = 0; - printk(KERN_INFO "CPU CAPS: ["); for (i = 0; i < ARRAY_SIZE(hwcaps); i++) { unsigned long bit = 1UL << i; - if (caps & bit) { - printk(KERN_CONT "%s%s", - printed ? "," : "", hwcaps[i]); - if (++printed == 8) { - printk(KERN_CONT "]\n"); - printk(KERN_INFO "CPU CAPS: ["); - printed = 0; - } - } + if (caps & bit) + report_one_hwcap(&printed, hwcaps[i]); } - printk(KERN_CONT "]\n"); + if (caps & HWCAP_SPARC_CRYPTO) + report_crypto_hwcaps(&printed); + if (printed != 0) + printk(KERN_CONT "]\n"); } static unsigned long __init mdesc_cpu_hwcap_list(void) @@ -411,6 +450,10 @@ static unsigned long __init mdesc_cpu_hwcap_list(void) break; } } + for (i = 0; i < ARRAY_SIZE(crypto_hwcaps); i++) { + if (!strcmp(prop, crypto_hwcaps[i])) + caps |= HWCAP_SPARC_CRYPTO; + } plen = strlen(prop) + 1; prop += plen; |