Skip to content

Fix incorrect mip.SEIP handling by adding hardware SEIP latch & correcting PLIC aliasing#2218

Open
rmkhurana28 wants to merge 2 commits intoriscv-software-src:masterfrom
rmkhurana28:fix-mip-seip-ordering
Open

Fix incorrect mip.SEIP handling by adding hardware SEIP latch & correcting PLIC aliasing#2218
rmkhurana28 wants to merge 2 commits intoriscv-software-src:masterfrom
rmkhurana28:fix-mip-seip-ordering

Conversation

@rmkhurana28
Copy link
Copy Markdown

This PR fixes a long-standing correctness issue in Spike’s handling of the
Supervisor External Interrupt Pending bit (mip.SEIP).

Root Cause

SEIP was incorrectly read/written directly through mip->val,
causing mismatches when:

  • mvien.SEIP = 0 (SEIP is aliased to mvip)
  • mvien.SEIP = 1 (SEIP must come only from hardware/PLIC)
  • PLIC needs to set/clear SEIP independently of software writes

Fix

This PR introduces a hardware SEIP latch inside mip_csr_t and updates all
call sites to follow the correct read/write ordering.

Changes:

  • Added seip_hw_latch field to mip_csr_t
  • Updated mip_csr_t::read() to merge hvip + mvip alias + hardware latch
  • Updated mip_csr_t::backdoor_write_with_mask() to route SEIP writes properly
  • Fixed plic_t::context_update() to respect mvien.SEIP aliasing rules
  • Added set_seip_hw_latch() for safe PLIC updates

Result

This restores correct SEIP semantics according to privileged spec 1.12, improves
behavior under virtualization (H-extension), and eliminates SEIP mis-ordering.

This is a correctness fix (not a functional extension), and has no effect unless
SEIP is toggled via hardware or mvien.

Copilot AI review requested due to automatic review settings January 21, 2026 18:20
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR attempts to fix the handling of the Supervisor External Interrupt Pending (SEIP) bit in Spike's implementation of the RISC-V privileged specification by introducing a hardware SEIP latch and updating the interaction between mip, mvip, mvien, and the PLIC.

Changes:

  • Added a seip_hw_latch field to mip_csr_t to track hardware-pending SEIP state
  • Updated mip_csr_t::read() to merge the hardware latch with other interrupt sources
  • Modified mip_csr_t::backdoor_write_with_mask() to route SEIP writes to the hardware latch
  • Changed plic_t::context_update() to check mvien.SEIP and conditionally update either mvip or the hardware latch

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
riscv/csrs.h Adds seip_hw_latch field and set_seip_hw_latch() method to mip_csr_t class
riscv/csrs.cc Implements hardware latch read logic and updates backdoor write handling for SEIP
riscv/plic.cc Modifies PLIC context update to respect mvien.SEIP aliasing when setting SEIP

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +139 to +145
// If mvien.SEIP == 0 → SEIP is aliased to mvip (virtual interrupt)
if (!(c->proc->state.mvien->read() & MIP_SEIP)) {
c->proc->state.mvip->write_with_mask(MIP_SEIP, pending);
} else {
// Otherwise SEIP is physical → update hardware latch, not mip.val
mip->set_seip_hw_latch((pending & MIP_SEIP) ? MIP_SEIP : 0);
}
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PLIC logic only handles the SEIP case (when c->mmode is false) but doesn't handle MEIP (when c->mmode is true). When handling machine-mode contexts (MEIP), the code should use backdoor_write_with_mask to update mip directly since mvien/mvip only apply to supervisor interrupts. The current implementation will incorrectly attempt to check mvien and update mvip or seip_hw_latch for MEIP, which is not correct behavior.

Copilot uses AI. Check for mistakes.
riscv/csrs.cc Outdated
}

// For all other bits, perform the normal backdoor write
this->val = (this->val & ~mask) | (val & mask);
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The backdoor_write_with_mask function has a logic error. When mask contains MIP_SEIP, the function updates both seip_hw_latch (lines 842-843) and this->val (line 847). This means the SEIP bit will be set in both places, which will be OR'd together in the read() function (line 830 and potentially in val). The line 847 should exclude MIP_SEIP from the mask when updating this->val to prevent double-setting the SEIP bit.

Suggested change
this->val = (this->val & ~mask) | (val & mask);
const reg_t non_seip_mask = mask & ~MIP_SEIP;
this->val = (this->val & ~non_seip_mask) | (val & non_seip_mask);

Copilot uses AI. Check for mistakes.
riscv/plic.cc Outdated
reg_t mask = c->mmode ? MIP_MEIP : MIP_SEIP;

c->proc->state.mip->backdoor_write_with_mask(mask, best_id ? mask : 0);
// Determine SEIP pending status from PLIC
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment on line 133 says "Determine SEIP pending status from PLIC" but this is misleading because the variable 'mask' on line 131 can be either MIP_MEIP or MIP_SEIP depending on whether the context is in machine mode or supervisor mode. The comment should be more generic to reflect that this line determines the pending status for either MEIP or SEIP.

Suggested change
// Determine SEIP pending status from PLIC
// Determine external interrupt pending (MEIP/SEIP) status from PLIC

Copilot uses AI. Check for mistakes.
@rmkhurana28
Copy link
Copy Markdown
Author

Updated the PR to address all follow-up issues:

• Correct MEIP bypass logic (MEIP no longer goes through SEIP/mvien/mvip path)
• SEIP is now fully isolated from software-writable mip.val
• PLIC update logic now cleanly separates machine-mode vs supervisor-mode paths
• Comments updated for clarity

This version reflects proper interrupt routing per RISC-V Privileged Spec v1.12.

@rmkhurana28 rmkhurana28 requested a review from Copilot January 21, 2026 19:38
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@rmkhurana28 rmkhurana28 requested a review from Copilot January 21, 2026 21:18
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants