mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-09 10:34:58 -06:00
host/include/aarch64: Implement aes-round.h
Detect AES in cpuinfo; implement the accel hooks. Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
d6a2443696
commit
8d97f28e36
4 changed files with 217 additions and 0 deletions
|
@ -9,6 +9,7 @@
|
||||||
#define CPUINFO_ALWAYS (1u << 0) /* so cpuinfo is nonzero */
|
#define CPUINFO_ALWAYS (1u << 0) /* so cpuinfo is nonzero */
|
||||||
#define CPUINFO_LSE (1u << 1)
|
#define CPUINFO_LSE (1u << 1)
|
||||||
#define CPUINFO_LSE2 (1u << 2)
|
#define CPUINFO_LSE2 (1u << 2)
|
||||||
|
#define CPUINFO_AES (1u << 3)
|
||||||
|
|
||||||
/* Initialized with a constructor. */
|
/* Initialized with a constructor. */
|
||||||
extern unsigned cpuinfo;
|
extern unsigned cpuinfo;
|
||||||
|
|
205
host/include/aarch64/host/crypto/aes-round.h
Normal file
205
host/include/aarch64/host/crypto/aes-round.h
Normal file
|
@ -0,0 +1,205 @@
|
||||||
|
/*
|
||||||
|
* AArch64 specific aes acceleration.
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AARCH64_HOST_CRYPTO_AES_ROUND_H
|
||||||
|
#define AARCH64_HOST_CRYPTO_AES_ROUND_H
|
||||||
|
|
||||||
|
#include "host/cpuinfo.h"
|
||||||
|
#include <arm_neon.h>
|
||||||
|
|
||||||
|
#ifdef __ARM_FEATURE_AES
|
||||||
|
# define HAVE_AES_ACCEL true
|
||||||
|
#else
|
||||||
|
# define HAVE_AES_ACCEL likely(cpuinfo & CPUINFO_AES)
|
||||||
|
#endif
|
||||||
|
#if !defined(__ARM_FEATURE_AES) && defined(CONFIG_ARM_AES_BUILTIN)
|
||||||
|
# define ATTR_AES_ACCEL __attribute__((target("+crypto")))
|
||||||
|
#else
|
||||||
|
# define ATTR_AES_ACCEL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline uint8x16_t aes_accel_bswap(uint8x16_t x)
|
||||||
|
{
|
||||||
|
return vqtbl1q_u8(x, (uint8x16_t){ 15, 14, 13, 12, 11, 10, 9, 8,
|
||||||
|
7, 6, 5, 4, 3, 2, 1, 0, });
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARM_AES_BUILTIN
|
||||||
|
# define aes_accel_aesd vaesdq_u8
|
||||||
|
# define aes_accel_aese vaeseq_u8
|
||||||
|
# define aes_accel_aesmc vaesmcq_u8
|
||||||
|
# define aes_accel_aesimc vaesimcq_u8
|
||||||
|
# define aes_accel_aesd_imc(S, K) vaesimcq_u8(vaesdq_u8(S, K))
|
||||||
|
# define aes_accel_aese_mc(S, K) vaesmcq_u8(vaeseq_u8(S, K))
|
||||||
|
#else
|
||||||
|
static inline uint8x16_t aes_accel_aesd(uint8x16_t d, uint8x16_t k)
|
||||||
|
{
|
||||||
|
asm(".arch_extension aes\n\t"
|
||||||
|
"aesd %0.16b, %1.16b" : "+w"(d) : "w"(k));
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8x16_t aes_accel_aese(uint8x16_t d, uint8x16_t k)
|
||||||
|
{
|
||||||
|
asm(".arch_extension aes\n\t"
|
||||||
|
"aese %0.16b, %1.16b" : "+w"(d) : "w"(k));
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8x16_t aes_accel_aesmc(uint8x16_t d)
|
||||||
|
{
|
||||||
|
asm(".arch_extension aes\n\t"
|
||||||
|
"aesmc %0.16b, %1.16b" : "=w"(d) : "w"(d));
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8x16_t aes_accel_aesimc(uint8x16_t d)
|
||||||
|
{
|
||||||
|
asm(".arch_extension aes\n\t"
|
||||||
|
"aesimc %0.16b, %1.16b" : "=w"(d) : "w"(d));
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Most CPUs fuse AESD+AESIMC in the execution pipeline. */
|
||||||
|
static inline uint8x16_t aes_accel_aesd_imc(uint8x16_t d, uint8x16_t k)
|
||||||
|
{
|
||||||
|
asm(".arch_extension aes\n\t"
|
||||||
|
"aesd %0.16b, %1.16b\n\t"
|
||||||
|
"aesimc %0.16b, %0.16b" : "+w"(d) : "w"(k));
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Most CPUs fuse AESE+AESMC in the execution pipeline. */
|
||||||
|
static inline uint8x16_t aes_accel_aese_mc(uint8x16_t d, uint8x16_t k)
|
||||||
|
{
|
||||||
|
asm(".arch_extension aes\n\t"
|
||||||
|
"aese %0.16b, %1.16b\n\t"
|
||||||
|
"aesmc %0.16b, %0.16b" : "+w"(d) : "w"(k));
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_ARM_AES_BUILTIN */
|
||||||
|
|
||||||
|
static inline void ATTR_AES_ACCEL
|
||||||
|
aesenc_MC_accel(AESState *ret, const AESState *st, bool be)
|
||||||
|
{
|
||||||
|
uint8x16_t t = (uint8x16_t)st->v;
|
||||||
|
|
||||||
|
if (be) {
|
||||||
|
t = aes_accel_bswap(t);
|
||||||
|
t = aes_accel_aesmc(t);
|
||||||
|
t = aes_accel_bswap(t);
|
||||||
|
} else {
|
||||||
|
t = aes_accel_aesmc(t);
|
||||||
|
}
|
||||||
|
ret->v = (AESStateVec)t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ATTR_AES_ACCEL
|
||||||
|
aesenc_SB_SR_AK_accel(AESState *ret, const AESState *st,
|
||||||
|
const AESState *rk, bool be)
|
||||||
|
{
|
||||||
|
uint8x16_t t = (uint8x16_t)st->v;
|
||||||
|
uint8x16_t z = { };
|
||||||
|
|
||||||
|
if (be) {
|
||||||
|
t = aes_accel_bswap(t);
|
||||||
|
t = aes_accel_aese(t, z);
|
||||||
|
t = aes_accel_bswap(t);
|
||||||
|
} else {
|
||||||
|
t = aes_accel_aese(t, z);
|
||||||
|
}
|
||||||
|
ret->v = (AESStateVec)t ^ rk->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ATTR_AES_ACCEL
|
||||||
|
aesenc_SB_SR_MC_AK_accel(AESState *ret, const AESState *st,
|
||||||
|
const AESState *rk, bool be)
|
||||||
|
{
|
||||||
|
uint8x16_t t = (uint8x16_t)st->v;
|
||||||
|
uint8x16_t z = { };
|
||||||
|
|
||||||
|
if (be) {
|
||||||
|
t = aes_accel_bswap(t);
|
||||||
|
t = aes_accel_aese_mc(t, z);
|
||||||
|
t = aes_accel_bswap(t);
|
||||||
|
} else {
|
||||||
|
t = aes_accel_aese_mc(t, z);
|
||||||
|
}
|
||||||
|
ret->v = (AESStateVec)t ^ rk->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ATTR_AES_ACCEL
|
||||||
|
aesdec_IMC_accel(AESState *ret, const AESState *st, bool be)
|
||||||
|
{
|
||||||
|
uint8x16_t t = (uint8x16_t)st->v;
|
||||||
|
|
||||||
|
if (be) {
|
||||||
|
t = aes_accel_bswap(t);
|
||||||
|
t = aes_accel_aesimc(t);
|
||||||
|
t = aes_accel_bswap(t);
|
||||||
|
} else {
|
||||||
|
t = aes_accel_aesimc(t);
|
||||||
|
}
|
||||||
|
ret->v = (AESStateVec)t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ATTR_AES_ACCEL
|
||||||
|
aesdec_ISB_ISR_AK_accel(AESState *ret, const AESState *st,
|
||||||
|
const AESState *rk, bool be)
|
||||||
|
{
|
||||||
|
uint8x16_t t = (uint8x16_t)st->v;
|
||||||
|
uint8x16_t z = { };
|
||||||
|
|
||||||
|
if (be) {
|
||||||
|
t = aes_accel_bswap(t);
|
||||||
|
t = aes_accel_aesd(t, z);
|
||||||
|
t = aes_accel_bswap(t);
|
||||||
|
} else {
|
||||||
|
t = aes_accel_aesd(t, z);
|
||||||
|
}
|
||||||
|
ret->v = (AESStateVec)t ^ rk->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ATTR_AES_ACCEL
|
||||||
|
aesdec_ISB_ISR_AK_IMC_accel(AESState *ret, const AESState *st,
|
||||||
|
const AESState *rk, bool be)
|
||||||
|
{
|
||||||
|
uint8x16_t t = (uint8x16_t)st->v;
|
||||||
|
uint8x16_t k = (uint8x16_t)rk->v;
|
||||||
|
uint8x16_t z = { };
|
||||||
|
|
||||||
|
if (be) {
|
||||||
|
t = aes_accel_bswap(t);
|
||||||
|
k = aes_accel_bswap(k);
|
||||||
|
t = aes_accel_aesd(t, z);
|
||||||
|
t ^= k;
|
||||||
|
t = aes_accel_aesimc(t);
|
||||||
|
t = aes_accel_bswap(t);
|
||||||
|
} else {
|
||||||
|
t = aes_accel_aesd(t, z);
|
||||||
|
t ^= k;
|
||||||
|
t = aes_accel_aesimc(t);
|
||||||
|
}
|
||||||
|
ret->v = (AESStateVec)t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ATTR_AES_ACCEL
|
||||||
|
aesdec_ISB_ISR_IMC_AK_accel(AESState *ret, const AESState *st,
|
||||||
|
const AESState *rk, bool be)
|
||||||
|
{
|
||||||
|
uint8x16_t t = (uint8x16_t)st->v;
|
||||||
|
uint8x16_t z = { };
|
||||||
|
|
||||||
|
if (be) {
|
||||||
|
t = aes_accel_bswap(t);
|
||||||
|
t = aes_accel_aesd_imc(t, z);
|
||||||
|
t = aes_accel_bswap(t);
|
||||||
|
} else {
|
||||||
|
t = aes_accel_aesd_imc(t, z);
|
||||||
|
}
|
||||||
|
ret->v = (AESStateVec)t ^ rk->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* AARCH64_HOST_CRYPTO_AES_ROUND_H */
|
|
@ -2665,6 +2665,15 @@ config_host_data.set('CONFIG_AVX512BW_OPT', get_option('avx512bw') \
|
||||||
int main(int argc, char *argv[]) { return bar(argv[0]); }
|
int main(int argc, char *argv[]) { return bar(argv[0]); }
|
||||||
'''), error_message: 'AVX512BW not available').allowed())
|
'''), error_message: 'AVX512BW not available').allowed())
|
||||||
|
|
||||||
|
# For both AArch64 and AArch32, detect if builtins are available.
|
||||||
|
config_host_data.set('CONFIG_ARM_AES_BUILTIN', cc.compiles('''
|
||||||
|
#include <arm_neon.h>
|
||||||
|
#ifndef __ARM_FEATURE_AES
|
||||||
|
__attribute__((target("+crypto")))
|
||||||
|
#endif
|
||||||
|
void foo(uint8x16_t *p) { *p = vaesmcq_u8(*p); }
|
||||||
|
'''))
|
||||||
|
|
||||||
have_pvrdma = get_option('pvrdma') \
|
have_pvrdma = get_option('pvrdma') \
|
||||||
.require(rdma.found(), error_message: 'PVRDMA requires OpenFabrics libraries') \
|
.require(rdma.found(), error_message: 'PVRDMA requires OpenFabrics libraries') \
|
||||||
.require(cc.compiles(gnu_source_prefix + '''
|
.require(cc.compiles(gnu_source_prefix + '''
|
||||||
|
|
|
@ -56,10 +56,12 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
|
||||||
unsigned long hwcap = qemu_getauxval(AT_HWCAP);
|
unsigned long hwcap = qemu_getauxval(AT_HWCAP);
|
||||||
info |= (hwcap & HWCAP_ATOMICS ? CPUINFO_LSE : 0);
|
info |= (hwcap & HWCAP_ATOMICS ? CPUINFO_LSE : 0);
|
||||||
info |= (hwcap & HWCAP_USCAT ? CPUINFO_LSE2 : 0);
|
info |= (hwcap & HWCAP_USCAT ? CPUINFO_LSE2 : 0);
|
||||||
|
info |= (hwcap & HWCAP_AES ? CPUINFO_AES: 0);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_DARWIN
|
#ifdef CONFIG_DARWIN
|
||||||
info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE") * CPUINFO_LSE;
|
info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE") * CPUINFO_LSE;
|
||||||
info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE2") * CPUINFO_LSE2;
|
info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE2") * CPUINFO_LSE2;
|
||||||
|
info |= sysctl_for_bool("hw.optional.arm.FEAT_AES") * CPUINFO_AES;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cpuinfo = info;
|
cpuinfo = info;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue