File: /usr/src/linux/include/asm-s390x/system.h
1 /*
2 * include/asm-s390/system.h
3 *
4 * S390 version
5 * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
7 *
8 * Derived from "include/asm-i386/system.h"
9 */
10
11 #ifndef __ASM_SYSTEM_H
12 #define __ASM_SYSTEM_H
13
14 #include <linux/config.h>
15 #ifdef __KERNEL__
16 #include <asm/lowcore.h>
17 #endif
18 #include <linux/kernel.h>
19
20 #define prepare_to_switch() do { } while(0)
21 #define switch_to(prev,next,last) do { \
22 if (prev == next) \
23 break; \
24 save_fp_regs(&prev->thread.fp_regs); \
25 restore_fp_regs(&next->thread.fp_regs); \
26 last = resume(&prev->thread,&next->thread); \
27 } while (0)
28
29 struct task_struct;
30
31 #define nop() __asm__ __volatile__ ("nop")
32
33 #define xchg(ptr,x) \
34 ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(void *)(ptr),sizeof(*(ptr))))
35
36 extern void __misaligned_u16(void);
37 extern void __misaligned_u32(void);
38 extern void __misaligned_u64(void);
39
40 static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
41 {
42 switch (size) {
43 case 1:
44 asm volatile (
45 " lghi 1,3\n"
46 " nr 1,%0\n" /* isolate last 2 bits */
47 " xr %0,1\n" /* align ptr */
48 " bras 2,0f\n"
49 " icm 1,8,7(%1)\n" /* for ptr&3 == 0 */
50 " stcm 0,8,7(%1)\n"
51 " icm 1,4,7(%1)\n" /* for ptr&3 == 1 */
52 " stcm 0,4,7(%1)\n"
53 " icm 1,2,7(%1)\n" /* for ptr&3 == 2 */
54 " stcm 0,2,7(%1)\n"
55 " icm 1,1,7(%1)\n" /* for ptr&3 == 3 */
56 " stcm 0,1,7(%1)\n"
57 "0: sll 1,3\n"
58 " la 2,0(1,2)\n" /* r2 points to an icm */
59 " l 0,0(%0)\n" /* get fullword */
60 "1: lr 1,0\n" /* cs loop */
61 " ex 0,0(2)\n" /* insert x */
62 " cs 0,1,0(%0)\n"
63 " jl 1b\n"
64 " ex 0,4(2)" /* store *ptr to x */
65 : "+&a" (ptr) : "a" (&x)
66 : "memory", "cc", "0", "1", "2");
67 break;
68 case 2:
69 if(((addr_t)ptr)&1)
70 __misaligned_u16();
71 asm volatile (
72 " lghi 1,2\n"
73 " nr 1,%0\n" /* isolate bit 2^1 */
74 " xr %0,1\n" /* align ptr */
75 " bras 2,0f\n"
76 " icm 1,12,6(%1)\n" /* for ptr&2 == 0 */
77 " stcm 0,12,6(%1)\n"
78 " icm 1,3,2(%1)\n" /* for ptr&2 == 1 */
79 " stcm 0,3,2(%1)\n"
80 "0: sll 1,2\n"
81 " la 2,0(1,2)\n" /* r2 points to an icm */
82 " l 0,0(%0)\n" /* get fullword */
83 "1: lr 1,0\n" /* cs loop */
84 " ex 0,0(2)\n" /* insert x */
85 " cs 0,1,0(%0)\n"
86 " jl 1b\n"
87 " ex 0,4(2)" /* store *ptr to x */
88 : "+&a" (ptr) : "a" (&x)
89 : "memory", "cc", "0", "1", "2");
90 break;
91 case 4:
92 if(((addr_t)ptr)&3)
93 __misaligned_u32();
94 asm volatile (
95 " l 0,0(%1)\n"
96 "0: cs 0,%0,0(%1)\n"
97 " jl 0b\n"
98 " lgfr %0,0\n"
99 : "+d" (x) : "a" (ptr)
100 : "memory", "cc", "0" );
101 break;
102 case 8:
103 if(((addr_t)ptr)&7)
104 __misaligned_u64();
105 asm volatile (
106 " lg 0,0(%1)\n"
107 "0: csg 0,%0,0(%1)\n"
108 " jl 0b\n"
109 " lgr %0,0\n"
110 : "+d" (x) : "a" (ptr)
111 : "memory", "cc", "0" );
112 break;
113 default:
114 abort();
115 }
116 return x;
117 }
118
119 /*
120 * Force strict CPU ordering.
121 * And yes, this is required on UP too when we're talking
122 * to devices.
123 *
124 * This is very similar to the ppc eieio/sync instruction in that is
125 * does a checkpoint syncronisation & makes sure that
126 * all memory ops have completed wrt other CPU's ( see 7-15 POP DJB ).
127 */
128
129 #define eieio() __asm__ __volatile__ ("BCR 15,0")
130 # define SYNC_OTHER_CORES(x) eieio()
131 #define mb() eieio()
132 #define rmb() eieio()
133 #define wmb() eieio()
134 #define smp_mb() mb()
135 #define smp_rmb() rmb()
136 #define smp_wmb() wmb()
137 #define smp_mb__before_clear_bit() smp_mb()
138 #define smp_mb__after_clear_bit() smp_mb()
139
140 #define set_mb(var, value) do { var = value; mb(); } while (0)
141 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
142
143 /* interrupt control.. */
144 #define __sti() ({ \
145 unsigned long dummy; \
146 __asm__ __volatile__ ( \
147 "stosm %0,0x03" : "=m" (dummy) : : "memory"); \
148 })
149
150 #define __cli() ({ \
151 unsigned long flags; \
152 __asm__ __volatile__ ( \
153 "stnsm %0,0xFC" : "=m" (flags) : : "memory"); \
154 flags; \
155 })
156
157 #define __save_flags(x) \
158 __asm__ __volatile__("stosm %0,0" : "=m" (x) : : "memory")
159
160 #define __restore_flags(x) \
161 __asm__ __volatile__("ssm %0" : : "m" (x) : "memory")
162
163 #define __load_psw(psw) \
164 __asm__ __volatile__("lpswe %0" : : "m" (psw) : "cc" );
165
166 #define __ctl_load(array, low, high) ({ \
167 __asm__ __volatile__ ( \
168 " la 1,%0\n" \
169 " bras 2,0f\n" \
170 " lctlg 0,0,0(1)\n" \
171 "0: ex %1,0(2)" \
172 : : "m" (array), "a" (((low)<<4)+(high)) : "1", "2" ); \
173 })
174
175 #define __ctl_store(array, low, high) ({ \
176 __asm__ __volatile__ ( \
177 " la 1,%0\n" \
178 " bras 2,0f\n" \
179 " stctg 0,0,0(1)\n" \
180 "0: ex %1,0(2)" \
181 : "=m" (array) : "a" (((low)<<4)+(high)): "1", "2" ); \
182 })
183
184 #define __ctl_set_bit(cr, bit) ({ \
185 __u8 dummy[24]; \
186 __asm__ __volatile__ ( \
187 " la 1,%0\n" /* align to 8 byte */ \
188 " aghi 1,7\n" \
189 " nill 1,0xfff8\n" \
190 " bras 2,0f\n" /* skip indirect insns */ \
191 " stctg 0,0,0(1)\n" \
192 " lctlg 0,0,0(1)\n" \
193 "0: ex %1,0(2)\n" /* execute stctl */ \
194 " lg 0,0(1)\n" \
195 " ogr 0,%2\n" /* set the bit */ \
196 " stg 0,0(1)\n" \
197 "1: ex %1,6(2)" /* execute lctl */ \
198 : "=m" (dummy) : "a" (cr*17), "a" (1L<<(bit)) \
199 : "cc", "0", "1", "2"); \
200 })
201
202 #define __ctl_clear_bit(cr, bit) ({ \
203 __u8 dummy[24]; \
204 __asm__ __volatile__ ( \
205 " la 1,%0\n" /* align to 8 byte */ \
206 " aghi 1,7\n" \
207 " nill 1,0xfff8\n" \
208 " bras 2,0f\n" /* skip indirect insns */ \
209 " stctg 0,0,0(1)\n" \
210 " lctlg 0,0,0(1)\n" \
211 "0: ex %1,0(2)\n" /* execute stctl */ \
212 " lg 0,0(1)\n" \
213 " ngr 0,%2\n" /* set the bit */ \
214 " stg 0,0(1)\n" \
215 "1: ex %1,6(2)" /* execute lctl */ \
216 : "=m" (dummy) : "a" (cr*17), "a" (~(1L<<(bit))) \
217 : "cc", "0", "1", "2"); \
218 })
219
220 /* For spinlocks etc */
221 #define local_irq_save(x) ((x) = __cli())
222 #define local_irq_restore(x) __restore_flags(x)
223 #define local_irq_disable() __cli()
224 #define local_irq_enable() __sti()
225
226 #ifdef CONFIG_SMP
227
228 extern void __global_cli(void);
229 extern void __global_sti(void);
230
231 extern unsigned long __global_save_flags(void);
232 extern void __global_restore_flags(unsigned long);
233 #define cli() __global_cli()
234 #define sti() __global_sti()
235 #define save_flags(x) ((x)=__global_save_flags())
236 #define restore_flags(x) __global_restore_flags(x)
237
238 extern void smp_ctl_set_bit(int cr, int bit);
239 extern void smp_ctl_clear_bit(int cr, int bit);
240 #define ctl_set_bit(cr, bit) smp_ctl_set_bit(cr, bit)
241 #define ctl_clear_bit(cr, bit) smp_ctl_clear_bit(cr, bit)
242
243 #else
244
245 #define cli() __cli()
246 #define sti() __sti()
247 #define save_flags(x) __save_flags(x)
248 #define restore_flags(x) __restore_flags(x)
249
250 #define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit)
251 #define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit)
252
253
254 #endif
255
256 #ifdef __KERNEL__
257 extern struct task_struct *resume(void *,void *);
258
259 extern int save_fp_regs1(s390_fp_regs *fpregs);
260 extern void save_fp_regs(s390_fp_regs *fpregs);
261 extern int restore_fp_regs1(s390_fp_regs *fpregs);
262 extern void restore_fp_regs(s390_fp_regs *fpregs);
263 #endif
264
265 #endif
266
267
268
269