162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * trace_output.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2008 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#include <linux/module.h>
962306a36Sopenharmony_ci#include <linux/mutex.h>
1062306a36Sopenharmony_ci#include <linux/ftrace.h>
1162306a36Sopenharmony_ci#include <linux/kprobes.h>
1262306a36Sopenharmony_ci#include <linux/sched/clock.h>
1362306a36Sopenharmony_ci#include <linux/sched/mm.h>
1462306a36Sopenharmony_ci#include <linux/idr.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include "trace_output.h"
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/* must be a power of 2 */
1962306a36Sopenharmony_ci#define EVENT_HASHSIZE	128
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ciDECLARE_RWSEM(trace_event_sem);
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistatic struct hlist_head event_hash[EVENT_HASHSIZE] __read_mostly;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cienum print_line_t trace_print_bputs_msg_only(struct trace_iterator *iter)
2662306a36Sopenharmony_ci{
2762306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
2862306a36Sopenharmony_ci	struct trace_entry *entry = iter->ent;
2962306a36Sopenharmony_ci	struct bputs_entry *field;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	trace_assign_type(field, entry);
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	trace_seq_puts(s, field->str);
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	return trace_handle_return(s);
3662306a36Sopenharmony_ci}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cienum print_line_t trace_print_bprintk_msg_only(struct trace_iterator *iter)
3962306a36Sopenharmony_ci{
4062306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
4162306a36Sopenharmony_ci	struct trace_entry *entry = iter->ent;
4262306a36Sopenharmony_ci	struct bprint_entry *field;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	trace_assign_type(field, entry);
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	trace_seq_bprintf(s, field->fmt, field->buf);
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	return trace_handle_return(s);
4962306a36Sopenharmony_ci}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cienum print_line_t trace_print_printk_msg_only(struct trace_iterator *iter)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
5462306a36Sopenharmony_ci	struct trace_entry *entry = iter->ent;
5562306a36Sopenharmony_ci	struct print_entry *field;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	trace_assign_type(field, entry);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	trace_seq_puts(s, field->buf);
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	return trace_handle_return(s);
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ciconst char *
6562306a36Sopenharmony_citrace_print_flags_seq(struct trace_seq *p, const char *delim,
6662306a36Sopenharmony_ci		      unsigned long flags,
6762306a36Sopenharmony_ci		      const struct trace_print_flags *flag_array)
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	unsigned long mask;
7062306a36Sopenharmony_ci	const char *str;
7162306a36Sopenharmony_ci	const char *ret = trace_seq_buffer_ptr(p);
7262306a36Sopenharmony_ci	int i, first = 1;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	for (i = 0;  flag_array[i].name && flags; i++) {
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci		mask = flag_array[i].mask;
7762306a36Sopenharmony_ci		if ((flags & mask) != mask)
7862306a36Sopenharmony_ci			continue;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci		str = flag_array[i].name;
8162306a36Sopenharmony_ci		flags &= ~mask;
8262306a36Sopenharmony_ci		if (!first && delim)
8362306a36Sopenharmony_ci			trace_seq_puts(p, delim);
8462306a36Sopenharmony_ci		else
8562306a36Sopenharmony_ci			first = 0;
8662306a36Sopenharmony_ci		trace_seq_puts(p, str);
8762306a36Sopenharmony_ci	}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	/* check for left over flags */
9062306a36Sopenharmony_ci	if (flags) {
9162306a36Sopenharmony_ci		if (!first && delim)
9262306a36Sopenharmony_ci			trace_seq_puts(p, delim);
9362306a36Sopenharmony_ci		trace_seq_printf(p, "0x%lx", flags);
9462306a36Sopenharmony_ci	}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	trace_seq_putc(p, 0);
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	return ret;
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ciEXPORT_SYMBOL(trace_print_flags_seq);
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ciconst char *
10362306a36Sopenharmony_citrace_print_symbols_seq(struct trace_seq *p, unsigned long val,
10462306a36Sopenharmony_ci			const struct trace_print_flags *symbol_array)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	int i;
10762306a36Sopenharmony_ci	const char *ret = trace_seq_buffer_ptr(p);
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	for (i = 0;  symbol_array[i].name; i++) {
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci		if (val != symbol_array[i].mask)
11262306a36Sopenharmony_ci			continue;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci		trace_seq_puts(p, symbol_array[i].name);
11562306a36Sopenharmony_ci		break;
11662306a36Sopenharmony_ci	}
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	if (ret == (const char *)(trace_seq_buffer_ptr(p)))
11962306a36Sopenharmony_ci		trace_seq_printf(p, "0x%lx", val);
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	trace_seq_putc(p, 0);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	return ret;
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ciEXPORT_SYMBOL(trace_print_symbols_seq);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci#if BITS_PER_LONG == 32
12862306a36Sopenharmony_ciconst char *
12962306a36Sopenharmony_citrace_print_flags_seq_u64(struct trace_seq *p, const char *delim,
13062306a36Sopenharmony_ci		      unsigned long long flags,
13162306a36Sopenharmony_ci		      const struct trace_print_flags_u64 *flag_array)
13262306a36Sopenharmony_ci{
13362306a36Sopenharmony_ci	unsigned long long mask;
13462306a36Sopenharmony_ci	const char *str;
13562306a36Sopenharmony_ci	const char *ret = trace_seq_buffer_ptr(p);
13662306a36Sopenharmony_ci	int i, first = 1;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	for (i = 0;  flag_array[i].name && flags; i++) {
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci		mask = flag_array[i].mask;
14162306a36Sopenharmony_ci		if ((flags & mask) != mask)
14262306a36Sopenharmony_ci			continue;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci		str = flag_array[i].name;
14562306a36Sopenharmony_ci		flags &= ~mask;
14662306a36Sopenharmony_ci		if (!first && delim)
14762306a36Sopenharmony_ci			trace_seq_puts(p, delim);
14862306a36Sopenharmony_ci		else
14962306a36Sopenharmony_ci			first = 0;
15062306a36Sopenharmony_ci		trace_seq_puts(p, str);
15162306a36Sopenharmony_ci	}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	/* check for left over flags */
15462306a36Sopenharmony_ci	if (flags) {
15562306a36Sopenharmony_ci		if (!first && delim)
15662306a36Sopenharmony_ci			trace_seq_puts(p, delim);
15762306a36Sopenharmony_ci		trace_seq_printf(p, "0x%llx", flags);
15862306a36Sopenharmony_ci	}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	trace_seq_putc(p, 0);
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	return ret;
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ciEXPORT_SYMBOL(trace_print_flags_seq_u64);
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ciconst char *
16762306a36Sopenharmony_citrace_print_symbols_seq_u64(struct trace_seq *p, unsigned long long val,
16862306a36Sopenharmony_ci			 const struct trace_print_flags_u64 *symbol_array)
16962306a36Sopenharmony_ci{
17062306a36Sopenharmony_ci	int i;
17162306a36Sopenharmony_ci	const char *ret = trace_seq_buffer_ptr(p);
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	for (i = 0;  symbol_array[i].name; i++) {
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci		if (val != symbol_array[i].mask)
17662306a36Sopenharmony_ci			continue;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci		trace_seq_puts(p, symbol_array[i].name);
17962306a36Sopenharmony_ci		break;
18062306a36Sopenharmony_ci	}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	if (ret == (const char *)(trace_seq_buffer_ptr(p)))
18362306a36Sopenharmony_ci		trace_seq_printf(p, "0x%llx", val);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	trace_seq_putc(p, 0);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	return ret;
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ciEXPORT_SYMBOL(trace_print_symbols_seq_u64);
19062306a36Sopenharmony_ci#endif
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ciconst char *
19362306a36Sopenharmony_citrace_print_bitmask_seq(struct trace_seq *p, void *bitmask_ptr,
19462306a36Sopenharmony_ci			unsigned int bitmask_size)
19562306a36Sopenharmony_ci{
19662306a36Sopenharmony_ci	const char *ret = trace_seq_buffer_ptr(p);
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	trace_seq_bitmask(p, bitmask_ptr, bitmask_size * 8);
19962306a36Sopenharmony_ci	trace_seq_putc(p, 0);
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	return ret;
20262306a36Sopenharmony_ci}
20362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(trace_print_bitmask_seq);
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci/**
20662306a36Sopenharmony_ci * trace_print_hex_seq - print buffer as hex sequence
20762306a36Sopenharmony_ci * @p: trace seq struct to write to
20862306a36Sopenharmony_ci * @buf: The buffer to print
20962306a36Sopenharmony_ci * @buf_len: Length of @buf in bytes
21062306a36Sopenharmony_ci * @concatenate: Print @buf as single hex string or with spacing
21162306a36Sopenharmony_ci *
21262306a36Sopenharmony_ci * Prints the passed buffer as a hex sequence either as a whole,
21362306a36Sopenharmony_ci * single hex string if @concatenate is true or with spacing after
21462306a36Sopenharmony_ci * each byte in case @concatenate is false.
21562306a36Sopenharmony_ci */
21662306a36Sopenharmony_ciconst char *
21762306a36Sopenharmony_citrace_print_hex_seq(struct trace_seq *p, const unsigned char *buf, int buf_len,
21862306a36Sopenharmony_ci		    bool concatenate)
21962306a36Sopenharmony_ci{
22062306a36Sopenharmony_ci	int i;
22162306a36Sopenharmony_ci	const char *ret = trace_seq_buffer_ptr(p);
22262306a36Sopenharmony_ci	const char *fmt = concatenate ? "%*phN" : "%*ph";
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	for (i = 0; i < buf_len; i += 16) {
22562306a36Sopenharmony_ci		if (!concatenate && i != 0)
22662306a36Sopenharmony_ci			trace_seq_putc(p, ' ');
22762306a36Sopenharmony_ci		trace_seq_printf(p, fmt, min(buf_len - i, 16), &buf[i]);
22862306a36Sopenharmony_ci	}
22962306a36Sopenharmony_ci	trace_seq_putc(p, 0);
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	return ret;
23262306a36Sopenharmony_ci}
23362306a36Sopenharmony_ciEXPORT_SYMBOL(trace_print_hex_seq);
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ciconst char *
23662306a36Sopenharmony_citrace_print_array_seq(struct trace_seq *p, const void *buf, int count,
23762306a36Sopenharmony_ci		      size_t el_size)
23862306a36Sopenharmony_ci{
23962306a36Sopenharmony_ci	const char *ret = trace_seq_buffer_ptr(p);
24062306a36Sopenharmony_ci	const char *prefix = "";
24162306a36Sopenharmony_ci	void *ptr = (void *)buf;
24262306a36Sopenharmony_ci	size_t buf_len = count * el_size;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	trace_seq_putc(p, '{');
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	while (ptr < buf + buf_len) {
24762306a36Sopenharmony_ci		switch (el_size) {
24862306a36Sopenharmony_ci		case 1:
24962306a36Sopenharmony_ci			trace_seq_printf(p, "%s0x%x", prefix,
25062306a36Sopenharmony_ci					 *(u8 *)ptr);
25162306a36Sopenharmony_ci			break;
25262306a36Sopenharmony_ci		case 2:
25362306a36Sopenharmony_ci			trace_seq_printf(p, "%s0x%x", prefix,
25462306a36Sopenharmony_ci					 *(u16 *)ptr);
25562306a36Sopenharmony_ci			break;
25662306a36Sopenharmony_ci		case 4:
25762306a36Sopenharmony_ci			trace_seq_printf(p, "%s0x%x", prefix,
25862306a36Sopenharmony_ci					 *(u32 *)ptr);
25962306a36Sopenharmony_ci			break;
26062306a36Sopenharmony_ci		case 8:
26162306a36Sopenharmony_ci			trace_seq_printf(p, "%s0x%llx", prefix,
26262306a36Sopenharmony_ci					 *(u64 *)ptr);
26362306a36Sopenharmony_ci			break;
26462306a36Sopenharmony_ci		default:
26562306a36Sopenharmony_ci			trace_seq_printf(p, "BAD SIZE:%zu 0x%x", el_size,
26662306a36Sopenharmony_ci					 *(u8 *)ptr);
26762306a36Sopenharmony_ci			el_size = 1;
26862306a36Sopenharmony_ci		}
26962306a36Sopenharmony_ci		prefix = ",";
27062306a36Sopenharmony_ci		ptr += el_size;
27162306a36Sopenharmony_ci	}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	trace_seq_putc(p, '}');
27462306a36Sopenharmony_ci	trace_seq_putc(p, 0);
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	return ret;
27762306a36Sopenharmony_ci}
27862306a36Sopenharmony_ciEXPORT_SYMBOL(trace_print_array_seq);
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ciconst char *
28162306a36Sopenharmony_citrace_print_hex_dump_seq(struct trace_seq *p, const char *prefix_str,
28262306a36Sopenharmony_ci			 int prefix_type, int rowsize, int groupsize,
28362306a36Sopenharmony_ci			 const void *buf, size_t len, bool ascii)
28462306a36Sopenharmony_ci{
28562306a36Sopenharmony_ci	const char *ret = trace_seq_buffer_ptr(p);
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	trace_seq_putc(p, '\n');
28862306a36Sopenharmony_ci	trace_seq_hex_dump(p, prefix_str, prefix_type,
28962306a36Sopenharmony_ci			   rowsize, groupsize, buf, len, ascii);
29062306a36Sopenharmony_ci	trace_seq_putc(p, 0);
29162306a36Sopenharmony_ci	return ret;
29262306a36Sopenharmony_ci}
29362306a36Sopenharmony_ciEXPORT_SYMBOL(trace_print_hex_dump_seq);
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ciint trace_raw_output_prep(struct trace_iterator *iter,
29662306a36Sopenharmony_ci			  struct trace_event *trace_event)
29762306a36Sopenharmony_ci{
29862306a36Sopenharmony_ci	struct trace_event_call *event;
29962306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
30062306a36Sopenharmony_ci	struct trace_seq *p = &iter->tmp_seq;
30162306a36Sopenharmony_ci	struct trace_entry *entry;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	event = container_of(trace_event, struct trace_event_call, event);
30462306a36Sopenharmony_ci	entry = iter->ent;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	if (entry->type != event->event.type) {
30762306a36Sopenharmony_ci		WARN_ON_ONCE(1);
30862306a36Sopenharmony_ci		return TRACE_TYPE_UNHANDLED;
30962306a36Sopenharmony_ci	}
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	trace_seq_init(p);
31262306a36Sopenharmony_ci	trace_seq_printf(s, "%s: ", trace_event_name(event));
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	return trace_handle_return(s);
31562306a36Sopenharmony_ci}
31662306a36Sopenharmony_ciEXPORT_SYMBOL(trace_raw_output_prep);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_civoid trace_event_printf(struct trace_iterator *iter, const char *fmt, ...)
31962306a36Sopenharmony_ci{
32062306a36Sopenharmony_ci	va_list ap;
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	va_start(ap, fmt);
32362306a36Sopenharmony_ci	trace_check_vprintf(iter, trace_event_format(iter, fmt), ap);
32462306a36Sopenharmony_ci	va_end(ap);
32562306a36Sopenharmony_ci}
32662306a36Sopenharmony_ciEXPORT_SYMBOL(trace_event_printf);
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_cistatic __printf(3, 0)
32962306a36Sopenharmony_ciint trace_output_raw(struct trace_iterator *iter, char *name,
33062306a36Sopenharmony_ci		     char *fmt, va_list ap)
33162306a36Sopenharmony_ci{
33262306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	trace_seq_printf(s, "%s: ", name);
33562306a36Sopenharmony_ci	trace_seq_vprintf(s, trace_event_format(iter, fmt), ap);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	return trace_handle_return(s);
33862306a36Sopenharmony_ci}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ciint trace_output_call(struct trace_iterator *iter, char *name, char *fmt, ...)
34162306a36Sopenharmony_ci{
34262306a36Sopenharmony_ci	va_list ap;
34362306a36Sopenharmony_ci	int ret;
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	va_start(ap, fmt);
34662306a36Sopenharmony_ci	ret = trace_output_raw(iter, name, fmt, ap);
34762306a36Sopenharmony_ci	va_end(ap);
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	return ret;
35062306a36Sopenharmony_ci}
35162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(trace_output_call);
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_cistatic inline const char *kretprobed(const char *name, unsigned long addr)
35462306a36Sopenharmony_ci{
35562306a36Sopenharmony_ci	if (is_kretprobe_trampoline(addr))
35662306a36Sopenharmony_ci		return "[unknown/kretprobe'd]";
35762306a36Sopenharmony_ci	return name;
35862306a36Sopenharmony_ci}
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_civoid
36162306a36Sopenharmony_citrace_seq_print_sym(struct trace_seq *s, unsigned long address, bool offset)
36262306a36Sopenharmony_ci{
36362306a36Sopenharmony_ci#ifdef CONFIG_KALLSYMS
36462306a36Sopenharmony_ci	char str[KSYM_SYMBOL_LEN];
36562306a36Sopenharmony_ci	const char *name;
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	if (offset)
36862306a36Sopenharmony_ci		sprint_symbol(str, address);
36962306a36Sopenharmony_ci	else
37062306a36Sopenharmony_ci		kallsyms_lookup(address, NULL, NULL, NULL, str);
37162306a36Sopenharmony_ci	name = kretprobed(str, address);
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	if (name && strlen(name)) {
37462306a36Sopenharmony_ci		trace_seq_puts(s, name);
37562306a36Sopenharmony_ci		return;
37662306a36Sopenharmony_ci	}
37762306a36Sopenharmony_ci#endif
37862306a36Sopenharmony_ci	trace_seq_printf(s, "0x%08lx", address);
37962306a36Sopenharmony_ci}
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci#ifndef CONFIG_64BIT
38262306a36Sopenharmony_ci# define IP_FMT "%08lx"
38362306a36Sopenharmony_ci#else
38462306a36Sopenharmony_ci# define IP_FMT "%016lx"
38562306a36Sopenharmony_ci#endif
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_cistatic int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm,
38862306a36Sopenharmony_ci			     unsigned long ip, unsigned long sym_flags)
38962306a36Sopenharmony_ci{
39062306a36Sopenharmony_ci	struct file *file = NULL;
39162306a36Sopenharmony_ci	unsigned long vmstart = 0;
39262306a36Sopenharmony_ci	int ret = 1;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	if (s->full)
39562306a36Sopenharmony_ci		return 0;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	if (mm) {
39862306a36Sopenharmony_ci		const struct vm_area_struct *vma;
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci		mmap_read_lock(mm);
40162306a36Sopenharmony_ci		vma = find_vma(mm, ip);
40262306a36Sopenharmony_ci		if (vma) {
40362306a36Sopenharmony_ci			file = vma->vm_file;
40462306a36Sopenharmony_ci			vmstart = vma->vm_start;
40562306a36Sopenharmony_ci		}
40662306a36Sopenharmony_ci		if (file) {
40762306a36Sopenharmony_ci			ret = trace_seq_path(s, &file->f_path);
40862306a36Sopenharmony_ci			if (ret)
40962306a36Sopenharmony_ci				trace_seq_printf(s, "[+0x%lx]",
41062306a36Sopenharmony_ci						 ip - vmstart);
41162306a36Sopenharmony_ci		}
41262306a36Sopenharmony_ci		mmap_read_unlock(mm);
41362306a36Sopenharmony_ci	}
41462306a36Sopenharmony_ci	if (ret && ((sym_flags & TRACE_ITER_SYM_ADDR) || !file))
41562306a36Sopenharmony_ci		trace_seq_printf(s, " <" IP_FMT ">", ip);
41662306a36Sopenharmony_ci	return !trace_seq_has_overflowed(s);
41762306a36Sopenharmony_ci}
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ciint
42062306a36Sopenharmony_ciseq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags)
42162306a36Sopenharmony_ci{
42262306a36Sopenharmony_ci	if (!ip) {
42362306a36Sopenharmony_ci		trace_seq_putc(s, '0');
42462306a36Sopenharmony_ci		goto out;
42562306a36Sopenharmony_ci	}
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	trace_seq_print_sym(s, ip, sym_flags & TRACE_ITER_SYM_OFFSET);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	if (sym_flags & TRACE_ITER_SYM_ADDR)
43062306a36Sopenharmony_ci		trace_seq_printf(s, " <" IP_FMT ">", ip);
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci out:
43362306a36Sopenharmony_ci	return !trace_seq_has_overflowed(s);
43462306a36Sopenharmony_ci}
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci/**
43762306a36Sopenharmony_ci * trace_print_lat_fmt - print the irq, preempt and lockdep fields
43862306a36Sopenharmony_ci * @s: trace seq struct to write to
43962306a36Sopenharmony_ci * @entry: The trace entry field from the ring buffer
44062306a36Sopenharmony_ci *
44162306a36Sopenharmony_ci * Prints the generic fields of irqs off, in hard or softirq, preempt
44262306a36Sopenharmony_ci * count.
44362306a36Sopenharmony_ci */
44462306a36Sopenharmony_ciint trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
44562306a36Sopenharmony_ci{
44662306a36Sopenharmony_ci	char hardsoft_irq;
44762306a36Sopenharmony_ci	char need_resched;
44862306a36Sopenharmony_ci	char irqs_off;
44962306a36Sopenharmony_ci	int hardirq;
45062306a36Sopenharmony_ci	int softirq;
45162306a36Sopenharmony_ci	int bh_off;
45262306a36Sopenharmony_ci	int nmi;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	nmi = entry->flags & TRACE_FLAG_NMI;
45562306a36Sopenharmony_ci	hardirq = entry->flags & TRACE_FLAG_HARDIRQ;
45662306a36Sopenharmony_ci	softirq = entry->flags & TRACE_FLAG_SOFTIRQ;
45762306a36Sopenharmony_ci	bh_off = entry->flags & TRACE_FLAG_BH_OFF;
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	irqs_off =
46062306a36Sopenharmony_ci		(entry->flags & TRACE_FLAG_IRQS_OFF && bh_off) ? 'D' :
46162306a36Sopenharmony_ci		(entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
46262306a36Sopenharmony_ci		bh_off ? 'b' :
46362306a36Sopenharmony_ci		(entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ? 'X' :
46462306a36Sopenharmony_ci		'.';
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	switch (entry->flags & (TRACE_FLAG_NEED_RESCHED |
46762306a36Sopenharmony_ci				TRACE_FLAG_PREEMPT_RESCHED)) {
46862306a36Sopenharmony_ci	case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_PREEMPT_RESCHED:
46962306a36Sopenharmony_ci		need_resched = 'N';
47062306a36Sopenharmony_ci		break;
47162306a36Sopenharmony_ci	case TRACE_FLAG_NEED_RESCHED:
47262306a36Sopenharmony_ci		need_resched = 'n';
47362306a36Sopenharmony_ci		break;
47462306a36Sopenharmony_ci	case TRACE_FLAG_PREEMPT_RESCHED:
47562306a36Sopenharmony_ci		need_resched = 'p';
47662306a36Sopenharmony_ci		break;
47762306a36Sopenharmony_ci	default:
47862306a36Sopenharmony_ci		need_resched = '.';
47962306a36Sopenharmony_ci		break;
48062306a36Sopenharmony_ci	}
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	hardsoft_irq =
48362306a36Sopenharmony_ci		(nmi && hardirq)     ? 'Z' :
48462306a36Sopenharmony_ci		nmi                  ? 'z' :
48562306a36Sopenharmony_ci		(hardirq && softirq) ? 'H' :
48662306a36Sopenharmony_ci		hardirq              ? 'h' :
48762306a36Sopenharmony_ci		softirq              ? 's' :
48862306a36Sopenharmony_ci		                       '.' ;
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	trace_seq_printf(s, "%c%c%c",
49162306a36Sopenharmony_ci			 irqs_off, need_resched, hardsoft_irq);
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	if (entry->preempt_count & 0xf)
49462306a36Sopenharmony_ci		trace_seq_printf(s, "%x", entry->preempt_count & 0xf);
49562306a36Sopenharmony_ci	else
49662306a36Sopenharmony_ci		trace_seq_putc(s, '.');
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	if (entry->preempt_count & 0xf0)
49962306a36Sopenharmony_ci		trace_seq_printf(s, "%x", entry->preempt_count >> 4);
50062306a36Sopenharmony_ci	else
50162306a36Sopenharmony_ci		trace_seq_putc(s, '.');
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	return !trace_seq_has_overflowed(s);
50462306a36Sopenharmony_ci}
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_cistatic int
50762306a36Sopenharmony_cilat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu)
50862306a36Sopenharmony_ci{
50962306a36Sopenharmony_ci	char comm[TASK_COMM_LEN];
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	trace_find_cmdline(entry->pid, comm);
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	trace_seq_printf(s, "%8.8s-%-7d %3d",
51462306a36Sopenharmony_ci			 comm, entry->pid, cpu);
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci	return trace_print_lat_fmt(s, entry);
51762306a36Sopenharmony_ci}
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci#undef MARK
52062306a36Sopenharmony_ci#define MARK(v, s) {.val = v, .sym = s}
52162306a36Sopenharmony_ci/* trace overhead mark */
52262306a36Sopenharmony_cistatic const struct trace_mark {
52362306a36Sopenharmony_ci	unsigned long long	val; /* unit: nsec */
52462306a36Sopenharmony_ci	char			sym;
52562306a36Sopenharmony_ci} mark[] = {
52662306a36Sopenharmony_ci	MARK(1000000000ULL	, '$'), /* 1 sec */
52762306a36Sopenharmony_ci	MARK(100000000ULL	, '@'), /* 100 msec */
52862306a36Sopenharmony_ci	MARK(10000000ULL	, '*'), /* 10 msec */
52962306a36Sopenharmony_ci	MARK(1000000ULL		, '#'), /* 1000 usecs */
53062306a36Sopenharmony_ci	MARK(100000ULL		, '!'), /* 100 usecs */
53162306a36Sopenharmony_ci	MARK(10000ULL		, '+'), /* 10 usecs */
53262306a36Sopenharmony_ci};
53362306a36Sopenharmony_ci#undef MARK
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_cichar trace_find_mark(unsigned long long d)
53662306a36Sopenharmony_ci{
53762306a36Sopenharmony_ci	int i;
53862306a36Sopenharmony_ci	int size = ARRAY_SIZE(mark);
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	for (i = 0; i < size; i++) {
54162306a36Sopenharmony_ci		if (d > mark[i].val)
54262306a36Sopenharmony_ci			break;
54362306a36Sopenharmony_ci	}
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	return (i == size) ? ' ' : mark[i].sym;
54662306a36Sopenharmony_ci}
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_cistatic int
54962306a36Sopenharmony_cilat_print_timestamp(struct trace_iterator *iter, u64 next_ts)
55062306a36Sopenharmony_ci{
55162306a36Sopenharmony_ci	struct trace_array *tr = iter->tr;
55262306a36Sopenharmony_ci	unsigned long verbose = tr->trace_flags & TRACE_ITER_VERBOSE;
55362306a36Sopenharmony_ci	unsigned long in_ns = iter->iter_flags & TRACE_FILE_TIME_IN_NS;
55462306a36Sopenharmony_ci	unsigned long long abs_ts = iter->ts - iter->array_buffer->time_start;
55562306a36Sopenharmony_ci	unsigned long long rel_ts = next_ts - iter->ts;
55662306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	if (in_ns) {
55962306a36Sopenharmony_ci		abs_ts = ns2usecs(abs_ts);
56062306a36Sopenharmony_ci		rel_ts = ns2usecs(rel_ts);
56162306a36Sopenharmony_ci	}
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci	if (verbose && in_ns) {
56462306a36Sopenharmony_ci		unsigned long abs_usec = do_div(abs_ts, USEC_PER_MSEC);
56562306a36Sopenharmony_ci		unsigned long abs_msec = (unsigned long)abs_ts;
56662306a36Sopenharmony_ci		unsigned long rel_usec = do_div(rel_ts, USEC_PER_MSEC);
56762306a36Sopenharmony_ci		unsigned long rel_msec = (unsigned long)rel_ts;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci		trace_seq_printf(
57062306a36Sopenharmony_ci			s, "[%08llx] %ld.%03ldms (+%ld.%03ldms): ",
57162306a36Sopenharmony_ci			ns2usecs(iter->ts),
57262306a36Sopenharmony_ci			abs_msec, abs_usec,
57362306a36Sopenharmony_ci			rel_msec, rel_usec);
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	} else if (verbose && !in_ns) {
57662306a36Sopenharmony_ci		trace_seq_printf(
57762306a36Sopenharmony_ci			s, "[%016llx] %lld (+%lld): ",
57862306a36Sopenharmony_ci			iter->ts, abs_ts, rel_ts);
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	} else if (!verbose && in_ns) {
58162306a36Sopenharmony_ci		trace_seq_printf(
58262306a36Sopenharmony_ci			s, " %4lldus%c: ",
58362306a36Sopenharmony_ci			abs_ts,
58462306a36Sopenharmony_ci			trace_find_mark(rel_ts * NSEC_PER_USEC));
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	} else { /* !verbose && !in_ns */
58762306a36Sopenharmony_ci		trace_seq_printf(s, " %4lld: ", abs_ts);
58862306a36Sopenharmony_ci	}
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	return !trace_seq_has_overflowed(s);
59162306a36Sopenharmony_ci}
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_cistatic void trace_print_time(struct trace_seq *s, struct trace_iterator *iter,
59462306a36Sopenharmony_ci			     unsigned long long ts)
59562306a36Sopenharmony_ci{
59662306a36Sopenharmony_ci	unsigned long secs, usec_rem;
59762306a36Sopenharmony_ci	unsigned long long t;
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	if (iter->iter_flags & TRACE_FILE_TIME_IN_NS) {
60062306a36Sopenharmony_ci		t = ns2usecs(ts);
60162306a36Sopenharmony_ci		usec_rem = do_div(t, USEC_PER_SEC);
60262306a36Sopenharmony_ci		secs = (unsigned long)t;
60362306a36Sopenharmony_ci		trace_seq_printf(s, " %5lu.%06lu", secs, usec_rem);
60462306a36Sopenharmony_ci	} else
60562306a36Sopenharmony_ci		trace_seq_printf(s, " %12llu", ts);
60662306a36Sopenharmony_ci}
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ciint trace_print_context(struct trace_iterator *iter)
60962306a36Sopenharmony_ci{
61062306a36Sopenharmony_ci	struct trace_array *tr = iter->tr;
61162306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
61262306a36Sopenharmony_ci	struct trace_entry *entry = iter->ent;
61362306a36Sopenharmony_ci	char comm[TASK_COMM_LEN];
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci	trace_find_cmdline(entry->pid, comm);
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	trace_seq_printf(s, "%16s-%-7d ", comm, entry->pid);
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	if (tr->trace_flags & TRACE_ITER_RECORD_TGID) {
62062306a36Sopenharmony_ci		unsigned int tgid = trace_find_tgid(entry->pid);
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci		if (!tgid)
62362306a36Sopenharmony_ci			trace_seq_printf(s, "(-------) ");
62462306a36Sopenharmony_ci		else
62562306a36Sopenharmony_ci			trace_seq_printf(s, "(%7d) ", tgid);
62662306a36Sopenharmony_ci	}
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	trace_seq_printf(s, "[%03d] ", iter->cpu);
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci	if (tr->trace_flags & TRACE_ITER_IRQ_INFO)
63162306a36Sopenharmony_ci		trace_print_lat_fmt(s, entry);
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci	trace_print_time(s, iter, iter->ts);
63462306a36Sopenharmony_ci	trace_seq_puts(s, ": ");
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	return !trace_seq_has_overflowed(s);
63762306a36Sopenharmony_ci}
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ciint trace_print_lat_context(struct trace_iterator *iter)
64062306a36Sopenharmony_ci{
64162306a36Sopenharmony_ci	struct trace_entry *entry, *next_entry;
64262306a36Sopenharmony_ci	struct trace_array *tr = iter->tr;
64362306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
64462306a36Sopenharmony_ci	unsigned long verbose = (tr->trace_flags & TRACE_ITER_VERBOSE);
64562306a36Sopenharmony_ci	u64 next_ts;
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	next_entry = trace_find_next_entry(iter, NULL, &next_ts);
64862306a36Sopenharmony_ci	if (!next_entry)
64962306a36Sopenharmony_ci		next_ts = iter->ts;
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci	/* trace_find_next_entry() may change iter->ent */
65262306a36Sopenharmony_ci	entry = iter->ent;
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci	if (verbose) {
65562306a36Sopenharmony_ci		char comm[TASK_COMM_LEN];
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci		trace_find_cmdline(entry->pid, comm);
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci		trace_seq_printf(
66062306a36Sopenharmony_ci			s, "%16s %7d %3d %d %08x %08lx ",
66162306a36Sopenharmony_ci			comm, entry->pid, iter->cpu, entry->flags,
66262306a36Sopenharmony_ci			entry->preempt_count & 0xf, iter->idx);
66362306a36Sopenharmony_ci	} else {
66462306a36Sopenharmony_ci		lat_print_generic(s, entry, iter->cpu);
66562306a36Sopenharmony_ci	}
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	lat_print_timestamp(iter, next_ts);
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	return !trace_seq_has_overflowed(s);
67062306a36Sopenharmony_ci}
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci/**
67362306a36Sopenharmony_ci * ftrace_find_event - find a registered event
67462306a36Sopenharmony_ci * @type: the type of event to look for
67562306a36Sopenharmony_ci *
67662306a36Sopenharmony_ci * Returns an event of type @type otherwise NULL
67762306a36Sopenharmony_ci * Called with trace_event_read_lock() held.
67862306a36Sopenharmony_ci */
67962306a36Sopenharmony_cistruct trace_event *ftrace_find_event(int type)
68062306a36Sopenharmony_ci{
68162306a36Sopenharmony_ci	struct trace_event *event;
68262306a36Sopenharmony_ci	unsigned key;
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	key = type & (EVENT_HASHSIZE - 1);
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci	hlist_for_each_entry(event, &event_hash[key], node) {
68762306a36Sopenharmony_ci		if (event->type == type)
68862306a36Sopenharmony_ci			return event;
68962306a36Sopenharmony_ci	}
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	return NULL;
69262306a36Sopenharmony_ci}
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_cistatic DEFINE_IDA(trace_event_ida);
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_cistatic void free_trace_event_type(int type)
69762306a36Sopenharmony_ci{
69862306a36Sopenharmony_ci	if (type >= __TRACE_LAST_TYPE)
69962306a36Sopenharmony_ci		ida_free(&trace_event_ida, type);
70062306a36Sopenharmony_ci}
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_cistatic int alloc_trace_event_type(void)
70362306a36Sopenharmony_ci{
70462306a36Sopenharmony_ci	int next;
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	/* Skip static defined type numbers */
70762306a36Sopenharmony_ci	next = ida_alloc_range(&trace_event_ida, __TRACE_LAST_TYPE,
70862306a36Sopenharmony_ci			       TRACE_EVENT_TYPE_MAX, GFP_KERNEL);
70962306a36Sopenharmony_ci	if (next < 0)
71062306a36Sopenharmony_ci		return 0;
71162306a36Sopenharmony_ci	return next;
71262306a36Sopenharmony_ci}
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_civoid trace_event_read_lock(void)
71562306a36Sopenharmony_ci{
71662306a36Sopenharmony_ci	down_read(&trace_event_sem);
71762306a36Sopenharmony_ci}
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_civoid trace_event_read_unlock(void)
72062306a36Sopenharmony_ci{
72162306a36Sopenharmony_ci	up_read(&trace_event_sem);
72262306a36Sopenharmony_ci}
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci/**
72562306a36Sopenharmony_ci * register_trace_event - register output for an event type
72662306a36Sopenharmony_ci * @event: the event type to register
72762306a36Sopenharmony_ci *
72862306a36Sopenharmony_ci * Event types are stored in a hash and this hash is used to
72962306a36Sopenharmony_ci * find a way to print an event. If the @event->type is set
73062306a36Sopenharmony_ci * then it will use that type, otherwise it will assign a
73162306a36Sopenharmony_ci * type to use.
73262306a36Sopenharmony_ci *
73362306a36Sopenharmony_ci * If you assign your own type, please make sure it is added
73462306a36Sopenharmony_ci * to the trace_type enum in trace.h, to avoid collisions
73562306a36Sopenharmony_ci * with the dynamic types.
73662306a36Sopenharmony_ci *
73762306a36Sopenharmony_ci * Returns the event type number or zero on error.
73862306a36Sopenharmony_ci */
73962306a36Sopenharmony_ciint register_trace_event(struct trace_event *event)
74062306a36Sopenharmony_ci{
74162306a36Sopenharmony_ci	unsigned key;
74262306a36Sopenharmony_ci	int ret = 0;
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci	down_write(&trace_event_sem);
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci	if (WARN_ON(!event))
74762306a36Sopenharmony_ci		goto out;
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci	if (WARN_ON(!event->funcs))
75062306a36Sopenharmony_ci		goto out;
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ci	if (!event->type) {
75362306a36Sopenharmony_ci		event->type = alloc_trace_event_type();
75462306a36Sopenharmony_ci		if (!event->type)
75562306a36Sopenharmony_ci			goto out;
75662306a36Sopenharmony_ci	} else if (WARN(event->type > __TRACE_LAST_TYPE,
75762306a36Sopenharmony_ci			"Need to add type to trace.h")) {
75862306a36Sopenharmony_ci		goto out;
75962306a36Sopenharmony_ci	} else {
76062306a36Sopenharmony_ci		/* Is this event already used */
76162306a36Sopenharmony_ci		if (ftrace_find_event(event->type))
76262306a36Sopenharmony_ci			goto out;
76362306a36Sopenharmony_ci	}
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci	if (event->funcs->trace == NULL)
76662306a36Sopenharmony_ci		event->funcs->trace = trace_nop_print;
76762306a36Sopenharmony_ci	if (event->funcs->raw == NULL)
76862306a36Sopenharmony_ci		event->funcs->raw = trace_nop_print;
76962306a36Sopenharmony_ci	if (event->funcs->hex == NULL)
77062306a36Sopenharmony_ci		event->funcs->hex = trace_nop_print;
77162306a36Sopenharmony_ci	if (event->funcs->binary == NULL)
77262306a36Sopenharmony_ci		event->funcs->binary = trace_nop_print;
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci	key = event->type & (EVENT_HASHSIZE - 1);
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci	hlist_add_head(&event->node, &event_hash[key]);
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_ci	ret = event->type;
77962306a36Sopenharmony_ci out:
78062306a36Sopenharmony_ci	up_write(&trace_event_sem);
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	return ret;
78362306a36Sopenharmony_ci}
78462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(register_trace_event);
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci/*
78762306a36Sopenharmony_ci * Used by module code with the trace_event_sem held for write.
78862306a36Sopenharmony_ci */
78962306a36Sopenharmony_ciint __unregister_trace_event(struct trace_event *event)
79062306a36Sopenharmony_ci{
79162306a36Sopenharmony_ci	hlist_del(&event->node);
79262306a36Sopenharmony_ci	free_trace_event_type(event->type);
79362306a36Sopenharmony_ci	return 0;
79462306a36Sopenharmony_ci}
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci/**
79762306a36Sopenharmony_ci * unregister_trace_event - remove a no longer used event
79862306a36Sopenharmony_ci * @event: the event to remove
79962306a36Sopenharmony_ci */
80062306a36Sopenharmony_ciint unregister_trace_event(struct trace_event *event)
80162306a36Sopenharmony_ci{
80262306a36Sopenharmony_ci	down_write(&trace_event_sem);
80362306a36Sopenharmony_ci	__unregister_trace_event(event);
80462306a36Sopenharmony_ci	up_write(&trace_event_sem);
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	return 0;
80762306a36Sopenharmony_ci}
80862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(unregister_trace_event);
80962306a36Sopenharmony_ci
81062306a36Sopenharmony_ci/*
81162306a36Sopenharmony_ci * Standard events
81262306a36Sopenharmony_ci */
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_cistatic void print_array(struct trace_iterator *iter, void *pos,
81562306a36Sopenharmony_ci			struct ftrace_event_field *field)
81662306a36Sopenharmony_ci{
81762306a36Sopenharmony_ci	int offset;
81862306a36Sopenharmony_ci	int len;
81962306a36Sopenharmony_ci	int i;
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci	offset = *(int *)pos & 0xffff;
82262306a36Sopenharmony_ci	len = *(int *)pos >> 16;
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci	if (field)
82562306a36Sopenharmony_ci		offset += field->offset + sizeof(int);
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci	if (offset + len > iter->ent_size) {
82862306a36Sopenharmony_ci		trace_seq_puts(&iter->seq, "<OVERFLOW>");
82962306a36Sopenharmony_ci		return;
83062306a36Sopenharmony_ci	}
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	pos = (void *)iter->ent + offset;
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	for (i = 0; i < len; i++, pos++) {
83562306a36Sopenharmony_ci		if (i)
83662306a36Sopenharmony_ci			trace_seq_putc(&iter->seq, ',');
83762306a36Sopenharmony_ci		trace_seq_printf(&iter->seq, "%02x", *(unsigned char *)pos);
83862306a36Sopenharmony_ci	}
83962306a36Sopenharmony_ci}
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_cistatic void print_fields(struct trace_iterator *iter, struct trace_event_call *call,
84262306a36Sopenharmony_ci			 struct list_head *head)
84362306a36Sopenharmony_ci{
84462306a36Sopenharmony_ci	struct ftrace_event_field *field;
84562306a36Sopenharmony_ci	int offset;
84662306a36Sopenharmony_ci	int len;
84762306a36Sopenharmony_ci	int ret;
84862306a36Sopenharmony_ci	void *pos;
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	list_for_each_entry_reverse(field, head, link) {
85162306a36Sopenharmony_ci		trace_seq_printf(&iter->seq, " %s=", field->name);
85262306a36Sopenharmony_ci		if (field->offset + field->size > iter->ent_size) {
85362306a36Sopenharmony_ci			trace_seq_puts(&iter->seq, "<OVERFLOW>");
85462306a36Sopenharmony_ci			continue;
85562306a36Sopenharmony_ci		}
85662306a36Sopenharmony_ci		pos = (void *)iter->ent + field->offset;
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci		switch (field->filter_type) {
85962306a36Sopenharmony_ci		case FILTER_COMM:
86062306a36Sopenharmony_ci		case FILTER_STATIC_STRING:
86162306a36Sopenharmony_ci			trace_seq_printf(&iter->seq, "%.*s", field->size, (char *)pos);
86262306a36Sopenharmony_ci			break;
86362306a36Sopenharmony_ci		case FILTER_RDYN_STRING:
86462306a36Sopenharmony_ci		case FILTER_DYN_STRING:
86562306a36Sopenharmony_ci			offset = *(int *)pos & 0xffff;
86662306a36Sopenharmony_ci			len = *(int *)pos >> 16;
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci			if (field->filter_type == FILTER_RDYN_STRING)
86962306a36Sopenharmony_ci				offset += field->offset + sizeof(int);
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci			if (offset + len > iter->ent_size) {
87262306a36Sopenharmony_ci				trace_seq_puts(&iter->seq, "<OVERFLOW>");
87362306a36Sopenharmony_ci				break;
87462306a36Sopenharmony_ci			}
87562306a36Sopenharmony_ci			pos = (void *)iter->ent + offset;
87662306a36Sopenharmony_ci			trace_seq_printf(&iter->seq, "%.*s", len, (char *)pos);
87762306a36Sopenharmony_ci			break;
87862306a36Sopenharmony_ci		case FILTER_PTR_STRING:
87962306a36Sopenharmony_ci			if (!iter->fmt_size)
88062306a36Sopenharmony_ci				trace_iter_expand_format(iter);
88162306a36Sopenharmony_ci			pos = *(void **)pos;
88262306a36Sopenharmony_ci			ret = strncpy_from_kernel_nofault(iter->fmt, pos,
88362306a36Sopenharmony_ci							  iter->fmt_size);
88462306a36Sopenharmony_ci			if (ret < 0)
88562306a36Sopenharmony_ci				trace_seq_printf(&iter->seq, "(0x%px)", pos);
88662306a36Sopenharmony_ci			else
88762306a36Sopenharmony_ci				trace_seq_printf(&iter->seq, "(0x%px:%s)",
88862306a36Sopenharmony_ci						 pos, iter->fmt);
88962306a36Sopenharmony_ci			break;
89062306a36Sopenharmony_ci		case FILTER_TRACE_FN:
89162306a36Sopenharmony_ci			pos = *(void **)pos;
89262306a36Sopenharmony_ci			trace_seq_printf(&iter->seq, "%pS", pos);
89362306a36Sopenharmony_ci			break;
89462306a36Sopenharmony_ci		case FILTER_CPU:
89562306a36Sopenharmony_ci		case FILTER_OTHER:
89662306a36Sopenharmony_ci			switch (field->size) {
89762306a36Sopenharmony_ci			case 1:
89862306a36Sopenharmony_ci				if (isprint(*(char *)pos)) {
89962306a36Sopenharmony_ci					trace_seq_printf(&iter->seq, "'%c'",
90062306a36Sopenharmony_ci						 *(unsigned char *)pos);
90162306a36Sopenharmony_ci				}
90262306a36Sopenharmony_ci				trace_seq_printf(&iter->seq, "(%d)",
90362306a36Sopenharmony_ci						 *(unsigned char *)pos);
90462306a36Sopenharmony_ci				break;
90562306a36Sopenharmony_ci			case 2:
90662306a36Sopenharmony_ci				trace_seq_printf(&iter->seq, "0x%x (%d)",
90762306a36Sopenharmony_ci						 *(unsigned short *)pos,
90862306a36Sopenharmony_ci						 *(unsigned short *)pos);
90962306a36Sopenharmony_ci				break;
91062306a36Sopenharmony_ci			case 4:
91162306a36Sopenharmony_ci				/* dynamic array info is 4 bytes */
91262306a36Sopenharmony_ci				if (strstr(field->type, "__data_loc")) {
91362306a36Sopenharmony_ci					print_array(iter, pos, NULL);
91462306a36Sopenharmony_ci					break;
91562306a36Sopenharmony_ci				}
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci				if (strstr(field->type, "__rel_loc")) {
91862306a36Sopenharmony_ci					print_array(iter, pos, field);
91962306a36Sopenharmony_ci					break;
92062306a36Sopenharmony_ci				}
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci				trace_seq_printf(&iter->seq, "0x%x (%d)",
92362306a36Sopenharmony_ci						 *(unsigned int *)pos,
92462306a36Sopenharmony_ci						 *(unsigned int *)pos);
92562306a36Sopenharmony_ci				break;
92662306a36Sopenharmony_ci			case 8:
92762306a36Sopenharmony_ci				trace_seq_printf(&iter->seq, "0x%llx (%lld)",
92862306a36Sopenharmony_ci						 *(unsigned long long *)pos,
92962306a36Sopenharmony_ci						 *(unsigned long long *)pos);
93062306a36Sopenharmony_ci				break;
93162306a36Sopenharmony_ci			default:
93262306a36Sopenharmony_ci				trace_seq_puts(&iter->seq, "<INVALID-SIZE>");
93362306a36Sopenharmony_ci				break;
93462306a36Sopenharmony_ci			}
93562306a36Sopenharmony_ci			break;
93662306a36Sopenharmony_ci		default:
93762306a36Sopenharmony_ci			trace_seq_puts(&iter->seq, "<INVALID-TYPE>");
93862306a36Sopenharmony_ci		}
93962306a36Sopenharmony_ci	}
94062306a36Sopenharmony_ci	trace_seq_putc(&iter->seq, '\n');
94162306a36Sopenharmony_ci}
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_cienum print_line_t print_event_fields(struct trace_iterator *iter,
94462306a36Sopenharmony_ci				     struct trace_event *event)
94562306a36Sopenharmony_ci{
94662306a36Sopenharmony_ci	struct trace_event_call *call;
94762306a36Sopenharmony_ci	struct list_head *head;
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_ci	/* ftrace defined events have separate call structures */
95062306a36Sopenharmony_ci	if (event->type <= __TRACE_LAST_TYPE) {
95162306a36Sopenharmony_ci		bool found = false;
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci		down_read(&trace_event_sem);
95462306a36Sopenharmony_ci		list_for_each_entry(call, &ftrace_events, list) {
95562306a36Sopenharmony_ci			if (call->event.type == event->type) {
95662306a36Sopenharmony_ci				found = true;
95762306a36Sopenharmony_ci				break;
95862306a36Sopenharmony_ci			}
95962306a36Sopenharmony_ci			/* No need to search all events */
96062306a36Sopenharmony_ci			if (call->event.type > __TRACE_LAST_TYPE)
96162306a36Sopenharmony_ci				break;
96262306a36Sopenharmony_ci		}
96362306a36Sopenharmony_ci		up_read(&trace_event_sem);
96462306a36Sopenharmony_ci		if (!found) {
96562306a36Sopenharmony_ci			trace_seq_printf(&iter->seq, "UNKNOWN TYPE %d\n", event->type);
96662306a36Sopenharmony_ci			goto out;
96762306a36Sopenharmony_ci		}
96862306a36Sopenharmony_ci	} else {
96962306a36Sopenharmony_ci		call = container_of(event, struct trace_event_call, event);
97062306a36Sopenharmony_ci	}
97162306a36Sopenharmony_ci	head = trace_get_fields(call);
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci	trace_seq_printf(&iter->seq, "%s:", trace_event_name(call));
97462306a36Sopenharmony_ci
97562306a36Sopenharmony_ci	if (head && !list_empty(head))
97662306a36Sopenharmony_ci		print_fields(iter, call, head);
97762306a36Sopenharmony_ci	else
97862306a36Sopenharmony_ci		trace_seq_puts(&iter->seq, "No fields found\n");
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci out:
98162306a36Sopenharmony_ci	return trace_handle_return(&iter->seq);
98262306a36Sopenharmony_ci}
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_cienum print_line_t trace_nop_print(struct trace_iterator *iter, int flags,
98562306a36Sopenharmony_ci				  struct trace_event *event)
98662306a36Sopenharmony_ci{
98762306a36Sopenharmony_ci	trace_seq_printf(&iter->seq, "type: %d\n", iter->ent->type);
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci	return trace_handle_return(&iter->seq);
99062306a36Sopenharmony_ci}
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_cistatic void print_fn_trace(struct trace_seq *s, unsigned long ip,
99362306a36Sopenharmony_ci			   unsigned long parent_ip, int flags)
99462306a36Sopenharmony_ci{
99562306a36Sopenharmony_ci	seq_print_ip_sym(s, ip, flags);
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci	if ((flags & TRACE_ITER_PRINT_PARENT) && parent_ip) {
99862306a36Sopenharmony_ci		trace_seq_puts(s, " <-");
99962306a36Sopenharmony_ci		seq_print_ip_sym(s, parent_ip, flags);
100062306a36Sopenharmony_ci	}
100162306a36Sopenharmony_ci}
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_ci/* TRACE_FN */
100462306a36Sopenharmony_cistatic enum print_line_t trace_fn_trace(struct trace_iterator *iter, int flags,
100562306a36Sopenharmony_ci					struct trace_event *event)
100662306a36Sopenharmony_ci{
100762306a36Sopenharmony_ci	struct ftrace_entry *field;
100862306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci	print_fn_trace(s, field->ip, field->parent_ip, flags);
101362306a36Sopenharmony_ci	trace_seq_putc(s, '\n');
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci	return trace_handle_return(s);
101662306a36Sopenharmony_ci}
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_cistatic enum print_line_t trace_fn_raw(struct trace_iterator *iter, int flags,
101962306a36Sopenharmony_ci				      struct trace_event *event)
102062306a36Sopenharmony_ci{
102162306a36Sopenharmony_ci	struct ftrace_entry *field;
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_ci	trace_seq_printf(&iter->seq, "%lx %lx\n",
102662306a36Sopenharmony_ci			 field->ip,
102762306a36Sopenharmony_ci			 field->parent_ip);
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci	return trace_handle_return(&iter->seq);
103062306a36Sopenharmony_ci}
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_cistatic enum print_line_t trace_fn_hex(struct trace_iterator *iter, int flags,
103362306a36Sopenharmony_ci				      struct trace_event *event)
103462306a36Sopenharmony_ci{
103562306a36Sopenharmony_ci	struct ftrace_entry *field;
103662306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
103962306a36Sopenharmony_ci
104062306a36Sopenharmony_ci	SEQ_PUT_HEX_FIELD(s, field->ip);
104162306a36Sopenharmony_ci	SEQ_PUT_HEX_FIELD(s, field->parent_ip);
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci	return trace_handle_return(s);
104462306a36Sopenharmony_ci}
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_cistatic enum print_line_t trace_fn_bin(struct trace_iterator *iter, int flags,
104762306a36Sopenharmony_ci				      struct trace_event *event)
104862306a36Sopenharmony_ci{
104962306a36Sopenharmony_ci	struct ftrace_entry *field;
105062306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci	SEQ_PUT_FIELD(s, field->ip);
105562306a36Sopenharmony_ci	SEQ_PUT_FIELD(s, field->parent_ip);
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_ci	return trace_handle_return(s);
105862306a36Sopenharmony_ci}
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_cistatic struct trace_event_functions trace_fn_funcs = {
106162306a36Sopenharmony_ci	.trace		= trace_fn_trace,
106262306a36Sopenharmony_ci	.raw		= trace_fn_raw,
106362306a36Sopenharmony_ci	.hex		= trace_fn_hex,
106462306a36Sopenharmony_ci	.binary		= trace_fn_bin,
106562306a36Sopenharmony_ci};
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_cistatic struct trace_event trace_fn_event = {
106862306a36Sopenharmony_ci	.type		= TRACE_FN,
106962306a36Sopenharmony_ci	.funcs		= &trace_fn_funcs,
107062306a36Sopenharmony_ci};
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ci/* TRACE_CTX an TRACE_WAKE */
107362306a36Sopenharmony_cistatic enum print_line_t trace_ctxwake_print(struct trace_iterator *iter,
107462306a36Sopenharmony_ci					     char *delim)
107562306a36Sopenharmony_ci{
107662306a36Sopenharmony_ci	struct ctx_switch_entry *field;
107762306a36Sopenharmony_ci	char comm[TASK_COMM_LEN];
107862306a36Sopenharmony_ci	int S, T;
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	T = task_index_to_char(field->next_state);
108462306a36Sopenharmony_ci	S = task_index_to_char(field->prev_state);
108562306a36Sopenharmony_ci	trace_find_cmdline(field->next_pid, comm);
108662306a36Sopenharmony_ci	trace_seq_printf(&iter->seq,
108762306a36Sopenharmony_ci			 " %7d:%3d:%c %s [%03d] %7d:%3d:%c %s\n",
108862306a36Sopenharmony_ci			 field->prev_pid,
108962306a36Sopenharmony_ci			 field->prev_prio,
109062306a36Sopenharmony_ci			 S, delim,
109162306a36Sopenharmony_ci			 field->next_cpu,
109262306a36Sopenharmony_ci			 field->next_pid,
109362306a36Sopenharmony_ci			 field->next_prio,
109462306a36Sopenharmony_ci			 T, comm);
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci	return trace_handle_return(&iter->seq);
109762306a36Sopenharmony_ci}
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_cistatic enum print_line_t trace_ctx_print(struct trace_iterator *iter, int flags,
110062306a36Sopenharmony_ci					 struct trace_event *event)
110162306a36Sopenharmony_ci{
110262306a36Sopenharmony_ci	return trace_ctxwake_print(iter, "==>");
110362306a36Sopenharmony_ci}
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_cistatic enum print_line_t trace_wake_print(struct trace_iterator *iter,
110662306a36Sopenharmony_ci					  int flags, struct trace_event *event)
110762306a36Sopenharmony_ci{
110862306a36Sopenharmony_ci	return trace_ctxwake_print(iter, "  +");
110962306a36Sopenharmony_ci}
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_cistatic int trace_ctxwake_raw(struct trace_iterator *iter, char S)
111262306a36Sopenharmony_ci{
111362306a36Sopenharmony_ci	struct ctx_switch_entry *field;
111462306a36Sopenharmony_ci	int T;
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci	if (!S)
111962306a36Sopenharmony_ci		S = task_index_to_char(field->prev_state);
112062306a36Sopenharmony_ci	T = task_index_to_char(field->next_state);
112162306a36Sopenharmony_ci	trace_seq_printf(&iter->seq, "%d %d %c %d %d %d %c\n",
112262306a36Sopenharmony_ci			 field->prev_pid,
112362306a36Sopenharmony_ci			 field->prev_prio,
112462306a36Sopenharmony_ci			 S,
112562306a36Sopenharmony_ci			 field->next_cpu,
112662306a36Sopenharmony_ci			 field->next_pid,
112762306a36Sopenharmony_ci			 field->next_prio,
112862306a36Sopenharmony_ci			 T);
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci	return trace_handle_return(&iter->seq);
113162306a36Sopenharmony_ci}
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_cistatic enum print_line_t trace_ctx_raw(struct trace_iterator *iter, int flags,
113462306a36Sopenharmony_ci				       struct trace_event *event)
113562306a36Sopenharmony_ci{
113662306a36Sopenharmony_ci	return trace_ctxwake_raw(iter, 0);
113762306a36Sopenharmony_ci}
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_cistatic enum print_line_t trace_wake_raw(struct trace_iterator *iter, int flags,
114062306a36Sopenharmony_ci					struct trace_event *event)
114162306a36Sopenharmony_ci{
114262306a36Sopenharmony_ci	return trace_ctxwake_raw(iter, '+');
114362306a36Sopenharmony_ci}
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_cistatic int trace_ctxwake_hex(struct trace_iterator *iter, char S)
114762306a36Sopenharmony_ci{
114862306a36Sopenharmony_ci	struct ctx_switch_entry *field;
114962306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
115062306a36Sopenharmony_ci	int T;
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_ci	if (!S)
115562306a36Sopenharmony_ci		S = task_index_to_char(field->prev_state);
115662306a36Sopenharmony_ci	T = task_index_to_char(field->next_state);
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci	SEQ_PUT_HEX_FIELD(s, field->prev_pid);
115962306a36Sopenharmony_ci	SEQ_PUT_HEX_FIELD(s, field->prev_prio);
116062306a36Sopenharmony_ci	SEQ_PUT_HEX_FIELD(s, S);
116162306a36Sopenharmony_ci	SEQ_PUT_HEX_FIELD(s, field->next_cpu);
116262306a36Sopenharmony_ci	SEQ_PUT_HEX_FIELD(s, field->next_pid);
116362306a36Sopenharmony_ci	SEQ_PUT_HEX_FIELD(s, field->next_prio);
116462306a36Sopenharmony_ci	SEQ_PUT_HEX_FIELD(s, T);
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci	return trace_handle_return(s);
116762306a36Sopenharmony_ci}
116862306a36Sopenharmony_ci
116962306a36Sopenharmony_cistatic enum print_line_t trace_ctx_hex(struct trace_iterator *iter, int flags,
117062306a36Sopenharmony_ci				       struct trace_event *event)
117162306a36Sopenharmony_ci{
117262306a36Sopenharmony_ci	return trace_ctxwake_hex(iter, 0);
117362306a36Sopenharmony_ci}
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_cistatic enum print_line_t trace_wake_hex(struct trace_iterator *iter, int flags,
117662306a36Sopenharmony_ci					struct trace_event *event)
117762306a36Sopenharmony_ci{
117862306a36Sopenharmony_ci	return trace_ctxwake_hex(iter, '+');
117962306a36Sopenharmony_ci}
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_cistatic enum print_line_t trace_ctxwake_bin(struct trace_iterator *iter,
118262306a36Sopenharmony_ci					   int flags, struct trace_event *event)
118362306a36Sopenharmony_ci{
118462306a36Sopenharmony_ci	struct ctx_switch_entry *field;
118562306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
118662306a36Sopenharmony_ci
118762306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
118862306a36Sopenharmony_ci
118962306a36Sopenharmony_ci	SEQ_PUT_FIELD(s, field->prev_pid);
119062306a36Sopenharmony_ci	SEQ_PUT_FIELD(s, field->prev_prio);
119162306a36Sopenharmony_ci	SEQ_PUT_FIELD(s, field->prev_state);
119262306a36Sopenharmony_ci	SEQ_PUT_FIELD(s, field->next_cpu);
119362306a36Sopenharmony_ci	SEQ_PUT_FIELD(s, field->next_pid);
119462306a36Sopenharmony_ci	SEQ_PUT_FIELD(s, field->next_prio);
119562306a36Sopenharmony_ci	SEQ_PUT_FIELD(s, field->next_state);
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_ci	return trace_handle_return(s);
119862306a36Sopenharmony_ci}
119962306a36Sopenharmony_ci
120062306a36Sopenharmony_cistatic struct trace_event_functions trace_ctx_funcs = {
120162306a36Sopenharmony_ci	.trace		= trace_ctx_print,
120262306a36Sopenharmony_ci	.raw		= trace_ctx_raw,
120362306a36Sopenharmony_ci	.hex		= trace_ctx_hex,
120462306a36Sopenharmony_ci	.binary		= trace_ctxwake_bin,
120562306a36Sopenharmony_ci};
120662306a36Sopenharmony_ci
120762306a36Sopenharmony_cistatic struct trace_event trace_ctx_event = {
120862306a36Sopenharmony_ci	.type		= TRACE_CTX,
120962306a36Sopenharmony_ci	.funcs		= &trace_ctx_funcs,
121062306a36Sopenharmony_ci};
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_cistatic struct trace_event_functions trace_wake_funcs = {
121362306a36Sopenharmony_ci	.trace		= trace_wake_print,
121462306a36Sopenharmony_ci	.raw		= trace_wake_raw,
121562306a36Sopenharmony_ci	.hex		= trace_wake_hex,
121662306a36Sopenharmony_ci	.binary		= trace_ctxwake_bin,
121762306a36Sopenharmony_ci};
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_cistatic struct trace_event trace_wake_event = {
122062306a36Sopenharmony_ci	.type		= TRACE_WAKE,
122162306a36Sopenharmony_ci	.funcs		= &trace_wake_funcs,
122262306a36Sopenharmony_ci};
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci/* TRACE_STACK */
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_cistatic enum print_line_t trace_stack_print(struct trace_iterator *iter,
122762306a36Sopenharmony_ci					   int flags, struct trace_event *event)
122862306a36Sopenharmony_ci{
122962306a36Sopenharmony_ci	struct stack_entry *field;
123062306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
123162306a36Sopenharmony_ci	unsigned long *p;
123262306a36Sopenharmony_ci	unsigned long *end;
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
123562306a36Sopenharmony_ci	end = (unsigned long *)((long)iter->ent + iter->ent_size);
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci	trace_seq_puts(s, "<stack trace>\n");
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_ci	for (p = field->caller; p && p < end && *p != ULONG_MAX; p++) {
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ci		if (trace_seq_has_overflowed(s))
124262306a36Sopenharmony_ci			break;
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_ci		trace_seq_puts(s, " => ");
124562306a36Sopenharmony_ci		seq_print_ip_sym(s, *p, flags);
124662306a36Sopenharmony_ci		trace_seq_putc(s, '\n');
124762306a36Sopenharmony_ci	}
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci	return trace_handle_return(s);
125062306a36Sopenharmony_ci}
125162306a36Sopenharmony_ci
125262306a36Sopenharmony_cistatic struct trace_event_functions trace_stack_funcs = {
125362306a36Sopenharmony_ci	.trace		= trace_stack_print,
125462306a36Sopenharmony_ci};
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_cistatic struct trace_event trace_stack_event = {
125762306a36Sopenharmony_ci	.type		= TRACE_STACK,
125862306a36Sopenharmony_ci	.funcs		= &trace_stack_funcs,
125962306a36Sopenharmony_ci};
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci/* TRACE_USER_STACK */
126262306a36Sopenharmony_cistatic enum print_line_t trace_user_stack_print(struct trace_iterator *iter,
126362306a36Sopenharmony_ci						int flags, struct trace_event *event)
126462306a36Sopenharmony_ci{
126562306a36Sopenharmony_ci	struct trace_array *tr = iter->tr;
126662306a36Sopenharmony_ci	struct userstack_entry *field;
126762306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
126862306a36Sopenharmony_ci	struct mm_struct *mm = NULL;
126962306a36Sopenharmony_ci	unsigned int i;
127062306a36Sopenharmony_ci
127162306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
127262306a36Sopenharmony_ci
127362306a36Sopenharmony_ci	trace_seq_puts(s, "<user stack trace>\n");
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_ci	if (tr->trace_flags & TRACE_ITER_SYM_USEROBJ) {
127662306a36Sopenharmony_ci		struct task_struct *task;
127762306a36Sopenharmony_ci		/*
127862306a36Sopenharmony_ci		 * we do the lookup on the thread group leader,
127962306a36Sopenharmony_ci		 * since individual threads might have already quit!
128062306a36Sopenharmony_ci		 */
128162306a36Sopenharmony_ci		rcu_read_lock();
128262306a36Sopenharmony_ci		task = find_task_by_vpid(field->tgid);
128362306a36Sopenharmony_ci		if (task)
128462306a36Sopenharmony_ci			mm = get_task_mm(task);
128562306a36Sopenharmony_ci		rcu_read_unlock();
128662306a36Sopenharmony_ci	}
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci	for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
128962306a36Sopenharmony_ci		unsigned long ip = field->caller[i];
129062306a36Sopenharmony_ci
129162306a36Sopenharmony_ci		if (!ip || trace_seq_has_overflowed(s))
129262306a36Sopenharmony_ci			break;
129362306a36Sopenharmony_ci
129462306a36Sopenharmony_ci		trace_seq_puts(s, " => ");
129562306a36Sopenharmony_ci		seq_print_user_ip(s, mm, ip, flags);
129662306a36Sopenharmony_ci		trace_seq_putc(s, '\n');
129762306a36Sopenharmony_ci	}
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_ci	if (mm)
130062306a36Sopenharmony_ci		mmput(mm);
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	return trace_handle_return(s);
130362306a36Sopenharmony_ci}
130462306a36Sopenharmony_ci
130562306a36Sopenharmony_cistatic struct trace_event_functions trace_user_stack_funcs = {
130662306a36Sopenharmony_ci	.trace		= trace_user_stack_print,
130762306a36Sopenharmony_ci};
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_cistatic struct trace_event trace_user_stack_event = {
131062306a36Sopenharmony_ci	.type		= TRACE_USER_STACK,
131162306a36Sopenharmony_ci	.funcs		= &trace_user_stack_funcs,
131262306a36Sopenharmony_ci};
131362306a36Sopenharmony_ci
131462306a36Sopenharmony_ci/* TRACE_HWLAT */
131562306a36Sopenharmony_cistatic enum print_line_t
131662306a36Sopenharmony_citrace_hwlat_print(struct trace_iterator *iter, int flags,
131762306a36Sopenharmony_ci		  struct trace_event *event)
131862306a36Sopenharmony_ci{
131962306a36Sopenharmony_ci	struct trace_entry *entry = iter->ent;
132062306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
132162306a36Sopenharmony_ci	struct hwlat_entry *field;
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci	trace_assign_type(field, entry);
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_ci	trace_seq_printf(s, "#%-5u inner/outer(us): %4llu/%-5llu ts:%lld.%09ld count:%d",
132662306a36Sopenharmony_ci			 field->seqnum,
132762306a36Sopenharmony_ci			 field->duration,
132862306a36Sopenharmony_ci			 field->outer_duration,
132962306a36Sopenharmony_ci			 (long long)field->timestamp.tv_sec,
133062306a36Sopenharmony_ci			 field->timestamp.tv_nsec, field->count);
133162306a36Sopenharmony_ci
133262306a36Sopenharmony_ci	if (field->nmi_count) {
133362306a36Sopenharmony_ci		/*
133462306a36Sopenharmony_ci		 * The generic sched_clock() is not NMI safe, thus
133562306a36Sopenharmony_ci		 * we only record the count and not the time.
133662306a36Sopenharmony_ci		 */
133762306a36Sopenharmony_ci		if (!IS_ENABLED(CONFIG_GENERIC_SCHED_CLOCK))
133862306a36Sopenharmony_ci			trace_seq_printf(s, " nmi-total:%llu",
133962306a36Sopenharmony_ci					 field->nmi_total_ts);
134062306a36Sopenharmony_ci		trace_seq_printf(s, " nmi-count:%u",
134162306a36Sopenharmony_ci				 field->nmi_count);
134262306a36Sopenharmony_ci	}
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_ci	trace_seq_putc(s, '\n');
134562306a36Sopenharmony_ci
134662306a36Sopenharmony_ci	return trace_handle_return(s);
134762306a36Sopenharmony_ci}
134862306a36Sopenharmony_ci
134962306a36Sopenharmony_cistatic enum print_line_t
135062306a36Sopenharmony_citrace_hwlat_raw(struct trace_iterator *iter, int flags,
135162306a36Sopenharmony_ci		struct trace_event *event)
135262306a36Sopenharmony_ci{
135362306a36Sopenharmony_ci	struct hwlat_entry *field;
135462306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
135562306a36Sopenharmony_ci
135662306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
135762306a36Sopenharmony_ci
135862306a36Sopenharmony_ci	trace_seq_printf(s, "%llu %lld %lld %09ld %u\n",
135962306a36Sopenharmony_ci			 field->duration,
136062306a36Sopenharmony_ci			 field->outer_duration,
136162306a36Sopenharmony_ci			 (long long)field->timestamp.tv_sec,
136262306a36Sopenharmony_ci			 field->timestamp.tv_nsec,
136362306a36Sopenharmony_ci			 field->seqnum);
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_ci	return trace_handle_return(s);
136662306a36Sopenharmony_ci}
136762306a36Sopenharmony_ci
136862306a36Sopenharmony_cistatic struct trace_event_functions trace_hwlat_funcs = {
136962306a36Sopenharmony_ci	.trace		= trace_hwlat_print,
137062306a36Sopenharmony_ci	.raw		= trace_hwlat_raw,
137162306a36Sopenharmony_ci};
137262306a36Sopenharmony_ci
137362306a36Sopenharmony_cistatic struct trace_event trace_hwlat_event = {
137462306a36Sopenharmony_ci	.type		= TRACE_HWLAT,
137562306a36Sopenharmony_ci	.funcs		= &trace_hwlat_funcs,
137662306a36Sopenharmony_ci};
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci/* TRACE_OSNOISE */
137962306a36Sopenharmony_cistatic enum print_line_t
138062306a36Sopenharmony_citrace_osnoise_print(struct trace_iterator *iter, int flags,
138162306a36Sopenharmony_ci		    struct trace_event *event)
138262306a36Sopenharmony_ci{
138362306a36Sopenharmony_ci	struct trace_entry *entry = iter->ent;
138462306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
138562306a36Sopenharmony_ci	struct osnoise_entry *field;
138662306a36Sopenharmony_ci	u64 ratio, ratio_dec;
138762306a36Sopenharmony_ci	u64 net_runtime;
138862306a36Sopenharmony_ci
138962306a36Sopenharmony_ci	trace_assign_type(field, entry);
139062306a36Sopenharmony_ci
139162306a36Sopenharmony_ci	/*
139262306a36Sopenharmony_ci	 * compute the available % of cpu time.
139362306a36Sopenharmony_ci	 */
139462306a36Sopenharmony_ci	net_runtime = field->runtime - field->noise;
139562306a36Sopenharmony_ci	ratio = net_runtime * 10000000;
139662306a36Sopenharmony_ci	do_div(ratio, field->runtime);
139762306a36Sopenharmony_ci	ratio_dec = do_div(ratio, 100000);
139862306a36Sopenharmony_ci
139962306a36Sopenharmony_ci	trace_seq_printf(s, "%llu %10llu %3llu.%05llu %7llu",
140062306a36Sopenharmony_ci			 field->runtime,
140162306a36Sopenharmony_ci			 field->noise,
140262306a36Sopenharmony_ci			 ratio, ratio_dec,
140362306a36Sopenharmony_ci			 field->max_sample);
140462306a36Sopenharmony_ci
140562306a36Sopenharmony_ci	trace_seq_printf(s, " %6u", field->hw_count);
140662306a36Sopenharmony_ci	trace_seq_printf(s, " %6u", field->nmi_count);
140762306a36Sopenharmony_ci	trace_seq_printf(s, " %6u", field->irq_count);
140862306a36Sopenharmony_ci	trace_seq_printf(s, " %6u", field->softirq_count);
140962306a36Sopenharmony_ci	trace_seq_printf(s, " %6u", field->thread_count);
141062306a36Sopenharmony_ci
141162306a36Sopenharmony_ci	trace_seq_putc(s, '\n');
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci	return trace_handle_return(s);
141462306a36Sopenharmony_ci}
141562306a36Sopenharmony_ci
141662306a36Sopenharmony_cistatic enum print_line_t
141762306a36Sopenharmony_citrace_osnoise_raw(struct trace_iterator *iter, int flags,
141862306a36Sopenharmony_ci		  struct trace_event *event)
141962306a36Sopenharmony_ci{
142062306a36Sopenharmony_ci	struct osnoise_entry *field;
142162306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
142462306a36Sopenharmony_ci
142562306a36Sopenharmony_ci	trace_seq_printf(s, "%lld %llu %llu %u %u %u %u %u\n",
142662306a36Sopenharmony_ci			 field->runtime,
142762306a36Sopenharmony_ci			 field->noise,
142862306a36Sopenharmony_ci			 field->max_sample,
142962306a36Sopenharmony_ci			 field->hw_count,
143062306a36Sopenharmony_ci			 field->nmi_count,
143162306a36Sopenharmony_ci			 field->irq_count,
143262306a36Sopenharmony_ci			 field->softirq_count,
143362306a36Sopenharmony_ci			 field->thread_count);
143462306a36Sopenharmony_ci
143562306a36Sopenharmony_ci	return trace_handle_return(s);
143662306a36Sopenharmony_ci}
143762306a36Sopenharmony_ci
143862306a36Sopenharmony_cistatic struct trace_event_functions trace_osnoise_funcs = {
143962306a36Sopenharmony_ci	.trace		= trace_osnoise_print,
144062306a36Sopenharmony_ci	.raw		= trace_osnoise_raw,
144162306a36Sopenharmony_ci};
144262306a36Sopenharmony_ci
144362306a36Sopenharmony_cistatic struct trace_event trace_osnoise_event = {
144462306a36Sopenharmony_ci	.type		= TRACE_OSNOISE,
144562306a36Sopenharmony_ci	.funcs		= &trace_osnoise_funcs,
144662306a36Sopenharmony_ci};
144762306a36Sopenharmony_ci
144862306a36Sopenharmony_ci/* TRACE_TIMERLAT */
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_cistatic char *timerlat_lat_context[] = {"irq", "thread", "user-ret"};
145162306a36Sopenharmony_cistatic enum print_line_t
145262306a36Sopenharmony_citrace_timerlat_print(struct trace_iterator *iter, int flags,
145362306a36Sopenharmony_ci		     struct trace_event *event)
145462306a36Sopenharmony_ci{
145562306a36Sopenharmony_ci	struct trace_entry *entry = iter->ent;
145662306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
145762306a36Sopenharmony_ci	struct timerlat_entry *field;
145862306a36Sopenharmony_ci
145962306a36Sopenharmony_ci	trace_assign_type(field, entry);
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	trace_seq_printf(s, "#%-5u context %6s timer_latency %9llu ns\n",
146262306a36Sopenharmony_ci			 field->seqnum,
146362306a36Sopenharmony_ci			 timerlat_lat_context[field->context],
146462306a36Sopenharmony_ci			 field->timer_latency);
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci	return trace_handle_return(s);
146762306a36Sopenharmony_ci}
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_cistatic enum print_line_t
147062306a36Sopenharmony_citrace_timerlat_raw(struct trace_iterator *iter, int flags,
147162306a36Sopenharmony_ci		   struct trace_event *event)
147262306a36Sopenharmony_ci{
147362306a36Sopenharmony_ci	struct timerlat_entry *field;
147462306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
147762306a36Sopenharmony_ci
147862306a36Sopenharmony_ci	trace_seq_printf(s, "%u %d %llu\n",
147962306a36Sopenharmony_ci			 field->seqnum,
148062306a36Sopenharmony_ci			 field->context,
148162306a36Sopenharmony_ci			 field->timer_latency);
148262306a36Sopenharmony_ci
148362306a36Sopenharmony_ci	return trace_handle_return(s);
148462306a36Sopenharmony_ci}
148562306a36Sopenharmony_ci
148662306a36Sopenharmony_cistatic struct trace_event_functions trace_timerlat_funcs = {
148762306a36Sopenharmony_ci	.trace		= trace_timerlat_print,
148862306a36Sopenharmony_ci	.raw		= trace_timerlat_raw,
148962306a36Sopenharmony_ci};
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_cistatic struct trace_event trace_timerlat_event = {
149262306a36Sopenharmony_ci	.type		= TRACE_TIMERLAT,
149362306a36Sopenharmony_ci	.funcs		= &trace_timerlat_funcs,
149462306a36Sopenharmony_ci};
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci/* TRACE_BPUTS */
149762306a36Sopenharmony_cistatic enum print_line_t
149862306a36Sopenharmony_citrace_bputs_print(struct trace_iterator *iter, int flags,
149962306a36Sopenharmony_ci		   struct trace_event *event)
150062306a36Sopenharmony_ci{
150162306a36Sopenharmony_ci	struct trace_entry *entry = iter->ent;
150262306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
150362306a36Sopenharmony_ci	struct bputs_entry *field;
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci	trace_assign_type(field, entry);
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci	seq_print_ip_sym(s, field->ip, flags);
150862306a36Sopenharmony_ci	trace_seq_puts(s, ": ");
150962306a36Sopenharmony_ci	trace_seq_puts(s, field->str);
151062306a36Sopenharmony_ci
151162306a36Sopenharmony_ci	return trace_handle_return(s);
151262306a36Sopenharmony_ci}
151362306a36Sopenharmony_ci
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_cistatic enum print_line_t
151662306a36Sopenharmony_citrace_bputs_raw(struct trace_iterator *iter, int flags,
151762306a36Sopenharmony_ci		struct trace_event *event)
151862306a36Sopenharmony_ci{
151962306a36Sopenharmony_ci	struct bputs_entry *field;
152062306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
152162306a36Sopenharmony_ci
152262306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
152362306a36Sopenharmony_ci
152462306a36Sopenharmony_ci	trace_seq_printf(s, ": %lx : ", field->ip);
152562306a36Sopenharmony_ci	trace_seq_puts(s, field->str);
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_ci	return trace_handle_return(s);
152862306a36Sopenharmony_ci}
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_cistatic struct trace_event_functions trace_bputs_funcs = {
153162306a36Sopenharmony_ci	.trace		= trace_bputs_print,
153262306a36Sopenharmony_ci	.raw		= trace_bputs_raw,
153362306a36Sopenharmony_ci};
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_cistatic struct trace_event trace_bputs_event = {
153662306a36Sopenharmony_ci	.type		= TRACE_BPUTS,
153762306a36Sopenharmony_ci	.funcs		= &trace_bputs_funcs,
153862306a36Sopenharmony_ci};
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci/* TRACE_BPRINT */
154162306a36Sopenharmony_cistatic enum print_line_t
154262306a36Sopenharmony_citrace_bprint_print(struct trace_iterator *iter, int flags,
154362306a36Sopenharmony_ci		   struct trace_event *event)
154462306a36Sopenharmony_ci{
154562306a36Sopenharmony_ci	struct trace_entry *entry = iter->ent;
154662306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
154762306a36Sopenharmony_ci	struct bprint_entry *field;
154862306a36Sopenharmony_ci
154962306a36Sopenharmony_ci	trace_assign_type(field, entry);
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	seq_print_ip_sym(s, field->ip, flags);
155262306a36Sopenharmony_ci	trace_seq_puts(s, ": ");
155362306a36Sopenharmony_ci	trace_seq_bprintf(s, field->fmt, field->buf);
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_ci	return trace_handle_return(s);
155662306a36Sopenharmony_ci}
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_ci
155962306a36Sopenharmony_cistatic enum print_line_t
156062306a36Sopenharmony_citrace_bprint_raw(struct trace_iterator *iter, int flags,
156162306a36Sopenharmony_ci		 struct trace_event *event)
156262306a36Sopenharmony_ci{
156362306a36Sopenharmony_ci	struct bprint_entry *field;
156462306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
156762306a36Sopenharmony_ci
156862306a36Sopenharmony_ci	trace_seq_printf(s, ": %lx : ", field->ip);
156962306a36Sopenharmony_ci	trace_seq_bprintf(s, field->fmt, field->buf);
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci	return trace_handle_return(s);
157262306a36Sopenharmony_ci}
157362306a36Sopenharmony_ci
157462306a36Sopenharmony_cistatic struct trace_event_functions trace_bprint_funcs = {
157562306a36Sopenharmony_ci	.trace		= trace_bprint_print,
157662306a36Sopenharmony_ci	.raw		= trace_bprint_raw,
157762306a36Sopenharmony_ci};
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_cistatic struct trace_event trace_bprint_event = {
158062306a36Sopenharmony_ci	.type		= TRACE_BPRINT,
158162306a36Sopenharmony_ci	.funcs		= &trace_bprint_funcs,
158262306a36Sopenharmony_ci};
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci/* TRACE_PRINT */
158562306a36Sopenharmony_cistatic enum print_line_t trace_print_print(struct trace_iterator *iter,
158662306a36Sopenharmony_ci					   int flags, struct trace_event *event)
158762306a36Sopenharmony_ci{
158862306a36Sopenharmony_ci	struct print_entry *field;
158962306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
159062306a36Sopenharmony_ci	int max = iter->ent_size - offsetof(struct print_entry, buf);
159162306a36Sopenharmony_ci
159262306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
159362306a36Sopenharmony_ci
159462306a36Sopenharmony_ci	seq_print_ip_sym(s, field->ip, flags);
159562306a36Sopenharmony_ci	trace_seq_printf(s, ": %.*s", max, field->buf);
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_ci	return trace_handle_return(s);
159862306a36Sopenharmony_ci}
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_cistatic enum print_line_t trace_print_raw(struct trace_iterator *iter, int flags,
160162306a36Sopenharmony_ci					 struct trace_event *event)
160262306a36Sopenharmony_ci{
160362306a36Sopenharmony_ci	struct print_entry *field;
160462306a36Sopenharmony_ci	int max = iter->ent_size - offsetof(struct print_entry, buf);
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
160762306a36Sopenharmony_ci
160862306a36Sopenharmony_ci	trace_seq_printf(&iter->seq, "# %lx %.*s", field->ip, max, field->buf);
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci	return trace_handle_return(&iter->seq);
161162306a36Sopenharmony_ci}
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_cistatic struct trace_event_functions trace_print_funcs = {
161462306a36Sopenharmony_ci	.trace		= trace_print_print,
161562306a36Sopenharmony_ci	.raw		= trace_print_raw,
161662306a36Sopenharmony_ci};
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_cistatic struct trace_event trace_print_event = {
161962306a36Sopenharmony_ci	.type	 	= TRACE_PRINT,
162062306a36Sopenharmony_ci	.funcs		= &trace_print_funcs,
162162306a36Sopenharmony_ci};
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_cistatic enum print_line_t trace_raw_data(struct trace_iterator *iter, int flags,
162462306a36Sopenharmony_ci					 struct trace_event *event)
162562306a36Sopenharmony_ci{
162662306a36Sopenharmony_ci	struct raw_data_entry *field;
162762306a36Sopenharmony_ci	int i;
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
163062306a36Sopenharmony_ci
163162306a36Sopenharmony_ci	trace_seq_printf(&iter->seq, "# %x buf:", field->id);
163262306a36Sopenharmony_ci
163362306a36Sopenharmony_ci	for (i = 0; i < iter->ent_size - offsetof(struct raw_data_entry, buf); i++)
163462306a36Sopenharmony_ci		trace_seq_printf(&iter->seq, " %02x",
163562306a36Sopenharmony_ci				 (unsigned char)field->buf[i]);
163662306a36Sopenharmony_ci
163762306a36Sopenharmony_ci	trace_seq_putc(&iter->seq, '\n');
163862306a36Sopenharmony_ci
163962306a36Sopenharmony_ci	return trace_handle_return(&iter->seq);
164062306a36Sopenharmony_ci}
164162306a36Sopenharmony_ci
164262306a36Sopenharmony_cistatic struct trace_event_functions trace_raw_data_funcs = {
164362306a36Sopenharmony_ci	.trace		= trace_raw_data,
164462306a36Sopenharmony_ci	.raw		= trace_raw_data,
164562306a36Sopenharmony_ci};
164662306a36Sopenharmony_ci
164762306a36Sopenharmony_cistatic struct trace_event trace_raw_data_event = {
164862306a36Sopenharmony_ci	.type	 	= TRACE_RAW_DATA,
164962306a36Sopenharmony_ci	.funcs		= &trace_raw_data_funcs,
165062306a36Sopenharmony_ci};
165162306a36Sopenharmony_ci
165262306a36Sopenharmony_cistatic enum print_line_t
165362306a36Sopenharmony_citrace_func_repeats_raw(struct trace_iterator *iter, int flags,
165462306a36Sopenharmony_ci			 struct trace_event *event)
165562306a36Sopenharmony_ci{
165662306a36Sopenharmony_ci	struct func_repeats_entry *field;
165762306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
165862306a36Sopenharmony_ci
165962306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
166062306a36Sopenharmony_ci
166162306a36Sopenharmony_ci	trace_seq_printf(s, "%lu %lu %u %llu\n",
166262306a36Sopenharmony_ci			 field->ip,
166362306a36Sopenharmony_ci			 field->parent_ip,
166462306a36Sopenharmony_ci			 field->count,
166562306a36Sopenharmony_ci			 FUNC_REPEATS_GET_DELTA_TS(field));
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_ci	return trace_handle_return(s);
166862306a36Sopenharmony_ci}
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_cistatic enum print_line_t
167162306a36Sopenharmony_citrace_func_repeats_print(struct trace_iterator *iter, int flags,
167262306a36Sopenharmony_ci			 struct trace_event *event)
167362306a36Sopenharmony_ci{
167462306a36Sopenharmony_ci	struct func_repeats_entry *field;
167562306a36Sopenharmony_ci	struct trace_seq *s = &iter->seq;
167662306a36Sopenharmony_ci
167762306a36Sopenharmony_ci	trace_assign_type(field, iter->ent);
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_ci	print_fn_trace(s, field->ip, field->parent_ip, flags);
168062306a36Sopenharmony_ci	trace_seq_printf(s, " (repeats: %u, last_ts:", field->count);
168162306a36Sopenharmony_ci	trace_print_time(s, iter,
168262306a36Sopenharmony_ci			 iter->ts - FUNC_REPEATS_GET_DELTA_TS(field));
168362306a36Sopenharmony_ci	trace_seq_puts(s, ")\n");
168462306a36Sopenharmony_ci
168562306a36Sopenharmony_ci	return trace_handle_return(s);
168662306a36Sopenharmony_ci}
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_cistatic struct trace_event_functions trace_func_repeats_funcs = {
168962306a36Sopenharmony_ci	.trace		= trace_func_repeats_print,
169062306a36Sopenharmony_ci	.raw		= trace_func_repeats_raw,
169162306a36Sopenharmony_ci};
169262306a36Sopenharmony_ci
169362306a36Sopenharmony_cistatic struct trace_event trace_func_repeats_event = {
169462306a36Sopenharmony_ci	.type	 	= TRACE_FUNC_REPEATS,
169562306a36Sopenharmony_ci	.funcs		= &trace_func_repeats_funcs,
169662306a36Sopenharmony_ci};
169762306a36Sopenharmony_ci
169862306a36Sopenharmony_cistatic struct trace_event *events[] __initdata = {
169962306a36Sopenharmony_ci	&trace_fn_event,
170062306a36Sopenharmony_ci	&trace_ctx_event,
170162306a36Sopenharmony_ci	&trace_wake_event,
170262306a36Sopenharmony_ci	&trace_stack_event,
170362306a36Sopenharmony_ci	&trace_user_stack_event,
170462306a36Sopenharmony_ci	&trace_bputs_event,
170562306a36Sopenharmony_ci	&trace_bprint_event,
170662306a36Sopenharmony_ci	&trace_print_event,
170762306a36Sopenharmony_ci	&trace_hwlat_event,
170862306a36Sopenharmony_ci	&trace_osnoise_event,
170962306a36Sopenharmony_ci	&trace_timerlat_event,
171062306a36Sopenharmony_ci	&trace_raw_data_event,
171162306a36Sopenharmony_ci	&trace_func_repeats_event,
171262306a36Sopenharmony_ci	NULL
171362306a36Sopenharmony_ci};
171462306a36Sopenharmony_ci
171562306a36Sopenharmony_ci__init int init_events(void)
171662306a36Sopenharmony_ci{
171762306a36Sopenharmony_ci	struct trace_event *event;
171862306a36Sopenharmony_ci	int i, ret;
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci	for (i = 0; events[i]; i++) {
172162306a36Sopenharmony_ci		event = events[i];
172262306a36Sopenharmony_ci		ret = register_trace_event(event);
172362306a36Sopenharmony_ci		WARN_ONCE(!ret, "event %d failed to register", event->type);
172462306a36Sopenharmony_ci	}
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_ci	return 0;
172762306a36Sopenharmony_ci}
1728