arch/x86/kvm/pmu.c
Source file repositories/reference/linux-study-clean/arch/x86/kvm/pmu.c
File Facts
- System
- Linux kernel
- Corpus path
arch/x86/kvm/pmu.c- Extension
.c- Size
- 41642 bytes
- Lines
- 1425
- 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.
- 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/types.hlinux/kvm_host.hlinux/perf_event.hlinux/bsearch.hlinux/sort.hlinux/moduleparam.hasm/perf_event.hasm/cpu_device_id.hx86.hcpuid.hlapic.hpmu.hasm/kvm-x86-pmu-ops.h
Detected Declarations
struct kvm_pmu_emulated_event_selectorsfunction kvm_pmu_ops_updatefunction kvm_init_pmu_capabilityfunction kvm_handle_guest_mediated_pmifunction __kvm_perf_overflowfunction kvm_perf_overflowfunction pmc_get_pebs_precise_levelfunction get_sample_periodfunction pmc_reprogram_counterfunction pmc_pause_counterfunction pmc_resume_counterfunction pmc_release_perf_eventfunction pmc_stop_counterfunction pmc_update_sample_periodfunction pmc_write_counterfunction filter_cmpfunction filter_sort_cmpfunction filter_event_cmpfunction find_filter_indexfunction is_filter_entry_matchfunction filter_contains_matchfunction is_gp_event_allowedfunction is_fixed_event_allowedfunction pmc_is_event_allowedfunction kvm_mediated_pmu_refresh_event_filterfunction reprogram_counterfunction pmc_is_event_matchfunction kvm_pmu_recalc_pmc_emulationfunction kvm_pmu_handle_eventfunction kvm_for_each_pmcfunction kvm_pmu_check_rdpmc_earlyfunction is_vmware_backdoor_pmcfunction kvm_pmu_rdpmc_vmwarefunction kvm_pmu_rdpmcfunction kvm_need_any_pmc_interceptfunction kvm_need_perf_global_ctrl_interceptfunction kvm_need_rdpmc_interceptfunction kvm_pmu_deliver_pmifunction kvm_pmu_is_valid_msrfunction kvm_pmu_mark_pmc_in_usefunction kvm_pmu_get_msrfunction kvm_pmu_set_msrfunction kvm_pmu_resetfunction kvm_for_each_pmcfunction kvm_pmu_refreshfunction kvm_pmu_initfunction kvm_pmu_cleanupfunction kvm_for_each_pmc
Annotated Snippet
struct kvm_pmu_emulated_event_selectors {
u64 INSTRUCTIONS_RETIRED;
u64 BRANCH_INSTRUCTIONS_RETIRED;
};
static struct kvm_pmu_emulated_event_selectors __read_mostly kvm_pmu_eventsel;
/* Precise Distribution of Instructions Retired (PDIR) */
static const struct x86_cpu_id vmx_pebs_pdir_cpu[] = {
X86_MATCH_VFM(INTEL_ICELAKE_D, NULL),
X86_MATCH_VFM(INTEL_ICELAKE_X, NULL),
/* Instruction-Accurate PDIR (PDIR++) */
X86_MATCH_VFM(INTEL_SAPPHIRERAPIDS_X, NULL),
{}
};
/* Precise Distribution (PDist) */
static const struct x86_cpu_id vmx_pebs_pdist_cpu[] = {
X86_MATCH_VFM(INTEL_SAPPHIRERAPIDS_X, NULL),
{}
};
/* NOTE:
* - Each perf counter is defined as "struct kvm_pmc";
* - There are two types of perf counters: general purpose (gp) and fixed.
* gp counters are stored in gp_counters[] and fixed counters are stored
* in fixed_counters[] respectively. Both of them are part of "struct
* kvm_pmu";
* - pmu.c understands the difference between gp counters and fixed counters.
* However AMD doesn't support fixed-counters;
* - There are three types of index to access perf counters (PMC):
* 1. MSR (named msr): For example Intel has MSR_IA32_PERFCTRn and AMD
* has MSR_K7_PERFCTRn and, for families 15H and later,
* MSR_F15H_PERF_CTRn, where MSR_F15H_PERF_CTR[0-3] are
* aliased to MSR_K7_PERFCTRn.
* 2. MSR Index (named idx): This normally is used by RDPMC instruction.
* For instance AMD RDPMC instruction uses 0000_0003h in ECX to access
* C001_0007h (MSR_K7_PERCTR3). Intel has a similar mechanism, except
* that it also supports fixed counters. idx can be used to as index to
* gp and fixed counters.
* 3. Global PMC Index (named pmc): pmc is an index specific to PMU
* code. Each pmc, stored in kvm_pmc.idx field, is unique across
* all perf counters (both gp and fixed). The mapping relationship
* between pmc and perf counters is as the following:
* * Intel: [0 .. KVM_MAX_NR_INTEL_GP_COUNTERS-1] <=> gp counters
* [KVM_FIXED_PMC_BASE_IDX .. KVM_FIXED_PMC_BASE_IDX + 2] <=> fixed
* * AMD: [0 .. AMD64_NUM_COUNTERS-1] and, for families 15H
* and later, [0 .. AMD64_NUM_COUNTERS_CORE-1] <=> gp counters
*/
static struct kvm_pmu_ops kvm_pmu_ops __read_mostly;
#define KVM_X86_PMU_OP(func) \
DEFINE_STATIC_CALL_NULL(kvm_x86_pmu_##func, \
*(((struct kvm_pmu_ops *)0)->func));
#define KVM_X86_PMU_OP_OPTIONAL KVM_X86_PMU_OP
#define KVM_X86_PMU_OP_OPTIONAL_RET0 KVM_X86_PMU_OP
#include <asm/kvm-x86-pmu-ops.h>
EXPORT_STATIC_CALL_GPL(kvm_x86_pmu_pmc_is_disabled_in_current_mode);
void kvm_pmu_ops_update(const struct kvm_pmu_ops *pmu_ops)
{
memcpy(&kvm_pmu_ops, pmu_ops, sizeof(kvm_pmu_ops));
#define __KVM_X86_PMU_OP(func) \
static_call_update(kvm_x86_pmu_##func, kvm_pmu_ops.func);
#define KVM_X86_PMU_OP(func) \
WARN_ON(!kvm_pmu_ops.func); __KVM_X86_PMU_OP(func)
#define KVM_X86_PMU_OP_OPTIONAL __KVM_X86_PMU_OP
#define KVM_X86_PMU_OP_OPTIONAL_RET0(func) \
static_call_update(kvm_x86_pmu_##func, (void *)kvm_pmu_ops.func ? : \
(void *)__static_call_return0);
#include <asm/kvm-x86-pmu-ops.h>
#undef __KVM_X86_PMU_OP
}
void kvm_init_pmu_capability(struct kvm_pmu_ops *pmu_ops)
{
bool is_intel = boot_cpu_data.x86_vendor == X86_VENDOR_INTEL;
int min_nr_gp_ctrs = pmu_ops->MIN_NR_GP_COUNTERS;
/*
* Hybrid PMUs don't play nice with virtualization without careful
* configuration by userspace, and KVM's APIs for reporting supported
* vPMU features do not account for hybrid PMUs. Disable vPMU support
* for hybrid PMUs until KVM gains a way to let userspace opt-in.
*/
if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) {
enable_pmu = false;
memset(&kvm_host_pmu, 0, sizeof(kvm_host_pmu));
} else {
Annotation
- Immediate include surface: `linux/types.h`, `linux/kvm_host.h`, `linux/perf_event.h`, `linux/bsearch.h`, `linux/sort.h`, `linux/moduleparam.h`, `asm/perf_event.h`, `asm/cpu_device_id.h`.
- Detected declarations: `struct kvm_pmu_emulated_event_selectors`, `function kvm_pmu_ops_update`, `function kvm_init_pmu_capability`, `function kvm_handle_guest_mediated_pmi`, `function __kvm_perf_overflow`, `function kvm_perf_overflow`, `function pmc_get_pebs_precise_level`, `function get_sample_period`, `function pmc_reprogram_counter`, `function pmc_pause_counter`.
- Atlas domain: Architecture Layer / arch/x86.
- Implementation status: integration 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.