NMI sampling
- if profile --nmi kernel uses NMI watchdog based sampling based on Intel architecture performance counters - using NMI makes kernel profiling possible - watchdog kernel lockup detection is disabled while sampling as we may get unpredictable interrupts in kernel and thus possibly many false positives - if watchdog is not enabled at boot time, profiling enables it and turns it of again when done
This commit is contained in:
@@ -6,12 +6,13 @@
|
||||
|
||||
#include "watchdog.h"
|
||||
#include "arch/i386/glo.h"
|
||||
#include "profile.h"
|
||||
|
||||
unsigned watchdog_local_timer_ticks = 0U;
|
||||
struct arch_watchdog *watchdog;
|
||||
int watchdog_enabled;
|
||||
|
||||
void nmi_watchdog_handler(struct nmi_frame * frame)
|
||||
PRIVATE void lockup_check(struct nmi_frame * frame)
|
||||
{
|
||||
/* FIXME this should be CPU local */
|
||||
static unsigned no_ticks;
|
||||
@@ -23,7 +24,7 @@ void nmi_watchdog_handler(struct nmi_frame * frame)
|
||||
* report a lockup in such situation
|
||||
*/
|
||||
if (serial_debug_active)
|
||||
goto reset_and_continue;
|
||||
return;
|
||||
|
||||
if (last_tick_count != watchdog_local_timer_ticks) {
|
||||
if (no_ticks == 1) {
|
||||
@@ -32,7 +33,7 @@ void nmi_watchdog_handler(struct nmi_frame * frame)
|
||||
}
|
||||
/* we are still ticking, everything seems good */
|
||||
last_tick_count = watchdog_local_timer_ticks;
|
||||
goto reset_and_continue;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -42,12 +43,63 @@ void nmi_watchdog_handler(struct nmi_frame * frame)
|
||||
if (++no_ticks < 10) {
|
||||
if (no_ticks == 1)
|
||||
printf("WARNING watchdog : possible kernel lockup\n");
|
||||
goto reset_and_continue;
|
||||
return;
|
||||
}
|
||||
|
||||
/* if we get this far, the kernel is locked up */
|
||||
arch_watchdog_lockup(frame);
|
||||
}
|
||||
|
||||
reset_and_continue:
|
||||
if (watchdog->reinit)
|
||||
PUBLIC void nmi_watchdog_handler(struct nmi_frame * frame)
|
||||
{
|
||||
/*
|
||||
* Do not check for lockups while profiling, it is extremely likely that
|
||||
* a false positive is detected if the frequency is high
|
||||
*/
|
||||
if (watchdog_enabled && !sprofiling)
|
||||
lockup_check(frame);
|
||||
if (sprofiling)
|
||||
nmi_sprofile_handler(frame);
|
||||
|
||||
if ((watchdog_enabled || sprofiling) && watchdog->reinit)
|
||||
watchdog->reinit(cpuid);
|
||||
}
|
||||
|
||||
int nmi_watchdog_start_profiling(const unsigned freq)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* if watchdog hasn't been enabled, we must enable it now */
|
||||
if (!watchdog_enabled) {
|
||||
if (arch_watchdog_init())
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
if (!watchdog->profile_init) {
|
||||
printf("WARNING NMI watchdog profiling not supported\n");
|
||||
nmi_watchdog_stop_profiling();
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
err = watchdog->profile_init(freq);
|
||||
if (err != OK)
|
||||
return err;
|
||||
|
||||
watchdog->resetval = watchdog->profile_resetval;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void nmi_watchdog_stop_profiling(void)
|
||||
{
|
||||
/*
|
||||
* if we do not rearm the NMI source, we are done, if we want to keep
|
||||
* the watchdog running, we reset is to its normal value
|
||||
*/
|
||||
|
||||
if (watchdog)
|
||||
watchdog->resetval = watchdog->watchdog_resetval;
|
||||
|
||||
if (!watchdog_enabled)
|
||||
arch_watchdog_stop();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user