Linux Audio

Check our new training course

Loading...
v3.5.6
 
  1/*
  2 *  include/asm-s390/processor.h
  3 *
  4 *  S390 version
  5 *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  6 *    Author(s): Hartmut Penner (hp@de.ibm.com),
  7 *               Martin Schwidefsky (schwidefsky@de.ibm.com)
  8 *
  9 *  Derived from "include/asm-i386/processor.h"
 10 *    Copyright (C) 1994, Linus Torvalds
 11 */
 12
 13#ifndef __ASM_S390_PROCESSOR_H
 14#define __ASM_S390_PROCESSOR_H
 15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 16#include <linux/linkage.h>
 17#include <linux/irqflags.h>
 
 18#include <asm/cpu.h>
 19#include <asm/page.h>
 20#include <asm/ptrace.h>
 21#include <asm/setup.h>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 22
 23/*
 24 * Default implementation of macro that returns current
 25 * instruction pointer ("program counter").
 26 */
 27#define current_text_addr() ({ void *pc; asm("basr %0,0" : "=a" (pc)); pc; })
 
 
 
 
 
 
 
 28
 29static inline void get_cpu_id(struct cpuid *ptr)
 30{
 31	asm volatile("stidp %0" : "=Q" (*ptr));
 32}
 33
 34extern void s390_adjust_jiffies(void);
 
 
 
 35extern const struct seq_operations cpuinfo_op;
 36extern int sysctl_ieee_emulation_warnings;
 
 
 37
 38/*
 39 * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit.
 40 */
 41#ifndef CONFIG_64BIT
 42
 43#define TASK_SIZE		(1UL << 31)
 44#define TASK_UNMAPPED_BASE	(1UL << 30)
 45
 46#else /* CONFIG_64BIT */
 47
 48#define TASK_SIZE_OF(tsk)	((tsk)->mm->context.asce_limit)
 49#define TASK_UNMAPPED_BASE	(test_thread_flag(TIF_31BIT) ? \
 50					(1UL << 30) : (1UL << 41))
 51#define TASK_SIZE		TASK_SIZE_OF(current)
 52
 53#endif /* CONFIG_64BIT */
 54
 55#ifndef CONFIG_64BIT
 56#define STACK_TOP		(1UL << 31)
 57#define STACK_TOP_MAX		(1UL << 31)
 58#else /* CONFIG_64BIT */
 59#define STACK_TOP		(1UL << (test_thread_flag(TIF_31BIT) ? 31:42))
 60#define STACK_TOP_MAX		(1UL << 42)
 61#endif /* CONFIG_64BIT */
 62
 63#define HAVE_ARCH_PICK_MMAP_LAYOUT
 64
 65typedef struct {
 66        __u32 ar4;
 67} mm_segment_t;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 68
 69/*
 70 * Thread structure
 71 */
 72struct thread_struct {
 73	s390_fp_regs fp_regs;
 74	unsigned int  acrs[NUM_ACRS];
 75        unsigned long ksp;              /* kernel stack pointer             */
 76	mm_segment_t mm_segment;
 77	unsigned long gmap_addr;	/* address of last gmap fault. */
 78	struct per_regs per_user;	/* User specified PER registers */
 79	struct per_event per_event;	/* Cause of the last PER trap */
 80        /* pfault_wait is used to block the process on a pfault event */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 81	unsigned long pfault_wait;
 82	struct list_head list;
 
 
 
 
 
 
 
 83};
 84
 85typedef struct thread_struct thread_struct;
 86
 87/*
 88 * Stack layout of a C stack frame.
 
 
 
 89 */
 90#ifndef __PACK_STACK
 91struct stack_frame {
 92	unsigned long back_chain;
 93	unsigned long empty1[5];
 94	unsigned long gprs[10];
 95	unsigned int  empty2[8];
 96};
 97#else
 98struct stack_frame {
 99	unsigned long empty1[5];
100	unsigned int  empty2[8];
101	unsigned long gprs[10];
102	unsigned long back_chain;
103};
104#endif
105
106#define ARCH_MIN_TASKALIGN	8
107
108#define INIT_THREAD {							\
109	.ksp = sizeof(init_stack) + (unsigned long) &init_stack,	\
 
