PCIe Series — PCIe-09: Message TLPs — VLSI Trainers
PCIe Series · PCIe-09

Message TLPs

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.

📋 Why Message TLPs Exist

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.

PCI Sideband Wires → PCIe Message TLPs PCI — Physical Sideband Wires INTA# INTB# INTC# INTD# PME# · SERR# · PERR# PRSNT1# PRSNT2# (hot plug) Dedicated pins · routed on every board PCIe replaces PCIe — In-band Message TLPs Assert_INTx / Deassert_INTx (INTx emulation) PM_PME · ERR_COR · ERR_NONFATAL · ERR_FATAL Attention_Button_Pressed (hot plug) All carried over the same diff pairs as data
Figure 1 — PCI used dedicated sideband wires for every system signal. PCIe carries all of these as in-band Message TLPs over the same PCIe link, eliminating all sideband wiring. The PCIe fabric routes Message TLPs using one of six routing methods depending on the message type.

📋 Msg vs MsgD — Two TLP Types

There are two Message TLP types. Both share the same 4DW header. The only difference is whether a data payload follows.

NameFmtType 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 are posted — no completion returns. Like MWr, Message TLPs are posted. No CplD or Cpl will ever come back for a Message. This means the sender cannot know whether the message was received or acted upon at the final destination. For error messages and interrupts this is acceptable — the RC processes them asynchronously and software handles the resulting events.

📋 Routing Sub-field — Six Codes

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.

Six Message Routing Codes — Type bits [2:0] 000 — Routed to Root Complex Every switch forwards upstream. RC is always upstream of everything. No address or BDF comparison needed. Used by: PME, ERR_* messages 001 — Routed by Address Uses address in DW2–DW3. Switch compares to Base/Limit regs. Same lookup as memory address routing. Used by: some Vendor-Defined messages 010 — Routed by ID Target BDF in DW2 bytes 8–9. Switch uses Secondary/Subordinate bus range — same as Config ID routing. Used by: some Vendor-Defined messages 011 — Broadcast from RC RC broadcasts downstream. Switch duplicates to all downstream ports simultaneously. Used by: PM_Turn_Off, Unlock 100 — Local (Terminate Here) Message consumed by the receiving port. Not forwarded to any other port. Allows switch to remap interrupt pins. Used by: INTx, Slot Power, LTR, OBFF 101 — Gather to Root Forwarded upstream. Switch with multiple downstream ports waits for all ports before forwarding. Used by: PME_TO_Ack
Figure 3 — Six routing codes embedded in Type bits [2:0]. Code 000 (to RC) and 011 (broadcast from RC) are implicit — no address or BDF lookup needed. Code 100 (Local) means consume here. Code 101 (Gather) means wait for all downstream ports before forwarding. Codes 001 and 010 use the same address/ID logic as memory TLPs.

📋 Message Code Field (DW1 Byte 7)

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 rangeGroupRouting
0000 0000Unlock (locked transaction release)011 — Broadcast from RC
0001 0000LTR — Latency Tolerance Reporting100 — Local
0001 0010OBFF — Optimized Buffer Flush/Fill100 — Local
0001 0100PM_Active_State_Nak100 — Local
0001 1000PM_PME — Power Management Event000 — To RC
0001 1001PM_Turn_Off011 — Broadcast from RC
0001 1011PME_TO_Ack — Acknowledge Turn-Off101 — Gather to RC
0010 0000–0010 0011Assert_INTA/B/C/D100 — Local
0010 0100–0010 0111Deassert_INTA/B/C/D100 — Local
0011 0000ERR_COR — Correctable Error000 — To RC
0011 0001ERR_NONFATAL — Uncorrectable Non-Fatal000 — To RC
0011 0011ERR_FATAL — Uncorrectable Fatal000 — To RC
0100 xxxxIgnored Messages (legacy hot-plug, deprecated)100 — Local
0101 0000Set_Slot_Power_Limit100 — Local
0111 1110Vendor-Defined Message Type 0000/010/011/100
0111 1111Vendor-Defined Message Type 1000/010/011/100

