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 を生むのか、その全解析
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 都無效)。
[ 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/state は write のまま止まり、書き込み中のプロセスは割り込み不能なスリープ(D 状態、kill -9 でも落ちない)に入る。要理解這個問題,必須先分清楚三種位址。很多人把它們混為一談, 但它們是三個不同的東西: 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 のどこにあるか」とは別の問いである。両者が等しい保証はない。| 情境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-direct)The 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(別途確認が必要) |
兩者都是位址轉譯器,差別在於替誰轉譯。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デバイスが触れてはならないメモリへ書き込むこと |
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 / ioremap) | CPU 的 MMU | 否 |
| 裝置 → 記憶體(DMA / bus-master) | SMMU | 是 |
iommus governs only accesses that the device itself initiates. Direction matters: | Direction | Translated by | Affected by iommus? |
|---|---|---|
CPU → device registers (MMIO / ioremap) | the CPU's MMU | No |
| Device → memory (DMA / bus-master) | the SMMU | Yes |
iommus が管轄するのは「デバイス自身が発行する」アクセスだけである。方向が重要になる:| 方向 | 変換する主体 | iommus の影響を受けるか? |
|---|---|---|
CPU → デバイスのレジスタ(MMIO / ioremap) | CPU の MMU | いいえ |
| デバイス → メモリ(DMA / bus-master) | SMMU | はい |
| 當事人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 propertyIOVA — iommus プロパティを持つため |
是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 のデバイスではない |
stratix10-svc(compatible = "intel,agilex5-svc")。
它位於 device tree 的 /firmware/svc(注意是 /firmware 而非 /soc,
因為它是軟體服務,不是記憶體映射週邊)。底下掛了三個服務:
fpga-mgr(FPGA 組態)、fcs-hal(加密服務)、hwmon(電壓溫度)。SVC (service layer): the service-layer driver through which Linux talks to the SDM, namely stratix10-svc (compatible = "intel,agilex5-svc"). It lives at /firmware/svc in the device tree (note /firmware, not /soc, because it is a software service rather than a memory-mapped peripheral). Three services hang beneath it: fpga-mgr (FPGA configuration), fcs-hal (cryptographic services) and hwmon (voltage and temperature).SVC(service layer):Linux 側が SDM と通信するためのサービス層ドライバ、すなわち stratix10-svc(compatible = "intel,agilex5-svc")である。device tree 上では /firmware/svc に置かれる(/soc ではなく /firmware である点に注意。メモリマップドな周辺回路ではなくソフトウェアサービスだからである)。その下に fpga-mgr(FPGA コンフィギュレーション)、fcs-hal(暗号サービス)、hwmon(電圧・温度)の 3 つのサービスがぶら下がる。
所以錯誤訊息 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 クライアント、という意味である。
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分歧就發生在這裡。
因為 svc 有 iommus 屬性,SMMU 配置了一個 IOVA。以示意數值說明:4This is where they diverge. Because svc has an iommus property, the SMMU allocates an IOVA. Using illustrative numbers:4食い違いはここで生じる。
svc が iommus プロパティを持つため、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 を読みにいく。
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:実際に観測された結果:
state 卡在 write — FPGA manager 從未離開寫入階段state stuck at write — the FPGA manager never leaves the write phasestate が write のまま止まる — FPGA manager が書き込みフェーズから抜けないD state(不可中斷睡眠),
Ctrl-C 與 kill -9 都無效The writing process enters D state (uninterruptible sleep); neither Ctrl-C nor kill -9 has any effect書き込みプロセスが D state(割り込み不可のスリープ)に入り、
Ctrl-C も kill -9 も効かないsystemd-journald 也一起卡住並觸發 watchdog 失敗systemd-journald hangs alongside it and trips a watchdog failuresystemd-journald も巻き込まれて停止し、watchdog 失敗を引き起こす結論:CRAM 從未被寫入,fabric 維持原本的組態不變。Conclusion: CRAM was never written, and the fabric keeps its original configuration.結論:CRAM は一度も書かれていない。fabric は元のコンフィギュレーションのままである。
memcpy 進 svcbuffer@0 是成功的,
保留區的實體位置正是 firmware 預期的位置,32 MB 容納 1.35 MB 的檔案綽綽有餘。
錯的只有 mailbox 訊息裡的那個數字。
因此「把緩衝區搬到別的位址」沒有用 — 兩端會一起搬過去,不一致依然存在。
① The data was in the right place the whole time.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 メッセージの中のあの数値だけである。
したがって「バッファを別のアドレスへ移す」ことには意味がない — 両端が一緒に移動し、不一致は残ったままになる。nomap 是結構性的矛盾。nomap is a structural contradiction here.nomap は構造的な矛盾である。ada.rbf 一樣失敗。ada.rbf fails identically.ada.rbf が同じように失敗する理由もこれで説明できる。altr,smmu_enable_quirk 的存在是強力線索。svc 節點上同時有 iommus 與
altr,smmu_enable_quirk。後者的存在說明 Altera 知道
svc 與 SMMU 的組合需要特別處理 — 而逾時說明在這個 kernel build 上,
負責讀取這個 quirk 的機制並沒有生效。
⑤ The presence of altr,smmu_enable_quirk is a strong clue.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 が存在すること自体が強い手がかりである。svc ノードには iommus と
altr,smmu_enable_quirk の両方が付いている。後者が存在するということは、
svc と SMMU の組み合わせに特別な扱いが必要だと Altera が把握していたことを示す —
そして timeout は、この kernel build ではその quirk を読む仕組みが効いていないことを示している。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 プロパティを取り除くか(このデバイスだけに効く)である。
| 測試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 |
iommu.passthrough=1 讓所有裝置 IOVA == PA。
svc 因此可以運作,但 sdhci-cdns 原本依賴 IOMMU 配置的位址窗,
改為 identity 映射後它的 descriptor 無法表達那些位址 —
於是出現 DMA 0x0000000000000000, LEN 0x0000 與
mmc0: error -5 whilst initialising SD card,root filesystem 掛不起來。iommu.passthrough=1 makes IOVA == PA for every device. That lets svc work, but sdhci-cdns relied on the address window the IOMMU had allocated; under identity mapping its descriptors cannot express those addresses — hence DMA 0x0000000000000000, LEN 0x0000 and mmc0: error -5 whilst initialising SD card, and the root filesystem fails to mount.iommu.passthrough=1 はすべてのデバイスで IOVA == PA にする。
これで svc は動くようになるが、sdhci-cdns は IOMMU が割り当てたアドレス窓に依存していたため、
identity マッピングに変わると descriptor がそのアドレスを表現できなくなる —
その結果 DMA 0x0000000000000000, LEN 0x0000 と
mmc0: error -5 whilst initialising SD card が出て、root filesystem がマウントできなくなる。arm-smmu-v3.disable_bypass=0 只影響
沒有 device tree IOMMU 對應的 stream ID。
stratix10-svc 有明確的 iommus 屬性,
所以無論如何都會拿到會轉譯的 domain。arm-smmu-v3.disable_bypass=0 only affects stream IDs that have no device-tree IOMMU mapping. stratix10-svc has an explicit iommus property, so it gets a translating domain regardless.arm-smmu-v3.disable_bypass=0 が影響するのは、
device tree に IOMMU マッピングを持たない stream ID だけである。
stratix10-svc には明示的な iommus プロパティがあるため、
いずれにせよ変換を行う domain が割り当てられる。這兩個測試剛好從兩側夾出了問題本質: 全域 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 を変更することを意味する。
| 修正方式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-mgr、hwmon、fcs-config
等子節點全部一起消失svc never comes up at all — the fpga-mgr, hwmon and fcs-config child nodes all disappear with itsvc がまったく起動しない —
fpga-mgr、hwmon、fcs-config
といった子ノードもすべて一緒に消える |
✓ 對齊 kernel + DTB + ATF 版本,
並確認 altr,smmu_enable_quirk
在 svc 與 fpga-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_quirk が
svc と fpga-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 platformsee 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。兩者都不成立。
StreamID 10;它另有一顆自己的 remapper,
SMMU 啟用時由驅動以 SMC funcid 513 關閉。intel,agilex5-svc 的 probe 沒有 non-SMMU 分支 —
移除 iommus 只會得到 -ENODEV,
svc 與其所有子節點全部不上線。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. StreamID 10; it also has a remapper of its own, which the driver disables with SMC funcid 513 when the SMMU is enabled.intel,agilex5-svc probe has no non-SMMU branch — removing iommus only yields -ENODEV, and svc plus all of its child nodes fail to come up.linux-socfpga-6.12 のソース、tag QPDS25.3.1_REL_FCS_FIX に基づく):
本節では当初「SDM はそもそも DMA master ではなく、SMMU に登録されていない」と述べ、
iommus の削除を勧めていた。そのどちらも成り立たない。
StreamID 10 に対応する。さらに自前の remapper を備えており、
SMMU 有効時にはドライバが SMC funcid 513 でこれを無効化する。intel,agilex5-svc の probe にはnon-SMMU の分岐がない —
iommus を取り除いても -ENODEV になるだけで、
svc とそのすべての子ノードが起動しなくなる。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 者は同一のプロトコルであり、バージョンが混ざれば成立しない。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)ls /proc/device-tree/firmware/svc/altr,smmu_enable_quirk 與
ls /proc/device-tree/firmware/svc/fpga-mgr/altr,smmu_enable_quirk
dma_map_single(),svc 卻仍加 0x8000_0000Confirm 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 dma_map_single(), yet svc still adds 0x8000_0000quirk が両方のノードに存在することを確認する:
ls /proc/device-tree/firmware/svc/altr,smmu_enable_quirk と
ls /proc/device-tree/firmware/svc/fpga-mgr/altr,smmu_enable_quirk
dma_map_single() を呼ばないのに、svc は 0x8000_0000 を加算してしまう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 remapper —
Failed to configure remapper!(pr_info)が出ていなければ
ATF は funcid 513 を実装している
完整的原始碼引用與逐行分析見 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 節にある。
Linux 存取 fabric_avalon_uart 的路徑是:Linux reaches fabric_avalon_uart along this path:Linux が fabric_avalon_uart にアクセスする経路は次のとおりである:
這是以 CPU 為發起端,所以走 MMU 而非 SMMU。因此: This is CPU-initiated, so it goes through the MMU, not the SMMU. Therefore:これはCPU 側が起点であり、SMMU ではなく MMU を通る。したがって:
iommus 屬性 — 它不做 bus-master,只被動回應The mailbox needs no iommus property at all — it is never a bus master, only a passive respondermailbox には iommus プロパティはまったく不要である — bus master にはならず、受動的に応答するだけであるsvc 的 SMMU 設定改動(iommus、
altr,smmu_enable_quirk、版本對齊)
都不可能影響驅動讀寫 DATA/STATUS/CONTROLNo change to svc's SMMU configuration (iommus, altr,smmu_enable_quirk, version alignment) can possibly affect the driver reading and writing DATA/STATUS/CONTROLsvc の SMMU 設定(iommus、
altr,smmu_enable_quirk、バージョン整合)をどう変更しても、
ドライバによる DATA/STATUS/CONTROL の読み書きに
影響を与えることはあり得ないreg = <0x0 0x20000000 0x0 0x10>
是給 ioremap 用的實體位址,與 SMMU 無關The reg = <0x0 0x20000000 0x0 0x10> in the overlay is a physical address for ioremap and has nothing to do with the SMMUoverlay にある reg = <0x0 0x20000000 0x0 0x10> は
ioremap のための物理アドレスであり、SMMU とは無関係である