With SecureIbex + BranchPredictor, a dummy instruction destroys a predicted-taken conditional branch
Maintainer thường phản hồi trong vòng 2 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 57/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Lĩnh vực
- backend-api-design
Hướng nghiên cứu
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.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
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.
- Ngôn ngữ chính
- SystemVerilog
- Star
- 2.2k
- Fork
- 836
- Merge trung bình
- 5 ngày 8 giờ
- Pull request đã merge (30 ngày)
- 22
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của lowRISC/ibex
-
[Bug Report] rvfi_intr is not set on the first instruction of an exception handlerCó thể đã có người làm @h-filali đã nhận 7 ngày trước. Đang mởType:Bug
Độ khó 2/5 Nửa ngày Mức phù hợp với người mới 68/100
lowRISC/ibex#2556 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Type:Bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 83/100
lowRISC/ibex#2528 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 2 ngày
-
mip documentation errorĐang mởType:Bug
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
Maintainer thường phản hồi trong vòng 2 ngày
-
[doc] Document basic commands for running/checking IbexCó thể đã có người làm @shrutikbalwan đã nhận 47 ngày trước. Đang mởComponent:Doc Good First Issue Type:Task
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
lowRISC/ibex#741 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 42/100
Maintainer thường phản hồi trong vòng 2 ngày
Issue tương tự
-
parse: child keys like `007`, `1e3`, `0x1f`, `-1` make the parent an empty array and hide the valueĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 85/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
OCA/account-invoicing#2529 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
jlcodes99/cockpit-tools#3125 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
deadfin-org/deadfin#35 ·