summaryrefslogtreecommitdiff
path: root/asm/asm_int.s
blob: f7107deac30f7166a1daf44666215c44f5aa60be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
.global int0
.global int1
.global int2
.global int3
.global int4
.global int5
.global int6
.global int7

.global int8
.global int9
.global int10
.global int11
.global int12
.global int13
.global int14
.global int15

.global int128
.global int129
.global int200
.global int255

.global exc0
.global exc1
.global exc2
.global exc3
.global exc4
.global exc5
.global exc6
.global exc7
.global exc8
.global exc9
.global exc10
.global exc11
.global exc12
.global exc13
.global exc14
.global exc15
.global exc16
.global exc17
.global exc18

// nothing to ack
.macro ack0
.endm

// ack master
.macro ack1
    push %eax // persist
    mov $0x20,%al
    out %al,$0x20   
    pop %eax // load original
.endm

// ack master and servant
.macro ack2
    push %eax // persist
    mov $0x20,%al
    out %al,$0xa0 // slave
    out %al,$0x20 // master
    pop %eax // load original
.endm

.macro intx ack num func

    /* 
       Once we arrived here the stack already contains 3x 32bit values,
       which will be poped by 'iret'

       - eflags
       - return code segment selector
       - return instruction pointer

       There are two possiblities concerning our stack position:

       a) if the interrupt occured while kernel code was executed we are
          on the same stack and have no clue about the stack alignment

       b) if the interrupt occured while user code was executed the 
          configured tss.esp0 was used, in this case we are at the start
          of the esp0 stack. 
    */

    \ack           //acknowledge interrupt 
                   //also remember that we will get new interrupts only 
                   //after iret or reenabling themn explicitly!
                    
    push $0x666    //make room for potential C functions 'return value'.
                   //we use eax already for esp (so we can context switch)

    push $0x0      //indicate if we want to return the value in ebx 0x0=NO

    pusha          //Push all standard registers 8 regs x 4bytes/32bit
    push %ds       //Push data segment
    push %es       //etc...
    push %fs
    push %gs

    mov %esp,%eax  // remember THIS stack position 

    and $-16,%esp  // padding to align stack on 16byte boundary before CALL
    sub $8,%esp    // ...

    push \num      // pass in this interrupt number
    push %eax      // pass in original %esp (saved just few lines before)
    call \func     // call aligned
    mov  %eax,%esp // use the %esp we got from c function

    pop %gs        // pop everything back...
    pop %fs        // ...
    pop %es
    pop %ds
    popa           

    cmp $0x0,(%esp)
    je skip\num
    pop %ebx
    pop %ebx
    jmp ret\num
    skip\num:
    add $8,%esp    // potentially set return value to eax to return to the caller
    ret\num:

    iret           // pops the return instruction pointer, return code segment selector, and EFLAGS image from the stack

.endm

.macro excx num func
    mov %esp,%eax  // remember THIS stack position 
    and $-16,%esp  // padding to align stack on 16byte boundary before CALL
    sub $8,%esp    // ...
    push \num      // pass in this interrupt number
    push %eax      // pass in original %esp (saved just few lines before)
    call \func     // call aligned
    jmp .
.endm

int0: intx ack1 $0 interrupt_handler
int1: intx ack1 $1 interrupt_handler
int2: intx ack1 $2 interrupt_handler
int3: intx ack1 $3 interrupt_handler
int4: intx ack1 $4 interrupt_handler
int5: intx ack1 $5 interrupt_handler
int6: intx ack1 $6 interrupt_handler
int7: intx ack1 $7 interrupt_handler

int8: intx ack2  $8 interrupt_handler
int9: intx ack2  $9 interrupt_handler
int10: intx ack2 $10 interrupt_handler
int11: intx ack2 $11 interrupt_handler
int12: intx ack2 $12 interrupt_handler
int13: intx ack2 $13 interrupt_handler
int14: intx ack2 $14 interrupt_handler
int15: intx ack2 $15 interrupt_handler

int128: intx ack0 $128 interrupt_handler
int129: intx ack0 $129 interrupt_handler

int255: intx ack0 $255 interrupt_handler
int200: intx ack0 $200 interrupt_handler

exc0: excx $0 exception_handle
exc1: excx $1 exception_handle
exc2: excx $2 exception_handle
exc3: excx $3 exception_handle
exc4: excx $4 exception_handle
exc5: excx $5 exception_handle
exc6: excx $6 exception_handle
exc7: excx $7 exception_handle
exc8: excx $8 exception_handle
exc9: excx $9 exception_handle
exc10: excx $10 exception_handle
exc11: excx $11 exception_handle
exc12: excx $12 exception_handle
exc13: excx $13 exception_handle
exc14: excx $14 exception_handle
exc15: excx $15 exception_handle
exc16: excx $16 exception_handle
exc17: excx $17 exception_handle
exc18: excx $18 exception_handle