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