Skip to content

Host↔Device DMA

本页所有地址均适用于 libtpu-0.0.40-cp314 wheel 中的 libtpu.so(构建 libtpu_lts_20260413_b_RC00,build-id md5 89edbbe81c5b328a958fe628a9f2207d)。该镜像剥离符号;反混淆后的 C++ 符号名按原样引用。.text VMA 等于文件偏移(.text 基址 0xe63c000);.data.rel.ro 带有 0x200000 的 VMA→file delta。其他版本会不同。

摘要

host↔device DMA 是一种另一端位于 host memory 的传输:向 TensorCore queue 供给数据的 infeed(host→device)、排空队列的 outfeed(device→host)、activation data 的 direct-write,或来自 host-interface bridge 的 physical-address response。这类传输的本地 leg 的片上描述符是 片上 DMA 描述符 中记录的 OciDescriptorCommonIssuedFromTcs;本页记录 profiler 中跨边界 leg 会发生什么:device trace stream 的 host-interface 事件如何被重新组装为一个 host↔device transfer span,它被归入哪个方向(H2D vs D2H),以及 host endpoint 为渲染出的事件贡献了什么。

重组逻辑是 DeriveHostDmaTransfers,即一对 timeline producer(每个 silicon generation 一个):它们扫描合并后的 device trace,按逐事务 key 将一个“started” host-DMA 事件与其“completion”事件配对,并向 host-DMA lane 发射一个 XEventpxc(Pufferfish/BarnaCore)generation 通过 UHI host-interface band(trace points {0, 2, 4})完成此事,并产生携带 kind tag 6(MemcpyH2D)或 7(MemcpyD2HDmaTransfer record,这是整个二进制中唯一写入这两个 tag 的位置。jxc(Jellyfish)generation 通过完全不同的机制完成此事:在 HIB(host-interface block)descriptor band 上进行 SyncFlagUpdate-deque 配对,key 是 sync-flag target,而不是 transaction id,并渲染到 Sync-Flag lanes。本页负责 derivation、tag-6/7 语义和 host endpoint;UHI message wire format 和完整 QueueIdValues enum 见 UHI Host-Interface DMADmaTransfer record + 逐 span XStat 集合见 片上 DMA 描述符 §5

重新实现时,契约是:

  • 两个 DeriveHostDmaTransfers passpxc UHI host-DMA pass(MemcpyH2D/MemcpyD2H span 的来源)和 jxc HIB host-DMA pass(SyncFlagUpdate-deque 配对),以及它们为何在结构上不同。
  • tag-6/7 选择器:字节精确的 (queue_id & ~1) == 2 ? 6 : 7 规则,它从 STARTED 事件的 queue_id 将 host DMA 分桶为 H2D vs D2H,并决定产生的 lane(63 / 64)。
  • transfer 构建:STARTED 事件如何打开一个 DmaTransfer 槽位(begin gtc、byte count、queue label、kind tag),RESPONSE 事件如何关闭它(end gtc),二者按 trace_id_header.transaction_id 配对。
  • host endpoint:host 侧字段(queue_iddvasequence_number)贡献什么:queue_id 成为 H2D/D2H 选择器和 queue XStat;dva(device virtual address)和 sequence_number 会被解码但丢弃,因此不会渲染任何 host↔device address。
pxc host-DMA producerxprof::tpu::ConvertTpuTraceToXPlane<…pxc::profiler::TraceEntry>{lambda}{lambda} @ 0xf26afa0
pxc 片上(ICI)producer同一 template 的 sibling lambda @ 0xf26c6e0写入 tag 6/7)
jxc host-DMA producerDeriveHostDmaTransfers,内联 @ 0xf252f000xf25303bjxc lambda @ 0xf252260
共享 rendererxprof::tpu::ConvertDmaTransfersToXPlane(absl::Span<DmaTransfer>, …) @ 0xf254bc0
jxc populate sidexprof::tpu::ConvertDmaDescriptorToXPlane @ 0xf253620
jxc consume sidexprof::tpu::ConvertDmaEndsToXPlane<…jxc…> @ 0xf25c500
Tag-6/7 选择器(((queue_id & ~1) == 2) ? 6 : 7) @ 0xf26b5a6.text唯一匹配
Host-DMA lanesTpuComponent 63 MemcpyH2D,64 MemcpyD2Hpxc);17 Tensor Core Sync Flag,23 Barna Core Fabric Syncjxc
证据等级重新实现级 / 经 IDA 反编译 + FDP descriptor pool 字节确认

