Msg and MsgD — why messages exist, the 4DW header in full detail, all six routing codes, INTx interrupt signalling, power management messages, error messages, slot power limit, vendor-defined messages, LTR, OBFF, and how all of this carries forward unchanged into Gen 6.
PCI used physical sideband wires for interrupts (INTA#–INTD#), power management events (PME#), system error (SERR#), parity error (PERR#), and slot signals. These wires had to be routed across every board, every connector, and every bridge — a wiring nightmare that grew worse with every additional slot.
PCIe eliminated those sideband wires entirely. Every signal that PCI carried on a dedicated pin is now carried as an in-band Message TLP. This means the PCIe fabric itself delivers interrupts, error reports, power events, and hot-plug notifications — using the same differential pair infrastructure that carries data.
There are two Message TLP types. Both share the same 4DW header. The only difference is whether a data payload follows.
| Name | Fmt | Type bits [4:3] | Type bits [2:0] | Data payload? | Used for |
|---|---|---|---|---|---|
| Msg | 001 | 10 | rrr (routing) | No | INTx, PME, errors, unlock, hot-plug, LTR, OBFF |
| MsgD | 011 | 10 | rrr (routing) | Yes — 1 DW | Set Slot Power Limit, Vendor-Defined with data |
Type bits [4:3] are always 10 for all messages. Type bits [2:0] — the routing sub-field — vary by message group and determine how every switch in the fabric routes this TLP. The Message Code in DW1 byte 7 identifies the specific message type within the group.
Messages always use the 4DW (16-byte) header. The extra DW compared to memory TLPs is needed because bytes 8–15 carry message-specific data (target address for address routing, target BDF for ID routing, or message-specific payload fields).
The 3-bit routing sub-field in Type bits [2:0] determines how every switch handles this Message TLP. Unlike address routing (used by memory TLPs) or ID routing (used by completions), Message routing can be implicit — requiring no address or BDF lookup at all.
The Message Code is an 8-bit field in DW1 byte 7. Combined with the routing sub-field, it uniquely identifies every defined Message type. The top 4 bits group messages by category; the lower 4 bits identify the specific message within that group.
| Code range | Group | Routing |
|---|---|---|
| 0000 0000 | Unlock (locked transaction release) | 011 — Broadcast from RC |
| 0001 0000 | LTR — Latency Tolerance Reporting | 100 — Local |
| 0001 0010 | OBFF — Optimized Buffer Flush/Fill | 100 — Local |
| 0001 0100 | PM_Active_State_Nak | 100 — Local |
| 0001 1000 | PM_PME — Power Management Event | 000 — To RC |
| 0001 1001 | PM_Turn_Off | 011 — Broadcast from RC |
| 0001 1011 | PME_TO_Ack — Acknowledge Turn-Off | 101 — Gather to RC |
| 0010 0000–0010 0011 | Assert_INTA/B/C/D | 100 — Local |
| 0010 0100–0010 0111 | Deassert_INTA/B/C/D | 100 — Local |
| 0011 0000 | ERR_COR — Correctable Error | 000 — To RC |
| 0011 0001 | ERR_NONFATAL — Uncorrectable Non-Fatal | 000 — To RC |
| 0011 0011 | ERR_FATAL — Uncorrectable Fatal | 000 — To RC |
| 0100 xxxx | Ignored Messages (legacy hot-plug, deprecated) | 100 — Local |
| 0101 0000 | Set_Slot_Power_Limit | 100 — Local |
| 0111 1110 | Vendor-Defined Message Type 0 | 000/010/011/100 |
| 0111 1111 | Vendor-Defined Message Type 1 | 000/010/011/100 |
INTx messages replace the four physical interrupt pins (INTA#–INTD#) of PCI. They emulate the level-sensitive behaviour of those pins: Assert to signal interrupt pending, Deassert to signal interrupt serviced.
| INTx Message | Code [7:0] | Routing |
|---|---|---|
| Assert_INTA | 0010 0000 | 100 — Local |
| Assert_INTB | 0010 0001 | 100 — Local |
| Assert_INTC | 0010 0010 | 100 — Local |
| Assert_INTD | 0010 0011 | 100 — Local |
| Deassert_INTA | 0010 0100 | 100 — Local |
| Deassert_INTB | 0010 0101 | 100 — Local |
| Deassert_INTC | 0010 0110 | 100 — Local |
| Deassert_INTD | 0010 0111 | 100 — Local |
Power management messages coordinate link power state transitions between devices and the Root Complex. They replace the physical PME# pin of PCI.
| PM Message | Code [7:0] | Routing | Meaning |
|---|---|---|---|
| PM_Active_State_Nak | 0001 0100 | 100 — Local | Downstream port declined a request to enter L1 ASPM. No data, TC=0. |
| PM_PME | 0001 1000 | 000 — To RC | Device has wake event and requests power-on. Sent upstream to RC. |
| PM_Turn_Off | 0001 1001 | 011 — Broadcast | RC broadcasts power-down request to all downstream devices. |
| PME_TO_Ack | 0001 1011 | 101 — Gather to RC | Endpoint acknowledges PM_Turn_Off. Switch gathers all from downstream before forwarding. |
Error messages are how PCIe devices tell the Root Complex about protocol errors. They travel upstream using routing code 000 (to Root Complex) and identify the reporting device in the Requester ID field.
| Message | Code [7:0] | Routing | Severity | When sent |
|---|---|---|---|---|
| ERR_COR | 0011 0000 | 000 — To RC | Correctable | Error detected and corrected in hardware — link replay succeeded, ECC corrected, etc. No data lost. RC logs it in AER registers. |
| ERR_NONFATAL | 0011 0001 | 000 — To RC | Uncorrectable, non-fatal | Error could not be corrected but the link/device is still functional. Possible loss of a transaction. RC may attempt recovery. |
| ERR_FATAL | 0011 0011 | 000 — To RC | Uncorrectable, fatal | Error is unrecoverable — link or device may be in an unknown state. RC typically resets the link. System may need reboot. |
The Unlock Message is the termination signal for a locked transaction sequence (MRdLk). When a device sends MRdLk, every switch along the path locks VC0 to prevent other requesters from using it. The Unlock Message releases those locks across the entire path.
| Field | Value |
|---|---|
| Message Code | 0000 0000 |
| Routing | 011 — Broadcast from RC (RC sends it downstream, switches forward to all ports) |
| TC | TC=0 required |
| Data payload | None — Length field reserved |
| Sent by | Root Complex, after receiving the final CplDLk from the locked transaction |
This MsgD (message with data) informs a card in a slot of its physical power budget. The device stores this limit in its Device Capabilities Register and must not draw more power than specified without explicit software permission.
| Field | Value |
|---|---|
| Message Code | 0101 0000 |
| Routing | 100 — Local (consumed by the receiving card; not forwarded) |
| TC | TC=0 required |
| Data payload | 1 DW — lower 10 bits encode the power limit with scale factor; upper bits must be zero |
| Sent by | Downstream port of RC or Switch, automatically when link enters DL_Active or when Slot Capabilities Register is written |
| Card behaviour | If card already draws less than the limit, it may ignore this message |
Vendor-Defined Messages (VDM) allow companies to define proprietary message types for features not covered by the PCIe spec. The header includes a Vendor ID field in DW2 bytes 10–11 that disambiguates messages from different vendors sharing the same code range.
| Property | VDM Type 0 (0x7E) | VDM Type 1 (0x7F) |
|---|---|---|
| Code | 0111 1110 | 0111 1111 |
| Routing options | 000, 010, 011, 100 | 000, 010, 011, 100 |
| Unrecognised by receiver | UR error condition | Silent discard — no error |
| Attr bits | Not reserved — all three Attr bits usable | Not reserved — all three Attr bits usable |
| Data payload | Optional (Msg or MsgD) | Optional (Msg or MsgD) |
| Vendor disambiguation | Vendor ID field in DW2 bytes 10–11 — must match a PCI-SIG assigned Vendor ID | |
LTR Messages allow an endpoint to inform the platform of its acceptable service latency — how long it can tolerate waiting before the platform must respond to a read or write. The platform uses this information to optimise power management decisions: if all devices can tolerate long latencies, the platform can enter deeper sleep states between transactions.
| Field | Value |
|---|---|
| Message Code | 0001 0000 |
| Routing | 100 — Local (terminate at receiving port) |
| TC | TC=0 required |
| Data | No payload — Length reserved (DW2/DW3 carry Snoop Latency and No-Snoop Latency fields) |
| Requester ID | Must be set to the transmitting port’s own ID |
| When sent | When a device’s latency requirements change, e.g. after entering/exiting active DMA mode |
The LTR header differs slightly from the standard message layout: DW2 carries the Snoop Latency field and DW3 carries the No-Snoop Latency field, each encoding a latency value with a scale factor (1 ns, 32 ns, 1024 ns, or 32768 ns).
OBFF Messages allow the platform to communicate its current power state and activity hint to endpoints. Endpoints use this hint to optimise their DMA behaviour — for example, flushing their transmit buffers when the platform signals it is about to enter a low-power state, rather than waiting until a full DMA burst is assembled.
| Field | Value |
|---|---|
| Message Code | 0001 0010 |
| Routing | 100 — Local |
| TC | TC=0 required |
| Data payload | No payload — DW3 carries the OBFF Code field indicating platform state |
| Sent by | Root Complex or switch, downstream to endpoint |
| Requester ID | Must be the transmitting port’s ID |
The Message TLP format — header layout, routing codes, message codes, and all rules — is completely unchanged in Gen 6. Message TLPs are packed into Gen 6 flits the same way any other TLP is. From the Transaction Layer’s perspective, nothing has changed.
| Item | Value / Rule |
|---|---|
| Msg — Fmt, Type | Fmt=001 · Type=1_0rrr · no data · 16 bytes header |
| MsgD — Fmt, Type | Fmt=011 · Type=1_0rrr · 1 DW data · 16 bytes header |
| Posted? | Yes — all messages are posted. No completion ever returns. |
| Tag field | Always 0x00 — no completion, no tag needed |
| TC requirement | TC=0 required for most messages. Violations → Malformed TLP. |
| DW1 Byte 7 | Message Code — 8 bits identifying the specific message type |
| Routing 000 | Implicit → Root Complex. Each switch forwards upstream. Used by PME, ERR_* |
| Routing 001 | Address routing — DW2/DW3 carry 64-bit target address |
| Routing 010 | ID routing — DW2 bytes 8–9 carry target BDF |
| Routing 011 | Broadcast from RC. Switch duplicates to all downstream ports. Used by PM_Turn_Off, Unlock |
| Routing 100 | Local — terminate at receiver. Switch consumes and re-sends with own Req ID. Used by INTx |
| Routing 101 | Gather to Root. Switch waits for all downstream ports before forwarding one. Used by PME_TO_Ack |
| INTx Assert | Codes 0x20–0x23 · Routing 100 · TC=0 · no data |
| INTx Deassert | Codes 0x24–0x27 · Routing 100 · TC=0 · no data |
| PM_PME | Code 0x18 · Routing 000 · device wakeup request to RC |
| PM_Turn_Off | Code 0x19 · Routing 011 · RC broadcasts power-down |
| PME_TO_Ack | Code 0x1B · Routing 101 · endpoint acks power-down · gathered at switches |
| ERR_COR | Code 0x30 · Routing 000 · correctable error notification to RC |
| ERR_NONFATAL | Code 0x31 · Routing 000 · uncorrectable non-fatal |
| ERR_FATAL | Code 0x33 · Routing 000 · uncorrectable fatal |
| Unlock | Code 0x00 · Routing 011 · RC broadcasts to release MRdLk locks |
| Set Slot Power Limit | Code 0x50 · Routing 100 · MsgD with 1DW power limit payload |
| VDM Type 0 | Code 0x7E · Unknown receiver → UR error |
| VDM Type 1 | Code 0x7F · Unknown receiver → silent discard |
| LTR | Code 0x10 · Routing 100 · endpoint reports acceptable latency to platform |
| OBFF | Code 0x12 · Routing 100 · platform hints power state to endpoint |
| Gen 6 impact | Zero on header format — same 4DW header, same routing codes, same message codes. FEC reduces ERR_COR volume. FRS and CXL VDMs are new message codes with same structure. |