arch/x86/kvm/svm/pmu.c
Source file repositories/reference/linux-study-clean/arch/x86/kvm/svm/pmu.c
File Facts
- System
- Linux kernel
- Corpus path
arch/x86/kvm/svm/pmu.c- Extension
.c- Size
- 8899 bytes
- Lines
- 329
- Domain
- Architecture Layer
- Bucket
- arch/x86
- Inferred role
- Architecture Layer: implementation source
- Status
- source 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.
- 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.hx86.hcpuid.hlapic.hpmu.hsvm.h
Detected Declarations
enum pmu_typefunction amd_check_rdpmc_earlyfunction amd_is_valid_msrfunction amd_pmu_get_msrfunction amd_pmu_set_msrfunction amd_pmu_refreshfunction amd_pmu_initfunction amd_pmu_is_mediated_pmu_supportedfunction amd_mediated_pmu_loadfunction amd_mediated_pmu_putfunction amd_pmc_is_disabled_in_current_mode
Annotated Snippet
if (data != pmc->eventsel) {
pmc->eventsel = data;
pmc->eventsel_hw = (data & ~AMD64_EVENTSEL_HOSTONLY) |
AMD64_EVENTSEL_GUESTONLY;
if (data & AMD64_EVENTSEL_HOST_GUEST_MASK)
__set_bit(pmc->idx, pmu->pmc_has_mode_specific_enables);
else
__clear_bit(pmc->idx, pmu->pmc_has_mode_specific_enables);
kvm_pmu_request_counter_reprogram(pmc);
}
return 0;
}
return 1;
}
static void amd_pmu_refresh(struct kvm_vcpu *vcpu)
{
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
union cpuid_0x80000022_ebx ebx;
pmu->version = 1;
if (guest_cpu_cap_has(vcpu, X86_FEATURE_PERFMON_V2)) {
pmu->version = 2;
/*
* Note, PERFMON_V2 is also in 0x80000022.0x0, i.e. the guest
* CPUID entry is guaranteed to be non-NULL.
*/
BUILD_BUG_ON(x86_feature_cpuid(X86_FEATURE_PERFMON_V2).function != 0x80000022 ||
x86_feature_cpuid(X86_FEATURE_PERFMON_V2).index);
ebx.full = kvm_find_cpuid_entry_index(vcpu, 0x80000022, 0)->ebx;
pmu->nr_arch_gp_counters = ebx.split.num_core_pmc;
} else if (guest_cpu_cap_has(vcpu, X86_FEATURE_PERFCTR_CORE)) {
pmu->nr_arch_gp_counters = AMD64_NUM_COUNTERS_CORE;
} else {
pmu->nr_arch_gp_counters = AMD64_NUM_COUNTERS;
}
pmu->nr_arch_gp_counters = min_t(unsigned int, pmu->nr_arch_gp_counters,
kvm_pmu_cap.num_counters_gp);
if (pmu->version > 1) {
pmu->global_ctrl_rsvd = ~(BIT_ULL(pmu->nr_arch_gp_counters) - 1);
pmu->global_status_rsvd = pmu->global_ctrl_rsvd;
}
pmu->counter_bitmask[KVM_PMC_GP] = BIT_ULL(48) - 1;
pmu->reserved_bits = 0xfffffff000280000ull;
if (guest_cpu_cap_has(vcpu, X86_FEATURE_SVM) && kvm_vcpu_has_mediated_pmu(vcpu))
pmu->reserved_bits &= ~AMD64_EVENTSEL_HOST_GUEST_MASK;
pmu->raw_event_mask = AMD64_RAW_EVENT_MASK;
/* not applicable to AMD; but clean them to prevent any fall out */
pmu->counter_bitmask[KVM_PMC_FIXED] = 0;
pmu->nr_arch_fixed_counters = 0;
}
static void amd_pmu_init(struct kvm_vcpu *vcpu)
{
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
int i;
BUILD_BUG_ON(KVM_MAX_NR_AMD_GP_COUNTERS > AMD64_NUM_COUNTERS_CORE);
for (i = 0; i < KVM_MAX_NR_AMD_GP_COUNTERS; i++) {
pmu->gp_counters[i].type = KVM_PMC_GP;
pmu->gp_counters[i].vcpu = vcpu;
pmu->gp_counters[i].idx = i;
pmu->gp_counters[i].current_config = 0;
}
}
static bool amd_pmu_is_mediated_pmu_supported(struct x86_pmu_capability *host_pmu)
{
return host_pmu->version >= 2;
}
static void amd_mediated_pmu_load(struct kvm_vcpu *vcpu)
{
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
u64 global_status;
rdmsrq(MSR_AMD64_PERF_CNTR_GLOBAL_STATUS, global_status);
/* Clear host global_status MSR if non-zero. */
if (global_status)
wrmsrq(MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR, global_status);
Annotation
- Immediate include surface: `linux/types.h`, `linux/kvm_host.h`, `linux/perf_event.h`, `x86.h`, `cpuid.h`, `lapic.h`, `pmu.h`, `svm.h`.
- Detected declarations: `enum pmu_type`, `function amd_check_rdpmc_early`, `function amd_is_valid_msr`, `function amd_pmu_get_msr`, `function amd_pmu_set_msr`, `function amd_pmu_refresh`, `function amd_pmu_init`, `function amd_pmu_is_mediated_pmu_supported`, `function amd_mediated_pmu_load`, `function amd_mediated_pmu_put`.
- Atlas domain: Architecture Layer / arch/x86.
- 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.