2019-06-03 08:44:50 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2014-07-16 19:32:44 +04:00
/*
* Record and handle CPU attributes .
*
* Copyright ( C ) 2014 ARM Ltd .
*/
# include <asm/arch_timer.h>
2017-03-10 23:32:23 +03:00
# include <asm/cache.h>
2014-07-16 19:32:44 +04:00
# include <asm/cpu.h>
# include <asm/cputype.h>
2014-11-14 18:54:09 +03:00
# include <asm/cpufeature.h>
2017-10-31 18:51:10 +03:00
# include <asm/fpsimd.h>
2014-07-16 19:32:44 +04:00
2014-07-16 19:32:45 +04:00
# include <linux/bitops.h>
2014-08-08 15:51:39 +04:00
# include <linux/bug.h>
2016-05-31 17:55:03 +03:00
# include <linux/compat.h>
# include <linux/elf.h>
2014-07-16 19:32:44 +04:00
# include <linux/init.h>
2014-07-16 19:32:46 +04:00
# include <linux/kernel.h>
2015-10-19 16:24:43 +03:00
# include <linux/personality.h>
2014-08-08 15:51:39 +04:00
# include <linux/preempt.h>
2014-07-16 19:32:45 +04:00
# include <linux/printk.h>
2015-10-19 16:24:43 +03:00
# include <linux/seq_file.h>
# include <linux/sched.h>
2014-07-16 19:32:44 +04:00
# include <linux/smp.h>
2015-11-18 21:48:55 +03:00
# include <linux/delay.h>
2014-07-16 19:32:44 +04:00
/*
* In case the boot CPU is hotpluggable , we record its initial state and
* current state separately . Certain system registers may contain different
* values depending on configuration at or after reset .
*/
DEFINE_PER_CPU ( struct cpuinfo_arm64 , cpu_data ) ;
static struct cpuinfo_arm64 boot_cpu_data ;
2022-07-04 20:02:35 +03:00
static inline const char * icache_policy_str ( int l1ip )
{
switch ( l1ip ) {
2022-07-04 20:02:40 +03:00
case CTR_EL0_L1Ip_VIPT :
2022-07-04 20:02:35 +03:00
return " VIPT " ;
2022-07-04 20:02:40 +03:00
case CTR_EL0_L1Ip_PIPT :
2022-07-04 20:02:35 +03:00
return " PIPT " ;
default :
return " RESERVED/UNKNOWN " ;
}
}
2014-07-16 19:32:45 +04:00
unsigned long __icache_flags ;
2015-07-30 18:36:25 +03:00
static const char * const hwcap_str [ ] = {
2020-09-09 08:48:55 +03:00
[ KERNEL_HWCAP_FP ] = " fp " ,
[ KERNEL_HWCAP_ASIMD ] = " asimd " ,
[ KERNEL_HWCAP_EVTSTRM ] = " evtstrm " ,
[ KERNEL_HWCAP_AES ] = " aes " ,
[ KERNEL_HWCAP_PMULL ] = " pmull " ,
[ KERNEL_HWCAP_SHA1 ] = " sha1 " ,
[ KERNEL_HWCAP_SHA2 ] = " sha2 " ,
[ KERNEL_HWCAP_CRC32 ] = " crc32 " ,
[ KERNEL_HWCAP_ATOMICS ] = " atomics " ,
[ KERNEL_HWCAP_FPHP ] = " fphp " ,
[ KERNEL_HWCAP_ASIMDHP ] = " asimdhp " ,
[ KERNEL_HWCAP_CPUID ] = " cpuid " ,
[ KERNEL_HWCAP_ASIMDRDM ] = " asimdrdm " ,
[ KERNEL_HWCAP_JSCVT ] = " jscvt " ,
[ KERNEL_HWCAP_FCMA ] = " fcma " ,
[ KERNEL_HWCAP_LRCPC ] = " lrcpc " ,
[ KERNEL_HWCAP_DCPOP ] = " dcpop " ,
[ KERNEL_HWCAP_SHA3 ] = " sha3 " ,
[ KERNEL_HWCAP_SM3 ] = " sm3 " ,
[ KERNEL_HWCAP_SM4 ] = " sm4 " ,
[ KERNEL_HWCAP_ASIMDDP ] = " asimddp " ,
[ KERNEL_HWCAP_SHA512 ] = " sha512 " ,
[ KERNEL_HWCAP_SVE ] = " sve " ,
[ KERNEL_HWCAP_ASIMDFHM ] = " asimdfhm " ,
[ KERNEL_HWCAP_DIT ] = " dit " ,
[ KERNEL_HWCAP_USCAT ] = " uscat " ,
[ KERNEL_HWCAP_ILRCPC ] = " ilrcpc " ,
[ KERNEL_HWCAP_FLAGM ] = " flagm " ,
[ KERNEL_HWCAP_SSBS ] = " ssbs " ,
[ KERNEL_HWCAP_SB ] = " sb " ,
[ KERNEL_HWCAP_PACA ] = " paca " ,
[ KERNEL_HWCAP_PACG ] = " pacg " ,
[ KERNEL_HWCAP_DCPODP ] = " dcpodp " ,
[ KERNEL_HWCAP_SVE2 ] = " sve2 " ,
[ KERNEL_HWCAP_SVEAES ] = " sveaes " ,
[ KERNEL_HWCAP_SVEPMULL ] = " svepmull " ,
[ KERNEL_HWCAP_SVEBITPERM ] = " svebitperm " ,
[ KERNEL_HWCAP_SVESHA3 ] = " svesha3 " ,
[ KERNEL_HWCAP_SVESM4 ] = " svesm4 " ,
[ KERNEL_HWCAP_FLAGM2 ] = " flagm2 " ,
[ KERNEL_HWCAP_FRINT ] = " frint " ,
[ KERNEL_HWCAP_SVEI8MM ] = " svei8mm " ,
[ KERNEL_HWCAP_SVEF32MM ] = " svef32mm " ,
[ KERNEL_HWCAP_SVEF64MM ] = " svef64mm " ,
[ KERNEL_HWCAP_SVEBF16 ] = " svebf16 " ,
[ KERNEL_HWCAP_I8MM ] = " i8mm " ,
[ KERNEL_HWCAP_BF16 ] = " bf16 " ,
[ KERNEL_HWCAP_DGH ] = " dgh " ,
[ KERNEL_HWCAP_RNG ] = " rng " ,
[ KERNEL_HWCAP_BTI ] = " bti " ,
2020-10-02 14:16:11 +03:00
[ KERNEL_HWCAP_MTE ] = " mte " ,
2021-10-17 15:42:25 +03:00
[ KERNEL_HWCAP_ECV ] = " ecv " ,
2021-12-10 19:54:30 +03:00
[ KERNEL_HWCAP_AFP ] = " afp " ,
2021-12-10 19:54:32 +03:00
[ KERNEL_HWCAP_RPRES ] = " rpres " ,
2022-02-16 20:32:23 +03:00
[ KERNEL_HWCAP_MTE3 ] = " mte3 " ,
2022-04-19 14:22:16 +03:00
[ KERNEL_HWCAP_SME ] = " sme " ,
[ KERNEL_HWCAP_SME_I16I64 ] = " smei16i64 " ,
[ KERNEL_HWCAP_SME_F64F64 ] = " smef64f64 " ,
[ KERNEL_HWCAP_SME_I8I32 ] = " smei8i32 " ,
[ KERNEL_HWCAP_SME_F16F32 ] = " smef16f32 " ,
[ KERNEL_HWCAP_SME_B16F32 ] = " smeb16f32 " ,
[ KERNEL_HWCAP_SME_F32F32 ] = " smef32f32 " ,
[ KERNEL_HWCAP_SME_FA64 ] = " smefa64 " ,
2022-04-20 15:21:12 +03:00
[ KERNEL_HWCAP_WFXT ] = " wfxt " ,
2022-07-07 13:36:32 +03:00
[ KERNEL_HWCAP_EBF16 ] = " ebf16 " ,
2022-08-29 18:48:15 +03:00
[ KERNEL_HWCAP_SVE_EBF16 ] = " sveebf16 " ,
2022-10-17 18:25:15 +03:00
[ KERNEL_HWCAP_CSSC ] = " cssc " ,
2022-10-17 18:25:17 +03:00
[ KERNEL_HWCAP_RPRFM ] = " rprfm " ,
2022-10-17 18:25:19 +03:00
[ KERNEL_HWCAP_SVE2P1 ] = " sve2p1 " ,
2023-01-16 19:04:48 +03:00
[ KERNEL_HWCAP_SME2 ] = " sme2 " ,
[ KERNEL_HWCAP_SME2P1 ] = " sme2p1 " ,
[ KERNEL_HWCAP_SME_I16I32 ] = " smei16i32 " ,
[ KERNEL_HWCAP_SME_BI32I32 ] = " smebi32i32 " ,
[ KERNEL_HWCAP_SME_B16B16 ] = " smeb16b16 " ,
[ KERNEL_HWCAP_SME_F16F16 ] = " smef16f16 " ,
2023-05-09 17:22:33 +03:00
[ KERNEL_HWCAP_MOPS ] = " mops " ,
2023-08-04 17:37:45 +03:00
[ KERNEL_HWCAP_HBC ] = " hbc " ,
2023-09-15 15:18:06 +03:00
[ KERNEL_HWCAP_SVE_B16B16 ] = " sveb16b16 " ,
2023-09-19 19:27:56 +03:00
[ KERNEL_HWCAP_LRCPC3 ] = " lrcpc3 " ,
2023-10-03 15:45:43 +03:00
[ KERNEL_HWCAP_LSE128 ] = " lse128 " ,
2015-10-19 16:24:43 +03:00
} ;
# ifdef CONFIG_COMPAT
2020-09-09 08:48:55 +03:00
# define COMPAT_KERNEL_HWCAP(x) const_ilog2(COMPAT_HWCAP_ ## x)
2015-07-30 18:36:25 +03:00
static const char * const compat_hwcap_str [ ] = {
2020-09-09 08:48:55 +03:00
[ COMPAT_KERNEL_HWCAP ( SWP ) ] = " swp " ,
[ COMPAT_KERNEL_HWCAP ( HALF ) ] = " half " ,
[ COMPAT_KERNEL_HWCAP ( THUMB ) ] = " thumb " ,
[ COMPAT_KERNEL_HWCAP ( 26 BIT ) ] = NULL , /* Not possible on arm64 */
[ COMPAT_KERNEL_HWCAP ( FAST_MULT ) ] = " fastmult " ,
[ COMPAT_KERNEL_HWCAP ( FPA ) ] = NULL , /* Not possible on arm64 */
[ COMPAT_KERNEL_HWCAP ( VFP ) ] = " vfp " ,
[ COMPAT_KERNEL_HWCAP ( EDSP ) ] = " edsp " ,
[ COMPAT_KERNEL_HWCAP ( JAVA ) ] = NULL , /* Not possible on arm64 */
[ COMPAT_KERNEL_HWCAP ( IWMMXT ) ] = NULL , /* Not possible on arm64 */
[ COMPAT_KERNEL_HWCAP ( CRUNCH ) ] = NULL , /* Not possible on arm64 */
[ COMPAT_KERNEL_HWCAP ( THUMBEE ) ] = NULL , /* Not possible on arm64 */
[ COMPAT_KERNEL_HWCAP ( NEON ) ] = " neon " ,
[ COMPAT_KERNEL_HWCAP ( VFPv3 ) ] = " vfpv3 " ,
[ COMPAT_KERNEL_HWCAP ( VFPV3D16 ) ] = NULL , /* Not possible on arm64 */
[ COMPAT_KERNEL_HWCAP ( TLS ) ] = " tls " ,
[ COMPAT_KERNEL_HWCAP ( VFPv4 ) ] = " vfpv4 " ,
[ COMPAT_KERNEL_HWCAP ( IDIVA ) ] = " idiva " ,
[ COMPAT_KERNEL_HWCAP ( IDIVT ) ] = " idivt " ,
[ COMPAT_KERNEL_HWCAP ( VFPD32 ) ] = NULL , /* Not possible on arm64 */
[ COMPAT_KERNEL_HWCAP ( LPAE ) ] = " lpae " ,
[ COMPAT_KERNEL_HWCAP ( EVTSTRM ) ] = " evtstrm " ,
2023-01-11 08:37:00 +03:00
[ COMPAT_KERNEL_HWCAP ( FPHP ) ] = " fphp " ,
[ COMPAT_KERNEL_HWCAP ( ASIMDHP ) ] = " asimdhp " ,
2023-01-11 08:37:01 +03:00
[ COMPAT_KERNEL_HWCAP ( ASIMDDP ) ] = " asimddp " ,
2023-01-11 08:37:02 +03:00
[ COMPAT_KERNEL_HWCAP ( ASIMDFHM ) ] = " asimdfhm " ,
2023-01-11 08:37:03 +03:00
[ COMPAT_KERNEL_HWCAP ( ASIMDBF16 ) ] = " asimdbf16 " ,
2023-01-11 08:37:04 +03:00
[ COMPAT_KERNEL_HWCAP ( I8MM ) ] = " i8mm " ,
2015-10-19 16:24:43 +03:00
} ;
2020-09-09 08:48:55 +03:00
# define COMPAT_KERNEL_HWCAP2(x) const_ilog2(COMPAT_HWCAP2_ ## x)
2015-07-30 18:36:25 +03:00
static const char * const compat_hwcap2_str [ ] = {
2020-09-09 08:48:55 +03:00
[ COMPAT_KERNEL_HWCAP2 ( AES ) ] = " aes " ,
[ COMPAT_KERNEL_HWCAP2 ( PMULL ) ] = " pmull " ,
[ COMPAT_KERNEL_HWCAP2 ( SHA1 ) ] = " sha1 " ,
[ COMPAT_KERNEL_HWCAP2 ( SHA2 ) ] = " sha2 " ,
[ COMPAT_KERNEL_HWCAP2 ( CRC32 ) ] = " crc32 " ,
2023-01-11 08:37:05 +03:00
[ COMPAT_KERNEL_HWCAP2 ( SB ) ] = " sb " ,
2023-01-11 08:37:06 +03:00
[ COMPAT_KERNEL_HWCAP2 ( SSBS ) ] = " ssbs " ,
2015-10-19 16:24:43 +03:00
} ;
# endif /* CONFIG_COMPAT */
static int c_show ( struct seq_file * m , void * v )
{
int i , j ;
2016-05-31 17:55:03 +03:00
bool compat = personality ( current - > personality ) = = PER_LINUX32 ;
2015-10-19 16:24:43 +03:00
for_each_online_cpu ( i ) {
struct cpuinfo_arm64 * cpuinfo = & per_cpu ( cpu_data , i ) ;
u32 midr = cpuinfo - > reg_midr ;
/*
* glibc reads / proc / cpuinfo to determine the number of
* online processors , looking for lines beginning with
* " processor " . Give glibc what it expects .
*/
seq_printf ( m , " processor \t : %d \n " , i ) ;
2016-05-31 17:55:03 +03:00
if ( compat )
seq_printf ( m , " model name \t : ARMv8 Processor rev %d (%s) \n " ,
MIDR_REVISION ( midr ) , COMPAT_ELF_PLATFORM ) ;
2015-10-19 16:24:43 +03:00
2015-11-18 21:48:55 +03:00
seq_printf ( m , " BogoMIPS \t : %lu.%02lu \n " ,
loops_per_jiffy / ( 500000UL / HZ ) ,
loops_per_jiffy / ( 5000UL / HZ ) % 100 ) ;
2015-10-19 16:24:43 +03:00
/*
* Dump out the common processor features in a single line .
* Userspace should read the hwcaps with getauxval ( AT_HWCAP )
* rather than attempting to parse this , but there ' s a body of
* software which does already ( at least for 32 - bit ) .
*/
seq_puts ( m , " Features \t : " ) ;
2016-05-31 17:55:03 +03:00
if ( compat ) {
2015-10-19 16:24:43 +03:00
# ifdef CONFIG_COMPAT
2020-09-09 08:48:55 +03:00
for ( j = 0 ; j < ARRAY_SIZE ( compat_hwcap_str ) ; j + + ) {
if ( compat_elf_hwcap & ( 1 < < j ) ) {
/*
* Warn once if any feature should not
* have been present on arm64 platform .
*/
if ( WARN_ON_ONCE ( ! compat_hwcap_str [ j ] ) )
continue ;
2015-10-19 16:24:43 +03:00
seq_printf ( m , " %s " , compat_hwcap_str [ j ] ) ;
2020-09-09 08:48:55 +03:00
}
}
2015-10-19 16:24:43 +03:00
2020-09-09 08:48:55 +03:00
for ( j = 0 ; j < ARRAY_SIZE ( compat_hwcap2_str ) ; j + + )
2015-10-19 16:24:43 +03:00
if ( compat_elf_hwcap2 & ( 1 < < j ) )
seq_printf ( m , " %s " , compat_hwcap2_str [ j ] ) ;
# endif /* CONFIG_COMPAT */
} else {
2020-09-09 08:48:55 +03:00
for ( j = 0 ; j < ARRAY_SIZE ( hwcap_str ) ; j + + )
2019-04-09 12:52:40 +03:00
if ( cpu_have_feature ( j ) )
2015-10-19 16:24:43 +03:00
seq_printf ( m , " %s " , hwcap_str [ j ] ) ;
}
seq_puts ( m , " \n " ) ;
seq_printf ( m , " CPU implementer \t : 0x%02x \n " ,
MIDR_IMPLEMENTOR ( midr ) ) ;
seq_printf ( m , " CPU architecture: 8 \n " ) ;
seq_printf ( m , " CPU variant \t : 0x%x \n " , MIDR_VARIANT ( midr ) ) ;
seq_printf ( m , " CPU part \t : 0x%03x \n " , MIDR_PARTNUM ( midr ) ) ;
seq_printf ( m , " CPU revision \t : %d \n \n " , MIDR_REVISION ( midr ) ) ;
}
return 0 ;
}
static void * c_start ( struct seq_file * m , loff_t * pos )
{
return * pos < 1 ? ( void * ) 1 : NULL ;
}
static void * c_next ( struct seq_file * m , void * v , loff_t * pos )
{
+ + * pos ;
return NULL ;
}
static void c_stop ( struct seq_file * m , void * v )
{
}
const struct seq_operations cpuinfo_op = {
. start = c_start ,
. next = c_next ,
. stop = c_stop ,
. show = c_show
} ;
2016-07-08 18:01:13 +03:00
static struct kobj_type cpuregs_kobj_type = {
. sysfs_ops = & kobj_sysfs_ops ,
} ;
/*
* The ARM ARM uses the phrase " 32-bit register " to describe a register
* whose upper 32 bits are RES0 ( per C5 .1 .1 , ARM DDI 04 87 A . i ) , however
* no statement is made as to whether the upper 32 bits will or will not
* be made use of in future , and between ARM DDI 04 87 A . c and ARM DDI
* 04 87 A . d CLIDR_EL1 was expanded from 32 - bit to 64 - bit .
*
* Thus , while both MIDR_EL1 and REVIDR_EL1 are described as 32 - bit
* registers , we expose them both as 64 bit values to cater for possible
* future expansion without an ABI break .
*/
# define kobj_to_cpuinfo(kobj) container_of(kobj, struct cpuinfo_arm64, kobj)
# define CPUREGS_ATTR_RO(_name, _field) \
static ssize_t _name # # _show ( struct kobject * kobj , \
struct kobj_attribute * attr , char * buf ) \
{ \
struct cpuinfo_arm64 * info = kobj_to_cpuinfo ( kobj ) ; \
\
if ( info - > reg_midr ) \
2021-05-26 22:36:20 +03:00
return sprintf ( buf , " 0x%016llx \n " , info - > reg_ # # _field ) ; \
2016-07-08 18:01:13 +03:00
else \
return 0 ; \
} \
static struct kobj_attribute cpuregs_attr_ # # _name = __ATTR_RO ( _name )
CPUREGS_ATTR_RO ( midr_el1 , midr ) ;
CPUREGS_ATTR_RO ( revidr_el1 , revidr ) ;
2022-06-07 16:28:57 +03:00
CPUREGS_ATTR_RO ( smidr_el1 , smidr ) ;
2016-07-08 18:01:13 +03:00
static struct attribute * cpuregs_id_attrs [ ] = {
& cpuregs_attr_midr_el1 . attr ,
& cpuregs_attr_revidr_el1 . attr ,
NULL
} ;
2017-06-30 14:30:20 +03:00
static const struct attribute_group cpuregs_attr_group = {
2016-07-08 18:01:13 +03:00
. attrs = cpuregs_id_attrs ,
. name = " identification "
} ;
2022-06-07 16:28:57 +03:00
static struct attribute * sme_cpuregs_id_attrs [ ] = {
& cpuregs_attr_smidr_el1 . attr ,
NULL
} ;
static const struct attribute_group sme_cpuregs_attr_group = {
. attrs = sme_cpuregs_id_attrs ,
. name = " identification "
} ;
2016-11-27 02:13:44 +03:00
static int cpuid_cpu_online ( unsigned int cpu )
2016-07-08 18:01:13 +03:00
{
int rc ;
struct device * dev ;
struct cpuinfo_arm64 * info = & per_cpu ( cpu_data , cpu ) ;
dev = get_cpu_device ( cpu ) ;
if ( ! dev ) {
rc = - ENODEV ;
goto out ;
}
rc = kobject_add ( & info - > kobj , & dev - > kobj , " regs " ) ;
if ( rc )
goto out ;
rc = sysfs_create_group ( & info - > kobj , & cpuregs_attr_group ) ;
if ( rc )
kobject_del ( & info - > kobj ) ;
2022-06-07 16:28:57 +03:00
if ( system_supports_sme ( ) )
rc = sysfs_merge_group ( & info - > kobj , & sme_cpuregs_attr_group ) ;
2016-07-08 18:01:13 +03:00
out :
return rc ;
}
2016-11-27 02:13:44 +03:00
static int cpuid_cpu_offline ( unsigned int cpu )
2016-07-08 18:01:13 +03:00
{
struct device * dev ;
struct cpuinfo_arm64 * info = & per_cpu ( cpu_data , cpu ) ;
dev = get_cpu_device ( cpu ) ;
if ( ! dev )
return - ENODEV ;
if ( info - > kobj . parent ) {
sysfs_remove_group ( & info - > kobj , & cpuregs_attr_group ) ;
kobject_del ( & info - > kobj ) ;
}
return 0 ;
}
static int __init cpuinfo_regs_init ( void )
{
2016-11-27 02:13:44 +03:00
int cpu , ret ;
2016-07-08 18:01:13 +03:00
for_each_possible_cpu ( cpu ) {
struct cpuinfo_arm64 * info = & per_cpu ( cpu_data , cpu ) ;
kobject_init ( & info - > kobj , & cpuregs_kobj_type ) ;
}
2016-11-27 02:13:44 +03:00
ret = cpuhp_setup_state ( CPUHP_AP_ONLINE_DYN , " arm64/cpuinfo:online " ,
cpuid_cpu_online , cpuid_cpu_offline ) ;
if ( ret < 0 ) {
pr_err ( " cpuinfo: failed to register hotplug callbacks. \n " ) ;
return ret ;
}
2016-07-08 18:01:13 +03:00
return 0 ;
}
2020-05-04 15:29:37 +03:00
device_initcall ( cpuinfo_regs_init ) ;
2014-07-16 19:32:45 +04:00
static void cpuinfo_detect_icache_policy ( struct cpuinfo_arm64 * info )
{
unsigned int cpu = smp_processor_id ( ) ;
u32 l1ip = CTR_L1IP ( info - > reg_ctr ) ;
2017-03-10 23:32:20 +03:00
switch ( l1ip ) {
2022-07-04 20:02:40 +03:00
case CTR_EL0_L1Ip_PIPT :
2017-03-10 23:32:20 +03:00
break ;
2022-07-04 20:02:40 +03:00
case CTR_EL0_L1Ip_VIPT :
2022-07-04 20:02:35 +03:00
default :
2017-03-10 23:32:20 +03:00
/* Assume aliasing */
set_bit ( ICACHEF_ALIASING , & __icache_flags ) ;
2020-10-26 22:37:46 +03:00
break ;
2017-03-10 23:32:20 +03:00
}
2014-07-16 19:32:45 +04:00
2022-07-04 20:02:35 +03:00
pr_info ( " Detected %s I-cache on CPU%d \n " , icache_policy_str ( l1ip ) , cpu ) ;
2014-07-16 19:32:45 +04:00
}
2021-06-08 21:02:54 +03:00
static void __cpuinfo_store_cpu_32bit ( struct cpuinfo_32bit * info )
{
info - > reg_id_dfr0 = read_cpuid ( ID_DFR0_EL1 ) ;
info - > reg_id_dfr1 = read_cpuid ( ID_DFR1_EL1 ) ;
info - > reg_id_isar0 = read_cpuid ( ID_ISAR0_EL1 ) ;
info - > reg_id_isar1 = read_cpuid ( ID_ISAR1_EL1 ) ;
info - > reg_id_isar2 = read_cpuid ( ID_ISAR2_EL1 ) ;
info - > reg_id_isar3 = read_cpuid ( ID_ISAR3_EL1 ) ;
info - > reg_id_isar4 = read_cpuid ( ID_ISAR4_EL1 ) ;
info - > reg_id_isar5 = read_cpuid ( ID_ISAR5_EL1 ) ;
info - > reg_id_isar6 = read_cpuid ( ID_ISAR6_EL1 ) ;
info - > reg_id_mmfr0 = read_cpuid ( ID_MMFR0_EL1 ) ;
info - > reg_id_mmfr1 = read_cpuid ( ID_MMFR1_EL1 ) ;
info - > reg_id_mmfr2 = read_cpuid ( ID_MMFR2_EL1 ) ;
info - > reg_id_mmfr3 = read_cpuid ( ID_MMFR3_EL1 ) ;
info - > reg_id_mmfr4 = read_cpuid ( ID_MMFR4_EL1 ) ;
info - > reg_id_mmfr5 = read_cpuid ( ID_MMFR5_EL1 ) ;
info - > reg_id_pfr0 = read_cpuid ( ID_PFR0_EL1 ) ;
info - > reg_id_pfr1 = read_cpuid ( ID_PFR1_EL1 ) ;
info - > reg_id_pfr2 = read_cpuid ( ID_PFR2_EL1 ) ;
info - > reg_mvfr0 = read_cpuid ( MVFR0_EL1 ) ;
info - > reg_mvfr1 = read_cpuid ( MVFR1_EL1 ) ;
info - > reg_mvfr2 = read_cpuid ( MVFR2_EL1 ) ;
}
2014-07-16 19:32:44 +04:00
static void __cpuinfo_store_cpu ( struct cpuinfo_arm64 * info )
{
info - > reg_cntfrq = arch_timer_get_cntfrq ( ) ;
2018-10-09 16:47:06 +03:00
/*
* Use the effective value of the CTR_EL0 than the raw value
2019-10-25 09:32:06 +03:00
* exposed by the CPU . CTR_EL0 . IDC field value must be interpreted
2018-10-09 16:47:06 +03:00
* with the CLIDR_EL1 fields to avoid triggering false warnings
* when there is a mismatch across the CPUs . Keep track of the
* effective value of the CTR_EL0 in our internal records for
2021-03-20 01:28:48 +03:00
* accurate sanity check and feature enablement .
2018-10-09 16:47:06 +03:00
*/
info - > reg_ctr = read_cpuid_effective_cachetype ( ) ;
2016-03-04 15:54:05 +03:00
info - > reg_dczid = read_cpuid ( DCZID_EL0 ) ;
2014-07-16 19:32:44 +04:00
info - > reg_midr = read_cpuid_id ( ) ;
2016-07-08 18:01:13 +03:00
info - > reg_revidr = read_cpuid ( REVIDR_EL1 ) ;
2014-07-16 19:32:44 +04:00
2016-03-04 15:54:05 +03:00
info - > reg_id_aa64dfr0 = read_cpuid ( ID_AA64DFR0_EL1 ) ;
info - > reg_id_aa64dfr1 = read_cpuid ( ID_AA64DFR1_EL1 ) ;
info - > reg_id_aa64isar0 = read_cpuid ( ID_AA64ISAR0_EL1 ) ;
info - > reg_id_aa64isar1 = read_cpuid ( ID_AA64ISAR1_EL1 ) ;
2021-12-10 19:54:31 +03:00
info - > reg_id_aa64isar2 = read_cpuid ( ID_AA64ISAR2_EL1 ) ;
2016-03-04 15:54:05 +03:00
info - > reg_id_aa64mmfr0 = read_cpuid ( ID_AA64MMFR0_EL1 ) ;
info - > reg_id_aa64mmfr1 = read_cpuid ( ID_AA64MMFR1_EL1 ) ;
info - > reg_id_aa64mmfr2 = read_cpuid ( ID_AA64MMFR2_EL1 ) ;
2023-06-06 17:58:44 +03:00
info - > reg_id_aa64mmfr3 = read_cpuid ( ID_AA64MMFR3_EL1 ) ;
2016-03-04 15:54:05 +03:00
info - > reg_id_aa64pfr0 = read_cpuid ( ID_AA64PFR0_EL1 ) ;
info - > reg_id_aa64pfr1 = read_cpuid ( ID_AA64PFR1_EL1 ) ;
2017-10-31 18:51:10 +03:00
info - > reg_id_aa64zfr0 = read_cpuid ( ID_AA64ZFR0_EL1 ) ;
2022-04-19 14:22:16 +03:00
info - > reg_id_aa64smfr0 = read_cpuid ( ID_AA64SMFR0_EL1 ) ;
2016-03-04 15:54:05 +03:00
2021-05-26 22:36:21 +03:00
if ( id_aa64pfr1_mte ( info - > reg_id_aa64pfr1 ) )
info - > reg_gmid = read_cpuid ( GMID_EL1 ) ;
2021-06-08 21:02:54 +03:00
if ( id_aa64pfr0_32bit_el0 ( info - > reg_id_aa64pfr0 ) )
__cpuinfo_store_cpu_32bit ( & info - > aarch32 ) ;
2015-01-07 13:31:56 +03:00
2014-07-16 19:32:45 +04:00
cpuinfo_detect_icache_policy ( info ) ;
2014-07-16 19:32:44 +04:00
}
void cpuinfo_store_cpu ( void )
{
struct cpuinfo_arm64 * info = this_cpu_ptr ( & cpu_data ) ;
__cpuinfo_store_cpu ( info ) ;
2015-10-19 16:24:46 +03:00
update_cpu_features ( smp_processor_id ( ) , info , & boot_cpu_data ) ;
2014-07-16 19:32:44 +04:00
}
void __init cpuinfo_store_boot_cpu ( void )
{
struct cpuinfo_arm64 * info = & per_cpu ( cpu_data , 0 ) ;
__cpuinfo_store_cpu ( info ) ;
boot_cpu_data = * info ;
2015-10-19 16:24:45 +03:00
init_cpu_features ( & boot_cpu_data ) ;
2014-07-16 19:32:44 +04:00
}