feat: further kernel power and power optimizations

This commit is contained in:
2026-04-21 20:51:12 +02:00
parent d1fffecff6
commit 0dfb3e8dbb
31 changed files with 895 additions and 52 deletions
+70
View File
@@ -0,0 +1,70 @@
/*
* InputEvents.cpp
* Shared input activity event source
* Copyright (c) 2026 Daniel Hammer
*/
#include "InputEvents.hpp"
#include <atomic>
#include <Sched/Scheduler.hpp>
#include <Timekeeping/ApicTimer.hpp>
namespace Drivers::InputEvents {
static std::atomic<uint64_t> g_serial{1};
static uint8_t g_waitObject;
struct WaitContext {
uint64_t observedSerial;
};
static bool SerialStillObserved(void* rawContext) {
auto* context = static_cast<WaitContext*>(rawContext);
return context != nullptr &&
g_serial.load(std::memory_order_acquire) == context->observedSerial;
}
uint64_t GetSerial() {
return g_serial.load(std::memory_order_acquire);
}
void NotifyActivity() {
Timekeeping::NoteInteractiveActivity();
g_serial.fetch_add(1, std::memory_order_release);
Sched::WakeObjectWaiters(&g_waitObject);
}
uint64_t WaitForChange(uint64_t observedSerial, uint64_t timeoutMs) {
uint64_t current = GetSerial();
if (current != observedSerial || timeoutMs == 0) {
return current;
}
WaitContext context{observedSerial};
uint64_t start = Timekeeping::GetMilliseconds();
for (;;) {
current = GetSerial();
if (current != observedSerial) {
return current;
}
uint64_t waitMs = 0;
if (timeoutMs == UINT64_MAX) {
waitMs = 0;
} else {
uint64_t elapsed = Timekeeping::GetMilliseconds() - start;
if (elapsed >= timeoutMs) {
return current;
}
waitMs = timeoutMs - elapsed;
if (waitMs == 0) {
waitMs = 1;
}
}
Sched::BlockOnObjectIf(&g_waitObject, waitMs, SerialStillObserved, &context);
}
}
}
+22
View File
@@ -0,0 +1,22 @@
/*
* InputEvents.hpp
* Shared input activity event source
* Copyright (c) 2026 Daniel Hammer
*/
#pragma once
#include <cstdint>
namespace Drivers::InputEvents {
// Monotonic serial incremented after mouse or keyboard state changes.
uint64_t GetSerial();
// Notify latency-sensitive input activity and wake input waiters.
void NotifyActivity();
// Wait until the serial differs from observedSerial or timeoutMs elapses.
// timeoutMs == 0 is a poll; timeoutMs == UINT64_MAX waits indefinitely.
uint64_t WaitForChange(uint64_t observedSerial, uint64_t timeoutMs);
}
+5
View File
@@ -124,6 +124,10 @@ namespace Drivers::Net::E1000E {
return *(volatile uint32_t*)(g_mmioBase + reg);
}
static void ConfigureInterruptModeration() {
WriteReg(REG_ITR, ITR_INTERVAL_512US);
}
// -------------------------------------------------------------------------
// SW/FW semaphore (prevents conflicts with Intel Management Engine)
// -------------------------------------------------------------------------
@@ -586,6 +590,7 @@ namespace Drivers::Net::E1000E {
SetupRx();
SetupTx();
ConfigureInterruptModeration();
if (SetupMsi(bus, device, function)) {
WriteReg(REG_IMS, ICR_RXT0 | ICR_TXDW | ICR_TXQE | ICR_LSC | ICR_RXDMT0);
+2
View File
@@ -17,6 +17,7 @@ namespace Drivers::Net::E1000E {
constexpr uint32_t REG_CTRL_EXT = 0x0018; // Extended Device Control
constexpr uint32_t REG_MDIC = 0x0020; // MDI Control (PHY access)
constexpr uint32_t REG_ICR = 0x00C0; // Interrupt Cause Read
constexpr uint32_t REG_ITR = 0x00C4; // Interrupt Throttling
constexpr uint32_t REG_IMS = 0x00D0; // Interrupt Mask Set
constexpr uint32_t REG_IMC = 0x00D8; // Interrupt Mask Clear
constexpr uint32_t REG_RCTL = 0x0100; // Receive Control
@@ -93,6 +94,7 @@ namespace Drivers::Net::E1000E {
constexpr uint32_t ICR_RXDMT0 = (1 << 4); // RX Descriptor Minimum Threshold
constexpr uint32_t ICR_RXO = (1 << 6); // Receiver Overrun
constexpr uint32_t ICR_RXT0 = (1 << 7); // Receiver Timer Interrupt
constexpr uint32_t ITR_INTERVAL_512US = 2048; // 2048 * 256 ns
// TX descriptor command bits
constexpr uint8_t TXCMD_EOP = (1 << 0); // End Of Packet
+19 -15
View File
@@ -13,6 +13,7 @@
#include <Terminal/Terminal.hpp>
#include <Hal/Apic/Interrupts.hpp>
#include <Hal/Apic/IoApic.hpp>
#include <Drivers/Input/InputEvents.hpp>
namespace Drivers::PS2::Keyboard {
@@ -86,14 +87,15 @@ namespace Drivers::PS2::Keyboard {
return shift ^ caps;
}
static void BufferPush(const KeyEvent& event) {
static bool BufferPush(const KeyEvent& event) {
uint32_t nextHead = (g_BufferHead + 1) & (KeyBufferSize - 1);
if (nextHead == g_BufferTail) {
// Buffer full, drop the event
return;
return false;
}
g_KeyBuffer[g_BufferHead] = event;
g_BufferHead = nextHead;
return true;
}
static bool BufferPop(KeyEvent& event) {
@@ -105,6 +107,16 @@ namespace Drivers::PS2::Keyboard {
return true;
}
static void PushAndNotify(const KeyEvent& event) {
g_BufferLock.Acquire();
bool pushed = BufferPush(event);
g_BufferLock.Release();
if (pushed) {
Drivers::InputEvents::NotifyActivity();
}
}
void Initialize() {
Kt::KernelLogStream(Kt::INFO, "PS2/KB") << "Initializing keyboard driver";
@@ -169,9 +181,7 @@ namespace Drivers::PS2::Keyboard {
.Alt = g_Modifiers.LeftAlt || g_Modifiers.RightAlt,
.CapsLock = g_Modifiers.CapsLock
};
g_BufferLock.Acquire();
BufferPush(event);
g_BufferLock.Release();
PushAndNotify(event);
return;
}
@@ -229,9 +239,7 @@ namespace Drivers::PS2::Keyboard {
.Alt = g_Modifiers.LeftAlt || g_Modifiers.RightAlt,
.CapsLock = g_Modifiers.CapsLock
};
g_BufferLock.Acquire();
BufferPush(event);
g_BufferLock.Release();
PushAndNotify(event);
return;
}
if (isModifier) return;
@@ -256,9 +264,7 @@ namespace Drivers::PS2::Keyboard {
.CapsLock = g_Modifiers.CapsLock
};
g_BufferLock.Acquire();
BufferPush(event);
g_BufferLock.Release();
PushAndNotify(event);
}
bool IsKeyAvailable() {
@@ -292,9 +298,7 @@ namespace Drivers::PS2::Keyboard {
}
void InjectKeyEvent(const KeyEvent& event) {
g_BufferLock.Acquire();
BufferPush(event);
g_BufferLock.Release();
PushAndNotify(event);
}
};
};
+4 -1
View File
@@ -13,6 +13,7 @@
#include <Terminal/Terminal.hpp>
#include <Hal/Apic/Interrupts.hpp>
#include <Hal/Apic/IoApic.hpp>
#include <Drivers/Input/InputEvents.hpp>
namespace Drivers::PS2::Mouse {
@@ -170,6 +171,7 @@ namespace Drivers::PS2::Mouse {
if (g_State.Y > g_MaxY) g_State.Y = g_MaxY;
g_StateLock.Release();
Drivers::InputEvents::NotifyActivity();
}
MouseState GetMouseState() {
@@ -236,6 +238,7 @@ namespace Drivers::PS2::Mouse {
if (g_State.Y > g_MaxY) g_State.Y = g_MaxY;
g_StateLock.Release();
Drivers::InputEvents::NotifyActivity();
}
};
};
+13
View File
@@ -377,4 +377,17 @@ namespace Drivers::USB::HidKeyboard {
}
}
uint64_t GetNextTickDeadline() {
if (g_RepeatKey == 0) {
return 0;
}
uint64_t firstRepeat = g_RepeatStartMs + TYPEMATIC_DELAY_MS;
if (g_LastRepeatMs == 0 || g_LastRepeatMs < firstRepeat) {
return firstRepeat;
}
return g_LastRepeatMs + TYPEMATIC_PERIOD_MS;
}
}
+4
View File
@@ -18,4 +18,8 @@ namespace Drivers::USB::HidKeyboard {
// Timer tick for typematic repeat (call from periodic timer, e.g. 1ms)
void Tick();
// Earliest millisecond deadline when typematic repeat needs service again.
// Returns 0 when no repeat is pending.
uint64_t GetNextTickDeadline();
};
+2 -2
View File
@@ -959,7 +959,7 @@ namespace Drivers::USB::Xhci {
// Enable interrupter 0
WriteRt(IR0_IMAN, IMAN_IE);
WriteRt(IR0_IMOD, 0);
WriteRt(IR0_IMOD, IMOD_INTERVAL_100US);
// Start controller
WriteOp(OP_USBCMD, USBCMD_RS | USBCMD_INTE | USBCMD_HSEE);
@@ -1269,7 +1269,7 @@ namespace Drivers::USB::Xhci {
// Step 13: Enable interrupter 0
// -----------------------------------------------------------------
WriteRt(IR0_IMAN, IMAN_IE);
WriteRt(IR0_IMOD, 0); // No moderation
WriteRt(IR0_IMOD, IMOD_INTERVAL_100US);
// -----------------------------------------------------------------
// Step 14: Start controller
+1
View File
@@ -110,6 +110,7 @@ namespace Drivers::USB::Xhci {
// IMAN bits
constexpr uint32_t IMAN_IP = (1 << 0); // Interrupt Pending
constexpr uint32_t IMAN_IE = (1 << 1); // Interrupt Enable
constexpr uint32_t IMOD_INTERVAL_100US = 400; // 100 us in 250 ns units
// ---------------------------------------------------------------------------
// TRB (Transfer Request Block) - 16 bytes