/* * linux/arch/i386/nmi.c * * NMI watchdog support on APIC systems * * Started by Ingo Molnar * * Fixes: * Mikael Pettersson : AMD K7 support for local APIC NMI watchdog. * Mikael Pettersson : Power Management for local APIC NMI watchdog. * Mikael Pettersson : Pentium 4 support for local APIC NMI watchdog. * Pavel Machek and * Mikael Pettersson : PM converted to driver model. Disable/enable API. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include unsigned int nmi_watchdog = NMI_NONE; static unsigned int nmi_hz = HZ; static unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ static unsigned int nmi_p4_cccr_val; static DEFINE_PER_CPU(struct timer, nmi_timer); static DEFINE_PER_CPU(unsigned int, nmi_timer_ticks); /* * lapic_nmi_owner tracks the ownership of the lapic NMI hardware: * - it may be reserved by some other driver, or not * - when not reserved by some other driver, it may be used for * the NMI watchdog, or not * * This is maintained separately from nmi_active because the NMI * watchdog may also be driven from the I/O APIC timer. */ static DEFINE_SPINLOCK(lapic_nmi_owner_lock); static unsigned int lapic_nmi_owner; #define LAPIC_NMI_WATCHDOG (1<<0) #define LAPIC_NMI_RESERVED (1<<1) /* nmi_active: * +1: the lapic NMI watchdog is active, but can be disabled * 0: the lapic NMI watchdog has not been set up, and cannot * be enabled * -1: the lapic NMI watchdog is disabled, but can be enabled */ int nmi_active; #define K7_EVNTSEL_ENABLE (1 << 22) #define K7_EVNTSEL_INT (1 << 20) #define K7_EVNTSEL_OS (1 << 17) #define K7_EVNTSEL_USR (1 << 16) #define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76 #define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING #define P6_EVNTSEL0_ENABLE (1 << 22) #define P6_EVNTSEL_INT (1 << 20) #define P6_EVNTSEL_OS (1 << 17) #define P6_EVNTSEL_USR (1 << 16) #define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79 #define CORE_EVENT_CPU_CLOCKS_NOT_HALTED 0x3c #define P4_ESCR_EVENT_SELECT(N) ((N)<<25) #define P4_CCCR_OVF_PMI0 (1<<26) #define P4_CCCR_OVF_PMI1 (1<<27) #define P4_CCCR_THRESHOLD(N) ((N)<<20) #define P4_CCCR_COMPLEMENT (1<<19) #define P4_CCCR_COMPARE (1<<18) #define P4_CCCR_REQUIRED (3<<16) #define P4_CCCR_ESCR_SELECT(N) ((N)<<13) #define P4_CCCR_ENABLE (1<<12) /* * Set up IQ_PERFCTR0 to behave like a clock, by having IQ_CCCR0 filter * CRU_ESCR0 (with any non-null event selector) through a complemented * max threshold. [IA32-Vol3, Section 14.9.9] */ #define P4_NMI_CRU_ESCR0 P4_ESCR_EVENT_SELECT(0x3F) #define P4_NMI_IQ_CCCR0 \ (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \ P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE) int __init check_nmi_watchdog (void) { static unsigned int __initdata prev_nmi_count[NR_CPUS]; int cpu; if ( !nmi_watchdog ) return 0; printk("Testing NMI watchdog --- "); for ( cpu = 0; cpu < NR_CPUS; cpu++ ) prev_nmi_count[cpu] = nmi_count(cpu); local_irq_enable(); mdelay((10*1000)/nmi_hz); /* wait 10 ticks */ for ( cpu = 0; cpu < NR_CPUS; cpu++ ) { if ( !cpu_isset(cpu, cpu_callin_map) && !cpu_isset(cpu, cpu_online_map) ) continue; if ( nmi_count(cpu) - prev_nmi_count[cpu] <= 5 ) printk("CPU#%d stuck. ", cpu); else printk("CPU#%d okay. ", cpu); } printk("\n"); /* * Now that we know it works we can reduce NMI frequency to * something more reasonable; makes a difference in some configs. * There's a limit to how slow we can go because writing the perfctr * MSRs only sets the low 32 bits, with the top 8 bits sign-extended * from those, so it's not possible to set up a delay larger than * 2^31 cycles and smaller than (2^40 - 2^31) cycles. * (Intel SDM, section 18.22.2) */ if ( nmi_watchdog == NMI_LOCAL_APIC ) nmi_hz = max(1ul, cpu_khz >> 20); return 0; } static void nmi_timer_fn(void *unused) { this_cpu(nmi_timer_ticks)++; set_timer(&this_cpu(nmi_timer), NOW() + MILLISECS(1000)); } static void disable_lapic_nmi_watchdog(void) { if (nmi_active <= 0) return; switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_AMD: wrmsr(MSR_K7_EVNTSEL0, 0, 0); break; case X86_VENDOR_INTEL: switch (boot_cpu_data.x86) { case 6: if (boot_cpu_data.x86_model > 0xd) break; wrmsr(MSR_P6_EVNTSEL0, 0, 0); break; case 15: if (boot_cpu_data.x86_model > 0x4) break; wrmsr(MSR_P4_IQ_CCCR0, 0, 0); wrmsr(MSR_P4_CRU_ESCR0, 0, 0); break; } break; } nmi_active = -1; /* tell do_nmi() and others that we're not active any more */ nmi_watchdog = 0; } static void enable_lapic_nmi_watchdog(void) { if (nmi_active < 0) { nmi_watchdog = NMI_LOCAL_APIC; setup_apic_nmi_watchdog(); } } int reserve_lapic_nmi(void) { unsigned int old_owner; spin_lock(&lapic_nmi_owner_lock); old_owner = lapic_nmi_owner; lapic_nmi_owner |= LAPIC_NMI_RESERVED; spin_unlock(&lapic_nmi_owner_lock); if (old_owner & LAPIC_NMI_RESERVED) return -EBUSY; if (old_owner & LAPIC_NMI_WATCHDOG) disable_lapic_nmi_watchdog(); return 0; } void release_lapic_nmi(void) { unsigned int new_owner; spin_lock(&lapic_nmi_owner_lock); new_owner = lapic_nmi_owner & ~LAPIC_NMI_RESERVED; lapic_nmi_owner = new_owner; spin_unlock(&lapic_nmi_owner_lock); if (new_owner & LAPIC_NMI_WATCHDOG) enable_lapic_nmi_watchdog(); } #define __pminit __devinit /* * Activate the NMI watchdog via the local APIC. * Original code written by Keith Owens. */ static void __pminit clear_msr_range(unsigned int base, unsigned int n) { unsigned int i; for (i = 0; i < n; i++) wrmsr(base+i, 0, 0); } static inline void write_watchdog_counter(const char *descr) { u64 count = (u64)cpu_khz * 1000; do_div(count, nmi_hz); if(descr) Dprintk("setting %s to -0x%08Lx\n", descr, count); wrmsrl(nmi_perfctr_msr, 0 - count); } static void __pminit setup_k7_watchdog(void) { unsigned int evntsel; nmi_perfctr_msr = MSR_K7_PERFCTR0; clear_msr_range(MSR_K7_EVNTSEL0, 4); clear_msr_range(MSR_K7_PERFCTR0, 4); evntsel = K7_EVNTSEL_INT | K7_EVNTSEL_OS | K7_EVNTSEL_USR | K7_NMI_EVENT; wrmsr(MSR_K7_EVNTSEL0, evntsel, 0); write_watchdog_counter("K7_PERFCTR0"); apic_write(APIC_LVTPC, APIC_DM_NMI); evntsel |= K7_EVNTSEL_ENABLE; wrmsr(MSR_K7_EVNTSEL0, evntsel, 0); } static void __pminit setup_p6_watchdog(unsigned counter) { unsigned int evntsel; nmi_perfctr_msr = MSR_P6_PERFCTR0; clear_msr_range(MSR_P6_EVNTSEL0, 2); clear_msr_range(MSR_P6_PERFCTR0, 2); evntsel = P6_EVNTSEL_INT | P6_EVNTSEL_OS | P6_EVNTSEL_USR | counter; wrmsr(MSR_P6_EVNTSEL0, evntsel, 0); write_watchdog_counter("P6_PERFCTR0
//TODO: move into utils
.user-select (@val) {
    -webkit-touch-callout: @val;
    -webkit-user-select: @val;
    -khtml-user-select: @val;
    -moz-user-select: @val;
    -ms-user-select: @val;
    user-select: @val;
}

