xref: /kvm-unit-tests/lib/x86/isr.c (revision dcda215bee0e3d21eefba1b3658ba384952b5576)
1 #include "libcflat.h"
2 #include "processor.h"
3 #include "isr.h"
4 #include "alloc.h"
5 #include "desc.h"
6 
7 extern char isr_entry_point[];
8 
9 asm (
10     "isr_entry_point: \n"
11 #ifdef __x86_64__
12     "push %r15 \n\t"
13     "push %r14 \n\t"
14     "push %r13 \n\t"
15     "push %r12 \n\t"
16     "push %r11 \n\t"
17     "push %r10 \n\t"
18     "push %r9  \n\t"
19     "push %r8  \n\t"
20 #endif
21     "push %"R "di \n\t"
22     "push %"R "si \n\t"
23     "push %"R "bp \n\t"
24     "push %"R "sp \n\t"
25     "push %"R "bx \n\t"
26     "push %"R "dx \n\t"
27     "push %"R "cx \n\t"
28     "push %"R "ax \n\t"
29 #ifdef __x86_64__
30     "mov %rsp, %rdi \n\t"
31     "callq *8*16(%rsp) \n\t"
32 #else
33     "push %esp \n\t"
34     "calll *4+4*8(%esp) \n\t"
35     "add $4, %esp \n\t"
36 #endif
37     "pop %"R "ax \n\t"
38     "pop %"R "cx \n\t"
39     "pop %"R "dx \n\t"
40     "pop %"R "bx \n\t"
41     "pop %"R "bp \n\t"
42     "pop %"R "bp \n\t"
43     "pop %"R "si \n\t"
44     "pop %"R "di \n\t"
45 #ifdef __x86_64__
46     "pop %r8  \n\t"
47     "pop %r9  \n\t"
48     "pop %r10 \n\t"
49     "pop %r11 \n\t"
50     "pop %r12 \n\t"
51     "pop %r13 \n\t"
52     "pop %r14 \n\t"
53     "pop %r15 \n\t"
54 #endif
55     ".globl isr_iret_ip\n\t"
56 #ifdef __x86_64__
57     "add $8, %rsp \n\t"
58     "isr_iret_ip: \n\t"
59     "iretq \n\t"
60 #else
61     "add $4, %esp \n\t"
62     "isr_iret_ip: \n\t"
63     "iretl \n\t"
64 #endif
65     );
66 
handle_irq(unsigned vec,void (* func)(isr_regs_t * regs))67 void handle_irq(unsigned vec, void (*func)(isr_regs_t *regs))
68 {
69     u8 *thunk = malloc(50);
70 
71     set_idt_entry(vec, thunk, 0);
72 
73 #ifdef __x86_64__
74     /* sub $8, %rsp */
75     *thunk++ = 0x48; *thunk++ = 0x83; *thunk++ = 0xec; *thunk++ = 0x08;
76     /* mov $func_low, %(rsp) */
77     *thunk++ = 0xc7; *thunk++ = 0x04; *thunk++ = 0x24;
78     *(u32 *)thunk = (ulong)func; thunk += 4;
79     /* mov $func_high, %(rsp+4) */
80     *thunk++ = 0xc7; *thunk++ = 0x44; *thunk++ = 0x24; *thunk++ = 0x04;
81     *(u32 *)thunk = (ulong)func >> 32; thunk += 4;
82     /* jmp isr_entry_point */
83     *thunk ++ = 0xe9;
84     *(u32 *)thunk = (ulong)isr_entry_point - (ulong)(thunk + 4);
85 #else
86     /* push $func */
87     *thunk++ = 0x68;
88     *(u32 *)thunk = (ulong)func; thunk += 4;
89     /* jmp isr_entry_point */
90     *thunk++ = 0xe9;
91     *(u32 *)thunk = (ulong)isr_entry_point - (ulong)(thunk + 4);
92 #endif
93 }
94 
handle_external_interrupt(int vector)95 void handle_external_interrupt(int vector)
96 {
97 	idt_entry_t *idt = &boot_idt[vector];
98 	unsigned long entry =
99 		idt->offset0 | ((unsigned long)idt->offset1 << 16);
100 #ifdef __x86_64__
101 	unsigned long tmp;
102 	entry |= ((unsigned long)idt->offset2 << 32);
103 #endif
104 
105 	asm volatile(
106 #ifdef __x86_64__
107 		     "mov %%rsp, %[sp]\n\t"
108 		     "and $0xfffffffffffffff0, %%rsp\n\t"
109 		     "push $%c[ss]\n\t"
110 		     "push %[sp]\n\t"
111 #endif
112 		     "pushf\n\t"
113 		     "orl $0x200, (%%"R "sp)\n\t"
114 		     "push $%c[cs]\n\t"
115 		     "call *%[entry]\n\t"
116 		     :
117 #ifdef __x86_64__
118 		     [sp]"=&r"(tmp)
119 #endif
120 		     :
121 		     [entry]"r"(entry),
122 		     [ss]"i"(KERNEL_DS),
123 		     [cs]"i"(KERNEL_CS)
124 		     );
125 }
126