📋 INTx — Interrupt Signalling

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 Virtual Wire — Assert / Deassert Sequence Endpoint Interrupt fires needs service ISR complete sends Deassert Switch Routing=Local(100) Consumes INTx May remap pin (INTA→INTB etc) Re-sends upstream with own Req ID Root Complex Receives Assert_INTA Raises system interrupt CPU runs ISR Receives Deassert Clears interrupt signal Assert_INTA Code=0x20 · Local Assert_INTA (re-sent) Req ID = Switch upstream port Deassert_INTA Code=0x24 · Local Deassert_INTA (re-sent) In practice: MSI or MSI-X preferred for new designs — INTx emulation is a legacy compatibility feature
Figure 4 — INTx virtual wire emulation. Routing=Local (100) means each switch terminates the message and re-transmits it upstream with its own Requester ID (enabling interrupt pin remapping). The RC converts the final Assert into a system interrupt. Deassert clears it. Both messages carry no data payload (Msg, Length=0).

INTx rules from the spec (Table 5-9)

INTx MessageCode [7:0]Routing
Assert_INTA0010 0000100 — Local
Assert_INTB0010 0001100 — Local
Assert_INTC0010 0010100 — Local
Assert_INTD0010 0011100 — Local
Deassert_INTA0010 0100100 — Local
Deassert_INTB0010 0101100 — Local
Deassert_INTC0010 0110100 — Local
Deassert_INTD0010 0111100 — Local

📋 Power Management Messages

Power management messages coordinate link power state transitions between devices and the Root Complex. They replace the physical PME# pin of PCI.

PM_Turn_Off / PME_TO_Ack — Power-Down Handshake Root Complex System wants to power down Waits for all PME_TO_Acks before D3 Switch Receives PM_Turn_Off Broadcasts to all downstream ports Gathers all PME_TO_Acks then forwards one Endpoints Each receives PM_Turn_Off Prepares for power-down Each sends PME_TO_Ack upstream (code=0x1B) PM_Turn_Off 011-Broadcast PM_Turn_Off broadcast to all ports PME_TO_Ack (gathered) PME_TO_Ack (one)
Figure 5 — PM_Turn_Off / PME_TO_Ack power-down handshake. RC broadcasts PM_Turn_Off (code 011, Broadcast). Every endpoint receives it, prepares for power-down, and sends PME_TO_Ack (code 101, Gather). Switches gather all PME_TO_Acks from all downstream ports before forwarding a single combined one upstream. The RC powers down only after receiving the gathered ack.
PM MessageCode [7:0]RoutingMeaning
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 Signalling Messages

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.

MessageCode [7:0]RoutingSeverityWhen 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.
ERR_FATAL does not stop message propagation. Even in a fatal error condition, the device must attempt to send ERR_FATAL upstream. The message travels on the potentially-failing link using whatever reliability remains. If the link is so badly broken that the message cannot be sent, the RC typically detects the link failure through other means (link down, timeout on LTSSM, loss of ACK/NAK).

📋 Unlock Message

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.

FieldValue
Message Code0000 0000
Routing011 — Broadcast from RC (RC sends it downstream, switches forward to all ports)
TCTC=0 required
Data payloadNone — Length field reserved
Sent byRoot Complex, after receiving the final CplDLk from the locked transaction
Unlock is broadcast — not targeted. The RC sends one Unlock message that propagates to every device in the fabric. Every switch that was holding a lock on VC0 releases it. This is intentional — the lock may span multiple hops and the RC may not know exactly which path was locked without tracking the entire fabric topology at runtime.

📋 Set Slot Power Limit

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.

FieldValue
Message Code0101 0000
Routing100 — Local (consumed by the receiving card; not forwarded)
TCTC=0 required
Data payload1 DW — lower 10 bits encode the power limit with scale factor; upper bits must be zero
Sent byDownstream port of RC or Switch, automatically when link enters DL_Active or when Slot Capabilities Register is written
Card behaviourIf card already draws less than the limit, it may ignore this message

📋 Vendor-Defined Messages

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.

