Skip to content

Commit f63ce4b

Browse files
committed
more stuff
1 parent bb125d2 commit f63ce4b

7 files changed

Lines changed: 207 additions & 16 deletions

File tree

boot/bootdata/bootcd.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[FREELOADER]
2-
DefaultOS=LiveImg_Debug_Net
2+
DefaultOS=LiveImg_Debug
33
TimeOut=10
44

55
[Display]

drivers/bus/acpi_new/uacpiosl.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,8 +491,11 @@ UacpiQueryAcpiRootFromRegistry(_Out_ PHYSICAL_ADDRESS *OutRootTable)
491491
if (!NT_SUCCESS(Status))
492492
goto Exit;
493493

494-
/* Allocate enough to hold the longest subkey name (+ terminator) */
495-
Bytes = FullInfo->MaxNameLen + sizeof(WCHAR);
494+
/* Allocate enough to hold the KEY_BASIC_INFORMATION header plus the longest
495+
* subkey name (+ terminator). MaxNameLen counts only the name bytes, so the
496+
* fixed header (LastWriteTime/TitleIndex/NameLength, i.e. up to Name[]) must
497+
* be added; otherwise ZwEnumerateKey fails with STATUS_BUFFER_TOO_SMALL. */
498+
Bytes = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name) + FullInfo->MaxNameLen + sizeof(WCHAR);
496499
KeyInfo = ExAllocatePoolWithTag(PagedPool, Bytes, 'rAcu');
497500
if (!KeyInfo)
498501
{

drivers/bus/pci/pdo.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2370,7 +2370,12 @@ PdoStartDevice(
23702370
PciDevice->SlotNumber.u.AsULONG,
23712371
PciDevice->BusNumber);
23722372

2373-
PciProgramInterruptResource(PciDevice);
2373+
/*
2374+
* NB: do not program the capability here. An MSI-X table lives in
2375+
* the device's BAR memory, so it can only be written once Memory
2376+
* Space decoding is enabled below. Defer until after the command
2377+
* register is set up.
2378+
*/
23742379
}
23752380
else if (RawPartialDesc->Type == CmResourceTypeInterrupt)
23762381
{
@@ -2452,6 +2457,19 @@ PdoStartDevice(
24522457
DBGPRINT("None\n");
24532458
}
24542459

2460+
/*
2461+
* Now that Memory Space (and Bus Master) decoding is enabled, program the
2462+
* MSI/MSI-X capability. This must happen after the command register write:
2463+
* an MSI-X table is mapped from the device's BAR, and the message-address
2464+
* writes only reach the device once memory decoding is on. (MSI lives in
2465+
* config space and would work either way, but is harmless to defer too.)
2466+
*/
2467+
if (DeviceExtension->PciDevice->InterruptResource.Type == PciInterruptTypeMsi ||
2468+
DeviceExtension->PciDevice->InterruptResource.Type == PciInterruptTypeMsiX)
2469+
{
2470+
PciProgramInterruptResource(DeviceExtension->PciDevice);
2471+
}
2472+
24552473
return STATUS_SUCCESS;
24562474
}
24572475

