interrupts, timer, keyboard, segments, lots of kernel code
[bootcensus] / src / intr_asm.S
1         .data
2         .align 4
3         .short 0
4 idtr_desc:
5 lim:    .short 0
6 addr:   .long 0
7
8         .text
9 /* void set_idt(uint32_t addr, uint16_t limit) */
10         .global set_idt
11 set_idt:
12         mov 4(%esp), %eax
13         mov %eax, addr
14         mov 8(%esp), %ax
15         mov %ax, lim
16         lidt (idtr_desc)
17         ret
18
19 /* int get_intr_flag() */
20         .global get_intr_flag
21 get_intr_flag:
22         pushf
23         popl %eax
24         # bit 9 of eflags is IF
25         shr $9, %eax
26         and $1, %eax
27         ret
28
29 /* void set_intr_flag(int onoff) */
30         .global set_intr_flag
31 set_intr_flag:
32         cmpl $0, 4(%esp)
33         jz 0f
34         sti
35         ret
36 0:      cli
37         ret
38
39 /* interrupt entry with error code macro
40  * this macro generates an interrupt entry point for the
41  * exceptions which include error codes in the stack frame
42  */
43         .macro ientry_err n name
44         .globl intr_entry_\name
45 intr_entry_\name:
46         pushl $\n
47         jmp intr_entry_common
48         .endm
49
50 /* interrupt entry without error code macro
51  * this macro generates an interrupt entry point for the interrupts
52  * and exceptions which do not include error codes in the stack frame
53  * it pushes a dummy error code (0), to make the stack frame identical
54  */
55         .macro ientry_noerr n name
56         .globl intr_entry_\name
57 intr_entry_\name:
58         pushl $0
59         pushl $\n
60         jmp intr_entry_common
61         .endm
62
63 /* common code used by all entry points. calls dispatch_intr()
64  * defined in intr.c
65  */
66         .extern dispatch_intr
67 intr_entry_common:
68         /* save general purpose registers */
69         pusha
70         call dispatch_intr
71 intr_ret_local:
72         /* restore general purpose registers */
73         popa
74         /* remove error code and intr num from stack */
75         add $8, %esp
76         iret
77
78 /* special case for the timer interrupt, to avoid all the overhead of
79  * going through the C interrupt dispatcher 250 times each second
80  */
81         .extern nticks
82         .global intr_entry_fast_timer
83 intr_entry_fast_timer:
84         incl nticks
85         # signal end of interrupt
86         push %eax
87         mov $0x20, %al
88         out %al, $0x20
89         pop %eax
90         iret
91         
92
93 /* XXX not necessary for now, just leaving it in in case it's useful
94  * down the road.
95  *
96  * intr_ret is called by context_switch to return from the kernel
97  * to userspace. The argument is a properly formed intr_frame
98  * structure with the saved context of the new task.
99  *
100  * First thing to do is remove the return address pointing back
101  * to context_switch, which then leaves us with a proper interrupt
102  * stack frame, so we can jump right in the middle of the regular
103  * interrupt return code above.
104  */
105         .global intr_ret
106 intr_ret:
107         add $4, %esp
108         jmp intr_ret_local
109
110 /* by including interrupts.h with ASM defined, the macros above
111  * are expanded to generate all required interrupt entry points
112  */
113 #define ASM
114 #include <intrtab.h>