1. 两代,两种 Host-DMA Derivation

ConvertDmaTransfersToXPlane @ 0xf254bc0 是共享 renderer,会将一段 DmaTransfer record 转为 device XEvent。它有 16 个调用方(对 .texte8-rel32 扫描),每个 silicon generation 有一个 host-DMA producer 和一个片上 ICI producer,另有 merge/helper 站点。其中,正好一个会写 kind tag 6 或 7:对整个 .text 扫描 tag selector pattern(83 e0 fe = and ~1,随后 83 f1 07 = xor 0x7)只返回一个命中,位于 pxc host-DMA producer 内的 0xf26b5aa。较新的 SparseCore generations(vfc/vlc/glc/gfc)会调用共享 renderer,但从不发射 MemcpyH2D/MemcpyD2H span;jxc 则完全通过另一个 pass 路由 host DMA。

方面pxc host-DMA(UHI band)jxc host-DMA(HIB band)
Producerlambda @ 0xf26afa0DeriveHostDmaTransfers(内联)@ 0xf252f00
Trace pointsUHI {0, 2, 4}nf_descriptor_hib + 4 个 HIB band
配对 keytransaction_id(32-bit)sync_flag_targetUpdatedSyncFlagTarget
Begin markerSTARTED(id 0)nf_descriptor source-sync-flag target
End markerRESPONSE_READ/WRITE(id 2 / id 4)LastSyncForTracedDma completion
Byte countsize(f5,raw)length << 10(1 KiB 单位,GetDmaSize
KIND / lanestag 6/7 → MemcpyH2D 63 / MemcpyD2H 64kindDMA Local/DMA Remote/DMA H2D
Render lanes63 / 6417 Tensor Core Sync Flag / 23 Barna Core Fabric Sync
queue XStatQueueId enum name(FILLED)(携带在 descriptor XEvent 上)
Renderer共享 ConvertDmaTransfersToXPlaneConvertDmaDescriptorToXPlane + ConvertDmaEndsToXPlane

注意 — pxc template ConvertTpuTraceToXPlane<…pxc::profiler::TraceEntry> 实例化了两个嵌套 lambda,二者都馈入共享 renderer:第一个(@ 0xf26afa0,call @ 0xf26b9b7)是本文记录的 UHI host-DMA pass;第二个(@ 0xf26c6e0)是 ICR Node-Fabric 片上 pass,它将 ICI tag 2/3 发射到 lanes 54/55(见 ICR DMA Timeline Band)。它们共享 renderer 和 DmaTransfer record 形状,但 key 使用不同 trace point,并写入不同 tag。置信度:CONFIRMED(16-caller 拆分和唯一 tag-6/7 字节扫描命中)。


2. pxc UHI Host-DMA Derivation

2.1 三个 trace point

producer 构建一个 3 元素 TracePoints list(每个 UHI host-interface event 一个打包 {band, id} 条目),将其传给 GetMerged,然后迭代合并后的按时间排序 stream。该 list 在反编译中按字节可见:每个条目都是打包的 64-bit (band << 32) | id。第一个条目是 0x400000000 = (band 4) | (id 0),即 STARTED 事件;随后追加 ids 2 和 4 的条目,并在调用前将 list size 设为 3:

c
// xprof::tpu::ConvertTpuTraceToXPlane<pxc::…TraceEntry>{lambda}{lambda}   sub_F26AFA0
*v10        = 0x400000000LL;     // @0xf26afee  entry[0] = (band 4)|(id 0) = STARTED
v11[2]      = 2;                 // @0xf26b03d  entry[1] id 2  (Read response)
// + entry[2] id 4 (@0xf26b04e), list size = 3 (@0xf26b063)
TpuTraceEntries<…pxc…TraceEntry>::GetMerged(&v90, v8, &ptr);  // @0xf26b07f, ids {0, 2, 4}
```text

| `trace_point_id` | UHI message(`pxc::profiler::`) | oneof case | 角色 |
|---:|---|---:|---|
| 0 | `UhiHostDmaTransactionStartedAddressTranslation` | 2 | BEGIN + byte count + queue + tag |
| 2 | `UhiHostPhysicalResponseRead` | 4 | END(read response) |
| 4 | `UhiHostPhysicalResponseWrite` | 6 | END(write response) |

逐条目分派读取 `trace_point_id`(`TraceHeader+0x18`)并据此分支(反编译确认 `if (v21 == 4)` → Write-response,`if (v21 == 2)` → Read-response,fall-through `== 0` → Started),随后用标准 proto2 oneof-case guard 解析匹配的 message global(`UhiHostDmaTransactionStartedAddressTranslation_globals_` @ `0x2237ac40`、`UhiHostPhysicalResponseRead_globals_` @ `0x2237ab98`、`UhiHostPhysicalResponseWrite_globals_` @ `0x2237ab70`)。id↔name 绑定(id 0 = `UHI_HOST_DMA_TRANSACTION_STARTED_ADDRESS_TRANSLATION`,id 2 = `UHI_HOST_PHYSICAL_RESPONSE_READ`,id 4 = `UHI_HOST_PHYSICAL_RESPONSE_WRITE`)与 UHI band 的 trace-point registry 一致。置信度:CONFIRMED(字节精确 seed + `== 4 / == 2 / == 0` 分派 + 三个 message global)。

### 2.2 STARTED 事件 — 打开 transfer(host endpoint)

id-0 STARTED 事件是唯一携带 host endpoint 的事件。其字段布局(完整 wire format 见 [UHI Host-Interface DMA](uhi-host-interface.md))以及 producer 对每个字段的处理如下:

| f# | 字段 | 类型 | cpp off | Producer 用途 |
|---:|---|---|---:|---|
| 1 | `trace_id_header` | `TraceIdHeader` | `+0x18` | `dma_id` = `transaction_id`(`hdr+0x18`)— 配对 key |
| 2 | `queue_id` | `QueueIdValues` | `+0x20` | KIND-tag 选择器(§3**以及** `queue` XStat(enum name) |
| 3 | `sequence_number` | u32 | `+0x24` | 解码,**丢弃** |
| 4 | `dva` | u64 | `+0x28` | device virtual address — 解码,**丢弃** |
| 5 | `size` | u32 | `+0x30` | `byte_count` = `size`(无 granule shift) |

begin-store 块(`@0xf26b560`,字节精确)在以 `transaction_id` 为 key 的 map 中打开一个 `DmaTransfer` 槽位(槽位是 map value 形式;偏移在该槽内):

```c
// id-0 STARTED begin store   @0xf26b560
slot.begin_gtc      = gtc;                  // [slot+0x8]  = TraceHeader.timestamp (+0x20)
slot.begin_present  = 1;                    // [slot+0x10]
slot.byte_count     = msg.size;             // [slot+0x28] = [msg+0x30], NO shift   @0xf26b568
slot.queue.ptr      = NameOfDenseEnum(queue_id);  // [slot+0x30]  (QueueIdValues name / SSO)
slot.queue.len      = …;                    // [slot+0x38]
slot.kind_tag       = (((queue_id & ~1) == 2) ? 6 : 7);  // [slot+0x40]   §3

queue label 通过 proto2::internal::NameOfDenseEnum<&…QueueIdValues_descriptor, 0, 21> 取得(dense 22-value enum,索引 0..21):快路径索引 descriptor table,慢路径落到 NameOfDenseEnumSlow。这是 renderer 作为 XStat 79 附加到逐 DMA span 的 queue 字符串;它在 host-DMA span 上非空(在 ICI 片上 band 上为空)。

陷阱 — host endpoint 被丢弃。 STARTED 事件携带一个 device virtual addressdva,f4 @ +0x28),也就是命名 host↔device copy 的 device 端的字段,但 producer 从不读取它。它也不读取 sequence_number。只有 trace_id_header(用于 key)、queue_id(用于 tag + label)和 size(用于 byte count)保留下来进入渲染的 span。因此捕获到的 pxc host-DMA XEvent 会显示多少字节哪个 queue,但显示 host 或 device address。这与片上 band 一样,后者也会丢弃其 src/dst endpoint(片上 DMA 描述符 §5)。libtpu.so 中没有链接任何会重新读取 dva 的下游 symbolizer。置信度:CONFIRMED(producer 只读取 STARTED message 的 +0x18/+0x20/+0x30)。

