|
|
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.