| .. | .. | 
|---|
 | 1 | +// SPDX-License-Identifier: GPL-2.0  | 
|---|
| 1 | 2 |  /* | 
|---|
| 2 | 3 |   * Performance events callchain code, extracted from core.c: | 
|---|
| 3 | 4 |   * | 
|---|
| .. | .. | 
|---|
| 5 | 6 |   *  Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar | 
|---|
| 6 | 7 |   *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra | 
|---|
| 7 | 8 |   *  Copyright  ©  2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com> | 
|---|
| 8 |  | - *  | 
|---|
| 9 |  | - * For licensing details see kernel-base/COPYING  | 
|---|
| 10 | 9 |   */ | 
|---|
| 11 | 10 |   | 
|---|
| 12 | 11 |  #include <linux/perf_event.h> | 
|---|
| .. | .. | 
|---|
| 17 | 16 |   | 
|---|
| 18 | 17 |  struct callchain_cpus_entries { | 
|---|
| 19 | 18 |  	struct rcu_head			rcu_head; | 
|---|
| 20 |  | -	struct perf_callchain_entry	*cpu_entries[0];  | 
|---|
 | 19 | +	struct perf_callchain_entry	*cpu_entries[];  | 
|---|
| 21 | 20 |  }; | 
|---|
| 22 | 21 |   | 
|---|
| 23 | 22 |  int sysctl_perf_event_max_stack __read_mostly = PERF_MAX_STACK_DEPTH; | 
|---|
| .. | .. | 
|---|
| 150 | 149 |  	} | 
|---|
| 151 | 150 |  } | 
|---|
| 152 | 151 |   | 
|---|
| 153 |  | -static struct perf_callchain_entry *get_callchain_entry(int *rctx)  | 
|---|
 | 152 | +struct perf_callchain_entry *get_callchain_entry(int *rctx)  | 
|---|
| 154 | 153 |  { | 
|---|
| 155 | 154 |  	int cpu; | 
|---|
| 156 | 155 |  	struct callchain_cpus_entries *entries; | 
|---|
| .. | .. | 
|---|
| 160 | 159 |  		return NULL; | 
|---|
| 161 | 160 |   | 
|---|
| 162 | 161 |  	entries = rcu_dereference(callchain_cpus_entries); | 
|---|
| 163 |  | -	if (!entries)  | 
|---|
 | 162 | +	if (!entries) {  | 
|---|
 | 163 | +		put_recursion_context(this_cpu_ptr(callchain_recursion), *rctx);  | 
|---|
| 164 | 164 |  		return NULL; | 
|---|
 | 165 | +	}  | 
|---|
| 165 | 166 |   | 
|---|
| 166 | 167 |  	cpu = smp_processor_id(); | 
|---|
| 167 | 168 |   | 
|---|
| .. | .. | 
|---|
| 169 | 170 |  		(*rctx * perf_callchain_entry__sizeof())); | 
|---|
| 170 | 171 |  } | 
|---|
| 171 | 172 |   | 
|---|
| 172 |  | -static void  | 
|---|
 | 173 | +void  | 
|---|
| 173 | 174 |  put_callchain_entry(int rctx) | 
|---|
| 174 | 175 |  { | 
|---|
| 175 | 176 |  	put_recursion_context(this_cpu_ptr(callchain_recursion), rctx); | 
|---|
| .. | .. | 
|---|
| 184 | 185 |  	int rctx; | 
|---|
| 185 | 186 |   | 
|---|
| 186 | 187 |  	entry = get_callchain_entry(&rctx); | 
|---|
| 187 |  | -	if (rctx == -1)  | 
|---|
| 188 |  | -		return NULL;  | 
|---|
| 189 |  | -  | 
|---|
| 190 | 188 |  	if (!entry) | 
|---|
| 191 |  | -		goto exit_put;  | 
|---|
 | 189 | +		return NULL;  | 
|---|
| 192 | 190 |   | 
|---|
| 193 | 191 |  	ctx.entry     = entry; | 
|---|
| 194 | 192 |  	ctx.max_stack = max_stack; | 
|---|
| .. | .. | 
|---|
| 219 | 217 |  			if (add_mark) | 
|---|
| 220 | 218 |  				perf_callchain_store_context(&ctx, PERF_CONTEXT_USER); | 
|---|
| 221 | 219 |   | 
|---|
| 222 |  | -			fs = get_fs();  | 
|---|
| 223 |  | -			set_fs(USER_DS);  | 
|---|
 | 220 | +			fs = force_uaccess_begin();  | 
|---|
| 224 | 221 |  			perf_callchain_user(&ctx, regs); | 
|---|
| 225 |  | -			set_fs(fs);  | 
|---|
 | 222 | +			force_uaccess_end(fs);  | 
|---|
| 226 | 223 |  		} | 
|---|
| 227 | 224 |  	} | 
|---|
| 228 | 225 |   | 
|---|
| .. | .. | 
|---|
| 237 | 234 |   * sysctl_perf_event_max_contexts_per_stack. | 
|---|
| 238 | 235 |   */ | 
|---|
| 239 | 236 |  int perf_event_max_stack_handler(struct ctl_table *table, int write, | 
|---|
| 240 |  | -				 void __user *buffer, size_t *lenp, loff_t *ppos)  | 
|---|
 | 237 | +				 void *buffer, size_t *lenp, loff_t *ppos)  | 
|---|
| 241 | 238 |  { | 
|---|
| 242 | 239 |  	int *value = table->data; | 
|---|
| 243 | 240 |  	int new_value = *value, ret; | 
|---|