[PATCH] arm64: Generate cpucaps.h

dann frazier dann.frazier at canonical.com
Tue Sep 21 11:08:11 PDT 2021


On Wed, Apr 28, 2021 at 01:12:31PM +0100, Mark Brown wrote:
> The arm64 code allocates an internal constant to every CPU feature it can
> detect, distinct from the public hwcap numbers we use to expose some
> features to userspace. Currently this is maintained manually which is an
> irritating source of conflicts when working on new features, to avoid this
> replace the header with a simple text file listing the names we've assigned
> and sort it to minimise conflicts.

Thanks for doing this Mark, speaking as someone who has had to
backport a lot of these patches to a distro kernel :)

> As part of doing this we also do the Kbuild hookup required to hook up
> an arch tools directory and to generate header files in there.
> 
> This will result in a renumbering and reordering of the existing constants,
> since they are all internal only the values should not be important. The
> reordering will impact the order in which some steps in enumeration handle
> features but the algorithm is not intended to depend on this and I haven't
> seen any issues when testing.

Unfortunately I believe I've hit a regression[*] due to such an
ordering dependency. UNMAP_KERNEL_AT_EL0 currently needs to be
processed after WORKAROUND_CAVIUM_27456. ThunderX systems are
incompatible with KPTI, so unmap_kernel_at_el0() bails if
WORKAROUND_CAVIUM_27456 is set. Because of the sorting,
WORKAROUND_CAVIUM_27456 will not yet have been considered when
unmap_kernel_at_el0() checks for it, so the kernel tries to
run w/ KPTI - and quickly falls over.

I've verified that reordering cpucaps to move WORKAROUND_CAVIUM_27456
just above UNMAP_KERNEL_AT_EL0 restores the old behavior. I'm not sure
of the right way to address this - perhaps unmap_kernel_at_el0() could
check cavium_erratum_27456_cpus[] directly instead of keying on the
ARM64_WORKAROUND_CAVIUM_27456 cap?

  -dann

[*] https://bugs.launchpad.net/bugs/1942633

