prism2.device: Compiler delint
[AROS.git] / arch / x86_64-pc / kernel / core_interrupts.s
blob609d20de2702fa40a2ceec3370dfadc93916dce2
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)
63 BUILD_16(0x2)
64 BUILD_IRQ(0x80)
65 BUILD_IRQ(0xfe) // APIC timer
67 .balign 32, 0x90
68 .globl core_EnterInterrupt
69 .type core_EnterInterrupt,@function
71 core_EnterInterrupt: // At this point two UQUADs for segment registers are
72 // already reserved. They are occupied by error code and IRQ number
73 pushq $0 // Reserve two more UQUADs (for ES and DS)
74 pushq $0
75 pushq %rbp // Now save GPRs
76 pushq %r15
77 pushq %r14
78 pushq %r13
79 pushq %r12
80 pushq %r11
81 pushq %r10
82 pushq %r9
83 pushq %r8
84 pushq %rdi
85 pushq %rsi
86 pushq %rdx
87 pushq %rcx
88 pushq %rbx
89 pushq %rax
90 pushq $ECF_SEGMENTS // Flags. We have no FPU context here and even no pointer for it.
91 movq %rsp, %rdi // Supply context pointer to core_IRQHandle (first argument)
92 movq reg_gs(%rdi), %rsi // Error number - second argument
93 movq reg_fs(%rdi), %rdx // IRQ number - third argument
94 xorq %rax, %rax // Zero-pad segments
95 mov %ds, %ax // Now save segment registers
96 movq %rax, reg_ds(%rdi)
97 mov %es, %ax
98 movq %rax, reg_es(%rdi)
99 mov %fs, %ax
100 movq %rax, reg_fs(%rdi)
101 mov %gs, %ax
102 movq %rax, reg_gs(%rdi)
103 // In x86-64 only CS is used to determine current CPL.
104 // Also SS is used as an indicator into which mode iretq returns
105 // (set to zero when interrupt raises privilege level).
106 // So we do not have to manipulate segment registers here (unlike on i386).
107 jmp core_IRQHandle // Proceed to C handler
108 .size core_EnterInterrupt, .-core_EnterInterrupt
110 .globl core_LeaveInterrupt
111 .type core_LeaveInterrupt, @function
113 core_LeaveInterrupt:
114 movl Flags(%rdi), %eax // Test if the context contains segment registers
115 test $ECF_SEGMENTS, %eax
116 je noSegments
117 movq reg_ds(%rdi), %rax // Restore segment registers if present
118 mov %ax, %ds
119 movq reg_es(%rdi), %rax
120 mov %ax, %es
121 movq reg_fs(%rdi), %rax
122 mov %ax, %fs
123 movq reg_gs(%rdi), %rax
124 mov %ax, %gs
125 noSegments:
126 movq %rdi, %rsp // Load context pointer into SP, we will pop everything
127 popq %rax // These were flags, just remove them
128 popq %rax // Restore GPRs
129 popq %rbx
130 popq %rcx
131 popq %rdx
132 popq %rsi
133 popq %rdi
134 popq %r8
135 popq %r9
136 popq %r10
137 popq %r11
138 popq %r12
139 popq %r13
140 popq %r14
141 popq %r15
142 popq %rbp
143 addq $32, %rsp // Remove segments
145 .globl core_DefaultIRETQ
146 .type core_DefaultIRETQ, @function
148 core_DefaultIRETQ:
149 iretq // Exit
150 .size core_LeaveInterrupt, .-core_LeaveInterrupt
152 .globl core_Supervisor
153 .type core_Supervisor, @function
155 core_Supervisor:
156 movq %rdi, %rsp // Similar to above, but does not restore segment registers, and
157 popq %rax // chains to the routine pointed to by RDI.
158 popq %rax // Used for Supervisor() implementation.
159 popq %rbx // We could use int 0x81 with the only jmpq *%rdi instruction,
160 popq %rcx // but it's easier to jump to such code ocassionally. I hope
161 popq %rdx // it's not a big speed loss
162 popq %rsi
163 popq %rdi
164 popq %r8
165 popq %r9
166 popq %r10
167 popq %r11
168 popq %r12
169 popq %r13
170 popq %r14
171 popq %r15
172 popq %rbp
173 addq $32, %rsp
174 jmpq *%rdi
175 .size core_Supervisor, .-core_Supervisor