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