2.3 RESPONSE 事件 — 关闭 transfer

id-2(UhiHostPhysicalResponseRead)和 id-4(UhiHostPhysicalResponseWrite)事件是 END marker。每个都携带 {f1 trace_id_header @+0x18, f2 is_l2_pte_fetch (bool) @+0x24, f3 chunk_id (u32)};producer 只读取 trace_id_header(用于查找槽位)和事件 gtc。is_l2_pte_fetch/chunk_id 字段会被解码但丢弃。end-store 块(@0xf26b0d0):

c
// id-2 / id-4 RESPONSE end store   @0xf26b0d0
slot.end_gtc      = gtc;   // [slot+0x18] = TraceHeader.timestamp
slot.end_present  = 1;     // [slot+0x20]
```text

**配对。** 槽位 key 仅为 `trace_id_header.transaction_id`,一个完整的 32-bit 逐事务 tag,零扩展到 `flat_hash_map<u64, DmaTransfer>` key(policy @ `0x21646fe8`),**不会**像片上 ICR band 那样掩到 38-bit composite(后者会折入 `core_id`/`chip_id`)。一个 host DMA 正好有一个 `transaction_id`;它的 STARTED(id 0)和 RESPONSE(id 2 read / id 4 write)共享该 id 并写入同一槽位,产生一个 `DmaTransfer {begin, end, byte_count, queue, tag}`。如果 STARTED 到达时槽位已经填满,producer 会 flush 旧 transfer 并重新打开(`@0xf26b52f`)。置信度:CONFIRMED。

> **注意 — read-response vs write-response *不是* H2D/D2H 信号。** 直觉上可能会认为 id-2(READ response)关闭 device→host read,而 id-4(WRITE response)关闭 host→device write,但 producer 完全根据 STARTED 事件中的 `queue_id` 决定*方向*(§3),两个 response 变体都只是提供 end timestamp。重新实现者不得从关闭槽位的是哪个 RESPONSE id 推断方向。置信度:CONFIRMED(end store 只写 gtc/present;tag 在 begin 时固定)。

---

## 3. Tag-6/7(H2D vs D2H)选择器

host-DMA 路径的核心行是 kind-tag 计算,字节精确位于 `0xf26b5a6`,且是 `.text` 中**唯一**这样的站点:

```c
// @0xf26b5a6 — the sole tag-6/7 producer in the binary
// asm: mov eax, queue_id ; and eax, 0xFFFFFFFE ; cmp eax, 2 ; sete cl ; xor ecx, 0x7
slot.kind_tag = (((queue_id & ~1) == 2) ? 6 : 7);   // decompile: (((v22[4] & 0xFFFFFFFE) == 2) ^ 7)

