arch/arm64/kvm/vgic/vgic-mmio.c
Source file repositories/reference/linux-study-clean/arch/arm64/kvm/vgic/vgic-mmio.c
File Facts
- System
- Linux kernel
- Corpus path
arch/arm64/kvm/vgic/vgic-mmio.c- Extension
.c- Size
- 28750 bytes
- Lines
- 1132
- 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/bitops.hlinux/bsearch.hlinux/interrupt.hlinux/irq.hlinux/kvm.hlinux/kvm_host.hkvm/iodev.hkvm/arm_arch_timer.hkvm/arm_vgic.hvgic.hvgic-mmio.h
Detected Declarations
function vgic_mmio_read_razfunction vgic_mmio_read_raofunction vgic_mmio_write_wifunction vgic_mmio_read_groupfunction vgic_update_vsgifunction vgic_mmio_write_groupfunction vgic_mmio_read_enablefunction vgic_mmio_write_senablefunction for_each_set_bitfunction vgic_mmio_write_cenablefunction for_each_set_bitfunction vgic_uaccess_write_senablefunction for_each_set_bitfunction vgic_uaccess_write_cenablefunction for_each_set_bitfunction __read_pendingfunction vgic_mmio_read_pendingfunction vgic_uaccess_read_pendingfunction is_vgic_v2_sgifunction __set_pendingfunction for_each_set_bitfunction vgic_mmio_write_spendingfunction vgic_uaccess_write_spendingfunction vgic_hw_irq_cpendingfunction __clear_pendingfunction for_each_set_bitfunction vgic_mmio_write_cpendingfunction vgic_uaccess_write_cpendingfunction vgic_access_active_preparefunction vgic_access_active_finishfunction __vgic_mmio_read_activefunction vgic_mmio_read_activefunction vgic_uaccess_read_activefunction vgic_hw_irq_change_activefunction vgic_mmio_change_activefunction __vgic_mmio_write_cactivefunction for_each_set_bitfunction vgic_mmio_write_cactivefunction vgic_mmio_uaccess_write_cactivefunction __vgic_mmio_write_sactivefunction for_each_set_bitfunction vgic_mmio_write_sactivefunction vgic_mmio_uaccess_write_sactivefunction vgic_mmio_read_priorityfunction guestfunction vgic_mmio_read_configfunction vgic_mmio_write_configfunction vgic_read_irq_line_level_info
Annotated Snippet
if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
vgic_update_vsgi(irq);
raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
} else {
vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
}
vgic_put_irq(vcpu->kvm, irq);
}
}
/*
* Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
* of the enabled bit, so there is only one function for both here.
*/
unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
gpa_t addr, unsigned int len)
{
u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
u32 value = 0;
int i;
/* Loop over all IRQs affected by this read */
for (i = 0; i < len * 8; i++) {
struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
if (irq->enabled)
value |= (1U << i);
vgic_put_irq(vcpu->kvm, irq);
}
return value;
}
void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
gpa_t addr, unsigned int len,
unsigned long val)
{
u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
int i;
unsigned long flags;
for_each_set_bit(i, &val, len * 8) {
struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
if (!irq->enabled) {
struct irq_data *data;
irq->enabled = true;
data = &irq_to_desc(irq->host_irq)->irq_data;
while (irqd_irq_disabled(data))
enable_irq(irq->host_irq);
}
raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
vgic_put_irq(vcpu->kvm, irq);
continue;
} else if (vgic_irq_is_mapped_level(irq)) {
bool was_high = irq->line_level;
/*
* We need to update the state of the interrupt because
* the guest might have changed the state of the device
* while the interrupt was disabled at the VGIC level.
*/
irq->line_level = vgic_get_phys_line_level(irq);
/*
* Deactivate the physical interrupt so the GIC will let
* us know when it is asserted again.
*/
if (!irq->active && was_high && !irq->line_level)
vgic_irq_set_phys_active(irq, false);
}
irq->enabled = true;
vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
vgic_put_irq(vcpu->kvm, irq);
}
}
void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
gpa_t addr, unsigned int len,
unsigned long val)
{
u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
int i;
Annotation
- Immediate include surface: `linux/bitops.h`, `linux/bsearch.h`, `linux/interrupt.h`, `linux/irq.h`, `linux/kvm.h`, `linux/kvm_host.h`, `kvm/iodev.h`, `kvm/arm_arch_timer.h`.
- Detected declarations: `function vgic_mmio_read_raz`, `function vgic_mmio_read_rao`, `function vgic_mmio_write_wi`, `function vgic_mmio_read_group`, `function vgic_update_vsgi`, `function vgic_mmio_write_group`, `function vgic_mmio_read_enable`, `function vgic_mmio_write_senable`, `function for_each_set_bit`, `function vgic_mmio_write_cenable`.
- 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.