drivers/storage/ide/pciidex/chipset/ahci_generic.c

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,19 @@ AtaAhciHbaFreeResouces(
548548
{
549549
PAGED_CODE();
550550

551-
if (Controller->InterruptObject)
551+
if (Controller->InterruptMessageTable)
552+
{
553+
IO_DISCONNECT_INTERRUPT_PARAMETERS Params;
554+
555+
Params.Version = CONNECT_MESSAGE_BASED;
556+
Params.ConnectionContext.InterruptMessageTable = Controller->InterruptMessageTable;
557+
IoDisconnectInterruptEx(&Params);
558+
Controller->InterruptMessageTable = NULL;
559+
560+
/* IoDisconnectInterruptEx freed the KINTERRUPT we aliased here */
561+
Controller->InterruptObject = NULL;
562+
}
563+
else if (Controller->InterruptObject)
552564
{
553565
IoDisconnectInterrupt(Controller->InterruptObject);
554566
Controller->InterruptObject = NULL;
@@ -729,6 +741,52 @@ AhciGetControllerProperties(
729741
/* Clear HBA interrupts */
730742
AHCI_HBA_WRITE(Controller->IoBase, HbaInterruptStatus, 0xFFFFFFFF);
731743

744+
/*
745+
* MSI/MSI-X interrupts must be connected through the message-based path.
746+
* The legacy IoConnectInterrupt() does not arm message-signalled delivery,
747+
* so the HBA would assert its interrupt but the ISR would never run.
748+
* Try the message-based path first (it locates any assigned MSI resource
749+
* from the PDO itself) and fall back to a line-based connection.
750+
*/
751+
{
752+
PFDO_DEVICE_EXTENSION FdoExt =
753+
CONTAINING_RECORD(Controller, FDO_DEVICE_EXTENSION, Controller);
754+
IO_CONNECT_INTERRUPT_PARAMETERS Params;
755+
756+
RtlZeroMemory(&Params, sizeof(Params));
757+
Params.Version = CONNECT_MESSAGE_BASED;
758+
Params.MessageBased.PhysicalDeviceObject = FdoExt->Pdo;
759+
Params.MessageBased.ConnectionContext.InterruptMessageTable =
760+
&Controller->InterruptMessageTable;
761+
Params.MessageBased.MessageServiceRoutine = AtaAhciHbaMessageIsr;
762+
Params.MessageBased.ServiceContext = Controller;
763+
Params.MessageBased.SpinLock = NULL;
764+
Params.MessageBased.SynchronizeIrql = 0;
765+
Params.MessageBased.FloatingSave = FALSE;
766+
Params.MessageBased.FallBackServiceRoutine = NULL;
767+
768+
Status = IoConnectInterruptEx(&Params);
769+
if (NT_SUCCESS(Status))
770+
{
771+
/*
772+
* Publish the message's KINTERRUPT as the controller interrupt object
773+
* so the existing per-port/atapi synchronization (which calls
774+
* KeAcquireInterruptSpinLock(Controller->InterruptObject)) keeps
775+
* working with the message-based connection. The HBA uses a single
776+
* MSI for all ports, so message 0's object covers the controller.
777+
*/
778+
Controller->InterruptObject =
779+
Controller->InterruptMessageTable->MessageInfo[0].InterruptObject;
780+
781+
INFO("Connected message-based interrupt: %lu message(s)\n",
782+
Controller->InterruptMessageTable->MessageCount);
783+
return STATUS_SUCCESS;
784+
}
785+
786+
WARN("Message-based connect failed (0x%lx), trying line-based\n", Status);
787+
Controller->InterruptMessageTable = NULL;
788+
}
789+
732790
Status = IoConnectInterrupt(&Controller->InterruptObject,
733791
AtaAhciHbaIsr,
734792
Controller,

drivers/storage/ide/pciidex/chipset/ahci_io.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,3 +427,19 @@ AtaAhciHbaIsr(
427427

428428
return TRUE;
429429
}
430+
431+
/*
432+
* Message-signalled (MSI/MSI-X) interrupt trampoline. The HBA shares a single
433+
* MSI for all ports, so the message id is irrelevant - just run the HBA ISR.
434+
*/
435+
BOOLEAN
436+
NTAPI
437+
AtaAhciHbaMessageIsr(
438+
_In_ PKINTERRUPT Interrupt,
439+
_In_ PVOID ServiceContext,
440+
_In_ ULONG MessageId)
441+
{
442+
UNREFERENCED_PARAMETER(MessageId);
443+
444+
return AtaAhciHbaIsr(Interrupt, ServiceContext);
445+
}

drivers/storage/ide/pciidex/pciidex.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ typedef struct _ATA_CONTROLLER
170170
{
171171
CM_PARTIAL_RESOURCE_DESCRIPTOR InterruptDesc;
172172
PKINTERRUPT InterruptObject;
173+
/* Set when the HBA interrupt is connected via the message-based (MSI/MSI-X) path. */
174+
PIO_INTERRUPT_MESSAGE_INFO InterruptMessageTable;
173175
struct
174176
{
175177
USHORT VendorID;
@@ -627,6 +629,7 @@ CHANNEL_PREPARE_IO AtaAhciPrepareIo;
627629
CHANNEL_PREPARE_PRD_TABLE AtaAhciPreparePrdTable;
628630
CHANNEL_ALLOCATE_SLOT AtaAhciAllocateSlot;
629631
KSERVICE_ROUTINE AtaAhciHbaIsr;
632+
KMESSAGE_SERVICE_ROUTINE AtaAhciHbaMessageIsr;
630633

631634
/* pata_generic.c *************************************************************/
632635

ntoskrnl/io/iomgr/irq.c

Lines changed: 104 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -169,25 +169,103 @@ IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
169169
ExFreePoolWithTag(IoInterrupt, TAG_IO_INTERRUPT);
170170
}
171171

172+
static PCM_PARTIAL_RESOURCE_DESCRIPTOR
173+
IopFindMessageInterruptDescriptor(
174+
_In_ PDEVICE_OBJECT PhysicalDeviceObject);
175+
static PCM_PARTIAL_RESOURCE_DESCRIPTOR
176+
IopFindMessageInterruptDescriptorEx(
177+
_In_ PDEVICE_OBJECT PhysicalDeviceObject,
178+
_In_ BOOLEAN Translated);
179+
172180
NTSTATUS
173181
IopConnectInterruptExFullySpecific(
174182
_Inout_ PIO_CONNECT_INTERRUPT_PARAMETERS Parameters)
175183
{
176184
NTSTATUS Status;
185+
ULONG Vector = Parameters->FullySpecified.Vector;
186+
KIRQL Irql = Parameters->FullySpecified.Irql;
187+
KIRQL SynchronizeIrql = Parameters->FullySpecified.SynchronizeIrql;
188+
KINTERRUPT_MODE Mode = Parameters->FullySpecified.InterruptMode;
189+
KAFFINITY Affinity = Parameters->FullySpecified.ProcessorEnableMask;
190+
PCM_PARTIAL_RESOURCE_DESCRIPTOR RawDesc;
177191

178192
PAGED_CODE();
179193

180-
/* Fallback to standard IoConnectInterrupt */
194+
/*
195+
* If the device was granted a message-signalled interrupt (MSI/MSI-X), the
196+
* caller passes the *translated* system vector, but the LAPIC actually
197+
* delivers the *raw* message vector that the bus driver programmed into the
198+
* device's MSI/MSI-X capability. IoConnectInterrupt() arms the IDT at the
199+
* vector it is given, so without remapping the IDT entry would never match
200+
* the delivered vector and the ISR would never run. Remap to the raw vector
201+
* (with its message IRQL and edge-triggered mode) before connecting.
202+
*
203+
* Win8's IoConnectInterruptEx resolves the same thing via the device's
204+
* interrupt connection data; we derive it from the raw/translated resource
205+
* lists the PnP manager assigned.
206+
*/
207+
RawDesc = IopFindMessageInterruptDescriptor(Parameters->FullySpecified.PhysicalDeviceObject);
208+
if (RawDesc != NULL)
209+
{
210+
ULONG RawBase = RawDesc->u.MessageInterrupt.Raw.Vector;
211+
ULONG Count = RawDesc->u.MessageInterrupt.Raw.MessageCount;
212+
BOOLEAN Remap = FALSE;
213+
214+
if (Count == 0)
215+
Count = 1;
216+
217+
if (Count == 1)
218+
{
219+
/*
220+
* Single message: the device delivers exactly one vector - the raw
221+
* message vector the bus driver programmed into the MSI/MSI-X
222+
* capability. The caller's translated vector belongs to a different
223+
* HAL domain and would arm the wrong IDT entry, so use the raw one.
224+
*/
225+
Vector = RawBase;
226+
Remap = TRUE;
227+
}
228+
else
229+
{
230+
/*
231+
* Multiple messages: map the caller's translated vector to the raw
232+
* message vector by its offset within the translated block.
233+
*/
234+
PCM_PARTIAL_RESOURCE_DESCRIPTOR TransDesc =
235+
IopFindMessageInterruptDescriptorEx(Parameters->FullySpecified.PhysicalDeviceObject, TRUE);
236+
if (TransDesc != NULL)
237+
{
238+
ULONG TransBase = TransDesc->u.MessageInterrupt.Translated.Vector;
239+
if (Vector >= TransBase && Vector < TransBase + Count)
240+
{
241+
Vector = RawBase + (Vector - TransBase);
242+
Remap = TRUE;
243+
}
244+
}
245+
}
246+
247+
if (Remap)
248+
{
249+
Irql = HalGetMessageVectorIrql((UCHAR)Vector);
250+
Mode = Latched; /* MSI/MSI-X are edge-triggered */
251+
Affinity = RawDesc->u.MessageInterrupt.Raw.Affinity;
252+
}
253+
}
254+
255+
/* KeInitializeInterrupt requires SynchronizeIrql >= the interrupt IRQL */
256+
if (SynchronizeIrql < Irql)
257+
SynchronizeIrql = Irql;
258+
181259
Status = IoConnectInterrupt(Parameters->FullySpecified.InterruptObject,
182260
Parameters->FullySpecified.ServiceRoutine,
183261
Parameters->FullySpecified.ServiceContext,
184262
Parameters->FullySpecified.SpinLock,
185-
Parameters->FullySpecified.Vector,
186-
Parameters->FullySpecified.Irql,
187-
Parameters->FullySpecified.SynchronizeIrql,
188-
Parameters->FullySpecified.InterruptMode,
263+
Vector,
264+
Irql,
265+
SynchronizeIrql,
266+
Mode,
189267
Parameters->FullySpecified.ShareVector,
190-
Parameters->FullySpecified.ProcessorEnableMask,
268+
Affinity,
191269
Parameters->FullySpecified.FloatingSave);
192270
if (!NT_SUCCESS(Status))
193271
DPRINT1("IopConnectInterruptExFullySpecific() failed: 0x%lx\n", Status);
@@ -249,20 +327,27 @@ IopFreeMsiInterrupts(
249327
*/
250328
static
251329
PCM_PARTIAL_RESOURCE_DESCRIPTOR
252-
IopFindMessageInterruptDescriptor(
253-
_In_ PDEVICE_OBJECT PhysicalDeviceObject)
330+
IopFindMessageInterruptDescriptorEx(
331+
_In_ PDEVICE_OBJECT PhysicalDeviceObject,
332+
_In_ BOOLEAN Translated)
254333
{
255334
PDEVICE_NODE DeviceNode;
256335
PCM_RESOURCE_LIST ResourceList;
257336
PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
258337
ULONG i, j;
259338

260339
DeviceNode = IopGetDeviceNode(PhysicalDeviceObject);
261-
if (!DeviceNode || !DeviceNode->ResourceList)
340+
if (!DeviceNode)
341+
return NULL;
342+
343+
/*
344+
* The raw list carries the MessageInterrupt.Raw form (base vector + count);
345+
* the translated list carries MessageInterrupt.Translated (system vector).
346+
*/
347+
ResourceList = Translated ? DeviceNode->ResourceListTranslated : DeviceNode->ResourceList;
348+
if (!ResourceList)
262349
return NULL;
263350

264-
/* The raw list carries the MessageInterrupt.Raw form (base vector + count) */
265-
ResourceList = DeviceNode->ResourceList;
266351
FullDescriptor = &ResourceList->List[0];
267352

268353
for (i = 0; i < ResourceList->Count; i++)
@@ -286,6 +371,14 @@ IopFindMessageInterruptDescriptor(
286371
return NULL;
287372
}
288373

374+
static
375+
PCM_PARTIAL_RESOURCE_DESCRIPTOR
376+
IopFindMessageInterruptDescriptor(
377+
_In_ PDEVICE_OBJECT PhysicalDeviceObject)
378+
{
379+
return IopFindMessageInterruptDescriptorEx(PhysicalDeviceObject, FALSE);
380+
}
381+
289382
NTSTATUS
290383
IopConnectInterruptExMessageBased(
291384
_Inout_ PIO_CONNECT_INTERRUPT_PARAMETERS Parameters)

0 commit comments

Comments
 (0)