title: PCI Message Signaled Interrupts not working (edit : not working only on QEMU)
body: <p>I tried to implement MSI Support from &quot;osdev/PCI&quot; page, I use APIC And IOAPIC To route interrupts, I was also working on parsing the AML And everything is good to now but the device does not generate MSI Interrupts on QEMU nor on my Primary Computer, however it does on a second Laptop (Booted in LEGACY BIOS Mode). Here is the code for MSI Enabling :</p>
  <pre><code>if(PciStatus &amp; PCI_STATUS_CAPABILITES_LIST) {
          // Capabilites Supported
          UINT16 CapOffset = PciDeviceConfigurationRead16(Device, PCI_CAPABILITIES_PTR);
          UINT16 _caphdr = PciDeviceConfigurationRead16(Device, CapOffset);
          PCI_CAPABILITY_HEADER* CapabilityHeader = (PCI_CAPABILITY_HEADER*)&amp;_caphdr;
          DWORD CapBuffer[0x10] = {0};
          for(;;) {
              if(CapabilityHeader-&gt;CapabilityId == PCI_CAPABILITY_ID_MSI) {
  
                  // Copy capability buffer
  
                  for(UINT i = 0;i&lt;sizeof(PCI_MSI_CAPABILITY) &gt;&gt; 2;i++){
                      CapBuffer[i] = PciDeviceConfigurationRead32(Device, CapOffset + (i &lt;&lt; 2));
                  }
                  PCI_MSI_CAPABILITY* Msi = (PCI_MSI_CAPABILITY*)CapBuffer;
                  
                  UINT8 MsiSystemVector = 0x32; // Just for Test
  
  
                  UINT64 WriteBytes = 0;
  
                  if(Msi-&gt;MessageControl.x64AddressCapable) {
                      PCI_MSI_CAPABILITY_64BIT* MsiX64 = (PCI_MSI_CAPABILITY_64BIT*)CapBuffer;
                      WriteBytes = sizeof(PCI_MSI_CAPABILITY_64BIT) - sizeof(PCI_CAPABILITY_HEADER);
                      MsiX64-&gt;MessageData = MsiSystemVector;
                      MsiX64-&gt;MessageAddress = (UINT64)LocalApicPhysicalAddress;
                      MsiX64-&gt;MessageControl.MsiEnable = 1;
                      MsiX64-&gt;Mask = 1;
                      MsiX64-&gt;MessageControl.MultipleMessageEnable = 0;
                  _RT_SystemDebugPrint(L&quot;PCI : MSI64 Capability MSG_CONTROL : %x, MessageAddress : %x, MSG_DATA : %x&quot;, *(UINT64*)&amp;MsiX64-&gt;MessageControl, (UINT64)MsiX64-&gt;MessageAddress, (UINT64)MsiX64-&gt;MessageData);
  
                  } else {
                      WriteBytes = sizeof(PCI_MSI_CAPABILITY) - sizeof(PCI_CAPABILITY_HEADER);
  
                      Msi-&gt;MessageData = MsiSystemVector;// | (3 &lt;&lt; 14);
                      Msi-&gt;MessageAddress = (UINT64)LocalApicPhysicalAddress;
                      Msi-&gt;MessageControl.MsiEnable = 1;
                      Msi-&gt;Mask = 0;
                      Msi-&gt;MessageControl.MultipleMessageEnable = 0;
  
                  _RT_SystemDebugPrint(L&quot;PCI : MSI Capability MSG_CONTROL : %x, MessageAddress : %x, MSG_DATA : %x&quot;, *(UINT64*)&amp;Msi-&gt;MessageControl, (UINT64)Msi-&gt;MessageAddress, (UINT64)Msi-&gt;MessageData);
  
                  }
  
                  
                  // Some writing stuff (Everything gets written properly)
              
                  UINT64 NumDwords = WriteBytes &gt;&gt; 2;
                  UINT64 Remaining = WriteBytes &amp; 3;
                  char* tmp = (char*)Msi;
                  tmp+=sizeof(PCI_CAPABILITY_HEADER);
                  for(UINT i = 0;i&lt;NumDwords;i++, tmp+=4) {
                      PciDeviceConfigurationWrite32(Device, *(UINT32*)tmp, CapOffset + (i &lt;&lt; 2) + sizeof(PCI_CAPABILITY_HEADER));
                  }
                  for(UINT i = 0;i&lt;Remaining;i++, tmp++) {
                      PciDeviceConfigurationWrite8(Device, *tmp, CapOffset + ((i + NumDwords) &lt;&lt; 2) + sizeof(PCI_CAPABILITY_HEADER));
                  }
                  for(UINT i = 0;i&lt;sizeof(PCI_MSI_CAPABILITY) &gt;&gt; 2;i++){
                      CapBuffer[i] = PciDeviceConfigurationRead32(Device, CapOffset + (i &lt;&lt; 2));
                  }
                  
                  if(Msi-&gt;MessageControl.x64AddressCapable) {
                      PCI_MSI_CAPABILITY_64BIT* MsiX64 = (PCI_MSI_CAPABILITY_64BIT*)CapBuffer;
                  _RT_SystemDebugPrint(L&quot;PCI (RESULT) : MSI64 Capability MSG_CONTROL : %x, MessageAddress : %x, MSG_DATA : %x&quot;, *(UINT64*)&amp;MsiX64-&gt;MessageControl, (UINT64)MsiX64-&gt;MessageAddress, (UINT64)MsiX64-&gt;MessageData);
  
                  } else {
                  _RT_SystemDebugPrint(L&quot;PCI (RESULT) : MSI Capability MSG_CONTROL : %x, MessageAddress : %x, MSG_DATA : %x&quot;, *(UINT64*)&amp;Msi-&gt;MessageControl, (UINT64)Msi-&gt;MessageAddress, (UINT64)Msi-&gt;MessageData);
  
                  }
              } else if(CapabilityHeader-&gt;CapabilityId == PCI_CAPABILITY_ID_MSI_X) {
                  _RT_SystemDebugPrint(L&quot;MSI-X Supported&quot;);
                  while(1);
              }
              if(!CapabilityHeader-&gt;NextPointer) break;
              CapOffset = CapabilityHeader-&gt;NextPointer;
              _caphdr = PciDeviceConfigurationRead16(Device, CapOffset);
          }
      }
  </code></pre>
  <p>For more information : The kernel is a 64 bit (X86_64) Relocatable PE Executable made from scratch without any library and not based on any OS(unix, NT...) , I recently created a program that formats drive with FAT32 and copy files and puts My bootsector &amp; bootmanager on it. The kernel runs in APIC ACPI Mode, it has a multiprocessor preemptive priority schedulling mechanism, one TSS &amp; GDT Per processor. I am currently working on EHCI &amp; AHCI Drivers and I needed interrupts so I was parsing the ACPI AML ( not finished), and now I'm trying MSI before I parse that AML.</p>