162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __ASM_POWERPC_CPU_HAS_FEATURE_H
362306a36Sopenharmony_ci#define __ASM_POWERPC_CPU_HAS_FEATURE_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#ifndef __ASSEMBLY__
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/bug.h>
862306a36Sopenharmony_ci#include <asm/cputable.h>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_cistatic __always_inline bool early_cpu_has_feature(unsigned long feature)
1162306a36Sopenharmony_ci{
1262306a36Sopenharmony_ci	return !!((CPU_FTRS_ALWAYS & feature) ||
1362306a36Sopenharmony_ci		  (CPU_FTRS_POSSIBLE & cur_cpu_spec->cpu_features & feature));
1462306a36Sopenharmony_ci}
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS
1762306a36Sopenharmony_ci#include <linux/jump_label.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#define NUM_CPU_FTR_KEYS	BITS_PER_LONG
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ciextern struct static_key_true cpu_feature_keys[NUM_CPU_FTR_KEYS];
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistatic __always_inline bool cpu_has_feature(unsigned long feature)
2462306a36Sopenharmony_ci{
2562306a36Sopenharmony_ci	int i;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#ifndef __clang__ /* clang can't cope with this */
2862306a36Sopenharmony_ci	BUILD_BUG_ON(!__builtin_constant_p(feature));
2962306a36Sopenharmony_ci#endif
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECK_DEBUG
3262306a36Sopenharmony_ci	if (!static_key_initialized) {
3362306a36Sopenharmony_ci		printk("Warning! cpu_has_feature() used prior to jump label init!\n");
3462306a36Sopenharmony_ci		dump_stack();
3562306a36Sopenharmony_ci		return early_cpu_has_feature(feature);
3662306a36Sopenharmony_ci	}
3762306a36Sopenharmony_ci#endif
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	if (CPU_FTRS_ALWAYS & feature)
4062306a36Sopenharmony_ci		return true;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	if (!(CPU_FTRS_POSSIBLE & feature))
4362306a36Sopenharmony_ci		return false;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	i = __builtin_ctzl(feature);
4662306a36Sopenharmony_ci	return static_branch_likely(&cpu_feature_keys[i]);
4762306a36Sopenharmony_ci}
4862306a36Sopenharmony_ci#else
4962306a36Sopenharmony_cistatic __always_inline bool cpu_has_feature(unsigned long feature)
5062306a36Sopenharmony_ci{
5162306a36Sopenharmony_ci	return early_cpu_has_feature(feature);
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci#endif
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#endif /* __ASSEMBLY__ */
5662306a36Sopenharmony_ci#endif /* __ASM_POWERPC_CPU_HAS_FEATURE_H */
57