Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6f859c0e authored by David S. Miller's avatar David S. Miller
Browse files

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: default avatarDavid S. Miller <davem@davemloft.net>
parent 6dab7ede
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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

+14 −0
Original line number Diff line number Diff line
@@ -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) */
+55 −12
Original line number Diff line number Diff line
@@ -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,26 +362,60 @@ 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_hwcaps(unsigned long caps)
static void __init report_one_hwcap(int *printed, const char *name)
{
	int i, printed = 0;

	if ((*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) {
	       (*printed) ? "," : "", name);
	if (++(*printed) == 8) {
		printk(KERN_CONT "]\n");
				printk(KERN_INFO "CPU CAPS: [");
				printed = 0;
		*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;

	for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
		unsigned long bit = 1UL << i;
		if (caps & bit)
			report_one_hwcap(&printed, hwcaps[i]);
	}
	if (caps & HWCAP_SPARC_CRYPTO)
		report_crypto_hwcaps(&printed);
	if (printed != 0)
		printk(KERN_CONT "]\n");
}

@@ -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;