為什麼 SDM 無法把 RBF 載入 FPGA 的組態 SRAMWhy the SDM cannot load the RBF into the FPGA configuration SRAMSDM が RBF を FPGA コンフィギュレーション SRAM へロードできない理由

SMMU 位址轉譯不一致造成 timeout waiting for svc layer buffers 的完整分析A full analysis of how inconsistent SMMU address translation produces timeout waiting for svc layer buffersSMMU のアドレス変換の不整合がいかにして timeout waiting for svc layer buffers を生むのか、その全解析

DE25-Standard Agilex 5 (A5ED013BB32AE4SCS) Linux 6.12.11 arm-smmu-v3 stratix10-svc of_fpga_region

0. 一句話結論0. The conclusion in one sentence0. 結論を一文で

Bitstream 的資料本身一直放在正確的位置;出錯的是 傳給 SDM 的那個「位址數字」。 因為 stratix10-svc 掛在 SMMU 後面,驅動程式拿到的是 IOVA(裝置虛擬位址), 但 SDM 不在 SMMU 後面,它把這個數字當成實體位址(PA)去讀 DRAM, 於是讀到完全不相干的記憶體,找不到 bitstream,也就永遠不回應 — 驅動程式因此卡在等待,最後逾時。 The bitstream data was always in the right place; what was wrong is the address number handed to the SDM. Because stratix10-svc sits behind the SMMU, the driver receives an IOVA (device virtual address), but the SDM is not behind the SMMU — it treats that number as a physical address (PA) and reads DRAM with it. It therefore reads completely unrelated memory, never finds the bitstream, and never responds — so the driver waits forever and eventually times out.ビットストリームのデータは最初から正しい場所にあった。誤っていたのは SDM に渡されたアドレスの数値である。stratix10-svc は SMMU の背後にあるため、ドライバが受け取るのは IOVA(デバイス仮想アドレス)だが、SDM は SMMU の背後にいない — その数値を物理アドレス(PA)として扱い、それで DRAM を読む。結果、まったく無関係なメモリを読んでビットストリームを見つけられず、応答も返さない。そのためドライバは待ち続け、最後にタイムアウトする。

觀察到的錯誤訊息:
[  698.226136] fpga_manager fpga0: writing new40kHz4.core.rbf to Stratix10 SOC FPGA Manager
[  705.512932] Stratix10 SoC FPGA manager firmware:svc:fpga-mgr: timeout waiting for svc layer buffers
同時 /sys/class/fpga_manager/fpga0/state 卡在 write, 寫入的行程進入不可中斷睡眠(D state,連 kill -9 都無效)。
The observed error message:
[ 698.226136] fpga_manager fpga0: writing new40kHz4.core.rbf to Stratix10 SOC FPGA Manager [ 705.512932] Stratix10 SoC FPGA manager firmware:svc:fpga-mgr: timeout waiting for svc layer buffers
Meanwhile /sys/class/fpga_manager/fpga0/state is stuck at write, and the writing process enters uninterruptible sleep (D state, immune even to kill -9).
観測されたエラーメッセージ:
[ 698.226136] fpga_manager fpga0: writing new40kHz4.core.rbf to Stratix10 SOC FPGA Manager [ 705.512932] Stratix10 SoC FPGA manager firmware:svc:fpga-mgr: timeout waiting for svc layer buffers
このとき /sys/class/fpga_manager/fpga0/statewrite のまま止まり、書き込み中のプロセスは割り込み不能なスリープ(D 状態、kill -9 でも落ちない)に入る。

1. 三種位址空間:VA、PA、DMA address1. Three address spaces: VA, PA and DMA address1. 3 つのアドレス空間:VA、PA、DMA アドレス

要理解這個問題,必須先分清楚三種位址。很多人把它們混為一談, 但它們是三個不同的東西To understand this problem you first have to separate three kinds of address. They are frequently conflated, but they are three different things:この問題を理解するには、まず 3 種類のアドレスを区別する必要がある。しばしば混同されるが、これらは互いに別物である:

