Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef _ASM_POWERPC_CPUTHREADS_H
0003 #define _ASM_POWERPC_CPUTHREADS_H
0004 
0005 #ifndef __ASSEMBLY__
0006 #include <linux/cpumask.h>
0007 #include <asm/cpu_has_feature.h>
0008 
0009 /*
0010  * Mapping of threads to cores
0011  *
0012  * Note: This implementation is limited to a power of 2 number of
0013  * threads per core and the same number for each core in the system
0014  * (though it would work if some processors had less threads as long
0015  * as the CPU numbers are still allocated, just not brought online).
0016  *
0017  * However, the API allows for a different implementation in the future
0018  * if needed, as long as you only use the functions and not the variables
0019  * directly.
0020  */
0021 
0022 #ifdef CONFIG_SMP
0023 extern int threads_per_core;
0024 extern int threads_per_subcore;
0025 extern int threads_shift;
0026 extern cpumask_t threads_core_mask;
0027 #else
0028 #define threads_per_core    1
0029 #define threads_per_subcore 1
0030 #define threads_shift       0
0031 #define has_big_cores       0
0032 #define threads_core_mask   (*get_cpu_mask(0))
0033 #endif
0034 
0035 static inline int cpu_nr_cores(void)
0036 {
0037     return nr_cpu_ids >> threads_shift;
0038 }
0039 
0040 #ifdef CONFIG_SMP
0041 int cpu_core_index_of_thread(int cpu);
0042 int cpu_first_thread_of_core(int core);
0043 #else
0044 static inline int cpu_core_index_of_thread(int cpu) { return cpu; }
0045 static inline int cpu_first_thread_of_core(int core) { return core; }
0046 #endif
0047 
0048 static inline int cpu_thread_in_core(int cpu)
0049 {
0050     return cpu & (threads_per_core - 1);
0051 }
0052 
0053 static inline int cpu_thread_in_subcore(int cpu)
0054 {
0055     return cpu & (threads_per_subcore - 1);
0056 }
0057 
0058 static inline int cpu_first_thread_sibling(int cpu)
0059 {
0060     return cpu & ~(threads_per_core - 1);
0061 }
0062 
0063 static inline int cpu_last_thread_sibling(int cpu)
0064 {
0065     return cpu | (threads_per_core - 1);
0066 }
0067 
0068 /*
0069  * tlb_thread_siblings are siblings which share a TLB. This is not
0070  * architected, is not something a hypervisor could emulate and a future
0071  * CPU may change behaviour even in compat mode, so this should only be
0072  * used on PowerNV, and only with care.
0073  */
0074 static inline int cpu_first_tlb_thread_sibling(int cpu)
0075 {
0076     if (cpu_has_feature(CPU_FTR_ARCH_300) && (threads_per_core == 8))
0077         return cpu & ~0x6;  /* Big Core */
0078     else
0079         return cpu_first_thread_sibling(cpu);
0080 }
0081 
0082 static inline int cpu_last_tlb_thread_sibling(int cpu)
0083 {
0084     if (cpu_has_feature(CPU_FTR_ARCH_300) && (threads_per_core == 8))
0085         return cpu | 0x6;   /* Big Core */
0086     else
0087         return cpu_last_thread_sibling(cpu);
0088 }
0089 
0090 static inline int cpu_tlb_thread_sibling_step(void)
0091 {
0092     if (cpu_has_feature(CPU_FTR_ARCH_300) && (threads_per_core == 8))
0093         return 2;       /* Big Core */
0094     else
0095         return 1;
0096 }
0097 
0098 static inline u32 get_tensr(void)
0099 {
0100 #ifdef  CONFIG_BOOKE
0101     if (cpu_has_feature(CPU_FTR_SMT))
0102         return mfspr(SPRN_TENSR);
0103 #endif
0104     return 1;
0105 }
0106 
0107 void book3e_start_thread(int thread, unsigned long addr);
0108 void book3e_stop_thread(int thread);
0109 
0110 #endif /* __ASSEMBLY__ */
0111 
0112 #define INVALID_THREAD_HWID 0x0fff
0113 
0114 #endif /* _ASM_POWERPC_CPUTHREADS_H */
0115