interrupts, timer, keyboard, segments, lots of kernel code
[bootcensus] / src / intr_asm.S
diff --git a/src/intr_asm.S b/src/intr_asm.S
new file mode 100644 (file)
index 0000000..ea0be36
--- /dev/null
@@ -0,0 +1,114 @@
+       .data
+       .align 4
+       .short 0
+idtr_desc:
+lim:   .short 0
+addr:  .long 0
+
+       .text
+/* void set_idt(uint32_t addr, uint16_t limit) */
+       .global set_idt
+set_idt:
+       mov 4(%esp), %eax
+       mov %eax, addr
+       mov 8(%esp), %ax
+       mov %ax, lim
+       lidt (idtr_desc)
+       ret
+
+/* int get_intr_flag() */
+       .global get_intr_flag
+get_intr_flag:
+       pushf
+       popl %eax
+       # bit 9 of eflags is IF
+       shr $9, %eax
+       and $1, %eax
+       ret
+
+/* void set_intr_flag(int onoff) */
+       .global set_intr_flag
+set_intr_flag:
+       cmpl $0, 4(%esp)
+       jz 0f
+       sti
+       ret
+0:     cli
+       ret
+
+/* interrupt entry with error code macro
+ * this macro generates an interrupt entry point for the
+ * exceptions which include error codes in the stack frame
+ */
+       .macro ientry_err n name
+       .globl intr_entry_\name
+intr_entry_\name:
+       pushl $\n
+       jmp intr_entry_common
+       .endm
+
+/* interrupt entry without error code macro
+ * this macro generates an interrupt entry point for the interrupts
+ * and exceptions which do not include error codes in the stack frame
+ * it pushes a dummy error code (0), to make the stack frame identical
+ */
+       .macro ientry_noerr n name
+       .globl intr_entry_\name
+intr_entry_\name:
+       pushl $0
+       pushl $\n
+       jmp intr_entry_common
+       .endm
+
+/* common code used by all entry points. calls dispatch_intr()
+ * defined in intr.c
+ */
+       .extern dispatch_intr
+intr_entry_common:
+       /* save general purpose registers */
+       pusha
+       call dispatch_intr
+intr_ret_local:
+       /* restore general purpose registers */
+       popa
+       /* remove error code and intr num from stack */
+       add $8, %esp
+       iret
+
+/* special case for the timer interrupt, to avoid all the overhead of
+ * going through the C interrupt dispatcher 250 times each second
+ */
+       .extern nticks
+       .global intr_entry_fast_timer
+intr_entry_fast_timer:
+       incl nticks
+       # signal end of interrupt
+       push %eax
+       mov $0x20, %al
+       out %al, $0x20
+       pop %eax
+       iret
+       
+
+/* XXX not necessary for now, just leaving it in in case it's useful
+ * down the road.
+ *
+ * intr_ret is called by context_switch to return from the kernel
+ * to userspace. The argument is a properly formed intr_frame
+ * structure with the saved context of the new task.
+ *
+ * First thing to do is remove the return address pointing back
+ * to context_switch, which then leaves us with a proper interrupt
+ * stack frame, so we can jump right in the middle of the regular
+ * interrupt return code above.
+ */
+       .global intr_ret
+intr_ret:
+       add $4, %esp
+       jmp intr_ret_local
+
+/* by including interrupts.h with ASM defined, the macros above
+ * are expanded to generate all required interrupt entry points
+ */
+#define ASM
+#include <intrtab.h>