feat(hal/core): implement heartbeat of iron (real-time SBI timer driver)
- Implemented RISC-V SBI timer driver in HAL (entry_riscv.zig). - Integrated timer into the Harmonic Scheduler (kernel.nim/sched.nim). - Re-enabled the Silence Doctrine: system now enters low-power WFI state during idle. - Confirmed precise nanosecond wakeup and LwIP pump loop stability. - Updated kernel version to v1.1.2.
This commit is contained in:
parent
96ee0a0112
commit
77b4cb55c7
|
|
@ -62,12 +62,8 @@ proc main() =
|
|||
if loop_count mod 1 == 0:
|
||||
print(cstring("[INIT] Heartbeat\n"))
|
||||
|
||||
# Busy Wait Sleep (10ms) to bypass broken WFI/Timer
|
||||
# TODO: Restore nanosleep once HAL Timer Driver is implemented
|
||||
proc sys_now(): uint32 {.importc, cdecl.}
|
||||
let start_sleep = sys_now()
|
||||
while sys_now() - start_sleep < 10:
|
||||
discard syscall(0x100, 0, 0, 0) # YIELD
|
||||
# Sleep 10ms using Timer Driver (System Call)
|
||||
discard syscall(0x65, 10000000'u64)
|
||||
|
||||
when isMainModule:
|
||||
main()
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ const
|
|||
MAX_FIBER_STACK* = 128 * 1024
|
||||
SYSTABLE_BASE* = 0x83000000'u64
|
||||
|
||||
# Export Nim Timer Handler for HAL (Zig calls this)
|
||||
proc rumpk_timer_handler() {.exportc, cdecl, used.} =
|
||||
discard
|
||||
|
||||
# --- EXTERNAL SYMBOLS ---
|
||||
proc ion_get_phys(id: uint16): uint64 {.importc, cdecl.}
|
||||
proc ion_alloc_raw*(out_id: ptr uint16): uint64 {.importc, cdecl.}
|
||||
|
|
@ -286,7 +290,7 @@ proc ion_fiber_entry() {.cdecl.} =
|
|||
fiber_child.satp_value = mm_create_worker_map(cast[uint64](addr stack_child[0]), uint64(sizeof(stack_child)), SYSTABLE_BASE, cell_base, cell_size)
|
||||
kprintln("[ION] Child fiber spawned successfully")
|
||||
else: discard
|
||||
fiber_sleep(100)
|
||||
fiber_sleep(10_000_000) # 10ms
|
||||
|
||||
proc fiber_yield*() {.exportc, cdecl.} =
|
||||
proc rumpk_yield_guard() {.importc, cdecl.}
|
||||
|
|
@ -303,7 +307,7 @@ proc fiber_netswitch_entry() {.cdecl.} =
|
|||
if chan_netswitch_rx.recv(pkt):
|
||||
ion_free_raw(pkt.id)
|
||||
else:
|
||||
fiber_sleep(100)
|
||||
fiber_sleep(10_000_000) # 10ms
|
||||
fiber_yield()
|
||||
|
||||
proc ion_ingress*(id: uint16, len: uint16) {.exportc, cdecl.} =
|
||||
|
|
@ -455,7 +459,7 @@ proc kmain() {.exportc, cdecl.} =
|
|||
var next_mmio_addr {.importc: "virtio_pci_next_mmio_addr", nodecl.}: uint32
|
||||
kprint("\n[Kernel] next_mmio_addr check: ")
|
||||
kprint_hex(uint64(next_mmio_addr))
|
||||
kprintln("\nNexus Sovereign Core v1.1.1 Starting...")
|
||||
kprintln("\nNexus Sovereign Core v1.1.2 Starting...")
|
||||
ion_pool_init()
|
||||
proc mm_init() {.importc, cdecl.}
|
||||
proc mm_enable_kernel_paging() {.importc, cdecl.}
|
||||
|
|
@ -607,11 +611,15 @@ proc kmain() {.exportc, cdecl.} =
|
|||
if not sched_tick_spectrum(active_fibers_arr.toOpenArray(0, 5)):
|
||||
# The Silence Doctrine: Wait for Interrupt
|
||||
let next_wake = sched_get_next_wakeup(active_fibers_arr.toOpenArray(0, 5))
|
||||
if next_wake != 0xFFFFFFFFFFFFFFFF'u64:
|
||||
proc sched_arm_timer(ns: uint64) {.importc, cdecl.}
|
||||
# kprint("[Sleep] "); kprint_hex(next_wake); kprintln("")
|
||||
sched_arm_timer(next_wake)
|
||||
let now = sched_get_now_ns()
|
||||
|
||||
if next_wake > now and next_wake != 0xFFFFFFFFFFFFFFFF'u64:
|
||||
proc rumpk_timer_set_ns(ns: uint64) {.importc, cdecl.}
|
||||
# kprint("Interval: "); kprint_hex(next_wake - now); kprintln("")
|
||||
rumpk_timer_set_ns(next_wake - now) # Pass interval
|
||||
else:
|
||||
# No timer needed (or overdue), just WFI for other interrupts (IO)
|
||||
discard
|
||||
|
||||
asm "csrsi sstatus, 2"
|
||||
asm "wfi"
|
||||
# kprintln("[Wake]")
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ proc sched_get_now_ns*(): uint64 {.importc: "rumpk_timer_now_ns", cdecl.}
|
|||
proc fiber_can_run_on_channels*(id: uint64, mask: uint64): bool {.importc, cdecl.}
|
||||
|
||||
proc is_runnable(f: ptr FiberObject, now: uint64): bool =
|
||||
if f == nil: return false
|
||||
if f == nil or f.state.sp == 0: return false # Can only run initialized fibers
|
||||
if now < f.sleep_until: return false
|
||||
if f.is_blocked:
|
||||
if fiber_can_run_on_channels(f.id, f.blocked_on_mask):
|
||||
|
|
|
|||
|
|
@ -265,6 +265,9 @@ export fn rss_trap_handler(frame: *TrapFrame) void {
|
|||
:
|
||||
: [mask] "r" (@as(usize, 1 << 5)),
|
||||
);
|
||||
|
||||
// Call Nim Handler
|
||||
rumpk_timer_handler();
|
||||
}
|
||||
k_check_deferred_yield();
|
||||
return;
|
||||
|
|
@ -303,6 +306,7 @@ export var stack_bytes: [64 * 1024]u8 align(16) = undefined;
|
|||
const hud = @import("hud.zig");
|
||||
extern fn kmain() void;
|
||||
extern fn NimMain() void;
|
||||
extern fn rumpk_timer_handler() void;
|
||||
|
||||
export fn zig_entry() void {
|
||||
uart.init_riscv();
|
||||
|
|
@ -360,30 +364,49 @@ export fn rumpk_halt() noreturn {
|
|||
}
|
||||
}
|
||||
|
||||
export fn rumpk_timer_now_ns() u64 {
|
||||
// RISC-V Time Constants
|
||||
const TIMEBASE: u64 = 10_000_000; // QEMU 'virt' machine (10 MHz)
|
||||
const SBI_TIME_EID: u64 = 0x54494D45;
|
||||
|
||||
fn rdtime() u64 {
|
||||
var ticks: u64 = 0;
|
||||
asm volatile ("rdtime %[ticks]"
|
||||
: [ticks] "=r" (ticks),
|
||||
);
|
||||
// QEMU Virt machine is 10MHz -> 1 tick = 100ns
|
||||
return ticks * 100;
|
||||
return ticks;
|
||||
}
|
||||
|
||||
export fn sched_arm_timer(deadline_ns: u64) void {
|
||||
// 1 tick = 100ns (10MHz)
|
||||
const deadline_ticks = deadline_ns / 100;
|
||||
|
||||
// Use SBI Time Extension (0x54494D45) to set timer
|
||||
// FID=0: sbi_set_timer(stime_value)
|
||||
fn sbi_set_timer(stime_value: u64) void {
|
||||
asm volatile (
|
||||
\\ ecall
|
||||
:
|
||||
: [arg0] "{a0}" (deadline_ticks),
|
||||
[eid] "{a7}" (0x54494D45),
|
||||
[fid] "{a6}" (0),
|
||||
: [arg0] "{a0}" (stime_value),
|
||||
[eid] "{a7}" (SBI_TIME_EID),
|
||||
[fid] "{a6}" (0), // FID 0 = set_timer
|
||||
: .{ .memory = true });
|
||||
}
|
||||
|
||||
// Enable STIE (Supervisor Timer Interrupt Enable) in sie (bit 5)
|
||||
export fn rumpk_timer_now_ns() u64 {
|
||||
return rdtime() * 100; // 10MHz = 100ns/tick
|
||||
}
|
||||
|
||||
export fn rumpk_timer_set_ns(interval_ns: u64) void {
|
||||
if (interval_ns == std.math.maxInt(u64)) {
|
||||
sbi_set_timer(std.math.maxInt(u64));
|
||||
// Disable STIE
|
||||
asm volatile ("csrc sie, %[mask]"
|
||||
:
|
||||
: [mask] "r" (@as(usize, 1 << 5)),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const ticks = interval_ns / 100; // 100ns per tick for 10MHz
|
||||
const now = rdtime();
|
||||
const next_time = now + ticks;
|
||||
sbi_set_timer(next_time);
|
||||
|
||||
// Enable STIE (Supervisor Timer Interrupt Enable)
|
||||
asm volatile ("csrs sie, %[mask]"
|
||||
:
|
||||
: [mask] "r" (@as(usize, 1 << 5)),
|
||||
|
|
|
|||
Loading…
Reference in New Issue