APLIC: clear level-sensitive MSI pending bit when the rectified input is low#47
Open
dreamqin68 wants to merge 1 commit into
Open
APLIC: clear level-sensitive MSI pending bit when the rectified input is low#47dreamqin68 wants to merge 1 commit into
dreamqin68 wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR fixes a stale pending-bit case for level-sensitive APLIC sources in MSI
delivery mode.
For a valid active Level1/Level0 source with
domaincfg.DM = 1, the currentips.wBitUIhelper gates every pending-bit write byintSrcsRectified(ui):That gate correctly prevents setting a level-sensitive pending bit while the
rectified input is low, but it also blocks clears. As a result, if a source
deasserts after its pending bit was already set, the pending bit can remain set.
If an MSI was already forwarded, the later ack clear can also be blocked by the
same gate.
Impact
Software can observe a stale pending bit when reading
setip. A stale sourcecan also be forwarded again as a spurious MSI after the original level input has
already deasserted.
Spec Anchor
RISC-V AIA (
riscv-aiacommit9507866427961d4ec2d2400ea875103b2a09520b, 20250312 revision),src/AdvPLIC.adoc, "Precise effects on interrupt-pending bits" / Level1and Level0 source behavior in MSI delivery mode, raw
src/AdvPLIC.adoclines1013-1027 in that source revision, says:
So low rectified input must clear pending, and forwarded-MSI ack/clear must not
be suppressed by the current low rectified input.
Minimal Reproducer Shape
Focused architectural state:
domaincfg.DM = 1/ MSI delivery modeExpected by AIA:
Observed before this patch in a focused generated-RTL replay:
low_rectified_without_ack: pending remains setack_after_forwarded_msi: pending remains setObserved after this patch in the same replay:
low_rectified_without_ack: pending clearsack_after_forwarded_msi: pending clearsThe patch also adds a cocotb regression,
aplic_level_msi_pending_clear_on_low_test, that uses the existingtest/aplicregister-access helpers to programdomaincfg/sourcecfg, drivethe external
intSrcs_Npins, and readsetipsfor both Level1 and Level0.That regression is still a focused APLIC test, not a full-system XiangShan
cosim.
Root Cause
The common root cause is that
ips.wBitUIgates all Level1/Level0 MSI-deliverypending-bit writes by
intSrcsRectified(ui). That predicate is right forset-to-one writes, but wrong for clear-to-zero writes.
This shows up in two places:
source-trigger block calls
ips.wBitUI(i.U, true.B)on a trigger, but thereis no matching
ips.wBitUI(i.U, false.B)for Level1/Level0 MSI-deliverysources while the rectified input is low.
(
ips.wBitUI(topi, false.B)) and explicit clear-register paths, can beblocked by the same rectified-input gate.
Fix
This patch does two things:
ips.wBitUIhelper so clear-to-zero writes reachips.bitseven when the current rectified input is low, while set-to-onewrites remain blocked when low.
when the rectified input is low, so source deassertion clears stale pending
state without relying on a later MSI ack.
The first change is not an ack-only special case: the new low-rectified clear
path also calls
ips.wBitUI(i.U, false.B), so without the helper change itwould be blocked by the original gate. Keeping all clear writes in
wBitUIalso preserves one central pending-bit write rule for explicit
clrip/in_clripclears and MSI-ack clears.
There is also a real timing window for the forwarded-MSI case. When the MSI
request A-channel fires,
Domainenterswaiting_ack; the pending bit is notcleared until the later D-channel ack. During that wait, the synchronized
rectified input can become low. In that state, both the low-rectified clear
request and the eventual ack clear are clear-to-zero writes, so they must not be
rejected by the old
intSrcsRectified(ui)set-write gate.Patch diff:
The patch is intentionally narrow: edge-triggered sources continue to use the
existing path, and set-to-one writes for Level1/Level0 MSI sources are still
blocked when the rectified input is low.
Write ordering follows the existing last-connect structure in
Domain:register-map writes are connected first, source-trigger updates are connected
next, and the MSI ack clear is connected last. The new low-rectified clear and
the trigger set are mutually exclusive in the same source-update block:
low-clear requires
!intSrcsRectified(i), whiletriggerisintSrcsRectified(i) && !RegNext(intSrcsRectified(i)). If a set-to-one writecollides with a low rectified input, the low-clear wins, which is the required
AIA behavior; if a later MSI ack also clears, it writes the same
falsevalue.The explicit low-clear branch intentionally calls
ips.wBitUIinstead ofwriting
bitsdirectly so the normal active/level/MSI pending-write semanticsremain centralized in one helper.
This patch follows the current AIA text for the level-sensitive MSI race
discussed in riscv/riscv-aia#58: when the rectified input becomes low, the
pending bit is cleared. If a level source asserts and then deasserts before an
MSI is forwarded, this implementation does not retain an extra latched
interrupt after deassertion; it reflects the spec rule that a Level1/Level0 MSI
pending bit is never set while the rectified input is low.
Validation
I checked the two load-bearing scenarios with a focused generated-RTL replay of
Domain.I also added
aplic_level_msi_pending_clear_on_low_testto the existingcocotb APLIC test. It covers the register-programmed Level1 and Level0
clear-on-low path through
setips. It intentionally leaves domain interruptenable and MSI targets unconfigured, so MSI forwarding cannot consume the
pending bit while the test is observing pending set/clear behavior; forwarding
itself is already covered by the existing
aplic_msi_test.The load-bearing cocotb check is non-vacuous: the same testcase fails on
unpatched generated RTL and passes on patched generated RTL:
PYTHONPATH=$PWD/test make -C test/aplic \ TESTCASE=aplic_level_msi_pending_clear_on_low_test \ SIM=verilator EXTRA_ARGS=--traceThe run reports
TESTS=1 PASS=1 FAIL=0 SKIP=0at 71.5 ns of simulated time.On unpatched generated RTL, the same testcase reports
TESTS=1 PASS=0 FAIL=1 SKIP=0at 38 ns, failing after a Level1 sourcedeassertion because the
setipspending bit remains set.The
ack_after_forwarded_msisubcase is covered by the focusedDomainreplayabove. The cocotb regression is intentionally the normal register-programmed
clear-on-low path; after that low-clear fix is present, a top-level APLIC+IMSIC
test no longer isolates the later ack clear without adding internal
response-stall/poke machinery.
Public Context
I did not find an existing ChiselAIA/XiangShan implementation report or fix for
this stale-pending clear case.
The RISC-V AIA specification discussions riscv/riscv-aia#58 and
riscv/riscv-aia#130 discuss Level-sensitive APLIC behavior in MSI mode and are
consistent with the clear-on-low / clear-on-forwarding reading above. They are
specification-context discussions, not ChiselAIA implementation reports for
this bug.
Scope
This PR fixes the focused APLIC pending-bit behavior. The validation above
does not claim full-system XiangShan cosim.