110}
111
112/*
113 * Do necessary setup to start up a new thread.
114 */
115#define start_thread(regs, new_psw, new_stackp) do {			\
116	regs->psw.mask	= psw_user_bits | PSW_MASK_EA | PSW_MASK_BA;	\
117	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;			\
118	regs->gprs[15]	= new_stackp;					\
 
119} while (0)
120
121#define start_thread31(regs, new_psw, new_stackp) do {			\
122	regs->psw.mask	= psw_user_bits | PSW_MASK_BA;			\
123	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;			\
124	regs->gprs[15]	= new_stackp;					\
125	__tlb_flush_mm(current->mm);					\
126	crst_table_downgrade(current->mm, 1UL << 31);			\
127	update_mm(current->mm, current);				\
128} while (0)
129
130/* Forward declaration, a strange C thing */
131struct task_struct;
132struct mm_struct;
133struct seq_file;
 
134
135/* Free all resources held by a thread. */
136extern void release_thread(struct task_struct *);
137extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
138
139/*
140 * Return saved PC of a blocked thread.
141 */
142extern unsigned long thread_saved_pc(struct task_struct *t);
143
144extern void show_code(struct pt_regs *regs);
 
 
145
146unsigned long get_wchan(struct task_struct *p);
147#define task_pt_regs(tsk) ((struct pt_regs *) \
148        (task_stack_page(tsk) + THREAD_SIZE) - 1)
149#define KSTK_EIP(tsk)	(task_pt_regs(tsk)->psw.addr)
150#define KSTK_ESP(tsk)	(task_pt_regs(tsk)->gprs[15])
151
152static inline unsigned short stap(void)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153{
154	unsigned short cpu_address;
155
156	asm volatile("stap %0" : "=m" (cpu_address));
157	return cpu_address;
158}
159
160/*
161 * Give up the time slice of the virtual PU.
162 */
163static inline void cpu_relax(void)
 
 
164{
165	if (MACHINE_HAS_DIAG44)
166		asm volatile("diag 0,0,68");
167	barrier();
 
168}
169
170static inline void psw_set_key(unsigned int key)
171{
172	asm volatile("spka 0(%0)" : : "d" (key));
173}
174
175/*
176 * Set PSW to specified value.
177 */
178static inline void __load_psw(psw_t psw)
179{
180#ifndef CONFIG_64BIT
181	asm volatile("lpsw  %0" : : "Q" (psw) : "cc");
182#else
183	asm volatile("lpswe %0" : : "Q" (psw) : "cc");
184#endif
185}
186
187/*
188 * Set PSW mask to specified value, while leaving the
189 * PSW addr pointing to the next instruction.
190 */
191static inline void __load_psw_mask (unsigned long mask)
192{
193	unsigned long addr;
194	psw_t psw;
195
196	psw.mask = mask;
197
198#ifndef CONFIG_64BIT
199	asm volatile(
200		"	basr	%0,0\n"
201		"0:	ahi	%0,1f-0b\n"
202		"	st	%0,%O1+4(%R1)\n"
203		"	lpsw	%1\n"
204		"1:"
205		: "=&d" (addr), "=Q" (psw) : "Q" (psw) : "memory", "cc");
206#else /* CONFIG_64BIT */
207	asm volatile(
208		"	larl	%0,1f\n"
209		"	stg	%0,%O1+8(%R1)\n"
210		"	lpswe	%1\n"
211		"1:"
212		: "=&d" (addr), "=Q" (psw) : "Q" (psw) : "memory", "cc");
213#endif /* CONFIG_64BIT */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214}
215
216/*
217 * Rewind PSW instruction address by specified number of bytes.
218 */
219static inline unsigned long __rewind_psw(psw_t psw, unsigned long ilc)
220{
221#ifndef CONFIG_64BIT
222	if (psw.addr & PSW_ADDR_AMODE)
223		/* 31 bit mode */
224		return (psw.addr - ilc) | PSW_ADDR_AMODE;
225	/* 24 bit mode */
226	return (psw.addr - ilc) & ((1UL << 24) - 1);
227#else
228	unsigned long mask;
229
230	mask = (psw.mask & PSW_MASK_EA) ? -1UL :
231	       (psw.mask & PSW_MASK_BA) ? (1UL << 31) - 1 :
232					  (1UL << 24) - 1;
233	return (psw.addr - ilc) & mask;
234#endif
235}
236 
237/*
238 * Function to drop a processor into disabled wait state
239 */
240static inline void __noreturn disabled_wait(unsigned long code)
241{
242        unsigned long ctl_buf;
243        psw_t dw_psw;
244
245	dw_psw.mask = PSW_MASK_BASE | PSW_MASK_WAIT | PSW_MASK_BA | PSW_MASK_EA;
246        dw_psw.addr = code;
247        /* 
248         * Store status and then load disabled wait psw,
249         * the processor is dead afterwards
250         */
251#ifndef CONFIG_64BIT
252	asm volatile(
253		"	stctl	0,0,0(%2)\n"
254		"	ni	0(%2),0xef\n"	/* switch off protection */
255		"	lctl	0,0,0(%2)\n"
256		"	stpt	0xd8\n"		/* store timer */
257		"	stckc	0xe0\n"		/* store clock comparator */
258		"	stpx	0x108\n"	/* store prefix register */
259		"	stam	0,15,0x120\n"	/* store access registers */
260		"	std	0,0x160\n"	/* store f0 */
261		"	std	2,0x168\n"	/* store f2 */
262		"	std	4,0x170\n"	/* store f4 */
263		"	std	6,0x178\n"	/* store f6 */
264		"	stm	0,15,0x180\n"	/* store general registers */
265		"	stctl	0,15,0x1c0\n"	/* store control registers */
266		"	oi	0x1c0,0x10\n"	/* fake protection bit */
267		"	lpsw	0(%1)"
268		: "=m" (ctl_buf)
269		: "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc");
270#else /* CONFIG_64BIT */
271	asm volatile(
272		"	stctg	0,0,0(%2)\n"
273		"	ni	4(%2),0xef\n"	/* switch off protection */
274		"	lctlg	0,0,0(%2)\n"
275		"	lghi	1,0x1000\n"
276		"	stpt	0x328(1)\n"	/* store timer */
277		"	stckc	0x330(1)\n"	/* store clock comparator */
278		"	stpx	0x318(1)\n"	/* store prefix register */
279		"	stam	0,15,0x340(1)\n"/* store access registers */
280		"	stfpc	0x31c(1)\n"	/* store fpu control */
281		"	std	0,0x200(1)\n"	/* store f0 */
282		"	std	1,0x208(1)\n"	/* store f1 */
283		"	std	2,0x210(1)\n"	/* store f2 */
284		"	std	3,0x218(1)\n"	/* store f3 */
285		"	std	4,0x220(1)\n"	/* store f4 */
286		"	std	5,0x228(1)\n"	/* store f5 */
287		"	std	6,0x230(1)\n"	/* store f6 */
288		"	std	7,0x238(1)\n"	/* store f7 */
289		"	std	8,0x240(1)\n"	/* store f8 */
290		"	std	9,0x248(1)\n"	/* store f9 */
291		"	std	10,0x250(1)\n"	/* store f10 */
292		"	std	11,0x258(1)\n"	/* store f11 */
293		"	std	12,0x260(1)\n"	/* store f12 */
294		"	std	13,0x268(1)\n"	/* store f13 */
295		"	std	14,0x270(1)\n"	/* store f14 */
296		"	std	15,0x278(1)\n"	/* store f15 */
297		"	stmg	0,15,0x280(1)\n"/* store general registers */
298		"	stctg	0,15,0x380(1)\n"/* store control registers */
299		"	oi	0x384(1),0x10\n"/* fake protection bit */
300		"	lpswe	0(%1)"
301		: "=m" (ctl_buf)
302		: "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc", "0", "1");
303#endif /* CONFIG_64BIT */
304	while (1);
305}
306
307/*
308 * Use to set psw mask except for the first byte which
309 * won't be changed by this function.
310 */
311static inline void
312__set_psw_mask(unsigned long mask)
313{
314	__load_psw_mask(mask | (arch_local_save_flags() & ~(-1UL >> 8)));
315}
316
317#define local_mcck_enable() \
318	__set_psw_mask(psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK)
319#define local_mcck_disable() \
320	__set_psw_mask(psw_kernel_bits | PSW_MASK_DAT)
321
322/*
323 * Basic Machine Check/Program Check Handler.
324 */
325
326extern void s390_base_mcck_handler(void);
327extern void s390_base_pgm_handler(void);
328extern void s390_base_ext_handler(void);
329
330extern void (*s390_base_mcck_handler_fn)(void);
331extern void (*s390_base_pgm_handler_fn)(void);
332extern void (*s390_base_ext_handler_fn)(void);
333
334#define ARCH_LOW_ADDRESS_LIMIT	0x7fffffffUL
335
336/*
337 * Helper macro for exception table entries
338 */
339#ifndef CONFIG_64BIT
340#define EX_TABLE(_fault,_target)			\
341	".section __ex_table,\"a\"\n"			\
342	"	.align 4\n"				\
343	"	.long  " #_fault "," #_target "\n"	\
344	".previous\n"
345#else
346#define EX_TABLE(_fault,_target)			\
347	".section __ex_table,\"a\"\n"			\
348	"	.align 8\n"				\
349	"	.quad  " #_fault "," #_target "\n"	\
350	".previous\n"
351#endif
352
353#endif                                 /* __ASM_S390_PROCESSOR_H           */
v6.9.4
  1/* SPDX-License-Identifier: GPL-2.0 */
  2/*
 
 
  3 *  S390 version
  4 *    Copyright IBM Corp. 1999
  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
 15#include <linux/bits.h>
 16
 17#define CIF_SIE			0	/* CPU needs SIE exit cleanup */
 18#define CIF_NOHZ_DELAY		2	/* delay HZ disable for a tick */
 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 */
 22
 23#define _CIF_SIE		BIT(CIF_SIE)
 24#define _CIF_NOHZ_DELAY		BIT(CIF_NOHZ_DELAY)
 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)
 28
 29#define RESTART_FLAG_CTLREGS	_AC(1 << 0, U)
 30
 31#ifndef __ASSEMBLY__
 32
 33#include <linux/cpumask.h>
 34#include <linux/linkage.h>
 35#include <linux/irqflags.h>
 36#include <asm/fpu-types.h>
 37#include <asm/cpu.h>
 38#include <asm/page.h>
 39#include <asm/ptrace.h>
 40#include <asm/setup.h>
 41#include <asm/runtime_instr.h>
 42#include <asm/irqflags.h>
 43
 44typedef long (*sys_call_ptr_t)(struct pt_regs *regs);
 45
 46static __always_inline void set_cpu_flag(int flag)
 47{
 48	S390_lowcore.cpu_flags |= (1UL << flag);
 49}
 50
 51static __always_inline void clear_cpu_flag(int flag)
 52{
 53	S390_lowcore.cpu_flags &= ~(1UL << flag);
 54}
 55
 56static __always_inline bool test_cpu_flag(int flag)
 57{
 58	return S390_lowcore.cpu_flags & (1UL << flag);
 59}
 60
 61static __always_inline bool test_and_set_cpu_flag(int flag)
 62{
 63	if (test_cpu_flag(flag))
 64		return true;
 65	set_cpu_flag(flag);
 66	return false;
 67}
 68
 69static __always_inline bool test_and_clear_cpu_flag(int flag)
 70{
 71	if (!test_cpu_flag(flag))
 72		return false;
 73	clear_cpu_flag(flag);
 74	return true;
 75}
 76
 77/*
 78 * Test CIF flag of another CPU. The caller needs to ensure that
 79 * CPU hotplug can not happen, e.g. by disabling preemption.
 80 */
 81static __always_inline bool test_cpu_flag_of(int flag, int cpu)
 82{
 83	struct lowcore *lc = lowcore_ptr[cpu];
 84
 85	return lc->cpu_flags & (1UL << flag);
 86}
 87
 88#define arch_needs_cpu() test_cpu_flag(CIF_NOHZ_DELAY)
 89
 90static inline void get_cpu_id(struct cpuid *ptr)
 91{
 92	asm volatile("stidp %0" : "=Q" (*ptr));
 93}
 94
 95void s390_adjust_jiffies(void);
 96void s390_update_cpu_mhz(void);
 97void cpu_detect_mhz_feature(void);
 98
 99extern const struct seq_operations cpuinfo_op;
