18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef __ASM_POWERPC_CPU_HAS_FEATURE_H
38c2ecf20Sopenharmony_ci#define __ASM_POWERPC_CPU_HAS_FEATURE_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <linux/bug.h>
88c2ecf20Sopenharmony_ci#include <asm/cputable.h>
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_cistatic __always_inline bool early_cpu_has_feature(unsigned long feature)
118c2ecf20Sopenharmony_ci{
128c2ecf20Sopenharmony_ci	return !!((CPU_FTRS_ALWAYS & feature) ||
138c2ecf20Sopenharmony_ci		  (CPU_FTRS_POSSIBLE & cur_cpu_spec->cpu_features & feature));
148c2ecf20Sopenharmony_ci}
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS
178c2ecf20Sopenharmony_ci#include <linux/jump_label.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#define NUM_CPU_FTR_KEYS	BITS_PER_LONG
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ciextern struct static_key_true cpu_feature_keys[NUM_CPU_FTR_KEYS];
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistatic __always_inline bool cpu_has_feature(unsigned long feature)
248c2ecf20Sopenharmony_ci{
258c2ecf20Sopenharmony_ci	int i;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci#ifndef __clang__ /* clang can't cope with this */
288c2ecf20Sopenharmony_ci	BUILD_BUG_ON(!__builtin_constant_p(feature));
298c2ecf20Sopenharmony_ci#endif
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECK_DEBUG
328c2ecf20Sopenharmony_ci	if (!static_key_initialized) {
338c2ecf20Sopenharmony_ci		printk("Warning! cpu_has_feature() used prior to jump label init!\n");
348c2ecf20Sopenharmony_ci		dump_stack();
358c2ecf20Sopenharmony_ci		return early_cpu_has_feature(feature);
368c2ecf20Sopenharmony_ci	}
378c2ecf20Sopenharmony_ci#endif
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	if (CPU_FTRS_ALWAYS & feature)
408c2ecf20Sopenharmony_ci		return true;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	if (!(CPU_FTRS_POSSIBLE & feature))
438c2ecf20Sopenharmony_ci		return false;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	i = __builtin_ctzl(feature);
468c2ecf20Sopenharmony_ci	return static_branch_likely(&cpu_feature_keys[i]);
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ci#else
498c2ecf20Sopenharmony_cistatic __always_inline bool cpu_has_feature(unsigned long feature)
508c2ecf20Sopenharmony_ci{
518c2ecf20Sopenharmony_ci	return early_cpu_has_feature(feature);
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ci#endif
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */
568c2ecf20Sopenharmony_ci#endif /* __ASM_POWERPC_CPU_HAS_FEATURE_H */
57