drivers/iommu/intel/perfmon.c
Source file repositories/reference/linux-study-clean/drivers/iommu/intel/perfmon.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/iommu/intel/perfmon.c- Extension
.c- Size
- 22966 bytes
- Lines
- 791
- Domain
- Driver Families
- Bucket
- drivers/iommu
- 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.
- 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
linux/dmar.hiommu.hperfmon.h
Detected Declarations
function iommu_event_basefunction iommu_config_basefunction iommu_event_configfunction is_iommu_pmu_eventfunction iommu_pmu_validate_eventfunction iommu_pmu_validate_groupfunction iommu_pmu_event_initfunction iommu_pmu_event_updatefunction iommu_pmu_startfunction iommu_pmu_stopfunction iommu_pmu_validate_per_cntr_eventfunction iommu_pmu_assign_eventfunction iommu_pmu_addfunction iommu_pmu_delfunction iommu_pmu_enablefunction iommu_pmu_disablefunction iommu_pmu_counter_overflowfunction for_each_set_bitfunction iommu_pmu_irq_handlerfunction __iommu_pmu_registerfunction get_perf_reg_addressfunction alloc_iommu_pmufunction free_iommu_pmufunction iommu_pmu_set_interruptfunction iommu_pmu_unset_interruptfunction iommu_pmu_registerfunction iommu_pmu_unregister
Annotated Snippet
for_each_set_bit(i, (unsigned long *)&status, iommu_pmu->num_cntr) {
/*
* Find the assigned event of the counter.
* Accumulate the value into the event->count.
*/
event = iommu_pmu->event_list[i];
if (!event) {
pr_warn_once("Cannot find the assigned event for counter %d\n", i);
continue;
}
iommu_pmu_event_update(event);
}
writeq(status, iommu_pmu->overflow);
}
}
static irqreturn_t iommu_pmu_irq_handler(int irq, void *dev_id)
{
struct intel_iommu *iommu = dev_id;
if (!readl(iommu->reg + DMAR_PERFINTRSTS_REG))
return IRQ_NONE;
iommu_pmu_counter_overflow(iommu->pmu);
/* Clear the status bit */
writel(DMA_PERFINTRSTS_PIS, iommu->reg + DMAR_PERFINTRSTS_REG);
return IRQ_HANDLED;
}
static int __iommu_pmu_register(struct intel_iommu *iommu)
{
struct iommu_pmu *iommu_pmu = iommu->pmu;
iommu_pmu->pmu.name = iommu->name;
iommu_pmu->pmu.task_ctx_nr = perf_invalid_context;
iommu_pmu->pmu.event_init = iommu_pmu_event_init;
iommu_pmu->pmu.pmu_enable = iommu_pmu_enable;
iommu_pmu->pmu.pmu_disable = iommu_pmu_disable;
iommu_pmu->pmu.add = iommu_pmu_add;
iommu_pmu->pmu.del = iommu_pmu_del;
iommu_pmu->pmu.start = iommu_pmu_start;
iommu_pmu->pmu.stop = iommu_pmu_stop;
iommu_pmu->pmu.read = iommu_pmu_event_update;
iommu_pmu->pmu.attr_groups = iommu_pmu_attr_groups;
iommu_pmu->pmu.attr_update = iommu_pmu_attr_update;
iommu_pmu->pmu.capabilities = PERF_PMU_CAP_NO_EXCLUDE;
iommu_pmu->pmu.scope = PERF_PMU_SCOPE_SYS_WIDE;
iommu_pmu->pmu.module = THIS_MODULE;
return perf_pmu_register(&iommu_pmu->pmu, iommu_pmu->pmu.name, -1);
}
static inline void __iomem *
get_perf_reg_address(struct intel_iommu *iommu, u32 offset)
{
u32 off = readl(iommu->reg + offset);
return iommu->reg + off;
}
int alloc_iommu_pmu(struct intel_iommu *iommu)
{
struct iommu_pmu *iommu_pmu;
int i, j, ret;
u64 perfcap;
u32 cap;
if (!ecap_pms(iommu->ecap))
return 0;
/* The IOMMU PMU requires the ECMD support as well */
if (!cap_ecmds(iommu->cap))
return -ENODEV;
perfcap = readq(iommu->reg + DMAR_PERFCAP_REG);
/* The performance monitoring is not supported. */
if (!perfcap)
return -ENODEV;
/* Sanity check for the number of the counters and event groups */
if (!pcap_num_cntr(perfcap) || !pcap_num_event_group(perfcap))
return -ENODEV;
/* The interrupt on overflow is required */
if (!pcap_interrupt(perfcap))
return -ENODEV;
Annotation
- Immediate include surface: `linux/dmar.h`, `iommu.h`, `perfmon.h`.
- Detected declarations: `function iommu_event_base`, `function iommu_config_base`, `function iommu_event_config`, `function is_iommu_pmu_event`, `function iommu_pmu_validate_event`, `function iommu_pmu_validate_group`, `function iommu_pmu_event_init`, `function iommu_pmu_event_update`, `function iommu_pmu_start`, `function iommu_pmu_stop`.
- Atlas domain: Driver Families / drivers/iommu.
- Implementation status: source 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.