drivers/perf/riscv_pmu.c
Source file repositories/reference/linux-study-clean/drivers/perf/riscv_pmu.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/perf/riscv_pmu.c- Extension
.c- Size
- 11213 bytes
- Lines
- 428
- Domain
- Driver Families
- Bucket
- drivers/perf
- Inferred role
- Driver Families: implementation source
- Status
- source 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.
- 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/cpumask.hlinux/irq.hlinux/irqdesc.hlinux/perf/riscv_pmu.hlinux/printk.hlinux/smp.hlinux/sched_clock.hasm/sbi.h
Detected Declarations
function Copyrightfunction arch_perf_update_userpagefunction csr_read_numfunction riscv_pmu_ctr_read_csrfunction riscv_pmu_ctr_get_width_maskfunction riscv_pmu_event_updatefunction riscv_pmu_stopfunction riscv_pmu_event_set_periodfunction riscv_pmu_startfunction riscv_pmu_addfunction riscv_pmu_delfunction riscv_pmu_readfunction riscv_pmu_event_initfunction riscv_pmu_event_idxfunction riscv_pmu_event_mappedfunction riscv_pmu_event_unmappedfunction for_each_possible_cpu
Annotated Snippet
if (rvpmu->ctr_stop) {
rvpmu->ctr_stop(event, 0);
hwc->state |= PERF_HES_STOPPED;
}
riscv_pmu_event_update(event);
hwc->state |= PERF_HES_UPTODATE;
}
}
int riscv_pmu_event_set_period(struct perf_event *event)
{
struct hw_perf_event *hwc = &event->hw;
s64 left = local64_read(&hwc->period_left);
s64 period = hwc->sample_period;
int overflow = 0;
uint64_t max_period = riscv_pmu_ctr_get_width_mask(event);
if (unlikely(left <= -period)) {
left = period;
local64_set(&hwc->period_left, left);
hwc->last_period = period;
overflow = 1;
}
if (unlikely(left <= 0)) {
left += period;
local64_set(&hwc->period_left, left);
hwc->last_period = period;
overflow = 1;
}
/*
* Limit the maximum period to prevent the counter value
* from overtaking the one we are about to program. In
* effect we are reducing max_period to account for
* interrupt latency (and we are being very conservative).
*/
if (left > (max_period >> 1))
left = (max_period >> 1);
local64_set(&hwc->prev_count, (u64)-left);
perf_event_update_userpage(event);
return overflow;
}
void riscv_pmu_start(struct perf_event *event, int flags)
{
struct hw_perf_event *hwc = &event->hw;
struct riscv_pmu *rvpmu = to_riscv_pmu(event->pmu);
uint64_t max_period = riscv_pmu_ctr_get_width_mask(event);
u64 init_val;
if (flags & PERF_EF_RELOAD)
WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
hwc->state = 0;
riscv_pmu_event_set_period(event);
init_val = local64_read(&hwc->prev_count) & max_period;
rvpmu->ctr_start(event, init_val);
perf_event_update_userpage(event);
}
static int riscv_pmu_add(struct perf_event *event, int flags)
{
struct riscv_pmu *rvpmu = to_riscv_pmu(event->pmu);
struct cpu_hw_events *cpuc = this_cpu_ptr(rvpmu->hw_events);
struct hw_perf_event *hwc = &event->hw;
int idx;
idx = rvpmu->ctr_get_idx(event);
if (idx < 0)
return idx;
hwc->idx = idx;
cpuc->events[idx] = event;
cpuc->n_events++;
hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
if (flags & PERF_EF_START)
riscv_pmu_start(event, PERF_EF_RELOAD);
/* Propagate our changes to the userspace mapping. */
perf_event_update_userpage(event);
return 0;
}
static void riscv_pmu_del(struct perf_event *event, int flags)
{
Annotation
- Immediate include surface: `linux/cpumask.h`, `linux/irq.h`, `linux/irqdesc.h`, `linux/perf/riscv_pmu.h`, `linux/printk.h`, `linux/smp.h`, `linux/sched_clock.h`, `asm/sbi.h`.
- Detected declarations: `function Copyright`, `function arch_perf_update_userpage`, `function csr_read_num`, `function riscv_pmu_ctr_read_csr`, `function riscv_pmu_ctr_get_width_mask`, `function riscv_pmu_event_update`, `function riscv_pmu_stop`, `function riscv_pmu_event_set_period`, `function riscv_pmu_start`, `function riscv_pmu_add`.
- Atlas domain: Driver Families / drivers/perf.
- Implementation status: source implementation candidate.
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.