diff options
Diffstat (limited to 'linux/kernel/asm.s')
| -rw-r--r-- | linux/kernel/asm.s | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/linux/kernel/asm.s b/linux/kernel/asm.s new file mode 100644 index 0000000..6fe1981 --- /dev/null +++ b/linux/kernel/asm.s @@ -0,0 +1,157 @@ +/* + * asm.s contains the low-level code for most hardware faults. + * page_exception is handled by the mm, so that isn't here. This + * file also handles (hopefully) fpu-exceptions due to TS-bit, as + * the fpu must be properly saved/resored. This hasn't been tested. + */ + +.globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op +.globl _device_not_available,_double_fault,_coprocessor_segment_overrun +.globl _invalid_TSS,_segment_not_present,_stack_segment +.globl _general_protection,_coprocessor_error,_reserved + +_divide_error: + pushl $_do_divide_error +no_error_code: + xchgl %eax,(%esp) + pushl %ebx + pushl %ecx + pushl %edx + pushl %edi + pushl %esi + pushl %ebp + push %ds + push %es + push %fs + pushl $0 # "error code" + lea 44(%esp),%edx + pushl %edx + movl $0x10,%edx + mov %dx,%ds + mov %dx,%es + mov %dx,%fs + call *%eax + addl $8,%esp + pop %fs + pop %es + pop %ds + popl %ebp + popl %esi + popl %edi + popl %edx + popl %ecx + popl %ebx + popl %eax + iret + +_debug: + pushl $_do_int3 # _do_debug + jmp no_error_code + +_nmi: + pushl $_do_nmi + jmp no_error_code + +_int3: + pushl $_do_int3 + jmp no_error_code + +_overflow: + pushl $_do_overflow + jmp no_error_code + +_bounds: + pushl $_do_bounds + jmp no_error_code + +_invalid_op: + pushl $_do_invalid_op + jmp no_error_code + +math_emulate: + popl %eax + pushl $_do_device_not_available + jmp no_error_code +_device_not_available: + pushl %eax + movl %cr0,%eax + bt $2,%eax # EM (math emulation bit) + jc math_emulate + clts # clear TS so that we can use math + movl _current,%eax + cmpl _last_task_used_math,%eax + je 1f # shouldn't happen really ... + pushl %ecx + pushl %edx + push %ds + movl $0x10,%eax + mov %ax,%ds + call _math_state_restore + pop %ds + popl %edx + popl %ecx +1: popl %eax + iret + +_coprocessor_segment_overrun: + pushl $_do_coprocessor_segment_overrun + jmp no_error_code + +_reserved: + pushl $_do_reserved + jmp no_error_code + +_coprocessor_error: + pushl $_do_coprocessor_error + jmp no_error_code + +_double_fault: + pushl $_do_double_fault +error_code: + xchgl %eax,4(%esp) # error code <-> %eax + xchgl %ebx,(%esp) # &function <-> %ebx + pushl %ecx + pushl %edx + pushl %edi + pushl %esi + pushl %ebp + push %ds + push %es + push %fs + pushl %eax # error code + lea 44(%esp),%eax # offset + pushl %eax + movl $0x10,%eax + mov %ax,%ds + mov %ax,%es + mov %ax,%fs + call *%ebx + addl $8,%esp + pop %fs + pop %es + pop %ds + popl %ebp + popl %esi + popl %edi + popl %edx + popl %ecx + popl %ebx + popl %eax + iret + +_invalid_TSS: + pushl $_do_invalid_TSS + jmp error_code + +_segment_not_present: + pushl $_do_segment_not_present + jmp error_code + +_stack_segment: + pushl $_do_stack_segment + jmp error_code + +_general_protection: + pushl $_do_general_protection + jmp error_code + |
