With SecureIbex + BranchPredictor, a dummy instruction destroys a predicted-taken conditional branch
メンテナーはふだん 2 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 57/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
調査の方向性
Start by tracing branch_req, insert_dummy_instr, and stall_dummy_instr in rtl/ibex_if_stage.sv, then inspect the fetch FIFO and IF-ID handoff around the reported line 555. Reproduce with wrongpath_m.elf on the SecureIbex plus BranchPredictor configuration and compare against the no-dummy control. Done means the branch reaches execution and the test records the fall-through marker with all 15 guard increments.
索引モデルが issue の本文から書いたものです。
説明
Observed Behavior
On an Ibex elaboration with SecureIbex=1 (dummy instruction insertion enabled) and BranchPredictor=1, a conditional branch at the fetch-FIFO head is dropped when insert_dummy_instr asserts. In the matched test below, the branch is a backward blt x20,x21 with x20 == x21 == 0, so its condition is false and it must fall through; the predictor nevertheless marks the negative-offset branch as taken.
Compare the clean build against the same test with dummy insertion forced off (mut_nodummy), both from the same run:
| build | retired | guard increments (addi x11,x11,1) |
last marker stored |
|---|---|---|---|
secbp (SecureIbex + BP) |
33 | 2 | 0x00000bad at 0x00100190 |
mut_nodummy (dummies disarmed) |
57 | 15 | 0x00005eed at 0x001002dc |
ibex_simple_system_pcount.csv (divergence marked):
secbp: Cycles,73 Instructions Retired,33
mut_nodummy: Cycles,89 Instructions Retired,57 <--
The clean build's tracer log shows only the first two guard increments, then control lands at 0x00100180 (the predicted-taken target) and stores the wrong-path marker 0xBAD:
86 39 00100250 f35a48e3 blt x20,x21,100180 x20:0x00000000 x21:0x00000000
92 42 00100254 00158593 addi x11,x11,1 x11:0x00000000 x11=0x00000001
94 43 00100258 f35a44e3 blt x20,x21,100180 x20:0x00000000 x21:0x00000000
98 45 0010025c 00158593 addi x11,x11,1 x11:0x00000001 x11=0x00000002
120 56 0010018c bad60613 addi x12,x12,-1107 x12:0x00001000 x12=0x00000bad
124 58 00100190 00c4aa23 sw x12,20(x9) <-- wrong-path marker 0xBAD
0xf35a48e3 is blt x20, x21, -208. Bits [24:20] are rs2=x21 (21), bits [19:15] are rs1=x20, and bits [11:7] are immediate bits, not a register. 0x100250 + (-208) = 0x100180, which is the target printed on that line. wrongpath_m.S encodes the same word (.word 0xf35a48e3) after li x20, 0 / li x21, 0. The register names in the tracer line match the encoding.
The no-dummy control reaches all 15 increments and stores the fall-through marker 0x5EED:
160 76 001002c4 00158593 addi x11,x11,1 x11:0x0000000e x11=0x0000000f
176 84 001002dc 0064a623 sw x6,12(x9) <-- 0x5EED
No exception or ecall occurs in the test window.
Expected Behavior
Per the RISC-V Unprivileged Specification, "Conditional Branches" (rv32.adoc, section 2.5):
Branch instructions compare two registers. ... BLT and BLTU take the branch if rs1 is less than rs2, using signed and unsigned comparison respectively.
With x20 == x21 the blt must fall through and must not change the PC. Ibex's own doc/03_reference/security.rst ("Dummy Instruction Insertion") states:
The dummy instructions have no functional impact on processor state, but add some difficult-to-predict timing and power disruption to executed code.
So inserting a dummy should not remove an architectural branch. The secbp build is expected to run the same 15 guard increments as the no-dummy control.
Steps to reproduce the issue
Configuration (prebuilt elaborations):
secbp:SecureIbex=1,BranchPredictor=1,ICache=0,RV32E=0,WritebackStage=0.mut_nodummy: the same elaboration, withassign insert_dummy_instr = 1'b0;added beforeassign stall_dummy_instr = insert_dummy_instr;(rtl/ibex_if_stage.sv:555).rtl/ibex_top.sv:214setslocalparam bit DummyInstructions = SecureIbex.- Test:
wrongpath_m.elf, built bygen_wrongpath.pyfromwrongpath_m.S.
# Vibex_simple_system.secbp: SecureIbex=1, BranchPredictor=1
# Vibex_simple_system.mut_nodummy: same elaboration, insert_dummy_instr forced to 0
ELF=wrongpath_m.elf
for b in secbp mut_nodummy; do
mkdir -p runs/$b
( cd runs/$b && timeout 120 "./Vibex_simple_system.$b" \
--meminit=ram,"$ELF" -c 20000 > sim.out 2>&1 )
grep -aE 'Instructions Retired|Cycles' \
runs/$b/ibex_simple_system_pcount.csv
grep -ac 'addi.*x11,x11,1' runs/$b/trace_core_00000000.log
done
secbp: Cycles,73 Instructions Retired,33 guard_count=2
mut_nodummy: Cycles,89 Instructions Retired,57 guard_count=15
Attached: wrongpath_m.S, wrongpath_m.elf, logs/secbp/trace_core_00000000.log, logs/secbp/ibex_simple_system_pcount.csv (Cycles,73 / Instructions Retired,33), logs/mut_nodummy/trace_core_00000000.log, logs/mut_nodummy/ibex_simple_system_pcount.csv (Cycles,89 / Instructions Retired,57), gen_wrongpath.py (emits wrongpath_m.S).
My Environment
EDA tool and version: Verilator (prebuilt Vibex_simple_system.secbp and Vibex_simple_system.mut_nodummy elaborations).
Operating system: Linux 6.8.0-90-generic x86_64.
Version of the Ibex source code: official-tree commit d513671dae09e701ceb6cd732d2da5fb52c13856. The secbp elaboration is stock at that commit. The mut_nodummy control adds assign insert_dummy_instr = 1'b0; before rtl/ibex_if_stage.sv:555.
I suspect branch_req (pc_set_i | predict_branch_taken) clears the fetch FIFO without a stall_dummy_instr gate, so the dummy replaces the branch in IF-ID and the branch never reaches ID, but I have not traced it. This test runs in M-mode.
#1479 describes a predicted branch or jal that never reaches ID while insert_dummy_instr is high. The reply on that issue is about instr_valid_id_d staying low so the inserter can take a PC. Here x20 == x21 == 0, the DUT stores 0xBAD, and the no-dummy control stores 0x5EED.
- 主要言語
- SystemVerilog
- スター
- 2.2k
- フォーク
- 836
- 平均マージ
- 5日 8時間
- マージ済み PR(30日)
- 22
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
lowRISC/ibex のほかの issue
-
[Bug Report] rvfi_intr is not set on the first instruction of an exception handler対応中かも @h-filali が 7 日前に担当しました。 オープンType:Bug
難易度 2/5 半日 初心者へのやさしさ 68/100
lowRISC/ibex#2556 · コメント 1 件 ·
メンテナーはふだん 2 日以内に返信
-
Type:Bug
難易度 2/5 1〜3時間 初心者へのやさしさ 83/100
lowRISC/ibex#2528 · コメント 1 件 ·
メンテナーはふだん 2 日以内に返信
-
Type:Bug
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
メンテナーはふだん 2 日以内に返信
-
[doc] Document basic commands for running/checking Ibex対応中かも @shrutikbalwan が 47 日前に担当しました。 オープンComponent:Doc Good First Issue Type:Task
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
メンテナーはふだん 2 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 42/100
メンテナーはふだん 2 日以内に返信
似ている issue
-
parse: child keys like `007`, `1e3`, `0x1f`, `-1` make the parent an empty array and hide the valueオープン
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
-
難易度 1/5 1時間未満 初心者へのやさしさ 85/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
OCA/account-invoicing#2529 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
jlcodes99/cockpit-tools#3125 ·
メンテナーはふだん 2 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
deadfin-org/deadfin#35 ·