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
8729e9b9a4
commit
bc5f488155
|
|
@ -62,12 +62,8 @@ proc main() =
|
||||||
if loop_count mod 1 == 0:
|
if loop_count mod 1 == 0:
|
||||||
print(cstring("[INIT] Heartbeat\n"))
|
print(cstring("[INIT] Heartbeat\n"))
|
||||||
|
|
||||||
# Busy Wait Sleep (10ms) to bypass broken WFI/Timer
|
# Sleep 10ms using Timer Driver (System Call)
|
||||||
# TODO: Restore nanosleep once HAL Timer Driver is implemented
|
discard syscall(0x65, 10000000'u64)
|
||||||
proc sys_now(): uint32 {.importc, cdecl.}
|
|
||||||
let start_sleep = sys_now()
|
|
||||||
while sys_now() - start_sleep < 10:
|
|
||||||
discard syscall(0x100, 0, 0, 0) # YIELD
|
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@ const
|
||||||
MAX_FIBER_STACK* = 128 * 1024
|
MAX_FIBER_STACK* = 128 * 1024
|
||||||
SYSTABLE_BASE* = 0x83000000'u64
|
SYSTABLE_BASE* = 0x83000000'u64
|
||||||
|
|
||||||
|
# Export Nim Timer Handler for HAL (Zig calls this)
|
||||||
|
proc rumpk_timer_handler() {.exportc, cdecl, used.} =
|
||||||
|
discard
|
||||||
|
|
||||||
# --- EXTERNAL SYMBOLS ---
|
# --- EXTERNAL SYMBOLS ---
|
||||||
proc ion_get_phys(id: uint16): uint64 {.importc, cdecl.}
|
proc ion_get_phys(id: uint16): uint64 {.importc, cdecl.}
|
||||||
proc ion_alloc_raw*(out_id: ptr 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)
|
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")
|
kprintln("[ION] Child fiber spawned successfully")
|
||||||
else: discard
|
else: discard
|
||||||
fiber_sleep(100)
|
fiber_sleep(10_000_000) # 10ms
|
||||||
|
|
||||||
proc fiber_yield*() {.exportc, cdecl.} =
|
proc fiber_yield*() {.exportc, cdecl.} =
|
||||||
proc rumpk_yield_guard() {.importc, cdecl.}
|
proc rumpk_yield_guard() {.importc, cdecl.}
|
||||||
|
|
@ -303,7 +307,7 @@ proc fiber_netswitch_entry() {.cdecl.} =
|
||||||
if chan_netswitch_rx.recv(pkt):
|
if chan_netswitch_rx.recv(pkt):
|
||||||
ion_free_raw(pkt.id)
|
ion_free_raw(pkt.id)
|
||||||
else:
|
else:
|
||||||
fiber_sleep(100)
|
fiber_sleep(10_000_000) # 10ms
|
||||||
fiber_yield()
|
fiber_yield()
|
||||||
|
|
||||||
proc ion_ingress*(id: uint16, len: uint16) {.exportc, cdecl.} =
|
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
|
var next_mmio_addr {.importc: "virtio_pci_next_mmio_addr", nodecl.}: uint32
|
||||||
kprint("\n[Kernel] next_mmio_addr check: ")
|
kprint("\n[Kernel] next_mmio_addr check: ")
|
||||||
kprint_hex(uint64(next_mmio_addr))
|
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()
|
ion_pool_init()
|
||||||
proc mm_init() {.importc, cdecl.}
|
proc mm_init() {.importc, cdecl.}
|
||||||
proc mm_enable_kernel_paging() {.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)):
|
if not sched_tick_spectrum(active_fibers_arr.toOpenArray(0, 5)):
|
||||||
# The Silence Doctrine: Wait for Interrupt
|
# The Silence Doctrine: Wait for Interrupt
|
||||||
let next_wake = sched_get_next_wakeup(active_fibers_arr.toOpenArray(0, 5))
|
let next_wake = sched_get_next_wakeup(active_fibers_arr.toOpenArray(0, 5))
|
||||||
if next_wake != 0xFFFFFFFFFFFFFFFF'u64:
|
let now = sched_get_now_ns()
|
||||||
proc sched_arm_timer(ns: uint64) {.importc, cdecl.}
|
|
||||||
# kprint("[Sleep] "); kprint_hex(next_wake); kprintln("")
|
if next_wake > now and next_wake != 0xFFFFFFFFFFFFFFFF'u64:
|
||||||
sched_arm_timer(next_wake)
|
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 "csrsi sstatus, 2"
|
||||||
asm "wfi"
|
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 fiber_can_run_on_channels*(id: uint64, mask: uint64): bool {.importc, cdecl.}
|
||||||
|
|
||||||
proc is_runnable(f: ptr FiberObject, now: uint64): bool =
|
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 now < f.sleep_until: return false
|
||||||
if f.is_blocked:
|
if f.is_blocked:
|
||||||
if fiber_can_run_on_channels(f.id, f.blocked_on_mask):
|
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)),
|
: [mask] "r" (@as(usize, 1 << 5)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Call Nim Handler
|
||||||
|
rumpk_timer_handler();
|
||||||
}
|
}
|
||||||
k_check_deferred_yield();
|
k_check_deferred_yield();
|
||||||
return;
|
return;
|
||||||
|
|
@ -303,6 +306,7 @@ export var stack_bytes: [64 * 1024]u8 align(16) = undefined;
|
||||||
const hud = @import("hud.zig");
|
const hud = @import("hud.zig");
|
||||||
extern fn kmain() void;
|
extern fn kmain() void;
|
||||||
extern fn NimMain() void;
|
extern fn NimMain() void;
|
||||||
|
extern fn rumpk_timer_handler() void;
|
||||||
|
|
||||||
export fn zig_entry() void {
|
export fn zig_entry() void {
|
||||||
uart.init_riscv();
|
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;
|
var ticks: u64 = 0;
|
||||||
asm volatile ("rdtime %[ticks]"
|
asm volatile ("rdtime %[ticks]"
|
||||||
: [ticks] "=r" (ticks),
|
: [ticks] "=r" (ticks),
|
||||||
);
|
);
|
||||||
// QEMU Virt machine is 10MHz -> 1 tick = 100ns
|
return ticks;
|
||||||
return ticks * 100;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn sched_arm_timer(deadline_ns: u64) void {
|
fn sbi_set_timer(stime_value: 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)
|
|
||||||
asm volatile (
|
asm volatile (
|
||||||
\\ ecall
|
\\ ecall
|
||||||
:
|
:
|
||||||
: [arg0] "{a0}" (deadline_ticks),
|
: [arg0] "{a0}" (stime_value),
|
||||||
[eid] "{a7}" (0x54494D45),
|
[eid] "{a7}" (SBI_TIME_EID),
|
||||||
[fid] "{a6}" (0),
|
[fid] "{a6}" (0), // FID 0 = set_timer
|
||||||
: .{ .memory = true });
|
: .{ .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]"
|
asm volatile ("csrs sie, %[mask]"
|
||||||
:
|
:
|
||||||
: [mask] "r" (@as(usize, 1 << 5)),
|
: [mask] "r" (@as(usize, 1 << 5)),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue