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