100extern void execve_tail(void);
101unsigned long vdso_text_size(void);
102unsigned long vdso_size(void);
103
104/*
105 * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit.
106 */
 
 
 
 
107
108#define TASK_SIZE		(test_thread_flag(TIF_31BIT) ? \
109					_REGION3_SIZE : TASK_SIZE_MAX)
 
110#define TASK_UNMAPPED_BASE	(test_thread_flag(TIF_31BIT) ? \
111					(_REGION3_SIZE >> 1) : (_REGION2_SIZE >> 1))
112#define TASK_SIZE_MAX		(-PAGE_SIZE)
 
 
113
114#define VDSO_BASE		(STACK_TOP + PAGE_SIZE)
115#define VDSO_LIMIT		(test_thread_flag(TIF_31BIT) ? _REGION3_SIZE : _REGION2_SIZE)
116#define STACK_TOP		(VDSO_LIMIT - vdso_size() - PAGE_SIZE)
117#define STACK_TOP_MAX		(_REGION2_SIZE - vdso_size() - PAGE_SIZE)
 
 
 
118
119#define HAVE_ARCH_PICK_MMAP_LAYOUT
120
121#define __stackleak_poison __stackleak_poison
122static __always_inline void __stackleak_poison(unsigned long erase_low,
123					       unsigned long erase_high,
124					       unsigned long poison)
125{
126	unsigned long tmp, count;
127
128	count = erase_high - erase_low;
129	if (!count)
130		return;
131	asm volatile(
132		"	cghi	%[count],8\n"
133		"	je	2f\n"
134		"	aghi	%[count],-(8+1)\n"
135		"	srlg	%[tmp],%[count],8\n"
136		"	ltgr	%[tmp],%[tmp]\n"
137		"	jz	1f\n"
138		"0:	stg	%[poison],0(%[addr])\n"
139		"	mvc	8(256-8,%[addr]),0(%[addr])\n"
140		"	la	%[addr],256(%[addr])\n"
141		"	brctg	%[tmp],0b\n"
142		"1:	stg	%[poison],0(%[addr])\n"
143		"	larl	%[tmp],3f\n"
144		"	ex	%[count],0(%[tmp])\n"
145		"	j	4f\n"
146		"2:	stg	%[poison],0(%[addr])\n"
147		"	j	4f\n"
148		"3:	mvc	8(1,%[addr]),0(%[addr])\n"
149		"4:\n"
150		: [addr] "+&a" (erase_low), [count] "+&d" (count), [tmp] "=&a" (tmp)
151		: [poison] "d" (poison)
152		: "memory", "cc"
153		);
154}
155
156/*
157 * Thread structure
158 */
159struct thread_struct {
 
160	unsigned int  acrs[NUM_ACRS];
161	unsigned long ksp;			/* kernel stack pointer */
162	unsigned long user_timer;		/* task cputime in user space */
163	unsigned long guest_timer;		/* task cputime in kvm guest */
164	unsigned long system_timer;		/* task cputime in kernel space */
165	unsigned long hardirq_timer;		/* task cputime in hardirq context */
166	unsigned long softirq_timer;		/* task cputime in softirq context */
167	const sys_call_ptr_t *sys_call_table;	/* system call table address */
168	unsigned long gmap_addr;		/* address of last gmap fault. */
169	unsigned int gmap_write_flag;		/* gmap fault write indication */
170	unsigned int gmap_int_code;		/* int code of last gmap fault */
171	unsigned int gmap_pfault;		/* signal of a pending guest pfault */
172	int ufpu_flags;				/* user fpu flags */
173	int kfpu_flags;				/* kernel fpu flags */
174
175	/* Per-thread information related to debugging */
176	struct per_regs per_user;		/* User specified PER registers */
177	struct per_event per_event;		/* Cause of the last PER trap */
178	unsigned long per_flags;		/* Flags to control debug behavior */
179	unsigned int system_call;		/* system call number in signal */
180	unsigned long last_break;		/* last breaking-event-address. */
181	/* pfault_wait is used to block the process on a pfault event */
182	unsigned long pfault_wait;
183	struct list_head list;
184	/* cpu runtime instrumentation */
185	struct runtime_instr_cb *ri_cb;
186	struct gs_cb *gs_cb;			/* Current guarded storage cb */
187	struct gs_cb *gs_bc_cb;			/* Broadcast guarded storage cb */
188	struct pgm_tdb trap_tdb;		/* Transaction abort diagnose block */
189	struct fpu ufpu;			/* User FP and VX register save area */
190	struct fpu kfpu;			/* Kernel FP and VX register save area */
191};
192
193/* Flag to disable transactions. */
194#define PER_FLAG_NO_TE			1UL
195/* Flag to enable random transaction aborts. */
196#define PER_FLAG_TE_ABORT_RAND		2UL
197/* Flag to specify random transaction abort mode:
198 * - abort each transaction at a random instruction before TEND if set.
199 * - abort random transactions at a random instruction if cleared.
200 */
201#define PER_FLAG_TE_ABORT_RAND_TEND	4UL
202
203typedef struct thread_struct thread_struct;
 
 
 
 
 
 
 
 
 
 
 
 
204
205#define ARCH_MIN_TASKALIGN	8
206
207#define INIT_THREAD {							\
208	.ksp = sizeof(init_stack) + (unsigned long) &init_stack,	\
209	.last_break = 1,						\
210}
211
212/*
213 * Do necessary setup to start up a new thread.
214 */
215#define start_thread(regs, new_psw, new_stackp) do {			\
216	regs->psw.mask	= PSW_USER_BITS | PSW_MASK_EA | PSW_MASK_BA;	\
217	regs->psw.addr	= new_psw;					\
218	regs->gprs[15]	= new_stackp;					\
219	execve_tail();							\
220} while (0)
221
222#define start_thread31(regs, new_psw, new_stackp) do {			\
223	regs->psw.mask	= PSW_USER_BITS | PSW_MASK_BA;			\
224	regs->psw.addr	= new_psw;					\
225	regs->gprs[15]	= new_stackp;					\
226	execve_tail();							\
 
 
227} while (0)
228
 