位址型別Address typeアドレスの種類 誰在使用Who uses it使う主体 由誰產生 / 轉譯Who produces / translates it生成/変換する主体
VA
virtual address
CPU、kernel 程式碼
void * 指標)
The CPU and kernel code
(a void * pointer)
CPU とカーネルのコード
void * のポインタ)
CPU 內的 MMU 轉譯成 PATranslated to a PA by the MMU inside the CPUCPU 内部の MMU によって PA へ変換される
PA
phys_addr_t
真實的 DRAM 位置The real location in DRAMDRAM 上の実際の位置 —(這就是實體位置本身)— (this is the physical location itself)—(これ自体が物理的な位置)
DMA address
dma_addr_t / IOVA
裝置發出匯流排交易時使用Used by a device when it issues a bus transactionデバイスがバストランザクションを起こすときに使う dma_alloc_coherent() 等 DMA API 回傳; 若裝置在 IOMMU 後面則由 SMMU 轉譯Returned by DMA APIs such as dma_alloc_coherent(); translated by the SMMU if the device sits behind an IOMMUdma_alloc_coherent() などの DMA API が返す。デバイスが IOMMU の背後にあれば SMMU が変換する
關鍵觀念: dma_addr_t 回答的問題是 「裝置要在匯流排上放哪個數字才能存取這塊緩衝區?」, 這和「這塊緩衝區在 DRAM 的哪裡?」是兩個不同的問題。 兩者不保證相等。 The key idea: dma_addr_t answers the question “what number must the device put on the bus to reach this buffer?”, which is a different question from “where in DRAM does this buffer live?”. The two are not guaranteed to be equal.要点:dma_addr_t が答えるのは「このバッファに届くためにデバイスはバス上へどの数値を出せばよいか」であり、「このバッファは DRAM のどこにあるか」とは別の問いである。両者が等しい保証はない。

什麼情況下 dma_addr_t == PA?When is dma_addr_t == PA?dma_addr_t == PA になるのはどんなときか

情境Situation状況 結果Result結果
裝置在會轉譯的 IOMMU 後面The device sits behind an IOMMU that translatesデバイスが変換を行う IOMMU の背後にある dma_addr_t = IOVA ≠ PA ← 本板目前狀況dma_addr_t = IOVA ≠ PA ← the current state of this boarddma_addr_t = IOVA ≠ PA ← このボードの現状
裝置沒有 IOMMU 對應(走 dma-directThe device has no IOMMU mapping (it uses dma-direct)デバイスに IOMMU マッピングがないdma-direct を使う) dma_addr_t == PA
IOMMU 設為 identity / passthrough domainThe IOMMU is set to an identity / passthrough domainIOMMU が identity / passthrough ドメインに設定されている dma_addr_t == PA
平台宣告了 dma-ranges 位移The platform declares a dma-ranges offsetプラットフォームが dma-ranges のオフセットを宣言している dma_addr_t = PA − offset ≠ PA(需另外確認)dma_addr_t = PA − offset ≠ PA (needs separate confirmation)dma_addr_t = PA − offset ≠ PA(別途確認が必要)

2. MMU 與 SMMU 的差別2. The difference between the MMU and the SMMU2. MMU と SMMU の違い

兩者都是位址轉譯器,差別在於替誰轉譯Both are address translators; the difference is who they translate for.どちらもアドレス変換器であり、違いは誰のために変換するかである。

