5efa92f754
There is not that much use for it on a single CPU, however, deadlock between kernel and system task can be delected. Or a runaway loop. If a kernel gets locked up the timer interrupts don't occure (as all interrupts are disabled in kernel mode). The only chance is to interrupt the kernel by a non-maskable interrupt. This patch generates NMIs using performance counters. It uses the most widely available performace counters. As the performance counters are highly model-specific this patch is not guaranteed to work on every machine. Unfortunately this is also true for KVM :-/ On the other hand adding this feature for other models is not extremely difficult and the framework makes it hopefully easy enough. Depending on the frequency of the CPU an NMI is generated at most about every 0.5s If the cpu's speed is less then 2Ghz it is generated at most every 1s. In general an NMI is generated much less often as the performance counter counts down only if the cpu is not idle. Therefore the overhead of this feature is fairly minimal even if the load is high. Uppon detecting that the kernel is locked up the kernel dumps the state of the kernel registers and panics. Local APIC must be enabled for the watchdog to work. The code is _always_ compiled in, however, it is only enabled if watchdog=<non-zero> is set in the boot monitor. One corner case is serial console debugging. As dumping a lot of stuff to the serial link may take a lot of time, the watchdog does not detect lockups during this time!!! as it would result in too many false positives. 10 nmi have to be handled before the lockup is detected. This means something between ~5s to 10s. Another corner case is that the watchdog is enabled only after the paging is enabled as it would be pure madness to try to get it right.
98 lines
1.8 KiB
Makefile
98 lines
1.8 KiB
Makefile
# Makefile for kernel
|
|
|
|
include /etc/make.conf
|
|
|
|
ARCHAR=$(ARCH).a
|
|
|
|
# objects, excluding first-stage code, which is $(HEAD).
|
|
# the HEAD variable is passed as an argument to this Makefile
|
|
# by an upper level Makefile.
|
|
|
|
OBJS= arch_do_vmctl.o \
|
|
clock.o \
|
|
do_int86.o \
|
|
do_iopenable.o \
|
|
do_readbios.o \
|
|
do_sdevio.o \
|
|
exception.o \
|
|
i8259.o \
|
|
klib386.o \
|
|
memory.o \
|
|
mpx386.o \
|
|
protect.o \
|
|
system.o \
|
|
apic.o \
|
|
apic_asm.o \
|
|
watchdog.o
|
|
|
|
CPPFLAGS=-Iinclude
|
|
CFLAGS=$(CPPFLAGS) -Wall $(CPROFILE)
|
|
|
|
build: $(HEAD) $(ARCHAR)
|
|
|
|
$(ARCHAR): $(OBJS)
|
|
aal cr $@ $(OBJS)
|
|
|
|
depend:
|
|
mkdep "$(CC) -E $(CPPFLAGS)" *.c *.S > .depend
|
|
|
|
clean:
|
|
rm -f *.a *.o *~ *.tmp *.s
|
|
|
|
# How to build it
|
|
$(ARCHAR)(exception.o): exception.c
|
|
$(CC) $(CFLAGS) -c $<
|
|
|
|
$(ARCHAR)(i8259.o): i8259.c
|
|
$(CC) $(CFLAGS) -c $<
|
|
|
|
$(ARCHAR)(memory.o): memory.c
|
|
$(CC) $(CFLAGS) -c $<
|
|
|
|
$(ARCHAR)(protect.o): protect.c
|
|
$(CC) $(CFLAGS) -c $<
|
|
|
|
$(ARCHAR)(system.o): system.c
|
|
$(CC) $(CFLAGS) -c $<
|
|
|
|
$(ARCHAR)(do_int86.o): do_int86.c
|
|
$(CC) $(CFLAGS) -c $<
|
|
|
|
$(ARCHAR)(do_iopenable.o): do_iopenable.c
|
|
$(CC) $(CFLAGS) -c $<
|
|
|
|
$(ARCHAR)(arch_do_vmctl.o): arch_do_vmctl.c
|
|
$(CC) $(CFLAGS) -c $<
|
|
|
|
$(ARCHAR)(do_readbios.o): do_readbios.c
|
|
$(CC) $(CFLAGS) -c $<
|
|
|
|
$(ARCHAR)(do_sdevio.o): do_sdevio.c
|
|
$(CC) $(CFLAGS) -c $<
|
|
|
|
$(ARCHAR)(clock.o): clock.c
|
|
$(CC) $(CFLAGS) -c $<
|
|
|
|
klib386.o: klib386.S
|
|
$(CC) $(CFLAGS) -E -D__ASSEMBLY__ -o $@.tmp $<
|
|
gas2ack $@.tmp $@.s
|
|
$(CC) $(CFLAGS) -c -o $@ $@.s
|
|
|
|
mpx386.o: mpx386.S
|
|
$(CC) $(CFLAGS) -E -D__ASSEMBLY__ -o $@.tmp $<
|
|
gas2ack $@.tmp $@.s
|
|
$(CC) $(CFLAGS) -c -o $@ $@.s
|
|
|
|
apic_asm.o: apic_asm.S
|
|
$(CC) $(CFLAGS) -E -D__ASSEMBLY__ -o $@.tmp $<
|
|
gas2ack $@.tmp $@.s
|
|
$(CC) $(CFLAGS) -c -o $@ $@.s
|
|
|
|
.c.o:
|
|
$(CC) $(CFLAGS) -c -o $@ $<
|
|
|
|
$(HEAD): mpx386.o
|
|
cp $< $@
|
|
|
|
# Include generated dependencies.
|
|
include .depend
|