revert between 56095 -> 55830 in arch
[AROS.git] / arch / x86_64-pc / kernel / core_interrupts.s
blobebee32744bdd83166e3999b5eec8ad2bc0b378f5
1 /* CPU interrupt handling entry points */
3 #include <aros/x86_64/asm.h>
5 #include "segments.h"
7 #define BUILD_IRQ(nr) \
8 .balign 8, 0x90; \
9 .globl IRQ##nr##_intr; \
10 .type IRQ##nr##_intr, @function; \
11 IRQ##nr##_intr: \
12 pushq $0; \
13 pushq $##nr; \
14 jmp core_EnterInterrupt; \
15 .size IRQ##nr##_intr, .-IRQ##nr##_intr;
17 #define BUILD_IRQ_ERR(nr) \
18 .balign 8, 0x90; \
19 .globl IRQ##nr##_intr; \
20 .type IRQ##nr##_intr, @function; \
21 IRQ##nr##_intr: \
22 pushq $##nr; \
23 jmp core_EnterInterrupt; \
24 .size IRQ##nr##_intr, .-IRQ##nr##_intr;
26 #define B(x,y) BUILD_IRQ(x##y)
27 #define BUILD_16(x) \
28 B(x,0) B(x,1) B(x,2) B(x,3) B(x,4) B(x,5) B(x,6) B(x,7) \
29 B(x,8) B(x,9) B(x,A) B(x,B) B(x,C) B(x,D) B(x,E) B(x,F)
31 BUILD_IRQ(0x00) // Divide-By-Zero Exception
32 BUILD_IRQ(0x01) // Debug Exception
33 BUILD_IRQ(0x02) // NMI Exception
34 BUILD_IRQ(0x03) // Breakpoint Exception
35 BUILD_IRQ(0x04) // Overflow Exception
36 BUILD_IRQ(0x05) // Bound-Range Exception
37 BUILD_IRQ(0x06) // Invalid-Opcode Exception
38 BUILD_IRQ(0x07) // Device-Not-Available Exception
39 BUILD_IRQ_ERR(0x08) // Double-Fault Exception
40 BUILD_IRQ(0x09) // Unused (used to be Coprocesor-Segment-Overrun)
41 BUILD_IRQ_ERR(0x0A) // Invalid-TSS Exception
42 BUILD_IRQ_ERR(0x0B) // Segment-Not-Present Exception
43 BUILD_IRQ_ERR(0x0C) // Stack Exception
44 BUILD_IRQ_ERR(0x0D) // General-Protection Exception
45 BUILD_IRQ_ERR(0x0E) // Page-Fault Exception
46 BUILD_IRQ(0x0F) // Reserved
47 BUILD_IRQ(0x10) // Floating-Point Exception
48 BUILD_IRQ_ERR(0x11) // Alignment-Check Exception
49 BUILD_IRQ(0x12) // Machine-Check Exception
50 BUILD_IRQ(0x13) // SIMD-Floating-Point Exception
51 BUILD_IRQ(0x14)
52 BUILD_IRQ(0x15)
53 BUILD_IRQ(0x16)
54 BUILD_IRQ(0x17)
55 BUILD_IRQ(0x18)
56 BUILD_IRQ(0x19)
57 BUILD_IRQ(0x1A)
58 BUILD_IRQ(0x1B)
59 BUILD_IRQ(0x1C)
60 BUILD_IRQ(0x1D)
61 BUILD_IRQ(0x1E)
62 BUILD_IRQ(0x1F)
64 BUILD_16(0x2) // Hardware IRQs...
65 BUILD_16(0x3)
66 BUILD_16(0x4)
67 BUILD_16(0x5)
68 BUILD_16(0x6)
69 BUILD_16(0x7)
70 BUILD_16(0x8)
71 BUILD_16(0x9)
72 BUILD_16(0xA)
73 BUILD_16(0xB)
74 BUILD_16(0xC)
75 BUILD_16(0xD)
76 BUILD_16(0xE)
77 BUILD_IRQ(0xF0)
78 BUILD_IRQ(0xF1)
79 BUILD_IRQ(0xF2)
80 BUILD_IRQ(0xF3)
81 BUILD_IRQ(0xF4)
82 BUILD_IRQ(0xF5)
83 BUILD_IRQ(0xF6)
84 BUILD_IRQ(0xF7)
85 BUILD_IRQ(0xF8)
86 BUILD_IRQ(0xF9)
87 BUILD_IRQ(0xFA)
88 BUILD_IRQ(0xFB)
89 BUILD_IRQ(0xFC)
90 BUILD_IRQ(0xFD)
91 BUILD_IRQ(0xFE)
92 BUILD_IRQ(0xFF)
94 .balign 32, 0x90
95 .globl core_EnterInterrupt
96 .type core_EnterInterrupt,@function
98 core_EnterInterrupt: // At this point two UQUADs for segment registers are
99 // already reserved. They are occupied by error code and IRQ number
100 pushq $0 // Reserve two more UQUADs (for ES and DS)
101 pushq $0
102 pushq %rbp // Now save GPRs
103 pushq %r15
104 pushq %r14
105 pushq %r13
106 pushq %r12
107 pushq %r11
108 pushq %r10
109 pushq %r9
110 pushq %r8
111 pushq %rdi
112 pushq %rsi
113 pushq %rdx
114 pushq %rcx
115 pushq %rbx
116 pushq %rax
117 pushq $ECF_SEGMENTS // Flags. We have no FPU context here and even no pointer for it.
118 movq %rsp, %rdi // Supply context pointer to core_IRQHandle (first argument)
119 movq reg_gs(%rdi), %rsi // Error number - second argument
120 movq reg_fs(%rdi), %rdx // IRQ number - third argument
121 xorq %rax, %rax // Zero-pad segments
122 mov %ds, %ax // Now save segment registers
123 movq %rax, reg_ds(%rdi)
124 mov %es, %ax
125 movq %rax, reg_es(%rdi)
126 mov %fs, %ax
127 movq %rax, reg_fs(%rdi)
128 mov %gs, %ax
129 movq %rax, reg_gs(%rdi)
130 // In x86-64 only CS is used to determine current CPL.
131 // Also SS is used as an indicator into which mode iretq returns
132 // (set to zero when interrupt raises privilege level).
133 // So we do not have to manipulate segment registers here (unlike on i386).
134 jmp core_IRQHandle // Proceed to C handler
135 .size core_EnterInterrupt, .-core_EnterInterrupt
137 .globl core_LeaveInterrupt
138 .type core_LeaveInterrupt, @function
140 core_LeaveInterrupt:
141 movl Flags(%rdi), %eax // Test if the context contains segment registers
142 test $ECF_SEGMENTS, %eax
143 je noSegments
144 movq reg_ds(%rdi), %rax // Restore segment registers if present
145 mov %ax, %ds
146 movq reg_es(%rdi), %rax
147 mov %ax, %es
148 movq reg_fs(%rdi), %rax
149 mov %ax, %fs
150 movq reg_gs(%rdi), %rax
151 mov %ax, %gs
152 noSegments:
153 movq %rdi, %rsp // Load context pointer into SP, we will pop everything
154 popq %rax // These were flags, just remove them
155 popq %rax // Restore GPRs
156 popq %rbx
157 popq %rcx
158 popq %rdx
159 popq %rsi
160 popq %rdi
161 popq %r8
162 popq %r9
163 popq %r10
164 popq %r11
165 popq %r12
166 popq %r13
167 popq %r14
168 popq %r15
169 popq %rbp
170 addq $32, %rsp // Remove segments
172 .globl core_DefaultIRETQ
173 .type core_DefaultIRETQ, @function
175 core_DefaultIRETQ:
176 iretq // Exit
177 .size core_LeaveInterrupt, .-core_LeaveInterrupt
179 .globl core_Supervisor
180 .type core_Supervisor, @function
182 core_Supervisor:
183 movq %rdi, %rsp // Similar to above, but does not restore segment registers, and
184 popq %rax // chains to the routine pointed to by RDI.
185 popq %rax // Used for Supervisor() implementation.
186 popq %rbx // We could use int 0x81 with the only jmpq *%rdi instruction,
187 popq %rcx // but it's easier to jump to such code ocassionally. I hope
188 popq %rdx // it's not a big speed loss
189 popq %rsi
190 popq %rdi
191 popq %r8
192 popq %r9
193 popq %r10
194 popq %r11
195 popq %r12
196 popq %r13
197 popq %r14
198 popq %r15
199 popq %rbp
200 addq $32, %rsp
201 jmpq *%rdi
202 .size core_Supervisor, .-core_Supervisor