From a1cedadf73863ff103fecd64fa188334e1541337 Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Thu, 22 Apr 2021 14:41:27 +0100 Subject: [PATCH] feat(hw_crc): add support for HW computed CRC Added support for HW computed CRC using Arm ACLE intrinsics. These are built-in intrinsics available for ARMv8.1-A, and onwards. These intrinsics are enabled via '-march=armv8-a+crc' compile switch for ARMv8-A (supports CRC instructions optionally). HW CRC support is enabled unconditionally in BL2 for all Arm platforms. HW CRC calculation is verified offline to ensure a similar result as its respective ZLib utility function. HW CRC calculation support will be used in the upcoming firmware update patches. Change-Id: Ia2ae801f62d2003e89a9c3e6d77469b5312614b3 Signed-off-by: Manish V Badarkhe --- common/hw_crc32.c | 44 +++++++++++++++++++++++++++++++++++ include/common/hw_crc32.h | 16 +++++++++++++ include/lib/libc/arm_acle.h | 2 ++ plat/arm/common/arm_common.mk | 8 +++++++ 4 files changed, 70 insertions(+) create mode 100644 common/hw_crc32.c create mode 100644 include/common/hw_crc32.h diff --git a/common/hw_crc32.c b/common/hw_crc32.c new file mode 100644 index 000000000..a8731da17 --- /dev/null +++ b/common/hw_crc32.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +/* hw_crc32 - compute CRC using Arm intrinsic function + * + * This function is useful for the platforms with the CPU ARMv8.0 + * (with CRC instructions supported), and onwards. + * Platforms with CPU ARMv8.0 should make sure to add a compile switch + * '-march=armv8-a+crc" for successful compilation of this file. + * + * @crc: previous accumulated CRC + * @buf: buffer base address + * @size: the size of the buffer + * + * Return calculated CRC value + */ +uint32_t hw_crc32(uint32_t crc, const unsigned char *buf, size_t size) +{ + assert(buf != NULL); + + uint32_t calc_crc = ~crc; + const unsigned char *local_buf = buf; + size_t local_size = size; + + /* + * calculate CRC over byte data + */ + while (local_size != 0UL) { + calc_crc = __crc32b(calc_crc, *local_buf); + local_buf++; + local_size--; + } + + return ~calc_crc; +} diff --git a/include/common/hw_crc32.h b/include/common/hw_crc32.h new file mode 100644 index 000000000..0d14d5739 --- /dev/null +++ b/include/common/hw_crc32.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HW_CRC32_H +#define HW_CRC32_H + +#include +#include + +/* compute CRC using Arm intrinsic function */ +uint32_t hw_crc32(uint32_t crc, const unsigned char *buf, size_t size); + +#endif /* HW_CRC32_H */ diff --git a/include/lib/libc/arm_acle.h b/include/lib/libc/arm_acle.h index 953933f1d..eb08552db 100644 --- a/include/lib/libc/arm_acle.h +++ b/include/lib/libc/arm_acle.h @@ -14,8 +14,10 @@ #define ARM_ACLE_H #if !defined(__aarch64__) || defined(__clang__) +# define __crc32b __builtin_arm_crc32b # define __crc32w __builtin_arm_crc32w #else +# define __crc32b __builtin_aarch64_crc32b # define __crc32w __builtin_aarch64_crc32w #endif diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk index fff129489..5faf9f907 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -178,6 +178,13 @@ ifeq (${ARM_GPT_SUPPORT}, 1) drivers/partition/partition.c endif +# Enable CRC instructions via extension for ARMv8-A CPUs. +# For ARMv8.1-A, and onwards CRC instructions are default enabled. +# Enable HW computed CRC support unconditionally in BL2 component. +ifeq (${ARM_ARCH_MINOR},0) + BL2_CPPFLAGS += -march=armv8-a+crc +endif + ifeq (${ARCH}, aarch64) PLAT_INCLUDES += -Iinclude/plat/arm/common/aarch64 endif @@ -223,6 +230,7 @@ BL2_SOURCES += drivers/delay_timer/delay_timer.c \ drivers/io/io_storage.c \ plat/arm/common/arm_bl2_setup.c \ plat/arm/common/arm_err.c \ + common/hw_crc32.c \ ${ARM_IO_SOURCES} # Firmware Configuration Framework sources -- GitLab