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