Skip to content

Commit

Permalink
sparc64: Add detection for features new in SPARC-T4.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David S. Miller committed Aug 19, 2012
1 parent 6dab7ed commit 6f859c0
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 12 deletions.
9 changes: 9 additions & 0 deletions arch/sparc/include/asm/elf_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,15 @@
#define AV_SPARC_IMA 0x00400000 /* integer multiply-add */
#define AV_SPARC_ASI_CACHE_SPARING \
0x00800000 /* cache sparing ASIs available */
#define AV_SPARC_PAUSE 0x01000000 /* PAUSE available */
#define AV_SPARC_CBCOND 0x02000000 /* CBCOND insns available */

/* Solaris decided to enumerate every single crypto instruction type
* in the AT_HWCAP bits. This is wasteful, since if crypto is present,
* you still need to look in the CFR register to see if the opcode is
* really available. So we simply advertise only "crypto" support.
*/
#define HWCAP_SPARC_CRYPTO 0x04000000 /* CRYPTO insns available */

#define CORE_DUMP_USE_REGSET

Expand Down
14 changes: 14 additions & 0 deletions arch/sparc/include/asm/pstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,18 @@
#define VERS_MAXTL _AC(0x000000000000ff00,UL) /* Max Trap Level. */
#define VERS_MAXWIN _AC(0x000000000000001f,UL) /* Max RegWindow Idx.*/

/* Compatability Feature Register (%asr26), SPARC-T4 and later */
#define CFR_AES _AC(0x0000000000000001,UL) /* Supports AES opcodes */
#define CFR_DES _AC(0x0000000000000002,UL) /* Supports DES opcodes */
#define CFR_KASUMI _AC(0x0000000000000004,UL) /* Supports KASUMI opcodes */
#define CFR_CAMELIA _AC(0x0000000000000008,UL) /* Supports CAMELIA opcodes */
#define CFR_MD5 _AC(0x0000000000000010,UL) /* Supports MD5 opcodes */
#define CFR_SHA1 _AC(0x0000000000000020,UL) /* Supports SHA1 opcodes */
#define CFR_SHA256 _AC(0x0000000000000040,UL) /* Supports SHA256 opcodes */
#define CFR_SHA512 _AC(0x0000000000000080,UL) /* Supports SHA512 opcodes */
#define CFR_MPMUL _AC(0x0000000000000100,UL) /* Supports MPMUL opcodes */
#define CFR_MONTMUL _AC(0x0000000000000200,UL) /* Supports MONTMUL opcodes */
#define CFR_MONTSQR _AC(0x0000000000000400,UL) /* Supports MONTSQR opcodes */
#define CFR_CRC32C _AC(0x0000000000000800,UL) /* Supports CRC32C opcodes */

#endif /* !(_SPARC64_PSTATE_H) */
67 changes: 55 additions & 12 deletions arch/sparc/kernel/setup_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 6f859c0

Please sign in to comment.