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