android_kernel_xiaomi_sm8350/kernel/trace/trace_event_perf.c
Greg Kroah-Hartman ad8d63bdc6 Merge 5.4.287 into android11-5.4-lts
Changes in 5.4.287
	netlink: terminate outstanding dump on socket close
	net/mlx5: fs, lock FTE when checking if active
	net/mlx5e: kTLS, Fix incorrect page refcounting
	ocfs2: uncache inode which has failed entering the group
	KVM: VMX: Bury Intel PT virtualization (guest/host mode) behind CONFIG_BROKEN
	nilfs2: fix null-ptr-deref in block_touch_buffer tracepoint
	ocfs2: fix UBSAN warning in ocfs2_verify_volume()
	nilfs2: fix null-ptr-deref in block_dirty_buffer tracepoint
	Revert "mmc: dw_mmc: Fix IDMAC operation with pages bigger than 4K"
	media: dvbdev: fix the logic when DVB_DYNAMIC_MINORS is not set
	kbuild: Use uname for LINUX_COMPILE_HOST detection
	mm: revert "mm: shmem: fix data-race in shmem_getattr()"
	ASoC: Intel: bytcr_rt5640: Add DMI quirk for Vexia Edu Atla 10 tablet
	mac80211: fix user-power when emulating chanctx
	selftests/watchdog-test: Fix system accidentally reset after watchdog-test
	ALSA: hda/realtek: Add subwoofer quirk for Infinix ZERO BOOK 13
	x86/amd_nb: Fix compile-testing without CONFIG_AMD_NB
	net: usb: qmi_wwan: add Quectel RG650V
	soc: qcom: Add check devm_kasprintf() returned value
	regulator: rk808: Add apply_bit for BUCK3 on RK809
	ASoC: stm: Prevent potential division by zero in stm32_sai_mclk_round_rate()
	ASoC: stm: Prevent potential division by zero in stm32_sai_get_clk_div()
	proc/softirqs: replace seq_printf with seq_put_decimal_ull_width
	ipmr: Fix access to mfc_cache_list without lock held
	cifs: Fix buffer overflow when parsing NFS reparse points
	NFSD: Force all NFSv4.2 COPY requests to be synchronous
	nvme: fix metadata handling in nvme-passthrough
	x86/xen/pvh: Annotate indirect branch as safe
	mips: asm: fix warning when disabling MIPS_FP_SUPPORT
	initramfs: avoid filename buffer overrun
	nvme-pci: fix freeing of the HMB descriptor table
	m68k: mvme147: Fix SCSI controller IRQ numbers
	m68k: mvme16x: Add and use "mvme16x.h"
	m68k: mvme147: Reinstate early console
	acpi/arm64: Adjust error handling procedure in gtdt_parse_timer_block()
	s390/syscalls: Avoid creation of arch/arch/ directory
	hfsplus: don't query the device logical block size multiple times
	firmware: google: Unregister driver_info on failure and exit in gsmi
	firmware: google: Unregister driver_info on failure
	EDAC/bluefield: Fix potential integer overflow
	EDAC/fsl_ddr: Fix bad bit shift operations
	crypto: pcrypt - Call crypto layer directly when padata_do_parallel() return -EBUSY
	crypto: cavium - Fix the if condition to exit loop after timeout
	crypto: bcm - add error check in the ahash_hmac_init function
	crypto: cavium - Fix an error handling path in cpt_ucode_load_fw()
	time: Fix references to _msecs_to_jiffies() handling of values
	soc: ti: smartreflex: Use IRQF_NO_AUTOEN flag in request_irq()
	soc: qcom: geni-se: fix array underflow in geni_se_clk_tbl_get()
	mmc: mmc_spi: drop buggy snprintf()
	efi/tpm: Pass correct address to memblock_reserve
	tpm: fix signed/unsigned bug when checking event logs
	ARM: dts: cubieboard4: Fix DCDC5 regulator constraints
	regmap: irq: Set lockdep class for hierarchical IRQ domains
	firmware: arm_scpi: Check the DVFS OPP count returned by the firmware
	drm/mm: Mark drm_mm_interval_tree*() functions with __maybe_unused
	wifi: ath9k: add range check for conn_rsp_epid in htc_connect_service()
	drm/omap: Fix locking in omap_gem_new_dmabuf()
	wifi: p54: Use IRQF_NO_AUTOEN flag in request_irq()
	wifi: mwifiex: Use IRQF_NO_AUTOEN flag in request_irq()
	drm/imx/ipuv3: Use IRQF_NO_AUTOEN flag in request_irq()
	dt-bindings: vendor-prefixes: Add NeoFidelity, Inc
	ASoC: fsl_micfil: Drop unnecessary register read
	ASoC: fsl_micfil: do not define SHIFT/MASK for single bits
	ASoC: fsl_micfil: use GENMASK to define register bit fields
	ASoC: fsl_micfil: fix regmap_write_bits usage
	bpf: Fix the xdp_adjust_tail sample prog issue
	wifi: mwifiex: Fix memcpy() field-spanning write warning in mwifiex_config_scan()
	drm/panfrost: Remove unused id_mask from struct panfrost_model
	drm/msm/adreno: Use IRQF_NO_AUTOEN flag in request_irq()
	drm/etnaviv: dump: fix sparse warnings
	drm/etnaviv: fix power register offset on GC300
	drm/etnaviv: hold GPU lock across perfmon sampling
	bpf, sockmap: Several fixes to bpf_msg_push_data
	bpf, sockmap: Several fixes to bpf_msg_pop_data
	bpf, sockmap: Fix sk_msg_reset_curr
	selftests: net: really check for bg process completion
	net: rfkill: gpio: Add check for clk_enable()
	ALSA: us122l: Use snd_card_free_when_closed() at disconnection
	ALSA: caiaq: Use snd_card_free_when_closed() at disconnection
	ALSA: 6fire: Release resources at card release
	netpoll: Use rcu_access_pointer() in netpoll_poll_lock
	trace/trace_event_perf: remove duplicate samples on the first tracepoint event
	powerpc/vdso: Flag VDSO64 entry points as functions
	mfd: tps65010: Use IRQF_NO_AUTOEN flag in request_irq() to fix race
	mfd: da9052-spi: Change read-mask to write-mask
	mfd: intel_soc_pmic_bxtwc: Use dev_err_probe()
	mfd: intel_soc_pmic_bxtwc: Use IRQ domain for USB Type-C device
	mfd: intel_soc_pmic_bxtwc: Use IRQ domain for TMU device
	mfd: intel_soc_pmic_bxtwc: Use IRQ domain for PMIC devices
	cpufreq: loongson2: Unregister platform_driver on failure
	mtd: rawnand: atmel: Fix possible memory leak
	RDMA/bnxt_re: Check cqe flags to know imm_data vs inv_irkey
	mfd: rt5033: Fix missing regmap_del_irq_chip()
	scsi: bfa: Fix use-after-free in bfad_im_module_exit()
	scsi: fusion: Remove unused variable 'rc'
	scsi: qedf: Fix a possible memory leak in qedf_alloc_and_init_sb()
	scsi: qedi: Fix a possible memory leak in qedi_alloc_and_init_sb()
	ocfs2: fix uninitialized value in ocfs2_file_read_iter()
	powerpc/sstep: make emulate_vsx_load and emulate_vsx_store static
	fbdev/sh7760fb: Alloc DMA memory from hardware device
	fbdev: sh7760fb: Fix a possible memory leak in sh7760fb_alloc_mem()
	dt-bindings: clock: adi,axi-clkgen: convert old binding to yaml format
	dt-bindings: clock: axi-clkgen: include AXI clk
	clk: axi-clkgen: use devm_platform_ioremap_resource() short-hand
	clk: clk-axi-clkgen: make sure to enable the AXI bus clock
	perf cs-etm: Don't flush when packet_queue fills up
	perf probe: Correct demangled symbols in C++ program
	PCI: cpqphp: Use PCI_POSSIBLE_ERROR() to check config reads
	PCI: cpqphp: Fix PCIBIOS_* return value confusion
	m68k: mcfgpio: Fix incorrect register offset for CONFIG_M5441x
	m68k: coldfire/device.c: only build FEC when HW macros are defined
	perf trace: Do not lose last events in a race
	perf trace: Avoid garbage when not printing a syscall's arguments
	rpmsg: glink: Add TX_DATA_CONT command while sending
	rpmsg: glink: Send READ_NOTIFY command in FIFO full case
	rpmsg: glink: Fix GLINK command prefix
	rpmsg: glink: use only lower 16-bits of param2 for CMD_OPEN name length
	NFSD: Prevent NULL dereference in nfsd4_process_cb_update()
	NFSD: Cap the number of bytes copied by nfs4_reset_recoverydir()
	NFSD: Fix nfsd4_shutdown_copy()
	vfio/pci: Properly hide first-in-list PCIe extended capability
	power: supply: core: Remove might_sleep() from power_supply_put()
	net: usb: lan78xx: Fix memory leak on device unplug by freeing PHY device
	tg3: Set coherent DMA mask bits to 31 for BCM57766 chipsets
	net: usb: lan78xx: Fix refcounting and autosuspend on invalid WoL configuration
	marvell: pxa168_eth: fix call balance of pep->clk handling routines
	net: stmmac: dwmac-socfpga: Set RX watchdog interrupt as broken
	ipmr: convert /proc handlers to rcu_read_lock()
	ipmr: fix tables suspicious RCU usage
	usb: using mutex lock and supporting O_NONBLOCK flag in iowarrior_read()
	usb: yurex: make waiting on yurex_write interruptible
	USB: chaoskey: fail open after removal
	USB: chaoskey: Fix possible deadlock chaoskey_list_lock
	misc: apds990x: Fix missing pm_runtime_disable()
	staging: greybus: uart: clean up TIOCGSERIAL
	apparmor: fix 'Do simple duplicate message elimination'
	usb: ehci-spear: fix call balance of sehci clk handling routines
	cgroup: Make operations on the cgroup root_list RCU safe
	cgroup: Move rcu_head up near the top of cgroup_root
	soc: qcom: socinfo: fix revision check in qcom_socinfo_probe()
	ALSA: usb-audio: Fix potential out-of-bound accesses for Extigy and Mbox devices
	ext4: supress data-race warnings in ext4_free_inodes_{count,set}()
	ext4: fix FS_IOC_GETFSMAP handling
	jfs: xattr: check invalid xattr size more strictly
	ASoC: codecs: Fix atomicity violation in snd_soc_component_get_drvdata()
	PCI: Fix use-after-free of slot->bus on hot remove
	comedi: Flush partial mappings in error case
	tty: ldsic: fix tty_ldisc_autoload sysctl's proc_handler
	Bluetooth: Fix type of len in rfcomm_sock_getsockopt{,_old}()
	Revert "usb: gadget: composite: fix OS descriptors w_value logic"
	serial: sh-sci: Clean sci_ports[0] after at earlycon exit
	Revert "serial: sh-sci: Clean sci_ports[0] after at earlycon exit"
	netfilter: ipset: add missing range check in bitmap_ip_uadt
	spi: Fix acpi deferred irq probe
	ubi: wl: Put source PEB into correct list if trying locking LEB failed
	um: ubd: Do not use drvdata in release
	um: net: Do not use drvdata in release
	serial: 8250: omap: Move pm_runtime_get_sync
	um: vector: Do not use drvdata in release
	sh: cpuinfo: Fix a warning for CONFIG_CPUMASK_OFFSTACK
	arm64: tls: Fix context-switching of tpidrro_el0 when kpti is enabled
	block: fix ordering between checking BLK_MQ_S_STOPPED request adding
	HID: wacom: Interpret tilt data from Intuos Pro BT as signed values
	media: wl128x: Fix atomicity violation in fmc_send_cmd()
	ALSA: hda/realtek: Update ALC225 depop procedure
	ALSA: hda/realtek: Set PCBeep to default value for ALC274
	ALSA: hda/realtek: Fix Internal Speaker and Mic boost of Infinix Y4 Max
	ALSA: hda/realtek: Apply quirk for Medion E15433
	usb: dwc3: gadget: Fix checking for number of TRBs left
	lib: string_helpers: silence snprintf() output truncation warning
	NFSD: Prevent a potential integer overflow
	SUNRPC: make sure cache entry active before cache_show
	rpmsg: glink: Propagate TX failures in intentless mode as well
	um: Fix potential integer overflow during physmem setup
	um: Fix the return value of elf_core_copy_task_fpregs
	um/sysrq: remove needless variable sp
	um: add show_stack_loglvl()
	um: Clean up stacktrace dump
	um: Always dump trace for specified task in show_stack
	NFSv4.0: Fix a use-after-free problem in the asynchronous open()
	rtc: st-lpc: Use IRQF_NO_AUTOEN flag in request_irq()
	rtc: abx80x: Fix WDT bit position of the status register
	rtc: check if __rtc_read_time was successful in rtc_timer_do_work()
	ubifs: Correct the total block count by deducting journal reservation
	ubi: fastmap: Fix duplicate slab cache names while attaching
	ubifs: authentication: Fix use-after-free in ubifs_tnc_end_commit
	jffs2: fix use of uninitialized variable
	block: return unsigned int from bdev_io_min
	9p/xen: fix init sequence
	9p/xen: fix release of IRQ
	rtc: ab-eoz9: don't fail temperature reads on undervoltage notification
	modpost: remove incorrect code in do_eisa_entry()
	SUNRPC: correct error code comment in xs_tcp_setup_socket()
	SUNRPC: Replace internal use of SOCKWQ_ASYNC_NOSPACE
	sunrpc: clear XPRT_SOCK_UPD_TIMEOUT when reset transport
	sh: intc: Fix use-after-free bug in register_intc_controller()
	ASoC: fsl_micfil: fix the naming style for mask definition
	quota: flush quota_release_work upon quota writeback
	btrfs: ref-verify: fix use-after-free after invalid ref action
	media: i2c: tc358743: Fix crash in the probe error path when using polling
	media: ts2020: fix null-ptr-deref in ts2020_probe()
	media: venus: Fix pm_runtime_set_suspended() with runtime pm enabled
	media: gspca: ov534-ov772x: Fix off-by-one error in set_frame_rate()
	media: platform: allegro-dvt: Fix possible memory leak in allocate_buffers_internal()
	ovl: Filter invalid inodes with missing lookup function
	ftrace: Fix regression with module command in stack_trace_filter
	clk: qcom: gcc-qcs404: fix initial rate of GPLL3
	ad7780: fix division by zero in ad7780_write_raw()
	util_macros.h: fix/rework find_closest() macros
	i3c: master: Fix miss free init_dyn_addr at i3c_master_put_i3c_addrs()
	dm thin: Add missing destroy_work_on_stack()
	nfsd: make sure exp active before svc_export_show
	nfsd: fix nfs4_openowner leak when concurrent nfsd4_open occur
	drm/etnaviv: flush shader L1 cache after user commandstream
	iTCO_wdt: mask NMI_NOW bit for update_no_reboot_bit() call
	watchdog: mediatek: Make sure system reset gets asserted in mtk_wdt_restart()
	can: sun4i_can: sun4i_can_err(): call can_change_state() even if cf is NULL
	can: sun4i_can: sun4i_can_err(): fix {rx,tx}_errors statistics
	ipvs: fix UB due to uninitialized stack access in ip_vs_protocol_init()
	netfilter: x_tables: fix LED ID check in led_tg_check()
	net/sched: tbf: correct backlog statistic for GSO packets
	can: j1939: j1939_session_new(): fix skb reference counting
	net/ipv6: release expired exception dst cached in socket
	dccp: Fix memory leak in dccp_feat_change_recv
	tipc: add reference counter to bearer
	tipc: enable creating a "preliminary" node
	tipc: add new AEAD key structure for user API
	tipc: Fix use-after-free of kernel socket in cleanup_bearer().
	net/qed: allow old cards not supporting "num_images" to work
	igb: Fix potential invalid memory access in igb_init_module()
	netfilter: ipset: Hold module reference while requesting a module
	netfilter: nft_set_hash: skip duplicated elements pending gc run
	xen/xenbus: reference count registered modules
	xenbus/backend: Add memory pressure handler callback
	xenbus/backend: Protect xenbus callback with lock
	xen/xenbus: fix locking
	xen: Fix the issue of resource not being properly released in xenbus_dev_probe()
	x86/asm: Reorder early variables
	crypto: x86/aegis128 - access 32-bit arguments as 32-bit
	gpio: grgpio: use a helper variable to store the address of ofdev->dev
	gpio: grgpio: Add NULL check in grgpio_probe
	drm/sti: Add __iomem for mixer_dbg_mxn's parameter
	tcp_bpf: Fix the sk_mem_uncharge logic in tcp_bpf_sendmsg
	spi: mpc52xx: Add cancel_work_sync before module remove
	ocfs2: free inode when ocfs2_get_init_inode() fails
	bpf: Handle BPF_EXIST and BPF_NOEXIST for LPM trie
	bpf: Fix exact match conditions in trie_get_next_key()
	HID: wacom: fix when get product name maybe null pointer
	tracing: Fix cmp_entries_dup() to respect sort() comparison rules
	ocfs2: update seq_file index in ocfs2_dlm_seq_next
	scsi: qla2xxx: Fix NVMe and NPIV connect issue
	scsi: qla2xxx: Supported speed displayed incorrectly for VPorts
	scsi: qla2xxx: Remove check req_sg_cnt should be equal to rsp_sg_cnt
	nilfs2: fix potential out-of-bounds memory access in nilfs_find_entry()
	bcache: revert replacing IS_ERR_OR_NULL with IS_ERR again
	dma-buf: fix dma_fence_array_signaled v4
	regmap: detach regmap from dev on regmap_exit
	mmc: core: Further prevent card detect during shutdown
	s390/cpum_sf: Handle CPU hotplug remove during sampling
	media: uvcvideo: Add a quirk for the Kaiweets KTI-W02 infrared camera
	media: cx231xx: Add support for Dexatek USB Video Grabber 1d19:6108
	drm: panel-orientation-quirks: Add quirk for AYA NEO 2 model
	drm/mcde: Enable module autoloading
	drm/radeon/r600_cs: Fix possible int overflow in r600_packet3_check()
	samples/bpf: Fix a resource leak
	net: fec_mpc52xx_phy: Use %pa to format resource_size_t
	net: ethernet: fs_enet: Use %pa to format resource_size_t
	net/sched: cbs: Fix integer overflow in cbs_set_port_rate()
	af_packet: avoid erroring out after sock_init_data() in packet_create()
	Bluetooth: L2CAP: do not leave dangling sk pointer on error in l2cap_sock_create()
	net: af_can: do not leave a dangling sk pointer in can_create()
	net: ieee802154: do not leave a dangling sk pointer in ieee802154_create()
	net: inet: do not leave a dangling sk pointer in inet_create()
	net: inet6: do not leave a dangling sk pointer in inet6_create()
	wifi: ath5k: add PCI ID for SX76X
	wifi: ath5k: add PCI ID for Arcadyan devices
	jfs: array-index-out-of-bounds fix in dtReadFirst
	jfs: fix shift-out-of-bounds in dbSplit
	jfs: fix array-index-out-of-bounds in jfs_readdir
	jfs: add a check to prevent array-index-out-of-bounds in dbAdjTree
	drm/amdgpu: set the right AMDGPU sg segment limitation
	wifi: ipw2x00: libipw_rx_any(): fix bad alignment
	wifi: brcmfmac: Fix oops due to NULL pointer dereference in brcmf_sdiod_sglist_rw()
	Bluetooth: btusb: Add RTL8852BE device 0489:e123 to device tables
	ASoC: hdmi-codec: reorder channel allocation list
	rocker: fix link status detection in rocker_carrier_init()
	net/neighbor: clear error in case strict check is not set
	netpoll: Use rcu_access_pointer() in __netpoll_setup
	tracing: Use atomic64_inc_return() in trace_clock_counter()
	leds: class: Protect brightness_show() with led_cdev->led_access mutex
	scsi: st: Don't modify unknown block number in MTIOCGET
	scsi: st: Add MTIOCGET and MTLOAD to ioctls allowed after device reset
	pinctrl: qcom-pmic-gpio: add support for PM8937
	nvdimm: rectify the illogical code within nd_dax_probe()
	f2fs: fix f2fs_bug_on when uninstalling filesystem call f2fs_evict_inode.
	PCI: Add 'reset_subordinate' to reset hierarchy below bridge
	PCI: Add ACS quirk for Wangxun FF5xxx NICs
	i3c: Use i3cdev->desc->info instead of calling i3c_device_get_info() to avoid deadlock
	usb: chipidea: udc: handle USB Error Interrupt if IOC not set
	powerpc/prom_init: Fixup missing powermac #size-cells
	misc: eeprom: eeprom_93cx6: Add quirk for extra read clock cycle
	xdp: Simplify devmap cleanup
	bpf: fix OOB devmap writes when deleting elements
	Revert "unicode: Don't special case ignorable code points"
	perf/x86/intel/pt: Fix buffer full but size is 0 case
	KVM: arm64: vgic-its: Add a data length check in vgic_its_save_*
	KVM: arm64: vgic-its: Clear DTE when MAPD unmaps a device
	KVM: arm64: vgic-its: Clear ITE when DISCARD frees an ITE
	jffs2: Prevent rtime decompress memory corruption
	jffs2: Fix rtime decompressor
	ocfs2: Revert "ocfs2: fix the la space leak when unmounting an ocfs2 volume"
	modpost: Add .irqentry.text to OTHER_SECTIONS
	Revert "drm/amdgpu: add missing size check in amdgpu_debugfs_gprwave_read()"
	PCI: rockchip-ep: Fix address translation unit programming
	ALSA: usb-audio: Fix out of bounds reads when finding clock sources
	bpf, xdp: Update devmap comments to reflect napi/rcu usage
	Linux 5.4.287

