PLIC Block Diagram
--- config: layout: dagre --- flowchart LR classDef file fill:#FFFFFF,stroke:#111,stroke-width:3px,color:#111 classDef source fill:#E9F1FF,stroke:#111,stroke-width:2px,color:#111 classDef iface fill:#EDE7D4,stroke:#111,stroke-width:2px,color:#111 classDef backend fill:#F8F8F8,stroke:#111,stroke-width:2px,color:#111 subgraph DEV["external interrupt sources"] direction TB UART_HW["UART hardware<br/><br/>UART0_IRQ = 10"]:::source VIRTIO_HW["virtio disk hardware<br/><br/>VIRTIO0_IRQ = 1"]:::source end subgraph SETUP["PLIC setup interface"] direction TB PLICINIT["plicinit()<br/><br/>set device priorities"]:::iface PLICINITHART["plicinithart()<br/><br/>enable device IRQs for this hart<br/>set threshold = 0"]:::iface end subgraph PLIC_BOX["PLIC hardware state"] direction TB PLIC_STATE["PLIC<br/><br/>tracks pending external IRQs<br/>checks priority / enable / threshold<br/>routes IRQ to a hart<br/>supports claim + complete"]:::source end subgraph TRAP["trap-side interface"] direction TB CPU["RISC-V hart<br/><br/>supervisor external interrupt<br/>scause = external interrupt"]:::process DEVINTR["devintr()<br/><br/>classify interrupt<br/>external device / timer / unknown"]:::iface CLAIM["plic_claim()<br/><br/>read claimed IRQ number"]:::iface COMPLETE["plic_complete(irq)<br/><br/>mark IRQ as handled"]:::iface end subgraph BACKEND["driver backend after IRQ dispatch"] direction TB UARTINTR["uartintr()<br/><br/>console interrupt handler"]:::backend VIRTIOINTR["virtio_disk_intr()<br/><br/>disk interrupt handler"]:::backend UNKNOWN["unexpected irq<br/><br/>print warning"]:::backend end subgraph NONPLIC["not PLIC path"] direction TB TIMER["supervisor timer interrupt<br/><br/>clockintr()<br/>does not use PLIC"]:::backend end PLICINIT -->|"configures priorities"| PLIC_STATE PLICINITHART -->|"configures per-hart enables"| PLIC_STATE UART_HW -->|"raises IRQ 10"| PLIC_STATE VIRTIO_HW -->|"raises IRQ 1"| PLIC_STATE PLIC_STATE -->|"delivers external interrupt"| CPU CPU -->|"trap enters kernel"| DEVINTR DEVINTR -->|"external interrupt branch"| CLAIM CLAIM -->|"reads claim register"| PLIC_STATE CLAIM -->|"irq == UART0_IRQ"| UARTINTR CLAIM -->|"irq == VIRTIO0_IRQ"| VIRTIOINTR CLAIM -->|"other nonzero irq"| UNKNOWN UARTINTR -->|"handled"| COMPLETE VIRTIOINTR -->|"handled"| COMPLETE UNKNOWN -->|"handled / reported"| COMPLETE COMPLETE -->|"writes completion"| PLIC_STATE DEVINTR -.->|"timer branch bypasses PLIC"| TIMER