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
+17
View File
@@ -14,6 +14,8 @@ using namespace Kt;
namespace Hal {
namespace LocalApic {
static volatile uint32_t* g_apicBase = nullptr;
static constexpr uint32_t ICR_DELIVERY_STATUS = (1 << 12);
static constexpr uint32_t ICR_LEVEL_ASSERT = (1 << 14);
static inline uint64_t ReadMSR(uint32_t msr) {
uint32_t lo, hi;
@@ -113,6 +115,21 @@ namespace Hal {
WriteRegister(REG_EOI, 0);
}
void SendFixedIpi(uint32_t apicId, uint8_t vector) {
if (g_apicBase == nullptr) return;
while (ReadRegister(REG_ICR_LOW) & ICR_DELIVERY_STATUS) {
asm volatile("pause");
}
WriteRegister(REG_ICR_HIGH, apicId << 24);
WriteRegister(REG_ICR_LOW, (uint32_t)vector | ICR_LEVEL_ASSERT);
while (ReadRegister(REG_ICR_LOW) & ICR_DELIVERY_STATUS) {
asm volatile("pause");
}
}
uint32_t GetId() {
return (ReadRegister(REG_ID) >> 24) & 0xFF;
}
+1
View File
@@ -44,6 +44,7 @@ namespace Hal {
void Reinitialize();
void SendEOI();
void SendFixedIpi(uint32_t apicId, uint8_t vector);
uint32_t GetId();
uint32_t ReadRegister(uint32_t reg);
+1
View File
@@ -28,6 +28,7 @@ namespace Hal {
constexpr uint8_t IRQ_MOUSE = 12;
constexpr uint8_t IRQ_ATA1 = 14;
constexpr uint8_t IRQ_ATA2 = 15;
constexpr uint8_t IRQ_RESCHEDULE = 47;
// Register a handler for the given IRQ number (0-47)
void RegisterIrqHandler(uint8_t irq, IrqHandler handler);
+13
View File
@@ -31,6 +31,19 @@ namespace Hal {
asm volatile("mwait" :: "a"(0x00), "c"(0));
}
// Atomic idle entry for paths that have already disabled interrupts.
// Keeping STI immediately adjacent to HLT/MWAIT avoids the classic race
// where an IRQ is handled between enabling interrupts and entering idle,
// after which the CPU sleeps until the next timer deadline.
inline void HaltWithInterruptsDisabled() {
asm volatile("sti\n\thlt\n\tcli" ::: "memory");
}
inline void IdleWaitWithInterruptsDisabled(volatile uint64_t* monitorAddr) {
asm volatile("monitor" :: "a"(monitorAddr), "c"(0), "d"(0) : "memory");
asm volatile("sti\n\tmwait\n\tcli" :: "a"(0x00), "c"(0) : "memory");
}
inline void EnableSSE() {
uint64_t cr0;
asm volatile("mov %%cr0, %0" : "=r"(cr0));
+3 -9
View File
@@ -5,6 +5,7 @@
*/
#include "SmpBoot.hpp"
#include <ACPI/CpuIdle.hpp>
#include <Hal/Apic/Apic.hpp>
#include <Hal/Apic/Interrupts.hpp>
#include <Hal/IDT.hpp>
@@ -212,16 +213,9 @@ namespace Smp {
// --- Enable interrupts and enter idle loop ---
asm volatile("sti");
// Use MWAIT for deeper C-states if available, otherwise HLT.
static volatile uint64_t s_idleMonitor = 0;
if (cpu->hasMwait) {
for (;;) {
Hal::IdleWait(&s_idleMonitor);
}
} else {
for (;;) {
asm volatile("hlt");
}
for (;;) {
Hal::CpuIdle::Wait(10, cpu->hasMwait, &s_idleMonitor);
}
}