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 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 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