fix: kernel concurrency, interrupt context, and user VA safety
This commit is contained in:
1 parent
f222bf1f04
commit
b1c55073c7
71 files changed
+2654
-1092
No files matched your search
@@ -13,8 +13,6 @@
|
||||
#include <Memory/Paging.hpp>
|
||||
#include <Memory/PageFrameAllocator.hpp>
|
||||
#include <Libraries/Memory.hpp>
|
||||
#include <Hal/Apic/Interrupts.hpp>
|
||||
#include <Hal/Apic/IoApic.hpp>
|
||||
#include <Timekeeping/ApicTimer.hpp>
|
||||
|
||||
using namespace Kt;
|
||||
@@ -511,9 +509,9 @@ namespace Drivers::Storage::Nvme {
|
||||
cmd.Prp1 = g_ioCqPhys;
|
||||
// CDW10: bits 31:16 = queue size (0-based), bits 15:0 = queue ID
|
||||
cmd.Cdw10 = ((uint32_t)(g_ioCqDepth - 1) << 16) | 1;
|
||||
// CDW11: bit 0 = physically contiguous, bit 1 = interrupts enabled
|
||||
// bits 31:16 = interrupt vector
|
||||
cmd.Cdw11 = (1u << 0) | (1u << 1) | (0u << 16);
|
||||
// Physically contiguous, with completion interrupts disabled. The
|
||||
// queue is consumed synchronously by WaitCompletion().
|
||||
cmd.Cdw11 = (1u << 0);
|
||||
|
||||
CqEntry cqe;
|
||||
if (!AdminCommand(cmd, cqe)) {
|
||||
@@ -549,54 +547,6 @@ namespace Drivers::Storage::Nvme {
|
||||
return true;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Interrupt handler
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
static void HandleInterrupt(uint8_t irq) {
|
||||
(void)irq;
|
||||
// NVMe uses polling-based completion in this driver.
|
||||
// The interrupt handler just acknowledges the interrupt.
|
||||
// Completions are consumed in the polling loops above.
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// MSI setup
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
static bool SetupMsi(uint8_t bus, uint8_t dev, uint8_t func) {
|
||||
uint8_t cap = Pci::FindCapability(bus, dev, func, Pci::PCI_CAP_MSI);
|
||||
if (cap == 0) {
|
||||
KernelLogStream(INFO, "NVMe") << "MSI capability not found";
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
msgCtrl &= ~(0x70); // Single message
|
||||
msgCtrl |= (1 << 0); // MSI Enable
|
||||
Pci::LegacyWrite16(bus, dev, func, cap + 2, msgCtrl);
|
||||
|
||||
uint16_t pciCmd = Pci::LegacyRead16(bus, dev, func, (uint8_t)Pci::PCI_REG_COMMAND);
|
||||
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, "NVMe") << "MSI enabled: vector " << base::dec << (uint64_t)MSI_VECTOR;
|
||||
return true;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Probe (PCI driver entry point)
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -629,6 +579,7 @@ namespace Drivers::Storage::Nvme {
|
||||
|
||||
// Enable bus mastering and memory space
|
||||
Pci::EnableBusMaster(dev.Bus, dev.Device, dev.Function);
|
||||
Pci::DisableInterruptDelivery(dev.Bus, dev.Device, dev.Function);
|
||||
|
||||
// Read capabilities
|
||||
uint64_t cap = ReadReg64(REG_CAP);
|
||||
@@ -653,17 +604,9 @@ namespace Drivers::Storage::Nvme {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 2: Set up MSI
|
||||
bool hasMsi = SetupMsi(dev.Bus, dev.Device, dev.Function);
|
||||
if (!hasMsi) {
|
||||
uint8_t irqLine = Pci::LegacyRead8(dev.Bus, dev.Device, dev.Function,
|
||||
(uint8_t)Pci::PCI_REG_INTERRUPT);
|
||||
if (irqLine != 0xFF) {
|
||||
KernelLogStream(INFO, "NVMe") << "Using legacy IRQ " << base::dec << (uint64_t)irqLine;
|
||||
Hal::RegisterIrqHandler(irqLine, HandleInterrupt);
|
||||
Hal::IoApic::UnmaskIrq(Hal::IoApic::GetGsiForIrq(irqLine));
|
||||
}
|
||||
}
|
||||
// Step 2: keep PCI interrupt delivery disabled. Admin and I/O queues
|
||||
// are polled synchronously, so completion interrupts add latency and
|
||||
// can starve the lower-vector scheduler timer under sustained I/O.
|
||||
|
||||
// Step 3: Set up admin queues
|
||||
if (!SetupAdminQueues()) {
|
||||
|
||||
Reference in new issue
Block a user