fix(v4): the kernel's fatal stops halt, interrupts off, instead of spinning (#177)
sk_v4_run's three stops -- "not started", "did not let go of POST's
blocks", "stopped on a fault" -- ended in for (;;) { }: a core spinning at
100%, the thing #151 removed from the prompt. Each now calls sk_v4_stop()
(kernel/src/v4/sk_v4_stop.c): interrupts off, then arch_halt() for ever. Each
still says why first. sk_v4_stop.c added to the loader's and the kernel's v4
sources.
kernel/tests/test_sk_v4_stop.c, with arch_halt and arch_disable_interrupts
faked (the halt jumps back out after three calls; an alarm fails a spin):
against the stop as it was -- "spun for 2 s without halting"; now -- 2
checks, 0 failures: halts in a loop, interrupts off before the first halt.
Built for amd64, aarch64 and riscv64. #177's "seen on the three
architectures": no boot reaches these stops, so it is shown on the host only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
This commit is contained in:
@@ -19,7 +19,8 @@ CC ?= cc
|
||||
CFLAGS := -std=c99 -Wall -Wextra -Werror -O2 -g -I$(HERE) -I$(ROOT)/kernel/include \
|
||||
-I$(ROOT)/kernel/include/starkernel -I$(ROOT)/v3/include
|
||||
|
||||
TESTS := test_gpt test_usb_config
|
||||
TESTS := test_gpt test_usb_config test_sk_v4_stop
|
||||
SRC_test_sk_v4_stop := $(ROOT)/kernel/src/v4/sk_v4_stop.c
|
||||
SRC_test_gpt := $(ROOT)/kernel/src/gpt.c
|
||||
SRC_test_usb_config := $(ROOT)/kernel/src/usb/usb_config.c
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/* SPDX-License-Identifier: LicenseRef-Starship-1.0
|
||||
* Copyright (c) 2023-2026 Robert A. James
|
||||
*/
|
||||
/* test_sk_v4_stop.c -- kernel/src/v4/sk_v4_stop.c on the host (#177): the v4 kernel's fatal stops
|
||||
* halt -- interrupts off, then arch_halt() in a loop -- instead of spinning a core at 100%.
|
||||
* arch_halt() and arch_disable_interrupts() are faked: the fake halt counts, and after a few calls
|
||||
* jumps back out of the loop. A stop that spins never calls it: an alarm ends the test as failed.
|
||||
*/
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#include "harness.h"
|
||||
#include "starkernel/v4/sk_v4_stop.h"
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static jmp_buf out;
|
||||
static int halts, irq_off, irq_off_before_first_halt = -1;
|
||||
|
||||
void arch_disable_interrupts(void) { irq_off = 1; }
|
||||
void arch_enable_interrupts(void) { irq_off = 0; }
|
||||
void arch_halt(void)
|
||||
{
|
||||
if (irq_off_before_first_halt < 0) irq_off_before_first_halt = irq_off;
|
||||
if (++halts >= 3) longjmp(out, 1); /* it is halting, again and again: enough */
|
||||
}
|
||||
static void spun(int sig)
|
||||
{
|
||||
(void)sig;
|
||||
static const char msg[] = "FAIL sk_v4_stop spun for 2 s without halting (#177)\n 1 checks, 1 failures\n";
|
||||
(void)!write(1, msg, sizeof msg - 1); /* not printf: _exit would not flush it */
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
signal(SIGALRM, spun);
|
||||
alarm(2);
|
||||
if (setjmp(out) == 0) sk_v4_stop();
|
||||
alarm(0);
|
||||
CHECK(halts == 3, "#177: the stop halts in a loop (arch_halt called %d times before the test stopped it)", halts);
|
||||
CHECK(irq_off_before_first_halt == 1, "#177: interrupts off before the first halt, so nothing wakes it to spin again");
|
||||
return DONE();
|
||||
}
|
||||
Reference in New Issue
Block a user