15464 lines · 376.7 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* * Performance events core code: * *  Copyright (C) 2008 Linutronix GmbH, Thomas Gleixner <tglx@kernel.org> *  Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra *  Copyright  ©  2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com> */ #include <linux/fs.h>#include <linux/mm.h>#include <linux/cpu.h>#include <linux/smp.h>#include <linux/idr.h>#include <linux/file.h>#include <linux/poll.h>#include <linux/slab.h>#include <linux/hash.h>#include <linux/tick.h>#include <linux/sysfs.h>#include <linux/dcache.h>#include <linux/percpu.h>#include <linux/ptrace.h>#include <linux/reboot.h>#include <linux/vmstat.h>#include <linux/device.h>#include <linux/export.h>#include <linux/vmalloc.h>#include <linux/hardirq.h>#include <linux/hugetlb.h>#include <linux/rculist.h>#include <linux/uaccess.h>#include <linux/syscalls.h>#include <linux/anon_inodes.h>#include <linux/kernel_stat.h>#include <linux/cgroup.h>#include <linux/perf_event.h>#include <linux/trace_events.h>#include <linux/hw_breakpoint.h>#include <linux/mm_types.h>#include <linux/module.h>#include <linux/mman.h>#include <linux/compat.h>#include <linux/bpf.h>#include <linux/filter.h>#include <linux/namei.h>#include <linux/parser.h>#include <linux/sched/clock.h>#include <linux/sched/mm.h>#include <linux/proc_ns.h>#include <linux/mount.h>#include <linux/min_heap.h>#include <linux/highmem.h>#include <linux/pgtable.h>#include <linux/buildid.h>#include <linux/task_work.h>#include <linux/percpu-rwsem.h>#include <linux/unwind_deferred.h>#include <linux/kvm_types.h>#include <linux/seq_file.h> #include "internal.h" #include <asm/irq_regs.h> typedef int (*remote_function_f)(void *); struct remote_function_call {	struct task_struct	*p;	remote_function_f	func;	void			*info;	int			ret;}; static void remote_function(void *data){	struct remote_function_call *tfc = data;	struct task_struct *p = tfc->p; 	if (p) {		/* -EAGAIN */		if (task_cpu(p) != smp_processor_id())			return; 		/*		 * Now that we're on right CPU with IRQs disabled, we can test		 * if we hit the right task without races.		 */ 		tfc->ret = -ESRCH; /* No such (running) process */		if (p != current)			return;	} 	tfc->ret = tfc->func(tfc->info);} /** * task_function_call - call a function on the cpu on which a task runs * @p:		the task to evaluate * @func:	the function to be called * @info:	the function call argument * * Calls the function @func when the task is currently running. This might * be on the current CPU, which just calls the function directly.  This will * retry due to any failures in smp_call_function_single(), such as if the * task_cpu() goes offline concurrently. * * returns @func return value or -ESRCH or -ENXIO when the process isn't running */static inttask_function_call(struct task_struct *p, remote_function_f func, void *info){	struct remote_function_call data = {		.p	= p,		.func	= func,		.info	= info,		.ret	= -EAGAIN,	};	int ret; 	for (;;) {		ret = smp_call_function_single(task_cpu(p), remote_function,					       &data, 1);		if (!ret)			ret = data.ret; 		if (ret != -EAGAIN)			break; 		cond_resched();	} 	return ret;} /** * cpu_function_call - call a function on the cpu * @cpu:	target cpu to queue this function * @func:	the function to be called * @info:	the function call argument * * Calls the function @func on the remote cpu. * * returns: @func return value or -ENXIO when the cpu is offline */static int cpu_function_call(int cpu, remote_function_f func, void *info){	struct remote_function_call data = {		.p	= NULL,		.func	= func,		.info	= info,		.ret	= -ENXIO, /* No such CPU */	}; 	smp_call_function_single(cpu, remote_function, &data, 1); 	return data.ret;} enum event_type_t {	EVENT_FLEXIBLE	= 0x01,	EVENT_PINNED	= 0x02,	EVENT_TIME	= 0x04,	EVENT_FROZEN	= 0x08,	/* see ctx_resched() for details */	EVENT_CPU	= 0x10,	EVENT_CGROUP	= 0x20, 	/*	 * EVENT_GUEST is set when scheduling in/out events between the host	 * and a guest with a mediated vPMU.  Among other things, EVENT_GUEST	 * is used:	 *	 * - In for_each_epc() to skip PMUs that don't support events in a	 *   MEDIATED_VPMU guest, i.e. don't need to be context switched.	 * - To indicate the start/end point of the events in a guest.  Guest	 *   running time is deducted for host-only (exclude_guest) events.	 */	EVENT_GUEST	= 0x40,	EVENT_FLAGS	= EVENT_CGROUP | EVENT_GUEST,	/* compound helpers */	EVENT_ALL         = EVENT_FLEXIBLE | EVENT_PINNED,	EVENT_TIME_FROZEN = EVENT_TIME | EVENT_FROZEN,}; static inline void __perf_ctx_lock(struct perf_event_context *ctx){	raw_spin_lock(&ctx->lock);	WARN_ON_ONCE(ctx->is_active & EVENT_FROZEN);} static void perf_ctx_lock(struct perf_cpu_context *cpuctx,			  struct perf_event_context *ctx){	__perf_ctx_lock(&cpuctx->ctx);	if (ctx)		__perf_ctx_lock(ctx);} static inline void __perf_ctx_unlock(struct perf_event_context *ctx){	/*	 * If ctx_sched_in() didn't again set any ALL flags, clean up	 * after ctx_sched_out() by clearing is_active.	 */	if (ctx->is_active & EVENT_FROZEN) {		if (!(ctx->is_active & EVENT_ALL))			ctx->is_active = 0;		else			ctx->is_active &= ~EVENT_FROZEN;	}	raw_spin_unlock(&ctx->lock);} static void perf_ctx_unlock(struct perf_cpu_context *cpuctx,			    struct perf_event_context *ctx){	if (ctx)		__perf_ctx_unlock(ctx);	__perf_ctx_unlock(&cpuctx->ctx);} typedef struct {	struct perf_cpu_context *cpuctx;	struct perf_event_context *ctx;} class_perf_ctx_lock_t; static inline void class_perf_ctx_lock_destructor(class_perf_ctx_lock_t *_T){ perf_ctx_unlock(_T->cpuctx, _T->ctx); } static inline class_perf_ctx_lock_tclass_perf_ctx_lock_constructor(struct perf_cpu_context *cpuctx,				struct perf_event_context *ctx){ perf_ctx_lock(cpuctx, ctx); return (class_perf_ctx_lock_t){ cpuctx, ctx }; } #define TASK_TOMBSTONE ((void *)-1L) static bool is_kernel_event(struct perf_event *event){	return READ_ONCE(event->owner) == TASK_TOMBSTONE;} static DEFINE_PER_CPU(struct perf_cpu_context, perf_cpu_context); struct perf_event_context *perf_cpu_task_ctx(void){	lockdep_assert_irqs_disabled();	return this_cpu_ptr(&perf_cpu_context)->task_ctx;} /* * On task ctx scheduling... * * When !ctx->nr_events a task context will not be scheduled. This means * we can disable the scheduler hooks (for performance) without leaving * pending task ctx state. * * This however results in two special cases: * *  - removing the last event from a task ctx; this is relatively straight *    forward and is done in __perf_remove_from_context. * *  - adding the first event to a task ctx; this is tricky because we cannot *    rely on ctx->is_active and therefore cannot use event_function_call(). *    See perf_install_in_context(). * * If ctx->nr_events, then ctx->is_active and cpuctx->task_ctx are set. */ typedef void (*event_f)(struct perf_event *, struct perf_cpu_context *,			struct perf_event_context *, void *); struct event_function_struct {	struct perf_event *event;	event_f func;	void *data;}; static int event_function(void *info){	struct event_function_struct *efs = info;	struct perf_event *event = efs->event;	struct perf_event_context *ctx = event->ctx;	struct perf_cpu_context *cpuctx = this_cpu_ptr(&perf_cpu_context);	struct perf_event_context *task_ctx = cpuctx->task_ctx;	int ret = 0; 	lockdep_assert_irqs_disabled(); 	perf_ctx_lock(cpuctx, task_ctx);	/*	 * Since we do the IPI call without holding ctx->lock things can have	 * changed, double check we hit the task we set out to hit.	 */	if (ctx->task) {		if (ctx->task != current) {			ret = -ESRCH;			goto unlock;		} 		/*		 * We only use event_function_call() on established contexts,		 * and event_function() is only ever called when active (or		 * rather, we'll have bailed in task_function_call() or the		 * above ctx->task != current test), therefore we must have		 * ctx->is_active here.		 */		WARN_ON_ONCE(!ctx->is_active);		/*		 * And since we have ctx->is_active, cpuctx->task_ctx must		 * match.		 */		WARN_ON_ONCE(task_ctx != ctx);	} else {		WARN_ON_ONCE(&cpuctx->ctx != ctx);	} 	efs->func(event, cpuctx, ctx, efs->data);unlock:	perf_ctx_unlock(cpuctx, task_ctx); 	return ret;} static void event_function_call(struct perf_event *event, event_f func, void *data){	struct perf_event_context *ctx = event->ctx;	struct task_struct *task = READ_ONCE(ctx->task); /* verified in event_function */	struct perf_cpu_context *cpuctx;	struct event_function_struct efs = {		.event = event,		.func = func,		.data = data,	}; 	if (!event->parent) {		/*		 * If this is a !child event, we must hold ctx::mutex to		 * stabilize the event->ctx relation. See		 * perf_event_ctx_lock().		 */		lockdep_assert_held(&ctx->mutex);	} 	if (!task) {		cpu_function_call(event->cpu, event_function, &efs);		return;	} 	if (task == TASK_TOMBSTONE)		return; again:	if (!task_function_call(task, event_function, &efs))		return; 	local_irq_disable();	cpuctx = this_cpu_ptr(&perf_cpu_context);	perf_ctx_lock(cpuctx, ctx);	/*	 * Reload the task pointer, it might have been changed by	 * a concurrent perf_event_context_sched_out().	 */	task = ctx->task;	if (task == TASK_TOMBSTONE)		goto unlock;	if (ctx->is_active) {		perf_ctx_unlock(cpuctx, ctx);		local_irq_enable();		goto again;	}	func(event, NULL, ctx, data);unlock:	perf_ctx_unlock(cpuctx, ctx);	local_irq_enable();} /* * Similar to event_function_call() + event_function(), but hard assumes IRQs * are already disabled and we're on the right CPU. */static void event_function_local(struct perf_event *event, event_f func, void *data){	struct perf_event_context *ctx = event->ctx;	struct perf_cpu_context *cpuctx = this_cpu_ptr(&perf_cpu_context);	struct task_struct *task = READ_ONCE(ctx->task);	struct perf_event_context *task_ctx = NULL; 	lockdep_assert_irqs_disabled(); 	if (task) {		if (task == TASK_TOMBSTONE)			return; 		task_ctx = ctx;	} 	perf_ctx_lock(cpuctx, task_ctx); 	task = ctx->task;	if (task == TASK_TOMBSTONE)		goto unlock; 	if (task) {		/*		 * We must be either inactive or active and the right task,		 * otherwise we're screwed, since we cannot IPI to somewhere		 * else.		 */		if (ctx->is_active) {			if (WARN_ON_ONCE(task != current))				goto unlock; 			if (WARN_ON_ONCE(cpuctx->task_ctx != ctx))				goto unlock;		}	} else {		WARN_ON_ONCE(&cpuctx->ctx != ctx);	} 	func(event, cpuctx, ctx, data);unlock:	perf_ctx_unlock(cpuctx, task_ctx);} #define PERF_FLAG_ALL (PERF_FLAG_FD_NO_GROUP |\		       PERF_FLAG_FD_OUTPUT  |\		       PERF_FLAG_PID_CGROUP |\		       PERF_FLAG_FD_CLOEXEC) /* * branch priv levels that need permission checks */#define PERF_SAMPLE_BRANCH_PERM_PLM \	(PERF_SAMPLE_BRANCH_KERNEL |\	 PERF_SAMPLE_BRANCH_HV) /* * perf_sched_events : >0 events exist */ static void perf_sched_delayed(struct work_struct *work);DEFINE_STATIC_KEY_FALSE(perf_sched_events);static DECLARE_DELAYED_WORK(perf_sched_work, perf_sched_delayed);static DEFINE_MUTEX(perf_sched_mutex);static atomic_t perf_sched_count; static DEFINE_PER_CPU(struct pmu_event_list, pmu_sb_events); static atomic_t nr_mmap_events __read_mostly;static atomic_t nr_comm_events __read_mostly;static atomic_t nr_namespaces_events __read_mostly;static atomic_t nr_task_events __read_mostly;static atomic_t nr_freq_events __read_mostly;static atomic_t nr_switch_events __read_mostly;static atomic_t nr_ksymbol_events __read_mostly;static atomic_t nr_bpf_events __read_mostly;static atomic_t nr_cgroup_events __read_mostly;static atomic_t nr_text_poke_events __read_mostly;static atomic_t nr_build_id_events __read_mostly; static LIST_HEAD(pmus);static DEFINE_MUTEX(pmus_lock);static struct srcu_struct pmus_srcu;static cpumask_var_t perf_online_mask;static cpumask_var_t perf_online_core_mask;static cpumask_var_t perf_online_die_mask;static cpumask_var_t perf_online_cluster_mask;static cpumask_var_t perf_online_pkg_mask;static cpumask_var_t perf_online_sys_mask;static struct kmem_cache *perf_event_cache; #ifdef CONFIG_PERF_GUEST_MEDIATED_PMUstatic DEFINE_PER_CPU(bool, guest_ctx_loaded); static __always_inline bool is_guest_mediated_pmu_loaded(void){	return __this_cpu_read(guest_ctx_loaded);}#elsestatic __always_inline bool is_guest_mediated_pmu_loaded(void){	return false;}#endif /* * perf event paranoia level: *  -1 - not paranoid at all *   0 - disallow raw tracepoint access for unpriv *   1 - disallow cpu events for unpriv *   2 - disallow kernel profiling for unpriv */int sysctl_perf_event_paranoid __read_mostly = 2; /* Minimum for 512 kiB + 1 user control page. 'free' kiB per user. */static int sysctl_perf_event_mlock __read_mostly = 512 + (PAGE_SIZE / 1024); 

Lines 1–500 of 15464.