static int isr_hooker_init(void) { gate_desc *old_idt, *new_idt; unsigned long new_idt_page; pr_info("%s\n", __func__); /* obtain IDT descriptor */ store_idt(&old_idtr); old_idt = (gate_desc *)old_idtr.address; /* prepare new IDT */ new_idt_page = __get_free_page(GFP_KERNEL); if(!new_idt_page) return -ENOMEM; new_idtr.address = new_idt_page; new_idtr.size = old_idtr.size; new_idt = (gate_desc *)new_idtr.address; memcpy(new_idt, old_idt, old_idtr.size); /* modify the target entry */ orig_isr = gate_offset(new_idt[TRAP_NR]); pr_info("orig_isr@%p\n", (void*)orig_isr); pack_gate(&new_idt[TRAP_NR], GATE_INTERRUPT, (unsigned long)stub, 0, 0, __KERNEL_CS); /* setup new entry */ load_idt((void *)&new_idtr); smp_call_function((smp_call_func_t)load_idt, &new_idtr, 1); return 0; }
static int cvt_gate_to_trap(int vector, const gate_desc *val, struct trap_info *info) { unsigned long addr; if (val->type != GATE_TRAP && val->type != GATE_INTERRUPT) return 0; info->vector = vector; addr = gate_offset(*val); #ifdef CONFIG_X86_64 /* * Look for known traps using IST, and substitute them * appropriately. The debugger ones are the only ones we care * about. Xen will handle faults like double_fault, * so we should never see them. Warn if * there's an unexpected IST-using fault handler. */ if (addr == (unsigned long)debug) addr = (unsigned long)xen_debug; else if (addr == (unsigned long)int3) addr = (unsigned long)xen_int3; else if (addr == (unsigned long)stack_segment) addr = (unsigned long)xen_stack_segment; else if (addr == (unsigned long)double_fault || addr == (unsigned long)nmi) { /* Don't need to handle these */ return 0; #ifdef CONFIG_X86_MCE } else if (addr == (unsigned long)machine_check) { /* * when xen hypervisor inject vMCE to guest, * use native mce handler to handle it */ ; #endif } else { /* Some other trap using IST? */ if (WARN_ON(val->ist != 0)) return 0; } #endif /* CONFIG_X86_64 */ info->address = addr; info->cs = gate_segment(*val); info->flags = val->dpl; /* interrupt gates clear IF */ if (val->type == GATE_INTERRUPT) info->flags |= 1 << 2; return 1; }
void ltt_dump_idt_table(void *call_data) { int i; char namebuf[KSYM_NAME_LEN]; for (i = 0; i < IDT_ENTRIES; i++) { unsigned long address = gate_offset(idt_table[i]); sprint_symbol(namebuf, address); __trace_mark(0, irq_state, idt_table, call_data, "irq %d address %p symbol %s", i, (void *)address, namebuf); } }
static int cvt_gate_to_trap(int vector, const gate_desc *val, struct trap_info *info) { unsigned long addr; if (val->type != GATE_TRAP && val->type != GATE_INTERRUPT) return 0; info->vector = vector; addr = gate_offset(*val); #ifdef CONFIG_X86_64 /* */ if (addr == (unsigned long)debug) addr = (unsigned long)xen_debug; else if (addr == (unsigned long)int3) addr = (unsigned long)xen_int3; else if (addr == (unsigned long)stack_segment) addr = (unsigned long)xen_stack_segment; else if (addr == (unsigned long)double_fault || addr == (unsigned long)nmi) { /* */ return 0; #ifdef CONFIG_X86_MCE } else if (addr == (unsigned long)machine_check) { return 0; #endif } else { /* */ if (WARN_ON(val->ist != 0)) return 0; } #endif /* */ info->address = addr; info->cs = gate_segment(*val); info->flags = val->dpl; /* */ if (val->type == GATE_INTERRUPT) info->flags |= 1 << 2; return 1; }
static int cvt_gate_to_trap(int vector, const gate_desc *val, struct trap_info *info) { if (val->type != GATE_TRAP && val->type != GATE_INTERRUPT) return 0; info->vector = vector; info->address = gate_offset(*val); info->cs = gate_segment(*val); info->flags = val->dpl; /* interrupt gates clear IF */ if (val->type == GATE_INTERRUPT) info->flags |= 1 << 2; return 1; }