Vendor-Defined Message Header — DW2 and DW3 Layout Code=0x7E (Type 0) or 0x7F (Type 1) · DW0 and DW1 identical to standard message header Byte 8 Byte 9 Byte 10 Byte 11 Target BDF Bytes 8–9 Used only if ID routing (010) Reserved Bytes 10–9 when no ID routing Vendor ID [15:0] Bytes 10–11 · PCI-SIG assigned vendor ID Distinguishes vendors sharing 0x7E/0x7F codes DW2 Byte 12 Byte 13 Byte 14 Byte 15 Vendor-Defined Data — Bytes 12–15 Content is entirely defined by the vendor identified in the Vendor ID field DW3 VDM Type 0 (Code=0x7E) Unknown receiver → Unsupported Request error VDM Type 1 (Code=0x7F) Unknown receiver → silently discard (no error)
Figure 6 — Vendor-Defined Message header. DW2 carries the Target BDF (if ID routing) and the Vendor ID that identifies the manufacturer. DW3 is entirely vendor-defined. Type 0 VDMs generate a UR error at unrecognising receivers; Type 1 VDMs are silently discarded, making them safe for broadcast scenarios where not all devices are expected to recognise them.
PropertyVDM Type 0 (0x7E)VDM Type 1 (0x7F)
Code0111 11100111 1111
Routing options000, 010, 011, 100000, 010, 011, 100
Unrecognised by receiverUR error conditionSilent discard — no error
Attr bitsNot reserved — all three Attr bits usableNot reserved — all three Attr bits usable
Data payloadOptional (Msg or MsgD)Optional (Msg or MsgD)
Vendor disambiguationVendor ID field in DW2 bytes 10–11 — must match a PCI-SIG assigned Vendor ID

📋 Latency Tolerance Reporting (LTR)

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.

FieldValue
Message Code0001 0000
Routing100 — Local (terminate at receiving port)
TCTC=0 required
DataNo payload — Length reserved (DW2/DW3 carry Snoop Latency and No-Snoop Latency fields)
Requester IDMust be set to the transmitting port’s own ID
When sentWhen 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 — Optimized Buffer Flush and Fill

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.

FieldValue
Message Code0001 0010
Routing100 — Local
TCTC=0 required
Data payloadNo payload — DW3 carries the OBFF Code field indicating platform state
Sent byRoot Complex or switch, downstream to endpoint
Requester IDMust be the transmitting port’s ID

Message TLPs in Gen 6

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.

Gen 6 specific message considerations

The practical rule for Gen 6 message handling. Driver and firmware code that generates or processes Message TLPs needs no changes for Gen 6. The routing codes, message codes, header fields, and rules from this post apply identically. New Gen 6 message types (FRS, CXL VDMs) reuse the same 4DW header with new Message Code values — no structural changes.

📋 Quick Reference

ItemValue / Rule
Msg — Fmt, TypeFmt=001 · Type=1_0rrr · no data · 16 bytes header
MsgD — Fmt, TypeFmt=011 · Type=1_0rrr · 1 DW data · 16 bytes header
Posted?Yes — all messages are posted. No completion ever returns.
Tag fieldAlways 0x00 — no completion, no tag needed
TC requirementTC=0 required for most messages. Violations → Malformed TLP.
DW1 Byte 7Message Code — 8 bits identifying the specific message type
Routing 000Implicit → Root Complex. Each switch forwards upstream. Used by PME, ERR_*
Routing 001Address routing — DW2/DW3 carry 64-bit target address
Routing 010ID routing — DW2 bytes 8–9 carry target BDF
Routing 011Broadcast from RC. Switch duplicates to all downstream ports. Used by PM_Turn_Off, Unlock
Routing 100Local — terminate at receiver. Switch consumes and re-sends with own Req ID. Used by INTx
Routing 101Gather to Root. Switch waits for all downstream ports before forwarding one. Used by PME_TO_Ack
INTx AssertCodes 0x20–0x23 · Routing 100 · TC=0 · no data
INTx DeassertCodes 0x24–0x27 · Routing 100 · TC=0 · no data
PM_PMECode 0x18 · Routing 000 · device wakeup request to RC
PM_Turn_OffCode 0x19 · Routing 011 · RC broadcasts power-down
PME_TO_AckCode 0x1B · Routing 101 · endpoint acks power-down · gathered at switches
ERR_CORCode 0x30 · Routing 000 · correctable error notification to RC
ERR_NONFATALCode 0x31 · Routing 000 · uncorrectable non-fatal
ERR_FATALCode 0x33 · Routing 000 · uncorrectable fatal
UnlockCode 0x00 · Routing 011 · RC broadcasts to release MRdLk locks
Set Slot Power LimitCode 0x50 · Routing 100 · MsgD with 1DW power limit payload
VDM Type 0Code 0x7E · Unknown receiver → UR error
VDM Type 1Code 0x7F · Unknown receiver → silent discard
LTRCode 0x10 · Routing 100 · endpoint reports acceptable latency to platform
OBFFCode 0x12 · Routing 100 · platform hints power state to endpoint
Gen 6 impactZero 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.
Coming next — PCIe-10: TLP Ordering Rules.The 12-rule ordering table — posted vs non-posted vs completion, and why order matters.
Scroll to Top