(queue_id & ~1) == 2 只对 queue_id ∈ {2, 3} 成立,即 QUEUE_ID_DIRECTWRITEQUEUE0QUEUE_ID_DIRECTWRITEQUEUE1sete 产生 1,然后 xor 1, 7 = 6;对所有其他 queue_idsete 产生 0,然后 xor 0, 7 = 7。

queue_idQueue class(queue_id & ~1) == 2KIND tagLane
2, 3DIRECTWRITEQUEUE0/1yes6MemcpyH2D63
0, 1, 4..21debug / magic / infeed / outfeed / reservedno7MemcpyD2H64

因此,只有两个 direct-write queue 被分桶为 host→device;所有其他 queue,包括直觉上可能以为是 H2D 的 infeed queue,都会落到 D2H。完整 22-value QueueIdValues enum 和原因见 UHI Host-Interface DMA

陷阱 — 方向是 trace-design bucketing,不一定是物理方向。 该规则按字节固定(and ~1; cmp 2),但将 INFEEDQUEUE*/OUTFEEDQUEUE* 分类为 D2H 是反映硬件真实数据方向,还是有意的 timeline bucketing 选择,无法仅从 libtpu.so 证明;只有捕获的 XSpace 才能显示最终 lane placement。字面谓词为 CONFIRMED;它编码的 firmware queue→direction 约定为 LOW(解码为该谓词,未对 silicon 验证)。

