xref: /kvm-unit-tests/lib/x86/isr.c (revision 74b225a7c6a25205257f9d0a6266093a2a8ddace)
1110f0d93SGleb Natapov #include "libcflat.h"
2110f0d93SGleb Natapov #include "isr.h"
3110f0d93SGleb Natapov #include "vm.h"
4110f0d93SGleb Natapov #include "desc.h"
5110f0d93SGleb Natapov 
6110f0d93SGleb Natapov extern char isr_entry_point[];
7110f0d93SGleb Natapov 
8110f0d93SGleb Natapov asm (
9110f0d93SGleb Natapov     "isr_entry_point: \n"
10110f0d93SGleb Natapov #ifdef __x86_64__
11110f0d93SGleb Natapov     "push %r15 \n\t"
12110f0d93SGleb Natapov     "push %r14 \n\t"
13110f0d93SGleb Natapov     "push %r13 \n\t"
14110f0d93SGleb Natapov     "push %r12 \n\t"
15110f0d93SGleb Natapov     "push %r11 \n\t"
16110f0d93SGleb Natapov     "push %r10 \n\t"
17110f0d93SGleb Natapov     "push %r9  \n\t"
18110f0d93SGleb Natapov     "push %r8  \n\t"
19110f0d93SGleb Natapov #endif
20110f0d93SGleb Natapov     "push %"R "di \n\t"
21110f0d93SGleb Natapov     "push %"R "si \n\t"
22110f0d93SGleb Natapov     "push %"R "bp \n\t"
23110f0d93SGleb Natapov     "push %"R "sp \n\t"
24110f0d93SGleb Natapov     "push %"R "bx \n\t"
25110f0d93SGleb Natapov     "push %"R "dx \n\t"
26110f0d93SGleb Natapov     "push %"R "cx \n\t"
27110f0d93SGleb Natapov     "push %"R "ax \n\t"
28110f0d93SGleb Natapov #ifdef __x86_64__
29110f0d93SGleb Natapov     "mov %rsp, %rdi \n\t"
30110f0d93SGleb Natapov     "callq *8*16(%rsp) \n\t"
31110f0d93SGleb Natapov #else
32110f0d93SGleb Natapov     "push %esp \n\t"
33110f0d93SGleb Natapov     "calll *4+4*8(%esp) \n\t"
34110f0d93SGleb Natapov     "add $4, %esp \n\t"
35110f0d93SGleb Natapov #endif
36110f0d93SGleb Natapov     "pop %"R "ax \n\t"
37110f0d93SGleb Natapov     "pop %"R "cx \n\t"
38110f0d93SGleb Natapov     "pop %"R "dx \n\t"
39110f0d93SGleb Natapov     "pop %"R "bx \n\t"
40110f0d93SGleb Natapov     "pop %"R "bp \n\t"
41110f0d93SGleb Natapov     "pop %"R "bp \n\t"
42110f0d93SGleb Natapov     "pop %"R "si \n\t"
43110f0d93SGleb Natapov     "pop %"R "di \n\t"
44110f0d93SGleb Natapov #ifdef __x86_64__
45110f0d93SGleb Natapov     "pop %r8  \n\t"
46110f0d93SGleb Natapov     "pop %r9  \n\t"
47110f0d93SGleb Natapov     "pop %r10 \n\t"
48110f0d93SGleb Natapov     "pop %r11 \n\t"
49110f0d93SGleb Natapov     "pop %r12 \n\t"
50110f0d93SGleb Natapov     "pop %r13 \n\t"
51110f0d93SGleb Natapov     "pop %r14 \n\t"
52110f0d93SGleb Natapov     "pop %r15 \n\t"
53110f0d93SGleb Natapov #endif
54110f0d93SGleb Natapov     ".globl isr_iret_ip\n\t"
55110f0d93SGleb Natapov #ifdef __x86_64__
56110f0d93SGleb Natapov     "add $8, %rsp \n\t"
57110f0d93SGleb Natapov     "isr_iret_ip: \n\t"
58110f0d93SGleb Natapov     "iretq \n\t"
59110f0d93SGleb Natapov #else
60110f0d93SGleb Natapov     "add $4, %esp \n\t"
61110f0d93SGleb Natapov     "isr_iret_ip: \n\t"
62110f0d93SGleb Natapov     "iretl \n\t"
63110f0d93SGleb Natapov #endif
64110f0d93SGleb Natapov     );
65110f0d93SGleb Natapov 
66110f0d93SGleb Natapov void handle_irq(unsigned vec, void (*func)(isr_regs_t *regs))
67110f0d93SGleb Natapov {
68110f0d93SGleb Natapov     u8 *thunk = vmalloc(50);
69110f0d93SGleb Natapov 
70110f0d93SGleb Natapov     set_idt_entry(vec, thunk, 0);
71110f0d93SGleb Natapov 
72110f0d93SGleb Natapov #ifdef __x86_64__
73110f0d93SGleb Natapov     /* sub $8, %rsp */
74110f0d93SGleb Natapov     *thunk++ = 0x48; *thunk++ = 0x83; *thunk++ = 0xec; *thunk++ = 0x08;
75110f0d93SGleb Natapov     /* mov $func_low, %(rsp) */
76110f0d93SGleb Natapov     *thunk++ = 0xc7; *thunk++ = 0x04; *thunk++ = 0x24;
77110f0d93SGleb Natapov     *(u32 *)thunk = (ulong)func; thunk += 4;
78110f0d93SGleb Natapov     /* mov $func_high, %(rsp+4) */
79110f0d93SGleb Natapov     *thunk++ = 0xc7; *thunk++ = 0x44; *thunk++ = 0x24; *thunk++ = 0x04;
80110f0d93SGleb Natapov     *(u32 *)thunk = (ulong)func >> 32; thunk += 4;
81110f0d93SGleb Natapov     /* jmp isr_entry_point */
82110f0d93SGleb Natapov     *thunk ++ = 0xe9;
83110f0d93SGleb Natapov     *(u32 *)thunk = (ulong)isr_entry_point - (ulong)(thunk + 4);
84110f0d93SGleb Natapov #else
85110f0d93SGleb Natapov     /* push $func */
86110f0d93SGleb Natapov     *thunk++ = 0x68;
87110f0d93SGleb Natapov     *(u32 *)thunk = (ulong)func; thunk += 4;
88110f0d93SGleb Natapov     /* jmp isr_entry_point */
89110f0d93SGleb Natapov     *thunk++ = 0xe9;
90110f0d93SGleb Natapov     *(u32 *)thunk = (ulong)isr_entry_point - (ulong)(thunk + 4);
91110f0d93SGleb Natapov #endif
92110f0d93SGleb Natapov }
9357b4317dSBandan Das 
9457b4317dSBandan Das void handle_external_interrupt(int vector)
9557b4317dSBandan Das {
9657b4317dSBandan Das 	idt_entry_t *idt = &boot_idt[vector];
9757b4317dSBandan Das 	unsigned long entry =
98*74b225a7SPaolo Bonzini 		idt->offset0 | ((unsigned long)idt->offset1 << 16);
99*74b225a7SPaolo Bonzini #ifdef __x86_64__
100*74b225a7SPaolo Bonzini 	unsigned long tmp;
101*74b225a7SPaolo Bonzini 	entry |= ((unsigned long)idt->offset2 << 32);
102*74b225a7SPaolo Bonzini #endif
10357b4317dSBandan Das 
10457b4317dSBandan Das 	asm volatile(
10557b4317dSBandan Das #ifdef __x86_64__
10657b4317dSBandan Das 		     "mov %%rsp, %[sp]\n\t"
10757b4317dSBandan Das 		     "and $0xfffffffffffffff0, %%rsp\n\t"
10857b4317dSBandan Das 		     "push $%c[ss]\n\t"
10957b4317dSBandan Das 		     "push %[sp]\n\t"
11057b4317dSBandan Das #endif
11157b4317dSBandan Das 		     "pushf\n\t"
112*74b225a7SPaolo Bonzini 		     "orl $0x200, (%%"R"sp)\n\t"
11357b4317dSBandan Das 		     "push $%c[cs]\n\t"
11457b4317dSBandan Das 		     "call *%[entry]\n\t"
11557b4317dSBandan Das 		     :
11657b4317dSBandan Das #ifdef __x86_64__
11757b4317dSBandan Das 		     [sp]"=&r"(tmp)
11857b4317dSBandan Das #endif
11957b4317dSBandan Das 		     :
12057b4317dSBandan Das 		     [entry]"r"(entry),
12157b4317dSBandan Das 		     [ss]"i"(KERNEL_DS),
12257b4317dSBandan Das 		     [cs]"i"(KERNEL_CS)
12357b4317dSBandan Das 		     );
12457b4317dSBandan Das }
125