arch/arm64/kvm/vgic/vgic-v3.c
Source file repositories/reference/linux-study-clean/arch/arm64/kvm/vgic/vgic-v3.c
File Facts
- System
- Linux kernel
- Corpus path
arch/arm64/kvm/vgic/vgic-v3.c- Extension
.c- Size
- 26768 bytes
- Lines
- 1011
- Domain
- Architecture Layer
- Bucket
- arch/arm64
- Inferred role
- Architecture Layer: implementation source
- Status
- source implementation candidate
Why This File Exists
CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/irqchip/arm-gic-v3.hlinux/irq.hlinux/irqdomain.hlinux/kstrtox.hlinux/kvm.hlinux/kvm_host.hlinux/string_choices.hkvm/arm_vgic.hasm/kvm_hyp.hasm/kvm_mmu.hasm/kvm_asm.hvgic-mmio.hvgic.h
Detected Declarations
function vgic_v3_configure_hcrfunction lr_signals_eoi_mifunction vgic_v3_fold_lrfunction scoped_guardfunction vgic_v3_deactivate_physfunction vgic_v3_fold_lr_statefunction scoped_guardfunction vgic_v3_deactivatefunction vgic_v3_compute_lrfunction vgic_v3_populate_lrfunction vgic_v3_clear_lrfunction vgic_v3_set_vmcrfunction vgic_v3_get_vmcrfunction vgic_v3_resetfunction vcpu_set_ich_hcrfunction vgic_v3_lpi_sync_pending_statusfunction unmap_all_vpesfunction map_all_vpesfunction vgic_v3_save_pending_tablesfunction xa_for_eachfunction vgic_v3_rdist_overlapfunction list_for_each_entryfunction vgic_v3_check_basefunction list_for_each_entryfunction list_for_each_entryfunction list_for_each_entryfunction vgic_v3_map_resourcesfunction kvm_for_each_vcpufunction early_group0_trap_cfgfunction early_group1_trap_cfgfunction early_common_trap_cfgfunction early_gicv4_enablefunction vgic_v3_broken_seisfunction kvm_compute_ich_hcr_trap_bitsfunction vgic_v3_enable_cpuif_trapsfunction vgic_v3_probefunction vgic_v3_loadfunction vgic_v3_put
Annotated Snippet
if (is_v2_sgi) {
u8 cpuid = FIELD_GET(GICH_LR_PHYSID_CPUID, val);
if (irq->active)
irq->active_source = cpuid;
if (val & ICH_LR_PENDING_BIT)
irq->source |= BIT(cpuid);
}
/* Handle resampling for mapped interrupts if required */
vgic_irq_handle_resampling(irq, deactivated, val & ICH_LR_PENDING_BIT);
irq->on_lr = false;
}
/* Notify fds when the guest EOI'ed a level-triggered SPI, and drop the refcount */
if (deactivated && lr_signals_eoi_mi(val) && vgic_valid_spi(vcpu->kvm, intid)) {
kvm_notify_acked_irq(vcpu->kvm, 0,
intid - VGIC_NR_PRIVATE_IRQS);
atomic_dec_if_positive(&vcpu->kvm->arch.vgic.active_spis);
}
vgic_put_irq(vcpu->kvm, irq);
}
static u64 vgic_v3_compute_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq);
static void vgic_v3_deactivate_phys(u32 intid)
{
if (cpus_have_final_cap(ARM64_HAS_GICV5_LEGACY))
gic_insn(intid | FIELD_PREP(GICV5_GIC_CDDI_TYPE_MASK, 1), CDDI);
else
gic_write_dir(intid);
}
void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
{
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
struct vgic_v3_cpu_if *cpuif = &vgic_cpu->vgic_v3;
u32 eoicount = FIELD_GET(ICH_HCR_EL2_EOIcount, cpuif->vgic_hcr);
struct vgic_irq *irq = *host_data_ptr(last_lr_irq);
DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());
for (int lr = 0; lr < cpuif->used_lrs; lr++)
vgic_v3_fold_lr(vcpu, cpuif->vgic_lr[lr]);
/*
* EOIMode=0: use EOIcount to emulate deactivation. We are
* guaranteed to deactivate in reverse order of the activation, so
* just pick one active interrupt after the other in the tail part
* of the ap_list, past the LRs, and replay the deactivation as if
* the CPU was doing it. We also rely on priority drop to have taken
* place, and the list to be sorted by priority.
*/
list_for_each_entry_continue(irq, &vgic_cpu->ap_list_head, ap_list) {
u64 lr;
/*
* I would have loved to write this using a scoped_guard(),
* but using 'continue' here is a total train wreck.
*/
if (!eoicount) {
break;
} else {
guard(raw_spinlock)(&irq->irq_lock);
if (!(likely(vgic_target_oracle(irq) == vcpu) &&
irq->active))
continue;
lr = vgic_v3_compute_lr(vcpu, irq) & ~ICH_LR_ACTIVE_BIT;
}
if (lr & ICH_LR_HW)
vgic_v3_deactivate_phys(FIELD_GET(ICH_LR_PHYS_ID_MASK, lr));
vgic_v3_fold_lr(vcpu, lr);
eoicount--;
}
cpuif->used_lrs = 0;
}
void vgic_v3_deactivate(struct kvm_vcpu *vcpu, u64 val)
{
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
struct vgic_v3_cpu_if *cpuif = &vgic_cpu->vgic_v3;
u32 model = vcpu->kvm->arch.vgic.vgic_model;
Annotation
- Immediate include surface: `linux/irqchip/arm-gic-v3.h`, `linux/irq.h`, `linux/irqdomain.h`, `linux/kstrtox.h`, `linux/kvm.h`, `linux/kvm_host.h`, `linux/string_choices.h`, `kvm/arm_vgic.h`.
- Detected declarations: `function vgic_v3_configure_hcr`, `function lr_signals_eoi_mi`, `function vgic_v3_fold_lr`, `function scoped_guard`, `function vgic_v3_deactivate_phys`, `function vgic_v3_fold_lr_state`, `function scoped_guard`, `function vgic_v3_deactivate`, `function vgic_v3_compute_lr`, `function vgic_v3_populate_lr`.
- Atlas domain: Architecture Layer / arch/arm64.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.