Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * This file is subject to the terms and conditions of the GNU General Public |
| 3 | * License. See the file "COPYING" in the main directory of this archive |
| 4 | * for more details. |
| 5 | * |
| 6 | * Copyright (C) 1994 Waldorf GMBH |
| 7 | * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2003 Ralf Baechle |
| 8 | * Copyright (C) 1996 Paul M. Antoine |
| 9 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. |
| 10 | * Copyright (C) 2004 Maciej W. Rozycki |
| 11 | */ |
| 12 | #ifndef __ASM_CPU_INFO_H |
| 13 | #define __ASM_CPU_INFO_H |
| 14 | |
| 15 | #include <linux/cache.h> |
| 16 | #include <linux/types.h> |
| 17 | |
| 18 | #include <asm/mipsregs.h> |
| 19 | |
| 20 | /* |
| 21 | * Descriptor for a cache |
| 22 | */ |
| 23 | struct cache_desc { |
| 24 | unsigned int waysize; /* Bytes per way */ |
| 25 | unsigned short sets; /* Number of lines per set */ |
| 26 | unsigned char ways; /* Number of ways */ |
| 27 | unsigned char linesz; /* Size of line in bytes */ |
| 28 | unsigned char waybit; /* Bits to select in a cache set */ |
| 29 | unsigned char flags; /* Flags describing cache properties */ |
| 30 | }; |
| 31 | |
| 32 | struct guest_info { |
| 33 | unsigned long ases; |
| 34 | unsigned long ases_dyn; |
| 35 | unsigned long long options; |
| 36 | unsigned long long options_dyn; |
| 37 | int tlbsize; |
| 38 | u8 conf; |
| 39 | u8 kscratch_mask; |
| 40 | }; |
| 41 | |
| 42 | /* |
| 43 | * Flag definitions |
| 44 | */ |
| 45 | #define MIPS_CACHE_NOT_PRESENT 0x00000001 |
| 46 | #define MIPS_CACHE_VTAG 0x00000002 /* Virtually tagged cache */ |
| 47 | #define MIPS_CACHE_ALIASES 0x00000004 /* Cache could have aliases */ |
| 48 | #define MIPS_CACHE_IC_F_DC 0x00000008 /* Ic can refill from D-cache */ |
| 49 | #define MIPS_IC_SNOOPS_REMOTE 0x00000010 /* Ic snoops remote stores */ |
| 50 | #define MIPS_CACHE_PINDEX 0x00000020 /* Physically indexed cache */ |
| 51 | |
| 52 | struct cpuinfo_mips { |
| 53 | unsigned long asid_cache; |
| 54 | #ifdef CONFIG_MIPS_ASID_BITS_VARIABLE |
| 55 | unsigned long asid_mask; |
| 56 | #endif |
| 57 | |
| 58 | /* |
| 59 | * Capability and feature descriptor structure for MIPS CPU |
| 60 | */ |
| 61 | unsigned long ases; |
| 62 | unsigned long long options; |
| 63 | unsigned int udelay_val; |
| 64 | unsigned int processor_id; |
| 65 | unsigned int fpu_id; |
| 66 | unsigned int fpu_csr31; |
| 67 | unsigned int fpu_msk31; |
| 68 | unsigned int msa_id; |
| 69 | unsigned int cputype; |
| 70 | int isa_level; |
| 71 | int tlbsize; |
| 72 | int tlbsizevtlb; |
| 73 | int tlbsizeftlbsets; |
| 74 | int tlbsizeftlbways; |
| 75 | struct cache_desc icache; /* Primary I-cache */ |
| 76 | struct cache_desc dcache; /* Primary D or combined I/D cache */ |
| 77 | struct cache_desc vcache; /* Victim cache, between pcache and scache */ |
| 78 | struct cache_desc scache; /* Secondary cache */ |
| 79 | struct cache_desc tcache; /* Tertiary/split secondary cache */ |
| 80 | int srsets; /* Shadow register sets */ |
| 81 | int package;/* physical package number */ |
| 82 | unsigned int globalnumber; |
| 83 | #ifdef CONFIG_64BIT |
| 84 | int vmbits; /* Virtual memory size in bits */ |
| 85 | #endif |
| 86 | void *data; /* Additional data */ |
| 87 | unsigned int watch_reg_count; /* Number that exist */ |
| 88 | unsigned int watch_reg_use_cnt; /* Usable by ptrace */ |
| 89 | #define NUM_WATCH_REGS 4 |
| 90 | u16 watch_reg_masks[NUM_WATCH_REGS]; |
| 91 | unsigned int kscratch_mask; /* Usable KScratch mask. */ |
| 92 | /* |
| 93 | * Cache Coherency attribute for write-combine memory writes. |
| 94 | * (shifted by _CACHE_SHIFT) |
| 95 | */ |
| 96 | unsigned int writecombine; |
| 97 | /* |
| 98 | * Simple counter to prevent enabling HTW in nested |
| 99 | * htw_start/htw_stop calls |
| 100 | */ |
| 101 | unsigned int htw_seq; |
| 102 | |
| 103 | /* VZ & Guest features */ |
| 104 | struct guest_info guest; |
| 105 | unsigned int gtoffset_mask; |
| 106 | unsigned int guestid_mask; |
| 107 | unsigned int guestid_cache; |
| 108 | } __attribute__((aligned(SMP_CACHE_BYTES))); |
| 109 | |
| 110 | extern struct cpuinfo_mips cpu_data[]; |
| 111 | #define current_cpu_data cpu_data[smp_processor_id()] |
| 112 | #define raw_current_cpu_data cpu_data[raw_smp_processor_id()] |
| 113 | #define boot_cpu_data cpu_data[0] |
| 114 | |
| 115 | extern void cpu_probe(void); |
| 116 | extern void cpu_report(void); |
| 117 | |
| 118 | extern const char *__cpu_name[]; |
| 119 | #define cpu_name_string() __cpu_name[raw_smp_processor_id()] |
| 120 | |
| 121 | struct seq_file; |
| 122 | struct notifier_block; |
| 123 | |
| 124 | extern int register_proc_cpuinfo_notifier(struct notifier_block *nb); |
| 125 | extern int proc_cpuinfo_notifier_call_chain(unsigned long val, void *v); |
| 126 | |
| 127 | #define proc_cpuinfo_notifier(fn, pri) \ |
| 128 | ({ \ |
| 129 | static struct notifier_block fn##_nb = { \ |
| 130 | .notifier_call = fn, \ |
| 131 | .priority = pri \ |
| 132 | }; \ |
| 133 | \ |
| 134 | register_proc_cpuinfo_notifier(&fn##_nb); \ |
| 135 | }) |
| 136 | |
| 137 | struct proc_cpuinfo_notifier_args { |
| 138 | struct seq_file *m; |
| 139 | unsigned long n; |
| 140 | }; |
| 141 | |
| 142 | static inline unsigned int cpu_cluster(struct cpuinfo_mips *cpuinfo) |
| 143 | { |
| 144 | /* Optimisation for systems where multiple clusters aren't used */ |
| 145 | if (!IS_ENABLED(CONFIG_CPU_MIPSR6)) |
| 146 | return 0; |
| 147 | |
| 148 | return (cpuinfo->globalnumber & MIPS_GLOBALNUMBER_CLUSTER) >> |
| 149 | MIPS_GLOBALNUMBER_CLUSTER_SHF; |
| 150 | } |
| 151 | |
| 152 | static inline unsigned int cpu_core(struct cpuinfo_mips *cpuinfo) |
| 153 | { |
| 154 | return (cpuinfo->globalnumber & MIPS_GLOBALNUMBER_CORE) >> |
| 155 | MIPS_GLOBALNUMBER_CORE_SHF; |
| 156 | } |
| 157 | |
| 158 | static inline unsigned int cpu_vpe_id(struct cpuinfo_mips *cpuinfo) |
| 159 | { |
| 160 | /* Optimisation for systems where VP(E)s aren't used */ |
| 161 | if (!IS_ENABLED(CONFIG_MIPS_MT_SMP) && !IS_ENABLED(CONFIG_CPU_MIPSR6)) |
| 162 | return 0; |
| 163 | |
| 164 | return (cpuinfo->globalnumber & MIPS_GLOBALNUMBER_VP) >> |
| 165 | MIPS_GLOBALNUMBER_VP_SHF; |
| 166 | } |
| 167 | |
| 168 | extern void cpu_set_cluster(struct cpuinfo_mips *cpuinfo, unsigned int cluster); |
| 169 | extern void cpu_set_core(struct cpuinfo_mips *cpuinfo, unsigned int core); |
| 170 | extern void cpu_set_vpe_id(struct cpuinfo_mips *cpuinfo, unsigned int vpe); |
| 171 | |
| 172 | static inline bool cpus_are_siblings(int cpua, int cpub) |
| 173 | { |
| 174 | struct cpuinfo_mips *infoa = &cpu_data[cpua]; |
| 175 | struct cpuinfo_mips *infob = &cpu_data[cpub]; |
| 176 | unsigned int gnuma, gnumb; |
| 177 | |
| 178 | if (infoa->package != infob->package) |
| 179 | return false; |
| 180 | |
| 181 | gnuma = infoa->globalnumber & ~MIPS_GLOBALNUMBER_VP; |
| 182 | gnumb = infob->globalnumber & ~MIPS_GLOBALNUMBER_VP; |
| 183 | if (gnuma != gnumb) |
| 184 | return false; |
| 185 | |
| 186 | return true; |
| 187 | } |
| 188 | |
| 189 | static inline unsigned long cpu_asid_inc(void) |
| 190 | { |
| 191 | return 1 << CONFIG_MIPS_ASID_SHIFT; |
| 192 | } |
| 193 | |
| 194 | static inline unsigned long cpu_asid_mask(struct cpuinfo_mips *cpuinfo) |
| 195 | { |
| 196 | #ifdef CONFIG_MIPS_ASID_BITS_VARIABLE |
| 197 | return cpuinfo->asid_mask; |
| 198 | #endif |
| 199 | return ((1 << CONFIG_MIPS_ASID_BITS) - 1) << CONFIG_MIPS_ASID_SHIFT; |
| 200 | } |
| 201 | |
| 202 | static inline void set_cpu_asid_mask(struct cpuinfo_mips *cpuinfo, |
| 203 | unsigned long asid_mask) |
| 204 | { |
| 205 | #ifdef CONFIG_MIPS_ASID_BITS_VARIABLE |
| 206 | cpuinfo->asid_mask = asid_mask; |
| 207 | #endif |
| 208 | } |
| 209 | |
| 210 | #endif /* __ASM_CPU_INFO_H */ |