1 #ifndef _M68K_SYSTEM_H
2 #define _M68K_SYSTEM_H
3 
4 #include <linux/config.h> /* get configuration macros */
5 #include <linux/linkage.h>
6 #include <linux/kernel.h>
7 #include <linux/init.h>
8 #include <asm/segment.h>
9 #include <asm/entry.h>
10 
11 #define prepare_to_switch()	do { } while(0)
12 
13 #ifdef __KERNEL__
14 
15 /*
16  * switch_to(n) should switch tasks to task ptr, first checking that
17  * ptr isn't the current task, in which case it does nothing.  This
18  * also clears the TS-flag if the task we switched to has used the
19  * math co-processor latest.
20  */
21 /*
22  * switch_to() saves the extra registers, that are not saved
23  * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
24  * a0-a1. Some of these are used by schedule() and its predecessors
25  * and so we might get see unexpected behaviors when a task returns
26  * with unexpected register values.
27  *
28  * syscall stores these registers itself and none of them are used
29  * by syscall after the function in the syscall has been called.
30  *
31  * Beware that resume now expects *next to be in d1 and the offset of
32  * tss to be in a1. This saves a few instructions as we no longer have
33  * to push them onto the stack and read them back right after.
34  *
35  * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
36  *
37  * Changed 96/09/19 by Andreas Schwab
38  * pass prev in a0, next in a1, offset of tss in d1, and whether
39  * the mm structures are shared in d2 (to avoid atc flushing).
40  */
41 asmlinkage void resume(void);
42 #define switch_to(prev,next,last) { \
43   register void *_prev __asm__ ("a0") = (prev); \
44   register void *_next __asm__ ("a1") = (next); \
45   register void *_last __asm__ ("d1"); \
46   __asm__ __volatile__("jbsr " SYMBOL_NAME_STR(resume) \
47 		       : "=a" (_prev), "=a" (_next), "=d" (_last) \
48 		       : "0" (_prev), "1" (_next)		  \
49 		       : "d0", "d2", "d3", "d4", "d5"); \
50   (last) = _last; \
51 }
52 
53 /* interrupt control.. */
54 #if 0
55 #define __sti() asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory")
56 #else
57 #include <asm/hardirq.h>
58 #define __sti() ({							      \
59 	if (MACH_IS_Q40 || !local_irq_count(smp_processor_id()))              \
60 		asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory");  \
61 })
62 #endif
63 #define __cli() asm volatile ("oriw  #0x0700,%%sr": : : "memory")
64 #define __save_flags(x) asm volatile ("movew %%sr,%0":"=d" (x) : : "memory")
65 #define __restore_flags(x) asm volatile ("movew %0,%%sr": :"d" (x) : "memory")
66 
67 /* For spinlocks etc */
68 #define local_irq_save(x)	({ __save_flags(x); __cli(); })
69 #define local_irq_set(x)	({ __save_flags(x); __sti(); })
70 #define local_irq_restore(x)	__restore_flags(x)
71 #define local_irq_disable()	__cli()
72 #define local_irq_enable()	__sti()
73 
74 #define cli()			__cli()
75 #define sti()			__sti()
76 #define save_flags(x)		__save_flags(x)
77 #define restore_flags(x)	__restore_flags(x)
78 #define save_and_cli(x)		do { save_flags(x); cli(); } while(0)
79 #define save_and_set(x)		do { save_flags(x); sti(); } while(0)
80 
81 /*
82  * Force strict CPU ordering.
83  * Not really required on m68k...
84  */
85 #define nop()		do { asm volatile ("nop"); barrier(); } while (0)
86 #define mb()		barrier()
87 #define rmb()		barrier()
88 #define wmb()		barrier()
89 #define set_mb(var, value)     do { var = value; mb(); } while (0)
90 #define set_wmb(var, value)    do { var = value; wmb(); } while (0)
91 
92 #define smp_mb()	barrier()
93 #define smp_rmb()	barrier()
94 #define smp_wmb()	barrier()
95 
96 
97 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
98 #define tas(ptr) (xchg((ptr),1))
99 
100 struct __xchg_dummy { unsigned long a[100]; };
101 #define __xg(x) ((volatile struct __xchg_dummy *)(x))
102 
103 #ifndef CONFIG_RMW_INSNS
__xchg(unsigned long x,volatile void * ptr,int size)104 static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
105 {
106   unsigned long tmp, flags;
107 
108   save_flags(flags);
109   cli();
110 
111   switch (size) {
112   case 1:
113     __asm__ __volatile__
114     ("moveb %2,%0\n\t"
115      "moveb %1,%2"
116     : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
117     break;
118   case 2:
119     __asm__ __volatile__
120     ("movew %2,%0\n\t"
121      "movew %1,%2"
122     : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
123     break;
124   case 4:
125     __asm__ __volatile__
126     ("movel %2,%0\n\t"
127      "movel %1,%2"
128     : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
129     break;
130   }
131   restore_flags(flags);
132   return tmp;
133 }
134 #else
__xchg(unsigned long x,volatile void * ptr,int size)135 static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
136 {
137 	switch (size) {
138 	    case 1:
139 		__asm__ __volatile__
140 			("moveb %2,%0\n\t"
141 			 "1:\n\t"
142 			 "casb %0,%1,%2\n\t"
143 			 "jne 1b"
144 			 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
145 		break;
146 	    case 2:
147 		__asm__ __volatile__
148 			("movew %2,%0\n\t"
149 			 "1:\n\t"
150 			 "casw %0,%1,%2\n\t"
151 			 "jne 1b"
152 			 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
153 		break;
154 	    case 4:
155 		__asm__ __volatile__
156 			("movel %2,%0\n\t"
157 			 "1:\n\t"
158 			 "casl %0,%1,%2\n\t"
159 			 "jne 1b"
160 			 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
161 		break;
162 	}
163 	return x;
164 }
165 #endif
166 
167 #endif /* __KERNEL__ */
168 
169 #endif /* _M68K_SYSTEM_H */
170