With SecureIbex + BranchPredictor, a dummy instruction destroys a predicted-taken conditional branch

オープン
#2,568 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 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 の本文から書いたものです。

説明

Type:Bug

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, with assign insert_dummy_instr = 1'b0; added before assign stall_dummy_instr = insert_dummy_instr; (rtl/ibex_if_stage.sv:555). rtl/ibex_top.sv:214 sets localparam bit DummyInstructions = SecureIbex.
  • Test: wrongpath_m.elf, built by gen_wrongpath.py from wrongpath_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.

testcase.zip

主要言語
SystemVerilog
スター
2.2k
フォーク
836
平均マージ
5日 8時間
マージ済み PR(30日)
22

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

lowRISC/ibex のほかの issue

lowRISC/ibex の issue をすべて見る

似ている issue

Backend & API Design の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。