arch/arm64/kvm/pmu-emul.c
Source file repositories/reference/linux-study-clean/arch/arm64/kvm/pmu-emul.c
File Facts
- System
- Linux kernel
- Corpus path
arch/arm64/kvm/pmu-emul.c- Extension
.c- Size
- 34314 bytes
- Lines
- 1333
- 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.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/cpu.hlinux/kvm.hlinux/kvm_host.hlinux/list.hlinux/perf_event.hlinux/perf/arm_pmu.hlinux/uaccess.hasm/kvm_emulate.hkvm/arm_pmu.hkvm/arm_vgic.h
Detected Declarations
function kvm_supports_guest_pmuv3function __kvm_pmu_event_maskfunction kvm_pmu_event_maskfunction kvm_pmu_evtyper_maskfunction kvm_pmc_is_64bitfunction kvm_pmc_has_64bit_overflowfunction kvm_pmu_counter_can_chainfunction counter_index_to_regfunction counter_index_to_evtregfunction kvm_pmc_read_evtregfunction kvm_pmu_get_pmc_valuefunction kvm_pmu_get_counter_valuefunction kvm_pmu_set_pmc_valuefunction kvm_pmu_set_counter_valuefunction kvm_pmu_set_counter_value_userfunction kvm_pmu_release_perf_eventfunction kvm_pmu_stop_counterfunction kvm_pmu_vcpu_initfunction kvm_pmu_vcpu_destroyfunction kvm_pmu_hyp_counter_maskfunction kvm_pmu_counter_is_hypfunction kvm_pmu_accessible_counter_maskfunction kvm_pmu_implemented_counter_maskfunction kvm_pmc_enable_perf_eventfunction kvm_pmc_disable_perf_eventfunction kvm_pmu_reprogram_counter_maskfunction kvm_pmu_overflow_statusfunction kvm_pmu_update_statefunction kvm_pmu_should_notify_userfunction kvm_pmu_update_runfunction kvm_pmu_flush_hwstatefunction kvm_pmu_sync_hwstatefunction kvm_pmu_perf_overflow_notify_vcpufunction kvm_pmu_counter_incrementfunction for_each_set_bitfunction compute_periodfunction kvm_pmu_perf_overflowfunction kvm_pmu_software_incrementfunction kvm_pmu_handle_pmcrfunction kvm_pmu_counter_is_enabledfunction kvm_pmc_counts_at_el0function kvm_pmc_counts_at_el1function kvm_pmc_counts_at_el2function kvm_map_pmu_eventfunction kvm_pmu_create_perf_eventfunction kvm_pmu_set_counter_event_typefunction kvm_host_pmu_initfunction __compute_pmceid
Annotated Snippet
if (nr_events >= (0x4000 + base + 32)) {
byte = bitmap_get_value8(bmap, 0x4000 + base + i);
mask |= byte << (32 + i);
}
}
return val & mask;
}
void kvm_vcpu_reload_pmu(struct kvm_vcpu *vcpu)
{
u64 mask = kvm_pmu_implemented_counter_mask(vcpu);
__vcpu_rmw_sys_reg(vcpu, PMOVSSET_EL0, &=, mask);
__vcpu_rmw_sys_reg(vcpu, PMINTENSET_EL1, &=, mask);
__vcpu_rmw_sys_reg(vcpu, PMCNTENSET_EL0, &=, mask);
kvm_pmu_reprogram_counter_mask(vcpu, mask);
}
int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu)
{
if (!vcpu->arch.pmu.created)
return -EINVAL;
/*
* A valid interrupt configuration for the PMU is either to have a
* properly configured interrupt number and using an in-kernel
* irqchip, or to not have an in-kernel GIC and not set an IRQ.
*/
if (irqchip_in_kernel(vcpu->kvm)) {
int irq = vcpu->arch.pmu.irq_num;
/*
* If we are using an in-kernel vgic, at this point we know
* the vgic will be initialized, so we can check the PMU irq
* number against the dimensions of the vgic and make sure
* it's valid.
*/
if (!irq_is_ppi(vcpu->kvm, irq) &&
!vgic_valid_spi(vcpu->kvm, irq))
return -EINVAL;
} else if (kvm_arm_pmu_irq_initialized(vcpu)) {
return -EINVAL;
}
return 0;
}
static int kvm_arm_pmu_v3_init(struct kvm_vcpu *vcpu)
{
if (irqchip_in_kernel(vcpu->kvm)) {
int ret;
/*
* If using the PMU with an in-kernel virtual GIC
* implementation, we require the GIC to be already
* initialized when initializing the PMU.
*/
if (!vgic_initialized(vcpu->kvm))
return -ENODEV;
if (!kvm_arm_pmu_irq_initialized(vcpu)) {
if (!vgic_is_v5(vcpu->kvm))
return -ENXIO;
/* Use the architected irq number for GICv5. */
vcpu->arch.pmu.irq_num = KVM_ARMV8_PMU_GICV5_IRQ;
}
ret = kvm_vgic_set_owner(vcpu, vcpu->arch.pmu.irq_num,
&vcpu->arch.pmu);
if (ret)
return ret;
}
init_irq_work(&vcpu->arch.pmu.overflow_work,
kvm_pmu_perf_overflow_notify_vcpu);
vcpu->arch.pmu.created = true;
return 0;
}
/*
* For one VM the interrupt type must be same for each vcpu.
* As a PPI, the interrupt number is the same for all vcpus,
* while as an SPI it must be a separate number per vcpu.
*/
static bool pmu_irq_is_valid(struct kvm *kvm, int irq)
{
unsigned long i;
Annotation
- Immediate include surface: `linux/cpu.h`, `linux/kvm.h`, `linux/kvm_host.h`, `linux/list.h`, `linux/perf_event.h`, `linux/perf/arm_pmu.h`, `linux/uaccess.h`, `asm/kvm_emulate.h`.
- Detected declarations: `function kvm_supports_guest_pmuv3`, `function __kvm_pmu_event_mask`, `function kvm_pmu_event_mask`, `function kvm_pmu_evtyper_mask`, `function kvm_pmc_is_64bit`, `function kvm_pmc_has_64bit_overflow`, `function kvm_pmu_counter_can_chain`, `function counter_index_to_reg`, `function counter_index_to_evtreg`, `function kvm_pmc_read_evtreg`.
- Atlas domain: Architecture Layer / arch/arm64.
- Implementation status: source implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
- 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.