229struct task_struct;
230struct mm_struct;
231struct seq_file;
232struct pt_regs;
233
234void show_registers(struct pt_regs *regs);
235void show_cacheinfo(struct seq_file *m);
 
 
 
 
 
 
236
237/* Free guarded storage control block */
238void guarded_storage_release(struct task_struct *tsk);
239void gs_load_bc_cb(struct pt_regs *regs);
240
241unsigned long __get_wchan(struct task_struct *p);
242#define task_pt_regs(tsk) ((struct pt_regs *) \
243        (task_stack_page(tsk) + THREAD_SIZE) - 1)
244#define KSTK_EIP(tsk)	(task_pt_regs(tsk)->psw.addr)
245#define KSTK_ESP(tsk)	(task_pt_regs(tsk)->gprs[15])
246
247/* Has task runtime instrumentation enabled ? */
248#define is_ri_task(tsk) (!!(tsk)->thread.ri_cb)
249
250/* avoid using global register due to gcc bug in versions < 8.4 */
251#define current_stack_pointer (__current_stack_pointer())
252
253static __always_inline unsigned long __current_stack_pointer(void)
254{
255	unsigned long sp;
256
257	asm volatile("lgr %0,15" : "=d" (sp));
258	return sp;
259}
260
261static __always_inline bool on_thread_stack(void)
262{
263	unsigned long ksp = S390_lowcore.kernel_stack;
264
265	return !((ksp ^ current_stack_pointer) & ~(THREAD_SIZE - 1));
266}
267
268static __always_inline unsigned short stap(void)
269{
270	unsigned short cpu_address;
271
272	asm volatile("stap %0" : "=Q" (cpu_address));
273	return cpu_address;
274}
275
276#define cpu_relax() barrier()
277
278#define ECAG_CACHE_ATTRIBUTE	0
279#define ECAG_CPU_ATTRIBUTE	1
280
281static inline unsigned long __ecag(unsigned int asi, unsigned char parm)
282{
283	unsigned long val;
284
285	asm volatile("ecag %0,0,0(%1)" : "=d" (val) : "a" (asi << 8 | parm));
286	return val;
287}
288
289static inline void psw_set_key(unsigned int key)
290{
291	asm volatile("spka 0(%0)" : : "d" (key));
292}
293
294/*
295 * Set PSW to specified value.
296 */
297static inline void __load_psw(psw_t psw)
298{
 
 
 
299	asm volatile("lpswe %0" : : "Q" (psw) : "cc");
 
300}
301
302/*
303 * Set PSW mask to specified value, while leaving the
304 * PSW addr pointing to the next instruction.
305 */
306static __always_inline void __load_psw_mask(unsigned long mask)
307{
308	unsigned long addr;
309	psw_t psw;
310
311	psw.mask = mask;
312
 
 
 
 
 
 
 
 
 
313	asm volatile(
314		"	larl	%0,1f\n"
315		"	stg	%0,%1\n"
316		"	lpswe	%2\n"
317		"1:"
318		: "=&d" (addr), "=Q" (psw.addr) : "Q" (psw) : "memory", "cc");
319}
320
321/*
322 * Extract current PSW mask
323 */
324static inline unsigned long __extract_psw(void)
325{
326	unsigned int reg1, reg2;
327
328	asm volatile("epsw %0,%1" : "=d" (reg1), "=a" (reg2));
329	return (((unsigned long) reg1) << 32) | ((unsigned long) reg2);
330}
331
332static inline unsigned long __local_mcck_save(void)
333{
334	unsigned long mask = __extract_psw();
335
336	__load_psw_mask(mask & ~PSW_MASK_MCHECK);
337	return mask & PSW_MASK_MCHECK;
338}
339
340#define local_mcck_save(mflags)			\
341do {						\
342	typecheck(unsigned long, mflags);	\
343	mflags = __local_mcck_save();		\
344} while (0)
345
346static inline void local_mcck_restore(unsigned long mflags)
347{
348	unsigned long mask = __extract_psw();
349
350	mask &= ~PSW_MASK_MCHECK;
351	__load_psw_mask(mask | mflags);
352}
353
354static inline void local_mcck_disable(void)
355{
356	__local_mcck_save();
357}
358
359static inline void local_mcck_enable(void)
360{
361	__load_psw_mask(__extract_psw() | PSW_MASK_MCHECK);
362}
363
364/*
365 * Rewind PSW instruction address by specified number of bytes.
366 */
367static inline unsigned long __rewind_psw(psw_t psw, unsigned long ilc)
368{
 
 
 
 
 
 
 
369	unsigned long mask;
370
371	mask = (psw.mask & PSW_MASK_EA) ? -1UL :
372	       (psw.mask & PSW_MASK_BA) ? (1UL << 31) - 1 :
373					  (1UL << 24) - 1;
374	return (psw.addr - ilc) & mask;
 
375}
376
377/*
378 * Function to drop a processor into disabled wait state
379 */
380static __always_inline void __noreturn disabled_wait(void)
381{
382	psw_t psw;
 
383
384	psw.mask = PSW_MASK_BASE | PSW_MASK_WAIT | PSW_MASK_BA | PSW_MASK_EA;
385	psw.addr = _THIS_IP_;
386	__load_psw(psw);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387	while (1);
388}
389
390#define ARCH_LOW_ADDRESS_LIMIT	0x7fffffffUL
391
392static __always_inline bool regs_irqs_disabled(struct pt_regs *regs)
 
 
 
393{
394	return arch_irqs_disabled_flags(regs->psw.mask);
395}
396
397#endif /* __ASSEMBLY__ */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
398
399#endif /* __ASM_S390_PROCESSOR_H */