.flow-table {
    width: 100%;
    overflow-y: scroll;
    overflow-x: hidden;

    table {
        width: 100%;
        table-layout: fixed;
    }

    thead {
        background-color: #F2F2F2;
        line-height: 23px;
    }

    th {
        font-weight: normal;
        box-shadow: 0 1px 0 #a6a6a6;
        position: relative !important;
        padding-left: 1px;
        .user-select(none);

        &.sort-asc, &.sort-desc {
            background-color: lighten(#F2F2F2, 3%);
        }
        &.sort-asc:after, &.sort-desc:after {
            font: normal normal normal 14px/1 FontAwesome;
            position: absolute;
            right: 3px;
            top: 3px;
            padding: 2px;
            background-color: fadeout(lighten(#F2F2F2, 3%), 20%);
        }
        &.sort-asc:after {
            content: "\f0de";
        }
        &.sort-desc:after {
            content: "\f0dd";
        }

    }

    tr {
        cursor: pointer;

        &:nth-child(even) {
            background-color: rgba(0, 0, 0, 0.05);
        }
        &.selected {
            background-color: hsla(209, 52%, 84%, 0.5) !important;
        }
        &.highlighted {
            background-color: hsla(48, 100%, 50%, 0.4);
        }
        &.highlighted:nth-child(even) {
            background-color: hsla(48, 100%, 50%, 0.5);
        }
    }

    td {
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
    }

    @interceptorange: hsl(30, 100%, 50%);

    tr.intercepted:not(.has-response) {
        .col-path, .col-method {
            color: @interceptorange;
        }
    }
    tr.intercepted.has-response {
        .col-status, .col-size, .col-time {
            color: @interceptorange;
        }
    }

    .fa {
        line-height: inherit;
        &.pull-right {
            margin-left: 0;
        }
    }

    .col-tls {
        width: 10px;
    }
    .col-tls-https {
        background-color: rgba(0, 185, 0, 0.5);
    }
    .col-icon {
        width: 32px;
    }
    .col-path {
        .fa-repeat {
            color: green;
        }
        .fa-pause {
            color: @interceptorange;
        }
    }
    .col-method {
        width: 60px;
    }
    .col-status {
        width: 50px;
    }
    .col-size {
        width: 70px;
    }
    .col-time {
        width: 50px;
    }
    td.col-time, td.col-size {
        text-align: right;
    }
}