Files
LithosAnanake/include/starkernel/percpu.h
T
Robert Allan JamesandClaude Opus 5.5 8409e376cf Stage MC-0a: per-core block on one core -- current VM moves behind the per-CPU register (FABRIC-3.10.8 §3.1)
- New sk_percpu_t { self, core_id, current_vm }, reached via GS base
  (amd64, %gs:0), TPIDR_EL1 (aarch64), tp (riscv64). Boot core's block is
  one static object installed right after arch_early_init(); secondary
  cores' blocks come with MC-1.
- switch.c's global g_switch_current_vm is gone; current VM is
  sk_percpu()->current_vm, re-read after resume in the context switch.
- Probe (removed): normal path and every heartbeat ISR found core 0's
  block on all three ISAs (ISR ok 889/1877/1625, bad 0).
- Standard sequence on amd64/aarch64/riscv64: hashes unchanged from O-C,
  G A=40 B=40, MINT/WIREBIND/USE ok, conservation true, 0 idle growth.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 13:56:48 -04:00

90 lines
3.2 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) 2023–2025 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.
*/
/**
* percpu.h - Per-core state (FABRIC-3.10.8 Stage MC-0a).
*
* Each core owns one sk_percpu_t, reached through that ISA's per-CPU
* register, so code running on a core -- including an interrupt handler --
* finds its own block without a lookup:
* - amd64: the GS base (IA32_GS_BASE); the block's first field points
* back at itself, so `mov %gs:0` reads the pointer.
* - aarch64: TPIDR_EL1 (reachable from EL2 as well, so either boot EL).
* - riscv64: the tp register (the kernel owns it: no user mode, no TLS;
* the trap entry never touches it).
*
* MC-0a: only the boot core exists, and its block is a single statically
* allocated object (not a table of cores -- secondary cores' blocks are
* allocated as they come online, MC-1). What moves in first is the switch
* mechanism's "who is running on this core" (was switch.c's global
* g_switch_current_vm).
*/
#ifndef STARKERNEL_PERCPU_H
#define STARKERNEL_PERCPU_H
#include <stdint.h>
struct VM;
typedef struct sk_percpu {
struct sk_percpu *self; /* must stay first: amd64 reads it as %gs:0 */
uint32_t core_id; /* 0 = the boot core (the system core, MC-R1) */
struct VM *current_vm; /* who is running on this core (switch.c) */
} sk_percpu_t;
/* Installs the boot core's block in this core's per-CPU register. Call
* once, as early as possible (kernel_main, straight after
* arch_early_init(): on amd64 that reloads GS, which would reset the base). */
void sk_percpu_boot_init(void);
/* This core's block. Valid from sk_percpu_boot_init() on. */
static inline sk_percpu_t *sk_percpu(void)
{
sk_percpu_t *p;
#if defined(__x86_64__)
__asm__ volatile ("movq %%gs:0, %0" : "=r"(p));
#elif defined(__aarch64__)
__asm__ volatile ("mrs %0, tpidr_el1" : "=r"(p));
#elif defined(__riscv)
__asm__ volatile ("mv %0, tp" : "=r"(p));
#else
#error "percpu.h: unsupported architecture"
#endif
return p;
}
/* Architecture hook: point this core's per-CPU register at `p`. */
static inline void sk_percpu_install(sk_percpu_t *p)
{
#if defined(__x86_64__)
uint64_t v = (uint64_t)(uintptr_t)p;
__asm__ volatile ("wrmsr" : : "c"(0xC0000101u) /* IA32_GS_BASE */,
"a"((uint32_t)v), "d"((uint32_t)(v >> 32)) : "memory");
#elif defined(__aarch64__)
__asm__ volatile ("msr tpidr_el1, %0" : : "r"(p) : "memory");
#elif defined(__riscv)
__asm__ volatile ("mv tp, %0" : : "r"(p) : "memory");
#endif
}
#endif /* STARKERNEL_PERCPU_H */