1 #include "kernel/kernel.h"
2 #include "kernel/watchdog.h"
4 #include <minix/minlib.h>
9 #define CPUID_UNHALTED_CORE_CYCLES_AVAILABLE 0
11 #define MSR_PERFMON_CRT0 0xc1
12 #define MSR_PERFMON_SEL0 0x186
14 #define MSR_PERFMON_SEL0_ENABLE (1 << 22)
17 * Intel architecture performance counters watchdog
20 PRIVATE
void intel_arch_watchdog_init(int cpu
)
25 ia32_msr_write(MSR_PERFMON_CRT0
, 0, 0);
27 /* Int, OS, USR, Core ccyles */
28 val
= 1 << 20 | 1 << 17 | 1 << 16 | 0x3c;
29 ia32_msr_write(MSR_PERFMON_SEL0
, 0, val
);
32 * should give as a tick approx. every 0.5-1s, the perf counter has only
33 * lowest 31 bits writable :(
35 cpuf
= cpu_get_freq(cpu
);
36 while (cpuf
.hi
|| cpuf
.lo
> 0x7fffffffU
)
37 cpuf
= div64u64(cpuf
, 2);
38 watchdog
->resetval
= cpuf
.lo
;
40 ia32_msr_write(MSR_PERFMON_CRT0
, 0, -cpuf
.lo
);
42 ia32_msr_write(MSR_PERFMON_SEL0
, 0, val
| MSR_PERFMON_SEL0_ENABLE
);
44 /* unmask the performance counter interrupt */
45 lapic_write(LAPIC_LVTPCR
, APIC_ICR_DM_NMI
);
48 PRIVATE
void intel_arch_watchdog_reinit(const int cpu
)
50 lapic_write(LAPIC_LVTPCR
, APIC_ICR_DM_NMI
);
51 ia32_msr_write(MSR_PERFMON_CRT0
, 0, -watchdog
->resetval
);
54 PRIVATE
struct arch_watchdog intel_arch_watchdog
= {
55 /*.init = */ intel_arch_watchdog_init
,
56 /*.reinit = */ intel_arch_watchdog_reinit
59 int arch_watchdog_init(void)
61 u32_t eax
, ebx
, ecx
, edx
;
65 _cpuid(&eax
, &ebx
, &ecx
, &edx
);
67 /* FIXME currently we support only watchdog base on the intel
68 * architectural performance counters. Some Intel CPUs don't have this
71 if (ebx
& (1 << CPUID_UNHALTED_CORE_CYCLES_AVAILABLE
))
73 if (!((((eax
>> 8)) & 0xff) > 0))
76 watchdog
= &intel_arch_watchdog
;
78 /* Setup PC tas NMI for watchdog, is is masked for now */
79 lapic_write(LAPIC_LVTPCR
, APIC_ICR_INT_MASK
| APIC_ICR_DM_NMI
);
80 lapic_read(LAPIC_LVTPCR
);
82 /* double check if LAPIC is enabled */
83 if (lapic_addr
&& watchdog_enabled
&& watchdog
->init
) {
84 watchdog
->init(cpuid
);
90 void arch_watchdog_lockup(const struct nmi_frame
* frame
)
92 printf("KERNEL LOCK UP\n"
122 panic("Kernel lockup");
125 void i386_watchdog_start(void)
127 if (watchdog_enabled
) {
128 if (arch_watchdog_init()) {
129 printf("WARNING watchdog initialization "
130 "failed! Disabled\n");
131 watchdog_enabled
= 0;
134 BOOT_VERBOSE(printf("Watchdog enabled\n"););