Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
1da177e4 | 2 | /* |
1da177e4 | 3 | * S390 version |
a53c8fab | 4 | * Copyright IBM Corp. 1999 |
1da177e4 LT |
5 | * Author(s): Hartmut Penner (hp@de.ibm.com), |
6 | * Martin Schwidefsky (schwidefsky@de.ibm.com) | |
7 | * | |
8 | * Derived from "include/asm-i386/processor.h" | |
9 | * Copyright (C) 1994, Linus Torvalds | |
10 | */ | |
11 | ||
12 | #ifndef __ASM_S390_PROCESSOR_H | |
13 | #define __ASM_S390_PROCESSOR_H | |
14 | ||
fe6ba88b | 15 | #include <linux/bits.h> |
92778b99 | 16 | |
c239c83e | 17 | #define CIF_SIE 0 /* CPU needs SIE exit cleanup */ |
0b0ed657 | 18 | #define CIF_NOHZ_DELAY 2 /* delay HZ disable for a tick */ |
0b0ed657 SS |
19 | #define CIF_ENABLED_WAIT 5 /* in enabled wait state */ |
20 | #define CIF_MCCK_GUEST 6 /* machine check happening in guest */ | |
21 | #define CIF_DEDICATED_CPU 7 /* this CPU is dedicated */ | |
d3a73acb | 22 | |
c239c83e | 23 | #define _CIF_SIE BIT(CIF_SIE) |
fe6ba88b | 24 | #define _CIF_NOHZ_DELAY BIT(CIF_NOHZ_DELAY) |
fe6ba88b MY |
25 | #define _CIF_ENABLED_WAIT BIT(CIF_ENABLED_WAIT) |
26 | #define _CIF_MCCK_GUEST BIT(CIF_MCCK_GUEST) | |
27 | #define _CIF_DEDICATED_CPU BIT(CIF_DEDICATED_CPU) | |
d3a73acb | 28 | |
915fea04 AG |
29 | #define RESTART_FLAG_CTLREGS _AC(1 << 0, U) |
30 | ||
eb608fb3 HC |
31 | #ifndef __ASSEMBLY__ |
32 | ||
38f2c691 | 33 | #include <linux/cpumask.h> |
edd53787 | 34 | #include <linux/linkage.h> |
a0616cde | 35 | #include <linux/irqflags.h> |
fd2527f2 | 36 | #include <asm/fpu-types.h> |
e86a6ed6 | 37 | #include <asm/cpu.h> |
25097bf1 | 38 | #include <asm/page.h> |
1da177e4 | 39 | #include <asm/ptrace.h> |
25097bf1 | 40 | #include <asm/setup.h> |
e4b8b3f3 | 41 | #include <asm/runtime_instr.h> |
56e62a73 | 42 | #include <asm/irqflags.h> |
fa2ae4a3 | 43 | #include <asm/alternative.h> |
56e62a73 | 44 | |
3a790cc1 | 45 | typedef long (*sys_call_ptr_t)(struct pt_regs *regs); |
1da177e4 | 46 | |
87f79d88 | 47 | static __always_inline void set_cpu_flag(int flag) |
d3a73acb | 48 | { |
ac25e790 | 49 | S390_lowcore.cpu_flags |= (1UL << flag); |
d3a73acb MS |
50 | } |
51 | ||
87f79d88 | 52 | static __always_inline void clear_cpu_flag(int flag) |
d3a73acb | 53 | { |
ac25e790 | 54 | S390_lowcore.cpu_flags &= ~(1UL << flag); |
d3a73acb MS |
55 | } |
56 | ||
b977f03e | 57 | static __always_inline bool test_cpu_flag(int flag) |
d3a73acb | 58 | { |
b977f03e | 59 | return S390_lowcore.cpu_flags & (1UL << flag); |
d3a73acb MS |
60 | } |
61 | ||
f96f41aa HC |
62 | static __always_inline bool test_and_set_cpu_flag(int flag) |
63 | { | |
64 | if (test_cpu_flag(flag)) | |
65 | return true; | |
66 | set_cpu_flag(flag); | |
67 | return false; | |
68 | } | |
69 | ||
70 | static __always_inline bool test_and_clear_cpu_flag(int flag) | |
71 | { | |
72 | if (!test_cpu_flag(flag)) | |
73 | return false; | |
74 | clear_cpu_flag(flag); | |
75 | return true; | |
76 | } | |
77 | ||
419123f9 MS |
78 | /* |
79 | * Test CIF flag of another CPU. The caller needs to ensure that | |
80 | * CPU hotplug can not happen, e.g. by disabling preemption. | |
81 | */ | |
b977f03e | 82 | static __always_inline bool test_cpu_flag_of(int flag, int cpu) |
419123f9 | 83 | { |
c667aeac | 84 | struct lowcore *lc = lowcore_ptr[cpu]; |
b977f03e HC |
85 | |
86 | return lc->cpu_flags & (1UL << flag); | |
419123f9 MS |
87 | } |
88 | ||
fe0f4976 MS |
89 | #define arch_needs_cpu() test_cpu_flag(CIF_NOHZ_DELAY) |
90 | ||
e86a6ed6 | 91 | static inline void get_cpu_id(struct cpuid *ptr) |
72960a02 | 92 | { |
987bcdac | 93 | asm volatile("stidp %0" : "=Q" (*ptr)); |
72960a02 MH |
94 | } |
95 | ||
fa2ae4a3 SS |
96 | static __always_inline unsigned long get_cpu_timer(void) |
97 | { | |
98 | unsigned long timer; | |
99 | ||
100 | asm volatile("stpt %[timer]" : [timer] "=Q" (timer)); | |
101 | return timer; | |
102 | } | |
103 | ||
097a116c HC |
104 | void s390_adjust_jiffies(void); |
105 | void s390_update_cpu_mhz(void); | |
106 | void cpu_detect_mhz_feature(void); | |
107 | ||
638ad34a | 108 | extern const struct seq_operations cpuinfo_op; |
65f22a90 | 109 | extern void execve_tail(void); |
62b672c4 | 110 | unsigned long vdso_text_size(void); |
57761da4 | 111 | unsigned long vdso_size(void); |
1da177e4 | 112 | |
1da177e4 | 113 | /* |
f481bfaf | 114 | * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit. |
1da177e4 | 115 | */ |
1da177e4 | 116 | |
c4538d0f | 117 | #define TASK_SIZE (test_thread_flag(TIF_31BIT) ? \ |
f7555608 | 118 | _REGION3_SIZE : TASK_SIZE_MAX) |
5a216a20 | 119 | #define TASK_UNMAPPED_BASE (test_thread_flag(TIF_31BIT) ? \ |
f7555608 | 120 | (_REGION3_SIZE >> 1) : (_REGION2_SIZE >> 1)) |
1aea9b3f | 121 | #define TASK_SIZE_MAX (-PAGE_SIZE) |
1da177e4 | 122 | |
9e37a2e8 SS |
123 | #define VDSO_BASE (STACK_TOP + PAGE_SIZE) |
124 | #define VDSO_LIMIT (test_thread_flag(TIF_31BIT) ? _REGION3_SIZE : _REGION2_SIZE) | |
125 | #define STACK_TOP (VDSO_LIMIT - vdso_size() - PAGE_SIZE) | |
126 | #define STACK_TOP_MAX (_REGION2_SIZE - vdso_size() - PAGE_SIZE) | |
922a70d3 | 127 | |
1da177e4 LT |
128 | #define HAVE_ARCH_PICK_MMAP_LAYOUT |
129 | ||
2a405f6b HC |
130 | #define __stackleak_poison __stackleak_poison |
131 | static __always_inline void __stackleak_poison(unsigned long erase_low, | |
132 | unsigned long erase_high, | |
133 | unsigned long poison) | |
134 | { | |
135 | unsigned long tmp, count; | |
136 | ||
137 | count = erase_high - erase_low; | |
138 | if (!count) | |
139 | return; | |
140 | asm volatile( | |
141 | " cghi %[count],8\n" | |
142 | " je 2f\n" | |
143 | " aghi %[count],-(8+1)\n" | |
144 | " srlg %[tmp],%[count],8\n" | |
145 | " ltgr %[tmp],%[tmp]\n" | |
146 | " jz 1f\n" | |
147 | "0: stg %[poison],0(%[addr])\n" | |
148 | " mvc 8(256-8,%[addr]),0(%[addr])\n" | |
149 | " la %[addr],256(%[addr])\n" | |
150 | " brctg %[tmp],0b\n" | |
151 | "1: stg %[poison],0(%[addr])\n" | |
152 | " larl %[tmp],3f\n" | |
153 | " ex %[count],0(%[tmp])\n" | |
154 | " j 4f\n" | |
155 | "2: stg %[poison],0(%[addr])\n" | |
156 | " j 4f\n" | |
157 | "3: mvc 8(1,%[addr]),0(%[addr])\n" | |
158 | "4:\n" | |
159 | : [addr] "+&a" (erase_low), [count] "+&d" (count), [tmp] "=&a" (tmp) | |
160 | : [poison] "d" (poison) | |
161 | : "memory", "cc" | |
162 | ); | |
163 | } | |
164 | ||
1da177e4 LT |
165 | /* |
166 | * Thread structure | |
167 | */ | |
168 | struct thread_struct { | |
1da177e4 | 169 | unsigned int acrs[NUM_ACRS]; |
56e62a73 SS |
170 | unsigned long ksp; /* kernel stack pointer */ |
171 | unsigned long user_timer; /* task cputime in user space */ | |
172 | unsigned long guest_timer; /* task cputime in kvm guest */ | |
173 | unsigned long system_timer; /* task cputime in kernel space */ | |
174 | unsigned long hardirq_timer; /* task cputime in hardirq context */ | |
175 | unsigned long softirq_timer; /* task cputime in softirq context */ | |
176 | const sys_call_ptr_t *sys_call_table; /* system call table address */ | |
177 | unsigned long gmap_addr; /* address of last gmap fault. */ | |
178 | unsigned int gmap_write_flag; /* gmap fault write indication */ | |
179 | unsigned int gmap_int_code; /* int code of last gmap fault */ | |
180 | unsigned int gmap_pfault; /* signal of a pending guest pfault */ | |
8c09871a | 181 | int ufpu_flags; /* user fpu flags */ |
4eed43de | 182 | int kfpu_flags; /* kernel fpu flags */ |
56e62a73 | 183 | |
f8fc82b4 | 184 | /* Per-thread information related to debugging */ |
56e62a73 SS |
185 | struct per_regs per_user; /* User specified PER registers */ |
186 | struct per_event per_event; /* Cause of the last PER trap */ | |
187 | unsigned long per_flags; /* Flags to control debug behavior */ | |
188 | unsigned int system_call; /* system call number in signal */ | |
189 | unsigned long last_break; /* last breaking-event-address. */ | |
190 | /* pfault_wait is used to block the process on a pfault event */ | |
1da177e4 | 191 | unsigned long pfault_wait; |
f2db2e6c | 192 | struct list_head list; |
e4b8b3f3 JG |
193 | /* cpu runtime instrumentation */ |
194 | struct runtime_instr_cb *ri_cb; | |
56e62a73 SS |
195 | struct gs_cb *gs_cb; /* Current guarded storage cb */ |
196 | struct gs_cb *gs_bc_cb; /* Broadcast guarded storage cb */ | |
755112b3 | 197 | struct pgm_tdb trap_tdb; /* Transaction abort diagnose block */ |
87c5c700 | 198 | struct fpu ufpu; /* User FP and VX register save area */ |
4eed43de | 199 | struct fpu kfpu; /* Kernel FP and VX register save area */ |
1da177e4 LT |
200 | }; |
201 | ||
64597f9d MM |
202 | /* Flag to disable transactions. */ |
203 | #define PER_FLAG_NO_TE 1UL | |
204 | /* Flag to enable random transaction aborts. */ | |
205 | #define PER_FLAG_TE_ABORT_RAND 2UL | |
206 | /* Flag to specify random transaction abort mode: | |
207 | * - abort each transaction at a random instruction before TEND if set. | |
208 | * - abort random transactions at a random instruction if cleared. | |
209 | */ | |
210 | #define PER_FLAG_TE_ABORT_RAND_TEND 4UL | |
d35339a4 | 211 | |
1da177e4 LT |
212 | typedef struct thread_struct thread_struct; |
213 | ||
1da177e4 LT |
214 | #define ARCH_MIN_TASKALIGN 8 |
215 | ||
6f3fa3f0 MS |
216 | #define INIT_THREAD { \ |
217 | .ksp = sizeof(init_stack) + (unsigned long) &init_stack, \ | |
0b38b5e1 | 218 | .last_break = 1, \ |
6f3fa3f0 | 219 | } |
1da177e4 LT |
220 | |
221 | /* | |
222 | * Do necessary setup to start up a new thread. | |
223 | */ | |
b50511e4 | 224 | #define start_thread(regs, new_psw, new_stackp) do { \ |
e258d719 | 225 | regs->psw.mask = PSW_USER_BITS | PSW_MASK_EA | PSW_MASK_BA; \ |
fecc868a | 226 | regs->psw.addr = new_psw; \ |
b50511e4 | 227 | regs->gprs[15] = new_stackp; \ |
65f22a90 | 228 | execve_tail(); \ |
63506c41 MS |
229 | } while (0) |
230 | ||
b50511e4 | 231 | #define start_thread31(regs, new_psw, new_stackp) do { \ |
e258d719 | 232 | regs->psw.mask = PSW_USER_BITS | PSW_MASK_BA; \ |
fecc868a | 233 | regs->psw.addr = new_psw; \ |
b50511e4 | 234 | regs->gprs[15] = new_stackp; \ |
65f22a90 | 235 | execve_tail(); \ |
1da177e4 LT |
236 | } while (0) |
237 | ||
1da177e4 LT |
238 | struct task_struct; |
239 | struct mm_struct; | |
df5f8314 | 240 | struct seq_file; |
b5a882fc | 241 | struct pt_regs; |
1da177e4 | 242 | |
b5a882fc | 243 | void show_registers(struct pt_regs *regs); |
5a79859a | 244 | void show_cacheinfo(struct seq_file *m); |
6668022c | 245 | |
7b83c629 HC |
246 | /* Free guarded storage control block */ |
247 | void guarded_storage_release(struct task_struct *tsk); | |
56e62a73 | 248 | void gs_load_bc_cb(struct pt_regs *regs); |
916cda1a | 249 | |
42a20f86 | 250 | unsigned long __get_wchan(struct task_struct *p); |
c7584fb6 | 251 | #define task_pt_regs(tsk) ((struct pt_regs *) \ |
30af7120 | 252 | (task_stack_page(tsk) + THREAD_SIZE) - 1) |
c7584fb6 AV |
253 | #define KSTK_EIP(tsk) (task_pt_regs(tsk)->psw.addr) |
254 | #define KSTK_ESP(tsk) (task_pt_regs(tsk)->gprs[15]) | |
1da177e4 | 255 | |
5ebf250d HC |
256 | /* Has task runtime instrumentation enabled ? */ |
257 | #define is_ri_task(tsk) (!!(tsk)->thread.ri_cb) | |
258 | ||
e3c11025 VG |
259 | /* avoid using global register due to gcc bug in versions < 8.4 */ |
260 | #define current_stack_pointer (__current_stack_pointer()) | |
261 | ||
262 | static __always_inline unsigned long __current_stack_pointer(void) | |
263 | { | |
264 | unsigned long sp; | |
265 | ||
266 | asm volatile("lgr %0,15" : "=d" (sp)); | |
267 | return sp; | |
268 | } | |
76737ce1 | 269 | |
22ca1e77 HC |
270 | static __always_inline bool on_thread_stack(void) |
271 | { | |
272 | unsigned long ksp = S390_lowcore.kernel_stack; | |
273 | ||
274 | return !((ksp ^ current_stack_pointer) & ~(THREAD_SIZE - 1)); | |
275 | } | |
276 | ||
9c9a915a | 277 | static __always_inline unsigned short stap(void) |
a0616cde DH |
278 | { |
279 | unsigned short cpu_address; | |
280 | ||
11776eaa | 281 | asm volatile("stap %0" : "=Q" (cpu_address)); |
a0616cde DH |
282 | return cpu_address; |
283 | } | |
284 | ||
22b6430d | 285 | #define cpu_relax() barrier() |
083986e8 | 286 | |
097a116c HC |
287 | #define ECAG_CACHE_ATTRIBUTE 0 |
288 | #define ECAG_CPU_ATTRIBUTE 1 | |
289 | ||
290 | static inline unsigned long __ecag(unsigned int asi, unsigned char parm) | |
291 | { | |
292 | unsigned long val; | |
293 | ||
731efc96 | 294 | asm volatile("ecag %0,0,0(%1)" : "=d" (val) : "a" (asi << 8 | parm)); |
097a116c HC |
295 | return val; |
296 | } | |
297 | ||
dc74d7f9 HC |
298 | static inline void psw_set_key(unsigned int key) |
299 | { | |
300 | asm volatile("spka 0(%0)" : : "d" (key)); | |
301 | } | |
302 | ||
77fa2245 HC |
303 | /* |
304 | * Set PSW to specified value. | |
305 | */ | |
306 | static inline void __load_psw(psw_t psw) | |
307 | { | |
987bcdac | 308 | asm volatile("lpswe %0" : : "Q" (psw) : "cc"); |
77fa2245 HC |
309 | } |
310 | ||
1da177e4 LT |
311 | /* |
312 | * Set PSW mask to specified value, while leaving the | |
313 | * PSW addr pointing to the next instruction. | |
314 | */ | |
9c9a915a | 315 | static __always_inline void __load_psw_mask(unsigned long mask) |
1da177e4 | 316 | { |
7278a8fb | 317 | psw_t psw __uninitialized; |
1da177e4 | 318 | unsigned long addr; |
77fa2245 | 319 | |
1da177e4 LT |
320 | psw.mask = mask; |
321 | ||
94c12cc7 MS |
322 | asm volatile( |
323 | " larl %0,1f\n" | |
0a113efc AB |
324 | " stg %0,%1\n" |
325 | " lpswe %2\n" | |
1da177e4 | 326 | "1:" |
0a113efc | 327 | : "=&d" (addr), "=Q" (psw.addr) : "Q" (psw) : "memory", "cc"); |
1da177e4 | 328 | } |
ccf45caf | 329 | |
22362a0e MS |
330 | /* |
331 | * Extract current PSW mask | |
332 | */ | |
333 | static inline unsigned long __extract_psw(void) | |
334 | { | |
335 | unsigned int reg1, reg2; | |
336 | ||
337 | asm volatile("epsw %0,%1" : "=d" (reg1), "=a" (reg2)); | |
338 | return (((unsigned long) reg1) << 32) | ((unsigned long) reg2); | |
339 | } | |
340 | ||
1c8b8cf2 | 341 | static inline unsigned long __local_mcck_save(void) |
ecbafda8 | 342 | { |
1c8b8cf2 HC |
343 | unsigned long mask = __extract_psw(); |
344 | ||
345 | __load_psw_mask(mask & ~PSW_MASK_MCHECK); | |
346 | return mask & PSW_MASK_MCHECK; | |
347 | } | |
348 | ||
349 | #define local_mcck_save(mflags) \ | |
350 | do { \ | |
351 | typecheck(unsigned long, mflags); \ | |
352 | mflags = __local_mcck_save(); \ | |
353 | } while (0) | |
354 | ||
355 | static inline void local_mcck_restore(unsigned long mflags) | |
356 | { | |
357 | unsigned long mask = __extract_psw(); | |
358 | ||
359 | mask &= ~PSW_MASK_MCHECK; | |
360 | __load_psw_mask(mask | mflags); | |
ecbafda8 HC |
361 | } |
362 | ||
363 | static inline void local_mcck_disable(void) | |
364 | { | |
1c8b8cf2 HC |
365 | __local_mcck_save(); |
366 | } | |
367 | ||
368 | static inline void local_mcck_enable(void) | |
369 | { | |
370 | __load_psw_mask(__extract_psw() | PSW_MASK_MCHECK); | |
ecbafda8 HC |
371 | } |
372 | ||
ccf45caf MS |
373 | /* |
374 | * Rewind PSW instruction address by specified number of bytes. | |
375 | */ | |
376 | static inline unsigned long __rewind_psw(psw_t psw, unsigned long ilc) | |
377 | { | |
ccf45caf MS |
378 | unsigned long mask; |
379 | ||
380 | mask = (psw.mask & PSW_MASK_EA) ? -1UL : | |
381 | (psw.mask & PSW_MASK_BA) ? (1UL << 31) - 1 : | |
382 | (1UL << 24) - 1; | |
383 | return (psw.addr - ilc) & mask; | |
ccf45caf | 384 | } |
b5f87f15 | 385 | |
1da177e4 LT |
386 | /* |
387 | * Function to drop a processor into disabled wait state | |
388 | */ | |
c2e06e15 | 389 | static __always_inline void __noreturn disabled_wait(void) |
1da177e4 | 390 | { |
f9e6edfb HC |
391 | psw_t psw; |
392 | ||
393 | psw.mask = PSW_MASK_BASE | PSW_MASK_WAIT | PSW_MASK_BA | PSW_MASK_EA; | |
98587c2d | 394 | psw.addr = _THIS_IP_; |
f9e6edfb | 395 | __load_psw(psw); |
edd53787 | 396 | while (1); |
1da177e4 LT |
397 | } |
398 | ||
dfd54cbc HC |
399 | #define ARCH_LOW_ADDRESS_LIMIT 0x7fffffffUL |
400 | ||
56e62a73 SS |
401 | static __always_inline bool regs_irqs_disabled(struct pt_regs *regs) |
402 | { | |
403 | return arch_irqs_disabled_flags(regs->psw.mask); | |
404 | } | |
405 | ||
fa2ae4a3 SS |
406 | static __always_inline void bpon(void) |
407 | { | |
408 | asm volatile(ALTERNATIVE("nop", ".insn rrf,0xb2e80000,0,0,13,0", 82)); | |
409 | } | |
410 | ||
eb608fb3 HC |
411 | #endif /* __ASSEMBLY__ */ |
412 | ||
413 | #endif /* __ASM_S390_PROCESSOR_H */ |