feat: make kernel architecture-agnostic; primitive work on arm port

This commit is contained in:
daniel committed 2026-10-24 21:25:18 +02:00
1 parent dab7d5427b
commit 1bae77ec84
164 files changed
+3664 -1641

No files matched your search

+10 -15
View File
@@ -5,12 +5,12 @@
*/
#include "IntelHda.hpp"
#include <Arch/Cpu.hpp>
#include "Mixer.hpp"
#include <Memory/PageFrameAllocator.hpp>
#include <Memory/HHDM.hpp>
#include <Memory/Paging.hpp>
#include <Hal/Apic/Interrupts.hpp>
#include <Hal/Apic/IoApic.hpp>
#include <Arch/Interrupts.hpp>
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
#include <CppLib/Spinlock.hpp>
@@ -173,7 +173,7 @@ namespace Drivers::Audio::IntelHda {
static void MicroDelay(int us) {
// Simple busy-wait; us is approximate
for (volatile int i = 0; i < us * 100; i++) {
asm volatile("pause");
Arch::Pause();
}
}
@@ -851,13 +851,9 @@ namespace Drivers::Audio::IntelHda {
uint16_t msgCtrl = Pci::LegacyRead16(bus, dev, func, cap + 2);
bool is64bit = (msgCtrl & (1 << 7)) != 0;
Pci::LegacyWrite32(bus, dev, func, cap + 4, MSI_ADDR_BASE);
if (is64bit) {
Pci::LegacyWrite32(bus, dev, func, cap + 8, 0);
Pci::LegacyWrite16(bus, dev, func, cap + 12, MSI_VECTOR);
} else {
Pci::LegacyWrite16(bus, dev, func, cap + 8, MSI_VECTOR);
// Message Address/Data: IRQ slot MSI_IRQ on the boot CPU
if (!Pci::WriteMsiMessage(bus, dev, func, cap, MSI_IRQ)) {
return false;
}
msgCtrl &= ~(0x70);
@@ -868,10 +864,9 @@ namespace Drivers::Audio::IntelHda {
pciCmd |= Pci::PCI_CMD_INTX_DISABLE;
Pci::LegacyWrite16(bus, dev, func, (uint8_t)Pci::PCI_REG_COMMAND, pciCmd);
Hal::RegisterIrqHandler(MSI_IRQ, HandleInterrupt);
Arch::RegisterIrqHandler(MSI_IRQ, HandleInterrupt);
KernelLogStream(OK, "HDA") << "MSI enabled: vector " << base::dec << (uint64_t)MSI_VECTOR
<< " (IRQ slot " << (uint64_t)MSI_IRQ << ")" << (is64bit ? " [64-bit]" : " [32-bit]");
KernelLogStream(OK, "HDA") << "MSI enabled: IRQ slot " << base::dec << (uint64_t)MSI_IRQ << (is64bit ? " [64-bit]" : " [32-bit]");
return true;
}
@@ -1023,8 +1018,8 @@ namespace Drivers::Audio::IntelHda {
(uint8_t)Pci::PCI_REG_COMMAND);
Pci::LegacyWrite16(g_bus, g_dev, g_func,
(uint8_t)Pci::PCI_REG_COMMAND, command & ~Pci::PCI_CMD_INTX_DISABLE);
Hal::RegisterIrqHandler(irqLine, HandleInterrupt);
Hal::IoApic::UnmaskIrq(Hal::IoApic::GetGsiForIrq(irqLine));
Arch::RegisterIrqHandler(irqLine, HandleInterrupt);
Arch::EnableLegacyIrq(irqLine);
} else {
KernelLogStream(WARNING, "HDA") << "No interrupt available, polling only";
}
+1 -3
View File
@@ -235,9 +235,7 @@ namespace Drivers::Audio::IntelHda {
// MSI configuration
// =========================================================================
constexpr uint8_t MSI_IRQ = 27; // IRQ slot 27 = vector 59
constexpr uint32_t MSI_VECTOR = 59;
constexpr uint32_t MSI_ADDR_BASE = 0xFEE00000;
constexpr uint8_t MSI_IRQ = 27; // IRQ slot 27
// =========================================================================
// Audio stream state (one active output stream)
+1 -1
View File
@@ -10,7 +10,7 @@
#include <ACPI/AML/AmlInterpreter.hpp>
#include <Boot/Boot.hpp>
#include <Memory/HHDM.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Timekeeping/Timer.hpp>
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
+12 -11
View File
@@ -7,6 +7,7 @@
*/
#include "IntelGPU.hpp"
#include <Arch/Cpu.hpp>
#include <Pci/Pci.hpp>
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
@@ -17,7 +18,7 @@
#include <Io/IoPort.hpp>
#include <Graphics/Framebuffer.hpp>
#include <Libraries/Memory.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Timekeeping/Timer.hpp>
using namespace Kt;
@@ -500,7 +501,7 @@ namespace Drivers::Graphics::IntelGPU {
int busyWait = 100000;
while (((g_auxLastStatus = ReadReg(g_auxControlReg)) & DP_AUX_SEND_BUSY)
&& --busyWait)
asm volatile("pause");
Arch::Pause();
if (!busyWait) return -1;
for (int i = 0; i < sendBytes; i += 4) {
@@ -523,7 +524,7 @@ namespace Drivers::Graphics::IntelGPU {
status = ReadReg(g_auxControlReg);
g_auxLastStatus = status;
if (!(status & DP_AUX_SEND_BUSY)) break;
asm volatile("pause");
Arch::Pause();
} while (--completeWait);
if (!completeWait) return -1;
@@ -568,7 +569,7 @@ namespace Drivers::Graphics::IntelGPU {
return true;
if (nativeReply != 2 && i2cReply != 8 && result >= 0) return false;
for (int delay = 0; delay < 40000; delay++)
asm volatile("pause");
Arch::Pause();
}
return false;
}
@@ -1012,7 +1013,7 @@ namespace Drivers::Graphics::IntelGPU {
}
static void ShortSpin() {
for (int i = 0; i < 20000; i++) asm volatile("pause");
for (int i = 0; i < 20000; i++) Arch::Pause();
}
// ---- Panel PWM ----------------------------------------------------------
@@ -1210,7 +1211,7 @@ namespace Drivers::Graphics::IntelGPU {
if (status & GMBUS_SATOER) return false;
if (status & bit) return true;
if (Timekeeping::GetMilliseconds() - start > 50) return false;
asm volatile("pause");
Arch::Pause();
}
}
@@ -1218,7 +1219,7 @@ namespace Drivers::Graphics::IntelGPU {
uint64_t start = Timekeeping::GetMilliseconds();
while (ReadReg(GMBUS2) & GMBUS_ACTIVE) {
if (Timekeeping::GetMilliseconds() - start > 50) return false;
asm volatile("pause");
Arch::Pause();
}
return true;
}
@@ -1706,7 +1707,7 @@ namespace Drivers::Graphics::IntelGPU {
previous = current;
if ((i & 0x3FF) == 0 &&
Timekeeping::GetMilliseconds() - started >= 100) return false;
asm volatile("pause");
Arch::Pause();
}
return false;
}
@@ -2098,7 +2099,7 @@ namespace Drivers::Graphics::IntelGPU {
for (int i = 0; i < 200000; i++) {
bool state = (ReadReg(g_transConfReg) & PIPECONF_STATE) != 0;
if (state == enabled) return true;
asm volatile("pause");
Arch::Pause();
}
return false;
}
@@ -2366,7 +2367,7 @@ namespace Drivers::Graphics::IntelGPU {
// Scanout memory is exposed through WC mappings. Drain userspace's
// completed frame before programming the display-plane surface.
asm volatile("sfence" ::: "memory");
Arch::StoreFence();
uint64_t gttOff = (index == 0) ? g_fbGttOffsetA : g_buf1GttOffset;
WriteReg(DSPASURF, (uint32_t)gttOff);
(void)ReadReg(DSPASURF);
@@ -2511,7 +2512,7 @@ namespace Drivers::Graphics::IntelGPU {
for (int i = 0; i < 100000; i++) {
if (ReadReg(PIPEACONF) & PIPECONF_STATE)
break;
asm volatile("pause");
Arch::Pause();
}
if (!(ReadReg(PIPEACONF) & PIPECONF_STATE)) {
+1 -1
View File
@@ -7,7 +7,7 @@
#include "InputEvents.hpp"
#include <atomic>
#include <Sched/Scheduler.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Timekeeping/Timer.hpp>
namespace Drivers::InputEvents {
+5 -6
View File
@@ -12,8 +12,7 @@
#include <Memory/Paging.hpp>
#include <Memory/PageFrameAllocator.hpp>
#include <Libraries/Memory.hpp>
#include <Hal/Apic/Interrupts.hpp>
#include <Hal/Apic/IoApic.hpp>
#include <Arch/Interrupts.hpp>
#include <CppLib/Spinlock.hpp>
#include <atomic>
@@ -340,8 +339,8 @@ namespace Drivers::Net::E1000 {
SetupRx();
SetupTx();
Hal::RegisterIrqHandler(g_irqLine, HandleInterrupt);
Hal::IoApic::UnmaskIrq(Hal::IoApic::GetGsiForIrq(g_irqLine));
Arch::RegisterIrqHandler(g_irqLine, HandleInterrupt);
Arch::EnableLegacyIrq(g_irqLine);
WriteReg(REG_IMS, RX_INTERRUPT_MASK | ICR_LSC);
g_initialized = true;
@@ -450,8 +449,8 @@ namespace Drivers::Net::E1000 {
SetupTx();
// Register interrupt handler
Hal::RegisterIrqHandler(g_irqLine, HandleInterrupt);
Hal::IoApic::UnmaskIrq(Hal::IoApic::GetGsiForIrq(g_irqLine));
Arch::RegisterIrqHandler(g_irqLine, HandleInterrupt);
Arch::EnableLegacyIrq(g_irqLine);
// Enable RX and link-change only. TX completion is polled by descriptor.
WriteReg(REG_IMS, RX_INTERRUPT_MASK | ICR_LSC);
+11 -22
View File
@@ -5,6 +5,7 @@
*/
#include "E1000E.hpp"
#include <Arch/Cpu.hpp>
#include <Pci/Pci.hpp>
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
@@ -12,8 +13,7 @@
#include <Memory/Paging.hpp>
#include <Memory/PageFrameAllocator.hpp>
#include <Libraries/Memory.hpp>
#include <Hal/Apic/Interrupts.hpp>
#include <Hal/Apic/IoApic.hpp>
#include <Arch/Interrupts.hpp>
#include <CppLib/Spinlock.hpp>
#include <atomic>
@@ -80,9 +80,7 @@ namespace Drivers::Net::E1000E {
static constexpr uint32_t g_deviceTableSize = sizeof(g_deviceTable) / sizeof(g_deviceTable[0]);
// MSI configuration
static constexpr uint8_t MSI_IRQ = 24; // IRQ slot 24 = vector 56 (first MSI slot)
static constexpr uint32_t MSI_VECTOR = 56; // IRQ_VECTOR_BASE + MSI_IRQ
static constexpr uint32_t MSI_ADDR_BASE = 0xFEE00000; // Local APIC message address range
static constexpr uint8_t MSI_IRQ = 24; // first MSI IRQ slot
// Driver state
static bool g_initialized = false;
@@ -434,17 +432,9 @@ namespace Drivers::Net::E1000E {
uint16_t msgCtrl = Pci::LegacyRead16(bus, dev, func, cap + 2);
bool is64bit = (msgCtrl & (1 << 7)) != 0;
// Write Message Address (cap+4): BSP APIC ID 0, physical destination, fixed delivery
Pci::LegacyWrite32(bus, dev, func, cap + 4, MSI_ADDR_BASE);
// Write Message Data (vector number, edge-triggered, fixed delivery)
if (is64bit) {
// 64-bit: Upper Address at cap+8, Data at cap+12
Pci::LegacyWrite32(bus, dev, func, cap + 8, 0);
Pci::LegacyWrite16(bus, dev, func, cap + 12, MSI_VECTOR);
} else {
// 32-bit: Data at cap+8
Pci::LegacyWrite16(bus, dev, func, cap + 8, MSI_VECTOR);
// Message Address/Data: IRQ slot MSI_IRQ on the boot CPU
if (!Pci::WriteMsiMessage(bus, dev, func, cap, MSI_IRQ)) {
return false;
}
// Enable MSI: set bit 0 (MSI Enable), clear bits 6:4 (single message)
@@ -458,10 +448,9 @@ namespace Drivers::Net::E1000E {
Pci::LegacyWrite16(bus, dev, func, (uint8_t)Pci::PCI_REG_COMMAND, pciCmd);
// Register the interrupt handler for MSI vector
Hal::RegisterIrqHandler(MSI_IRQ, HandleInterrupt);
Arch::RegisterIrqHandler(MSI_IRQ, HandleInterrupt);
KernelLogStream(OK, "E1000E") << "MSI enabled: vector " << base::dec << (uint64_t)MSI_VECTOR
<< " (IRQ slot " << (uint64_t)MSI_IRQ << ")" << (is64bit ? " [64-bit]" : " [32-bit]");
KernelLogStream(OK, "E1000E") << "MSI enabled: IRQ slot " << base::dec << (uint64_t)MSI_IRQ << (is64bit ? " [64-bit]" : " [32-bit]");
return true;
}
@@ -545,7 +534,7 @@ namespace Drivers::Net::E1000E {
WriteReg(REG_CTRL, ctrl | CTRL_RST);
for (int i = 0; i < 100000; i++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
for (int i = 0; i < 10000; i++) {
if (!(ReadReg(REG_CTRL) & CTRL_RST)) break;
@@ -592,8 +581,8 @@ namespace Drivers::Net::E1000E {
(uint8_t)Pci::PCI_REG_COMMAND);
Pci::LegacyWrite16(bus, device, function,
(uint8_t)Pci::PCI_REG_COMMAND, command & ~Pci::PCI_CMD_INTX_DISABLE);
Hal::RegisterIrqHandler(g_irqLine, HandleInterrupt);
Hal::IoApic::UnmaskIrq(Hal::IoApic::GetGsiForIrq(g_irqLine));
Arch::RegisterIrqHandler(g_irqLine, HandleInterrupt);
Arch::EnableLegacyIrq(g_irqLine);
WriteReg(REG_IMS, RX_INTERRUPT_MASK | ICR_LSC);
} else {
KernelLogStream(WARNING, "E1000E") << "No MSI or legacy IRQ available, using polling mode";
+1 -1
View File
@@ -26,7 +26,7 @@
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
#include <CppLib/Spinlock.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Timekeeping/Timer.hpp>
using namespace Kt;
+2 -1
View File
@@ -12,6 +12,7 @@
*/
#include "Iwx.hpp"
#include <Arch/Cpu.hpp>
#include <Fs/Vfs.hpp>
#include <Memory/Heap.hpp>
#include <Libraries/Memory.hpp>
@@ -342,7 +343,7 @@ namespace Drivers::Net::Wifi {
}
Fs::Vfs::ReadBackendFile(file, buf, 0, size);
Fs::Vfs::CloseBackendFile(file);
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
*outSize = size;
return buf;
+1 -1
View File
@@ -11,7 +11,7 @@
#include <Libraries/Memory.hpp>
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Timekeeping/Timer.hpp>
using namespace Kt;
+29 -30
View File
@@ -17,6 +17,7 @@
*/
#include "Iwx.hpp"
#include <Arch/Cpu.hpp>
#include "Ieee80211.hpp"
#include <Pci/Pci.hpp>
#include <Memory/HHDM.hpp>
@@ -26,8 +27,8 @@
#include <Libraries/Memory.hpp>
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
#include <Hal/Apic/Interrupts.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Arch/Interrupts.hpp>
#include <Timekeeping/Timer.hpp>
using namespace Kt;
@@ -38,8 +39,6 @@ namespace Drivers::Net::Wifi {
// MSI-X/MSI interrupt slot. Slots in use elsewhere: 24 (E1000E),
// 27 (Intel HDA), 28 (GPU vblank), 29 (xHCI).
static constexpr uint8_t MSI_IRQ = 25;
static constexpr uint32_t MSI_VECTOR = 57; // IRQ_VECTOR_BASE + MSI_IRQ
static constexpr uint32_t MSI_ADDR_BASE = 0xFEE00000;
// Cached MSI-X masks (a cause is ENABLED when its mask bit is clear).
static uint32_t g_fhInitMask = 0;
@@ -76,14 +75,14 @@ namespace Drivers::Net::Wifi {
// exposed here; the loop count is calibrated the same way IntelHda does it.
void IwxDelayUs(uint32_t us) {
for (volatile uint32_t i = 0; i < us * 100u; i++) {
asm volatile("pause" ::: "memory");
Arch::Pause();
}
}
void IwxDelayMs(uint32_t ms) {
uint64_t start = Timekeeping::GetMilliseconds();
while (Timekeeping::GetMilliseconds() - start < ms) {
asm volatile("pause" ::: "memory");
Arch::Pause();
}
}
@@ -144,13 +143,13 @@ namespace Drivers::Net::Wifi {
uint32_t IwxReadPrph(uint32_t addr) {
IwxWrite32(IWX_HBUS_TARG_PRPH_RADDR, PrphAddr(addr));
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
return IwxRead32(IWX_HBUS_TARG_PRPH_RDAT);
}
void IwxWritePrph(uint32_t addr, uint32_t val) {
IwxWrite32(IWX_HBUS_TARG_PRPH_WADDR, PrphAddr(addr));
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
IwxWrite32(IWX_HBUS_TARG_PRPH_WDAT, val);
}
@@ -457,7 +456,7 @@ namespace Drivers::Net::Wifi {
descs[i].rbid = (uint16_t)(i & 0xffff);
descs[i].addr = g_iwx.RxQ.BufPhys[i];
}
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
// `stageSlots` reserves one page per concurrently queued frame; pass 0 for
@@ -652,7 +651,7 @@ namespace Drivers::Net::Wifi {
ci->mcr_size = (uint16_t)IWX_RX_QUEUE_CB_SIZE(IWX_RX_MQ_RING_COUNT);
memcpy(g_iwx.ImlDma.Virt, g_iwx.Fw.Iml, g_iwx.Fw.ImlLen);
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
uint64_t paddr = g_iwx.CtxtInfo.Phys;
IwxWrite32(IWX_CSR_CTXT_INFO_ADDR, (uint32_t)(paddr & 0xffffffff));
@@ -829,7 +828,7 @@ namespace Drivers::Net::Wifi {
auto* scratch = (IwxPrphScratch*)g_iwx.PrphScratch.Virt;
scratch->ctrl_cfg.pnvm_cfg.pnvm_base_addr = g_iwx.PnvmDma.Phys;
scratch->ctrl_cfg.pnvm_cfg.pnvm_size = g_iwx.PnvmSize;
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
if (!IwxNicLock()) return false;
@@ -1006,7 +1005,7 @@ namespace Drivers::Net::Wifi {
} else {
desc->num_tbs = 1;
}
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
g_iwx.CmdDone = false;
g_iwx.LastCmdId = code;
@@ -1337,7 +1336,7 @@ namespace Drivers::Net::Wifi {
auto* bc = (IwxGen3BcTblEntry*)ring.BcTbl.Virt;
bc[idx].tfd_offset = (uint16_t)((hdrLen + payloadLen) | (chunks << 14));
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
ring.Queued++;
ring.Cur = (ring.Cur + 1) % IWX_TX_RING_COUNT;
@@ -1488,7 +1487,7 @@ namespace Drivers::Net::Wifi {
static bool IwxReadMem(uint32_t addr, uint32_t* out, int dwords) {
if (!IwxNicLock()) return false;
IwxWrite32(IWX_HBUS_TARG_MEM_RADDR, addr);
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
for (int i = 0; i < dwords; i++)
out[i] = IwxRead32(IWX_HBUS_TARG_MEM_RDAT);
IwxNicUnlock();
@@ -1786,11 +1785,17 @@ namespace Drivers::Net::Wifi {
return false;
}
// Message for our IRQ slot on the boot CPU
Arch::MsiMessage msi;
if (!Arch::ComposeMsi(MSI_IRQ, msi)) {
return false;
}
// Program entry 0: all causes are mapped to vector 0 by IwxConfMsixHw.
volatile uint32_t* entry = (volatile uint32_t*)(g_iwx.Mmio + tableOff);
entry[0] = MSI_ADDR_BASE; // message address (BSP, physical, fixed)
entry[1] = 0; // upper address
entry[2] = MSI_VECTOR; // message data
entry[0] = (uint32_t)msi.address; // message address
entry[1] = (uint32_t)(msi.address >> 32); // upper address
entry[2] = msi.data; // message data
entry[3] = 0; // vector control: unmasked
msgCtrl |= (1 << 15); // MSI-X enable
@@ -1801,9 +1806,8 @@ namespace Drivers::Net::Wifi {
pciCmd |= Pci::PCI_CMD_INTX_DISABLE;
Pci::LegacyWrite16(bus, dev, func, (uint8_t)Pci::PCI_REG_COMMAND, pciCmd);
Hal::RegisterIrqHandler(MSI_IRQ, HandleInterrupt);
KernelLogStream(OK, "WiFi") << "MSI-X enabled: vector "
<< (uint64_t)MSI_VECTOR << " (IRQ slot " << (uint64_t)MSI_IRQ << ")";
Arch::RegisterIrqHandler(MSI_IRQ, HandleInterrupt);
KernelLogStream(OK, "WiFi") << "MSI-X enabled: IRQ slot " << (uint64_t)MSI_IRQ;
return true;
}
@@ -1814,14 +1818,10 @@ namespace Drivers::Net::Wifi {
Pci::DisableInterruptDelivery(bus, dev, func);
uint16_t msgCtrl = Pci::LegacyRead16(bus, dev, func, cap + 2);
bool is64 = (msgCtrl & (1 << 7)) != 0;
Pci::LegacyWrite32(bus, dev, func, cap + 4, MSI_ADDR_BASE);
if (is64) {
Pci::LegacyWrite32(bus, dev, func, cap + 8, 0);
Pci::LegacyWrite16(bus, dev, func, cap + 12, MSI_VECTOR);
} else {
Pci::LegacyWrite16(bus, dev, func, cap + 8, MSI_VECTOR);
// Message Address/Data: IRQ slot MSI_IRQ on the boot CPU
if (!Pci::WriteMsiMessage(bus, dev, func, cap, MSI_IRQ)) {
return false;
}
msgCtrl &= ~0x70; // single message
@@ -1832,9 +1832,8 @@ namespace Drivers::Net::Wifi {
pciCmd |= Pci::PCI_CMD_INTX_DISABLE;
Pci::LegacyWrite16(bus, dev, func, (uint8_t)Pci::PCI_REG_COMMAND, pciCmd);
Hal::RegisterIrqHandler(MSI_IRQ, HandleInterrupt);
KernelLogStream(OK, "WiFi") << "MSI enabled: vector "
<< (uint64_t)MSI_VECTOR << " (IRQ slot " << (uint64_t)MSI_IRQ << ")";
Arch::RegisterIrqHandler(MSI_IRQ, HandleInterrupt);
KernelLogStream(OK, "WiFi") << "MSI enabled: IRQ slot " << (uint64_t)MSI_IRQ;
return true;
}
+6 -7
View File
@@ -12,6 +12,7 @@
*/
#include "Wifi.hpp"
#include <Arch/Cpu.hpp>
#include "Iwx.hpp"
#include "Wpa.hpp"
#include <Fs/Vfs.hpp>
@@ -19,10 +20,9 @@
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
#include <CppLib/Spinlock.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Hal/SmpBoot.hpp>
#include <Hal/Apic/Apic.hpp>
#include <Hal/Apic/Interrupts.hpp>
#include <Timekeeping/Timer.hpp>
#include <Arch/Smp.hpp>
#include <Arch/Interrupts.hpp>
#include <Sched/Scheduler.hpp>
#include <atomic>
@@ -444,8 +444,7 @@ namespace Drivers::Net::Wifi {
auto* t = Smp::GetCpuData(i);
if (!t || !t->started) continue;
if (t->currentSlot >= 0 || t->reservedForKernelWork) continue;
if (Hal::LocalApic::SendFixedIpi(t->lapicId,
Hal::IRQ_VECTOR_BASE + Hal::IRQ_RESCHEDULE)) {
if (Arch::SendIpi(t->cpuIndex, Arch::IRQ_RESCHEDULE)) {
g_lastApKickMs = now;
return true;
}
@@ -624,7 +623,7 @@ namespace Drivers::Net::Wifi {
uint64_t start = Timekeeping::GetMilliseconds();
while (g_iwx.ScanActive && Timekeeping::GetMilliseconds() - start < timeoutMs) {
IwxProcessEvents();
for (int i = 0; i < 200; i++) asm volatile("pause" ::: "memory");
for (int i = 0; i < 200; i++) Arch::Pause();
}
if (g_iwx.ScanActive) {
+4 -6
View File
@@ -17,12 +17,13 @@
*/
#include "Wpa.hpp"
#include <Arch/Cpu.hpp>
#include "Ieee80211.hpp"
#include <Libraries/Crypto.hpp>
#include <Libraries/Memory.hpp>
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Timekeeping/Timer.hpp>
using namespace Kt;
@@ -131,12 +132,9 @@ namespace Drivers::Net::Wifi {
} pool;
for (int i = 0; i < 8; i++) {
uint64_t tsc;
asm volatile("rdtsc; shl $32, %%rdx; or %%rdx, %%rax"
: "=a"(tsc) :: "rdx");
pool.tsc[i] = tsc;
pool.tsc[i] = Arch::ReadTimestamp();
// Space the samples out so the low bits differ between them.
for (int k = 0; k < 64; k++) asm volatile("pause" ::: "memory");
for (int k = 0; k < 64; k++) Arch::Pause();
}
pool.counter = ++counter;
memcpy(pool.mac, g_cfg.OwnMac, 6);
+5 -5
View File
@@ -5,14 +5,14 @@
*/
#include "Keyboard.hpp"
#include <Arch/Cpu.hpp>
#include "PS2Controller.hpp"
#include <Io/IoPort.hpp>
#include <CppLib/Stream.hpp>
#include <CppLib/Spinlock.hpp>
#include <Terminal/Terminal.hpp>
#include <Hal/Apic/Interrupts.hpp>
#include <Hal/Apic/IoApic.hpp>
#include <Arch/Interrupts.hpp>
#include <Drivers/Input/InputEvents.hpp>
namespace Drivers::PS2::Keyboard {
@@ -145,8 +145,8 @@ namespace Drivers::PS2::Keyboard {
g_ExtendedScancode = false;
// Register IRQ handler and unmask IRQ1 on the IOAPIC
Hal::RegisterIrqHandler(Hal::IRQ_KEYBOARD, HandleIRQ);
Hal::IoApic::UnmaskIrq(Hal::IoApic::GetGsiForIrq(Hal::IRQ_KEYBOARD));
Arch::RegisterIrqHandler(Arch::IRQ_KEYBOARD, HandleIRQ);
Arch::EnableLegacyIrq(Arch::IRQ_KEYBOARD);
Kt::KernelLogStream(Kt::OK, "PS2/KB") << "Keyboard driver initialized";
}
@@ -299,7 +299,7 @@ namespace Drivers::PS2::Keyboard {
}
}
// Yield the CPU while waiting
asm volatile("hlt");
Arch::Halt();
}
}
+3 -4
View File
@@ -11,8 +11,7 @@
#include <CppLib/Stream.hpp>
#include <CppLib/Spinlock.hpp>
#include <Terminal/Terminal.hpp>
#include <Hal/Apic/Interrupts.hpp>
#include <Hal/Apic/IoApic.hpp>
#include <Arch/Interrupts.hpp>
#include <Drivers/Input/InputEvents.hpp>
namespace Drivers::PS2::Mouse {
@@ -103,8 +102,8 @@ namespace Drivers::PS2::Mouse {
g_PacketIndex = 0;
// Register IRQ handler and unmask IRQ12 on the IOAPIC
Hal::RegisterIrqHandler(Hal::IRQ_MOUSE, HandleIRQ);
Hal::IoApic::UnmaskIrq(Hal::IoApic::GetGsiForIrq(Hal::IRQ_MOUSE));
Arch::RegisterIrqHandler(Arch::IRQ_MOUSE, HandleIRQ);
Arch::EnableLegacyIrq(Arch::IRQ_MOUSE);
Kt::KernelLogStream(Kt::OK, "PS2/Mouse") << "Mouse driver initialized";
}
+10 -9
View File
@@ -5,6 +5,7 @@
*/
#include "Ahci.hpp"
#include <Arch/Cpu.hpp>
#include "BlockDevice.hpp"
#include <Pci/Pci.hpp>
#include <Terminal/Terminal.hpp>
@@ -91,14 +92,14 @@ namespace Drivers::Storage::Ahci {
KernelLogStream(OK, "AHCI") << "BIOS handoff complete";
return;
}
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
// If BIOS Busy, wait another 2 seconds
if (ReadReg(REG_BOHC) & BOHC_BB) {
for (int i = 0; i < 2000000; i++) {
if (!(ReadReg(REG_BOHC) & BOHC_BB)) break;
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -130,7 +131,7 @@ namespace Drivers::Storage::Ahci {
if (!(cmd & PORT_CMD_CR) && !(cmd & PORT_CMD_FR)) {
return;
}
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
KernelLogStream(WARNING, "AHCI") << "Port " << port << " stop timed out";
@@ -140,7 +141,7 @@ namespace Drivers::Storage::Ahci {
// Wait for CR to clear before starting
for (int i = 0; i < 500000; i++) {
if (!(ReadPortReg(port, PORT_CMD) & PORT_CMD_CR)) break;
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
uint32_t cmd = ReadPortReg(port, PORT_CMD);
@@ -170,7 +171,7 @@ namespace Drivers::Storage::Ahci {
for (int i = 0; i < 1000000; i++) {
uint32_t tfd = ReadPortReg(port, PORT_TFD);
if (!(tfd & PORT_TFD_BSY)) break;
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
uint32_t sig = ReadPortReg(port, PORT_SIG);
@@ -248,7 +249,7 @@ namespace Drivers::Storage::Ahci {
// Wait for the slot to be free
for (int i = 0; i < 500000; i++) {
if (!(ReadPortReg(port, PORT_CI) & (1u << slot))) break;
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
// Check that the port isn't in error
@@ -258,7 +259,7 @@ namespace Drivers::Storage::Ahci {
for (int i = 0; i < 1000000; i++) {
tfd = ReadPortReg(port, PORT_TFD);
if (!(tfd & (PORT_TFD_BSY | PORT_TFD_DRQ))) break;
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
if (tfd & (PORT_TFD_BSY | PORT_TFD_DRQ)) {
KernelLogStream(ERROR, "AHCI") << "Port " << port << " device busy before command issue";
@@ -294,7 +295,7 @@ namespace Drivers::Storage::Ahci {
return false;
}
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
KernelLogStream(ERROR, "AHCI") << "Port " << port << " command timeout";
@@ -554,7 +555,7 @@ namespace Drivers::Storage::Ahci {
WriteReg(REG_GHC, ghc);
return true;
}
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
KernelLogStream(ERROR, "AHCI") << "HBA reset timed out";
+3 -4
View File
@@ -5,6 +5,7 @@
*/
#include "Gpt.hpp"
#include <Arch/Cpu.hpp>
#include "BlockDevice.hpp"
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
@@ -565,13 +566,11 @@ namespace Drivers::Storage::Gpt {
}
// -------------------------------------------------------------------------
// Simple GUID generation from RDTSC + mixing
// Simple GUID generation from the CPU timestamp counter + mixing
// -------------------------------------------------------------------------
static uint64_t SimpleRand64() {
uint32_t lo, hi;
asm volatile ("rdtsc" : "=a"(lo), "=d"(hi));
uint64_t val = ((uint64_t)hi << 32) | lo;
uint64_t val = Arch::ReadTimestamp();
// xorshift64
val ^= val << 13;
val ^= val >> 7;
+5 -4
View File
@@ -5,6 +5,7 @@
*/
#include "Nvme.hpp"
#include <Arch/Cpu.hpp>
#include "BlockDevice.hpp"
#include <Pci/Pci.hpp>
#include <Terminal/Terminal.hpp>
@@ -13,7 +14,7 @@
#include <Memory/Paging.hpp>
#include <Memory/PageFrameAllocator.hpp>
#include <Libraries/Memory.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Timekeeping/Timer.hpp>
using namespace Kt;
@@ -191,7 +192,7 @@ namespace Drivers::Storage::Nvme {
if ((spins & 0x3FFF) == 0 &&
Timekeeping::GetMilliseconds() - start >= kTimeoutMs) break;
if (spins >= kMaxSpins) break;
asm volatile("pause" ::: "memory");
Arch::Pause();
}
KernelLogStream(ERROR, "NVMe") << "Command " << base::dec << (uint64_t)cmdId
@@ -254,7 +255,7 @@ namespace Drivers::Storage::Nvme {
if (!(csts & CSTS_RDY)) {
return true;
}
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
KernelLogStream(ERROR, "NVMe") << "Controller disable timeout";
@@ -280,7 +281,7 @@ namespace Drivers::Storage::Nvme {
if (csts & CSTS_RDY) {
return true;
}
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
KernelLogStream(ERROR, "NVMe") << "Controller enable timeout";
+12 -11
View File
@@ -5,6 +5,7 @@
*/
#include "A2dp.hpp"
#include <Arch/Cpu.hpp>
#include "Sbc.hpp"
#include "L2cap.hpp"
#include "Hci.hpp"
@@ -12,7 +13,7 @@
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
#include <Libraries/Memory.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Timekeeping/Timer.hpp>
#include <atomic>
using namespace Kt;
@@ -232,7 +233,7 @@ namespace Drivers::USB::Bluetooth::A2dp {
return true;
}
for (int j = 0; j < 100; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
g_expectLabel.store(0xFF, std::memory_order_release);
@@ -1166,7 +1167,7 @@ namespace Drivers::USB::Bluetooth::A2dp {
answered = true;
break;
}
for (int j = 0; j < 100; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 100; j++) Arch::CompilerBarrier();
}
// Transaction over: CLOSE the client channel (FreeChannel sends the
@@ -1200,7 +1201,7 @@ namespace Drivers::USB::Bluetooth::A2dp {
Hci::ProcessPendingCommands();
auto* c = Hci::GetConnection(g_aclHandle.load(std::memory_order_acquire));
if (c && c->Encrypted) return true;
for (int j = 0; j < 100; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 100; j++) Arch::CompilerBarrier();
}
return false;
}
@@ -1236,7 +1237,7 @@ namespace Drivers::USB::Bluetooth::A2dp {
&& Timekeeping::GetMilliseconds() - waitStart < timeoutMs) {
Xhci::PollEvents();
Hci::DrainEvents();
for (int j = 0; j < 100; j++) asm volatile("pause" ::: "memory");
for (int j = 0; j < 100; j++) Arch::Pause();
}
return IsReady();
}
@@ -1268,7 +1269,7 @@ namespace Drivers::USB::Bluetooth::A2dp {
Hci::DrainEvents();
Hci::ProcessPendingCommands();
if (g_sigCid.load(std::memory_order_acquire) != 0) break;
for (int j = 0; j < 100; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 100; j++) Arch::CompilerBarrier();
}
}
if (g_sigCid.load(std::memory_order_acquire) != 0) {
@@ -1327,7 +1328,7 @@ namespace Drivers::USB::Bluetooth::A2dp {
// timer.
if (L2cap::ConnRspResult(sig) == L2cap::CONN_PENDING)
waitBudgetMs = timeoutMs;
for (int j = 0; j < 100; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 100; j++) Arch::CompilerBarrier();
}
uint16_t readySig = g_sigCid.load(std::memory_order_acquire);
if (readySig != 0) {
@@ -1364,7 +1365,7 @@ namespace Drivers::USB::Bluetooth::A2dp {
while (Timekeeping::GetMilliseconds() - st < 400) {
Xhci::PollEvents();
Hci::DrainEvents();
for (int j = 0; j < 200; j++) asm volatile("pause" ::: "memory");
for (int j = 0; j < 200; j++) Arch::Pause();
}
}
@@ -1387,7 +1388,7 @@ namespace Drivers::USB::Bluetooth::A2dp {
Hci::DrainEvents();
State s = g_state.load(std::memory_order_acquire);
if (s == State::Open || s == State::Streaming) break;
for (int j = 0; j < 100; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 100; j++) Arch::CompilerBarrier();
}
State s = g_state.load(std::memory_order_acquire);
if (s != State::Open && s != State::Streaming) {
@@ -1495,7 +1496,7 @@ namespace Drivers::USB::Bluetooth::A2dp {
g_mediaCid.store(other, std::memory_order_release);
break;
}
for (int j = 0; j < 100; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 100; j++) Arch::CompilerBarrier();
}
if (g_mediaCid.load(std::memory_order_acquire) == 0) {
@@ -1879,7 +1880,7 @@ namespace Drivers::USB::Bluetooth::A2dp {
if (g_serviceActive.compare_exchange_weak(expected, true,
std::memory_order_acquire))
return true;
asm volatile("pause" ::: "memory");
Arch::Pause();
}
return false;
}
@@ -5,6 +5,7 @@
*/
#include "Bluetooth.hpp"
#include <Arch/Cpu.hpp>
#include "Hci.hpp"
#include "A2dp.hpp"
#include "IntelFirmware.hpp"
@@ -15,8 +16,8 @@
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
#include <Libraries/Memory.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Hal/SmpBoot.hpp>
#include <Timekeeping/Timer.hpp>
#include <Arch/Smp.hpp>
#include <atomic>
using namespace Kt;
@@ -223,7 +224,7 @@ namespace Drivers::USB::Bluetooth {
uint64_t start = Timekeeping::GetMilliseconds();
while (Timekeeping::GetMilliseconds() - start < 200) {
Xhci::PollEvents();
asm volatile("pause" ::: "memory");
Arch::Pause();
}
// Start the event pipe BEFORE sending any HCI commands.
@@ -498,7 +499,7 @@ namespace Drivers::USB::Bluetooth {
auto* conn = Hci::GetConnectionByIndex(i);
if (conn && conn->Active) { anyActive = true; break; }
}
for (int k = 0; k < 200; k++) asm volatile("pause" ::: "memory");
for (int k = 0; k < 200; k++) Arch::Pause();
}
if (anyActive) return false;
}
@@ -551,7 +552,7 @@ namespace Drivers::USB::Bluetooth {
Hci::DrainEvents();
for (int j = 0; j < 200; j++) {
asm volatile("pause" ::: "memory");
Arch::Pause();
}
}
@@ -568,7 +569,7 @@ namespace Drivers::USB::Bluetooth {
Xhci::PollEvents();
Hci::DrainEvents();
for (int j = 0; j < 100; j++)
asm volatile("pause" ::: "memory");
Arch::Pause();
}
if (Hci::IsInquiryActive() && !Hci::CancelInquiry()) return -1;
}
@@ -615,7 +616,7 @@ namespace Drivers::USB::Bluetooth {
Hci::DrainEvents();
target = FindAclConnection(bdAddr);
for (int j = 0; j < 200; j++) {
asm volatile("pause" ::: "memory");
Arch::Pause();
}
}
if (!target) return -1;
@@ -635,7 +636,7 @@ namespace Drivers::USB::Bluetooth {
Hci::ProcessPendingCommands();
if (!target->Active || !SameAddress(target->BdAddr, bdAddr)) break;
if (target->Encrypted) break;
for (int k = 0; k < 200; k++) asm volatile("pause" ::: "memory");
for (int k = 0; k < 200; k++) Arch::Pause();
}
}
+11 -10
View File
@@ -5,6 +5,7 @@
*/
#include "Hci.hpp"
#include <Arch/Cpu.hpp>
#include "L2cap.hpp"
#include "A2dp.hpp"
#include <atomic>
@@ -17,7 +18,7 @@
#include <Memory/HHDM.hpp>
#include <Memory/PageFrameAllocator.hpp>
#include <Libraries/Memory.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Timekeeping/Timer.hpp>
using namespace Kt;
@@ -632,7 +633,7 @@ namespace Drivers::USB::Bluetooth::Hci {
static void BusyWaitMs(uint64_t ms) {
uint64_t start = Timekeeping::GetMilliseconds();
while (Timekeeping::GetMilliseconds() - start < ms) {
asm volatile("pause" ::: "memory");
Arch::Pause();
}
}
@@ -643,7 +644,7 @@ namespace Drivers::USB::Bluetooth::Hci {
Xhci::PollEvents();
DrainEvents();
for (int j = 0; j < 100; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
}
@@ -835,7 +836,7 @@ namespace Drivers::USB::Bluetooth::Hci {
}
for (int j = 0; j < 100; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -884,7 +885,7 @@ namespace Drivers::USB::Bluetooth::Hci {
}
for (int j = 0; j < 100; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -1644,7 +1645,7 @@ namespace Drivers::USB::Bluetooth::Hci {
}
}
for (int j = 0; j < 100; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 100; j++) Arch::CompilerBarrier();
}
// Distinguish "pipe dead" (0 completions) from "responses arriving but
@@ -1734,7 +1735,7 @@ namespace Drivers::USB::Bluetooth::Hci {
if (outStatus) *outStatus = g_secureStatus;
return true;
}
for (int j = 0; j < 100; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 100; j++) Arch::CompilerBarrier();
}
return false;
}
@@ -1809,7 +1810,7 @@ namespace Drivers::USB::Bluetooth::Hci {
<< " byte " << g_ssBytesSent;
return false;
}
asm volatile("pause" ::: "memory");
Arch::Pause();
}
g_aclTxLock.Acquire();
@@ -1846,7 +1847,7 @@ namespace Drivers::USB::Bluetooth::Hci {
DrainEvents();
if (g_aclTxTransportError.load(std::memory_order_acquire)) return false;
if (Timekeeping::GetMilliseconds() - start > timeoutMs) return false;
asm volatile("pause" ::: "memory");
Arch::Pause();
}
return !g_aclTxTransportError.load(std::memory_order_acquire);
}
@@ -1874,7 +1875,7 @@ namespace Drivers::USB::Bluetooth::Hci {
Xhci::PollEvents();
DrainEvents();
if (g_intelBootup) return true;
for (int j = 0; j < 100; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 100; j++) Arch::CompilerBarrier();
}
KernelLogStream(ERROR, "BT-HCI") << "Timed out waiting for Intel bootup event";
@@ -12,13 +12,14 @@
*/
#include "IntelFirmware.hpp"
#include <Arch/Cpu.hpp>
#include "Hci.hpp"
#include <Fs/Vfs.hpp>
#include <Memory/Heap.hpp>
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
#include <Libraries/Memory.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Timekeeping/Timer.hpp>
using namespace Kt;
@@ -475,7 +476,7 @@ namespace Drivers::USB::Bluetooth {
}
Fs::Vfs::ReadBackendFile(file, fw, 0, size);
Fs::Vfs::CloseBackendFile(file);
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
// 4. Run the secure download + boot sequence.
bool ok = DownloadImage(fw, size, ver, cnvi, cnvr);
+3 -2
View File
@@ -5,6 +5,7 @@
*/
#include "L2cap.hpp"
#include <Arch/Cpu.hpp>
#include "Hci.hpp"
#include "A2dp.hpp"
#include "Avrcp.hpp"
@@ -12,7 +13,7 @@
#include <Terminal/Terminal.hpp>
#include <CppLib/Stream.hpp>
#include <Libraries/Memory.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Timekeeping/Timer.hpp>
using namespace Kt;
@@ -554,7 +555,7 @@ namespace Drivers::USB::Bluetooth::L2cap {
if (ch && ch->Configured) return true;
for (int j = 0; j < 100; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
return false;
+1 -1
View File
@@ -7,7 +7,7 @@
#include "HidKeyboard.hpp"
#include <Drivers/PS2/Keyboard.hpp>
#include <Terminal/Terminal.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Timekeeping/Timer.hpp>
#include <CppLib/Stream.hpp>
using namespace Kt;
+6 -7
View File
@@ -5,6 +5,7 @@
*/
#include "MassStorage.hpp"
#include <Arch/Cpu.hpp>
#include "Xhci.hpp"
#include "UsbDevice.hpp"
#include <Drivers/Storage/BlockDevice.hpp>
@@ -15,7 +16,7 @@
#include <Memory/HHDM.hpp>
#include <Memory/PageFrameAllocator.hpp>
#include <Libraries/Memory.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Timekeeping/Timer.hpp>
#include <atomic>
using namespace Kt;
@@ -130,12 +131,10 @@ namespace Drivers::USB::MassStorage {
}
static void PollWaitMs(uint32_t ms) {
uint64_t flags;
asm volatile("pushfq; pop %0" : "=r"(flags));
if ((flags & (1 << 9)) == 0) {
if (!Arch::InterruptsEnabled()) {
for (uint64_t i = 0; i < (uint64_t)ms * 1000; i++) {
Xhci::PollEvents();
asm volatile("outb %%al, $0x80" ::: "memory");
Arch::IoDelay();
}
return;
}
@@ -143,7 +142,7 @@ namespace Drivers::USB::MassStorage {
uint64_t start = Timekeeping::GetMilliseconds();
while (Timekeeping::GetMilliseconds() - start < ms) {
Xhci::PollEvents();
asm volatile("pause" ::: "memory");
Arch::Pause();
}
}
@@ -221,7 +220,7 @@ namespace Drivers::USB::MassStorage {
std::memory_order_acquire,
std::memory_order_relaxed)) {
expected = false;
asm volatile("pause" ::: "memory");
Arch::Pause();
}
}
+7 -8
View File
@@ -5,6 +5,7 @@
*/
#include "UsbDevice.hpp"
#include <Arch/Cpu.hpp>
#include "Xhci.hpp"
#include "HidKeyboard.hpp"
#include "HidMouse.hpp"
@@ -15,24 +16,22 @@
#include <Memory/HHDM.hpp>
#include <Memory/PageFrameAllocator.hpp>
#include <Libraries/Memory.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Timekeeping/Timer.hpp>
using namespace Kt;
static void BusyWaitMs(uint64_t ms) {
uint64_t flags;
asm volatile("pushfq; pop %0" : "=r"(flags));
if (flags & (1 << 9)) {
if (Arch::InterruptsEnabled()) {
// Interrupts enabled — use timer-based delay
uint64_t start = Timekeeping::GetMilliseconds();
while (Timekeeping::GetMilliseconds() - start < ms) {
asm volatile("pause" ::: "memory");
Arch::Pause();
}
} else {
// Interrupts disabled (e.g. timer tick context) — use I/O port delay
// Each outb to port 0x80 takes ~1µs on x86
// Interrupts disabled (e.g. timer tick context) — the tick is not
// advancing here, so count ~1 µs delays instead
for (uint64_t i = 0; i < ms * 1000; i++) {
asm volatile("outb %%al, $0x80" ::: "memory");
Arch::IoDelay();
}
}
}
+28 -38
View File
@@ -5,6 +5,7 @@
*/
#include "Xhci.hpp"
#include <Arch/Cpu.hpp>
#include <atomic>
#include "UsbDevice.hpp"
#include "HidKeyboard.hpp"
@@ -18,28 +19,26 @@
#include <Memory/Paging.hpp>
#include <Memory/PageFrameAllocator.hpp>
#include <Libraries/Memory.hpp>
#include <Hal/Apic/Interrupts.hpp>
#include <Hal/SmpBoot.hpp>
#include <Timekeeping/ApicTimer.hpp>
#include <Arch/Interrupts.hpp>
#include <Arch/Smp.hpp>
#include <Timekeeping/Timer.hpp>
#include <CppLib/Spinlock.hpp>
#include <atomic>
using namespace Kt;
static void BusyWaitMs(uint64_t ms) {
uint64_t flags;
asm volatile("pushfq; pop %0" : "=r"(flags));
if (flags & (1 << 9)) {
if (Arch::InterruptsEnabled()) {
// Interrupts enabled — use timer-based delay
uint64_t start = Timekeeping::GetMilliseconds();
while (Timekeeping::GetMilliseconds() - start < ms) {
asm volatile("pause" ::: "memory");
Arch::Pause();
}
} else {
// Interrupts disabled (e.g. timer tick context) — use I/O port delay
// Each outb to port 0x80 takes ~1µs on x86
// Interrupts disabled (e.g. timer tick context) — the tick is not
// advancing here, so count ~1 µs delays instead
for (uint64_t i = 0; i < ms * 1000; i++) {
asm volatile("outb %%al, $0x80" ::: "memory");
Arch::IoDelay();
}
}
}
@@ -429,17 +428,9 @@ namespace Drivers::USB::Xhci {
uint16_t msgCtrl = Pci::LegacyRead16(bus, dev, func, cap + 2);
bool is64bit = (msgCtrl & (1 << 7)) != 0;
// Write Message Address (cap+4): BSP APIC ID 0, physical destination, fixed delivery
Pci::LegacyWrite32(bus, dev, func, cap + 4, MSI_ADDR_BASE);
// Write Message Data (vector number, edge-triggered, fixed delivery)
if (is64bit) {
// 64-bit: Upper Address at cap+8, Data at cap+12
Pci::LegacyWrite32(bus, dev, func, cap + 8, 0);
Pci::LegacyWrite16(bus, dev, func, cap + 12, MSI_VECTOR);
} else {
// 32-bit: Data at cap+8
Pci::LegacyWrite16(bus, dev, func, cap + 8, MSI_VECTOR);
// Message Address/Data: IRQ slot MSI_IRQ on the boot CPU
if (!Pci::WriteMsiMessage(bus, dev, func, cap, MSI_IRQ)) {
return false;
}
// Enable MSI: set bit 0 (MSI Enable), clear bits 6:4 (single message)
@@ -453,10 +444,9 @@ namespace Drivers::USB::Xhci {
Pci::LegacyWrite16(bus, dev, func, (uint8_t)Pci::PCI_REG_COMMAND, pciCmd);
// Register the interrupt handler for MSI vector
Hal::RegisterIrqHandler(MSI_IRQ, HandleInterrupt);
Arch::RegisterIrqHandler(MSI_IRQ, HandleInterrupt);
KernelLogStream(OK, "xHCI") << "MSI enabled: vector " << base::dec << (uint64_t)MSI_VECTOR
<< " (IRQ slot " << (uint64_t)MSI_IRQ << ")" << (is64bit ? " [64-bit]" : " [32-bit]");
KernelLogStream(OK, "xHCI") << "MSI enabled: IRQ slot " << base::dec << (uint64_t)MSI_IRQ << (is64bit ? " [64-bit]" : " [32-bit]");
return true;
}
@@ -814,7 +804,7 @@ namespace Drivers::USB::Xhci {
}
// Small delay
for (int j = 0; j < 100; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -936,7 +926,7 @@ namespace Drivers::USB::Xhci {
return g_xferCompletionCode[slotId];
}
for (int j = 0; j < 100; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -1358,7 +1348,7 @@ namespace Drivers::USB::Xhci {
}
for (int j = 0; j < 100; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -1552,7 +1542,7 @@ namespace Drivers::USB::Xhci {
break;
}
for (int j = 0; j < 100; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -1665,7 +1655,7 @@ namespace Drivers::USB::Xhci {
for (uint32_t i = 0; i < 100000; i++) {
if (ReadOp(OP_USBSTS) & USBSTS_HCH) break;
for (int j = 0; j < 10; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 10; j++) Arch::CompilerBarrier();
}
if (!(ReadOp(OP_USBSTS) & USBSTS_HCH)) {
@@ -1677,11 +1667,11 @@ namespace Drivers::USB::Xhci {
WriteOp(OP_USBCMD, USBCMD_HCRST);
for (uint32_t i = 0; i < 100000; i++) {
if (!(ReadOp(OP_USBCMD) & USBCMD_HCRST)) break;
for (int j = 0; j < 10; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 10; j++) Arch::CompilerBarrier();
}
for (uint32_t i = 0; i < 100000; i++) {
if (!(ReadOp(OP_USBSTS) & USBSTS_CNR)) break;
for (int j = 0; j < 10; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 10; j++) Arch::CompilerBarrier();
}
if (ReadOp(OP_USBSTS) & USBSTS_CNR) {
KernelLogStream(WARNING, "xHCI") << "Controller not ready after reset";
@@ -1752,7 +1742,7 @@ namespace Drivers::USB::Xhci {
WriteOp(OP_USBCMD, USBCMD_RS | USBCMD_INTE | USBCMD_HSEE);
for (uint32_t i = 0; i < 100000; i++) {
if (!(ReadOp(OP_USBSTS) & USBSTS_HCH)) break;
for (int j = 0; j < 10; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 10; j++) Arch::CompilerBarrier();
}
KernelLogStream(OK, "xHCI") << "Controller started";
g_initialized = true;
@@ -1783,7 +1773,7 @@ namespace Drivers::USB::Xhci {
PollEvents();
uint32_t ps = ReadOp(OP_PORTSC_BASE + port * OP_PORTSC_STRIDE);
if (ps & PORTSC_PRC) { resetDone = true; break; }
for (int j = 0; j < 100; j++) asm volatile("" ::: "memory");
for (int j = 0; j < 100; j++) Arch::CompilerBarrier();
}
if (!resetDone) {
@@ -1924,7 +1914,7 @@ namespace Drivers::USB::Xhci {
break;
}
for (int j = 0; j < 10; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -1945,7 +1935,7 @@ namespace Drivers::USB::Xhci {
break;
}
for (int j = 0; j < 10; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -1955,7 +1945,7 @@ namespace Drivers::USB::Xhci {
break;
}
for (int j = 0; j < 10; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -2074,7 +2064,7 @@ namespace Drivers::USB::Xhci {
break;
}
for (int j = 0; j < 10; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
@@ -2123,7 +2113,7 @@ namespace Drivers::USB::Xhci {
break;
}
for (int j = 0; j < 100; j++) {
asm volatile("" ::: "memory");
Arch::CompilerBarrier();
}
}
-2
View File
@@ -24,8 +24,6 @@ namespace Drivers::USB::Xhci {
// the IRQ dispatcher has one handler per slot, so sharing would replace
// one driver's handler and eventually strand USB or storage completions.
constexpr uint8_t MSI_IRQ = 29;
constexpr uint32_t MSI_VECTOR = 61;
constexpr uint32_t MSI_ADDR_BASE = 0xFEE00000;
// PCI class/subclass/progif for xHCI
constexpr uint8_t PCI_CLASS_SERIAL = 0x0C;