Branch data Line data Source code
1 : : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 : : /* Copyright 2013-2019 IBM Corp. */
3 : :
4 : : #ifndef __PROCESSOR_H
5 : : #define __PROCESSOR_H
6 : :
7 : : #include <bitutils.h>
8 : :
9 : : /* MSR bits */
10 : : #define MSR_SF PPC_BIT(0) /* 64-bit mode */
11 : : #define MSR_HV PPC_BIT(3) /* Hypervisor mode */
12 : : #define MSR_VEC PPC_BIT(38) /* VMX enable */
13 : : #define MSR_VSX PPC_BIT(40) /* VSX enable */
14 : : #define MSR_S PPC_BIT(41) /* Secure mode */
15 : : #define MSR_EE PPC_BIT(48) /* External Int. Enable */
16 : : #define MSR_PR PPC_BIT(49) /* Problem state */
17 : : #define MSR_FP PPC_BIT(50) /* Floating Point Enable */
18 : : #define MSR_ME PPC_BIT(51) /* Machine Check Enable */
19 : : #define MSR_FE0 PPC_BIT(52) /* FP Exception 0 */
20 : : #define MSR_SE PPC_BIT(53) /* Step enable */
21 : : #define MSR_BE PPC_BIT(54) /* Branch trace enable */
22 : : #define MSR_FE1 PPC_BIT(55) /* FP Exception 1 */
23 : : #define MSR_IR PPC_BIT(58) /* Instructions reloc */
24 : : #define MSR_DR PPC_BIT(59) /* Data reloc */
25 : : #define MSR_PMM PPC_BIT(61) /* Perf Monitor */
26 : : #define MSR_RI PPC_BIT(62) /* Recoverable Interrupt */
27 : : #define MSR_LE PPC_BIT(63) /* Little Endian */
28 : :
29 : : /* PIR */
30 : : #define SPR_PIR_P10_MASK 0x7fff /* Mask of implemented bits */
31 : : #define SPR_PIR_P9_MASK 0x7fff /* Mask of implemented bits */
32 : : #define SPR_PIR_P8_MASK 0x1fff /* Mask of implemented bits */
33 : :
34 : : /* SPR register definitions */
35 : : #define SPR_DSCR 0x011 /* RW: Data stream control reg */
36 : : #define SPR_DSISR 0x012 /* RW: Data storage interrupt status reg */
37 : : #define SPR_DAR 0x013 /* RW: Data address reg */
38 : : #define SPR_DEC 0x016 /* RW: Decrement Register */
39 : : #define SPR_SDR1 0x019
40 : : #define SPR_SRR0 0x01a /* RW: Exception save/restore reg 0 */
41 : : #define SPR_SRR1 0x01b /* RW: Exception save/restore reg 1 */
42 : : #define SPR_CFAR 0x01c /* RW: Come From Address Register */
43 : : #define SPR_AMR 0x01d /* RW: Authority Mask Register */
44 : : #define SPR_IAMR 0x03d /* RW: Instruction Authority Mask Register */
45 : : #define SPR_RPR 0x0ba /* RW: Relative Priority Register */
46 : : #define SPR_TBRL 0x10c /* RO: Timebase low */
47 : : #define SPR_TBRU 0x10d /* RO: Timebase high */
48 : : #define SPR_SPRC 0x114 /* RW: Access to uArch SPRs (ex SCOMC) */
49 : : #define SPR_SPRD 0x115 /* RW: Access to uArch SPRs (ex SCOMD) */
50 : : #define SPR_SCOMC 0x114 /* RW: SCOM Control - old name of SPRC */
51 : : #define SPR_SCOMD 0x115 /* RW: SCOM Data - old name of SPRD */
52 : : #define SPR_TBWL 0x11c /* RW: Timebase low */
53 : : #define SPR_TBWU 0x11d /* RW: Timebase high */
54 : : #define SPR_TBU40 0x11e /* RW: Timebase Upper 40 bit */
55 : : #define SPR_PVR 0x11f /* RO: Processor version register */
56 : : #define SPR_HSPRG0 0x130 /* RW: Hypervisor scratch 0 */
57 : : #define SPR_HSPRG1 0x131 /* RW: Hypervisor scratch 1 */
58 : : #define SPR_SPURR 0x134 /* RW: Scaled Processor Utilization Resource */
59 : : #define SPR_PURR 0x135 /* RW: Processor Utilization Resource reg */
60 : : #define SPR_HDEC 0x136 /* RW: Hypervisor Decrementer */
61 : : #define SPR_HRMOR 0x139 /* RW: Hypervisor Real Mode Offset reg */
62 : : #define SPR_HSRR0 0x13a /* RW: HV Exception save/restore reg 0 */
63 : : #define SPR_HSRR1 0x13b /* RW: HV Exception save/restore reg 1 */
64 : : #define SPR_TFMR 0x13d
65 : : #define SPR_LPCR 0x13e
66 : : #define SPR_HMER 0x150 /* Hypervisor Maintenance Exception */
67 : : #define SPR_HMEER 0x151 /* HMER interrupt enable mask */
68 : : #define SPR_PCR 0x152
69 : : #define SPR_AMOR 0x15d
70 : : #define SPR_USRR0 0x1fa /* RW: Ultravisor Save/Restore Register 0 */
71 : : #define SPR_USRR1 0x1fb /* RW: Ultravisor Save/Restore Register 1 */
72 : : #define SPR_SMFCTRL 0x1ff /* RW: Secure Memory Facility Control */
73 : : #define SPR_PSSCR 0x357 /* RW: Stop status and control (ISA 3) */
74 : : #define SPR_PPR32 0x382
75 : : #define SPR_TSCR 0x399
76 : : #define SPR_HID0 0x3f0
77 : : #define SPR_HID1 0x3f1
78 : : #define SPR_HID2 0x3f8
79 : : #define SPR_HID4 0x3f4
80 : : #define SPR_HID5 0x3f6
81 : : #define SPR_PIR 0x3ff /* RO: Processor Identification */
82 : :
83 : : /* Bits in SRR1 */
84 : :
85 : : #define SPR_SRR1_PM_WAKE_MASK 0x3c0000 /* PM wake reason for P8/9 */
86 : : #define SPR_SRR1_PM_WAKE_SRESET 0x100000
87 : : #define SPR_SRR1_PM_WAKE_MCE 0x3c0000 /* Use reserved value for MCE */
88 : :
89 : : /* Bits in LPCR */
90 : :
91 : : /* Powersave Exit Cause Enable is different on each generation */
92 : : #define SPR_LPCR_P8_PECE PPC_BITMASK(47,51)
93 : : #define SPR_LPCR_P8_PECE0 PPC_BIT(47) /* Wake on priv doorbell */
94 : : #define SPR_LPCR_P8_PECE1 PPC_BIT(48) /* Wake on hv doorbell */
95 : : #define SPR_LPCR_P8_PECE2 PPC_BIT(49) /* Wake on external interrupts */
96 : : #define SPR_LPCR_P8_PECE3 PPC_BIT(50) /* Wake on decrementer */
97 : : #define SPR_LPCR_P8_PECE4 PPC_BIT(51) /* Wake on MCs, HMIs, etc... */
98 : :
99 : : #define SPR_LPCR_P9_PECE (PPC_BITMASK(47,51) | PPC_BITMASK(17,17))
100 : : #define SPR_LPCR_P9_PECEU0 PPC_BIT(17) /* Wake on HVI */
101 : : #define SPR_LPCR_P9_PECEL0 PPC_BIT(47) /* Wake on priv doorbell */
102 : : #define SPR_LPCR_P9_PECEL1 PPC_BIT(48) /* Wake on hv doorbell */
103 : : #define SPR_LPCR_P9_PECEL2 PPC_BIT(49) /* Wake on external interrupts */
104 : : #define SPR_LPCR_P9_PECEL3 PPC_BIT(50) /* Wake on decrementer */
105 : : #define SPR_LPCR_P9_PECEL4 PPC_BIT(51) /* Wake on MCs, HMIs, etc... */
106 : : #define SPR_LPCR_P9_LD PPC_BIT(46) /* Large decrementer mode bit */
107 : :
108 : :
109 : : /* Bits in TFMR - control bits */
110 : : #define SPR_TFMR_MAX_CYC_BET_STEPS PPC_BITMASK(0,7)
111 : : #define SPR_TFMR_N_CLKS_PER_STEP PPC_BITMASK(8,9)
112 : : #define SPR_TFMR_MASK_HMI PPC_BIT(10)
113 : : #define SPR_TFMR_SYNC_BIT_SEL PPC_BITMASK(11,13)
114 : : #define SPR_TFMR_TB_ECLIPZ PPC_BIT(14)
115 : : #define SPR_TFMR_LOAD_TOD_MOD PPC_BIT(16)
116 : : #define SPR_TFMR_MOVE_CHIP_TOD_TO_TB PPC_BIT(18)
117 : : #define SPR_TFMR_CLEAR_TB_ERRORS PPC_BIT(24)
118 : : /* Bits in TFMR - thread indep. status bits */
119 : : #define SPR_TFMR_TFAC_XFER_ERROR PPC_BIT(25)
120 : : #define SPR_TFMR_HDEC_PARITY_ERROR PPC_BIT(26)
121 : : #define SPR_TFMR_TBST_CORRUPT PPC_BIT(27)
122 : : #define SPR_TFMR_TBST_ENCODED PPC_BITMASK(28,31)
123 : : #define SPR_TFMR_TBST_LAST PPC_BITMASK(32,35)
124 : : #define SPR_TFMR_TB_ENABLED PPC_BIT(40)
125 : : #define SPR_TFMR_TB_VALID PPC_BIT(41)
126 : : #define SPR_TFMR_TB_SYNC_OCCURED PPC_BIT(42)
127 : : #define SPR_TFMR_TB_MISSING_SYNC PPC_BIT(43)
128 : : #define SPR_TFMR_TB_MISSING_STEP PPC_BIT(44)
129 : : #define SPR_TFMR_TB_RESIDUE_ERR PPC_BIT(45)
130 : : #define SPR_TFMR_FW_CONTROL_ERR PPC_BIT(46)
131 : : #define SPR_TFMR_CHIP_TOD_STATUS PPC_BITMASK(47,50)
132 : : #define SPR_TFMR_CHIP_TOD_INTERRUPT PPC_BIT(51)
133 : : #define SPR_TFMR_CHIP_TOD_TIMEOUT PPC_BIT(54)
134 : : #define SPR_TFMR_CHIP_TOD_PARITY_ERR PPC_BIT(56)
135 : : /* Bits in TFMR - thread specific. status bits */
136 : : #define SPR_TFMR_PURR_PARITY_ERR PPC_BIT(57)
137 : : #define SPR_TFMR_SPURR_PARITY_ERR PPC_BIT(58)
138 : : #define SPR_TFMR_DEC_PARITY_ERR PPC_BIT(59)
139 : : #define SPR_TFMR_TFMR_CORRUPT PPC_BIT(60)
140 : : #define SPR_TFMR_PURR_OVERFLOW PPC_BIT(61)
141 : : #define SPR_TFMR_SPURR_OVERFLOW PPC_BIT(62)
142 : :
143 : : /* Bits in HMER/HMEER */
144 : : #define SPR_HMER_MALFUNCTION_ALERT PPC_BIT(0)
145 : : #define SPR_HMER_PROC_RECV_DONE PPC_BIT(2)
146 : : #define SPR_HMER_PROC_RECV_ERROR_MASKED PPC_BIT(3) /* Not P10 */
147 : : #define SPR_HMER_TFAC_ERROR PPC_BIT(4)
148 : : #define SPR_HMER_TFMR_PARITY_ERROR PPC_BIT(5) /* P9 */
149 : : #define SPR_HMER_TFAC_SHADOW_XFER_ERROR PPC_BIT(5) /* P10 */
150 : : #define SPR_HMER_SPURR_SCALE_LIMIT PPC_BIT(6) /* P10 */
151 : : #define SPR_HMER_XSCOM_FAIL PPC_BIT(8)
152 : : #define SPR_HMER_XSCOM_DONE PPC_BIT(9)
153 : : #define SPR_HMER_PROC_RECV_AGAIN PPC_BIT(11)
154 : : #define SPR_HMER_WARN_RISE PPC_BIT(14) /* Not P10 */
155 : : #define SPR_HMER_WARN_FALL PPC_BIT(15) /* Not P10 */
156 : : #define SPR_HMER_SCOM_FIR_HMI PPC_BIT(16)
157 : : #define SPR_HMER_TRIG_FIR_HMI PPC_BIT(17) /* Not P10 */
158 : : #define SPR_HMER_THD_WAKE_BLOCKED_TM_SUSPEND PPC_BIT(17) /* Not P10 */
159 : : #define SPR_HMER_P10_TRIG_FIR_HMI PPC_BIT(18)
160 : : #define SPR_HMER_HYP_RESOURCE_ERR PPC_BIT(20) /* Not P10 */
161 : : #define SPR_HMER_XSCOM_STATUS PPC_BITMASK(21,23)
162 : :
163 : : /*
164 : : * HMEER: initial bits for HMI interrupt enable mask.
165 : : * Per Dave Larson, never enable 8,9,21-23
166 : : */
167 : : #define SPR_HMEER_HMI_ENABLE_MASK (SPR_HMER_MALFUNCTION_ALERT |\
168 : : SPR_HMER_HYP_RESOURCE_ERR |\
169 : : SPR_HMER_PROC_RECV_DONE |\
170 : : SPR_HMER_PROC_RECV_ERROR_MASKED |\
171 : : SPR_HMER_TFAC_ERROR |\
172 : : SPR_HMER_TFMR_PARITY_ERROR |\
173 : : SPR_HMER_PROC_RECV_AGAIN)
174 : :
175 : : #define SPR_HMEER_P10_HMI_ENABLE_MASK (SPR_HMER_MALFUNCTION_ALERT |\
176 : : SPR_HMER_PROC_RECV_DONE |\
177 : : SPR_HMER_TFAC_ERROR |\
178 : : SPR_HMER_TFAC_SHADOW_XFER_ERROR |\
179 : : SPR_HMER_SPURR_SCALE_LIMIT |\
180 : : SPR_HMER_PROC_RECV_AGAIN)
181 : :
182 : : /* Bits in HID0 */
183 : : #define SPR_HID0_POWER8_4LPARMODE PPC_BIT(2)
184 : : #define SPR_HID0_POWER8_2LPARMODE PPC_BIT(6)
185 : : #define SPR_HID0_POWER8_DYNLPARDIS PPC_BIT(15)
186 : : #define SPR_HID0_POWER8_HILE PPC_BIT(19)
187 : : #define SPR_HID0_POWER9_HILE PPC_BIT(4)
188 : : #define SPR_HID0_POWER10_HILE PPC_BIT(4)
189 : : #define SPR_HID0_POWER8_ENABLE_ATTN PPC_BIT(31)
190 : : #define SPR_HID0_POWER9_ENABLE_ATTN PPC_BIT(3)
191 : : #define SPR_HID0_POWER10_ENABLE_ATTN PPC_BIT(3)
192 : : #define SPR_HID0_POWER9_FLUSH_ICACHE PPC_BIT(2)
193 : : #define SPR_HID0_POWER10_FLUSH_ICACHE PPC_BIT(2)
194 : : #define SPR_HID0_POWER9_RADIX PPC_BIT(8)
195 : :
196 : : /* PVR bits */
197 : : #define SPR_PVR_TYPE 0xffff0000
198 : : #define SPR_PVR_CHIP_TYPE 0x0000f000
199 : : #define SPR_PVR_VERS_MAJ 0x00000f00
200 : : #define SPR_PVR_VERS_MIN 0x000000ff
201 : :
202 : : #define PVR_TYPE(_pvr) GETFIELD(SPR_PVR_TYPE, _pvr)
203 : : #define PVR_CHIP_TYPE(_pvr) GETFIELD(SPR_PVR_CHIP_TYPE, _pvr)
204 : : #define PVR_VERS_MAJ(_pvr) GETFIELD(SPR_PVR_VERS_MAJ, _pvr)
205 : : #define PVR_VERS_MIN(_pvr) GETFIELD(SPR_PVR_VERS_MIN, _pvr)
206 : :
207 : : /* PVR definitions */
208 : : #define PVR_TYPE_P8E 0x004b /* Murano */
209 : : #define PVR_TYPE_P8 0x004d /* Venice */
210 : : #define PVR_TYPE_P8NVL 0x004c /* Naples */
211 : : #define PVR_TYPE_P9 0x004e
212 : : #define PVR_TYPE_P9P 0x004f /* Axone */
213 : : #define PVR_TYPE_P10 0x0080
214 : :
215 : : #ifdef __ASSEMBLY__
216 : :
217 : : /* Thread priority control opcodes */
218 : : #define smt_low or 1,1,1
219 : : #define smt_medium or 2,2,2
220 : : #define smt_high or 3,3,3
221 : : #define smt_medium_high or 5,5,5
222 : : #define smt_medium_low or 6,6,6
223 : : #define smt_extra_high or 7,7,7
224 : : #define smt_very_low or 31,31,31
225 : : #define smt_lowest smt_low ; smt_very_low
226 : :
227 : : #else /* __ASSEMBLY__ */
228 : :
229 : : #include <ccan/str/str.h>
230 : : #include <compiler.h>
231 : : #include <stdbool.h>
232 : : #include <stdint.h>
233 : :
234 : : #define PPC_INST_NOP 0x60000000UL
235 : : #define PPC_INST_TRAP 0x7fe00008UL
236 : :
237 : : #define RB(b) (((b) & 0x1f) << 11)
238 : : #define MSGSND(b) stringify(.long 0x7c00019c | RB(b))
239 : : #define MSGCLR(b) stringify(.long 0x7c0001dc | RB(b))
240 : : #define MSGSYNC stringify(.long 0x7c0006ec)
241 : :
242 : 4 : static inline bool is_power9n(uint32_t version)
243 : : {
244 : 4 : if (PVR_TYPE(version) != PVR_TYPE_P9)
245 : 0 : return false;
246 : : /*
247 : : * Bit 13 tells us:
248 : : * 0 = Scale out (aka Nimbus)
249 : : * 1 = Scale up (aka Cumulus)
250 : : */
251 : 4 : if ((version >> 13) & 1)
252 : 0 : return false;
253 : 4 : return true;
254 : : }
255 : :
256 : : static inline bool is_fused_core(uint32_t version)
257 : : {
258 : : if (PVR_TYPE(version) == PVR_TYPE_P9) {
259 : : switch(PVR_CHIP_TYPE(version)) {
260 : : case 0:
261 : : case 2:
262 : : return true;
263 : : default:
264 : : return false;
265 : : }
266 : :
267 : : } else if(PVR_TYPE(version) == PVR_TYPE_P10) {
268 : : if(PVR_CHIP_TYPE(version) & 0x01)
269 : : return false;
270 : : else
271 : : return true;
272 : : } else
273 : : return false;
274 : : }
275 : :
276 : 0 : static inline bool is_power9c(uint32_t version)
277 : : {
278 : :
279 : 0 : if (PVR_TYPE(version) != PVR_TYPE_P9)
280 : 0 : return false;
281 : : /*
282 : : * Bit 13 tells us:
283 : : * 0 = Scale out (aka Nimbus)
284 : : * 1 = Scale up (aka Cumulus)
285 : : */
286 : 0 : if (!((version >> 13) & 1))
287 : 0 : return false;
288 : 0 : return true;
289 : : }
290 : :
291 : : #ifndef __TEST__
292 : :
293 : : /* POWER9 and above only */
294 : : static inline void flush_erat(void)
295 : : {
296 : : asm volatile("slbia 7");
297 : : }
298 : :
299 : : /*
300 : : * SMT priority
301 : : */
302 : :
303 : : static inline void smt_low(void) { asm volatile("or 1,1,1"); }
304 : : static inline void smt_medium(void) { asm volatile("or 2,2,2"); }
305 : : static inline void smt_high(void) { asm volatile("or 3,3,3"); }
306 : : static inline void smt_medium_high(void){ asm volatile("or 5,5,5"); }
307 : : static inline void smt_medium_low(void) { asm volatile("or 6,6,6"); }
308 : : static inline void smt_extra_high(void) { asm volatile("or 7,7,7"); }
309 : : static inline void smt_very_low(void) { asm volatile("or 31,31,31"); }
310 : : static inline void smt_lowest(void) { smt_low(); smt_very_low(); }
311 : :
312 : : /*
313 : : * SPR access functions
314 : : */
315 : :
316 : : static inline unsigned long mfmsr(void)
317 : : {
318 : : unsigned long val;
319 : :
320 : : asm volatile("mfmsr %0" : "=r"(val) : : "memory");
321 : : return val;
322 : : }
323 : :
324 : : static inline void mtmsr(unsigned long val)
325 : : {
326 : : asm volatile("mtmsr %0" : : "r"(val) : "memory");
327 : : }
328 : :
329 : : static inline void mtmsrd(unsigned long val, int l)
330 : : {
331 : : asm volatile("mtmsrd %0,%1" : : "r"(val), "i"(l) : "memory");
332 : : }
333 : :
334 : : static inline __attribute__((always_inline))
335 : : unsigned long mfspr(const unsigned int spr)
336 : : {
337 : : unsigned long val;
338 : :
339 : : asm volatile("mfspr %0,%1" : "=r"(val) : "i"(spr) : "memory");
340 : : return val;
341 : : }
342 : :
343 : : static inline __attribute__((always_inline))
344 : : void mtspr(const unsigned int spr, unsigned long val)
345 : : {
346 : : asm volatile("mtspr %0,%1" : : "i"(spr), "r"(val) : "memory");
347 : : }
348 : :
349 : : /* Helpers for special sequences needed by some registers */
350 : : extern void set_hid0(unsigned long hid0);
351 : : extern void trigger_attn(void);
352 : :
353 : : /*
354 : : * Barriers
355 : : */
356 : :
357 : : static inline void eieio(void)
358 : : {
359 : : asm volatile("eieio" : : : "memory");
360 : : }
361 : :
362 : : static inline void sync(void)
363 : : {
364 : : asm volatile("sync" : : : "memory");
365 : : }
366 : :
367 : : static inline void lwsync(void)
368 : : {
369 : : asm volatile("lwsync" : : : "memory");
370 : : }
371 : :
372 : : static inline void isync(void)
373 : : {
374 : : asm volatile("isync" : : : "memory");
375 : : }
376 : :
377 : :
378 : : /*
379 : : * Cache sync
380 : : */
381 : : static inline void sync_icache(void)
382 : : {
383 : : asm volatile("sync; icbi 0,%0; sync; isync" : : "r" (0) : "memory");
384 : : }
385 : :
386 : : /*
387 : : * Doorbells
388 : : */
389 : : static inline void msgclr(void)
390 : : {
391 : : uint64_t rb = (0x05 << (63-36));
392 : : asm volatile(MSGCLR(%0) : : "r"(rb));
393 : : }
394 : :
395 : : static inline void p9_dbell_receive(void)
396 : : {
397 : : uint64_t rb = (0x05 << (63-36));
398 : : asm volatile(MSGCLR(%0) ";"
399 : : MSGSYNC ";"
400 : : "lwsync"
401 : : : : "r"(rb));
402 : : }
403 : :
404 : : static inline void p9_dbell_send(uint32_t pir)
405 : : {
406 : : uint64_t rb = (0x05 << (63-36)) | pir;
407 : : asm volatile("sync ;"
408 : : MSGSND(%0)
409 : : : : "r"(rb));
410 : : }
411 : :
412 : : /*
413 : : * Byteswap load/stores
414 : : */
415 : :
416 : : static inline uint16_t ld_le16(const uint16_t *addr)
417 : : {
418 : : uint16_t val;
419 : : asm volatile("lhbrx %0,0,%1" : "=r"(val) : "r"(addr), "m"(*addr));
420 : : return val;
421 : : }
422 : :
423 : : static inline uint32_t ld_le32(const uint32_t *addr)
424 : : {
425 : : uint32_t val;
426 : : asm volatile("lwbrx %0,0,%1" : "=r"(val) : "r"(addr), "m"(*addr));
427 : : return val;
428 : : }
429 : :
430 : : static inline void st_le16(uint16_t *addr, uint16_t val)
431 : : {
432 : : asm volatile("sthbrx %0,0,%1" : : "r"(val), "r"(addr), "m"(*addr));
433 : : }
434 : :
435 : : static inline void st_le32(uint32_t *addr, uint32_t val)
436 : : {
437 : : asm volatile("stwbrx %0,0,%1" : : "r"(val), "r"(addr), "m"(*addr));
438 : : }
439 : :
440 : : #endif /* __TEST__ */
441 : :
442 : : #endif /* __ASSEMBLY__ */
443 : :
444 : : #endif /* __PROCESSOR_H */
|