Skip to content

refactor: migrate RISC-V and LoongArch virtual IPIs off PERCPU_EVENTS - #415

Open
peikachu wants to merge 4 commits into
syswonder:devfrom
peikachu:refactor/remove-percpu-events-stage2
Open

peikachu wants to merge 4 commits into
syswonder:devfrom
peikachu:refactor/remove-percpu-events-stage2

Conversation

@peikachu

@peikachu peikachu commented Nov 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

Continues removing PERCPU_EVENTS (follow-up to #407) by moving RISC-V and LoongArch virtual IPIs from the event FIFO to per-vCPU interrupt state.

  • refactor(irqchip): move per-vCPU IRQ hooks into each architecture: Each architecture now supplies GUEST_IRQ_NR (GIC vINTIDs, RISC-V hvip bits, LoongArch ESTAT.IS lines 0..=12, x86 vectors), ArchVcpu::prepare_post(), flush_guest_irqs() and VCPU_KICK_DOORBELL, so the common post_guest_irq(), kick_vcpu() and flush_current_guest_irqs() no longer contain GIC-specific cfg blocks. The GICv2 SGI source update and same-source coalescing move from the common post_guest_irq() into the AArch64 ArchVcpu::prepare_post(). x86 only gets stubs; its interrupts still go through PENDING_VECTORS.
  • refactor(riscv64): post SBI IPIs through per-vCPU state: SBI send_ipi posts IRQ_VS_SOFT to the target vCPU instead of queuing IPI_EVENT_SEND_IPI. Pending bits are flushed into hvip on guest entry and on trap/interrupt return.
  • refactor(irqchip): add level-triggered lines to guest IRQ state: Adds per-architecture GUEST_LINES, plus line_dirty, set_level() and take_dirty_lines() to GuestCpuIrqState. post_guest_irq() takes a level argument. Edge numbers keep their existing behavior (level = true; rejected when the zone is missing or the vCPU is Stopped). Level numbers are only rejected when the zone is missing, and they kick only when the level changes. Claiming and has_pending_edges() skip level numbers.
  • refactor(loongarch64): move virtual IPI state into ArchVcpu as a level line: IPI status/enable/mailbox registers move from global per-CPU statics into ArchVcpu (VirtIpiRegs). update_ipi_status() updates status under status_lock and posts INT_IPI as a level line when the status changes between zero and non-zero. _vcpu_return() syncs dirty lines to ESTAT. IPI_EVENT_SEND_IPI, sync_virtual_ipi_line(), arch_send_virtual_ipi() and the unused emulate_iocsr_legacy() are removed.

Motivation

Virtual IPIs routed through the shared event FIFO take the queue lock, may allocate, and are coupled to host event dispatch. As in #407 for AArch64, the producer now publishes pending state on the target vCPU before kicking its pCPU, and the target installs the interrupt on its own guest entry. LoongArch IPI status is level-like (INT_IPI stays asserted while IPI_STATUS is non-zero), so it is modeled as a level line instead of an edge. Level lines also prepare for the later RISC-V vPLIC (VSEIP) and LoongArch HWI migrations.

Verification

Platform What was run Result
aarch64 qemu-gicv3, riscv64 qemu-plic/qemu-aia zone0 load → insmod hvisor.ko → virtio backend → zone start → zone1 shell and load → zone shutdown -id 1 → zone0 load Passed
aarch64 qemu-gicv2 Same flow up to the zone1 load; zone shutdown not run (GICv2 arch_irqchip_reset() is unimplemented) Passed
loongarch64 QEMU/hardware Not run (no environment available)

"Load" runs more shell busy-loop processes than the zone has vCPUs (8 in zone0, 4 in zone1); process creation, exit and wakeups exercise cross-CPU IPIs.

Risks and Limitations

  • LoongArch is compile-tested only.
  • Not yet migrated: RISC-V vPLIC hart line, virtio IRQs, LoongArch HWI, DWC MSI and virtio-pci events. The legacy FIFO remains for these.
  • The pinned pCPU:vCPU mapping is unchanged.

@liulog

liulog commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

The reason for introducing IPI_EVENT_UPDATE_HART_LINE is that the PLIC broadcasts to all HARTs capable of handling the interrupt, rather than sending it point-to-point; I hope this proves helpful for your future migration.

Simulated this behavior by broadcasting via IPI.

From the ratified PLIC spec (Interrupt Notifications):

The PLIC hardware only supports multicasting of interrupts, such that all enabled targets will receive interrupt notifications for a given active interrupt.

@peikachu

peikachu commented Nov 4, 2026

Copy link
Copy Markdown
Collaborator Author

@liulog Thanks for the reminder. When I migrate IPI_EVENT_UPDATE_HART_LINE later, I will keep the multicast semantics.

Comment thread src/device/irqchip/mod.rs
Comment on lines +37 to +44
/// Post a guest IRQ to the target vCPU and kick its pCPU. `source_cpu` is used
/// only by GICv2; `level` is the new line value, or `true` for an edge.
pub fn post_guest_irq(
target_cpu: usize,
irq_id: usize,
source_cpu: Option<usize>,
level: bool,
) -> bool {

@agicy agicy Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It sounds not good in some cases we must suppose some parameters should be some specific values (an edge then level=true).

A minimal modification is to split this into two functions but may introduce more complexity.

@li041 Any suggestions?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Acctually only la may call this function with false. Other arch implements edge model.

However, I suggest keeping this parameter which outlines the model of interrupt handling. Futhermore, we can use enum instead of bool, and may have more detailed comment on this diff.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Thanks. I will use enum instead of bool. BTW, besides LoongArch, the follow-up RISC-V vPLIC migration also drives VSEIP as a level line, so the level path won’t stay LoongArch-only.

@peikachu
peikachu force-pushed the refactor/remove-percpu-events-stage2 branch from 03a9edc to fd42eab Compare November 9, 2026 08:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants