|
|
1.1 root 1: #ifndef __ASM_SYSTEM_H
2: #define __ASM_SYSTEM_H
3:
4: #include <asm/segment.h>
5:
6: /*
7: * Entry into gdt where to find first TSS. GDT layout:
8: * 0 - nul
9: * 1 - kernel code segment
10: * 2 - kernel data segment
11: * 3 - user code segment
12: * 4 - user data segment
13: * ...
14: * 8 - TSS #0
15: * 9 - LDT #0
16: * 10 - TSS #1
17: * 11 - LDT #1
18: */
19: #define FIRST_TSS_ENTRY 8
20: #define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)
21: #define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
22: #define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
23: #define load_TR(n) __asm__("ltr %%ax": /* no output */ :"a" (_TSS(n)))
24: #define load_ldt(n) __asm__("lldt %%ax": /* no output */ :"a" (_LDT(n)))
25: #define store_TR(n) \
26: __asm__("str %%ax\n\t" \
27: "subl %2,%%eax\n\t" \
28: "shrl $4,%%eax" \
29: :"=a" (n) \
30: :"0" (0),"i" (FIRST_TSS_ENTRY<<3))
31:
32: /* This special macro can be used to load a debugging register */
33:
34: #define loaddebug(register) \
35: __asm__("movl %0,%%edx\n\t" \
36: "movl %%edx,%%db" #register "\n\t" \
37: : /* no output */ \
38: :"m" (current->debugreg[register]) \
39: :"dx");
40:
41:
42: /*
43: * switch_to(n) should switch tasks to task nr n, first
44: * checking that n isn't the current task, in which case it does nothing.
45: * This also clears the TS-flag if the task we switched to has used
46: * the math co-processor latest.
47: *
48: * It also reloads the debug regs if necessary..
49: */
50:
51:
52: #ifdef __SMP__
53: /*
54: * Keep the lock depth straight. If we switch on an interrupt from
55: * kernel->user task we need to lose a depth, and if we switch the
56: * other way we need to gain a depth. Same layer switches come out
57: * the same.
58: *
59: * We spot a switch in user mode because the kernel counter is the
60: * same as the interrupt counter depth. (We never switch during the
61: * message/invalidate IPI).
62: *
63: * We fsave/fwait so that an exception goes off at the right time
64: * (as a call from the fsave or fwait in effect) rather than to
65: * the wrong process.
66: */
67:
68: #define switch_to(tsk) do { \
69: cli();\
70: if(current->flags&PF_USEDFPU) \
71: { \
72: __asm__ __volatile__("fnsave %0":"=m" (current->tss.i387.hard)); \
73: __asm__ __volatile__("fwait"); \
74: current->flags&=~PF_USEDFPU; \
75: } \
76: current->lock_depth=syscall_count; \
77: kernel_counter+=next->lock_depth-current->lock_depth; \
78: syscall_count=next->lock_depth; \
79: __asm__("pushl %%edx\n\t" \
80: "movl "SYMBOL_NAME_STR(apic_reg)",%%edx\n\t" \
81: "movl 0x20(%%edx), %%edx\n\t" \
82: "shrl $22,%%edx\n\t" \
83: "and $0x3C,%%edx\n\t" \
84: "xchgl %%ecx,"SYMBOL_NAME_STR(current_set)"(,%%edx)\n\t" \
85: "popl %%edx\n\t" \
86: "ljmp %0\n\t" \
87: "sti\n\t" \
88: : /* no output */ \
89: :"m" (*(((char *)&tsk->tss.tr)-4)), \
90: "c" (tsk) \
91: :"cx"); \
92: /* Now maybe reload the debug registers */ \
93: if(current->debugreg[7]){ \
94: loaddebug(0); \
95: loaddebug(1); \
96: loaddebug(2); \
97: loaddebug(3); \
98: loaddebug(6); \
99: } \
100: } while (0)
101:
102: #else
103: #define switch_to(tsk) do { \
104: __asm__("cli\n\t" \
105: "xchgl %%ecx,"SYMBOL_NAME_STR(current_set)"\n\t" \
106: "ljmp %0\n\t" \
107: "sti\n\t" \
108: "cmpl %%ecx,"SYMBOL_NAME_STR(last_task_used_math)"\n\t" \
109: "jne 1f\n\t" \
110: "clts\n" \
111: "1:" \
112: : /* no output */ \
113: :"m" (*(((char *)&tsk->tss.tr)-4)), \
114: "c" (tsk) \
115: :"cx"); \
116: /* Now maybe reload the debug registers */ \
117: if(current->debugreg[7]){ \
118: loaddebug(0); \
119: loaddebug(1); \
120: loaddebug(2); \
121: loaddebug(3); \
122: loaddebug(6); \
123: } \
124: } while (0)
125: #endif
126:
127: #define _set_base(addr,base) \
128: __asm__("movw %%dx,%0\n\t" \
129: "rorl $16,%%edx\n\t" \
130: "movb %%dl,%1\n\t" \
131: "movb %%dh,%2" \
132: : /* no output */ \
133: :"m" (*((addr)+2)), \
134: "m" (*((addr)+4)), \
135: "m" (*((addr)+7)), \
136: "d" (base) \
137: :"dx")
138:
139: #define _set_limit(addr,limit) \
140: __asm__("movw %%dx,%0\n\t" \
141: "rorl $16,%%edx\n\t" \
142: "movb %1,%%dh\n\t" \
143: "andb $0xf0,%%dh\n\t" \
144: "orb %%dh,%%dl\n\t" \
145: "movb %%dl,%1" \
146: : /* no output */ \
147: :"m" (*(addr)), \
148: "m" (*((addr)+6)), \
149: "d" (limit) \
150: :"dx")
151:
152: #define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )
153: #define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )
154:
155: static inline unsigned long _get_base(char * addr)
156: {
157: unsigned long __base;
158: __asm__("movb %3,%%dh\n\t"
159: "movb %2,%%dl\n\t"
160: "shll $16,%%edx\n\t"
161: "movw %1,%%dx"
162: :"=&d" (__base)
163: :"m" (*((addr)+2)),
164: "m" (*((addr)+4)),
165: "m" (*((addr)+7)));
166: return __base;
167: }
168:
169: #define get_base(ldt) _get_base( ((char *)&(ldt)) )
170:
171: static inline unsigned long get_limit(unsigned long segment)
172: {
173: unsigned long __limit;
174: __asm__("lsll %1,%0"
175: :"=r" (__limit):"r" (segment));
176: return __limit+1;
177: }
178:
179: #define nop() __asm__ __volatile__ ("nop")
180:
181: /*
182: * Clear and set 'TS' bit respectively
183: */
184: #define clts() __asm__ __volatile__ ("clts")
185: #define stts() \
186: __asm__ __volatile__ ( \
187: "movl %%cr0,%%eax\n\t" \
188: "orl $8,%%eax\n\t" \
189: "movl %%eax,%%cr0" \
190: : /* no outputs */ \
191: : /* no inputs */ \
192: :"ax")
193:
194:
195: #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
196: #define tas(ptr) (xchg((ptr),1))
197:
198: struct __xchg_dummy { unsigned long a[100]; };
199: #define __xg(x) ((volatile struct __xchg_dummy *)(x))
200:
201: static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
202: {
203: switch (size) {
204: case 1:
205: __asm__("xchgb %b0,%1"
206: :"=q" (x), "=m" (*__xg(ptr))
207: :"0" (x), "m" (*__xg(ptr)));
208: break;
209: case 2:
210: __asm__("xchgw %w0,%1"
211: :"=r" (x), "=m" (*__xg(ptr))
212: :"0" (x), "m" (*__xg(ptr)));
213: break;
214: case 4:
215: __asm__("xchgl %0,%1"
216: :"=r" (x), "=m" (*__xg(ptr))
217: :"0" (x), "m" (*__xg(ptr)));
218: break;
219: }
220: return x;
221: }
222:
223: #define mb() __asm__ __volatile__ ("" : : :"memory")
224: #define sti() __asm__ __volatile__ ("sti": : :"memory")
225: #define cli() __asm__ __volatile__ ("cli": : :"memory")
226:
227: #define save_flags(x) \
228: __asm__ __volatile__("pushfl ; popl %0":"=r" (x): /* no input */ :"memory")
229:
230: #define restore_flags(x) \
231: __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"r" (x):"memory")
232:
233: #define iret() __asm__ __volatile__ ("iret": : :"memory")
234:
235: #define _set_gate(gate_addr,type,dpl,addr) \
236: __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
237: "movw %2,%%dx\n\t" \
238: "movl %%eax,%0\n\t" \
239: "movl %%edx,%1" \
240: :"=m" (*((long *) (gate_addr))), \
241: "=m" (*(1+(long *) (gate_addr))) \
242: :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
243: "d" ((char *) (addr)),"a" (KERNEL_CS << 16) \
244: :"ax","dx")
245:
246: #define set_intr_gate(n,addr) \
247: _set_gate(&idt[n],14,0,addr)
248:
249: #define set_trap_gate(n,addr) \
250: _set_gate(&idt[n],15,0,addr)
251:
252: #define set_system_gate(n,addr) \
253: _set_gate(&idt[n],15,3,addr)
254:
255: #define set_call_gate(a,addr) \
256: _set_gate(a,12,3,addr)
257:
258: #define _set_seg_desc(gate_addr,type,dpl,base,limit) {\
259: *((gate_addr)+1) = ((base) & 0xff000000) | \
260: (((base) & 0x00ff0000)>>16) | \
261: ((limit) & 0xf0000) | \
262: ((dpl)<<13) | \
263: (0x00408000) | \
264: ((type)<<8); \
265: *(gate_addr) = (((base) & 0x0000ffff)<<16) | \
266: ((limit) & 0x0ffff); }
267:
268: #define _set_tssldt_desc(n,addr,limit,type) \
269: __asm__ __volatile__ ("movw $" #limit ",%1\n\t" \
270: "movw %%ax,%2\n\t" \
271: "rorl $16,%%eax\n\t" \
272: "movb %%al,%3\n\t" \
273: "movb $" type ",%4\n\t" \
274: "movb $0x00,%5\n\t" \
275: "movb %%ah,%6\n\t" \
276: "rorl $16,%%eax" \
277: : /* no output */ \
278: :"a" (addr+0xc0000000), "m" (*(n)), "m" (*(n+2)), "m" (*(n+4)), \
279: "m" (*(n+5)), "m" (*(n+6)), "m" (*(n+7)) \
280: )
281:
282: #define set_tss_desc(n,addr) _set_tssldt_desc(((char *) (n)),((int)(addr)),235,"0x89")
283: #define set_ldt_desc(n,addr,size) \
284: _set_tssldt_desc(((char *) (n)),((int)(addr)),((size << 3) - 1),"0x82")
285:
286: /*
287: * This is the ldt that every process will get unless we need
288: * something other than this.
289: */
290: extern struct desc_struct default_ldt;
291:
292: /*
293: * disable hlt during certain critical i/o operations
294: */
295: #ifndef MACH
296: #define HAVE_DISABLE_HLT
297: #endif
298: void disable_hlt(void);
299: void enable_hlt(void);
300:
301: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.