arch/x86/events/amd/core.c
Source file repositories/reference/linux-study-clean/arch/x86/events/amd/core.c
File Facts
- System
- Linux kernel
- Corpus path
arch/x86/events/amd/core.c- Extension
.c- Size
- 42682 bytes
- Lines
- 1600
- Domain
- Architecture Layer
- Bucket
- arch/x86
- Inferred role
- Architecture Layer: exported/initcall integration point
- Status
- integration 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.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- 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/perf_event.hlinux/jump_label.hlinux/export.hlinux/kvm_types.hlinux/types.hlinux/init.hlinux/slab.hlinux/delay.hlinux/jiffies.hasm/apicdef.hasm/apic.hasm/cpuid/api.hasm/msr.hasm/nmi.h../perf_event.h
Detected Declarations
function amd_pmu_event_mapfunction amd_pmu_addr_offsetfunction amd_get_event_codefunction amd_is_pair_event_codefunction amd_core_hw_configfunction amd_is_nb_eventfunction amd_has_nbfunction amd_pmu_hw_configfunction __amd_put_nb_event_constraintsfunction allocatedfunction assignedfunction amd_pmu_cpu_resetfunction amd_pmu_cpu_preparefunction amd_pmu_cpu_startingfunction for_each_online_cpufunction amd_pmu_cpu_deadfunction amd_pmu_set_global_ctlfunction amd_pmu_get_global_statusfunction amd_pmu_ack_global_statusfunction amd_pmu_test_overflow_topbitfunction amd_pmu_test_overflow_statusfunction amd_pmu_wait_on_overflowfunction amd_pmu_check_overflowfunction amd_pmu_enable_eventfunction amd_pmu_enable_allfunction for_each_set_bitfunction amd_pmu_v2_enable_eventfunction amd_pmu_core_enable_allfunction amd_pmu_v2_enable_allfunction amd_pmu_disable_eventfunction amd_pmu_disable_allfunction amd_pmu_core_disable_allfunction amd_pmu_v2_disable_allfunction amd_pmu_add_eventfunction amd_pmu_del_eventfunction amd_pmu_adjust_nmi_windowfunction amd_pmu_handle_irqfunction amd_pmu_v2_snapshot_branch_stackfunction amd_pmu_v2_handle_irqfunction for_each_set_bitfunction amd_get_event_constraintsfunction amd_put_event_constraintsfunction amd_get_event_constraints_f15hfunction amd_get_event_constraints_f17hfunction amd_put_event_constraints_f17hfunction amd_get_event_constraints_f19hfunction amd_event_sysfs_showfunction amd_pmu_limit_period
Annotated Snippet
if (nb->nb_id == nb_id) {
*onln = cpuc->amd_nb;
cpuc->amd_nb = nb;
break;
}
}
cpuc->amd_nb->nb_id = nb_id;
cpuc->amd_nb->refcnt++;
}
static void amd_pmu_cpu_dead(int cpu)
{
struct cpu_hw_events *cpuhw = &per_cpu(cpu_hw_events, cpu);
kfree(cpuhw->lbr_sel);
cpuhw->lbr_sel = NULL;
if (!x86_pmu.amd_nb_constraints)
return;
if (cpuhw->amd_nb) {
struct amd_nb *nb = cpuhw->amd_nb;
if (nb->nb_id == -1 || --nb->refcnt == 0)
kfree(nb);
cpuhw->amd_nb = NULL;
}
}
static __always_inline void amd_pmu_set_global_ctl(u64 ctl)
{
wrmsrq(MSR_AMD64_PERF_CNTR_GLOBAL_CTL, ctl);
}
static inline u64 amd_pmu_get_global_status(void)
{
u64 status;
/* PerfCntrGlobalStatus is read-only */
rdmsrq(MSR_AMD64_PERF_CNTR_GLOBAL_STATUS, status);
return status;
}
static inline void amd_pmu_ack_global_status(u64 status)
{
/*
* PerfCntrGlobalStatus is read-only but an overflow acknowledgment
* mechanism exists; writing 1 to a bit in PerfCntrGlobalStatusClr
* clears the same bit in PerfCntrGlobalStatus
*/
wrmsrq(MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR, status);
}
static bool amd_pmu_test_overflow_topbit(int idx)
{
u64 counter;
rdmsrq(x86_pmu_event_addr(idx), counter);
return !(counter & BIT_ULL(x86_pmu.cntval_bits - 1));
}
static bool amd_pmu_test_overflow_status(int idx)
{
return amd_pmu_get_global_status() & BIT_ULL(idx);
}
DEFINE_STATIC_CALL(amd_pmu_test_overflow, amd_pmu_test_overflow_topbit);
/*
* When a PMC counter overflows, an NMI is used to process the event and
* reset the counter. NMI latency can result in the counter being updated
* before the NMI can run, which can result in what appear to be spurious
* NMIs. This function is intended to wait for the NMI to run and reset
* the counter to avoid possible unhandled NMI messages.
*/
#define OVERFLOW_WAIT_COUNT 50
static void amd_pmu_wait_on_overflow(int idx)
{
unsigned int i;
/*
* Wait for the counter to be reset if it has overflowed. This loop
* should exit very, very quickly, but just in case, don't wait
* forever...
Annotation
- Immediate include surface: `linux/perf_event.h`, `linux/jump_label.h`, `linux/export.h`, `linux/kvm_types.h`, `linux/types.h`, `linux/init.h`, `linux/slab.h`, `linux/delay.h`.
- Detected declarations: `function amd_pmu_event_map`, `function amd_pmu_addr_offset`, `function amd_get_event_code`, `function amd_is_pair_event_code`, `function amd_core_hw_config`, `function amd_is_nb_event`, `function amd_has_nb`, `function amd_pmu_hw_config`, `function __amd_put_nb_event_constraints`, `function allocated`.
- Atlas domain: Architecture Layer / arch/x86.
- Implementation status: integration 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.