xref: /kvm-unit-tests/lib/x86/isr.c (revision 110f0d9389041e34b3597b505ef4774c237b35f7)
1*110f0d93SGleb Natapov #include "libcflat.h"
2*110f0d93SGleb Natapov #include "isr.h"
3*110f0d93SGleb Natapov #include "vm.h"
4*110f0d93SGleb Natapov #include "desc.h"
5*110f0d93SGleb Natapov 
6*110f0d93SGleb Natapov #ifdef __x86_64__
7*110f0d93SGleb Natapov #  define R "r"
8*110f0d93SGleb Natapov #else
9*110f0d93SGleb Natapov #  define R "e"
10*110f0d93SGleb Natapov #endif
11*110f0d93SGleb Natapov 
12*110f0d93SGleb Natapov extern char isr_entry_point[];
13*110f0d93SGleb Natapov 
14*110f0d93SGleb Natapov asm (
15*110f0d93SGleb Natapov     "isr_entry_point: \n"
16*110f0d93SGleb Natapov #ifdef __x86_64__
17*110f0d93SGleb Natapov     "push %r15 \n\t"
18*110f0d93SGleb Natapov     "push %r14 \n\t"
19*110f0d93SGleb Natapov     "push %r13 \n\t"
20*110f0d93SGleb Natapov     "push %r12 \n\t"
21*110f0d93SGleb Natapov     "push %r11 \n\t"
22*110f0d93SGleb Natapov     "push %r10 \n\t"
23*110f0d93SGleb Natapov     "push %r9  \n\t"
24*110f0d93SGleb Natapov     "push %r8  \n\t"
25*110f0d93SGleb Natapov #endif
26*110f0d93SGleb Natapov     "push %"R "di \n\t"
27*110f0d93SGleb Natapov     "push %"R "si \n\t"
28*110f0d93SGleb Natapov     "push %"R "bp \n\t"
29*110f0d93SGleb Natapov     "push %"R "sp \n\t"
30*110f0d93SGleb Natapov     "push %"R "bx \n\t"
31*110f0d93SGleb Natapov     "push %"R "dx \n\t"
32*110f0d93SGleb Natapov     "push %"R "cx \n\t"
33*110f0d93SGleb Natapov     "push %"R "ax \n\t"
34*110f0d93SGleb Natapov #ifdef __x86_64__
35*110f0d93SGleb Natapov     "mov %rsp, %rdi \n\t"
36*110f0d93SGleb Natapov     "callq *8*16(%rsp) \n\t"
37*110f0d93SGleb Natapov #else
38*110f0d93SGleb Natapov     "push %esp \n\t"
39*110f0d93SGleb Natapov     "calll *4+4*8(%esp) \n\t"
40*110f0d93SGleb Natapov     "add $4, %esp \n\t"
41*110f0d93SGleb Natapov #endif
42*110f0d93SGleb Natapov     "pop %"R "ax \n\t"
43*110f0d93SGleb Natapov     "pop %"R "cx \n\t"
44*110f0d93SGleb Natapov     "pop %"R "dx \n\t"
45*110f0d93SGleb Natapov     "pop %"R "bx \n\t"
46*110f0d93SGleb Natapov     "pop %"R "bp \n\t"
47*110f0d93SGleb Natapov     "pop %"R "bp \n\t"
48*110f0d93SGleb Natapov     "pop %"R "si \n\t"
49*110f0d93SGleb Natapov     "pop %"R "di \n\t"
50*110f0d93SGleb Natapov #ifdef __x86_64__
51*110f0d93SGleb Natapov     "pop %r8  \n\t"
52*110f0d93SGleb Natapov     "pop %r9  \n\t"
53*110f0d93SGleb Natapov     "pop %r10 \n\t"
54*110f0d93SGleb Natapov     "pop %r11 \n\t"
55*110f0d93SGleb Natapov     "pop %r12 \n\t"
56*110f0d93SGleb Natapov     "pop %r13 \n\t"
57*110f0d93SGleb Natapov     "pop %r14 \n\t"
58*110f0d93SGleb Natapov     "pop %r15 \n\t"
59*110f0d93SGleb Natapov #endif
60*110f0d93SGleb Natapov     ".globl isr_iret_ip\n\t"
61*110f0d93SGleb Natapov #ifdef __x86_64__
62*110f0d93SGleb Natapov     "add $8, %rsp \n\t"
63*110f0d93SGleb Natapov     "isr_iret_ip: \n\t"
64*110f0d93SGleb Natapov     "iretq \n\t"
65*110f0d93SGleb Natapov #else
66*110f0d93SGleb Natapov     "add $4, %esp \n\t"
67*110f0d93SGleb Natapov     "isr_iret_ip: \n\t"
68*110f0d93SGleb Natapov     "iretl \n\t"
69*110f0d93SGleb Natapov #endif
70*110f0d93SGleb Natapov     );
71*110f0d93SGleb Natapov 
72*110f0d93SGleb Natapov void handle_irq(unsigned vec, void (*func)(isr_regs_t *regs))
73*110f0d93SGleb Natapov {
74*110f0d93SGleb Natapov     u8 *thunk = vmalloc(50);
75*110f0d93SGleb Natapov 
76*110f0d93SGleb Natapov     set_idt_entry(vec, thunk, 0);
77*110f0d93SGleb Natapov 
78*110f0d93SGleb Natapov #ifdef __x86_64__
79*110f0d93SGleb Natapov     /* sub $8, %rsp */
80*110f0d93SGleb Natapov     *thunk++ = 0x48; *thunk++ = 0x83; *thunk++ = 0xec; *thunk++ = 0x08;
81*110f0d93SGleb Natapov     /* mov $func_low, %(rsp) */
82*110f0d93SGleb Natapov     *thunk++ = 0xc7; *thunk++ = 0x04; *thunk++ = 0x24;
83*110f0d93SGleb Natapov     *(u32 *)thunk = (ulong)func; thunk += 4;
84*110f0d93SGleb Natapov     /* mov $func_high, %(rsp+4) */
85*110f0d93SGleb Natapov     *thunk++ = 0xc7; *thunk++ = 0x44; *thunk++ = 0x24; *thunk++ = 0x04;
86*110f0d93SGleb Natapov     *(u32 *)thunk = (ulong)func >> 32; thunk += 4;
87*110f0d93SGleb Natapov     /* jmp isr_entry_point */
88*110f0d93SGleb Natapov     *thunk ++ = 0xe9;
89*110f0d93SGleb Natapov     *(u32 *)thunk = (ulong)isr_entry_point - (ulong)(thunk + 4);
90*110f0d93SGleb Natapov #else
91*110f0d93SGleb Natapov     /* push $func */
92*110f0d93SGleb Natapov     *thunk++ = 0x68;
93*110f0d93SGleb Natapov     *(u32 *)thunk = (ulong)func; thunk += 4;
94*110f0d93SGleb Natapov     /* jmp isr_entry_point */
95*110f0d93SGleb Natapov     *thunk++ = 0xe9;
96*110f0d93SGleb Natapov     *(u32 *)thunk = (ulong)isr_entry_point - (ulong)(thunk + 4);
97*110f0d93SGleb Natapov #endif
98*110f0d93SGleb Natapov }
99