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