/* * main.cpp * power - CPU power/thermal status tool. * * Reads the kernel's power management snapshot (SYS_POWERINFO): package * temperature, HWP frequency-scaling state, the thermal governor's * current frequency ceiling, and the measured average active frequency. * Useful for verifying that HWP and the thermal governor are doing their * job on real hardware. * * Usage: * power print the current snapshot * power watch sample once per second until 60 s elapse * power watch sample once per second for seconds * Copyright (c) 2026 Daniel Hammer */ #include using namespace montauk; static void put_u64(uint64_t n) { char buf[24]; int i = 0; if (n == 0) { putchar('0'); return; } while (n) { buf[i++] = (char)('0' + (n % 10)); n /= 10; } while (i) putchar(buf[--i]); } static void put_hex8(uint8_t v) { static const char* digits = "0123456789ABCDEF"; print("0x"); putchar(digits[(v >> 4) & 0xF]); putchar(digits[v & 0xF]); } static bool read_info(montauk::abi::PowerInfo& info) { return syscall1(montauk::abi::SYS_POWERINFO, (uint64_t)&info) == 0; } static void print_snapshot(const montauk::abi::PowerInfo& info) { print("CPU power/thermal status:\n"); print(" HWP: "); if (info.hwpActive) { print("active (EPP "); put_hex8(info.epp); print(", perf range "); put_u64(info.lowestPerf); print("-"); put_u64(info.highestPerf); print(")\n"); } else { print("not active\n"); } print(" Frequency: base "); put_u64(info.baseMHz); print(" MHz, turbo "); put_u64(info.maxMHz); print(" MHz, avg active "); put_u64(info.effMHz); print(" MHz\n"); print(" Package: "); if (info.tempC != 0) { put_u64(info.tempC); print(" C (hardware throttles at "); put_u64(info.tjMaxC); print(" C)\n"); } else { print("temperature unavailable\n"); } print(" Governor: "); if (!info.hwpActive) { print("inactive\n"); } else if (info.throttling) { print("THROTTLING - ceiling "); put_u64(info.curMaxPerf); print(" of "); put_u64(info.highestPerf); print("\n"); } else { print("not throttling (ceiling "); put_u64(info.curMaxPerf); print(")\n"); } print(" AP idle: MWAIT hint "); put_hex8((uint8_t)info.apIdleHint); if (info.apIdleHint == 0) { print(" (C1 only)"); } print("\n"); } static void print_watch_line(const montauk::abi::PowerInfo& info, uint64_t t) { put_u64(t); print("s "); put_u64(info.tempC); print(" C avg "); put_u64(info.effMHz); print(" MHz ceiling "); put_u64(info.curMaxPerf); print("/"); put_u64(info.highestPerf); print(info.throttling ? " THROTTLING\n" : "\n"); } static uint64_t parse_u64(const char* s, uint64_t fallback) { uint64_t v = 0; bool any = false; while (*s == ' ') s++; while (*s >= '0' && *s <= '9') { v = v * 10 + (uint64_t)(*s - '0'); s++; any = true; } return any ? v : fallback; } extern "C" void _start() { char args[64]; int alen = montauk::getargs(args, sizeof(args)); const char* rest = (alen > 0) ? args : ""; montauk::abi::PowerInfo info{}; if (!read_info(info)) { print("power: no CPU power management available\n"); print("(non-Intel CPU or running under emulation)\n"); montauk::exit(1); } bool watch = rest[0] == 'w'; if (!watch) { print_snapshot(info); montauk::exit(0); } const char* p = rest; while (*p && *p != ' ') p++; uint64_t seconds = parse_u64(p, 60); if (seconds == 0) seconds = 60; print("time temp freq ceiling (1 sample/s, "); put_u64(seconds); print(" s)\n"); for (uint64_t t = 0; t < seconds; t++) { if (!read_info(info)) break; print_watch_line(info, t); montauk::sleep_ms(1000); } montauk::exit(0); }