1 /* CPU interrupt handling entry points */
3 #include <aros/x86_64/asm.h>
7 #define BUILD_IRQ(nr) \
9 .globl IRQ##nr##_intr; \
10 .type IRQ##nr##_intr, @function; \
14 jmp core_EnterInterrupt; \
15 .size IRQ##nr##_intr, .-IRQ##nr##_intr;
17 #define BUILD_IRQ_ERR(nr) \
19 .globl IRQ##nr##_intr; \
20 .type IRQ##nr##_intr, @function; \
23 jmp core_EnterInterrupt; \
24 .size IRQ##nr##_intr, .-IRQ##nr##_intr;
26 #define B(x,y) BUILD_IRQ(x##y)
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
64 BUILD_16
(0x2) // Hardware IRQs.
..
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
)
102 pushq
%rbp
// Now save GPRs
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
)
125 movq
%rax
, reg_es
(%rdi
)
127 movq
%rax
, reg_fs
(%rdi
)
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
141 movl Flags
(%rdi
), %eax
// Test if the context contains segment registers
142 test $ECF_SEGMENTS
, %eax
144 movq reg_ds
(%rdi
), %rax
// Restore segment registers if present
146 movq reg_es
(%rdi
), %rax
148 movq reg_fs
(%rdi
), %rax
150 movq reg_gs
(%rdi
), %rax
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
170 addq $
32, %rsp
// Remove segments
172 .globl core_DefaultIRETQ
173 .type core_DefaultIRETQ, @function
177 .size core_LeaveInterrupt, .-core_LeaveInterrupt
179 .globl core_Supervisor
180 .type core_Supervisor, @function
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
202 .size core_Supervisor, .-core_Supervisor