MMU SMMU(ARM 對 IOMMU 的稱法)SMMU (ARM's name for an IOMMU)SMMU(IOMMU の ARM における呼称)
位於Located設置場所 CPU 核心內部Inside the CPU coreCPU コアの内部 匯流排上的獨立區塊A separate block on the busバス上の独立したブロック
為誰轉譯Translates for誰のために変換するか 軟體 — 行程、kernelSoftware — processes and the kernelソフトウェア — プロセスとカーネル 做 DMA 的裝置Devices performing DMADMA を行うデバイス
輸入位址Input address入力アドレス VA(虛擬位址)VA (virtual address)VA(仮想アドレス) IOVA(裝置虛擬位址)IOVA (device virtual address)IOVA(デバイス仮想アドレス)
輸出Output出力 PA PA
分頁表粒度Page-table granularityページテーブルの粒度 每個行程一份One per processプロセスごとに 1 つ 每個裝置(或每個 IOMMU group)一份One per device (or per IOMMU group)デバイスごと(または IOMMU グループごと)に 1 つ
防護對象Protects against何から守るか 行程之間不能亂讀彼此記憶體Processes reading each other's memoryプロセスどうしがメモリを覗き合うこと 裝置不能亂寫不該碰的記憶體Devices writing memory they should not touchデバイスが触れてはならないメモリへ書き込むこと

本板開機時 SMMU 的分組How the SMMU groups devices when this board bootsこのボードの起動時に SMMU がデバイスをどうグループ分けするか

arm-smmu-v3 16000000.iommu: ias 48-bit, oas 48-bit (features 0x001c1fef)
socfpga-dwmac 10810000.ethernet: Adding to iommu group 0
dwc2 10b00000.usb:               Adding to iommu group 1
sdhci-cdns 10808000.mmc0:        Adding to iommu group 2
stratix10-svc firmware:svc:      Adding to iommu group 3   ← 問題所在stratix10-svc firmware:svc: Adding to iommu group 3 ← the problemstratix10-svc firmware:svc:      Adding to iommu group 3   ← 問題箇所
dw_axi_dmac_platform 10db0000.dma-controller: Adding to iommu group 4
dw_axi_dmac_platform 10dc0000.dma-controller: Adding to iommu group 5
iommus 只管「裝置主動發起」的存取。 方向很重要:
方向由誰轉譯iommus 影響?
CPU → 裝置暫存器(MMIO / ioremapCPU 的 MMU
裝置 → 記憶體(DMA / bus-master)SMMU
iommus governs only accesses that the device itself initiates. Direction matters:
DirectionTranslated byAffected by iommus?
CPU → device registers (MMIO / ioremap)the CPU's MMUNo
Device → memory (DMA / bus-master)the SMMUYes
iommus が管轄するのは「デバイス自身が発行する」アクセスだけである。方向が重要になる:
方向変換する主体iommus の影響を受けるか?
CPU → デバイスのレジスタ(MMIO / ioremapCPU の MMUいいえ
デバイス → メモリ(DMA / bus-master)SMMUはい

3. 三個當事人:只有兩個講同一種位址語言3. Three parties — only two of them speak the same address language3. 三者の当事者:同じアドレス言語を話すのはそのうち二者だけ

當事人Party当事者 看得懂的位址Addresses it understands理解できるアドレス 在 SMMU 後面嗎?Behind the SMMU?SMMU の背後にあるか?
CPU / 驅動程式CPU / driverCPU / ドライバ VA,並向 DMA API 取得 dma_addr_tVA, and obtains a dma_addr_t from the DMA APIVA を使い、DMA API から dma_addr_t を受け取る
stratix10-svc
(Linux 眼中的「裝置」)(the “device” as Linux sees it)(Linux から見た「デバイス」)
IOVA — 因為它有 iommus 屬性IOVA — because it has an iommus propertyIOVAiommus プロパティを持つため Yesはい,iommu group 3, iommu group 3、iommu group 3
SDM
Secure Device Manager
只認實體位址(PA)Understands physical addresses (PA) only物理アドレス(PA)しか理解しない 不是 — 它根本不是 Linux 裝置No — it is not a Linux device at allいいえ — そもそも Linux のデバイスではない

名詞澄清Terminology用語の整理

完整呼叫鏈The full call chain呼び出し連鎖の全体

of_fpga_region fpga-mgr stratix10-svc SMC call ATF / firmware SDM CRAM(fabric)CRAM (fabric)CRAM(fabric) svcbuffer@0 (bitstream 放在這裡)(the bitstream lives here)(bitstream はここに置かれる)

所以錯誤訊息 firmware:svc:fpga-mgr 其實就是這個階層的字面展開: firmware 節點下的 svc 服務層裡的 fpga-mgr 客戶端。 So the error string firmware:svc:fpga-mgr is simply that hierarchy spelled out: the fpga-mgr client inside the svc service layer under the firmware node.つまりエラーメッセージ firmware:svc:fpga-mgr は、この階層をそのまま並べたものにすぎない。firmware ノード下の svc サービス層にある fpga-mgr クライアント、という意味である。

4. 失敗過程逐步拆解4. The failure, step by step4. 失敗の過程を一段ずつ分解する

1驅動程式讀檔。 of_fpga_region/lib/firmware 讀入 new40kHz4.core.rbf(1,351,680 bytes)。1The driver reads the file. of_fpga_region reads new40kHz4.core.rbf (1,351,680 bytes) from /lib/firmware.1ドライバがファイルを読む。 of_fpga_region/lib/firmware から new40kHz4.core.rbf(1,351,680 bytes)を読み込む。

2需要一塊 SDM 讀得到的緩衝區, 於是從專用保留區配置:2It needs a buffer the SDM can read, so it allocates from a dedicated reserved region:2SDM が読めるバッファが必要になるので、 専用の予約領域から確保する:

OF: reserved mem: 0x0000000080000000..0x0000000081ffffff (32768 KiB) nomap non-reusable svcbuffer@0

32 MB,專門切出來讓 firmware 讀取。nomap 表示不納入 kernel 線性映射, 因為擁有這塊記憶體定址權的是「不參與 Linux 記憶體管理的外部代理人」。32 MB, carved out specifically for firmware to read. nomap means it is excluded from the kernel's linear mapping, because the agent that addresses this memory is an external one that takes no part in Linux memory management.32 MB を firmware が読むためだけに切り出してある。nomapカーネルのリニアマッピングに含めないことを意味する。このメモリをアドレッシングする主体が、Linux のメモリ管理に一切関与しない外部のエージェントだからである。

3dma_alloc_coherent() 回傳兩個不同的東西:dma_alloc_coherent() returns two different things:dma_alloc_coherent() は 2 つの異なるものを返す:

CPU 指標(VA)  →  用來 memcpy 把 bitstream 複製進去
dma_addr_t      →  要交給「裝置」的那個數字CPU pointer (VA) → used to memcpy the bitstream in dma_addr_t → the number to hand to the “device”CPU ポインタ(VA)  →  bitstream を memcpy で書き込むために使う
dma_addr_t          →  「デバイス」に渡すべき数値

4分歧就發生在這裡。 因為 svciommus 屬性,SMMU 配置了一個 IOVA。以示意數值說明:4This is where they diverge. Because svc has an iommus property, the SMMU allocates an IOVA. Using illustrative numbers:4食い違いはここで生じる。 svciommus プロパティを持つため、SMMU は IOVA を割り当てる。説明用の数値で示す:

bitstream 實際位於   0x8000_0000   ← 資料真正所在
dma_addr_t 回傳值    0xFFFF_0000   ← IOVA;SMMU 會把它映射到 0x8000_0000bitstream actually at 0x8000_0000 ← where the data really is dma_addr_t returned 0xFFFF_0000 ← the IOVA; the SMMU maps it to 0x8000_0000bitstream の実際の位置   0x8000_0000   ← データが本当に存在する場所
dma_addr_t の戻り値      0xFFFF_0000   ← IOVA。SMMU がこれを 0x8000_0000 へマップする

兩個數字都「正確」— 只是對負責轉譯的那一方而言才正確。Both numbers are “correct” — but each only for the party that does the translating.どちらの数値も「正しい」— ただし変換を担う側にとってのみ正しい。

5驅動程式送出 mailbox 命令給 SDM: 「bitstream 在 0xFFFF_0000,長度 N。」5The driver sends a mailbox command to the SDM: “the bitstream is at 0xFFFF_0000, length N.”5ドライバが SDM へ mailbox コマンドを送る: 「bitstream は 0xFFFF_0000 にある、長さは N」。

6SDM 的路徑上沒有 SMMU。 它不會查任何分頁表,也沒有任何映射為它而設。 它把 0xFFFF_0000 當作字面上的實體位址去讀 DRAM。6There is no SMMU on the SDM's path. It consults no page tables and no mapping exists for it. It takes 0xFFFF_0000 as a literal physical address and reads DRAM there.6SDM の経路上に SMMU は存在しない。 ページテーブルを引くこともなく、SDM のためのマッピングも存在しない。 0xFFFF_0000文字どおりの物理アドレスとして DRAM を読みにいく。

SDM 讀取的位置Where the SDM readsSDM が読む位置 資料真正的位置Where the data really isデータの真の位置 0xFFFF_0000(不相干的 DRAM)0xFFFF_0000 (unrelated DRAM)0xFFFF_0000(無関係な DRAM) 0x8000_0000(bitstream)0x8000_0000 (bitstream)0x8000_0000(bitstream) └──────────── 不一致 ────────────┘└──────────── mismatch ────────────┘└──────────── 不一致 ────────────┘

7它找不到有效的 bitstream。 沒有 section header、沒有 magic、沒有任何它認得的組態資料。 因此它不會開始寫入 CRAM,而且關鍵是 — 它永遠不會回傳「緩衝區處理完畢」的回應7It finds no valid bitstream. No section header, no magic number, no configuration data it recognises. So it never starts writing CRAM and — crucially — it never returns the “buffer processed” response.7有効な bitstream が見つからない。 section header もなく、magic もなく、認識できるコンフィギュレーションデータもない。 そのためCRAM への書き込みを開始せず、しかも決定的なことに 「バッファ処理完了」の応答を返すこともない

8驅動程式就卡在等那個回應:The driver is left waiting for that response:ドライバはその応答を待ったまま止まる:

fpga_manager fpga0: writing new40kHz4.core.rbf to Stratix10 SOC FPGA Manager
Stratix10 SoC FPGA manager firmware:svc:fpga-mgr: timeout waiting for svc layer buffers

9實際觀察到的後果:The consequences actually observed:実際に観測された結果:

結論:CRAM 從未被寫入,fabric 維持原本的組態不變。Conclusion: CRAM was never written, and the fabric keeps its original configuration.結論:CRAM は一度も書かれていない。fabric は元のコンフィギュレーションのままである。

5. 幾個容易誤解的重點5. Points that are easy to misread5. 誤解されやすい要点

① 資料一直都在正確的位置。
這是這個 bug 反直覺的地方:memcpysvcbuffer@0 是成功的, 保留區的實體位置正是 firmware 預期的位置,32 MB 容納 1.35 MB 的檔案綽綽有餘。 錯的只有 mailbox 訊息裡的那個數字。 因此「把緩衝區搬到別的位址」沒有用 — 兩端會一起搬過去,不一致依然存在。
① The data was in the right place the whole time.
This is the counter-intuitive part of the bug: the memcpy into svcbuffer@0 succeeds, the reserved region's physical location is exactly where the firmware expects it, and 32 MB is far more than enough for a 1.35 MB file. Only the number in the mailbox message is wrong. So “move the buffer somewhere else” achieves nothing — both ends move together and the mismatch remains.
① データは終始正しい場所にあった。
ここがこのバグの直感に反する点である。svcbuffer@0 への memcpy は成功しており、 予約領域の物理的な位置はまさに firmware が期待する位置で、32 MB は 1.35 MB のファイルには十分すぎる。 間違っているのは mailbox メッセージの中のあの数値だけである。 したがって「バッファを別のアドレスへ移す」ことには意味がない — 両端が一緒に移動し、不一致は残ったままになる。
② 逾時(timeout)而非錯誤(fault),正是診斷指紋。
如果是超出範圍或未映射的存取,會產生 SMMU fault 或回傳錯誤碼。 但讀到合法但錯誤的 DRAM 兩者都不會發生: SDM 看到垃圾資料,判斷沒事可做,然後就安靜了。 「沉默」正是位址轉譯不一致的特徵,而不是權限或範圍問題。
② A timeout rather than a fault is the diagnostic fingerprint.
An out-of-range or unmapped access would raise an SMMU fault or return an error code. Reading valid but wrong DRAM does neither: the SDM sees garbage, concludes there is nothing to do, and goes quiet. That silence is the signature of an address-translation mismatch, not of a permission or range problem.
② fault ではなく timeout であること自体が診断上の指紋である。
範囲外あるいは未マッピングのアクセスであれば、SMMU fault が発生するかエラーコードが返る。 しかし正当ではあるが誤った DRAM を読んだ場合はそのどちらも起こらない。 SDM はゴミデータを見て、やるべきことは何もないと判断し、そのまま黙り込む。 この「沈黙」こそがアドレス変換の不整合の特徴であり、権限や範囲の問題の特徴ではない。
nomap 是結構性的矛盾。
這個旗標存在的原因,就是因為有個非 CPU 的代理人以實體位址存取這塊區域。 把這樣的區域放在一個會轉譯的 SMMU 後面,在設計上就是自相矛盾 — 所以修正方式必須是「讓那一個裝置不要被轉譯」,而不是去調整位址。
nomap is a structural contradiction here.
The flag exists precisely because a non-CPU agent accesses this region by physical address. Placing such a region behind a translating SMMU is self-contradictory by design — so the fix has to be “stop translating for that one device”, not “adjust the address”.
③ ここでの nomap は構造的な矛盾である。
このフラグが存在する理由は、まさに CPU 以外のエージェントがこの領域を物理アドレスでアクセスするからである。 そのような領域を、変換を行う SMMU の背後に置くことは設計上そもそも自己矛盾している — だから修正は「そのデバイスだけ変換しないようにする」ことであって、「アドレスを調整する」ことではあり得ない。
④ 這也解釋了為什麼 Terasic 自己的 ada.rbf 一樣失敗。
上述流程完全不依賴 bitstream 的內容、大小,或 HPS-First / FPGA-First 設定。 失敗發生在任何一個位元的組態資料被消耗之前。 這證明問題與我們的設計無關,而是板子出廠映像檔的問題。
④ It also explains why Terasic's own ada.rbf fails identically.
Nothing in the sequence above depends on the bitstream's content or size, or on the HPS-First / FPGA-First setting. The failure happens before a single bit of configuration data is consumed. That proves the problem is unrelated to our design and lies in the board's factory image.
④ Terasic 自身の ada.rbf が同じように失敗する理由もこれで説明できる。
ここまでの流れは bitstream の内容やサイズにも、HPS-First / FPGA-First の設定にも一切依存しない。 失敗はコンフィギュレーションデータが 1 ビットも消費されない段階で起きている。 これは問題が当方の設計とは無関係で、ボードの工場出荷イメージ側にあることを示している。
altr,smmu_enable_quirk 的存在是強力線索。
device tree 的 svc 節點上同時有 iommusaltr,smmu_enable_quirk。後者的存在說明 Altera 知道 svc 與 SMMU 的組合需要特別處理 — 而逾時說明在這個 kernel build 上, 負責讀取這個 quirk 的機制並沒有生效。
⑤ The presence of altr,smmu_enable_quirk is a strong clue.
The device tree's svc node carries both iommus and altr,smmu_enable_quirk. The latter's existence shows Altera knew the svc + SMMU combination needs special handling — and the timeout shows that, on this kernel build, whatever reads that quirk did not take effect.
altr,smmu_enable_quirk が存在すること自体が強い手がかりである。
device tree の svc ノードには iommusaltr,smmu_enable_quirk の両方が付いている。後者が存在するということは、 svc と SMMU の組み合わせに特別な扱いが必要だと Altera が把握していたことを示す — そして timeout は、この kernel build ではその quirk を読む仕組みが効いていないことを示している。

6. 為什麼「換一個 SDM 能存取的位址」行不通6. Why “just use an address the SDM can reach” does not work6. 「SDM が届くアドレスに変えればよい」が通用しない理由

DMA API 不允許驅動程式說「請給我一個數值上等於實體位址的 IOVA」。 IOVA 是由 SMMU 自己的配置器從它的位址空間分配的,驅動程式只能被動接受。 沒有任何旋鈕可以要求「請 identity 映射這一塊」。 The DMA API does not allow a driver to say “give me an IOVA numerically equal to the physical address”. IOVAs are handed out by the SMMU's own allocator from its address space, and the driver can only accept what it is given. There is no knob for “please identity-map this block”.DMA API は、ドライバが「物理アドレスと数値的に等しい IOVA をください」と要求することを許していない。 IOVA は SMMU 自身のアロケータがそのアドレス空間から割り当てるものであり、ドライバは渡されたものを受け取ることしかできない。 「このブロックを identity マップしてほしい」と指定するつまみは存在しない。

真正能讓 IOVA == PA 的機制就是 identity / passthrough domain — 也就是我們實測過的 iommu.passthrough=1(全域生效,但弄壞了 SD 卡), 或是把 svc 節點的 iommus 移除(只對這一個裝置生效)。 The mechanism that genuinely makes IOVA == PA is an identity / passthrough domain — that is, the iommu.passthrough=1 we tested (global, but it broke the SD card), or removing the iommus property from the svc node (which affects only that one device).本当に IOVA == PA を成立させる仕組みは identity / passthrough ドメインである — すなわち実測した iommu.passthrough=1(全体に効くが SD カードを壊した)か、 svc ノードから iommus プロパティを取り除くか(このデバイスだけに効く)である。

7. 已排除的做法(實測結果)7. Approaches already ruled out (measured results)7. すでに除外された方法(実測結果)

測試Testテスト 參數生效?Parameter took effect?パラメータは効いたか? 板子開機?Board boots?ボードは起動するか? RBF 載入?RBF loads?RBF はロードされるか?
iommu.passthrough=1 Yesはい
Default domain type: Passthrough
失敗Failed失敗
mmc0: error -5
無法測試Could not be testedテスト不能
arm-smmu-v3.disable_bypass=0 Yesはい
但 domain 仍為 Translatedbut the domain is still Translatedただし domain は依然 Translated
正常Normal正常 相同逾時Same timeout同じ timeout
為什麼這兩個都不行:Why neither one works:この 2 つがいずれも通用しない理由:

這兩個測試剛好從兩側夾出了問題本質: 全域 passthrough 修好 svc 卻弄壞 SDHCI;保留轉譯讓 SDHCI 正常但 svc 仍失敗。 沒有任何一個 kernel 命令列參數能同時滿足兩者 — 因此修正必須是針對單一裝置的,也就是改 device tree。 Together the two tests bracket the real issue from both sides: global passthrough fixes svc but breaks SDHCI; keeping translation keeps SDHCI working but svc still fails. No kernel command-line parameter satisfies both — so the fix has to be per-device, which means changing the device tree.この 2 つのテストは、問題の本質を両側から挟み込んでいる。 全体 passthrough は svc を直すが SDHCI を壊し、変換を残せば SDHCI は正常だが svc は依然失敗する。 両方を同時に満たす kernel コマンドラインパラメータは存在しない — したがって修正はデバイス単位でなければならず、それは device tree を変更することを意味する。

8. 可行的修正方向8. Workable fixes8. 実行可能な修正方針

修正方式Fix修正方法 改變了什麼What it changes何が変わるか 代價Cost代償
移除 svc 節點的 iommus
(原本以為可行,實際不可行)
Remove iommus from the svc node
(originally believed workable; it is not)
svc ノードから iommus を取り除く
(当初は可能と考えられたが、実際には不可)
在 Agilex 5 上無效。 intel,agilex5-svc 的 probe 沒有 non-SMMU 分支: 移除後 iommu_get_dma_domain() 回傳 NULL (或走 else),一律 -ENODEVIneffective on Agilex 5. The intel,agilex5-svc probe has no non-SMMU branch: with the property removed, iommu_get_dma_domain() returns NULL (or falls to the else), giving -ENODEV every timeAgilex 5 では効果がない。 intel,agilex5-svc の probe には non-SMMU の分岐がない。 取り除くと iommu_get_dma_domain()NULL を返し (あるいは else へ落ち)、必ず -ENODEV になる svc 完全不上線fpga-mgrhwmonfcs-config 等子節點全部一起消失svc never comes up at all — the fpga-mgr, hwmon and fcs-config child nodes all disappear with itsvc がまったく起動しないfpga-mgrhwmonfcs-config といった子ノードもすべて一緒に消える
對齊 kernel + DTB + ATF 版本, 並確認 altr,smmu_enable_quirksvcfpga-mgr 兩個節點都存在 Align the kernel, DTB and ATF versions, and confirm altr,smmu_enable_quirk is present on both the svc and fpga-mgr nodes kernel + DTB + ATF のバージョンを揃え、 altr,smmu_enable_quirksvcfpga-mgr両方のノードに存在することを確認する SMMU 路徑本來就是刻意設計要能運作的: IOVA domain 0x0–0x2000_0000、 送 SDM 前加 0x8000_0000、 並以 SMC funcid 513 關掉 SDM remapperThe SMMU path was deliberately designed to work: an IOVA domain of 0x0–0x2000_0000, adding 0x8000_0000 before handing the address to the SDM, and disabling the SDM remapper via SMC funcid 513SMMU 経路はもともと意図的に動作するよう設計されている。 IOVA domain は 0x0–0x2000_0000、 SDM へ渡す前に 0x8000_0000 を加算し、 SMC funcid 513 で SDM remapper を無効化する 需版本一致;但這是這個平台的正解
詳見 dt_iommus_svc_qa_zh.html 第 6–8 節
Requires matching versions, but this is the correct fix for this platform
see sections 6–8 of dt_iommus_svc_qa_zh.html
バージョンを揃える必要はあるが、このプラットフォームではこれが正解
詳細は dt_iommus_svc_qa_zh.html の第 6–8 節を参照
修改 stratix10-svc 驅動,改傳實體位址Modify the stratix10-svc driver to pass a physical addressstratix10-svc ドライバを改造し、物理アドレスを渡すようにする 驅動在 SMC 呼叫前自行轉換The driver converts the address itself before the SMC callドライバが SMC 呼び出しの前に自分で変換する 需改 kernel 原始碼;但這在上游語意上更正確Requires kernel source changes, but is semantically more correct upstreamkernel ソースの変更が必要。ただし上流の意味論としてはこちらが正しい
更新板子的出廠映像檔 / 洽詢 TerasicUpdate the board's factory image / ask Terasicボードの工場出荷イメージを更新する / Terasic に問い合わせる 可能上游已修正It may already be fixed upstream上流ではすでに修正されている可能性がある 風險最低;但需等待Lowest risk, but you have to waitリスクは最も低いが、待たなければならない
訂正(依 linux-socfpga-6.12 原始碼,tag QPDS25.3.1_REL_FCS_FIX): 本節原先寫「SDM 根本不是 DMA master、沒有被登錄進 SMMU」, 並建議移除 iommus兩者都不成立。
Correction (based on the linux-socfpga-6.12 sources, tag QPDS25.3.1_REL_FCS_FIX): this section originally claimed that “the SDM is not a DMA master at all and is not registered with the SMMU”, and recommended removing iommus. Neither statement holds.
訂正(linux-socfpga-6.12 のソース、tag QPDS25.3.1_REL_FCS_FIX に基づく): 本節では当初「SDM はそもそも DMA master ではなく、SMMU に登録されていない」と述べ、 iommus の削除を勧めていた。そのどちらも成り立たない。
正確的理解: SMMU + svc刻意設計要能運作的組合,由 altr,smmu_enable_quirk 啟用,需要 kernel、DTB、ATF 三者版本一致: IOVA domain 為 0x0–0x2000_0000、 送 SDM 前加上 AGILEX5_SDM_DMA_ADDR_OFFSET = 0x8000_0000、 並關掉 SDM remapper。三者是同一份協定,混版即失效。 The correct understanding: SMMU + svc is a combination deliberately designed to work, enabled by altr,smmu_enable_quirk and requiring the kernel, DTB and ATF to be version-consistent: an IOVA domain of 0x0–0x2000_0000, adding AGILEX5_SDM_DMA_ADDR_OFFSET = 0x8000_0000 before handing the address to the SDM, and disabling the SDM remapper. All three are one protocol; mixing versions breaks it.正しい理解: SMMU + svc意図的に動作するよう設計された組み合わせであり、 altr,smmu_enable_quirk によって有効化され、 kernel、DTB、ATF の 3 者のバージョンが一致していることを要求する。 IOVA domain は 0x0–0x2000_0000、 SDM へ渡す前に AGILEX5_SDM_DMA_ADDR_OFFSET = 0x8000_0000 を加算し、 SDM remapper を無効化する。3 者は同一のプロトコルであり、バージョンが混ざれば成立しない。

建議的檢查順序Suggested order of checks推奨する確認手順

  1. uname -r — 對照 kernel 樹版本 (失效環境 6.12.11;含完整 quirk 支援的樹為 6.12.43)uname -r — compare against the kernel tree version (the failing environment is 6.12.11; the tree with full quirk support is 6.12.43)uname -r — kernel ツリーのバージョンと照合する (失敗する環境は 6.12.11、quirk を完全にサポートするツリーは 6.12.43)
  2. 確認 quirk 在兩個節點都存在: ls /proc/device-tree/firmware/svc/altr,smmu_enable_quirkls /proc/device-tree/firmware/svc/fpga-mgr/altr,smmu_enable_quirk
    只有一個成功 → 這就是根因:fpga-mgr 不做 dma_map_single(),svc 卻仍加 0x8000_0000
    Confirm the quirk is present on both nodes: ls /proc/device-tree/firmware/svc/altr,smmu_enable_quirk and ls /proc/device-tree/firmware/svc/fpga-mgr/altr,smmu_enable_quirk
    only one succeeding → that is the root cause: fpga-mgr does not call dma_map_single(), yet svc still adds 0x8000_0000
    quirk が両方のノードに存在することを確認する: ls /proc/device-tree/firmware/svc/altr,smmu_enable_quirkls /proc/device-tree/firmware/svc/fpga-mgr/altr,smmu_enable_quirk
    片方しか成功しない → それが根本原因である。fpga-mgr は dma_map_single() を呼ばないのに、svc は 0x8000_0000 を加算してしまう
  3. dmesg | grep -i remapper — 沒有 Failed to configure remapper!pr_info) 表示 ATF 已實作 funcid 513dmesg | grep -i remapper — the absence of Failed to configure remapper! (a pr_info) means ATF implements funcid 513dmesg | grep -i remapperFailed to configure remapper!pr_info)が出ていなければ ATF は funcid 513 を実装している
  4. 以上都正常才考慮改驅動Only consider patching the driver once all of the above check out以上がすべて問題なければ、そこで初めてドライバの改造を検討する

完整的原始碼引用與逐行分析見 dt_iommus_svc_qa_zh.html 第 6–8 節。 Full source citations and a line-by-line analysis are in sections 6–8 of dt_iommus_svc_qa_zh.html.完全なソースの引用と逐行の解析は dt_iommus_svc_qa_zh.html の第 6–8 節にある。

9. 附註:這一切不影響 mailbox 的存取9. Footnote: none of this affects mailbox access9. 補足:ここまでの話は mailbox のアクセスには影響しない

Linux 存取 fabric_avalon_uart 的路徑是:Linux reaches fabric_avalon_uart along this path:Linux が fabric_avalon_uart にアクセスする経路は次のとおりである:

CPU LWH2F bridge Avalon slave @ 0x2000_0000 ← MMIO,CPU 主動發起← MMIO, initiated by the CPU← MMIO、CPU が発行する

這是以 CPU 為發起端,所以走 MMU 而非 SMMU。因此: This is CPU-initiated, so it goes through the MMU, not the SMMU. Therefore:これはCPU 側が起点であり、SMMU ではなく MMU を通る。したがって:

這一點乾淨地把兩個問題分開了: SMMU 的 bug 只侷限於 bitstream 的「載入」階段(svc → SDM,裝置主動發起)。 一旦 fabric 完成組態,與 mailbox 通訊純粹是 MMIO,完全不受影響。 所以修其中一個不會弄壞另一個。 This cleanly separates the two problems: the SMMU bug is confined to the bitstream “load” phase (svc → SDM, device-initiated). Once the fabric is configured, talking to the mailbox is pure MMIO and is entirely unaffected. Fixing one cannot break the other.この点が 2 つの問題をきれいに切り分ける。 SMMU のバグは bitstream の「ロード」フェーズ(svc → SDM、デバイス側が起点)に限定される。 fabric のコンフィギュレーションが済んでしまえば、mailbox との通信は純粋な MMIO であり、まったく影響を受けない。 したがって一方を直しても他方が壊れることはない。