| .. | .. |
|---|
| 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; |
|---|