tag → lane / event-metadata 映射

共享 renderer 的 kind switch 通过 (kind_tag - 2) 索引 @ 0xab589bc 的 jump table(add $0xfffffffe,%eax; cmp $5,%eax; ja skip; movslq (r9,rax,4),rax @ 0xf2550410xf25504c,因此有效 tag 范围是 2..7),在表索引 4 和 5 上分别给出 tag 6 和 7 的不同分支:

tagjt idxjt armTpuComponent lineXEvent metadata来源
640xf25507e63 MemcpyH2D"MemcpyH2D"queue_id ∈ {2,3}(direct-write)
750xf25534064 MemcpyD2H"MemcpyD2H"所有其他 queue_id

反编译确认 renderer 在 kind switch 前 intern GetOrCreateEventMetadata("MemcpyH2D")(@ 0xf254e5f,length 9)和 GetOrCreateEventMetadata("MemcpyD2H")(@ 0xf254e82,length 9),随后将 tag 6/7 路由到 H2D/D2H 分支。置信度:CONFIRMED。(这修正了早先 sibling note 中将 tag 6/7 列为“unused on pxc”以及 tag/lane 表转置的问题:tag 6 = H2D = lane 63,tag 7 = D2H = lane 64。)

渲染出的 span

逐 span XStat 是 片上 DMA 描述符 §5 中记录的共享 DmaTransfer 集合,并有两个 host-DMA 特点:

  • bytes_transferred (78) = size,即原始字节计数;不像片上 band 的 length << {2,9},这里没有 granule shift。
  • queue (79) = QueueId enum name(例如 QUEUE_ID_DIRECTWRITEQUEUE0),在 host-DMA span 上非空details(string)保持为空(producer 写 [slot+0x30]/[slot+0x38] = queue,从不写 [slot+0x48] = details)。

4. jxc HIB Host-DMA Derivation

jxc 是 proto2-self-describing 的,并且发射 MemcpyH2D/MemcpyD2H span。它的 host-interface(HIB)DMA timeline 由 DeriveHostDmaTransfers 构建,这是一个 SyncFlagUpdate-deque 配对:它记录 descriptor-staged 的“begin”,并将其与 sync-flag-update “completion”匹配。staging 每个 begin 的 intra-chip descriptor 是 片上 DMA 描述符 中的那个;本节记录构建在其上的 host↔device 配对

4.1 五个 trace point

DeriveHostDmaTransfers 内联到 jxc ConvertTpuTraceToXPlane lambda @ 0xf252260;其 static-init 块 @ 0xf252f000xf25303b 构造五个 function-local TracePoint static(五对 __cxa_guard_acquire/release),随后通过 TpuTraceEntries::GetMerged call @ 0xf252382(callee @ 0xf253080)合并它们:

StaticBand / id角色
nf_descriptor_hibnf_descriptor(case 3),id 2(HIB)host-side staged descriptor — begin
nf_hib_write_cmdnf(case 6),HIB_WRITE_COMMAND(id 22)HIB write command
nf_hib_write_data_endnf(case 6),HIB_WRITE_DATA_END(id 23)HIB write-data end
hib_hbm_writehib_hbm_write(case 19),HBM_WRITE(id 87)HIB→HBM write
hib_sync_updatehib_sync_update(case 18),SYNC_UPDATE(id 86)sync-flag-update — completion

这五个是 pxc UHI host-DMA band 的 jxc 对应物。置信度:CONFIRMED(五个 guard-var 符号 + 内联 init)。

4.2 SyncFlagUpdate deque map

配对结构是 absl::flat_hash_map<uint64 sync_flag_target, std::deque<SyncFlagUpdate>>(policy @ 0x21646f10;policy 类型在反编译中按字节可见)。SyncFlagUpdate 是 0x38 字节(56 字节)的 POD(stride 由 MergeSyncFlagUpdatesadd r15, 0x38 确认):

偏移字段用途
+0x00sync_flag_target配对 key(SourceSyncFlagTarget / UpdatedSyncFlagTarget 结果)
+0x08dma_idflow-stat 值来源(& 0xff_ffff_ffff_ffff → XFlow id)
+0x10kindDMA Local/Remote/H2D event-metadata 选择器(0..4)
+0x18..+0x37begin_gtc / size / endpoint记录的 begin metadata(由 reflection 填充)

