|
|
1.1 ! root 1: /* ! 2: * linux/kernel/sys_call.S ! 3: * ! 4: * (C) 1991 Linus Torvalds ! 5: */ ! 6: ! 7: /* ! 8: * sys_call.S contains the system-call and fault low-level handling routines. ! 9: * This also contains the timer-interrupt handler, as well as all interrupts ! 10: * and faults that can result in a task-switch. ! 11: * ! 12: * NOTE: This code handles signal-recognition, which happens every time ! 13: * after a timer-interrupt and after each system call. ! 14: * ! 15: * Stack layout in 'ret_from_system_call': ! 16: * ptrace needs to have all regs on the stack. ! 17: * if the order here is changed, it needs to be ! 18: * updated in fork.c:copy_process, signal.c:do_signal, ! 19: * ptrace.c and ptrace.h ! 20: * ! 21: * 0(%esp) - %ebx ! 22: * 4(%esp) - %ecx ! 23: * 8(%esp) - %edx ! 24: * C(%esp) - %esi ! 25: * 10(%esp) - %edi ! 26: * 14(%esp) - %ebp ! 27: * 18(%esp) - %eax ! 28: * 1C(%esp) - %ds ! 29: * 20(%esp) - %es ! 30: * 24(%esp) - %fs ! 31: * 28(%esp) - %gs ! 32: * 2C(%esp) - orig_eax ! 33: * 30(%esp) - %eip ! 34: * 34(%esp) - %cs ! 35: * 38(%esp) - %eflags ! 36: * 3C(%esp) - %oldesp ! 37: * 40(%esp) - %oldss ! 38: */ ! 39: ! 40: SIG_CHLD = 17 ! 41: ! 42: EBX = 0x00 ! 43: ECX = 0x04 ! 44: EDX = 0x08 ! 45: ESI = 0x0C ! 46: EDI = 0x10 ! 47: EBP = 0x14 ! 48: EAX = 0x18 ! 49: DS = 0x1C ! 50: ES = 0x20 ! 51: FS = 0x24 ! 52: GS = 0x28 ! 53: ORIG_EAX = 0x2C ! 54: EIP = 0x30 ! 55: CS = 0x34 ! 56: EFLAGS = 0x38 ! 57: OLDESP = 0x3C ! 58: OLDSS = 0x40 ! 59: ! 60: /* ! 61: * these are offsets into the task-struct. ! 62: */ ! 63: state = 0 ! 64: counter = 4 ! 65: priority = 8 ! 66: signal = 12 ! 67: sigaction = 16 # MUST be 16 (=len of sigaction) ! 68: blocked = (33*16) ! 69: ! 70: /* ! 71: * offsets within sigaction ! 72: */ ! 73: sa_handler = 0 ! 74: sa_mask = 4 ! 75: sa_flags = 8 ! 76: sa_restorer = 12 ! 77: ! 78: ENOSYS = 38 ! 79: ! 80: /* ! 81: * Ok, I get parallel printer interrupts while using the floppy for some ! 82: * strange reason. Urgel. Now I just ignore them. ! 83: */ ! 84: .globl _system_call,_timer_interrupt,_sys_execve ! 85: .globl _device_not_available, _coprocessor_error ! 86: .globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op ! 87: .globl _double_fault,_coprocessor_segment_overrun ! 88: .globl _invalid_TSS,_segment_not_present,_stack_segment ! 89: .globl _general_protection,_irq13,_reserved ! 90: .globl _alignment_check,_page_fault ! 91: .globl _keyboard_interrupt,_hd_interrupt ! 92: .globl _IRQ3_interrupt,_IRQ4_interrupt ! 93: ! 94: #define SAVE_ALL \ ! 95: cld; \ ! 96: push %gs; \ ! 97: push %fs; \ ! 98: push %es; \ ! 99: push %ds; \ ! 100: pushl %eax; \ ! 101: pushl %ebp; \ ! 102: pushl %edi; \ ! 103: pushl %esi; \ ! 104: pushl %edx; \ ! 105: pushl %ecx; \ ! 106: pushl %ebx; \ ! 107: movl $0x10,%edx; \ ! 108: mov %dx,%ds; \ ! 109: mov %dx,%es; \ ! 110: movl $0x17,%edx; \ ! 111: mov %dx,%fs ! 112: ! 113: #define ACK_FIRST(mask) \ ! 114: inb $0x21,%al; \ ! 115: jmp 1f; \ ! 116: 1: jmp 1f; \ ! 117: 1: orb $(mask),%al; \ ! 118: outb %al,$0x21; \ ! 119: jmp 1f; \ ! 120: 1: jmp 1f; \ ! 121: 1: movb $0x20,%al; \ ! 122: outb %al,$0x20 ! 123: ! 124: #define ACK_SECOND(mask) \ ! 125: inb $0xA1,%al; \ ! 126: jmp 1f; \ ! 127: 1: jmp 1f; \ ! 128: 1: orb $(mask),%al; \ ! 129: outb %al,$0xA1; \ ! 130: jmp 1f; \ ! 131: 1: jmp 1f; \ ! 132: 1: movb $0x20,%al; \ ! 133: outb %al,$0xA0 \ ! 134: jmp 1f; \ ! 135: 1: jmp 1f; \ ! 136: 1: outb %al,$0x20 ! 137: ! 138: #define UNBLK_FIRST(mask) \ ! 139: inb $0x21,%al; \ ! 140: jmp 1f; \ ! 141: 1: jmp 1f; \ ! 142: 1: andb $~(mask),%al; \ ! 143: outb %al,$0x21 ! 144: ! 145: #define UNBLK_SECOND(mask) \ ! 146: inb $0xA1,%al; \ ! 147: jmp 1f; \ ! 148: 1: jmp 1f; \ ! 149: 1: andb $~(mask),%al; \ ! 150: outb %al,$0xA1 ! 151: ! 152: .align 2 ! 153: bad_sys_call: ! 154: movl $-ENOSYS,EAX(%esp) ! 155: jmp ret_from_sys_call ! 156: .align 2 ! 157: reschedule: ! 158: pushl $ret_from_sys_call ! 159: jmp _schedule ! 160: .align 2 ! 161: _system_call: ! 162: pushl %eax # save orig_eax ! 163: SAVE_ALL ! 164: cmpl _NR_syscalls,%eax ! 165: jae bad_sys_call ! 166: call _sys_call_table(,%eax,4) ! 167: movl %eax,EAX(%esp) # save the return value ! 168: ret_from_sys_call: ! 169: cmpw $0x0f,CS(%esp) # was old code segment supervisor ? ! 170: jne 2f ! 171: cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ? ! 172: jne 2f ! 173: 1: movl _current,%eax ! 174: cmpl _task,%eax # task[0] cannot have signals ! 175: je 2f ! 176: cmpl $0,_need_resched ! 177: jne reschedule ! 178: cmpl $0,state(%eax) # state ! 179: jne reschedule ! 180: cmpl $0,counter(%eax) # counter ! 181: je reschedule ! 182: movl signal(%eax),%ebx ! 183: movl blocked(%eax),%ecx ! 184: notl %ecx ! 185: andl %ebx,%ecx ! 186: bsfl %ecx,%ecx ! 187: je 2f ! 188: btrl %ecx,%ebx ! 189: movl %ebx,signal(%eax) ! 190: incl %ecx ! 191: pushl %ecx ! 192: call _do_signal ! 193: popl %ecx ! 194: testl %eax, %eax ! 195: jne 1b # see if we need to switch tasks, or do more signals ! 196: 2: popl %ebx ! 197: popl %ecx ! 198: popl %edx ! 199: popl %esi ! 200: popl %edi ! 201: popl %ebp ! 202: popl %eax ! 203: pop %ds ! 204: pop %es ! 205: pop %fs ! 206: pop %gs ! 207: addl $4,%esp # skip the orig_eax ! 208: iret ! 209: ! 210: .align 2 ! 211: _irq13: ! 212: pushl %eax ! 213: xorb %al,%al ! 214: outb %al,$0xF0 ! 215: movb $0x20,%al ! 216: outb %al,$0x20 ! 217: jmp 1f ! 218: 1: jmp 1f ! 219: 1: outb %al,$0xA0 ! 220: popl %eax ! 221: _coprocessor_error: ! 222: pushl $-1 # mark this as an int. ! 223: SAVE_ALL ! 224: pushl $ret_from_sys_call ! 225: jmp _math_error ! 226: ! 227: .align 2 ! 228: _device_not_available: ! 229: pushl $-1 # mark this as an int ! 230: SAVE_ALL ! 231: pushl $ret_from_sys_call ! 232: clts # clear TS so that we can use math ! 233: movl %cr0,%eax ! 234: testl $0x4,%eax # EM (math emulation bit) ! 235: je _math_state_restore ! 236: pushl $0 # temporary storage for ORIG_EIP ! 237: call _math_emulate ! 238: addl $4,%esp ! 239: ret ! 240: ! 241: .align 2 ! 242: _keyboard_interrupt: ! 243: pushl $-1 ! 244: SAVE_ALL ! 245: ACK_FIRST(0x02) ! 246: sti ! 247: call _do_keyboard ! 248: cli ! 249: UNBLK_FIRST(0x02) ! 250: jmp ret_from_sys_call ! 251: ! 252: .align 2 ! 253: _IRQ3_interrupt: ! 254: pushl $-1 ! 255: SAVE_ALL ! 256: ACK_FIRST(0x08) ! 257: sti ! 258: call _do_IRQ3 ! 259: cli ! 260: UNBLK_FIRST(0x08) ! 261: jmp ret_from_sys_call ! 262: ! 263: .align 2 ! 264: _IRQ4_interrupt: ! 265: pushl $-1 ! 266: SAVE_ALL ! 267: ACK_FIRST(0x10) ! 268: sti ! 269: call _do_IRQ4 ! 270: cli ! 271: UNBLK_FIRST(0x10) ! 272: jmp ret_from_sys_call ! 273: ! 274: .align 2 ! 275: _timer_interrupt: ! 276: pushl $-1 # mark this as an int ! 277: SAVE_ALL ! 278: ACK_FIRST(0x01) ! 279: sti ! 280: incl _jiffies ! 281: movl CS(%esp),%eax ! 282: andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor) ! 283: pushl %eax ! 284: call _do_timer # 'do_timer(long CPL)' does everything from ! 285: addl $4,%esp # task switching to accounting ... ! 286: cli ! 287: UNBLK_FIRST(0x01) ! 288: jmp ret_from_sys_call ! 289: ! 290: .align 2 ! 291: _hd_interrupt: ! 292: pushl $-1 ! 293: SAVE_ALL ! 294: ACK_SECOND(0x40) ! 295: andl $0xfffeffff,_timer_active ! 296: xorl %edx,%edx ! 297: xchgl _do_hd,%edx ! 298: testl %edx,%edx ! 299: jne 1f ! 300: movl $_unexpected_hd_interrupt,%edx ! 301: 1: call *%edx # "interesting" way of handling intr. ! 302: cli ! 303: UNBLK_SECOND(0x40) ! 304: jmp ret_from_sys_call ! 305: ! 306: .align 2 ! 307: _sys_execve: ! 308: lea (EIP+4)(%esp),%eax # don't forget about the return address. ! 309: pushl %eax ! 310: call _do_execve ! 311: addl $4,%esp ! 312: ret ! 313: ! 314: _divide_error: ! 315: pushl $0 # no error code ! 316: pushl $_do_divide_error ! 317: error_code: ! 318: push %fs ! 319: push %es ! 320: push %ds ! 321: pushl %eax ! 322: pushl %ebp ! 323: pushl %edi ! 324: pushl %esi ! 325: pushl %edx ! 326: pushl %ecx ! 327: pushl %ebx ! 328: cld ! 329: movl $-1, %eax ! 330: xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. ) ! 331: xorl %ebx,%ebx # zero ebx ! 332: mov %gs,%bx # get the lower order bits of gs ! 333: xchgl %ebx, GS(%esp) # get the address and save gs. ! 334: pushl %eax # push the error code ! 335: lea 52(%esp),%edx ! 336: pushl %edx ! 337: movl $0x10,%edx ! 338: mov %dx,%ds ! 339: mov %dx,%es ! 340: movl $0x17,%edx ! 341: mov %dx,%fs ! 342: call *%ebx ! 343: addl $8,%esp ! 344: jmp ret_from_sys_call ! 345: ! 346: _debug: ! 347: pushl $0 ! 348: pushl $_do_int3 # _do_debug ! 349: jmp error_code ! 350: ! 351: _nmi: ! 352: pushl $0 ! 353: pushl $_do_nmi ! 354: jmp error_code ! 355: ! 356: _int3: ! 357: pushl $0 ! 358: pushl $_do_int3 ! 359: jmp error_code ! 360: ! 361: _overflow: ! 362: pushl $0 ! 363: pushl $_do_overflow ! 364: jmp error_code ! 365: ! 366: _bounds: ! 367: pushl $0 ! 368: pushl $_do_bounds ! 369: jmp error_code ! 370: ! 371: _invalid_op: ! 372: pushl $0 ! 373: pushl $_do_invalid_op ! 374: jmp error_code ! 375: ! 376: _coprocessor_segment_overrun: ! 377: pushl $0 ! 378: pushl $_do_coprocessor_segment_overrun ! 379: jmp error_code ! 380: ! 381: _reserved: ! 382: pushl $0 ! 383: pushl $_do_reserved ! 384: jmp error_code ! 385: ! 386: _double_fault: ! 387: pushl $_do_double_fault ! 388: jmp error_code ! 389: ! 390: _invalid_TSS: ! 391: pushl $_do_invalid_TSS ! 392: jmp error_code ! 393: ! 394: _segment_not_present: ! 395: pushl $_do_segment_not_present ! 396: jmp error_code ! 397: ! 398: _stack_segment: ! 399: pushl $_do_stack_segment ! 400: jmp error_code ! 401: ! 402: _general_protection: ! 403: pushl $_do_general_protection ! 404: jmp error_code ! 405: ! 406: _alignment_check: ! 407: pushl $_do_alignment_check ! 408: jmp error_code ! 409: ! 410: _page_fault: ! 411: pushl $_do_page_fault ! 412: jmp error_code
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.