Change-Id: Ib48a7a0e01226c0f910efae2139893c6a139b9b5
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2024-12-16 10:50:16 +00:00

528 lines
12 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* trace event based perf event profiling/tracing
*
* Copyright (C) 2009 Red Hat Inc, Peter Zijlstra
* Copyright (C) 2009-2010 Frederic Weisbecker <fweisbec@gmail.com>
*/
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/security.h>
#include "trace.h"
#include "trace_probe.h"
static char __percpu *perf_trace_buf[PERF_NR_CONTEXTS];
/*
* Force it to be aligned to unsigned long to avoid misaligned accesses
* suprises
*/
typedef typeof(unsigned long [PERF_MAX_TRACE_SIZE / sizeof(unsigned long)])
perf_trace_t;
/* Count the events in use (per event id, not per instance) */
static int total_ref_count;
static int perf_trace_event_perm(struct trace_event_call *tp_event,
struct perf_event *p_event)
{
int ret;
if (tp_event->perf_perm) {
ret = tp_event->perf_perm(tp_event, p_event);
if (ret)
return ret;
}
/*
* We checked and allowed to create parent,
* allow children without checking.
*/
if (p_event->parent)
return 0;
/*
* It's ok to check current process (owner) permissions in here,
* because code below is called only via perf_event_open syscall.
*/
/* The ftrace function trace is allowed only for root. */
if (ftrace_event_is_function(tp_event)) {
ret = perf_allow_tracepoint(&p_event->attr);
if (ret)
return ret;
if (!is_sampling_event(p_event))
return 0;
/*
* We don't allow user space callchains for function trace
* event, due to issues with page faults while tracing page
* fault handler and its overall trickiness nature.
*/
if (!p_event->attr.exclude_callchain_user)
return -EINVAL;
/*
* Same reason to disable user stack dump as for user space
* callchains above.
*/
if (p_event->attr.sample_type & PERF_SAMPLE_STACK_USER)
return -EINVAL;
}
/* No tracing, just counting, so no obvious leak */
if (!(p_event->attr.sample_type & PERF_SAMPLE_RAW))
return 0;
/* Some events are ok to be traced by non-root users... */
if (p_event->attach_state == PERF_ATTACH_TASK) {
if (tp_event->flags & TRACE_EVENT_FL_CAP_ANY)
return 0;
}
/*
* ...otherwise raw tracepoint data can be a severe data leak,
* only allow root to have these.
*/
ret = perf_allow_tracepoint(&p_event->attr);
if (ret)
return ret;
return 0;
}
static int perf_trace_event_reg(struct trace_event_call *tp_event,
struct perf_event *p_event)
{
struct hlist_head __percpu *list;
int ret = -ENOMEM;
int cpu;
p_event->tp_event = tp_event;
if (tp_event->perf_refcount++ > 0)
return 0;
list = alloc_percpu(struct hlist_head);
if (!list)
goto fail;
for_each_possible_cpu(cpu)
INIT_HLIST_HEAD(per_cpu_ptr(list, cpu));
tp_event->perf_events = list;
if (!total_ref_count) {
char __percpu *buf;
int i;
for (i = 0; i < PERF_NR_CONTEXTS; i++) {
buf = (char __percpu *)alloc_percpu(perf_trace_t);
if (!buf)
goto fail;
perf_trace_buf[i] = buf;
}
}
ret = tp_event->class->reg(tp_event, TRACE_REG_PERF_REGISTER, NULL);
if (ret)
goto fail;
total_ref_count++;
return 0;
fail:
if (!total_ref_count) {
int i;
for (i = 0; i < PERF_NR_CONTEXTS; i++) {
free_percpu(perf_trace_buf[i]);
perf_trace_buf[i] = NULL;
}
}
if (!--tp_event->perf_refcount) {
free_percpu(tp_event->perf_events);
tp_event->perf_events = NULL;
}
return ret;
}
static void perf_trace_event_unreg(struct perf_event *p_event)
{
struct trace_event_call *tp_event = p_event->tp_event;
int i;
if (--tp_event->perf_refcount > 0)
goto out;
tp_event->class->reg(tp_event, TRACE_REG_PERF_UNREGISTER, NULL);
/*
* Ensure our callback won't be called anymore. The buffers
* will be freed after that.
*/
tracepoint_synchronize_unregister();
free_percpu(tp_event->perf_events);
tp_event->perf_events = NULL;
if (!--total_ref_count) {
for (i = 0; i < PERF_NR_CONTEXTS; i++) {
free_percpu(perf_trace_buf[i]);
perf_trace_buf[i] = NULL;
}
}
out:
module_put(tp_event->mod);
}
static int perf_trace_event_open(struct perf_event *p_event)
{
struct trace_event_call *tp_event = p_event->tp_event;
return tp_event->class->reg(tp_event, TRACE_REG_PERF_OPEN, p_event);
}
static void perf_trace_event_close(struct perf_event *p_event)
{
struct trace_event_call *tp_event = p_event->tp_event;
tp_event->class->reg(tp_event, TRACE_REG_PERF_CLOSE, p_event);
}
static int perf_trace_event_init(struct trace_event_call *tp_event,
struct perf_event *p_event)
{
int ret;
ret = perf_trace_event_perm(tp_event, p_event);
if (ret)
return ret;
ret = perf_trace_event_reg(tp_event, p_event);
if (ret)
return ret;
ret = perf_trace_event_open(p_event);
if (ret) {
perf_trace_event_unreg(p_event);
return ret;
}
return 0;
}
int perf_trace_init(struct perf_event *p_event)
{
struct trace_event_call *tp_event;
u64 event_id = p_event->attr.config;
int ret = -EINVAL;
mutex_lock(&event_mutex);
list_for_each_entry(tp_event, &ftrace_events, list) {
if (tp_event->event.type == event_id &&
tp_event->class && tp_event->class->reg &&
try_module_get(tp_event->mod)) {
ret = perf_trace_event_init(tp_event, p_event);
if (ret)
module_put(tp_event->mod);
break;
}
}
mutex_unlock(&event_mutex);
return ret;
}
void perf_trace_destroy(struct perf_event *p_event)
{
mutex_lock(&event_mutex);
perf_trace_event_close(p_event);
perf_trace_event_unreg(p_event);
mutex_unlock(&event_mutex);
}
#ifdef CONFIG_KPROBE_EVENTS
int perf_kprobe_init(struct perf_event *p_event, bool is_retprobe)
{
int ret;
char *func = NULL;
struct trace_event_call *tp_event;
if (p_event->attr.kprobe_func) {
func = kzalloc(KSYM_NAME_LEN, GFP_KERNEL);
if (!func)
return -ENOMEM;
ret = strncpy_from_user(
func, u64_to_user_ptr(p_event->attr.kprobe_func),
KSYM_NAME_LEN);
if (ret == KSYM_NAME_LEN)
ret = -E2BIG;
if (ret < 0)
goto out;
if (func[0] == '\0') {
kfree(func);
func = NULL;
}
}
tp_event = create_local_trace_kprobe(
func, (void *)(unsigned long)(p_event->attr.kprobe_addr),
p_event->attr.probe_offset, is_retprobe);
if (IS_ERR(tp_event)) {
ret = PTR_ERR(tp_event);
goto out;
}
mutex_lock(&event_mutex);
ret = perf_trace_event_init(tp_event, p_event);
if (ret)
destroy_local_trace_kprobe(tp_event);
mutex_unlock(&event_mutex);
out:
kfree(func);
return ret;
}
void perf_kprobe_destroy(struct perf_event *p_event)
{
mutex_lock(&event_mutex);
perf_trace_event_close(p_event);
perf_trace_event_unreg(p_event);
mutex_unlock(&event_mutex);
destroy_local_trace_kprobe(p_event->tp_event);
}
#endif /* CONFIG_KPROBE_EVENTS */
#ifdef CONFIG_UPROBE_EVENTS
int perf_uprobe_init(struct perf_event *p_event,
unsigned long ref_ctr_offset, bool is_retprobe)
{
int ret;
char *path = NULL;
struct trace_event_call *tp_event;
if (!p_event->attr.uprobe_path)
return -EINVAL;
path = strndup_user(u64_to_user_ptr(p_event->attr.uprobe_path),
PATH_MAX);
if (IS_ERR(path)) {
ret = PTR_ERR(path);
return (ret == -EINVAL) ? -E2BIG : ret;
}
if (path[0] == '\0') {
ret = -EINVAL;
goto out;
}
tp_event = create_local_trace_uprobe(path, p_event->attr.probe_offset,
ref_ctr_offset, is_retprobe);
if (IS_ERR(tp_event)) {
ret = PTR_ERR(tp_event);
goto out;
}
/*
* local trace_uprobe need to hold event_mutex to call
* uprobe_buffer_enable() and uprobe_buffer_disable().
* event_mutex is not required for local trace_kprobes.
*/
mutex_lock(&event_mutex);
ret = perf_trace_event_init(tp_event, p_event);
if (ret)
destroy_local_trace_uprobe(tp_event);
mutex_unlock(&event_mutex);
out:
kfree(path);
return ret;
}
void perf_uprobe_destroy(struct perf_event *p_event)
{
mutex_lock(&event_mutex);
perf_trace_event_close(p_event);
perf_trace_event_unreg(p_event);
mutex_unlock(&event_mutex);
destroy_local_trace_uprobe(p_event->tp_event);
}
#endif /* CONFIG_UPROBE_EVENTS */
int perf_trace_add(struct perf_event *p_event, int flags)
{
struct trace_event_call *tp_event = p_event->tp_event;
struct hw_perf_event *hwc = &p_event->hw;
if (!(flags & PERF_EF_START))
p_event->hw.state = PERF_HES_STOPPED;
if (is_sampling_event(p_event)) {
hwc->last_period = hwc->sample_period;
perf_swevent_set_period(p_event);
}
/*
* If TRACE_REG_PERF_ADD returns false; no custom action was performed
* and we need to take the default action of enqueueing our event on
* the right per-cpu hlist.
*/
if (!tp_event->class->reg(tp_event, TRACE_REG_PERF_ADD, p_event)) {
struct hlist_head __percpu *pcpu_list;
struct hlist_head *list;
pcpu_list = tp_event->perf_events;
if (WARN_ON_ONCE(!pcpu_list))
return -EINVAL;
list = this_cpu_ptr(pcpu_list);
hlist_add_head_rcu(&p_event->hlist_entry, list);
}
return 0;
}
void perf_trace_del(struct perf_event *p_event, int flags)
{
struct trace_event_call *tp_event = p_event->tp_event;
/*
* If TRACE_REG_PERF_DEL returns false; no custom action was performed
* and we need to take the default action of dequeueing our event from
* the right per-cpu hlist.
*/
if (!tp_event->class->reg(tp_event, TRACE_REG_PERF_DEL, p_event))
hlist_del_rcu(&p_event->hlist_entry);
}
void *perf_trace_buf_alloc(int size, struct pt_regs **regs, int *rctxp)
{
char *raw_data;
int rctx;
BUILD_BUG_ON(PERF_MAX_TRACE_SIZE % sizeof(unsigned long));
if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE,
"perf buffer not large enough, wanted %d, have %d",
size, PERF_MAX_TRACE_SIZE))
return NULL;
*rctxp = rctx = perf_swevent_get_recursion_context();
if (rctx < 0)
return NULL;
if (regs)
*regs = this_cpu_ptr(&__perf_regs[rctx]);
raw_data = this_cpu_ptr(perf_trace_buf[rctx]);
/* zero the dead bytes from align to not leak stack to user */
memset(&raw_data[size - sizeof(u64)], 0, sizeof(u64));
return raw_data;
}
EXPORT_SYMBOL_GPL(perf_trace_buf_alloc);
NOKPROBE_SYMBOL(perf_trace_buf_alloc);
void perf_trace_buf_update(void *record, u16 type)
{
struct trace_entry *entry = record;
int pc = preempt_count();
unsigned long flags;
local_save_flags(flags);
tracing_generic_entry_update(entry, type, flags, pc);
}
NOKPROBE_SYMBOL(perf_trace_buf_update);
#ifdef CONFIG_FUNCTION_TRACER
static void
perf_ftrace_function_call(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *ops, struct pt_regs *pt_regs)
{
struct ftrace_entry *entry;
struct perf_event *event;
struct hlist_head head;
struct pt_regs regs;
int rctx;
if ((unsigned long)ops->private != smp_processor_id())
return;
event = container_of(ops, struct perf_event, ftrace_ops);
/*
* @event->hlist entry is NULL (per INIT_HLIST_NODE), and all
* the perf code does is hlist_for_each_entry_rcu(), so we can
* get away with simply setting the @head.first pointer in order
* to create a singular list.
*/
head.first = &event->hlist_entry;
#define ENTRY_SIZE (ALIGN(sizeof(struct ftrace_entry) + sizeof(u32), \
sizeof(u64)) - sizeof(u32))
BUILD_BUG_ON(ENTRY_SIZE > PERF_MAX_TRACE_SIZE);
memset(&regs, 0, sizeof(regs));
perf_fetch_caller_regs(&regs);
entry = perf_trace_buf_alloc(ENTRY_SIZE, NULL, &rctx);
if (!entry)
return;
entry->ip = ip;
entry->parent_ip = parent_ip;
perf_trace_buf_submit(entry, ENTRY_SIZE, rctx, TRACE_FN,
1, &regs, &head, NULL);
#undef ENTRY_SIZE
}
static int perf_ftrace_function_register(struct perf_event *event)
{
struct ftrace_ops *ops = &event->ftrace_ops;
ops->flags = FTRACE_OPS_FL_RCU;
ops->func = perf_ftrace_function_call;
ops->private = (void *)(unsigned long)nr_cpu_ids;
return register_ftrace_function(ops);
}
static int perf_ftrace_function_unregister(struct perf_event *event)
{
struct ftrace_ops *ops = &event->ftrace_ops;
int ret = unregister_ftrace_function(ops);
ftrace_free_filter(ops);
return ret;
}
int perf_ftrace_event_register(struct trace_event_call *call,
enum trace_reg type, void *data)
{
struct perf_event *event = data;
switch (type) {
case TRACE_REG_REGISTER:
case TRACE_REG_UNREGISTER:
break;
case TRACE_REG_PERF_REGISTER:
case TRACE_REG_PERF_UNREGISTER:
return 0;
case TRACE_REG_PERF_OPEN:
return perf_ftrace_function_register(data);
case TRACE_REG_PERF_CLOSE:
return perf_ftrace_function_unregister(data);
case TRACE_REG_PERF_ADD:
event->ftrace_ops.private = (void *)(unsigned long)smp_processor_id();
return 1;
case TRACE_REG_PERF_DEL:
event->ftrace_ops.private = (void *)(unsigned long)nr_cpu_ids;
return 1;
}
return -EINVAL;
}
#endif /* CONFIG_FUNCTION_TRACER */