diff --git a/CHANGELOG.md b/CHANGELOG.md index 3aaf598623..1663f6878e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - The cpuid_mask_* command line options for legacy AMD CPUs. These were deprecated in Xen 4.7 and noted not to work correctly with AMD CPUs from 2011 onwards. + - Xenoprofile support. Oprofile themselves removed support for Xen in 2014 + prior to the version 1.0 release, and there has been no development since + before then in Xen. ## [4.21.0](https://xenbits.xenproject.org/gitweb/?p=xen.git;a=shortlog;h=RELEASE-4.21.0) - 2025-11-19 diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc index bbbdf6a5bb..50d7edb248 100644 --- a/docs/misc/xen-command-line.pandoc +++ b/docs/misc/xen-command-line.pandoc @@ -508,12 +508,6 @@ character, but for xen to keep the console. > Default: `power` -### cpu_type (x86) -> `= arch_perfmon` - -If set, force use of the performance counters for oprofile, rather than detecting -available support. - ### cpufreq > `= none | {{ | xen } { [:[powersave|performance|ondemand|userspace][,[]][,[]]] } [,verbose]} | dom0-kernel | hwp[:[][,verbose]] | amd-cppc[:[active][,verbose]]` diff --git a/tools/flask/policy/modules/dom0.te b/tools/flask/policy/modules/dom0.te index ad2b4f9ea7..d30edf8be1 100644 --- a/tools/flask/policy/modules/dom0.te +++ b/tools/flask/policy/modules/dom0.te @@ -21,8 +21,6 @@ allow dom0_t xen_t:xen { writeconsole readapic writeapic - privprofile - nonprivprofile kexec firmware sleep diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index 1fc651146f..d8b41cec16 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_GUEST) += guest/ obj-$(CONFIG_HVM) += hvm/ obj-y += lib/ obj-y += mm/ -obj-$(CONFIG_XENOPROF) += oprofile/ obj-$(CONFIG_PV) += pv/ obj-y += x86_64/ obj-y += x86_emulate/ diff --git a/xen/arch/x86/cpu/vpmu_amd.c b/xen/arch/x86/cpu/vpmu_amd.c index fa157d45dd..d1f6bd5495 100644 --- a/xen/arch/x86/cpu/vpmu_amd.c +++ b/xen/arch/x86/cpu/vpmu_amd.c @@ -12,7 +12,6 @@ #include #include -#include #include #include @@ -363,8 +362,6 @@ static int cf_check amd_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content) if ( (type == MSR_TYPE_CTRL) && is_pmu_enabled(msr_content) && !vpmu_is_set(vpmu, VPMU_RUNNING) ) { - if ( !acquire_pmu_ownership(PMU_OWNER_HVM) ) - return 0; vpmu_set(vpmu, VPMU_RUNNING); if ( is_svm_vcpu(v) && is_msr_bitmap_on(vpmu) ) @@ -378,7 +375,6 @@ static int cf_check amd_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content) vpmu_reset(vpmu, VPMU_RUNNING); if ( is_svm_vcpu(v) && is_msr_bitmap_on(vpmu) ) amd_vpmu_unset_msr_bitmap(v); - release_pmu_ownership(PMU_OWNER_HVM); } if ( !vpmu_is_set(vpmu, VPMU_CONTEXT_LOADED) @@ -426,9 +422,6 @@ static void cf_check amd_vpmu_destroy(struct vcpu *v) vpmu->context = NULL; vpmu->priv_context = NULL; - if ( vpmu_is_set(vpmu, VPMU_RUNNING) ) - release_pmu_ownership(PMU_OWNER_HVM); - vpmu_clear(vpmu); } @@ -449,8 +442,6 @@ static void cf_check amd_vpmu_dump(const struct vcpu *v) } printk("("); - if ( vpmu_is_set(vpmu, VPMU_PASSIVE_DOMAIN_ALLOCATED) ) - printk("PASSIVE_DOMAIN_ALLOCATED, "); if ( vpmu_is_set(vpmu, VPMU_FROZEN) ) printk("FROZEN, "); if ( vpmu_is_set(vpmu, VPMU_CONTEXT_SAVE) ) diff --git a/xen/arch/x86/cpu/vpmu_intel.c b/xen/arch/x86/cpu/vpmu_intel.c index 7ce98ee42e..1e3b06ef8e 100644 --- a/xen/arch/x86/cpu/vpmu_intel.c +++ b/xen/arch/x86/cpu/vpmu_intel.c @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -441,9 +440,6 @@ static int cf_check core2_vpmu_alloc_resource(struct vcpu *v) struct xen_pmu_intel_ctxt *core2_vpmu_cxt = NULL; uint64_t *p = NULL; - if ( !acquire_pmu_ownership(PMU_OWNER_HVM) ) - return 0; - if ( is_vmx_vcpu(v) ) { if ( vmx_add_host_load_msr(v, MSR_CORE_PERF_GLOBAL_CTRL, 0) ) @@ -487,7 +483,6 @@ static int cf_check core2_vpmu_alloc_resource(struct vcpu *v) return 1; out_err: - release_pmu_ownership(PMU_OWNER_HVM); xfree(core2_vpmu_cxt); xfree(p); @@ -814,7 +809,6 @@ static void cf_check core2_vpmu_destroy(struct vcpu *v) vpmu->priv_context = NULL; if ( is_vmx_vcpu(v) && cpu_has_vmx_msr_bitmap ) core2_vpmu_unset_msr_bitmap(v); - release_pmu_ownership(PMU_OWNER_HVM); vpmu_clear(vpmu); } diff --git a/xen/arch/x86/hvm/svm/entry.S b/xen/arch/x86/hvm/svm/entry.S index 610c64bf4c..af8db23b03 100644 --- a/xen/arch/x86/hvm/svm/entry.S +++ b/xen/arch/x86/hvm/svm/entry.S @@ -155,7 +155,6 @@ __UNLIKELY_END(nsvm_hap) * to safely resolve any Spectre-v1 concerns in the above logic. */ stgi -LABEL(svm_stgi_label, 0) call svm_vmexit_handler jmp .Lsvm_do_resume diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 1208999454..da113f488b 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -36,7 +36,6 @@ #include #include #include -#include #include @@ -1152,7 +1151,6 @@ static int cf_check svm_vcpu_initialise(struct vcpu *v) static void cf_check svm_vcpu_destroy(struct vcpu *v) { svm_destroy_vmcb(v); - passive_domain_destroy(v); } /* diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 05b59cb8e4..f4beac192d 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #include @@ -692,7 +691,6 @@ static void cf_check vmx_vcpu_destroy(struct vcpu *v) */ vmx_vcpu_disable_pml(v); vmx_destroy_vmcs(v); - passive_domain_destroy(v); } /* @@ -3560,9 +3558,6 @@ static int cf_check vmx_msr_read_intercept( break; default: - if ( passive_domain_do_rdmsr(msr, msr_content) ) - goto done; - if ( vmx_read_guest_msr(curr, msr, msr_content) == 0 ) break; @@ -3582,7 +3577,6 @@ static int cf_check vmx_msr_read_intercept( goto gp_fault; } -done: HVM_DBG_LOG(DBG_LEVEL_MSR, "returns: ecx=%#x, msr_value=%#"PRIx64, msr, *msr_content); return X86EMUL_OKAY; @@ -3875,9 +3869,6 @@ static int cf_check vmx_msr_write_intercept( break; default: - if ( passive_domain_do_wrmsr(msr, msr_content) ) - return X86EMUL_OKAY; - if ( vmx_write_guest_msr(v, msr, msr_content) == 0 || is_last_branch_msr(msr) ) break; diff --git a/xen/arch/x86/include/asm/vpmu.h b/xen/arch/x86/include/asm/vpmu.h index dae9b43dac..d4504201fe 100644 --- a/xen/arch/x86/include/asm/vpmu.h +++ b/xen/arch/x86/include/asm/vpmu.h @@ -65,7 +65,7 @@ struct vpmu_struct { #define VPMU_RUNNING 0x0008 #define VPMU_CONTEXT_SAVE 0x0010 /* Force context save */ #define VPMU_FROZEN 0x0020 /* Stop counters while VCPU is not running */ -#define VPMU_PASSIVE_DOMAIN_ALLOCATED 0x0040 +/* 0x0040 available */ /* PV(H) guests: VPMU registers are accessed by guest from shared page */ #define VPMU_CACHED 0x0080 #define VPMU_AVAILABLE 0x0100 diff --git a/xen/arch/x86/include/asm/xenoprof.h b/xen/arch/x86/include/asm/xenoprof.h deleted file mode 100644 index dc6f822d32..0000000000 --- a/xen/arch/x86/include/asm/xenoprof.h +++ /dev/null @@ -1,95 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/****************************************************************************** - * asm-x86/xenoprof.h - * xenoprof x86 arch specific header file - * - * Copyright (c) 2006 Isaku Yamahata - * VA Linux Systems Japan K.K. - */ - -#ifndef __ASM_X86_XENOPROF_H__ -#define __ASM_X86_XENOPROF_H__ - -struct vcpu; - -#ifdef CONFIG_XENOPROF - -#include - -int nmi_reserve_counters(void); -int nmi_setup_events(void); -int nmi_enable_virq(void); -int nmi_start(void); -void nmi_stop(void); -void nmi_disable_virq(void); -void nmi_release_counters(void); - -int xenoprof_arch_init(int *num_events, char *cpu_type); -#define xenoprof_arch_reserve_counters() nmi_reserve_counters() -#define xenoprof_arch_setup_events() nmi_setup_events() -#define xenoprof_arch_enable_virq() nmi_enable_virq() -#define xenoprof_arch_start() nmi_start() -#define xenoprof_arch_stop() nmi_stop() -#define xenoprof_arch_disable_virq() nmi_disable_virq() -#define xenoprof_arch_release_counters() nmi_release_counters() - -int xenoprof_arch_counter(XEN_GUEST_HANDLE_PARAM(void) arg); -int compat_oprof_arch_counter(XEN_GUEST_HANDLE_PARAM(void) arg); -int xenoprof_arch_ibs_counter(XEN_GUEST_HANDLE_PARAM(void) arg); - -struct cpu_user_regs; - -/* AMD IBS support */ -void ibs_init(void); -extern u32 ibs_caps; - -int xenoprofile_get_mode(struct vcpu *, const struct cpu_user_regs *); - -static inline int xenoprof_backtrace_supported(void) -{ - return 1; -} - -void xenoprof_backtrace(struct vcpu *, const struct cpu_user_regs *, - unsigned long depth, int mode); - -int passive_domain_do_rdmsr(unsigned int msr, uint64_t *msr_content); -int passive_domain_do_wrmsr(unsigned int msr, uint64_t msr_content); -void passive_domain_destroy(struct vcpu *v); - -bool nmi_oprofile_send_virq(void); - -#else - -static inline int passive_domain_do_rdmsr(unsigned int msr, - uint64_t *msr_content) -{ - return 0; -} - -static inline int passive_domain_do_wrmsr(unsigned int msr, - uint64_t msr_content) -{ - return 0; -} - -static inline void passive_domain_destroy(struct vcpu *v) {} - -static inline bool nmi_oprofile_send_virq(void) -{ - return false; -} - -#endif /* CONFIG_XENOPROF */ - -#endif /* __ASM_X86_XENOPROF_H__ */ - -/* - * Local variables: - * mode: C - * c-file-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/arch/x86/oprofile/Makefile b/xen/arch/x86/oprofile/Makefile deleted file mode 100644 index 956e3d1b5d..0000000000 --- a/xen/arch/x86/oprofile/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -obj-y += xenoprof.o -obj-y += nmi_int.o -obj-y += op_model_p4.o -obj-y += op_model_ppro.o -obj-y += op_model_athlon.o -obj-y += backtrace.o diff --git a/xen/arch/x86/oprofile/backtrace.c b/xen/arch/x86/oprofile/backtrace.c deleted file mode 100644 index 61de18c8d5..0000000000 --- a/xen/arch/x86/oprofile/backtrace.c +++ /dev/null @@ -1,145 +0,0 @@ -/** - * @file backtrace.c - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author David Smith - * Modified for Xen by Amitabha Roy - * - */ - -#include -#include -#include -#include - -struct __packed frame_head { - struct frame_head * ebp; - unsigned long ret; -}; -typedef struct frame_head frame_head_t; - -struct __packed frame_head_32bit { - uint32_t ebp; - uint32_t ret; -}; -typedef struct frame_head_32bit frame_head32_t; - -static struct frame_head * -dump_hypervisor_backtrace(struct vcpu *vcpu, const struct frame_head *head, - int mode) -{ - if (!xenoprof_add_trace(vcpu, head->ret, mode)) - return 0; - - /* frame pointers should strictly progress back up the stack - * (towards higher addresses) */ - if (head >= head->ebp) - return NULL; - - return head->ebp; -} - -static inline int is_32bit_vcpu(struct vcpu *vcpu) -{ - if (is_hvm_vcpu(vcpu)) - return !hvm_long_mode_active(vcpu); - else - return is_pv_32bit_vcpu(vcpu); -} - -static struct frame_head * -dump_guest_backtrace(struct vcpu *vcpu, const struct frame_head *head, - int mode) -{ - /* Also check accessibility of one struct frame_head beyond. */ - frame_head_t bufhead[2]; - - if ( is_32bit_vcpu(vcpu) ) - { - frame_head32_t bufhead32[2]; - - if ( raw_copy_from_guest(bufhead32, head, sizeof(bufhead32)) ) - return 0; - bufhead[0].ebp = (struct frame_head *)(unsigned long)bufhead32[0].ebp; - bufhead[0].ret = bufhead32[0].ret; - } - else if ( raw_copy_from_guest(bufhead, head, sizeof(bufhead)) ) - return 0; - - if ( !xenoprof_add_trace(vcpu, bufhead[0].ret, mode) ) - return 0; - - /* frame pointers should strictly progress back up the stack - * (towards higher addresses) */ - if ( head >= bufhead[0].ebp ) - return NULL; - - return bufhead[0].ebp; -} - -/* - * | | /\ Higher addresses - * | | - * --------------- stack base (address of current_thread_info) - * | thread info | - * . . - * | stack | - * --------------- saved regs->ebp value if valid (frame_head address) - * . . - * --------------- saved regs->rsp value if x86_64 - * | | - * --------------- struct pt_regs * stored on stack if 32-bit - * | | - * . . - * | | - * --------------- %esp - * | | - * | | \/ Lower addresses - * - * Thus, regs (or regs->rsp for x86_64) <-> stack base restricts the - * valid(ish) ebp values. Note: (1) for x86_64, NMI and several other - * exceptions use special stacks, maintained by the interrupt stack table - * (IST). These stacks are set up in trap_init() in - * arch/x86_64/kernel/traps.c. Thus, for x86_64, regs now does not point - * to the kernel stack; instead, it points to some location on the NMI - * stack. On the other hand, regs->rsp is the stack pointer saved when the - * NMI occurred. (2) For 32-bit, regs->esp is not valid because the - * processor does not save %esp on the kernel stack when interrupts occur - * in the kernel mode. - */ -#if defined(CONFIG_FRAME_POINTER) -static int valid_hypervisor_stack(const struct frame_head *head, - const struct cpu_user_regs *regs) -{ - unsigned long headaddr = (unsigned long)head; - unsigned long stack = (unsigned long)regs->rsp; - unsigned long stack_base = (stack & ~(STACK_SIZE - 1)) + STACK_SIZE; - - return headaddr > stack && headaddr < stack_base; -} -#else -/* without fp, it's just junk */ -static int valid_hypervisor_stack(const struct frame_head *head, - const struct cpu_user_regs *regs) -{ - return 0; -} -#endif - -void xenoprof_backtrace(struct vcpu *vcpu, const struct cpu_user_regs *regs, - unsigned long depth, int mode) -{ - const struct frame_head *head = (void *)regs->rbp; - - if (mode > 1) { - while (depth-- && valid_hypervisor_stack(head, regs)) - head = dump_hypervisor_backtrace(vcpu, head, mode); - return; - } - - while (depth-- && head) - head = dump_guest_backtrace(vcpu, head, mode); -} diff --git a/xen/arch/x86/oprofile/nmi_int.c b/xen/arch/x86/oprofile/nmi_int.c deleted file mode 100644 index 1d6454cf39..0000000000 --- a/xen/arch/x86/oprofile/nmi_int.c +++ /dev/null @@ -1,485 +0,0 @@ -/** - * @file nmi_int.c - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * - * Modified for Xen: by Aravind Menon & Jose Renato Santos - * These modifications are: - * Copyright (C) 2005 Hewlett-Packard Co. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include "op_counter.h" -#include "op_x86_model.h" - -struct op_counter_config counter_config[OP_MAX_COUNTER]; -struct op_ibs_config ibs_config; - -struct op_x86_model_spec const *__read_mostly model; -static struct op_msrs cpu_msrs[NR_CPUS]; -static unsigned long saved_lvtpc[NR_CPUS]; - -static const char *cpu_type; - -static DEFINE_PER_CPU(struct vcpu *, nmi_cont_vcpu); - -static int passive_domain_msr_op_checks(unsigned int msr, int *typep, int *indexp) -{ - struct vpmu_struct *vpmu = vcpu_vpmu(current); - if ( model == NULL ) - return 0; - if ( model->is_arch_pmu_msr == NULL ) - return 0; - if ( !model->is_arch_pmu_msr(msr, typep, indexp) ) - return 0; - - if ( !vpmu_is_set(vpmu, VPMU_PASSIVE_DOMAIN_ALLOCATED) ) - if ( ! model->allocated_msr(current) ) - return 0; - return 1; -} - -int passive_domain_do_rdmsr(unsigned int msr, uint64_t *msr_content) -{ - int type, index; - - if ( !passive_domain_msr_op_checks(msr, &type, &index)) - return 0; - - model->load_msr(current, type, index, msr_content); - return 1; -} - -int passive_domain_do_wrmsr(unsigned int msr, uint64_t msr_content) -{ - int type, index; - - if ( !passive_domain_msr_op_checks(msr, &type, &index)) - return 0; - - model->save_msr(current, type, index, msr_content); - return 1; -} - -void passive_domain_destroy(struct vcpu *v) -{ - struct vpmu_struct *vpmu = vcpu_vpmu(v); - if ( vpmu_is_set(vpmu, VPMU_PASSIVE_DOMAIN_ALLOCATED) ) - model->free_msr(v); -} - -bool nmi_oprofile_send_virq(void) -{ - struct vcpu *v = xchg(&this_cpu(nmi_cont_vcpu), NULL); - - if (v) - send_guest_vcpu_virq(v, VIRQ_XENOPROF); - - return v; -} - -static int cf_check nmi_callback(const struct cpu_user_regs *regs, int cpu) -{ - int xen_mode, ovf; - - ovf = model->check_ctrs(cpu, &cpu_msrs[cpu], regs); - xen_mode = ring_0(regs); - if (ovf && is_active(current->domain) && !xen_mode && - !this_cpu(nmi_cont_vcpu)) { - this_cpu(nmi_cont_vcpu) = current; - trigger_nmi_continuation(); - } - - if ( ovf == 2 ) - current->arch.nmi_pending = true; - return 1; -} - - -static void nmi_cpu_save_registers(struct op_msrs *msrs) -{ - unsigned int const nr_ctrs = model->num_counters; - unsigned int const nr_ctrls = model->num_controls; - struct op_msr *counters = msrs->counters; - struct op_msr *controls = msrs->controls; - unsigned int i; - - for (i = 0; i < nr_ctrs; ++i) { - rdmsrl(counters[i].addr, counters[i].value); - } - - for (i = 0; i < nr_ctrls; ++i) { - rdmsrl(controls[i].addr, controls[i].value); - } -} - - -static void cf_check nmi_save_registers(void *dummy) -{ - int cpu = smp_processor_id(); - struct op_msrs * msrs = &cpu_msrs[cpu]; - model->fill_in_addresses(msrs); - nmi_cpu_save_registers(msrs); -} - - -static void free_msrs(void) -{ - unsigned int i; - - for (i = 0; i < nr_cpu_ids; ++i) { - XVFREE(cpu_msrs[i].counters); - XVFREE(cpu_msrs[i].controls); - } -} - - -static int allocate_msrs(void) -{ - unsigned int i; - int success = 1; - - for_each_online_cpu (i) { - cpu_msrs[i].counters = xvmalloc_array(struct op_msr, - model->num_counters); - if (!cpu_msrs[i].counters) { - success = 0; - break; - } - cpu_msrs[i].controls = xvmalloc_array(struct op_msr, - model->num_controls); - if (!cpu_msrs[i].controls) { - success = 0; - break; - } - } - - if (!success) - free_msrs(); - - return success; -} - - -static void cf_check nmi_cpu_setup(void *dummy) -{ - int cpu = smp_processor_id(); - struct op_msrs * msrs = &cpu_msrs[cpu]; - model->setup_ctrs(msrs); -} - - -int nmi_setup_events(void) -{ - on_each_cpu(nmi_cpu_setup, NULL, 1); - return 0; -} - -int nmi_reserve_counters(void) -{ - if (!allocate_msrs()) - return -ENOMEM; - - /* - * We need to be careful to install our NMI handler - * without actually triggering any NMIs as this will - * break the core code horrifically. - */ - if (reserve_lapic_nmi() < 0) { - free_msrs(); - return -EBUSY; - } - /* We need to serialize save and setup for HT because the subset - * of msrs are distinct for save and setup operations - */ - on_each_cpu(nmi_save_registers, NULL, 1); - return 0; -} - -int nmi_enable_virq(void) -{ - set_nmi_callback(nmi_callback); - return 0; -} - - -void nmi_disable_virq(void) -{ - unset_nmi_callback(); -} - - -static void nmi_restore_registers(struct op_msrs * msrs) -{ - unsigned int const nr_ctrs = model->num_counters; - unsigned int const nr_ctrls = model->num_controls; - struct op_msr * counters = msrs->counters; - struct op_msr * controls = msrs->controls; - unsigned int i; - - for (i = 0; i < nr_ctrls; ++i) { - wrmsrl(controls[i].addr, controls[i].value); - } - - for (i = 0; i < nr_ctrs; ++i) { - wrmsrl(counters[i].addr, counters[i].value); - } -} - - -static void cf_check nmi_cpu_shutdown(void *dummy) -{ - int cpu = smp_processor_id(); - struct op_msrs * msrs = &cpu_msrs[cpu]; - nmi_restore_registers(msrs); -} - - -void nmi_release_counters(void) -{ - on_each_cpu(nmi_cpu_shutdown, NULL, 1); - release_lapic_nmi(); - free_msrs(); -} - - -static void cf_check nmi_cpu_start(void *dummy) -{ - int cpu = smp_processor_id(); - struct op_msrs const * msrs = &cpu_msrs[cpu]; - saved_lvtpc[cpu] = apic_read(APIC_LVTPC); - apic_write(APIC_LVTPC, APIC_DM_NMI); - model->start(msrs); -} - - -int nmi_start(void) -{ - on_each_cpu(nmi_cpu_start, NULL, 1); - return 0; -} - - -static void cf_check nmi_cpu_stop(void *dummy) -{ - unsigned int v; - int cpu = smp_processor_id(); - struct op_msrs const * msrs = &cpu_msrs[cpu]; - model->stop(msrs); - - /* restoring APIC_LVTPC can trigger an apic error because the delivery - * mode and vector nr combination can be illegal. That's by design: on - * power on apic lvt contain a zero vector nr which are legal only for - * NMI delivery mode. So inhibit apic err before restoring lvtpc - */ - if ( (apic_read(APIC_LVTPC) & APIC_DM_MASK) != APIC_DM_NMI - || (apic_read(APIC_LVTPC) & APIC_LVT_MASKED) ) - { - printk("nmi_stop: APIC not good %ul\n", apic_read(APIC_LVTPC)); - mdelay(5000); - } - v = apic_read(APIC_LVTERR); - apic_write(APIC_LVTERR, v | APIC_LVT_MASKED); - apic_write(APIC_LVTPC, saved_lvtpc[cpu]); - apic_write(APIC_LVTERR, v); -} - - -void nmi_stop(void) -{ - on_each_cpu(nmi_cpu_stop, NULL, 1); -} - - -static int __init p4_init(const char **cpu_type) -{ - unsigned int cpu_model = current_cpu_data.x86_model; - - if ((cpu_model > 6) || (cpu_model == 5)) { - printk("xenoprof: Initialization failed. " - "Intel processor model %u for pentium 4 family is not " - "supported\n", cpu_model); - return 0; - } - - switch (current_cpu_data.x86_num_siblings) { - case 1: - *cpu_type = "i386/p4"; - model = &op_p4_spec; - return 1; - - case 2: - *cpu_type = "i386/p4-ht"; - model = &op_p4_ht2_spec; - return 1; - } - - printk("Xenoprof ERROR: P4 HyperThreading detected with > 2 threads\n"); - - return 0; -} - - -static int force_arch_perfmon; - -static int __init cf_check force_cpu_type(const char *str) -{ - if (!strcmp(str, "arch_perfmon")) { - force_arch_perfmon = 1; - printk(KERN_INFO "oprofile: forcing architectural perfmon\n"); - } - else - return -EINVAL; - - return 0; -} -custom_param("cpu_type", force_cpu_type); - -static int __init ppro_init(const char **cpu_type) -{ - if (force_arch_perfmon && cpu_has_arch_perfmon) - return 0; - - switch (current_cpu_data.x86_model) { - case 14: - *cpu_type = "i386/core"; - break; - case 15: - *cpu_type = "i386/core_2"; - ppro_has_global_ctrl = 1; - break; - default: - /* Unknown */ - return 0; - } - - model = &op_ppro_spec; - return 1; -} - -static int __init arch_perfmon_init(const char **cpu_type) -{ - if (!cpu_has_arch_perfmon) - return 0; - *cpu_type = "i386/arch_perfmon"; - model = &op_arch_perfmon_spec; - arch_perfmon_setup_counters(); - ppro_has_global_ctrl = 1; - return 1; -} - -static int __init cf_check nmi_init(void) -{ - unsigned int vendor = current_cpu_data.x86_vendor; - unsigned int family = current_cpu_data.x86; - - if (!cpu_has_apic) { - printk("xenoprof: Initialization failed. No APIC\n"); - return -ENODEV; - } - - switch (vendor) { - case X86_VENDOR_AMD: - /* Needs to be at least an Athlon (or hammer in 32bit mode) */ - - switch (family) { - default: - printk("xenoprof: Initialization failed. " - "AMD processor family %u is not " - "supported\n", family); - return -ENODEV; - case 0xf: - model = &op_athlon_spec; - cpu_type = "x86-64/hammer"; - break; - case 0x10: - model = &op_athlon_spec; - cpu_type = "x86-64/family10"; - ibs_init(); - break; - case 0x11: - model = &op_athlon_spec; - cpu_type = "x86-64/family11h"; - break; - case 0x12: - model = &op_athlon_spec; - cpu_type = "x86-64/family12h"; - break; - case 0x14: - model = &op_athlon_spec; - cpu_type = "x86-64/family14h"; - break; - case 0x15: - model = &op_amd_fam15h_spec; - cpu_type = "x86-64/family15h"; - break; - case 0x16: - model = &op_athlon_spec; - cpu_type = "x86-64/family16h"; - break; - } - break; - - case X86_VENDOR_INTEL: - switch (family) { - /* Pentium IV */ - case 0xf: - p4_init(&cpu_type); - break; - - /* A P6-class processor */ - case 6: - ppro_init(&cpu_type); - break; - - default: - break; - } - if (!cpu_type && !arch_perfmon_init(&cpu_type)) { - printk("xenoprof: Initialization failed. " - "Intel processor family %u model %d is not supported\n", - family, current_cpu_data.x86_model); - return -ENODEV; - } - break; - - default: - printk("xenoprof: Initialization failed. " - "Unsupported processor. Unknown vendor %u\n", - vendor); - return -ENODEV; - } - - return 0; -} - -__initcall(nmi_init); - -int xenoprof_arch_init(int *num_events, char *_cpu_type) -{ - if (cpu_type == NULL) - return -ENODEV; - *num_events = model->num_counters; - strlcpy(_cpu_type, cpu_type, XENOPROF_CPU_TYPE_SIZE); - return 0; -} diff --git a/xen/arch/x86/oprofile/op_counter.h b/xen/arch/x86/oprofile/op_counter.h deleted file mode 100644 index b515ac9ebc..0000000000 --- a/xen/arch/x86/oprofile/op_counter.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @file op_counter.h - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - */ - -#ifndef OP_COUNTER_H -#define OP_COUNTER_H - -#define OP_MAX_COUNTER 8 - -/* Per-perfctr configuration as set via - * oprofilefs. - */ -struct op_counter_config { - unsigned long count; - unsigned long enabled; - unsigned long event; - unsigned long kernel; - unsigned long user; - unsigned long unit_mask; -}; - -extern struct op_counter_config counter_config[]; - -/* AMD IBS configuration */ -struct op_ibs_config { - unsigned long op_enabled; - unsigned long fetch_enabled; - unsigned long max_cnt_fetch; - unsigned long max_cnt_op; - unsigned long rand_en; - unsigned long dispatched_ops; -}; - -extern struct op_ibs_config ibs_config; - -#endif /* OP_COUNTER_H */ diff --git a/xen/arch/x86/oprofile/op_model_athlon.c b/xen/arch/x86/oprofile/op_model_athlon.c deleted file mode 100644 index 4c016624a6..0000000000 --- a/xen/arch/x86/oprofile/op_model_athlon.c +++ /dev/null @@ -1,547 +0,0 @@ -/** - * @file op_model_athlon.h - * athlon / K7 model-specific MSR operations - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - * @author Graydon Hoare - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "op_x86_model.h" -#include "op_counter.h" - -#define K7_NUM_COUNTERS 4 -#define K7_NUM_CONTROLS 4 - -#define FAM15H_NUM_COUNTERS 6 -#define FAM15H_NUM_CONTROLS 6 - -#define MAX_COUNTERS FAM15H_NUM_COUNTERS - -#define CTR_READ(msr_content,msrs,c) do {rdmsrl(msrs->counters[(c)].addr, (msr_content));} while (0) -#define CTR_WRITE(l,msrs,c) wrmsr(msrs->counters[(c)].addr, -(l)) -#define CTR_OVERFLOWED(n) (!((n) & (1ULL<<31))) - -#define CTRL_READ(msr_content,msrs,c) do {rdmsrl(msrs->controls[(c)].addr, (msr_content));} while (0) -#define CTRL_WRITE(msr_content,msrs,c) do {wrmsrl(msrs->controls[(c)].addr, (msr_content));} while (0) -#define CTRL_SET_ACTIVE(n) (n |= (1ULL<<22)) -#define CTRL_SET_INACTIVE(n) (n &= ~(1ULL<<22)) -#define CTRL_CLEAR(val) (val &= (1ULL<<21)) -#define CTRL_SET_ENABLE(val) (val |= 1ULL<<20) -#define CTRL_SET_USR(val,u) (val |= ((u & 1) << 16)) -#define CTRL_SET_KERN(val,k) (val |= ((k & 1) << 17)) -#define CTRL_SET_UM(val, m) (val |= ((m & 0xff) << 8)) -#define CTRL_SET_EVENT(val, e) (val |= (((e >> 8) & 0xf) | (e & 0xff))) -#define CTRL_SET_HOST_ONLY(val, h) (val |= ((h & 0x1ULL) << 41)) -#define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 0x1ULL) << 40)) - -static unsigned long reset_value[MAX_COUNTERS]; - -extern char svm_stgi_label[]; - -u32 ibs_caps = 0; -static u64 ibs_op_ctl; - -/* IBS cpuid feature detection */ -#define IBS_CPUID_FEATURES 0x8000001b - -/* IBS MSRs */ -#define MSR_AMD64_IBSFETCHCTL 0xc0011030 -#define MSR_AMD64_IBSFETCHLINAD 0xc0011031 -#define MSR_AMD64_IBSFETCHPHYSAD 0xc0011032 -#define MSR_AMD64_IBSOPCTL 0xc0011033 -#define MSR_AMD64_IBSOPRIP 0xc0011034 -#define MSR_AMD64_IBSOPDATA 0xc0011035 -#define MSR_AMD64_IBSOPDATA2 0xc0011036 -#define MSR_AMD64_IBSOPDATA3 0xc0011037 -#define MSR_AMD64_IBSDCLINAD 0xc0011038 -#define MSR_AMD64_IBSDCPHYSAD 0xc0011039 -#define MSR_AMD64_IBSCTL 0xc001103a - -/* - * Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but - * bit 0 is used to indicate the existence of IBS. - */ -#define IBS_CAPS_AVAIL (1LL<<0) -#define IBS_CAPS_RDWROPCNT (1LL<<3) -#define IBS_CAPS_OPCNT (1LL<<4) - -/* IBS randomization macros */ -#define IBS_RANDOM_BITS 12 -#define IBS_RANDOM_MASK ((1ULL << IBS_RANDOM_BITS) - 1) -#define IBS_RANDOM_MAXCNT_OFFSET (1ULL << (IBS_RANDOM_BITS - 5)) - -/* IbsFetchCtl bits/masks */ -#define IBS_FETCH_RAND_EN (1ULL<<57) -#define IBS_FETCH_VAL (1ULL<<49) -#define IBS_FETCH_ENABLE (1ULL<<48) -#define IBS_FETCH_CNT 0xFFFF0000ULL -#define IBS_FETCH_MAX_CNT 0x0000FFFFULL - -/* IbsOpCtl bits */ -#define IBS_OP_CNT_CTL (1ULL<<19) -#define IBS_OP_VAL (1ULL<<18) -#define IBS_OP_ENABLE (1ULL<<17) -#define IBS_OP_MAX_CNT 0x0000FFFFULL - -/* IBS sample identifier */ -#define IBS_FETCH_CODE 13 -#define IBS_OP_CODE 14 - -#define clamp(val, min, max) ({ \ - typeof(val) __val = (val); \ - typeof(min) __min = (min); \ - typeof(max) __max = (max); \ - (void) (&__val == &__min); \ - (void) (&__val == &__max); \ - __val = __val < __min ? __min: __val; \ - __val > __max ? __max: __val; }) - -/* - * 16-bit Linear Feedback Shift Register (LFSR) - */ -static unsigned int lfsr_random(void) -{ - static unsigned int lfsr_value = 0xF00D; - unsigned int bit; - - /* Compute next bit to shift in */ - bit = ((lfsr_value >> 0) ^ - (lfsr_value >> 2) ^ - (lfsr_value >> 3) ^ - (lfsr_value >> 5)) & 0x0001; - - /* Advance to next register value */ - lfsr_value = (lfsr_value >> 1) | (bit << 15); - - return lfsr_value; -} - -/* - * IBS software randomization - * - * The IBS periodic op counter is randomized in software. The lower 12 - * bits of the 20 bit counter are randomized. IbsOpCurCnt is - * initialized with a 12 bit random value. - */ -static inline u64 op_amd_randomize_ibs_op(u64 val) -{ - unsigned int random = lfsr_random(); - - if (!(ibs_caps & IBS_CAPS_RDWROPCNT)) - /* - * Work around if the hw can not write to IbsOpCurCnt - * - * Randomize the lower 8 bits of the 16 bit - * IbsOpMaxCnt [15:0] value in the range of -128 to - * +127 by adding/subtracting an offset to the - * maximum count (IbsOpMaxCnt). - * - * To avoid over or underflows and protect upper bits - * starting at bit 16, the initial value for - * IbsOpMaxCnt must fit in the range from 0x0081 to - * 0xff80. - */ - val += (int8_t)(random >> 4); - else - val |= (u64)(random & IBS_RANDOM_MASK) << 32; - - return val; -} - -static void cf_check athlon_fill_in_addresses(struct op_msrs * const msrs) -{ - msrs->counters[0].addr = MSR_K7_PERFCTR0; - msrs->counters[1].addr = MSR_K7_PERFCTR1; - msrs->counters[2].addr = MSR_K7_PERFCTR2; - msrs->counters[3].addr = MSR_K7_PERFCTR3; - - msrs->controls[0].addr = MSR_K7_EVNTSEL0; - msrs->controls[1].addr = MSR_K7_EVNTSEL1; - msrs->controls[2].addr = MSR_K7_EVNTSEL2; - msrs->controls[3].addr = MSR_K7_EVNTSEL3; -} - -static void cf_check fam15h_fill_in_addresses(struct op_msrs * const msrs) -{ - msrs->counters[0].addr = MSR_AMD_FAM15H_PERFCTR0; - msrs->counters[1].addr = MSR_AMD_FAM15H_PERFCTR1; - msrs->counters[2].addr = MSR_AMD_FAM15H_PERFCTR2; - msrs->counters[3].addr = MSR_AMD_FAM15H_PERFCTR3; - msrs->counters[4].addr = MSR_AMD_FAM15H_PERFCTR4; - msrs->counters[5].addr = MSR_AMD_FAM15H_PERFCTR5; - - msrs->controls[0].addr = MSR_AMD_FAM15H_EVNTSEL0; - msrs->controls[1].addr = MSR_AMD_FAM15H_EVNTSEL1; - msrs->controls[2].addr = MSR_AMD_FAM15H_EVNTSEL2; - msrs->controls[3].addr = MSR_AMD_FAM15H_EVNTSEL3; - msrs->controls[4].addr = MSR_AMD_FAM15H_EVNTSEL4; - msrs->controls[5].addr = MSR_AMD_FAM15H_EVNTSEL5; -} - -static void cf_check athlon_setup_ctrs(struct op_msrs const * const msrs) -{ - uint64_t msr_content; - int i; - unsigned int const nr_ctrs = model->num_counters; - unsigned int const nr_ctrls = model->num_controls; - - /* clear all counters */ - for (i = 0 ; i < nr_ctrls; ++i) { - CTRL_READ(msr_content, msrs, i); - CTRL_CLEAR(msr_content); - CTRL_WRITE(msr_content, msrs, i); - } - - /* avoid a false detection of ctr overflows in NMI handler */ - for (i = 0; i < nr_ctrs; ++i) { - CTR_WRITE(1, msrs, i); - } - - /* enable active counters */ - for (i = 0; i < nr_ctrs; ++i) { - if (counter_config[i].enabled) { - reset_value[i] = counter_config[i].count; - - CTR_WRITE(counter_config[i].count, msrs, i); - - CTRL_READ(msr_content, msrs, i); - CTRL_CLEAR(msr_content); - CTRL_SET_ENABLE(msr_content); - CTRL_SET_USR(msr_content, counter_config[i].user); - CTRL_SET_KERN(msr_content, counter_config[i].kernel); - CTRL_SET_UM(msr_content, counter_config[i].unit_mask); - CTRL_SET_EVENT(msr_content, counter_config[i].event); - CTRL_SET_HOST_ONLY(msr_content, 0); - CTRL_SET_GUEST_ONLY(msr_content, 0); - CTRL_WRITE(msr_content, msrs, i); - } else { - reset_value[i] = 0; - } - } -} - -static inline void -ibs_log_event(u64 data, struct cpu_user_regs const * const regs, int mode) -{ - struct vcpu *v = current; - u32 temp = 0; - - temp = data & 0xFFFFFFFF; - xenoprof_log_event(v, regs, temp, mode, 0); - - temp = (data >> 32) & 0xFFFFFFFF; - xenoprof_log_event(v, regs, temp, mode, 0); - -} - -static inline int handle_ibs(int mode, struct cpu_user_regs const * const regs) -{ - u64 val, ctl; - struct vcpu *v = current; - - if (!ibs_caps) - return 1; - - if (ibs_config.fetch_enabled) { - rdmsrl(MSR_AMD64_IBSFETCHCTL, ctl); - if (ctl & IBS_FETCH_VAL) { - rdmsrl(MSR_AMD64_IBSFETCHLINAD, val); - xenoprof_log_event(v, regs, IBS_FETCH_CODE, mode, 0); - xenoprof_log_event(v, regs, val, mode, 0); - - ibs_log_event(val, regs, mode); - ibs_log_event(ctl, regs, mode); - - rdmsrl(MSR_AMD64_IBSFETCHPHYSAD, val); - ibs_log_event(val, regs, mode); - - /* reenable the IRQ */ - ctl &= ~(IBS_FETCH_VAL | IBS_FETCH_CNT); - ctl |= IBS_FETCH_ENABLE; - wrmsrl(MSR_AMD64_IBSFETCHCTL, ctl); - } - } - - if (ibs_config.op_enabled) { - rdmsrl(MSR_AMD64_IBSOPCTL, ctl); - if (ctl & IBS_OP_VAL) { - - rdmsrl(MSR_AMD64_IBSOPRIP, val); - xenoprof_log_event(v, regs, IBS_OP_CODE, mode, 0); - xenoprof_log_event(v, regs, val, mode, 0); - - ibs_log_event(val, regs, mode); - - rdmsrl(MSR_AMD64_IBSOPDATA, val); - ibs_log_event(val, regs, mode); - rdmsrl(MSR_AMD64_IBSOPDATA2, val); - ibs_log_event(val, regs, mode); - rdmsrl(MSR_AMD64_IBSOPDATA3, val); - ibs_log_event(val, regs, mode); - rdmsrl(MSR_AMD64_IBSDCLINAD, val); - ibs_log_event(val, regs, mode); - rdmsrl(MSR_AMD64_IBSDCPHYSAD, val); - ibs_log_event(val, regs, mode); - - /* reenable the IRQ */ - ctl = op_amd_randomize_ibs_op(ibs_op_ctl); - wrmsrl(MSR_AMD64_IBSOPCTL, ctl); - } - } - - return 1; -} - -static int cf_check athlon_check_ctrs( - unsigned int const cpu, struct op_msrs const * const msrs, - struct cpu_user_regs const * const regs) - -{ - uint64_t msr_content; - int i; - unsigned long eip = regs->rip; - int mode = 0; - struct vcpu *v = current; - unsigned int const nr_ctrs = model->num_counters; - -#ifdef CONFIG_AMD_SVM - struct cpu_user_regs *guest_regs = guest_cpu_user_regs(); - - if (!guest_mode(regs) && - (eip == (unsigned long)svm_stgi_label)) { - /* SVM guest was running when NMI occurred */ - ASSERT(is_hvm_vcpu(v)); - eip = guest_regs->rip; - mode = xenoprofile_get_mode(v, guest_regs); - } else -#endif - mode = xenoprofile_get_mode(v, regs); - - for (i = 0 ; i < nr_ctrs; ++i) { - CTR_READ(msr_content, msrs, i); - if (CTR_OVERFLOWED(msr_content)) { - xenoprof_log_event(current, regs, eip, mode, i); - CTR_WRITE(reset_value[i], msrs, i); - } - } - - /* See op_model_ppro.c */ - return handle_ibs(mode, regs); -} - -static inline void start_ibs(void) -{ - u64 val = 0; - - if (!ibs_caps) - return; - - if (ibs_config.fetch_enabled) { - val = (ibs_config.max_cnt_fetch >> 4) & IBS_FETCH_MAX_CNT; - val |= ibs_config.rand_en ? IBS_FETCH_RAND_EN : 0; - val |= IBS_FETCH_ENABLE; - wrmsrl(MSR_AMD64_IBSFETCHCTL, val); - } - - if (ibs_config.op_enabled) { - ibs_op_ctl = ibs_config.max_cnt_op >> 4; - if (!(ibs_caps & IBS_CAPS_RDWROPCNT)) { - /* - * IbsOpCurCnt not supported. See - * op_amd_randomize_ibs_op() for details. - */ - ibs_op_ctl = clamp((unsigned long long)ibs_op_ctl, - 0x0081ULL, 0xFF80ULL); - } else { - /* - * The start value is randomized with a - * positive offset, we need to compensate it - * with the half of the randomized range. Also - * avoid underflows. - */ - ibs_op_ctl = min(ibs_op_ctl + IBS_RANDOM_MAXCNT_OFFSET, - IBS_OP_MAX_CNT); - } - if (ibs_caps & IBS_CAPS_OPCNT && ibs_config.dispatched_ops) - ibs_op_ctl |= IBS_OP_CNT_CTL; - ibs_op_ctl |= IBS_OP_ENABLE; - val = op_amd_randomize_ibs_op(ibs_op_ctl); - wrmsrl(MSR_AMD64_IBSOPCTL, val); - } -} - -static void cf_check athlon_start(struct op_msrs const * const msrs) -{ - uint64_t msr_content; - int i; - unsigned int const nr_ctrs = model->num_counters; - for (i = 0 ; i < nr_ctrs ; ++i) { - if (reset_value[i]) { - CTRL_READ(msr_content, msrs, i); - CTRL_SET_ACTIVE(msr_content); - CTRL_WRITE(msr_content, msrs, i); - } - } - start_ibs(); -} - -static void stop_ibs(void) -{ - if (!ibs_caps) - return; - - if (ibs_config.fetch_enabled) - /* clear max count and enable */ - wrmsrl(MSR_AMD64_IBSFETCHCTL, 0); - - if (ibs_config.op_enabled) - /* clear max count and enable */ - wrmsrl(MSR_AMD64_IBSOPCTL, 0); -} - -static void cf_check athlon_stop(struct op_msrs const * const msrs) -{ - uint64_t msr_content; - int i; - unsigned int const nr_ctrs = model->num_counters; - - /* Subtle: stop on all counters to avoid race with - * setting our pm callback */ - for (i = 0 ; i < nr_ctrs ; ++i) { - CTRL_READ(msr_content, msrs, i); - CTRL_SET_INACTIVE(msr_content); - CTRL_WRITE(msr_content, msrs, i); - } - - stop_ibs(); -} - -#define IBSCTL_LVTOFFSETVAL (1 << 8) -#define APIC_EILVT_MSG_NMI 0x4 -#define APIC_EILVT_LVTOFF_IBS 1 -#define APIC_EILVTn(n) (0x500 + 0x10 * n) -static inline void __init cf_check init_ibs_nmi_per_cpu(void *arg) -{ - unsigned long reg; - - reg = (APIC_EILVT_LVTOFF_IBS << 4) + APIC_EILVTn(0); - apic_write(reg, APIC_EILVT_MSG_NMI << 8); -} - -#define PCI_DEVICE_ID_AMD_10H_NB_MISC 0x1203 -#define IBSCTL 0x1cc -static int __init init_ibs_nmi(void) -{ - int bus, dev, func; - u32 id, value; - u16 vendor_id, dev_id; - int nodes; - - /* per CPU setup */ - on_each_cpu(init_ibs_nmi_per_cpu, NULL, 1); - - nodes = 0; - for (bus = 0; bus < 256; bus++) { - for (dev = 0; dev < 32; dev++) { - for (func = 0; func < 8; func++) { - id = pci_conf_read32(PCI_SBDF(0, bus, dev, func), - PCI_VENDOR_ID); - - vendor_id = id & 0xffff; - dev_id = (id >> 16) & 0xffff; - - if ((vendor_id == PCI_VENDOR_ID_AMD) && - (dev_id == PCI_DEVICE_ID_AMD_10H_NB_MISC)) { - - pci_conf_write32( - PCI_SBDF(0, bus, dev, func), - IBSCTL, - IBSCTL_LVTOFFSETVAL | APIC_EILVT_LVTOFF_IBS); - - value = pci_conf_read32(PCI_SBDF(0, bus, dev, func), - IBSCTL); - - if (value != (IBSCTL_LVTOFFSETVAL | - APIC_EILVT_LVTOFF_IBS)) { - printk("Xenoprofile: Failed to setup IBS LVT offset, " - "IBSCTL = %#x\n", value); - return 1; - } - nodes++; - } - } - } - } - - if (!nodes) { - printk("Xenoprofile: No CPU node configured for IBS\n"); - return 1; - } - - return 0; -} - -static void __init get_ibs_caps(void) -{ - if (!boot_cpu_has(X86_FEATURE_IBS)) - return; - - /* check IBS cpuid feature flags */ - if (current_cpu_data.extended_cpuid_level >= IBS_CPUID_FEATURES) - ibs_caps = cpuid_eax(IBS_CPUID_FEATURES); - if (!(ibs_caps & IBS_CAPS_AVAIL)) - /* cpuid flags not valid */ - ibs_caps = 0; -} - -void __init ibs_init(void) -{ - get_ibs_caps(); - - if ( !ibs_caps ) - return; - - if (init_ibs_nmi()) { - ibs_caps = 0; - return; - } - - printk("Xenoprofile: AMD IBS detected (%#x)\n", - (unsigned)ibs_caps); -} - -struct op_x86_model_spec const op_athlon_spec = { - .num_counters = K7_NUM_COUNTERS, - .num_controls = K7_NUM_CONTROLS, - .fill_in_addresses = &athlon_fill_in_addresses, - .setup_ctrs = &athlon_setup_ctrs, - .check_ctrs = &athlon_check_ctrs, - .start = &athlon_start, - .stop = &athlon_stop -}; - -struct op_x86_model_spec const op_amd_fam15h_spec = { - .num_counters = FAM15H_NUM_COUNTERS, - .num_controls = FAM15H_NUM_CONTROLS, - .fill_in_addresses = &fam15h_fill_in_addresses, - .setup_ctrs = &athlon_setup_ctrs, - .check_ctrs = &athlon_check_ctrs, - .start = &athlon_start, - .stop = &athlon_stop -}; diff --git a/xen/arch/x86/oprofile/op_model_p4.c b/xen/arch/x86/oprofile/op_model_p4.c deleted file mode 100644 index d047258644..0000000000 --- a/xen/arch/x86/oprofile/op_model_p4.c +++ /dev/null @@ -1,721 +0,0 @@ -/** - * @file op_model_p4.c - * P4 model-specific MSR operations - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author Graydon Hoare - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "op_x86_model.h" -#include "op_counter.h" - -#define NUM_EVENTS 39 - -#define NUM_COUNTERS_NON_HT 8 -#define NUM_ESCRS_NON_HT 45 -#define NUM_CCCRS_NON_HT 18 -#define NUM_CONTROLS_NON_HT (NUM_ESCRS_NON_HT + NUM_CCCRS_NON_HT) - -#define NUM_COUNTERS_HT2 4 -#define NUM_ESCRS_HT2 23 -#define NUM_CCCRS_HT2 9 -#define NUM_CONTROLS_HT2 (NUM_ESCRS_HT2 + NUM_CCCRS_HT2) - -static unsigned int num_counters = NUM_COUNTERS_NON_HT; - - -/* this has to be checked dynamically since the - hyper-threadedness of a chip is discovered at - kernel boot-time. */ -static inline void setup_num_counters(void) -{ - if (boot_cpu_data.x86_num_siblings == 2) /* XXX */ - num_counters = NUM_COUNTERS_HT2; -} - -static int inline addr_increment(void) -{ - return boot_cpu_data.x86_num_siblings == 2 ? 2 : 1; -} - - -/* tables to simulate simplified hardware view of p4 registers */ -struct p4_counter_binding { - int virt_counter; - int counter_address; - int cccr_address; -}; - -struct p4_event_binding { - int escr_select; /* value to put in CCCR */ - int event_select; /* value to put in ESCR */ - struct { - int virt_counter; /* for this counter... */ - int escr_address; /* use this ESCR */ - } bindings[2]; -}; - -/* nb: these CTR_* defines are a duplicate of defines in - event/i386.p4*events. */ - - -#define CTR_BPU_0 (1 << 0) -#define CTR_MS_0 (1 << 1) -#define CTR_FLAME_0 (1 << 2) -#define CTR_IQ_4 (1 << 3) -#define CTR_BPU_2 (1 << 4) -#define CTR_MS_2 (1 << 5) -#define CTR_FLAME_2 (1 << 6) -#define CTR_IQ_5 (1 << 7) - -static struct p4_counter_binding p4_counters [NUM_COUNTERS_NON_HT] = { - { CTR_BPU_0, MSR_P4_BPU_PERFCTR0, MSR_P4_BPU_CCCR0 }, - { CTR_MS_0, MSR_P4_MS_PERFCTR0, MSR_P4_MS_CCCR0 }, - { CTR_FLAME_0, MSR_P4_FLAME_PERFCTR0, MSR_P4_FLAME_CCCR0 }, - { CTR_IQ_4, MSR_P4_IQ_PERFCTR4, MSR_P4_IQ_CCCR4 }, - { CTR_BPU_2, MSR_P4_BPU_PERFCTR2, MSR_P4_BPU_CCCR2 }, - { CTR_MS_2, MSR_P4_MS_PERFCTR2, MSR_P4_MS_CCCR2 }, - { CTR_FLAME_2, MSR_P4_FLAME_PERFCTR2, MSR_P4_FLAME_CCCR2 }, - { CTR_IQ_5, MSR_P4_IQ_PERFCTR5, MSR_P4_IQ_CCCR5 } -}; - -#define NUM_UNUSED_CCCRS NUM_CCCRS_NON_HT - NUM_COUNTERS_NON_HT - -/* All cccr we don't use. */ -static int p4_unused_cccr[NUM_UNUSED_CCCRS] = { - MSR_P4_BPU_CCCR1, MSR_P4_BPU_CCCR3, - MSR_P4_MS_CCCR1, MSR_P4_MS_CCCR3, - MSR_P4_FLAME_CCCR1, MSR_P4_FLAME_CCCR3, - MSR_P4_IQ_CCCR0, MSR_P4_IQ_CCCR1, - MSR_P4_IQ_CCCR2, MSR_P4_IQ_CCCR3 -}; - -/* p4 event codes in libop/op_event.h are indices into this table. */ - -static const struct p4_event_binding p4_events[NUM_EVENTS] = { - - { /* BRANCH_RETIRED */ - 0x05, 0x06, - { {CTR_IQ_4, MSR_P4_CRU_ESCR2}, - {CTR_IQ_5, MSR_P4_CRU_ESCR3} } - }, - - { /* MISPRED_BRANCH_RETIRED */ - 0x04, 0x03, - { { CTR_IQ_4, MSR_P4_CRU_ESCR0}, - { CTR_IQ_5, MSR_P4_CRU_ESCR1} } - }, - - { /* TC_DELIVER_MODE */ - 0x01, 0x01, - { { CTR_MS_0, MSR_P4_TC_ESCR0}, - { CTR_MS_2, MSR_P4_TC_ESCR1} } - }, - - { /* BPU_FETCH_REQUEST */ - 0x00, 0x03, - { { CTR_BPU_0, MSR_P4_BPU_ESCR0}, - { CTR_BPU_2, MSR_P4_BPU_ESCR1} } - }, - - { /* ITLB_REFERENCE */ - 0x03, 0x18, - { { CTR_BPU_0, MSR_P4_ITLB_ESCR0}, - { CTR_BPU_2, MSR_P4_ITLB_ESCR1} } - }, - - { /* MEMORY_CANCEL */ - 0x05, 0x02, - { { CTR_FLAME_0, MSR_P4_DAC_ESCR0}, - { CTR_FLAME_2, MSR_P4_DAC_ESCR1} } - }, - - { /* MEMORY_COMPLETE */ - 0x02, 0x08, - { { CTR_FLAME_0, MSR_P4_SAAT_ESCR0}, - { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} } - }, - - { /* LOAD_PORT_REPLAY */ - 0x02, 0x04, - { { CTR_FLAME_0, MSR_P4_SAAT_ESCR0}, - { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} } - }, - - { /* STORE_PORT_REPLAY */ - 0x02, 0x05, - { { CTR_FLAME_0, MSR_P4_SAAT_ESCR0}, - { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} } - }, - - { /* MOB_LOAD_REPLAY */ - 0x02, 0x03, - { { CTR_BPU_0, MSR_P4_MOB_ESCR0}, - { CTR_BPU_2, MSR_P4_MOB_ESCR1} } - }, - - { /* PAGE_WALK_TYPE */ - 0x04, 0x01, - { { CTR_BPU_0, MSR_P4_PMH_ESCR0}, - { CTR_BPU_2, MSR_P4_PMH_ESCR1} } - }, - - { /* BSQ_CACHE_REFERENCE */ - 0x07, 0x0c, - { { CTR_BPU_0, MSR_P4_BSU_ESCR0}, - { CTR_BPU_2, MSR_P4_BSU_ESCR1} } - }, - - { /* IOQ_ALLOCATION */ - 0x06, 0x03, - { { CTR_BPU_0, MSR_P4_FSB_ESCR0}, - { 0, 0 } } - }, - - { /* IOQ_ACTIVE_ENTRIES */ - 0x06, 0x1a, - { { CTR_BPU_2, MSR_P4_FSB_ESCR1}, - { 0, 0 } } - }, - - { /* FSB_DATA_ACTIVITY */ - 0x06, 0x17, - { { CTR_BPU_0, MSR_P4_FSB_ESCR0}, - { CTR_BPU_2, MSR_P4_FSB_ESCR1} } - }, - - { /* BSQ_ALLOCATION */ - 0x07, 0x05, - { { CTR_BPU_0, MSR_P4_BSU_ESCR0}, - { 0, 0 } } - }, - - { /* BSQ_ACTIVE_ENTRIES */ - 0x07, 0x06, - { { CTR_BPU_2, MSR_P4_BSU_ESCR1 /* guess */}, - { 0, 0 } } - }, - - { /* X87_ASSIST */ - 0x05, 0x03, - { { CTR_IQ_4, MSR_P4_CRU_ESCR2}, - { CTR_IQ_5, MSR_P4_CRU_ESCR3} } - }, - - { /* SSE_INPUT_ASSIST */ - 0x01, 0x34, - { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, - { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } - }, - - { /* PACKED_SP_UOP */ - 0x01, 0x08, - { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, - { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } - }, - - { /* PACKED_DP_UOP */ - 0x01, 0x0c, - { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, - { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } - }, - - { /* SCALAR_SP_UOP */ - 0x01, 0x0a, - { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, - { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } - }, - - { /* SCALAR_DP_UOP */ - 0x01, 0x0e, - { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, - { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } - }, - - { /* 64BIT_MMX_UOP */ - 0x01, 0x02, - { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, - { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } - }, - - { /* 128BIT_MMX_UOP */ - 0x01, 0x1a, - { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, - { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } - }, - - { /* X87_FP_UOP */ - 0x01, 0x04, - { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, - { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } - }, - - { /* X87_SIMD_MOVES_UOP */ - 0x01, 0x2e, - { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, - { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } - }, - - { /* MACHINE_CLEAR */ - 0x05, 0x02, - { { CTR_IQ_4, MSR_P4_CRU_ESCR2}, - { CTR_IQ_5, MSR_P4_CRU_ESCR3} } - }, - - { /* GLOBAL_POWER_EVENTS */ - 0x06, 0x13 /* older manual says 0x05, newer 0x13 */, - { { CTR_BPU_0, MSR_P4_FSB_ESCR0}, - { CTR_BPU_2, MSR_P4_FSB_ESCR1} } - }, - - { /* TC_MS_XFER */ - 0x00, 0x05, - { { CTR_MS_0, MSR_P4_MS_ESCR0}, - { CTR_MS_2, MSR_P4_MS_ESCR1} } - }, - - { /* UOP_QUEUE_WRITES */ - 0x00, 0x09, - { { CTR_MS_0, MSR_P4_MS_ESCR0}, - { CTR_MS_2, MSR_P4_MS_ESCR1} } - }, - - { /* FRONT_END_EVENT */ - 0x05, 0x08, - { { CTR_IQ_4, MSR_P4_CRU_ESCR2}, - { CTR_IQ_5, MSR_P4_CRU_ESCR3} } - }, - - { /* EXECUTION_EVENT */ - 0x05, 0x0c, - { { CTR_IQ_4, MSR_P4_CRU_ESCR2}, - { CTR_IQ_5, MSR_P4_CRU_ESCR3} } - }, - - { /* REPLAY_EVENT */ - 0x05, 0x09, - { { CTR_IQ_4, MSR_P4_CRU_ESCR2}, - { CTR_IQ_5, MSR_P4_CRU_ESCR3} } - }, - - { /* INSTR_RETIRED */ - 0x04, 0x02, - { { CTR_IQ_4, MSR_P4_CRU_ESCR0}, - { CTR_IQ_5, MSR_P4_CRU_ESCR1} } - }, - - { /* UOPS_RETIRED */ - 0x04, 0x01, - { { CTR_IQ_4, MSR_P4_CRU_ESCR0}, - { CTR_IQ_5, MSR_P4_CRU_ESCR1} } - }, - - { /* UOP_TYPE */ - 0x02, 0x02, - { { CTR_IQ_4, MSR_P4_RAT_ESCR0}, - { CTR_IQ_5, MSR_P4_RAT_ESCR1} } - }, - - { /* RETIRED_MISPRED_BRANCH_TYPE */ - 0x02, 0x05, - { { CTR_MS_0, MSR_P4_TBPU_ESCR0}, - { CTR_MS_2, MSR_P4_TBPU_ESCR1} } - }, - - { /* RETIRED_BRANCH_TYPE */ - 0x02, 0x04, - { { CTR_MS_0, MSR_P4_TBPU_ESCR0}, - { CTR_MS_2, MSR_P4_TBPU_ESCR1} } - } -}; - - -#define MISC_PMC_ENABLED_P(x) ((x) & 1ULL << 7) - -#define ESCR_RESERVED_BITS 0x80000003ULL -#define ESCR_CLEAR(escr) ((escr) &= ESCR_RESERVED_BITS) -#define ESCR_SET_USR_0(escr, usr) ((escr) |= (((usr) & 1ULL) << 2)) -#define ESCR_SET_OS_0(escr, os) ((escr) |= (((os) & 1ULL) << 3)) -#define ESCR_SET_USR_1(escr, usr) ((escr) |= (((usr) & 1ULL))) -#define ESCR_SET_OS_1(escr, os) ((escr) |= (((os) & 1ULL) << 1)) -#define ESCR_SET_EVENT_SELECT(escr, sel) ((escr) |= (((sel) & 0x3fULL) << 25)) -#define ESCR_SET_EVENT_MASK(escr, mask) ((escr) |= (((mask) & 0xffffULL) << 9)) -#define ESCR_READ(escr,ev,i) do {rdmsrl(ev->bindings[(i)].escr_address, (escr));} while (0) -#define ESCR_WRITE(escr,ev,i) do {wrmsrl(ev->bindings[(i)].escr_address, (escr));} while (0) - -#define CCCR_RESERVED_BITS 0x38030FFFULL -#define CCCR_CLEAR(cccr) ((cccr) &= CCCR_RESERVED_BITS) -#define CCCR_SET_REQUIRED_BITS(cccr) ((cccr) |= 0x00030000ULL) -#define CCCR_SET_ESCR_SELECT(cccr, sel) ((cccr) |= (((sel) & 0x07ULL) << 13)) -#define CCCR_SET_PMI_OVF_0(cccr) ((cccr) |= (1ULL<<26)) -#define CCCR_SET_PMI_OVF_1(cccr) ((cccr) |= (1ULL<<27)) -#define CCCR_SET_ENABLE(cccr) ((cccr) |= (1ULL<<12)) -#define CCCR_SET_DISABLE(cccr) ((cccr) &= ~(1ULL<<12)) -#define CCCR_READ(msr_content, i) do {rdmsrl(p4_counters[(i)].cccr_address, (msr_content));} while (0) -#define CCCR_WRITE(msr_content, i) do {wrmsrl(p4_counters[(i)].cccr_address, (msr_content));} while (0) -#define CCCR_OVF_P(cccr) ((cccr) & (1ULL<<31)) -#define CCCR_CLEAR_OVF(cccr) ((cccr) &= (~(1ULL<<31))) - -#define CTR_READ(msr_content,i) do {rdmsrl(p4_counters[(i)].counter_address, (msr_content));} while (0) -#define CTR_WRITE(msr_content,i) do {wrmsrl(p4_counters[(i)].counter_address, -(msr_content));} while (0) -#define CTR_OVERFLOW_P(ctr) (!((ctr) & 0x80000000ULL)) - - -/* this assigns a "stagger" to the current CPU, which is used throughout - the code in this module as an extra array offset, to select the "even" - or "odd" part of all the divided resources. */ -static unsigned int get_stagger(void) -{ - int cpu = smp_processor_id(); - return (cpu != cpumask_first(per_cpu(cpu_sibling_mask, cpu))); -} - - -/* finally, mediate access to a real hardware counter - by passing a "virtual" counter numer to this macro, - along with your stagger setting. */ -#define VIRT_CTR(stagger, i) ((i) + ((num_counters) * (stagger))) - -static unsigned long reset_value[NUM_COUNTERS_NON_HT]; - - -static void cf_check p4_fill_in_addresses(struct op_msrs * const msrs) -{ - unsigned int i; - unsigned int addr, stag; - - setup_num_counters(); - stag = get_stagger(); - - /* the counter registers we pay attention to */ - for (i = 0; i < num_counters; ++i) { - msrs->counters[i].addr = - p4_counters[VIRT_CTR(stag, i)].counter_address; - } - - /* FIXME: bad feeling, we don't save the 10 counters we don't use. */ - - /* 18 CCCR registers */ - for (i = 0, addr = MSR_P4_BPU_CCCR0 + stag; - addr <= MSR_P4_IQ_CCCR5; ++i, addr += addr_increment()) { - msrs->controls[i].addr = addr; - } - - /* 43 ESCR registers in three or four discontiguous group */ - for (addr = MSR_P4_BSU_ESCR0 + stag; - addr < MSR_P4_IQ_ESCR0; ++i, addr += addr_increment()) { - msrs->controls[i].addr = addr; - } - - /* no IQ_ESCR0/1 on some models, we save a seconde time BSU_ESCR0/1 - * to avoid special case in nmi_{save|restore}_registers() */ - if (boot_cpu_data.x86_model >= 0x3) { - for (addr = MSR_P4_BSU_ESCR0 + stag; - addr <= MSR_P4_BSU_ESCR1; ++i, addr += addr_increment()) { - msrs->controls[i].addr = addr; - } - } else { - for (addr = MSR_P4_IQ_ESCR0 + stag; - addr <= MSR_P4_IQ_ESCR1; ++i, addr += addr_increment()) { - msrs->controls[i].addr = addr; - } - } - - for (addr = MSR_P4_RAT_ESCR0 + stag; - addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) { - msrs->controls[i].addr = addr; - } - - for (addr = MSR_P4_MS_ESCR0 + stag; - addr <= MSR_P4_TC_ESCR1; ++i, addr += addr_increment()) { - msrs->controls[i].addr = addr; - } - - for (addr = MSR_P4_IX_ESCR0 + stag; - addr <= MSR_P4_CRU_ESCR3; ++i, addr += addr_increment()) { - msrs->controls[i].addr = addr; - } - - /* there are 2 remaining non-contiguously located ESCRs */ - - if (num_counters == NUM_COUNTERS_NON_HT) { - /* standard non-HT CPUs handle both remaining ESCRs*/ - msrs->controls[i++].addr = MSR_P4_CRU_ESCR5; - msrs->controls[i++].addr = MSR_P4_CRU_ESCR4; - - } else if (stag == 0) { - /* HT CPUs give the first remainder to the even thread, as - the 32nd control register */ - msrs->controls[i++].addr = MSR_P4_CRU_ESCR4; - - } else { - /* and two copies of the second to the odd thread, - for the 22st and 23nd control registers */ - msrs->controls[i++].addr = MSR_P4_CRU_ESCR5; - msrs->controls[i++].addr = MSR_P4_CRU_ESCR5; - } -} - - -static void pmc_setup_one_p4_counter(unsigned int ctr) -{ - int i; - int const maxbind = 2; - uint64_t cccr = 0; - uint64_t escr = 0; - unsigned int counter_bit; - const struct p4_event_binding *ev = NULL; - unsigned int stag; - - stag = get_stagger(); - - /* convert from counter *number* to counter *bit* */ - counter_bit = 1 << VIRT_CTR(stag, ctr); - - /* find our event binding structure. */ - if (counter_config[ctr].event <= 0 || counter_config[ctr].event > NUM_EVENTS) { - printk(KERN_ERR "oprofile: P4 event code %#lx out of range\n", - counter_config[ctr].event); - return; - } - - ev = &(p4_events[counter_config[ctr].event - 1]); - - for (i = 0; i < maxbind; i++) { - if (ev->bindings[i].virt_counter & counter_bit) { - - /* modify ESCR */ - ESCR_READ(escr, ev, i); - ESCR_CLEAR(escr); - if (stag == 0) { - ESCR_SET_USR_0(escr, counter_config[ctr].user); - ESCR_SET_OS_0(escr, counter_config[ctr].kernel); - } else { - ESCR_SET_USR_1(escr, counter_config[ctr].user); - ESCR_SET_OS_1(escr, counter_config[ctr].kernel); - } - ESCR_SET_EVENT_SELECT(escr, ev->event_select); - ESCR_SET_EVENT_MASK(escr, counter_config[ctr].unit_mask); - ESCR_WRITE(escr, ev, i); - - /* modify CCCR */ - CCCR_READ(cccr, VIRT_CTR(stag, ctr)); - CCCR_CLEAR(cccr); - CCCR_SET_REQUIRED_BITS(cccr); - CCCR_SET_ESCR_SELECT(cccr, ev->escr_select); - if (stag == 0) { - CCCR_SET_PMI_OVF_0(cccr); - } else { - CCCR_SET_PMI_OVF_1(cccr); - } - CCCR_WRITE(cccr, VIRT_CTR(stag, ctr)); - return; - } - } - - printk(KERN_ERR - "oprofile: P4 event code %#lx no binding, stag %d ctr %d\n", - counter_config[ctr].event, stag, ctr); -} - - -static void cf_check p4_setup_ctrs(struct op_msrs const * const msrs) -{ - unsigned int i; - uint64_t msr_content; - unsigned int addr; - unsigned int stag; - - stag = get_stagger(); - - rdmsrl(MSR_IA32_MISC_ENABLE, msr_content); - if (! MISC_PMC_ENABLED_P(msr_content)) { - printk(KERN_ERR "oprofile: P4 PMC not available\n"); - return; - } - - /* clear the cccrs we will use */ - for (i = 0 ; i < num_counters ; i++) { - rdmsrl(p4_counters[VIRT_CTR(stag, i)].cccr_address, msr_content); - CCCR_CLEAR(msr_content); - CCCR_SET_REQUIRED_BITS(msr_content); - wrmsrl(p4_counters[VIRT_CTR(stag, i)].cccr_address, msr_content); - } - - /* clear cccrs outside our concern */ - for (i = stag ; i < NUM_UNUSED_CCCRS ; i += addr_increment()) { - rdmsrl(p4_unused_cccr[i], msr_content); - CCCR_CLEAR(msr_content); - CCCR_SET_REQUIRED_BITS(msr_content); - wrmsrl(p4_unused_cccr[i], msr_content); - } - - /* clear all escrs (including those outside our concern) */ - for (addr = MSR_P4_BSU_ESCR0 + stag; - addr < MSR_P4_IQ_ESCR0; addr += addr_increment()) { - wrmsrl(addr, 0x0ULL); - } - - /* On older models clear also MSR_P4_IQ_ESCR0/1 */ - if (boot_cpu_data.x86_model < 0x3) { - wrmsrl(MSR_P4_IQ_ESCR0, 0x0ULL); - wrmsrl(MSR_P4_IQ_ESCR1, 0x0ULL); - } - - for (addr = MSR_P4_RAT_ESCR0 + stag; - addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) { - wrmsrl(addr, 0x0ULL); - } - - for (addr = MSR_P4_MS_ESCR0 + stag; - addr <= MSR_P4_TC_ESCR1; addr += addr_increment()){ - wrmsrl(addr, 0x0ULL); - } - - for (addr = MSR_P4_IX_ESCR0 + stag; - addr <= MSR_P4_CRU_ESCR3; addr += addr_increment()){ - wrmsrl(addr, 0x0ULL); - } - - if (num_counters == NUM_COUNTERS_NON_HT) { - wrmsrl(MSR_P4_CRU_ESCR4, 0x0ULL); - wrmsrl(MSR_P4_CRU_ESCR5, 0x0ULL); - } else if (stag == 0) { - wrmsrl(MSR_P4_CRU_ESCR4, 0x0ULL); - } else { - wrmsrl(MSR_P4_CRU_ESCR5, 0x0ULL); - } - - /* setup all counters */ - for (i = 0 ; i < num_counters ; ++i) { - if (counter_config[i].enabled) { - reset_value[i] = counter_config[i].count; - pmc_setup_one_p4_counter(i); - CTR_WRITE(counter_config[i].count, VIRT_CTR(stag, i)); - } else { - reset_value[i] = 0; - } - } -} - -static int cf_check p4_check_ctrs( - unsigned int const cpu, struct op_msrs const * const msrs, - struct cpu_user_regs const * const regs) -{ - unsigned long ctr, stag, real; - uint64_t msr_content; - int i; - int ovf = 0; - unsigned long eip = regs->rip; - int mode = xenoprofile_get_mode(current, regs); - - stag = get_stagger(); - - for (i = 0; i < num_counters; ++i) { - - if (!reset_value[i]) - continue; - - /* - * there is some eccentricity in the hardware which - * requires that we perform 2 extra corrections: - * - * - check both the CCCR:OVF flag for overflow and the - * counter high bit for un-flagged overflows. - * - * - write the counter back twice to ensure it gets - * updated properly. - * - * the former seems to be related to extra NMIs happening - * during the current NMI; the latter is reported as errata - * N15 in intel doc 249199-029, pentium 4 specification - * update, though their suggested work-around does not - * appear to solve the problem. - */ - - real = VIRT_CTR(stag, i); - - CCCR_READ(msr_content, real); - CTR_READ(ctr, real); - if (CCCR_OVF_P(msr_content) || CTR_OVERFLOW_P(ctr)) { - xenoprof_log_event(current, regs, eip, mode, i); - CTR_WRITE(reset_value[i], real); - CCCR_CLEAR_OVF(msr_content); - CCCR_WRITE(msr_content, real); - CTR_WRITE(reset_value[i], real); - ovf = 1; - } - } - - /* P4 quirk: you have to re-unmask the apic vector */ - apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); - - return ovf; -} - - -static void cf_check p4_start(struct op_msrs const * const msrs) -{ - unsigned int stag; - uint64_t msr_content; - int i; - - stag = get_stagger(); - - for (i = 0; i < num_counters; ++i) { - if (!reset_value[i]) - continue; - CCCR_READ(msr_content, VIRT_CTR(stag, i)); - CCCR_SET_ENABLE(msr_content); - CCCR_WRITE(msr_content, VIRT_CTR(stag, i)); - } -} - - -static void cf_check p4_stop(struct op_msrs const * const msrs) -{ - unsigned int stag; - uint64_t msr_content; - int i; - - stag = get_stagger(); - - for (i = 0; i < num_counters; ++i) { - CCCR_READ(msr_content, VIRT_CTR(stag, i)); - CCCR_SET_DISABLE(msr_content); - CCCR_WRITE(msr_content, VIRT_CTR(stag, i)); - } -} - - -struct op_x86_model_spec const op_p4_ht2_spec = { - .num_counters = NUM_COUNTERS_HT2, - .num_controls = NUM_CONTROLS_HT2, - .fill_in_addresses = &p4_fill_in_addresses, - .setup_ctrs = &p4_setup_ctrs, - .check_ctrs = &p4_check_ctrs, - .start = &p4_start, - .stop = &p4_stop -}; - - -struct op_x86_model_spec const op_p4_spec = { - .num_counters = NUM_COUNTERS_NON_HT, - .num_controls = NUM_CONTROLS_NON_HT, - .fill_in_addresses = &p4_fill_in_addresses, - .setup_ctrs = &p4_setup_ctrs, - .check_ctrs = &p4_check_ctrs, - .start = &p4_start, - .stop = &p4_stop -}; diff --git a/xen/arch/x86/oprofile/op_model_ppro.c b/xen/arch/x86/oprofile/op_model_ppro.c deleted file mode 100644 index 4bbb4502c7..0000000000 --- a/xen/arch/x86/oprofile/op_model_ppro.c +++ /dev/null @@ -1,348 +0,0 @@ -/** - * @file op_model_ppro.h - * pentium pro / P6 model-specific MSR operations - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author John Levon - * @author Philippe Elie - * @author Graydon Hoare - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "op_x86_model.h" -#include "op_counter.h" - -struct arch_msr_pair { - u64 counter; - u64 control; -}; - -/* - * Intel "Architectural Performance Monitoring" CPUID - * detection/enumeration details: - */ -union cpuid10_eax { - struct { - unsigned int version_id:8; - unsigned int num_counters:8; - unsigned int bit_width:8; - unsigned int mask_length:8; - } split; - unsigned int full; -}; - -static int num_counters = 2; -static int counter_width = 32; - -#define CTR_OVERFLOWED(n) (!((n) & (1ULL<<(counter_width-1)))) - -#define CTRL_READ(msr_content,msrs,c) do {rdmsrl((msrs->controls[(c)].addr), (msr_content));} while (0) -#define CTRL_WRITE(msr_content,msrs,c) do {wrmsrl((msrs->controls[(c)].addr), (msr_content));} while (0) -#define CTRL_SET_ACTIVE(n) (n |= (1ULL<<22)) -#define CTRL_SET_INACTIVE(n) (n &= ~(1ULL<<22)) -#define CTRL_CLEAR(x) (x &= (1ULL<<21)) -#define CTRL_SET_ENABLE(val) (val |= 1ULL<<20) -#define CTRL_SET_USR(val,u) (val |= ((u & 1ULL) << 16)) -#define CTRL_SET_KERN(val,k) (val |= ((k & 1ULL) << 17)) -#define CTRL_SET_UM(val, m) (val |= (m << 8)) -#define CTRL_SET_EVENT(val, e) (val |= e) -#define IS_ACTIVE(val) (val & (1ULL << 22) ) -#define IS_ENABLE(val) (val & (1ULL << 20) ) -static unsigned long reset_value[OP_MAX_COUNTER]; -int ppro_has_global_ctrl = 0; - -static void cf_check ppro_fill_in_addresses(struct op_msrs * const msrs) -{ - int i; - - for (i = 0; i < num_counters; i++) - msrs->counters[i].addr = MSR_P6_PERFCTR(i); - for (i = 0; i < num_counters; i++) - msrs->controls[i].addr = MSR_P6_EVNTSEL(i); -} - - -static void cf_check ppro_setup_ctrs(struct op_msrs const * const msrs) -{ - uint64_t msr_content; - int i; - - if (cpu_has_arch_perfmon) { - union cpuid10_eax eax; - eax.full = cpuid_eax(0xa); - - /* - * For Core2 (family 6, model 15), don't reset the - * counter width: - */ - if (!(eax.split.version_id == 0 && - current_cpu_data.x86 == 6 && - current_cpu_data.x86_model == 15)) { - - if (counter_width < eax.split.bit_width) - counter_width = eax.split.bit_width; - } - } - - /* clear all counters */ - for (i = 0 ; i < num_counters; ++i) { - CTRL_READ(msr_content, msrs, i); - CTRL_CLEAR(msr_content); - CTRL_WRITE(msr_content, msrs, i); - } - - /* avoid a false detection of ctr overflows in NMI handler */ - for (i = 0; i < num_counters; ++i) - wrmsrl(msrs->counters[i].addr, ~0x0ULL); - - /* enable active counters */ - for (i = 0; i < num_counters; ++i) { - if (counter_config[i].enabled) { - reset_value[i] = counter_config[i].count; - - wrmsrl(msrs->counters[i].addr, -reset_value[i]); - - CTRL_READ(msr_content, msrs, i); - CTRL_CLEAR(msr_content); - CTRL_SET_ENABLE(msr_content); - CTRL_SET_USR(msr_content, counter_config[i].user); - CTRL_SET_KERN(msr_content, counter_config[i].kernel); - CTRL_SET_UM(msr_content, counter_config[i].unit_mask); - CTRL_SET_EVENT(msr_content, counter_config[i].event); - CTRL_WRITE(msr_content, msrs, i); - } else { - reset_value[i] = 0; - } - } -} - -static int cf_check ppro_check_ctrs( - unsigned int const cpu, struct op_msrs const * const msrs, - struct cpu_user_regs const * const regs) -{ - u64 val; - int i; - int ovf = 0; - unsigned long eip = regs->rip; - int mode = xenoprofile_get_mode(current, regs); - struct arch_msr_pair *msrs_content = vcpu_vpmu(current)->context; - - for (i = 0 ; i < num_counters; ++i) { - if (!reset_value[i]) - continue; - rdmsrl(msrs->counters[i].addr, val); - if (CTR_OVERFLOWED(val)) { - xenoprof_log_event(current, regs, eip, mode, i); - wrmsrl(msrs->counters[i].addr, -reset_value[i]); - if ( is_passive(current->domain) && (mode != 2) && - vpmu_is_set(vcpu_vpmu(current), - VPMU_PASSIVE_DOMAIN_ALLOCATED) ) - { - if ( IS_ACTIVE(msrs_content[i].control) ) - { - msrs_content[i].counter = val; - if ( IS_ENABLE(msrs_content[i].control) ) - ovf = 2; - } - } - if ( !ovf ) - ovf = 1; - } - } - - /* Only P6 based Pentium M need to re-unmask the apic vector but it - * doesn't hurt other P6 variant */ - apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); - - return ovf; -} - - -static void cf_check ppro_start(struct op_msrs const * const msrs) -{ - uint64_t msr_content; - int i; - - for (i = 0; i < num_counters; ++i) { - if (reset_value[i]) { - CTRL_READ(msr_content, msrs, i); - CTRL_SET_ACTIVE(msr_content); - CTRL_WRITE(msr_content, msrs, i); - } - } - /* Global Control MSR is enabled by default when system power on. - * However, this may not hold true when xenoprof starts to run. - */ - if ( ppro_has_global_ctrl ) - wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, (1ULL<= MSR_IA32_PERFCTR0) && - (msr_index < (MSR_IA32_PERFCTR0 + num_counters)) ) - { - *type = MSR_TYPE_ARCH_COUNTER; - *index = msr_index - MSR_IA32_PERFCTR0; - return 1; - } - if ( (msr_index >= MSR_P6_EVNTSEL(0)) && - (msr_index < (MSR_P6_EVNTSEL(num_counters))) ) - { - *type = MSR_TYPE_ARCH_CTRL; - *index = msr_index - MSR_P6_EVNTSEL(0); - return 1; - } - - return 0; -} - -static int cf_check ppro_allocate_msr(struct vcpu *v) -{ - struct vpmu_struct *vpmu = vcpu_vpmu(v); - struct arch_msr_pair *msr_content; - - msr_content = xvzalloc_array(struct arch_msr_pair, num_counters); - if ( !msr_content ) - goto out; - vpmu->context = (void *)msr_content; - vpmu_clear(vpmu); - vpmu_set(vpmu, VPMU_PASSIVE_DOMAIN_ALLOCATED); - return 1; -out: - printk(XENLOG_G_WARNING "Insufficient memory for oprofile," - " oprofile is unavailable on dom%d vcpu%d\n", - v->vcpu_id, v->domain->domain_id); - return 0; -} - -static void cf_check ppro_free_msr(struct vcpu *v) -{ - struct vpmu_struct *vpmu = vcpu_vpmu(v); - - if ( !vpmu_is_set(vpmu, VPMU_PASSIVE_DOMAIN_ALLOCATED) ) - return; - XVFREE(vpmu->context); - vpmu_reset(vpmu, VPMU_PASSIVE_DOMAIN_ALLOCATED); -} - -static void cf_check ppro_load_msr( - struct vcpu *v, int type, int index, u64 *msr_content) -{ - struct arch_msr_pair *msrs = vcpu_vpmu(v)->context; - switch ( type ) - { - case MSR_TYPE_ARCH_COUNTER: - *msr_content = msrs[index].counter; - break; - case MSR_TYPE_ARCH_CTRL: - *msr_content = msrs[index].control; - break; - } -} - -static void cf_check ppro_save_msr( - struct vcpu *v, int type, int index, u64 msr_content) -{ - struct arch_msr_pair *msrs = vcpu_vpmu(v)->context; - - switch ( type ) - { - case MSR_TYPE_ARCH_COUNTER: - msrs[index].counter = msr_content; - break; - case MSR_TYPE_ARCH_CTRL: - msrs[index].control = msr_content; - break; - } -} - -/* - * Architectural performance monitoring. - * - * Newer Intel CPUs (Core1+) have support for architectural - * events described in CPUID 0xA. See the IA32 SDM Vol3b.18 for details. - * The advantage of this is that it can be done without knowing about - * the specific CPU. - */ -void arch_perfmon_setup_counters(void) -{ - union cpuid10_eax eax; - - eax.full = cpuid_eax(0xa); - - /* Workaround for BIOS bugs in 6/15. Taken from perfmon2 */ - if (eax.split.version_id == 0 && current_cpu_data.x86 == 6 && - current_cpu_data.x86_model == 15) { - eax.split.version_id = 2; - eax.split.num_counters = 2; - eax.split.bit_width = 40; - } - - num_counters = min_t(u8, eax.split.num_counters, OP_MAX_COUNTER); - - op_arch_perfmon_spec.num_counters = num_counters; - op_arch_perfmon_spec.num_controls = num_counters; - op_ppro_spec.num_counters = num_counters; - op_ppro_spec.num_controls = num_counters; -} - -struct op_x86_model_spec __read_mostly op_ppro_spec = { - .num_counters = 2, - .num_controls = 2, - .fill_in_addresses = &ppro_fill_in_addresses, - .setup_ctrs = &ppro_setup_ctrs, - .check_ctrs = &ppro_check_ctrs, - .start = &ppro_start, - .stop = &ppro_stop, - .is_arch_pmu_msr = &ppro_is_arch_pmu_msr, - .allocated_msr = &ppro_allocate_msr, - .free_msr = &ppro_free_msr, - .load_msr = &ppro_load_msr, - .save_msr = &ppro_save_msr -}; - -struct op_x86_model_spec __read_mostly op_arch_perfmon_spec = { - /* num_counters/num_controls filled in at runtime */ - .fill_in_addresses = &ppro_fill_in_addresses, - .setup_ctrs = &ppro_setup_ctrs, - .check_ctrs = &ppro_check_ctrs, - .start = &ppro_start, - .stop = &ppro_stop, - .is_arch_pmu_msr = &ppro_is_arch_pmu_msr, - .allocated_msr = &ppro_allocate_msr, - .free_msr = &ppro_free_msr, - .load_msr = &ppro_load_msr, - .save_msr = &ppro_save_msr -}; diff --git a/xen/arch/x86/oprofile/op_x86_model.h b/xen/arch/x86/oprofile/op_x86_model.h deleted file mode 100644 index 35bc3c1e22..0000000000 --- a/xen/arch/x86/oprofile/op_x86_model.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @file op_x86_model.h - * interface to x86 model-specific MSR operations - * - * @remark Copyright 2002 OProfile authors - * @remark Read the file COPYING - * - * @author Graydon Hoare - */ - -#ifndef OP_X86_MODEL_H -#define OP_X86_MODEL_H - -struct op_msr { - unsigned long addr; - uint64_t value; -}; - -struct op_msrs { - struct op_msr * counters; - struct op_msr * controls; -}; - -struct pt_regs; - -/* The model vtable abstracts the differences between - * various x86 CPU model's perfctr support. - */ -struct op_x86_model_spec { - unsigned int num_counters; - unsigned int num_controls; - void (*fill_in_addresses)(struct op_msrs * const msrs); - void (*setup_ctrs)(struct op_msrs const * const msrs); - int (*check_ctrs)(unsigned int const cpu, - struct op_msrs const * const msrs, - struct cpu_user_regs const * const regs); - void (*start)(struct op_msrs const * const msrs); - void (*stop)(struct op_msrs const * const msrs); - int (*is_arch_pmu_msr)(u64 msr_index, int *type, int *index); - int (*allocated_msr)(struct vcpu *v); - void (*free_msr)(struct vcpu *v); - void (*load_msr)(struct vcpu * const v, int type, int index, u64 *msr_content); - void (*save_msr)(struct vcpu * const v, int type, int index, u64 msr_content); -}; - -extern struct op_x86_model_spec op_ppro_spec; -extern struct op_x86_model_spec op_arch_perfmon_spec; -extern struct op_x86_model_spec const op_p4_spec; -extern struct op_x86_model_spec const op_p4_ht2_spec; -extern struct op_x86_model_spec const op_athlon_spec; -extern struct op_x86_model_spec const op_amd_fam15h_spec; - -void arch_perfmon_setup_counters(void); - -extern int ppro_has_global_ctrl; -extern struct op_x86_model_spec const *model; - -#endif /* OP_X86_MODEL_H */ diff --git a/xen/arch/x86/oprofile/xenoprof.c b/xen/arch/x86/oprofile/xenoprof.c deleted file mode 100644 index 7f2525bfb4..0000000000 --- a/xen/arch/x86/oprofile/xenoprof.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2005 Hewlett-Packard Co. - * written by Aravind Menon & Jose Renato Santos - * (email: xenoprof@groups.hp.com) - * - * Copyright (c) 2006 Isaku Yamahata - * VA Linux Systems Japan K.K. - * x86 specific part - */ - -#include -#include -#include -#include - -#include "op_counter.h" - -int xenoprof_arch_counter(XEN_GUEST_HANDLE_PARAM(void) arg) -{ - struct xenoprof_counter counter; - - if ( copy_from_guest(&counter, arg, 1) ) - return -EFAULT; - - if ( counter.ind >= OP_MAX_COUNTER ) - return -E2BIG; - - counter_config[counter.ind].count = counter.count; - counter_config[counter.ind].enabled = counter.enabled; - counter_config[counter.ind].event = counter.event; - counter_config[counter.ind].kernel = counter.kernel; - counter_config[counter.ind].user = counter.user; - counter_config[counter.ind].unit_mask = counter.unit_mask; - - return 0; -} - -int xenoprof_arch_ibs_counter(XEN_GUEST_HANDLE_PARAM(void) arg) -{ - struct xenoprof_ibs_counter ibs_counter; - - if ( copy_from_guest(&ibs_counter, arg, 1) ) - return -EFAULT; - - ibs_config.op_enabled = ibs_counter.op_enabled; - ibs_config.fetch_enabled = ibs_counter.fetch_enabled; - ibs_config.max_cnt_fetch = ibs_counter.max_cnt_fetch; - ibs_config.max_cnt_op = ibs_counter.max_cnt_op; - ibs_config.rand_en = ibs_counter.rand_en; - ibs_config.dispatched_ops = ibs_counter.dispatched_ops; - - return 0; -} - -#ifdef CONFIG_COMPAT -#include - -int compat_oprof_arch_counter(XEN_GUEST_HANDLE_PARAM(void) arg) -{ - struct compat_oprof_counter counter; - - if ( copy_from_guest(&counter, arg, 1) ) - return -EFAULT; - - if ( counter.ind >= OP_MAX_COUNTER ) - return -E2BIG; - - counter_config[counter.ind].count = counter.count; - counter_config[counter.ind].enabled = counter.enabled; - counter_config[counter.ind].event = counter.event; - counter_config[counter.ind].kernel = counter.kernel; - counter_config[counter.ind].user = counter.user; - counter_config[counter.ind].unit_mask = counter.unit_mask; - - return 0; -} -#endif - -int xenoprofile_get_mode(struct vcpu *curr, const struct cpu_user_regs *regs) -{ - if ( !guest_mode(regs) ) - return 2; - - if ( !is_hvm_vcpu(curr) ) - return guest_kernel_mode(curr, regs); - - switch ( hvm_guest_x86_mode(curr) ) - { - case X86_MODE_REAL: - return 1; - case X86_MODE_VM86: - return 0; - default: /* 16BIT | 32BIT | 64BIT */ - return hvm_get_cpl(curr) != 3; - } -} - -/* - * Local variables: - * mode: C - * c-file-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 6ba7ae5202..f621b99a5f 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -50,7 +50,6 @@ #include #include #include -#include /* * opt_nmi: one of 'ignore', 'dom0', or 'fatal'. @@ -1943,9 +1942,6 @@ bool nmi_check_continuation(void) if ( pci_serr_nmicont() ) ret = true; - if ( nmi_oprofile_send_virq() ) - ret = true; - return ret; } diff --git a/xen/common/Kconfig b/xen/common/Kconfig index 401d5046f6..38320b248a 100644 --- a/xen/common/Kconfig +++ b/xen/common/Kconfig @@ -374,17 +374,6 @@ config EFI_SET_VIRTUAL_ADDRESS_MAP If unsure, say N. -config XENOPROF - bool "Xen Oprofile Support" if EXPERT - depends on X86 - help - Xen OProfile (Xenoprof) is a system-wide profiler for Xen virtual - machine environments, capable of profiling the Xen virtual machine - monitor, multiple Linux guest operating systems, and applications - running on them. - - If unsure, say Y. - config XSM bool "Xen Security Modules support" default ARM diff --git a/xen/common/Makefile b/xen/common/Makefile index 8486c0b510..92c97d641e 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -63,7 +63,6 @@ obj-$(CONFIG_HAS_VMAP) += vmap.o obj-y += vsprintf.o obj-y += wait.o obj-bin-y += warning.init.o -obj-$(CONFIG_XENOPROF) += xenoprof.o obj-y += xmalloc_tlsf.o obj-bin-$(CONFIG_X86) += $(foreach n,decompress bunzip2 unxz unlzma lzo unlzo unlz4 unzstd earlycpio,$(n).init.o) diff --git a/xen/common/compat/xenoprof.c b/xen/common/compat/xenoprof.c deleted file mode 100644 index 8fbd86c24c..0000000000 --- a/xen/common/compat/xenoprof.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * compat/xenoprof.c - */ - -#include - -#define COMPAT -#define ret_t int - -#define do_xenoprof_op compat_xenoprof_op - -#define xen_oprof_init xenoprof_init -CHECK_oprof_init; -#undef xen_oprof_init - -#define xenoprof_get_buffer compat_oprof_get_buffer -#define xenoprof_op_get_buffer compat_oprof_op_get_buffer -#define xenoprof_arch_counter compat_oprof_arch_counter - -#define xen_domid_t domid_t -#define compat_domid_t domid_compat_t -CHECK_TYPE(domid); -#undef compat_domid_t -#undef xen_domid_t - -#define xen_oprof_passive xenoprof_passive -CHECK_oprof_passive; -#undef xen_oprof_passive - -#define xenoprof_counter compat_oprof_counter - -#include "../xenoprof.c" - -/* - * Local variables: - * mode: C - * c-file-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/common/domain.c b/xen/common/domain.c index ed4b6175de..376351b528 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -1472,11 +1471,6 @@ static void cf_check complete_domain_destroy(struct rcu_head *head) sched_destroy_domain(d); - /* Free page used by xen oprofile buffer. */ -#ifdef CONFIG_XENOPROF - free_xenoprof_pages(d); -#endif - #ifdef CONFIG_MEM_PAGING xfree(d->vm_event_paging); #endif diff --git a/xen/common/xenoprof.c b/xen/common/xenoprof.c deleted file mode 100644 index 1926a92fe4..0000000000 --- a/xen/common/xenoprof.c +++ /dev/null @@ -1,977 +0,0 @@ -/* - * Copyright (C) 2005 Hewlett-Packard Co. - * written by Aravind Menon & Jose Renato Santos - * (email: xenoprof@groups.hp.com) - * - * arch generic xenoprof and IA64 support. - * dynamic map/unmap xenoprof buffer support. - * Copyright (c) 2006 Isaku Yamahata - * VA Linux Systems Japan K.K. - */ - -#ifndef COMPAT -#include -#include -#include -#include -#include -#include -#include -#include - -/* Override macros from asm/page.h to make them work with mfn_t */ -#undef virt_to_mfn -#define virt_to_mfn(va) _mfn(__virt_to_mfn(va)) - -#define XENOPROF_DOMAIN_IGNORED 0 -#define XENOPROF_DOMAIN_ACTIVE 1 -#define XENOPROF_DOMAIN_PASSIVE 2 - -#define XENOPROF_IDLE 0 -#define XENOPROF_INITIALIZED 1 -#define XENOPROF_COUNTERS_RESERVED 2 -#define XENOPROF_READY 3 -#define XENOPROF_PROFILING 4 - -#ifndef CONFIG_COMPAT -#define XENOPROF_COMPAT(x) false -typedef struct xenoprof_buf xenoprof_buf_t; -#define xenoprof_buf(d, b, field) ACCESS_ONCE((b)->field) -#else -#include -#define XENOPROF_COMPAT(x) ((x)->is_compat) -typedef union { - struct xenoprof_buf native; - struct compat_oprof_buf compat; -} xenoprof_buf_t; -#define xenoprof_buf(d, b, field) ACCESS_ONCE(*(!(d)->xenoprof->is_compat \ - ? &(b)->native.field \ - : &(b)->compat.field)) -#endif - -/* Limit amount of pages used for shared buffer (per domain) */ -#define MAX_OPROF_SHARED_PAGES 32 - -/* Lock protecting the following global state */ -static DEFINE_SPINLOCK(xenoprof_lock); - -static DEFINE_SPINLOCK(pmu_owner_lock); -int pmu_owner = 0; -int pmu_hvm_refcount = 0; - -struct xenoprof_vcpu { - int event_size; - xenoprof_buf_t *buffer; -}; - -struct xenoprof { - char *rawbuf; - int npages; - int nbuf; - int bufsize; - int domain_type; -#ifdef CONFIG_COMPAT - bool is_compat; -#endif - struct xenoprof_vcpu *vcpu; -}; - -static struct domain *active_domains[MAX_OPROF_DOMAINS]; -static int active_ready[MAX_OPROF_DOMAINS]; -static unsigned int adomains; - -static struct domain *passive_domains[MAX_OPROF_DOMAINS]; -static unsigned int pdomains; - -static unsigned int activated; -static struct domain *xenoprof_primary_profiler; -static int xenoprof_state = XENOPROF_IDLE; -static unsigned long backtrace_depth; - -static u64 total_samples; -static u64 invalid_buffer_samples; -static u64 corrupted_buffer_samples; -static u64 lost_samples; -static u64 active_samples; -static u64 passive_samples; -static u64 idle_samples; -static u64 others_samples; - -int acquire_pmu_ownership(int pmu_ownership) -{ - spin_lock(&pmu_owner_lock); - if ( pmu_owner == PMU_OWNER_NONE ) - { - pmu_owner = pmu_ownership; - goto out; - } - - if ( pmu_owner == pmu_ownership ) - goto out; - - spin_unlock(&pmu_owner_lock); - return 0; - out: - if ( pmu_owner == PMU_OWNER_HVM ) - pmu_hvm_refcount++; - spin_unlock(&pmu_owner_lock); - return 1; -} - -void release_pmu_ownership(int pmu_ownership) -{ - spin_lock(&pmu_owner_lock); - if ( pmu_ownership == PMU_OWNER_HVM ) - pmu_hvm_refcount--; - if ( !pmu_hvm_refcount ) - pmu_owner = PMU_OWNER_NONE; - spin_unlock(&pmu_owner_lock); -} - -int is_active(struct domain *d) -{ - struct xenoprof *x = d->xenoprof; - return ((x != NULL) && (x->domain_type == XENOPROF_DOMAIN_ACTIVE)); -} - -int is_passive(struct domain *d) -{ - struct xenoprof *x = d->xenoprof; - return ((x != NULL) && (x->domain_type == XENOPROF_DOMAIN_PASSIVE)); -} - -static int is_profiled(struct domain *d) -{ - return (is_active(d) || is_passive(d)); -} - -static void xenoprof_reset_stat(void) -{ - total_samples = 0; - invalid_buffer_samples = 0; - corrupted_buffer_samples = 0; - lost_samples = 0; - active_samples = 0; - passive_samples = 0; - idle_samples = 0; - others_samples = 0; -} - -static void xenoprof_reset_buf(struct domain *d) -{ - int j; - xenoprof_buf_t *buf; - - if ( d->xenoprof == NULL ) - { - printk("xenoprof_reset_buf: ERROR - Unexpected " - "Xenoprof NULL pointer \n"); - return; - } - - for ( j = 0; j < d->max_vcpus; j++ ) - { - buf = d->xenoprof->vcpu[j].buffer; - if ( buf != NULL ) - { - xenoprof_buf(d, buf, event_head) = 0; - xenoprof_buf(d, buf, event_tail) = 0; - } - } -} - -static int -share_xenoprof_page_with_guest(struct domain *d, mfn_t mfn, int npages) -{ - int i; - - /* Check if previous page owner has released the page. */ - for ( i = 0; i < npages; i++ ) - { - struct page_info *page = mfn_to_page(mfn_add(mfn, i)); - - if ( (page->count_info & (PGC_allocated|PGC_count_mask)) != 0 ) - { - printk(XENLOG_G_INFO "dom%d mfn %#lx page->count_info %#lx\n", - d->domain_id, mfn_x(mfn_add(mfn, i)), page->count_info); - return -EBUSY; - } - page_set_owner(page, NULL); - } - - for ( i = 0; i < npages; i++ ) - share_xen_page_with_guest(mfn_to_page(mfn_add(mfn, i)), d, SHARE_rw); - - return 0; -} - -static void -unshare_xenoprof_page_with_guest(struct xenoprof *x) -{ - int i, npages = x->npages; - mfn_t mfn = virt_to_mfn(x->rawbuf); - - for ( i = 0; i < npages; i++ ) - { - struct page_info *page = mfn_to_page(mfn_add(mfn, i)); - - BUG_ON(page_get_owner(page) != current->domain); - put_page_alloc_ref(page); - } -} - -static void -xenoprof_shared_gmfn_with_guest( - struct domain *d, unsigned long maddr, unsigned long gmaddr, int npages) -{ - int i; - - for ( i = 0; i < npages; i++, maddr += PAGE_SIZE, gmaddr += PAGE_SIZE ) - { - BUG_ON(page_get_owner(maddr_to_page(maddr)) != d); - if ( i == 0 ) - gdprintk(XENLOG_WARNING, - "xenoprof unsupported with autotranslated guests\n"); - - } -} - -static int alloc_xenoprof_struct( - struct domain *d, int max_samples, int is_passive) -{ - struct vcpu *v; - int nvcpu, npages, bufsize, max_bufsize; - unsigned max_max_samples; - int i; - - nvcpu = 0; - for_each_vcpu ( d, v ) - nvcpu++; - - if ( !nvcpu ) - return -EINVAL; - - d->xenoprof = xzalloc(struct xenoprof); - if ( d->xenoprof == NULL ) - { - printk("alloc_xenoprof_struct(): memory allocation failed\n"); - return -ENOMEM; - } - - d->xenoprof->vcpu = xzalloc_array(struct xenoprof_vcpu, d->max_vcpus); - if ( d->xenoprof->vcpu == NULL ) - { - xfree(d->xenoprof); - d->xenoprof = NULL; - printk("alloc_xenoprof_struct(): vcpu array allocation failed\n"); - return -ENOMEM; - } - - bufsize = sizeof(struct xenoprof_buf); - i = sizeof(struct event_log); -#ifdef CONFIG_COMPAT - d->xenoprof->is_compat = is_pv_32bit_domain(is_passive ? hardware_domain : d); - if ( XENOPROF_COMPAT(d->xenoprof) ) - { - bufsize = sizeof(struct compat_oprof_buf); - i = sizeof(struct compat_event_log); - } -#endif - - /* reduce max_samples if necessary to limit pages allocated */ - max_bufsize = (MAX_OPROF_SHARED_PAGES * PAGE_SIZE) / nvcpu; - max_max_samples = ( (max_bufsize - bufsize) / i ) + 1; - if ( (unsigned)max_samples > max_max_samples ) - max_samples = max_max_samples; - - bufsize += (max_samples - 1) * i; - npages = (nvcpu * bufsize - 1) / PAGE_SIZE + 1; - - d->xenoprof->rawbuf = alloc_xenheap_pages(get_order_from_pages(npages), 0); - if ( d->xenoprof->rawbuf == NULL ) - { - xfree(d->xenoprof->vcpu); - xfree(d->xenoprof); - d->xenoprof = NULL; - return -ENOMEM; - } - - for ( i = 0; i < npages; ++i ) - clear_page(d->xenoprof->rawbuf + i * PAGE_SIZE); - - d->xenoprof->npages = npages; - d->xenoprof->nbuf = nvcpu; - d->xenoprof->bufsize = bufsize; - d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED; - - /* Update buffer pointers for active vcpus */ - i = 0; - for_each_vcpu ( d, v ) - { - xenoprof_buf_t *buf = (xenoprof_buf_t *) - &d->xenoprof->rawbuf[i * bufsize]; - - d->xenoprof->vcpu[v->vcpu_id].event_size = max_samples; - d->xenoprof->vcpu[v->vcpu_id].buffer = buf; - xenoprof_buf(d, buf, event_size) = max_samples; - xenoprof_buf(d, buf, vcpu_id) = v->vcpu_id; - - i++; - /* in the unlikely case that the number of active vcpus changes */ - if ( i >= nvcpu ) - break; - } - - return 0; -} - -void free_xenoprof_pages(struct domain *d) -{ - struct xenoprof *x; - int order; - - x = d->xenoprof; - if ( x == NULL ) - return; - - if ( x->rawbuf != NULL ) - { - order = get_order_from_pages(x->npages); - free_xenheap_pages(x->rawbuf, order); - } - - xfree(x->vcpu); - xfree(x); - d->xenoprof = NULL; -} - -static int active_index(struct domain *d) -{ - int i; - - for ( i = 0; i < adomains; i++ ) - if ( active_domains[i] == d ) - return i; - - return -1; -} - -static int set_active(struct domain *d) -{ - int ind; - struct xenoprof *x; - - ind = active_index(d); - if ( ind < 0 ) - return -EPERM; - - x = d->xenoprof; - if ( x == NULL ) - return -EPERM; - - x->domain_type = XENOPROF_DOMAIN_ACTIVE; - active_ready[ind] = 1; - activated++; - - return 0; -} - -static int reset_active(struct domain *d) -{ - int ind; - struct xenoprof *x; - - ind = active_index(d); - if ( ind < 0 ) - return -EPERM; - - x = d->xenoprof; - if ( x == NULL ) - return -EPERM; - - x->domain_type = XENOPROF_DOMAIN_IGNORED; - active_ready[ind] = 0; - active_domains[ind] = NULL; - activated--; - put_domain(d); - - if ( activated <= 0 ) - adomains = 0; - - return 0; -} - -static void reset_passive(struct domain *d) -{ - struct xenoprof *x; - - if ( d == NULL ) - return; - - x = d->xenoprof; - if ( x == NULL ) - return; - - x->domain_type = XENOPROF_DOMAIN_IGNORED; - unshare_xenoprof_page_with_guest(x); -} - -static void reset_active_list(void) -{ - int i; - - for ( i = 0; i < adomains; i++ ) - if ( active_ready[i] ) - reset_active(active_domains[i]); - - adomains = 0; - activated = 0; -} - -static void reset_passive_list(void) -{ - int i; - - for ( i = 0; i < pdomains; i++ ) - { - reset_passive(passive_domains[i]); - put_domain(passive_domains[i]); - passive_domains[i] = NULL; - } - - pdomains = 0; -} - -static int add_active_list(domid_t domid) -{ - struct domain *d; - - if ( adomains >= MAX_OPROF_DOMAINS ) - return -E2BIG; - - d = get_domain_by_id(domid); - if ( d == NULL ) - return -EINVAL; - - active_domains[adomains] = d; - active_ready[adomains] = 0; - adomains++; - - return 0; -} - -static int add_passive_list(XEN_GUEST_HANDLE_PARAM(void) arg) -{ - struct xenoprof_passive passive; - struct domain *d; - int ret = 0; - - if ( pdomains >= MAX_OPROF_DOMAINS ) - return -E2BIG; - - if ( copy_from_guest(&passive, arg, 1) ) - return -EFAULT; - - d = get_domain_by_id(passive.domain_id); - if ( d == NULL ) - return -EINVAL; - - if ( d->xenoprof == NULL ) - { - ret = alloc_xenoprof_struct(d, passive.max_samples, 1); - if ( ret < 0 ) - { - put_domain(d); - return -ENOMEM; - } - } - - ret = share_xenoprof_page_with_guest( - current->domain, virt_to_mfn(d->xenoprof->rawbuf), - d->xenoprof->npages); - if ( ret < 0 ) - { - put_domain(d); - return ret; - } - - d->xenoprof->domain_type = XENOPROF_DOMAIN_PASSIVE; - passive.nbuf = d->xenoprof->nbuf; - passive.bufsize = d->xenoprof->bufsize; - if ( !paging_mode_translate(current->domain) ) - passive.buf_gmaddr = __pa(d->xenoprof->rawbuf); - else - xenoprof_shared_gmfn_with_guest( - current->domain, __pa(d->xenoprof->rawbuf), - passive.buf_gmaddr, d->xenoprof->npages); - - if ( __copy_to_guest(arg, &passive, 1) ) - { - put_domain(d); - return -EFAULT; - } - - passive_domains[pdomains] = d; - pdomains++; - - return ret; -} - - -/* Get space in the buffer */ -static int xenoprof_buf_space(int head, int tail, int size) -{ - return ((tail > head) ? 0 : size) + tail - head - 1; -} - -/* Check for space and add a sample. Return 1 if successful, 0 otherwise. */ -static int xenoprof_add_sample(const struct domain *d, - const struct xenoprof_vcpu *v, - uint64_t eip, int mode, int event) -{ - xenoprof_buf_t *buf = v->buffer; - int head, tail, size; - - head = xenoprof_buf(d, buf, event_head); - tail = xenoprof_buf(d, buf, event_tail); - size = v->event_size; - - /* make sure indexes in shared buffer are sane */ - if ( (head < 0) || (head >= size) || (tail < 0) || (tail >= size) ) - { - corrupted_buffer_samples++; - return 0; - } - - if ( xenoprof_buf_space(head, tail, size) > 0 ) - { - xenoprof_buf(d, buf, event_log[head].eip) = eip; - xenoprof_buf(d, buf, event_log[head].mode) = mode; - xenoprof_buf(d, buf, event_log[head].event) = event; - head++; - if ( head >= size ) - head = 0; - - xenoprof_buf(d, buf, event_head) = head; - } - else - { - xenoprof_buf(d, buf, lost_samples)++; - lost_samples++; - return 0; - } - - return 1; -} - -int xenoprof_add_trace(struct vcpu *vcpu, uint64_t pc, int mode) -{ - struct domain *d = vcpu->domain; - - /* Do not accidentally write an escape code due to a broken frame. */ - if ( pc == XENOPROF_ESCAPE_CODE ) - { - invalid_buffer_samples++; - return 0; - } - - return xenoprof_add_sample(d, &d->xenoprof->vcpu[vcpu->vcpu_id], - pc, mode, 0); -} - -void xenoprof_log_event(struct vcpu *vcpu, const struct cpu_user_regs *regs, - uint64_t pc, int mode, int event) -{ - struct domain *d = vcpu->domain; - struct xenoprof_vcpu *v; - xenoprof_buf_t *buf; - - total_samples++; - - /* Ignore samples of un-monitored domains. */ - if ( !is_profiled(d) ) - { - others_samples++; - return; - } - - v = &d->xenoprof->vcpu[vcpu->vcpu_id]; - if ( v->buffer == NULL ) - { - invalid_buffer_samples++; - return; - } - - buf = v->buffer; - - /* Provide backtrace if requested. */ - if ( backtrace_depth > 0 ) - { - if ( xenoprof_buf_space(xenoprof_buf(d, buf, event_head), - xenoprof_buf(d, buf, event_tail), - v->event_size) < 2 ) - { - xenoprof_buf(d, buf, lost_samples)++; - lost_samples++; - return; - } - - /* xenoprof_add_sample() will increment lost_samples on failure */ - if ( !xenoprof_add_sample(d, v, XENOPROF_ESCAPE_CODE, mode, - XENOPROF_TRACE_BEGIN) ) - return; - } - - if ( xenoprof_add_sample(d, v, pc, mode, event) ) - { - if ( is_active(vcpu->domain) ) - active_samples++; - else - passive_samples++; - if ( mode == 0 ) - xenoprof_buf(d, buf, user_samples)++; - else if ( mode == 1 ) - xenoprof_buf(d, buf, kernel_samples)++; - else - xenoprof_buf(d, buf, xen_samples)++; - - } - - if ( backtrace_depth > 0 ) - xenoprof_backtrace(vcpu, regs, backtrace_depth, mode); -} - - - -static int xenoprof_op_init(XEN_GUEST_HANDLE_PARAM(void) arg) -{ - struct domain *d = current->domain; - struct xenoprof_init xenoprof_init; - int ret; - - if ( copy_from_guest(&xenoprof_init, arg, 1) ) - return -EFAULT; - - if ( (ret = xenoprof_arch_init(&xenoprof_init.num_events, - xenoprof_init.cpu_type)) ) - return ret; - - /* Only the hardware domain may become the primary profiler here because - * there is currently no cleanup of xenoprof_primary_profiler or associated - * profiling state when the primary profiling domain is shut down or - * crashes. Once a better cleanup method is present, it will be possible to - * allow another domain to be the primary profiler. - */ - xenoprof_init.is_primary = - ((xenoprof_primary_profiler == d) || - ((xenoprof_primary_profiler == NULL) && is_hardware_domain(d))); - if ( xenoprof_init.is_primary ) - xenoprof_primary_profiler = current->domain; - - return __copy_to_guest(arg, &xenoprof_init, 1) ? -EFAULT : 0; -} - -#define ret_t long - -#endif /* !COMPAT */ - -static int xenoprof_op_get_buffer(XEN_GUEST_HANDLE_PARAM(void) arg) -{ - struct xenoprof_get_buffer xenoprof_get_buffer; - struct domain *d = current->domain; - int ret; - - if ( copy_from_guest(&xenoprof_get_buffer, arg, 1) ) - return -EFAULT; - - /* - * We allocate xenoprof struct and buffers only at first time - * get_buffer is called. Memory is then kept until domain is destroyed. - */ - if ( d->xenoprof == NULL ) - { - ret = alloc_xenoprof_struct(d, xenoprof_get_buffer.max_samples, 0); - if ( ret < 0 ) - return ret; - } - else - d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED; - - ret = share_xenoprof_page_with_guest( - d, virt_to_mfn(d->xenoprof->rawbuf), d->xenoprof->npages); - if ( ret < 0 ) - return ret; - - xenoprof_reset_buf(d); - - xenoprof_get_buffer.nbuf = d->xenoprof->nbuf; - xenoprof_get_buffer.bufsize = d->xenoprof->bufsize; - if ( !paging_mode_translate(d) ) - xenoprof_get_buffer.buf_gmaddr = __pa(d->xenoprof->rawbuf); - else - xenoprof_shared_gmfn_with_guest( - d, __pa(d->xenoprof->rawbuf), xenoprof_get_buffer.buf_gmaddr, - d->xenoprof->npages); - - return __copy_to_guest(arg, &xenoprof_get_buffer, 1) ? -EFAULT : 0; -} - -#define NONPRIV_OP(op) ( (op == XENOPROF_init) \ - || (op == XENOPROF_enable_virq) \ - || (op == XENOPROF_disable_virq) \ - || (op == XENOPROF_get_buffer)) - -ret_t do_xenoprof_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg) -{ - int ret = 0; - - if ( (op < 0) || (op > XENOPROF_last_op) ) - { - gdprintk(XENLOG_DEBUG, "invalid operation %d\n", op); - return -EINVAL; - } - - if ( !NONPRIV_OP(op) && (current->domain != xenoprof_primary_profiler) ) - { - gdprintk(XENLOG_DEBUG, "denied privileged operation %d\n", op); - return -EPERM; - } - - ret = xsm_profile(XSM_HOOK, current->domain, op); - if ( ret ) - return ret; - - spin_lock(&xenoprof_lock); - - switch ( op ) - { - case XENOPROF_init: - ret = xenoprof_op_init(arg); - if ( (ret == 0) && - (current->domain == xenoprof_primary_profiler) ) - xenoprof_state = XENOPROF_INITIALIZED; - break; - - case XENOPROF_get_buffer: - if ( !acquire_pmu_ownership(PMU_OWNER_XENOPROF) ) - { - ret = -EBUSY; - break; - } - ret = xenoprof_op_get_buffer(arg); - break; - - case XENOPROF_reset_active_list: - reset_active_list(); - ret = 0; - break; - - case XENOPROF_reset_passive_list: - reset_passive_list(); - ret = 0; - break; - - case XENOPROF_set_active: - { - domid_t domid; - if ( xenoprof_state != XENOPROF_INITIALIZED ) - { - ret = -EPERM; - break; - } - if ( copy_from_guest(&domid, arg, 1) ) - { - ret = -EFAULT; - break; - } - ret = add_active_list(domid); - break; - } - - case XENOPROF_set_passive: - if ( xenoprof_state != XENOPROF_INITIALIZED ) - { - ret = -EPERM; - break; - } - ret = add_passive_list(arg); - break; - - case XENOPROF_reserve_counters: - if ( xenoprof_state != XENOPROF_INITIALIZED ) - { - ret = -EPERM; - break; - } - ret = xenoprof_arch_reserve_counters(); - if ( !ret ) - xenoprof_state = XENOPROF_COUNTERS_RESERVED; - break; - - case XENOPROF_counter: - if ( (xenoprof_state != XENOPROF_COUNTERS_RESERVED) || - (adomains == 0) ) - { - ret = -EPERM; - break; - } - ret = xenoprof_arch_counter(arg); - break; - - case XENOPROF_setup_events: - if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED ) - { - ret = -EPERM; - break; - } - ret = xenoprof_arch_setup_events(); - if ( !ret ) - xenoprof_state = XENOPROF_READY; - break; - - case XENOPROF_enable_virq: - { - int i; - - if ( current->domain == xenoprof_primary_profiler ) - { - if ( xenoprof_state != XENOPROF_READY ) - { - ret = -EPERM; - break; - } - xenoprof_arch_enable_virq(); - xenoprof_reset_stat(); - for ( i = 0; i < pdomains; i++ ) - xenoprof_reset_buf(passive_domains[i]); - } - xenoprof_reset_buf(current->domain); - ret = set_active(current->domain); - break; - } - - case XENOPROF_start: - ret = -EPERM; - if ( (xenoprof_state == XENOPROF_READY) && - (activated == adomains) ) - ret = xenoprof_arch_start(); - if ( ret == 0 ) - xenoprof_state = XENOPROF_PROFILING; - break; - - case XENOPROF_stop: - { - struct domain *d; - struct vcpu *v; - int i; - - if ( xenoprof_state != XENOPROF_PROFILING ) - { - ret = -EPERM; - break; - } - xenoprof_arch_stop(); - - /* Flush remaining samples. */ - for ( i = 0; i < adomains; i++ ) - { - if ( !active_ready[i] ) - continue; - d = active_domains[i]; - for_each_vcpu(d, v) - send_guest_vcpu_virq(v, VIRQ_XENOPROF); - } - xenoprof_state = XENOPROF_READY; - break; - } - - case XENOPROF_disable_virq: - { - struct xenoprof *x; - if ( (xenoprof_state == XENOPROF_PROFILING) && - (is_active(current->domain)) ) - { - ret = -EPERM; - break; - } - if ( (ret = reset_active(current->domain)) != 0 ) - break; - x = current->domain->xenoprof; - unshare_xenoprof_page_with_guest(x); - release_pmu_ownership(PMU_OWNER_XENOPROF); - break; - } - - case XENOPROF_release_counters: - ret = -EPERM; - if ( (xenoprof_state == XENOPROF_COUNTERS_RESERVED) || - (xenoprof_state == XENOPROF_READY) ) - { - xenoprof_state = XENOPROF_INITIALIZED; - xenoprof_arch_release_counters(); - xenoprof_arch_disable_virq(); - reset_passive_list(); - ret = 0; - } - break; - - case XENOPROF_shutdown: - ret = -EPERM; - if ( xenoprof_state == XENOPROF_INITIALIZED ) - { - activated = 0; - adomains=0; - xenoprof_primary_profiler = NULL; - backtrace_depth=0; - ret = 0; - } - break; - - case XENOPROF_set_backtrace: - ret = 0; - if ( !xenoprof_backtrace_supported() ) - ret = -EINVAL; - else if ( copy_from_guest(&backtrace_depth, arg, 1) ) - ret = -EFAULT; - break; - - case XENOPROF_ibs_counter: - if ( (xenoprof_state != XENOPROF_COUNTERS_RESERVED) || - (adomains == 0) ) - { - ret = -EPERM; - break; - } - ret = xenoprof_arch_ibs_counter(arg); - break; - - case XENOPROF_get_ibs_caps: - ret = ibs_caps; - break; - - default: - ret = -ENOSYS; - } - - spin_unlock(&xenoprof_lock); - - if ( ret < 0 ) - gdprintk(XENLOG_DEBUG, "operation %d failed: %d\n", op, ret); - - return ret; -} - -#if defined(CONFIG_COMPAT) && !defined(COMPAT) -#undef ret_t -#include "compat/xenoprof.c" -#endif - -/* - * Local variables: - * mode: C - * c-file-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/include/Makefile b/xen/include/Makefile index e71f419e8c..b3184a395b 100644 --- a/xen/include/Makefile +++ b/xen/include/Makefile @@ -31,7 +31,6 @@ headers-$(CONFIG_HVM) += compat/hvm/hvm_vcpu.h headers-$(CONFIG_HYPFS) += compat/hypfs.h headers-$(CONFIG_KEXEC) += compat/kexec.h headers-$(CONFIG_TRACEBUFFER) += compat/trace.h -headers-$(CONFIG_XENOPROF) += compat/xenoprof.h headers-$(CONFIG_XSM_FLASK) += compat/xsm/flask_op.h headers-n := $(sort $(filter-out $(headers-y),$(headers-n) $(headers-))) diff --git a/xen/include/hypercall-defs.c b/xen/include/hypercall-defs.c index 5782cdfd14..63755bb8df 100644 --- a/xen/include/hypercall-defs.c +++ b/xen/include/hypercall-defs.c @@ -127,9 +127,6 @@ argo_op(unsigned int cmd, void *arg1, void *arg2, unsigned long arg3, unsigned l #ifdef CONFIG_PV iret() nmi_op(unsigned int cmd, void *arg) -#ifdef CONFIG_XENOPROF -xenoprof_op(int op, void *arg) -#endif #endif /* CONFIG_PV */ #ifdef CONFIG_COMPAT @@ -269,9 +266,6 @@ xsm_op compat do compat do do nmi_op compat do - - - sched_op compat do compat do do callback_op compat do - - - -#ifdef CONFIG_XENOPROF -xenoprof_op compat do - - - -#endif event_channel_op do do do:1 do:1 do:1 physdev_op compat do hvm hvm do_arm #ifdef CONFIG_HVM diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index 7f15204c38..b12fd10e63 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -106,7 +106,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_ulong_t); #define __HYPERVISOR_nmi_op 28 #define __HYPERVISOR_sched_op 29 #define __HYPERVISOR_callback_op 30 -#define __HYPERVISOR_xenoprof_op 31 +#define __HYPERVISOR_xenoprof_op 31 /* Dropped in Xen 4.22 */ #define __HYPERVISOR_event_channel_op 32 #define __HYPERVISOR_physdev_op 33 #define __HYPERVISOR_hvm_op 34 diff --git a/xen/include/public/xenoprof.h b/xen/include/public/xenoprof.h index 2298b6759e..f97a67042e 100644 --- a/xen/include/public/xenoprof.h +++ b/xen/include/public/xenoprof.h @@ -3,7 +3,7 @@ * xenoprof.h * * Interface for enabling system wide profiling based on hardware performance - * counters + * counters. Dropped from Xen in 4.22. * * Copyright (C) 2005 Hewlett-Packard Co. * Written by Aravind Menon & Jose Renato Santos diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index d922c908c2..91d6a49daf 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -574,9 +574,6 @@ struct domain /* Control-plane tools handle for this domain. */ xen_domain_handle_t handle; - /* OProfile support. */ - struct xenoprof *xenoprof; - /* Domain watchdog. */ #define NR_DOMAIN_WATCHDOG_TIMERS 2 spinlock_t watchdog_lock; diff --git a/xen/include/xen/xenoprof.h b/xen/include/xen/xenoprof.h deleted file mode 100644 index c3dac447d3..0000000000 --- a/xen/include/xen/xenoprof.h +++ /dev/null @@ -1,49 +0,0 @@ -/****************************************************************************** - * xenoprof.h - * - * Xenoprof: Xenoprof enables performance profiling in Xen - * - * Copyright (C) 2005 Hewlett-Packard Co. - * written by Aravind Menon & Jose Renato Santos - */ - -#ifndef __XEN_XENOPROF_H__ -#define __XEN_XENOPROF_H__ - -#define PMU_OWNER_NONE 0 -#define PMU_OWNER_XENOPROF 1 -#define PMU_OWNER_HVM 2 - -#ifdef CONFIG_XENOPROF - -#include -#include - -struct domain; -struct vcpu; -struct cpu_user_regs; - -int acquire_pmu_ownership(int pmu_ownership); -void release_pmu_ownership(int pmu_ownership); - -int is_active(struct domain *d); -int is_passive(struct domain *d); -void free_xenoprof_pages(struct domain *d); - -int xenoprof_add_trace(struct vcpu *, uint64_t pc, int mode); - -void xenoprof_log_event(struct vcpu *, const struct cpu_user_regs *, - uint64_t pc, int mode, int event); - -#else -static inline int acquire_pmu_ownership(int pmu_ownership) -{ - return 1; -} - -static inline void release_pmu_ownership(int pmu_ownership) -{ -} -#endif /* CONFIG_XENOPROF */ - -#endif /* __XEN__XENOPROF_H__ */ diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h index e801dbcdba..b8fd7aeedd 100644 --- a/xen/include/xsm/dummy.h +++ b/xen/include/xsm/dummy.h @@ -278,13 +278,6 @@ static XSM_INLINE int cf_check xsm_console_io( return xsm_default_action(XSM_PRIV, d, NULL); } -static XSM_INLINE int cf_check xsm_profile( - XSM_DEFAULT_ARG struct domain *d, int op) -{ - XSM_ASSERT_ACTION(XSM_HOOK); - return xsm_default_action(action, d, NULL); -} - static XSM_INLINE int cf_check xsm_kexec(XSM_DEFAULT_VOID) { XSM_ASSERT_ACTION(XSM_PRIV); diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index 2d831d7745..cc32a6c091 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -101,8 +101,6 @@ struct xsm_ops { int (*console_io)(struct domain *d, int cmd); - int (*profile)(struct domain *d, int op); - int (*kexec)(void); int (*schedop_shutdown)(struct domain *d1, struct domain *d2); @@ -450,11 +448,6 @@ static inline int xsm_console_io(xsm_default_t def, struct domain *d, int cmd) return alternative_call(xsm_ops.console_io, d, cmd); } -static inline int xsm_profile(xsm_default_t def, struct domain *d, int op) -{ - return alternative_call(xsm_ops.profile, d, op); -} - static inline int xsm_kexec(xsm_default_t def) { return alternative_call(xsm_ops.kexec); diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index 96dc82ac2e..244ef55752 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -61,8 +61,6 @@ static const struct xsm_ops __initconst_cf_clobber dummy_ops = { .console_io = xsm_console_io, - .profile = xsm_profile, - .kexec = xsm_kexec, .schedop_shutdown = xsm_schedop_shutdown, diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 9f3915617c..b250b27065 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #ifdef CONFIG_HAS_PCI_MSI #include @@ -512,38 +511,6 @@ static int cf_check flask_console_io(struct domain *d, int cmd) return domain_has_xen(d, perm); } -static int cf_check flask_profile(struct domain *d, int op) -{ - uint32_t perm; - - switch ( op ) - { - case XENOPROF_init: - case XENOPROF_enable_virq: - case XENOPROF_disable_virq: - case XENOPROF_get_buffer: - perm = XEN__NONPRIVPROFILE; - break; - case XENOPROF_reset_active_list: - case XENOPROF_reset_passive_list: - case XENOPROF_set_active: - case XENOPROF_set_passive: - case XENOPROF_reserve_counters: - case XENOPROF_counter: - case XENOPROF_setup_events: - case XENOPROF_start: - case XENOPROF_stop: - case XENOPROF_release_counters: - case XENOPROF_shutdown: - perm = XEN__PRIVPROFILE; - break; - default: - return avc_unknown_permission("xenoprof op", op); - } - - return domain_has_xen(d, perm); -} - static int cf_check flask_kexec(void) { return domain_has_xen(current->domain, XEN__KEXEC); @@ -1930,8 +1897,6 @@ static const struct xsm_ops __initconst_cf_clobber flask_ops = { .console_io = flask_console_io, - .profile = flask_profile, - .kexec = flask_kexec, .schedop_shutdown = flask_schedop_shutdown, diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors index 51a1577a66..ce907d50a4 100644 --- a/xen/xsm/flask/policy/access_vectors +++ b/xen/xsm/flask/policy/access_vectors @@ -38,10 +38,6 @@ class xen readapic # PHYSDEVOP_apic_write writeapic -# Most XENOPROF_* - privprofile -# XENOPROF_{init,enable_virq,disable_virq,get_buffer} - nonprivprofile # kexec hypercall kexec # XENPF_firmware_info, XENPF_efi_runtime_call