> Due to the UAO cpucap having been removed in
> the past we end up with ARM64_NCAPS being 1 smaller than it was before.
> 
> Signed-off-by: Mark Brown <broonie at kernel.org>
> ---
>  arch/arm64/Makefile              |  3 ++
>  arch/arm64/include/asm/Kbuild    |  2 +
>  arch/arm64/include/asm/cpucaps.h | 74 --------------------------------
>  arch/arm64/tools/Makefile        | 22 ++++++++++
>  arch/arm64/tools/cpucaps         | 65 ++++++++++++++++++++++++++++
>  arch/arm64/tools/gen-cpucaps.awk | 40 +++++++++++++++++
>  6 files changed, 132 insertions(+), 74 deletions(-)
>  delete mode 100644 arch/arm64/include/asm/cpucaps.h
>  create mode 100644 arch/arm64/tools/Makefile
>  create mode 100644 arch/arm64/tools/cpucaps
>  create mode 100755 arch/arm64/tools/gen-cpucaps.awk
> 
> diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
> index 7ef44478560d..b52481f0605d 100644
> --- a/arch/arm64/Makefile
> +++ b/arch/arm64/Makefile
> @@ -175,6 +175,9 @@ vdso_install:
>  	$(if $(CONFIG_COMPAT_VDSO), \
>  		$(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso32 $@)
>  
> +archprepare:
> +	$(Q)$(MAKE) $(build)=arch/arm64/tools kapi
> +
>  # We use MRPROPER_FILES and CLEAN_FILES now
>  archclean:
>  	$(Q)$(MAKE) $(clean)=$(boot)
> diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
> index 73aa25843f65..64202010b700 100644
> --- a/arch/arm64/include/asm/Kbuild
> +++ b/arch/arm64/include/asm/Kbuild
> @@ -4,3 +4,5 @@ generic-y += mcs_spinlock.h
>  generic-y += qrwlock.h
>  generic-y += qspinlock.h
>  generic-y += user.h
> +
> +generated-y += cpucaps.h
> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
> deleted file mode 100644
> index b0c5eda0498f..000000000000
> --- a/arch/arm64/include/asm/cpucaps.h
> +++ /dev/null
> @@ -1,74 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * arch/arm64/include/asm/cpucaps.h
> - *
> - * Copyright (C) 2016 ARM Ltd.
> - */
> -#ifndef __ASM_CPUCAPS_H
> -#define __ASM_CPUCAPS_H
> -
> -#define ARM64_WORKAROUND_CLEAN_CACHE		0
> -#define ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE	1
> -#define ARM64_WORKAROUND_845719			2
> -#define ARM64_HAS_SYSREG_GIC_CPUIF		3
> -#define ARM64_HAS_PAN				4
> -#define ARM64_HAS_LSE_ATOMICS			5
> -#define ARM64_WORKAROUND_CAVIUM_23154		6
> -#define ARM64_WORKAROUND_834220			7
> -#define ARM64_HAS_NO_HW_PREFETCH		8
> -#define ARM64_HAS_VIRT_HOST_EXTN		11
> -#define ARM64_WORKAROUND_CAVIUM_27456		12
> -#define ARM64_HAS_32BIT_EL0			13
> -#define ARM64_SPECTRE_V3A			14
> -#define ARM64_HAS_CNP				15
> -#define ARM64_HAS_NO_FPSIMD			16
> -#define ARM64_WORKAROUND_REPEAT_TLBI		17
> -#define ARM64_WORKAROUND_QCOM_FALKOR_E1003	18
> -#define ARM64_WORKAROUND_858921			19
> -#define ARM64_WORKAROUND_CAVIUM_30115		20
> -#define ARM64_HAS_DCPOP				21
> -#define ARM64_SVE				22
> -#define ARM64_UNMAP_KERNEL_AT_EL0		23
> -#define ARM64_SPECTRE_V2			24
> -#define ARM64_HAS_RAS_EXTN			25
> -#define ARM64_WORKAROUND_843419			26
> -#define ARM64_HAS_CACHE_IDC			27
> -#define ARM64_HAS_CACHE_DIC			28
> -#define ARM64_HW_DBM				29
> -#define ARM64_SPECTRE_V4			30
> -#define ARM64_MISMATCHED_CACHE_TYPE		31
> -#define ARM64_HAS_STAGE2_FWB			32
> -#define ARM64_HAS_CRC32				33
> -#define ARM64_SSBS				34
> -#define ARM64_WORKAROUND_1418040		35
> -#define ARM64_HAS_SB				36
> -#define ARM64_WORKAROUND_SPECULATIVE_AT		37
> -#define ARM64_HAS_ADDRESS_AUTH_ARCH		38
> -#define ARM64_HAS_ADDRESS_AUTH_IMP_DEF		39
> -#define ARM64_HAS_GENERIC_AUTH_ARCH		40
> -#define ARM64_HAS_GENERIC_AUTH_IMP_DEF		41
> -#define ARM64_HAS_IRQ_PRIO_MASKING		42
> -#define ARM64_HAS_DCPODP			43
> -#define ARM64_WORKAROUND_1463225		44
> -#define ARM64_WORKAROUND_CAVIUM_TX2_219_TVM	45
> -#define ARM64_WORKAROUND_CAVIUM_TX2_219_PRFM	46
> -#define ARM64_WORKAROUND_1542419		47
> -#define ARM64_HAS_E0PD				48
> -#define ARM64_HAS_RNG				49
> -#define ARM64_HAS_AMU_EXTN			50
> -#define ARM64_HAS_ADDRESS_AUTH			51
> -#define ARM64_HAS_GENERIC_AUTH			52
> -#define ARM64_HAS_32BIT_EL1			53
> -#define ARM64_BTI				54
> -#define ARM64_HAS_ARMv8_4_TTL			55
> -#define ARM64_HAS_TLB_RANGE			56
> -#define ARM64_MTE				57
> -#define ARM64_WORKAROUND_1508412		58
> -#define ARM64_HAS_LDAPR				59
> -#define ARM64_KVM_PROTECTED_MODE		60
> -#define ARM64_WORKAROUND_NVIDIA_CARMEL_CNP	61
> -#define ARM64_HAS_EPAN				62
> -
> -#define ARM64_NCAPS				63
> -
> -#endif /* __ASM_CPUCAPS_H */
> diff --git a/arch/arm64/tools/Makefile b/arch/arm64/tools/Makefile
> new file mode 100644
> index 000000000000..932b4fe5c768
> --- /dev/null
> +++ b/arch/arm64/tools/Makefile
> @@ -0,0 +1,22 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +gen := arch/$(ARCH)/include/generated
> +kapi := $(gen)/asm
> +
> +kapi-hdrs-y := $(kapi)/cpucaps.h
> +
> +targets += $(addprefix ../../../,$(gen-y) $(kapi-hdrs-y))
> +
> +PHONY += kapi
> +
> +kapi:   $(kapi-hdrs-y) $(gen-y)
> +
> +# Create output directory if not already present
> +_dummy := $(shell [ -d '$(kapi)' ] || mkdir -p '$(kapi)')
> +
> +quiet_cmd_gen_cpucaps = GEN     $@
> +      cmd_gen_cpucaps = mkdir -p $(dir $@) && \
> +                     $(AWK) -f $(filter-out $(PHONY),$^) > $@
> +
> +$(kapi)/cpucaps.h: $(src)/gen-cpucaps.awk $(src)/cpucaps FORCE
> +	$(call if_changed,gen_cpucaps)
> diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
> new file mode 100644
> index 000000000000..21fbdda7086e
> --- /dev/null
> +++ b/arch/arm64/tools/cpucaps
> @@ -0,0 +1,65 @@
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Internal CPU capabilities constants, keep this list sorted
> +
> +BTI
> +HAS_32BIT_EL0
> +HAS_32BIT_EL1
> +HAS_ADDRESS_AUTH
> +HAS_ADDRESS_AUTH_ARCH
> +HAS_ADDRESS_AUTH_IMP_DEF
> +HAS_AMU_EXTN
> +HAS_ARMv8_4_TTL
> +HAS_CACHE_DIC
> +HAS_CACHE_IDC
> +HAS_CNP
> +HAS_CRC32
> +HAS_DCPODP
> +HAS_DCPOP
> +HAS_E0PD
> +HAS_EPAN
> +HAS_GENERIC_AUTH
> +HAS_GENERIC_AUTH_ARCH
> +HAS_GENERIC_AUTH_IMP_DEF
> +HAS_IRQ_PRIO_MASKING
> +HAS_LDAPR
> +HAS_LSE_ATOMICS
> +HAS_NO_FPSIMD
> +HAS_NO_HW_PREFETCH
> +HAS_PAN
> +HAS_RAS_EXTN
> +HAS_RNG
> +HAS_SB
> +HAS_STAGE2_FWB
> +HAS_SYSREG_GIC_CPUIF
> +HAS_TLB_RANGE
> +HAS_VIRT_HOST_EXTN
> +HW_DBM
> +KVM_PROTECTED_MODE
> +MISMATCHED_CACHE_TYPE
> +MTE
> +SPECTRE_V2
> +SPECTRE_V3A
> +SPECTRE_V4
> +SSBS
> +SVE
> +UNMAP_KERNEL_AT_EL0
> +WORKAROUND_834220
> +WORKAROUND_843419
> +WORKAROUND_845719
> +WORKAROUND_858921
> +WORKAROUND_1418040
> +WORKAROUND_1463225
> +WORKAROUND_1508412
> +WORKAROUND_1542419
> +WORKAROUND_CAVIUM_23154
> +WORKAROUND_CAVIUM_27456
> +WORKAROUND_CAVIUM_30115
> +WORKAROUND_CAVIUM_TX2_219_PRFM
> +WORKAROUND_CAVIUM_TX2_219_TVM
> +WORKAROUND_CLEAN_CACHE
> +WORKAROUND_DEVICE_LOAD_ACQUIRE
> +WORKAROUND_NVIDIA_CARMEL_CNP
> +WORKAROUND_QCOM_FALKOR_E1003
> +WORKAROUND_REPEAT_TLBI
> +WORKAROUND_SPECULATIVE_AT
> diff --git a/arch/arm64/tools/gen-cpucaps.awk b/arch/arm64/tools/gen-cpucaps.awk
> new file mode 100755
> index 000000000000..18737a1ce044
> --- /dev/null
> +++ b/arch/arm64/tools/gen-cpucaps.awk
> @@ -0,0 +1,40 @@
> +#!/bin/awk -f
> +# SPDX-License-Identifier: GPL-2.0
> +# gen-cpucaps.awk: arm64 cpucaps header generator
> +#
> +# Usage: awk -f gen-cpucaps.awk cpucaps.txt
> +
> +# Log an error and terminate
> +function fatal(msg) {
> +	print "Error at line " NR ": " msg > "/dev/stderr"
> +	exit 1
> +}
> +
> +# skip blank lines and comment lines
> +/^$/ { next }
> +/^#/ { next }
> +
> +BEGIN {
> +	print "#ifndef __ASM_CPUCAPS_H"
> +	print "#define __ASM_CPUCAPS_H"
> +	print ""
> +	print "/* Generated file - do not edit */"
> +	cap_num = 0
> +	print ""
> +}
> +
> +/^[vA-Z0-9_]+$/ {
> +	printf("#define ARM64_%-30s\t%d\n", $0, cap_num++)
> +	next
> +}
> +
> +END {
> +	printf("#define ARM64_NCAPS\t\t\t\t%d\n", cap_num)
> +	print ""
> +	print "#endif"
> +}
> +
> +# Any lines not handled by previous rules are unexpected
> +{
> +	fatal("unhandled statement")
> +}



More information about the linux-arm-kernel mailing list