+const char * trap_type[] = {TRAP_NAMES};
+unsigned TRAP_TYPES = sizeof(trap_type)/sizeof(trap_type[0]);
+
+extern void PE_incoming_interrupt(int interrupt);
+
+#if defined(__x86_64__) && DEBUG
+void
+kprint_state(x86_saved_state64_t *saved_state)
+{
+ kprintf("current_cpu_datap() 0x%lx\n", (uintptr_t)current_cpu_datap());
+ kprintf("Current GS base MSR 0x%llx\n", rdmsr64(MSR_IA32_GS_BASE));
+ kprintf("Kernel GS base MSR 0x%llx\n", rdmsr64(MSR_IA32_KERNEL_GS_BASE));
+ kprintf("state at 0x%lx:\n", (uintptr_t) saved_state);
+
+ kprintf(" rdi 0x%llx\n", saved_state->rdi);
+ kprintf(" rsi 0x%llx\n", saved_state->rsi);
+ kprintf(" rdx 0x%llx\n", saved_state->rdx);
+ kprintf(" r10 0x%llx\n", saved_state->r10);
+ kprintf(" r8 0x%llx\n", saved_state->r8);
+ kprintf(" r9 0x%llx\n", saved_state->r9);
+ kprintf(" v_arg6 0x%llx\n", saved_state->v_arg6);
+ kprintf(" v_arg7 0x%llx\n", saved_state->v_arg7);
+ kprintf(" v_arg8 0x%llx\n", saved_state->v_arg8);
+
+ kprintf(" cr2 0x%llx\n", saved_state->cr2);
+ kprintf("real cr2 0x%lx\n", get_cr2());
+ kprintf(" r15 0x%llx\n", saved_state->r15);
+ kprintf(" r14 0x%llx\n", saved_state->r14);
+ kprintf(" r13 0x%llx\n", saved_state->r13);
+ kprintf(" r12 0x%llx\n", saved_state->r12);
+ kprintf(" r11 0x%llx\n", saved_state->r11);
+ kprintf(" rbp 0x%llx\n", saved_state->rbp);
+ kprintf(" rbx 0x%llx\n", saved_state->rbx);
+ kprintf(" rcx 0x%llx\n", saved_state->rcx);
+ kprintf(" rax 0x%llx\n", saved_state->rax);
+
+ kprintf(" gs 0x%x\n", saved_state->gs);
+ kprintf(" fs 0x%x\n", saved_state->fs);
+
+ kprintf(" isf.trapno 0x%x\n", saved_state->isf.trapno);
+ kprintf(" isf._pad 0x%x\n", saved_state->isf._pad);
+ kprintf(" isf.trapfn 0x%llx\n", saved_state->isf.trapfn);
+ kprintf(" isf.err 0x%llx\n", saved_state->isf.err);
+ kprintf(" isf.rip 0x%llx\n", saved_state->isf.rip);
+ kprintf(" isf.cs 0x%llx\n", saved_state->isf.cs);
+ kprintf(" isf.rflags 0x%llx\n", saved_state->isf.rflags);
+ kprintf(" isf.rsp 0x%llx\n", saved_state->isf.rsp);
+ kprintf(" isf.ss 0x%llx\n", saved_state->isf.ss);
+}
+#endif
+
+
+/*
+ * Non-zero indicates latency assert is enabled and capped at valued
+ * absolute time units.
+ */
+
+uint64_t interrupt_latency_cap = 0;
+boolean_t ilat_assert = FALSE;
+
+void
+interrupt_latency_tracker_setup(void) {
+ uint32_t ilat_cap_us;
+ if (PE_parse_boot_argn("interrupt_latency_cap_us", &ilat_cap_us, sizeof(ilat_cap_us))) {
+ interrupt_latency_cap = ilat_cap_us * NSEC_PER_USEC;
+ nanoseconds_to_absolutetime(interrupt_latency_cap, &interrupt_latency_cap);
+ } else {
+ interrupt_latency_cap = LockTimeOut;
+ }
+ PE_parse_boot_argn("-interrupt_latency_assert_enable", &ilat_assert, sizeof(ilat_assert));
+}
+
+void interrupt_reset_latency_stats(void) {
+ uint32_t i;
+ for (i = 0; i < real_ncpus; i++) {
+ cpu_data_ptr[i]->cpu_max_observed_int_latency =
+ cpu_data_ptr[i]->cpu_max_observed_int_latency_vector = 0;
+ }
+}
+
+void interrupt_populate_latency_stats(char *buf, unsigned bufsize) {
+ uint32_t i, tcpu = ~0;
+ uint64_t cur_max = 0;
+
+ for (i = 0; i < real_ncpus; i++) {
+ if (cur_max < cpu_data_ptr[i]->cpu_max_observed_int_latency) {
+ cur_max = cpu_data_ptr[i]->cpu_max_observed_int_latency;
+ tcpu = i;
+ }
+ }
+
+ if (tcpu < real_ncpus)
+ snprintf(buf, bufsize, "0x%x 0x%x 0x%llx", tcpu, cpu_data_ptr[tcpu]->cpu_max_observed_int_latency_vector, cpu_data_ptr[tcpu]->cpu_max_observed_int_latency);
+}
+