aboutsummaryrefslogtreecommitdiff
path: root/linux/kernel/asm.s
diff options
context:
space:
mode:
Diffstat (limited to 'linux/kernel/asm.s')
-rw-r--r--linux/kernel/asm.s157
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
+