逐 core map 由 MergeSyncFlagUpdates @ 0xf248ee0 合并(遍历每个 map 的 {key, deque} 并合并 deque),然后再渲染。

注意 — +0x18..+0x37 槽位(begin_gtc、dma size、endpoint chip/node)由 populate side 的标准 reflection walk 填充;target/dma_id/kind 按字节钉牢,但其余 0x20 字节的逐字段映射未被 single-step。配对语义已解码;精确 begin-metadata 槽位布局为 CONFIRMED-PARTIAL。

4.3 populate side — ConvertDmaDescriptorToXPlane

ConvertDmaDescriptorToXPlane @ 0xf253620 将每个 staged HIB descriptor 渲染为一个 descriptor XEvent并且入队一个 pending begin:

c
// xprof::tpu::ConvertDmaDescriptorToXPlane   sub_F253620
// interns 4 event names: "DMA Local"(9), "DMA Remote"(10), "DMA H2D"(7), "DMA D2H"(7) + flow StatType 0x38
for (wrapper : descriptors):
    dma_id = wrapper.GetDmaId();                  // jxc composite   @0xf698180
    if (wrapper.EntryDataCase() != 3) continue;   // gate: nf_descriptor   @0xf25388b
    key    = wrapper.SourceSyncFlagTarget();      // sync_flag_target   @0xf6982e0
    slot   = map.find_or_prepare_insert_large(key);   // @0xf24f320
    slot.push_back(SyncFlagUpdate{ .target = key, .dma_id = dma_id, .kind = …, … });
    bytes  = wrapper.GetDmaSize();                // = length(@descr+0x48) << 10 (1 KiB)   @0xf6982a0
```text

`SourceSyncFlagTarget` @ `0xf6982e0` 是 descriptor 的 source-sync-flag-update target(对 `descr+0x60` 的 OCI SyncFlag fold);每个 staged HIB descriptor 都会在该 target 下入队一个 pending begin。`GetDmaSize` 已按字节确认:`nf_descriptor`(case 3)→ `length(@descr+0x48) << 10`。置信度:CONFIRMED(四个 event name、`deque<SyncFlagUpdate>` policy 上的 `find_or_prepare_insert_large`、`GetDmaId`/`SourceSyncFlagTarget`/`GetDmaSize` call 都存在于反编译中)。

### 4.4 consume side — `ConvertDmaEndsToXPlane<jxc>`

`ConvertDmaEndsToXPlane<jxc>` @ `0xf25c500` 消费 completion 并发射配对后的 host-DMA span:

```c
// xprof::tpu::ConvertDmaEndsToXPlane<…jxc…>   sub_F25C500
// interns 3 event names: "DMA Local"(9), "DMA Remote"(10), "DMA H2D"(7) + flow StatType 0x38
for (wrapper : completions):
    if (!wrapper.LastSyncForTracedDma()) continue;     // gate: only the LAST sync   @0xf6986a0
    key  = wrapper.UpdatedSyncFlagTarget();             // completion target   @0xf698400
    begin = map.lookup(key).pop_front();                // SwissTable lookup of pending begin
    name = event_meta[begin.kind];                      // cmp kind,5; jae skip   @0xf25c807
    span = GtcSpan{ begin.recorded_gtc, this.gtc };
    line.AddEvent(span, name);                           // @0xf25c843
    span.flow = begin.dma_id & 0xff_ffff_ffff_ffff;      // flow XStat 0x38   @0xf25c861

end gate LastSyncForTracedDma @ 0xf6986a0 已按字节确认:case 0xbhib_sync_update)→ field(@submsg+0x28).f@0x1c >> 31last top-bit);case 9(cs_external sync-flag-update)→ (f@0x30 != 0) && (f@0x3c != 0)last_sync_for_dma && successful_sync 门控)。UpdatedSyncFlagTarget @ 0xf698400 是 completion 的 target(EntryDataCase keyed sync-flag-target pack),用作 deque key。flow 值在成为 XFlow id 前被掩到 56 bit(& 0xFFFFFFFFFFFFFF)。置信度:CONFIRMED(字节精确 gate + flow mask + kind < 5 选择器 + AddEvent)。

