Files
LithosAnanake/include/starkernel/log_region.h
T
Robert Allan JamesandClaude Sonnet 5 2a30212bd3
Build / build-amd64-iso (push) Waiting to run
Build / build-aarch64-iso (push) Waiting to run
Build / build-riscv64-img (push) Waiting to run
Real per-VM log persistence: source attribution + ACL pin (FABRIC-3.md §XXVII)
Wires the previously-unused vm_log_attributed_vm() into LOG-APPEND's kernel
primitive so persisted log records carry a trustworthy source (the real
attributed VM's registry name, or "HADES" pseudo-source) instead of a
caller-supplied, trivially forgeable string. Drops src-addr/src-u from
LOG-APPEND's stack signature accordingly. Pins LOG-APPEND via bare ACL-PIN
in Artemis's own init.4th, matching BIRTH/CAPSULE-BIRTH's precedent for a
privileged word that can't reach the shared, host-portable ACL.4th.

Also fixes two console-banner nitpicks: a mis-rendering em dash (U+2014)
in the boot banner, and drops "Emergency" from the CLI banner text.

Doc corrections to artemis_sig.h/zuse_eligibility_list.h reconciling the
three fixed devblock ranges now in play. LOG-FLUSH (the intended normal
entry point) and level-aware log eviction remain open, flagged not fixed.

Re-verified clean boot to ok> on all 3 architectures after every change.
riscv64 showed one new, unrelated virtio_blk write-timeout anomaly during
Artemis's early physics self-test (self-recovered, boot unaffected,
sector doesn't map to the log region) -- flagged, not investigated.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016UNhH1mhi52i6Qihh7ZV5S
2026-09-13 08:56:33 -04:00

178 lines
8.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
StarForth — Steady-State Virtual Machine Runtime
Copyright (c) 20232025 Robert A. James
All rights reserved.
This file is part of the StarForth project.
Licensed under the StarForth License, Version 1.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
https://github.com/star.4th@proton.me/StarForth/LICENSE.txt
This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
express or implied, including but not limited to the warranties of
merchantability, fitness for a particular purpose, and noninfringement.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* log_region.h - Growable per-VM log-persistence ring on Artemis's own disk
* (FABRIC-3.md §XXVI follow-on, Step 4, 2026-09-13)
*
* Records real log_message() output (INFO and above, independent of the
* console's own current_level filter) so a run survives past the QEMU
* serial log -- the motivating case is comparing bare-metal and QEMU
* results directly as a DoE factor once bare-metal boot lands, where the
* only artifact both platforms share is whatever got persisted to disk.
*
* Lives in the SAME top-of-device system-metadata fence artemis_sig_t and
* Zuse's genesis marker/eligibility list already use
* (block_subsystem.h's blk_meta_zone_read()/write(), devblock_from_top
* addressing) -- reached the SAME way, deliberately NOT through
* artemis_sig.c's own independent blkio_info()-based arithmetic. That
* arithmetic exists only because artemis_sig_t must be discoverable on a
* device that isn't attached yet (bus-agnostic discovery, repl.c's
* idle-loop USB-MSC scan); this ring is only ever read or written once
* Artemis's disk is already attached and formatted (LOG-APPEND runs
* inside Artemis's own already-live dictionary context, dispatched by a
* sender's MSG-SEND/MSG-TICK), so blk_meta_zone_*() -- which requires
* exactly that already-attached state -- is the correct, simpler,
* already-tested tool, not a limitation to work around.
*
* Fixed devblock_from_top allocation (NOT persisted in artemis_sig_t's own
* log_region_offset/log_region_devblocks fields -- those stay at their
* genesis-time value of 0/0, "informational only, control header below is
* authoritative," documented in artemis_sig.h; two writers of the same
* fact was rejected as unnecessary drift risk):
* 64 -- artemis_sig_t itself (ARTEMIS_SIG_DEVBLOCK_FROM_TOP)
* 65 -- this ring's control header (LOG_REGION_DEVBLOCK_FROM_TOP_BASE)
* 66-96 -- this ring's slot devblocks, growable up to LOG_REGION_MAX_DEVBLOCKS
* Chosen clear of Zuse's genesis marker (devblock_from_top=0) and
* eligibility list (chains upward from 1, unbounded in code -- see
* zuse_eligibility_list.h's own CORRECTION comment, updated alongside this
* file, for the honest real-world headroom that leaves: devblocks 1-63,
* ~8000 possible eligible identities before ever reaching 64).
*
* Ring granularity is one whole devblock-quarter (LOG_SLOT_SIZE, 1024
* bytes = exactly one blkio forth-block) per record -- avoids any
* partial-forth-block read-modify-write for the write itself (a slot
* write is one aligned blkio_write()-equivalent-sized unit); the
* surrounding devblock (4 slots) still needs a read-modify-write via
* blk_meta_zone_read()/write() since that accessor's own unit is one full
* 4 KiB devblock, but that cost is the same regardless of slot size.
* Records are truncated to fit one slot rather than spanning multiple --
* simple, real, and sufficient for what's actually persisted (see
* vm_log_buffer.h's own tighter caps, chosen to fit a whole batch of
* several records inside one VM-EXEC/MSG-SEND line, INPUT_BUFFER_SIZE=1025).
*/
#ifndef STARKERNEL_LOG_REGION_H
#define STARKERNEL_LOG_REGION_H
#include <stdint.h>
#include "starkernel/artemis_sig.h" /* ARTEMIS_SIG_DEVBLOCK_FROM_TOP */
#ifdef __cplusplus
extern "C" {
#endif
/*===========================================================================
* Fence allocation
*===========================================================================*/
#define LOG_REGION_DEVBLOCK_FROM_TOP_BASE (ARTEMIS_SIG_DEVBLOCK_FROM_TOP + 1u) /* 65 */
#define LOG_REGION_INITIAL_DEVBLOCKS 4u /* slot devblocks at first use, excludes control header */
#define LOG_REGION_GROWTH_INCREMENT 4u
#define LOG_REGION_MAX_DEVBLOCKS 32u /* ceiling -- devblock_from_top stays within [66,96] */
#define LOG_SLOTS_PER_DEVBLOCK 4u /* 4 x 1 KiB forth-blocks per 4 KiB devblock */
#define LOG_SLOT_SIZE 1024u
/*===========================================================================
* log_region_ctrl_t - ring control header, one devblock at
* LOG_REGION_DEVBLOCK_FROM_TOP_BASE. head_slot/tail_slot/record_count are
* the authoritative, live ring state -- nothing outside this header (not
* even artemis_sig_t) needs to track it.
*===========================================================================*/
#define LOG_REGION_MAGIC 0x474C474Cull /* 'LGLG' */
#define LOG_REGION_VERSION_0 0
#define LOG_REGION_PACK(ver) \
(LOG_REGION_MAGIC | ((uint64_t)(ver) << 32))
#define LOG_REGION_GET_MAGIC(m) ((uint32_t)((m) & 0xFFFFFFFFull))
#define LOG_REGION_GET_VERSION(m) ((uint8_t)(((m) >> 32) & 0xFF))
typedef struct {
uint64_t magic; /* LOG_REGION_PACK(...) */
uint32_t devblocks; /* current slot-area size, in devblocks (excludes this header) */
uint32_t head_slot; /* index of the oldest live record */
uint32_t tail_slot; /* index where the NEXT record will be written */
uint32_t record_count; /* live records, <= devblocks * LOG_SLOTS_PER_DEVBLOCK */
uint64_t hdr_crc; /* covers every field above this one */
uint8_t _pad[4096 - (8 + 4 + 4 + 4 + 4 + 8)];
} log_region_ctrl_t;
typedef char log_region_ctrl_size_check[(sizeof(log_region_ctrl_t) == 4096) ? 1 : -1];
/*===========================================================================
* log_slot_t - one record, exactly one 1 KiB forth-block.
*===========================================================================*/
#define LOG_SLOT_SOURCE_MAX 16u /* NUL-padded VM/source tag, e.g. "Hera", "HADES" */
#define LOG_SLOT_MSG_MAX (LOG_SLOT_SIZE - 8u - 2u - 1u - LOG_SLOT_SOURCE_MAX) /* 997 */
/* Field order deliberate: uint64_t, uint16_t, uint8_t, then char arrays --
* every fixed field lands on its natural alignment with zero compiler-
* inserted padding (offsets 0, 8, 10, 11), so sizeof() == the hand-summed
* byte count the static assert below checks, and LOG_SLOT_SIZE (1024,
* already a multiple of 8) needs no trailing padding either. */
typedef struct {
uint64_t timestamp; /* shim.c's own KRELTSC-style relative tick */
uint16_t msg_len; /* used length of msg[], <= LOG_SLOT_MSG_MAX (997, needs 16 bits) */
uint8_t level; /* LogLevel */
char source[LOG_SLOT_SOURCE_MAX];
char msg[LOG_SLOT_MSG_MAX];
} log_slot_t;
typedef char log_slot_size_check[(sizeof(log_slot_t) == LOG_SLOT_SIZE) ? 1 : -1];
/*===========================================================================
* API
*===========================================================================*/
/*
* log_region_append - Write one record to the ring, growing it (within
* LOG_REGION_MAX_DEVBLOCKS) or evicting the oldest record (ring full and
* already at the growth ceiling) as needed. Initializes the ring on first
* use (control header blank). Never calls log_message() or anything that
* might (this runs inside Artemis's own dictionary context during message
* delivery -- see this header's own note on why; a log call here could
* recurse into this same append path via Artemis's own buffered flush).
*
* @param level LogLevel of this record.
* @param timestamp Caller-supplied relative timestamp (same KRELTSC base
* shim.c's own log_message() uses).
* @param source VM/source tag, e.g. "Hera", "HADES", an identity name.
* @param source_len Length of source (truncated to LOG_SLOT_SOURCE_MAX-1).
* @param msg Message text (not NUL-terminated required).
* @param msg_len Length of msg (truncated to LOG_SLOT_MSG_MAX).
* @return 0 on success, -1 on any read/write failure (ring left however
* the failed operation left it -- blk_meta_zone_write() itself
* never partially writes a devblock).
*/
int log_region_append(uint8_t level, uint64_t timestamp,
const char *source, uint32_t source_len,
const char *msg, uint32_t msg_len);
#ifdef __cplusplus
}
#endif
#endif /* STARKERNEL_LOG_REGION_H */