drivers/perf/arm_pmuv3.c
Source file repositories/reference/linux-study-clean/drivers/perf/arm_pmuv3.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/perf/arm_pmuv3.c- Extension
.c- Size
- 52898 bytes
- Lines
- 1667
- Domain
- Driver Families
- Bucket
- drivers/perf
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- 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
asm/irq_regs.hasm/perf_event.hasm/virt.hclocksource/arm_arch_timer.hlinux/acpi.hlinux/bitfield.hlinux/clocksource.hlinux/of.hlinux/perf/arm_pmu.hlinux/perf/arm_pmuv3.hlinux/platform_device.hlinux/sched_clock.hlinux/smp.hlinux/nmi.harm_brbe.h
Detected Declarations
struct armv8pmu_probe_infofunction armv8pmu_events_sysfs_showfunction armv8pmu_event_attr_is_visiblefunction armv8pmu_event_is_64bitfunction armv8pmu_event_want_user_accessfunction armv8pmu_event_get_thresholdfunction armv8pmu_event_threshold_controlfunction slots_showfunction bus_slots_showfunction bus_width_showfunction threshold_maxfunction threshold_max_showfunction branches_showfunction caps_is_visiblefunction armv8pmu_has_long_eventfunction armv8pmu_event_has_user_readfunction counterfunction armv8pmu_pmcr_readfunction armv8pmu_pmcr_writefunction armv8pmu_has_overflowedfunction armv8pmu_counter_has_overflowedfunction armv8pmu_read_evcntrfunction armv8pmu_read_hw_counterfunction counterfunction armv8pmu_bias_long_counterfunction armv8pmu_unbias_long_counterfunction armv8pmu_read_counterfunction armv8pmu_write_evcntrfunction armv8pmu_write_hw_counterfunction armv8pmu_write_counterfunction armv8pmu_write_evtypefunction armv8pmu_write_event_typefunction armv8pmu_event_cnten_maskfunction armv8pmu_enable_counterfunction armv8pmu_enable_event_counterfunction armv8pmu_disable_counterfunction armv8pmu_disable_event_counterfunction armv8pmu_enable_intensfunction armv8pmu_enable_event_irqfunction armv8pmu_disable_intensfunction armv8pmu_disable_event_irqfunction armv8pmu_getreset_flagsfunction update_pmuserenrfunction armv8pmu_disable_user_accessfunction armv8pmu_enable_user_accessfunction for_each_set_bitfunction for_each_andnot_bitfunction armv8pmu_enable_event
Annotated Snippet
device_initcall(armv8_pmu_driver_init)
void arch_perf_update_userpage(struct perf_event *event,
struct perf_event_mmap_page *userpg, u64 now)
{
struct clock_read_data *rd;
unsigned int seq;
u64 ns;
userpg->cap_user_time = 0;
userpg->cap_user_time_zero = 0;
userpg->cap_user_time_short = 0;
userpg->cap_user_rdpmc = armv8pmu_event_has_user_read(event);
if (userpg->cap_user_rdpmc) {
if (event->hw.flags & ARMPMU_EVT_64BIT)
userpg->pmc_width = 64;
else
userpg->pmc_width = 32;
}
do {
rd = sched_clock_read_begin(&seq);
if (rd->read_sched_clock != arch_timer_read_counter)
return;
userpg->time_mult = rd->mult;
userpg->time_shift = rd->shift;
userpg->time_zero = rd->epoch_ns;
userpg->time_cycles = rd->epoch_cyc;
userpg->time_mask = rd->sched_clock_mask;
/*
* Subtract the cycle base, such that software that
* doesn't know about cap_user_time_short still 'works'
* assuming no wraps.
*/
ns = mul_u64_u32_shr(rd->epoch_cyc, rd->mult, rd->shift);
userpg->time_zero -= ns;
} while (sched_clock_read_retry(seq));
userpg->time_offset = userpg->time_zero - now;
/*
* time_shift is not expected to be greater than 31 due to
* the original published conversion algorithm shifting a
* 32-bit value (now specifies a 64-bit value) - refer
* perf_event_mmap_page documentation in perf_event.h.
*/
if (userpg->time_shift == 32) {
userpg->time_shift = 31;
userpg->time_mult >>= 1;
}
/*
* Internal timekeeping for enabled/running/stopped times
* is always computed with the sched_clock.
*/
userpg->cap_user_time = 1;
userpg->cap_user_time_zero = 1;
userpg->cap_user_time_short = 1;
}
Annotation
- Immediate include surface: `asm/irq_regs.h`, `asm/perf_event.h`, `asm/virt.h`, `clocksource/arm_arch_timer.h`, `linux/acpi.h`, `linux/bitfield.h`, `linux/clocksource.h`, `linux/of.h`.
- Detected declarations: `struct armv8pmu_probe_info`, `function armv8pmu_events_sysfs_show`, `function armv8pmu_event_attr_is_visible`, `function armv8pmu_event_is_64bit`, `function armv8pmu_event_want_user_access`, `function armv8pmu_event_get_threshold`, `function armv8pmu_event_threshold_control`, `function slots_show`, `function bus_slots_show`, `function bus_width_show`.
- Atlas domain: Driver Families / drivers/perf.
- Implementation status: integration implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
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.