mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'perf-core-2025-09-26' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull performance events updates from Ingo Molnar:
"Core perf code updates:
- Convert mmap() related reference counts to refcount_t. This is in
reaction to the recently fixed refcount bugs, which could have been
detected earlier and could have mitigated the bug somewhat (Thomas
Gleixner, Peter Zijlstra)
- Clean up and simplify the callchain code, in preparation for
sframes (Steven Rostedt, Josh Poimboeuf)
Uprobes updates:
- Add support to optimize usdt probes on x86-64, which gives a
substantial speedup (Jiri Olsa)
- Cleanups and fixes on x86 (Peter Zijlstra)
PMU driver updates:
- Various optimizations and fixes to the Intel PMU driver (Dapeng Mi)
Misc cleanups and fixes:
- Remove redundant __GFP_NOWARN (Qianfeng Rong)"
* tag 'perf-core-2025-09-26' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (57 commits)
selftests/bpf: Fix uprobe_sigill test for uprobe syscall error value
uprobes/x86: Return error from uprobe syscall when not called from trampoline
perf: Skip user unwind if the task is a kernel thread
perf: Simplify get_perf_callchain() user logic
perf: Use current->flags & PF_KTHREAD|PF_USER_WORKER instead of current->mm == NULL
perf: Have get_perf_callchain() return NULL if crosstask and user are set
perf: Remove get_perf_callchain() init_nr argument
perf/x86: Print PMU counters bitmap in x86_pmu_show_pmu_cap()
perf/x86/intel: Add ICL_FIXED_0_ADAPTIVE bit into INTEL_FIXED_BITS_MASK
perf/x86/intel: Change macro GLOBAL_CTRL_EN_PERF_METRICS to BIT_ULL(48)
perf/x86: Add PERF_CAP_PEBS_TIMING_INFO flag
perf/x86/intel: Fix IA32_PMC_x_CFG_B MSRs access error
perf/x86/intel: Use early_initcall() to hook bts_init()
uprobes: Remove redundant __GFP_NOWARN
selftests/seccomp: validate uprobe syscall passes through seccomp
seccomp: passthrough uprobe systemcall without filtering
selftests/bpf: Fix uprobe syscall shadow stack test
selftests/bpf: Change test_uretprobe_regs_change for uprobe and uretprobe
selftests/bpf: Add uprobe_regs_equal test
selftests/bpf: Add optimized usdt variant for basic usdt test
...
This commit is contained in:
@@ -30,7 +30,7 @@ int set_swbp(struct arch_uprobe *auprobe, struct vm_area_struct *vma,
|
||||
unsigned long vaddr)
|
||||
{
|
||||
return uprobe_write_opcode(auprobe, vma, vaddr,
|
||||
__opcode_to_mem_arm(auprobe->bpinsn));
|
||||
__opcode_to_mem_arm(auprobe->bpinsn), true);
|
||||
}
|
||||
|
||||
bool arch_uprobe_ignore(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
||||
|
||||
@@ -345,6 +345,7 @@
|
||||
333 common io_pgetevents sys_io_pgetevents
|
||||
334 common rseq sys_rseq
|
||||
335 common uretprobe sys_uretprobe
|
||||
336 common uprobe sys_uprobe
|
||||
# don't use numbers 387 through 423, add new calls after the last
|
||||
# 'common' entry
|
||||
424 common pidfd_send_signal sys_pidfd_send_signal
|
||||
|
||||
@@ -2069,13 +2069,15 @@ static void _x86_pmu_read(struct perf_event *event)
|
||||
|
||||
void x86_pmu_show_pmu_cap(struct pmu *pmu)
|
||||
{
|
||||
pr_info("... version: %d\n", x86_pmu.version);
|
||||
pr_info("... bit width: %d\n", x86_pmu.cntval_bits);
|
||||
pr_info("... generic registers: %d\n", x86_pmu_num_counters(pmu));
|
||||
pr_info("... value mask: %016Lx\n", x86_pmu.cntval_mask);
|
||||
pr_info("... max period: %016Lx\n", x86_pmu.max_period);
|
||||
pr_info("... fixed-purpose events: %d\n", x86_pmu_num_counters_fixed(pmu));
|
||||
pr_info("... event mask: %016Lx\n", hybrid(pmu, intel_ctrl));
|
||||
pr_info("... version: %d\n", x86_pmu.version);
|
||||
pr_info("... bit width: %d\n", x86_pmu.cntval_bits);
|
||||
pr_info("... generic counters: %d\n", x86_pmu_num_counters(pmu));
|
||||
pr_info("... generic bitmap: %016llx\n", hybrid(pmu, cntr_mask64));
|
||||
pr_info("... fixed-purpose counters: %d\n", x86_pmu_num_counters_fixed(pmu));
|
||||
pr_info("... fixed-purpose bitmap: %016llx\n", hybrid(pmu, fixed_cntr_mask64));
|
||||
pr_info("... value mask: %016llx\n", x86_pmu.cntval_mask);
|
||||
pr_info("... max period: %016llx\n", x86_pmu.max_period);
|
||||
pr_info("... global_ctrl mask: %016llx\n", hybrid(pmu, intel_ctrl));
|
||||
}
|
||||
|
||||
static int __init init_hw_perf_events(void)
|
||||
|
||||
@@ -643,4 +643,4 @@ static __init int bts_init(void)
|
||||
|
||||
return perf_pmu_register(&bts_pmu, "intel_bts", -1);
|
||||
}
|
||||
arch_initcall(bts_init);
|
||||
early_initcall(bts_init);
|
||||
|
||||
@@ -2845,8 +2845,8 @@ static void intel_pmu_enable_fixed(struct perf_event *event)
|
||||
{
|
||||
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
u64 mask, bits = 0;
|
||||
int idx = hwc->idx;
|
||||
u64 bits = 0;
|
||||
|
||||
if (is_topdown_idx(idx)) {
|
||||
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
||||
@@ -2885,14 +2885,10 @@ static void intel_pmu_enable_fixed(struct perf_event *event)
|
||||
|
||||
idx -= INTEL_PMC_IDX_FIXED;
|
||||
bits = intel_fixed_bits_by_idx(idx, bits);
|
||||
mask = intel_fixed_bits_by_idx(idx, INTEL_FIXED_BITS_MASK);
|
||||
|
||||
if (x86_pmu.intel_cap.pebs_baseline && event->attr.precise_ip) {
|
||||
if (x86_pmu.intel_cap.pebs_baseline && event->attr.precise_ip)
|
||||
bits |= intel_fixed_bits_by_idx(idx, ICL_FIXED_0_ADAPTIVE);
|
||||
mask |= intel_fixed_bits_by_idx(idx, ICL_FIXED_0_ADAPTIVE);
|
||||
}
|
||||
|
||||
cpuc->fixed_ctrl_val &= ~mask;
|
||||
cpuc->fixed_ctrl_val &= ~intel_fixed_bits_by_idx(idx, INTEL_FIXED_BITS_MASK);
|
||||
cpuc->fixed_ctrl_val |= bits;
|
||||
}
|
||||
|
||||
@@ -2997,7 +2993,8 @@ static void intel_pmu_acr_late_setup(struct cpu_hw_events *cpuc)
|
||||
if (event->group_leader != leader->group_leader)
|
||||
break;
|
||||
for_each_set_bit(idx, (unsigned long *)&event->attr.config2, X86_PMC_IDX_MAX) {
|
||||
if (WARN_ON_ONCE(i + idx > cpuc->n_events))
|
||||
if (i + idx >= cpuc->n_events ||
|
||||
!is_acr_event_group(cpuc->event_list[i + idx]))
|
||||
return;
|
||||
__set_bit(cpuc->assign[i + idx], (unsigned long *)&event->hw.config1);
|
||||
}
|
||||
@@ -5318,9 +5315,9 @@ static void intel_pmu_check_hybrid_pmus(struct x86_hybrid_pmu *pmu)
|
||||
0, x86_pmu_num_counters(&pmu->pmu), 0, 0);
|
||||
|
||||
if (pmu->intel_cap.perf_metrics)
|
||||
pmu->intel_ctrl |= 1ULL << GLOBAL_CTRL_EN_PERF_METRICS;
|
||||
pmu->intel_ctrl |= GLOBAL_CTRL_EN_PERF_METRICS;
|
||||
else
|
||||
pmu->intel_ctrl &= ~(1ULL << GLOBAL_CTRL_EN_PERF_METRICS);
|
||||
pmu->intel_ctrl &= ~GLOBAL_CTRL_EN_PERF_METRICS;
|
||||
|
||||
intel_pmu_check_event_constraints(pmu->event_constraints,
|
||||
pmu->cntr_mask64,
|
||||
@@ -5455,7 +5452,7 @@ static void intel_pmu_cpu_starting(int cpu)
|
||||
rdmsrq(MSR_IA32_PERF_CAPABILITIES, perf_cap.capabilities);
|
||||
if (!perf_cap.perf_metrics) {
|
||||
x86_pmu.intel_cap.perf_metrics = 0;
|
||||
x86_pmu.intel_ctrl &= ~(1ULL << GLOBAL_CTRL_EN_PERF_METRICS);
|
||||
x86_pmu.intel_ctrl &= ~GLOBAL_CTRL_EN_PERF_METRICS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7789,7 +7786,7 @@ __init int intel_pmu_init(void)
|
||||
}
|
||||
|
||||
if (!is_hybrid() && x86_pmu.intel_cap.perf_metrics)
|
||||
x86_pmu.intel_ctrl |= 1ULL << GLOBAL_CTRL_EN_PERF_METRICS;
|
||||
x86_pmu.intel_ctrl |= GLOBAL_CTRL_EN_PERF_METRICS;
|
||||
|
||||
if (x86_pmu.intel_cap.pebs_timing_info)
|
||||
x86_pmu.flags |= PMU_FL_RETIRE_LATENCY;
|
||||
|
||||
@@ -315,12 +315,14 @@
|
||||
#define PERF_CAP_PT_IDX 16
|
||||
|
||||
#define MSR_PEBS_LD_LAT_THRESHOLD 0x000003f6
|
||||
#define PERF_CAP_PEBS_TRAP BIT_ULL(6)
|
||||
#define PERF_CAP_ARCH_REG BIT_ULL(7)
|
||||
#define PERF_CAP_PEBS_FORMAT 0xf00
|
||||
#define PERF_CAP_PEBS_BASELINE BIT_ULL(14)
|
||||
#define PERF_CAP_PEBS_MASK (PERF_CAP_PEBS_TRAP | PERF_CAP_ARCH_REG | \
|
||||
PERF_CAP_PEBS_FORMAT | PERF_CAP_PEBS_BASELINE)
|
||||
#define PERF_CAP_PEBS_TRAP BIT_ULL(6)
|
||||
#define PERF_CAP_ARCH_REG BIT_ULL(7)
|
||||
#define PERF_CAP_PEBS_FORMAT 0xf00
|
||||
#define PERF_CAP_PEBS_BASELINE BIT_ULL(14)
|
||||
#define PERF_CAP_PEBS_TIMING_INFO BIT_ULL(17)
|
||||
#define PERF_CAP_PEBS_MASK (PERF_CAP_PEBS_TRAP | PERF_CAP_ARCH_REG | \
|
||||
PERF_CAP_PEBS_FORMAT | PERF_CAP_PEBS_BASELINE | \
|
||||
PERF_CAP_PEBS_TIMING_INFO)
|
||||
|
||||
#define MSR_IA32_RTIT_CTL 0x00000570
|
||||
#define RTIT_CTL_TRACEEN BIT(0)
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#define ARCH_PERFMON_EVENTSEL_EQ (1ULL << 36)
|
||||
#define ARCH_PERFMON_EVENTSEL_UMASK2 (0xFFULL << 40)
|
||||
|
||||
#define INTEL_FIXED_BITS_MASK 0xFULL
|
||||
#define INTEL_FIXED_BITS_STRIDE 4
|
||||
#define INTEL_FIXED_0_KERNEL (1ULL << 0)
|
||||
#define INTEL_FIXED_0_USER (1ULL << 1)
|
||||
@@ -48,6 +47,11 @@
|
||||
#define ICL_EVENTSEL_ADAPTIVE (1ULL << 34)
|
||||
#define ICL_FIXED_0_ADAPTIVE (1ULL << 32)
|
||||
|
||||
#define INTEL_FIXED_BITS_MASK \
|
||||
(INTEL_FIXED_0_KERNEL | INTEL_FIXED_0_USER | \
|
||||
INTEL_FIXED_0_ANYTHREAD | INTEL_FIXED_0_ENABLE_PMI | \
|
||||
ICL_FIXED_0_ADAPTIVE)
|
||||
|
||||
#define intel_fixed_bits_by_idx(_idx, _bits) \
|
||||
((_bits) << ((_idx) * INTEL_FIXED_BITS_STRIDE))
|
||||
|
||||
@@ -430,7 +434,7 @@ static inline bool is_topdown_idx(int idx)
|
||||
#define GLOBAL_STATUS_TRACE_TOPAPMI BIT_ULL(GLOBAL_STATUS_TRACE_TOPAPMI_BIT)
|
||||
#define GLOBAL_STATUS_PERF_METRICS_OVF_BIT 48
|
||||
|
||||
#define GLOBAL_CTRL_EN_PERF_METRICS 48
|
||||
#define GLOBAL_CTRL_EN_PERF_METRICS BIT_ULL(48)
|
||||
/*
|
||||
* We model guest LBR event tracing as another fixed-mode PMC like BTS.
|
||||
*
|
||||
|
||||
@@ -23,6 +23,8 @@ int setup_signal_shadow_stack(struct ksignal *ksig);
|
||||
int restore_signal_shadow_stack(void);
|
||||
int shstk_update_last_frame(unsigned long val);
|
||||
bool shstk_is_enabled(void);
|
||||
int shstk_pop(u64 *val);
|
||||
int shstk_push(u64 val);
|
||||
#else
|
||||
static inline long shstk_prctl(struct task_struct *task, int option,
|
||||
unsigned long arg2) { return -EINVAL; }
|
||||
@@ -35,6 +37,8 @@ static inline int setup_signal_shadow_stack(struct ksignal *ksig) { return 0; }
|
||||
static inline int restore_signal_shadow_stack(void) { return 0; }
|
||||
static inline int shstk_update_last_frame(unsigned long val) { return 0; }
|
||||
static inline bool shstk_is_enabled(void) { return false; }
|
||||
static inline int shstk_pop(u64 *val) { return -ENOTSUPP; }
|
||||
static inline int shstk_push(u64 val) { return -ENOTSUPP; }
|
||||
#endif /* CONFIG_X86_USER_SHADOW_STACK */
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
@@ -20,6 +20,11 @@ typedef u8 uprobe_opcode_t;
|
||||
#define UPROBE_SWBP_INSN 0xcc
|
||||
#define UPROBE_SWBP_INSN_SIZE 1
|
||||
|
||||
enum {
|
||||
ARCH_UPROBE_FLAG_CAN_OPTIMIZE = 0,
|
||||
ARCH_UPROBE_FLAG_OPTIMIZE_FAIL = 1,
|
||||
};
|
||||
|
||||
struct uprobe_xol_ops;
|
||||
|
||||
struct arch_uprobe {
|
||||
@@ -45,6 +50,8 @@ struct arch_uprobe {
|
||||
u8 ilen;
|
||||
} push;
|
||||
};
|
||||
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
struct arch_uprobe_task {
|
||||
|
||||
@@ -246,6 +246,46 @@ static unsigned long get_user_shstk_addr(void)
|
||||
return ssp;
|
||||
}
|
||||
|
||||
int shstk_pop(u64 *val)
|
||||
{
|
||||
int ret = 0;
|
||||
u64 ssp;
|
||||
|
||||
if (!features_enabled(ARCH_SHSTK_SHSTK))
|
||||
return -ENOTSUPP;
|
||||
|
||||
fpregs_lock_and_load();
|
||||
|
||||
rdmsrq(MSR_IA32_PL3_SSP, ssp);
|
||||
if (val && get_user(*val, (__user u64 *)ssp))
|
||||
ret = -EFAULT;
|
||||
else
|
||||
wrmsrq(MSR_IA32_PL3_SSP, ssp + SS_FRAME_SIZE);
|
||||
fpregs_unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int shstk_push(u64 val)
|
||||
{
|
||||
u64 ssp;
|
||||
int ret;
|
||||
|
||||
if (!features_enabled(ARCH_SHSTK_SHSTK))
|
||||
return -ENOTSUPP;
|
||||
|
||||
fpregs_lock_and_load();
|
||||
|
||||
rdmsrq(MSR_IA32_PL3_SSP, ssp);
|
||||
ssp -= SS_FRAME_SIZE;
|
||||
ret = write_user_shstk_64((__user void *)ssp, val);
|
||||
if (!ret)
|
||||
wrmsrq(MSR_IA32_PL3_SSP, ssp);
|
||||
fpregs_unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define SHSTK_DATA_BIT BIT(63)
|
||||
|
||||
static int put_shstk_data(u64 __user *addr, u64 data)
|
||||
|
||||
+613
-22
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -13,7 +13,7 @@
|
||||
#define MSR_IA32_MISC_ENABLE_PMU_RO_MASK (MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL | \
|
||||
MSR_IA32_MISC_ENABLE_BTS_UNAVAIL)
|
||||
|
||||
/* retrieve the 4 bits for EN and PMI out of IA32_FIXED_CTR_CTRL */
|
||||
/* retrieve a fixed counter bits out of IA32_FIXED_CTR_CTRL */
|
||||
#define fixed_ctrl_field(ctrl_reg, idx) \
|
||||
(((ctrl_reg) >> ((idx) * INTEL_FIXED_BITS_STRIDE)) & INTEL_FIXED_BITS_MASK)
|
||||
|
||||
|
||||
@@ -859,7 +859,7 @@ struct perf_event {
|
||||
|
||||
/* mmap bits */
|
||||
struct mutex mmap_mutex;
|
||||
atomic_t mmap_count;
|
||||
refcount_t mmap_count;
|
||||
|
||||
struct perf_buffer *rb;
|
||||
struct list_head rb_entry;
|
||||
@@ -1719,7 +1719,7 @@ DECLARE_PER_CPU(struct perf_callchain_entry, perf_callchain_entry);
|
||||
extern void perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs);
|
||||
extern void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs);
|
||||
extern struct perf_callchain_entry *
|
||||
get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user,
|
||||
get_perf_callchain(struct pt_regs *regs, bool kernel, bool user,
|
||||
u32 max_stack, bool crosstask, bool add_mark);
|
||||
extern int get_callchain_buffers(int max_stack);
|
||||
extern void put_callchain_buffers(void);
|
||||
|
||||
@@ -1005,6 +1005,8 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
|
||||
|
||||
asmlinkage long sys_uretprobe(void);
|
||||
|
||||
asmlinkage long sys_uprobe(void);
|
||||
|
||||
/* pciconfig: alpha, arm, arm64, ia64, sparc */
|
||||
asmlinkage long sys_pciconfig_read(unsigned long bus, unsigned long dfn,
|
||||
unsigned long off, unsigned long len,
|
||||
|
||||
+18
-2
@@ -17,6 +17,7 @@
|
||||
#include <linux/wait.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/seqlock.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
struct uprobe;
|
||||
struct vm_area_struct;
|
||||
@@ -185,8 +186,14 @@ struct xol_area;
|
||||
|
||||
struct uprobes_state {
|
||||
struct xol_area *xol_area;
|
||||
#ifdef CONFIG_X86_64
|
||||
struct hlist_head head_tramps;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef int (*uprobe_write_verify_t)(struct page *page, unsigned long vaddr,
|
||||
uprobe_opcode_t *insn, int nbytes, void *data);
|
||||
|
||||
extern void __init uprobes_init(void);
|
||||
extern int set_swbp(struct arch_uprobe *aup, struct vm_area_struct *vma, unsigned long vaddr);
|
||||
extern int set_orig_insn(struct arch_uprobe *aup, struct vm_area_struct *vma, unsigned long vaddr);
|
||||
@@ -194,7 +201,11 @@ extern bool is_swbp_insn(uprobe_opcode_t *insn);
|
||||
extern bool is_trap_insn(uprobe_opcode_t *insn);
|
||||
extern unsigned long uprobe_get_swbp_addr(struct pt_regs *regs);
|
||||
extern unsigned long uprobe_get_trap_addr(struct pt_regs *regs);
|
||||
extern int uprobe_write_opcode(struct arch_uprobe *auprobe, struct vm_area_struct *vma, unsigned long vaddr, uprobe_opcode_t);
|
||||
extern int uprobe_write_opcode(struct arch_uprobe *auprobe, struct vm_area_struct *vma, unsigned long vaddr, uprobe_opcode_t,
|
||||
bool is_register);
|
||||
extern int uprobe_write(struct arch_uprobe *auprobe, struct vm_area_struct *vma, const unsigned long opcode_vaddr,
|
||||
uprobe_opcode_t *insn, int nbytes, uprobe_write_verify_t verify, bool is_register, bool do_update_ref_ctr,
|
||||
void *data);
|
||||
extern struct uprobe *uprobe_register(struct inode *inode, loff_t offset, loff_t ref_ctr_offset, struct uprobe_consumer *uc);
|
||||
extern int uprobe_apply(struct uprobe *uprobe, struct uprobe_consumer *uc, bool);
|
||||
extern void uprobe_unregister_nosync(struct uprobe *uprobe, struct uprobe_consumer *uc);
|
||||
@@ -224,8 +235,13 @@ extern bool arch_uprobe_ignore(struct arch_uprobe *aup, struct pt_regs *regs);
|
||||
extern void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
|
||||
void *src, unsigned long len);
|
||||
extern void uprobe_handle_trampoline(struct pt_regs *regs);
|
||||
extern void *arch_uprobe_trampoline(unsigned long *psize);
|
||||
extern void *arch_uretprobe_trampoline(unsigned long *psize);
|
||||
extern unsigned long uprobe_get_trampoline_vaddr(void);
|
||||
extern void uprobe_copy_from_page(struct page *page, unsigned long vaddr, void *dst, int len);
|
||||
extern void arch_uprobe_clear_state(struct mm_struct *mm);
|
||||
extern void arch_uprobe_init_state(struct mm_struct *mm);
|
||||
extern void handle_syscall_uprobe(struct pt_regs *regs, unsigned long bp_vaddr);
|
||||
extern void arch_uprobe_optimize(struct arch_uprobe *auprobe, unsigned long vaddr);
|
||||
#else /* !CONFIG_UPROBES */
|
||||
struct uprobes_state {
|
||||
};
|
||||
|
||||
@@ -314,7 +314,7 @@ BPF_CALL_3(bpf_get_stackid, struct pt_regs *, regs, struct bpf_map *, map,
|
||||
if (max_depth > sysctl_perf_event_max_stack)
|
||||
max_depth = sysctl_perf_event_max_stack;
|
||||
|
||||
trace = get_perf_callchain(regs, 0, kernel, user, max_depth,
|
||||
trace = get_perf_callchain(regs, kernel, user, max_depth,
|
||||
false, false);
|
||||
|
||||
if (unlikely(!trace))
|
||||
@@ -451,7 +451,7 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task,
|
||||
else if (kernel && task)
|
||||
trace = get_callchain_entry_for_task(task, max_depth);
|
||||
else
|
||||
trace = get_perf_callchain(regs, 0, kernel, user, max_depth,
|
||||
trace = get_perf_callchain(regs, kernel, user, max_depth,
|
||||
crosstask, false);
|
||||
|
||||
if (unlikely(!trace) || trace->nr < skip) {
|
||||
|
||||
+20
-22
@@ -217,22 +217,26 @@ static void fixup_uretprobe_trampoline_entries(struct perf_callchain_entry *entr
|
||||
}
|
||||
|
||||
struct perf_callchain_entry *
|
||||
get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user,
|
||||
get_perf_callchain(struct pt_regs *regs, bool kernel, bool user,
|
||||
u32 max_stack, bool crosstask, bool add_mark)
|
||||
{
|
||||
struct perf_callchain_entry *entry;
|
||||
struct perf_callchain_entry_ctx ctx;
|
||||
int rctx, start_entry_idx;
|
||||
|
||||
/* crosstask is not supported for user stacks */
|
||||
if (crosstask && user && !kernel)
|
||||
return NULL;
|
||||
|
||||
entry = get_callchain_entry(&rctx);
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
ctx.entry = entry;
|
||||
ctx.max_stack = max_stack;
|
||||
ctx.nr = entry->nr = init_nr;
|
||||
ctx.contexts = 0;
|
||||
ctx.contexts_maxed = false;
|
||||
ctx.entry = entry;
|
||||
ctx.max_stack = max_stack;
|
||||
ctx.nr = entry->nr = 0;
|
||||
ctx.contexts = 0;
|
||||
ctx.contexts_maxed = false;
|
||||
|
||||
if (kernel && !user_mode(regs)) {
|
||||
if (add_mark)
|
||||
@@ -240,25 +244,19 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user,
|
||||
perf_callchain_kernel(&ctx, regs);
|
||||
}
|
||||
|
||||
if (user) {
|
||||
if (user && !crosstask) {
|
||||
if (!user_mode(regs)) {
|
||||
if (current->mm)
|
||||
regs = task_pt_regs(current);
|
||||
else
|
||||
regs = NULL;
|
||||
}
|
||||
|
||||
if (regs) {
|
||||
if (crosstask)
|
||||
if (current->flags & (PF_KTHREAD | PF_USER_WORKER))
|
||||
goto exit_put;
|
||||
|
||||
if (add_mark)
|
||||
perf_callchain_store_context(&ctx, PERF_CONTEXT_USER);
|
||||
|
||||
start_entry_idx = entry->nr;
|
||||
perf_callchain_user(&ctx, regs);
|
||||
fixup_uretprobe_trampoline_entries(entry, start_entry_idx);
|
||||
regs = task_pt_regs(current);
|
||||
}
|
||||
|
||||
if (add_mark)
|
||||
perf_callchain_store_context(&ctx, PERF_CONTEXT_USER);
|
||||
|
||||
start_entry_idx = entry->nr;
|
||||
perf_callchain_user(&ctx, regs);
|
||||
fixup_uretprobe_trampoline_entries(entry, start_entry_idx);
|
||||
}
|
||||
|
||||
exit_put:
|
||||
|
||||
+217
-204
File diff suppressed because it is too large
Load Diff
@@ -35,7 +35,7 @@ struct perf_buffer {
|
||||
spinlock_t event_lock;
|
||||
struct list_head event_list;
|
||||
|
||||
atomic_t mmap_count;
|
||||
refcount_t mmap_count;
|
||||
unsigned long mmap_locked;
|
||||
struct user_struct *mmap_user;
|
||||
|
||||
@@ -47,7 +47,7 @@ struct perf_buffer {
|
||||
unsigned long aux_pgoff;
|
||||
int aux_nr_pages;
|
||||
int aux_overwrite;
|
||||
atomic_t aux_mmap_count;
|
||||
refcount_t aux_mmap_count;
|
||||
unsigned long aux_mmap_locked;
|
||||
void (*free_aux)(void *);
|
||||
refcount_t aux_refcount;
|
||||
|
||||
@@ -400,7 +400,7 @@ void *perf_aux_output_begin(struct perf_output_handle *handle,
|
||||
* the same order, see perf_mmap_close. Otherwise we end up freeing
|
||||
* aux pages in this path, which is a bug, because in_atomic().
|
||||
*/
|
||||
if (!atomic_read(&rb->aux_mmap_count))
|
||||
if (!refcount_read(&rb->aux_mmap_count))
|
||||
goto err;
|
||||
|
||||
if (!refcount_inc_not_zero(&rb->aux_refcount))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user