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