ConvertDmaEndsToXPlane<jxc> 被调用两次:一次来自 lambda(@0xf25b1e0),带 TpuComponent 23 Barna Core Fabric Syncedi = 0x17,call @ 0xf25b8db);另一次(@0xf25d6e0)带 TpuComponent 17 Tensor Core Sync Flagedi = 0x11,call @ 0xf25ee62)。因此 jxc host-DMA span 会落到 Sync-Flag lanes(17/23),根据匹配 begin 的 kind 命名为 DMA Local/DMA Remote/DMA H2D,并通过 dma_id flow-link 到其 descriptor。这是 pxc UHI begin/end 配对的 jxc analog,但 key 是 sync-flag target,且由 DMA 的最后一次 sync-flag-update 门控,而不是 RESPONSE trace point。

注意 — kind → direction label。 host-DMA span 的名称(DMA Local/Remote/H2D)由记录的 SyncFlagUpdate.kind+0x10,以 cmp kind, 5; jae skip 边界索引 event-metadata array)选择。哪个 nf_descriptor 字段(descriptor_source enum / dma locality)设置各个 kind,在 populate side 中已结构性读取,但未制成 descriptor locality enum 对照表;kind 索引来源为 CONFIRMED,精确 descriptor-field → kind 映射为 LOW。


5. 重新实现说明

  • 检测 host DMA。pxc 上,一个传输当且仅当源自 UHI band(trace points {0,2,4})时是 host↔device;除 tag 外,DmaTransfer record 上没有额外标志(6/7 = host,2/3 = 片上 ICI)。在 jxc 上,host DMA 是 HIB nf_descriptor_hib band staging 且由 hib_sync_update completion 关闭的任何 DMA;它渲染在 Sync-Flag lanes 上,不是专用 Memcpy lane。
  • 方向。 pxc(queue_id & ~1) == 2 ? H2D : D2H,只有 DIRECTWRITEQUEUE0/1 是 H2D。jxc:匹配 begin 的 kind 字段(DMA Local/Remote/H2D);没有单独的 H2D/D2H tag;“Local”覆盖片上 staged 情形。
  • Byte count。 pxc:原始 size(无 shift)。jxclength << 10(1 KiB granule)。不要将片上 band 的 << {2,9} granule 逻辑应用到任一 host 路径。
  • 配对 key。 pxc:32-bit transaction_id,每个 host DMA 一个。jxcsync_flag_targetSourceSyncFlagTarget/UpdatedSyncFlagTarget fold),且每个 DMA 的最后一次 sync-flag-update 关闭 span。
  • host endpoint 仅保留摘要。 两条路径都不渲染 host 或 device address。pxc 解码并丢弃 dvajxcSyncFlagUpdate 中记录 endpoint 槽位,但没有 symbolizer 回读它。需要 host↔device address 的重新实现者必须重新读取被丢弃的 proto 字段(pxc STARTED +0x28 处的 dva);libtpu.so 中没有 consumer 这样做。

交叉引用

  • UHI Host-Interface DMA — UHI message wire format,以及 tag-6/7 选择器据以分派的完整 22-value QueueIdValues enum
  • 片上 DMA 描述符OciDescriptorCommonIssuedFromTcs local-leg descriptor;§5 记录本页 span 使用的共享 DmaTransfer record + 逐 span XStat 集合
  • OCI Command DMA-IDtrace_id_header DMA-id 配对 key 和逐 band id helper(pxc transaction_id analog)
  • Rolled / Strided / General 发射器 — 发射 jxc host-DMA pass 所 staging 描述符的 transfer-body 发射器
  • ICR DMA Timeline Band — 由 sibling pxc lambda @ 0xf26c6e0 产生的片上 ICI band(tags 2/3,lanes 54/55),不同于此 host band
  • DMA Endpoint RenderingConvertDmaTransfersToXPlane 如何将配对后的 DmaTransfer 渲染为 device XEvent,以及它保留和丢弃哪些字段
  • JXC DMA / HBM-Mux / BrnPerfSyncFlagUpdate 配对渲染到 Sync-Flag lanes(17/23)的 jxc DMA band