PCI: Difference between revisions

2,839 bytes added ,  3 years ago
→‎Message Signaled Interrupts: Add MSI-X and finish MSI
[unchecked revision][unchecked revision]
(→‎Message Signaled Interrupts: Created message signalled interrupts section)
(→‎Message Signaled Interrupts: Add MSI-X and finish MSI)
Line 1,086:
 
== Message Signaled Interrupts ==
{{In Progress}}
Message Signaled Interrupts, or MSI, have been supported since PCI v2.2. However, support for them is ''mandatory'' in PCIe devices, so you can be sure that they're usable on modern hardware.
 
Use of MSI and MSI-X are mutually exclusive.
 
=== Enabling MSI ===
Line 1,118 ⟶ 1,119:
| cap+04
| cap+10
| colspan="4" | [Mask]
|-
| cap+05
| cap+14
| colspan="4" | [Pending]
|}
 
Line 1,125 ⟶ 1,130:
{| {{wikitable}}
|-
! Bit 15-9 !! Bit 8 !! Bit 7 !! Bit 6-4 !! Bit 3-1 !! Bit 0
|-
| Reserved
| Per-vector masking
| 64 bit
| Multiple Message Enable
Line 1,143 ⟶ 1,149:
</source>
MSI interrupts seem to be invariably edge triggered high.
 
'''Multiple messages:'''
{| {{wikitable}}
|-
! MME / MMI !! Interrupts
|-
| 000 || 1
|-
| 001 || 2
|-
| 010 || 4
|-
| 011 || 8
|-
| 100 || 16
|-
| 101 || 32
|}
 
In MME, specifies the number of low bits of Message Data that may be modified by the device.
 
Therefore, the interrupt vector block allocated must be aligned accordingly.
 
'''Interrupt masking'''
 
If capable, you can mask individual messages by setting the corresponding bit (1<<x), in the mask register.
 
If a message is pending, then the corresponding bit in the pending register is set.
 
Note that the PCI specification doesn't specify the location of these registers if the message address is 32 bit. This is because a function that supports masking is required to implement 64 bit addressing!
 
=== Enabling MSI-X ===
Like for MSI, you have to find the MSI-X capability, but the ID for MSI-X is '''0x11'''
 
The structure is as follows:
{| {{wikitable}}
|-
! register !! offset !! bits 31-24 !! bits 23-16 !! bits 15-8 !! bits 7-3 !! bits 2-0
|-
| cap+00
| cap+00
| colspan="2" | Message Control
| Next ptr
| colspan="2" | Capability ID = 11
|-
| cap+01
| cap+04
| colspan="5" | Message Upper Address
|-
| cap+02
| cap+08
| colspan="4" | Table Offset
| colspan="1" | BIR
|}
 
Unlike MSI, MSI-X supports 2048 interrupts. This is achieved by maintaining a table of interrupts in the PCI device's address space. The wording of the PCI 3.0 spec indicates that this ''must'' be via a Memory BAR.
 
'''BIR''' specifies which BAR is used for the Message Table. This may be a 64 bit BAR, and is zero-indexed (so BIR=0, BAR0, offset 10h into the header).
 
'''Table Offset''' is an offset into that BAR where the Message Table lives. Note that it is 8 byte aligned - so simply mask BIR.
 
The format of Message Control is as follows:
{| {{wikitable}}
|-
! Bit 15 !! Bit 14-11 !! Bit 10-0
|-
| Enable
| Reserved
| Table Size
|}
 
'''Table Size''' is N-1 encoded, and is the number of entries in the MSI-X table. This field is Read-Only.
 
Now you have all the information you need to find the MSI-X table:
{| {{wikitable}}
|-
! Bit 63-32 !! Bit 31-0
|-
| Message Address (0)
| Message Data (0)
|-
| Message Address (1)
| Message Data (1)
|-
| ...
| ...
|-
| Message Address (N-1)
| Message Data (N-1)
|}
 
Note that '''Message Address''' is as follows:
{| {{wikitable}}
|-
! Bit 31-2 !! Bit 1 !! Bit 0
|-
| Address
| Mask
| Pending
|}
Address is DWORD-aligned, so, again, mask the low bits. The interrupt is masked if Mask is set to 1. Pending is read-only.
 
Message Address and Data are as they were for MSI - architecture specific. However, unlike with MSI, you can specify independent vectors for all the interrupts, only limited by having the same upper 32 bit message address.
 
== Multifunction Devices ==
Anonymous user