...
 
Commits (5)
......@@ -361,4 +361,11 @@ config PUNIT_ATOM_DEBUG
The current power state can be read from
/sys/kernel/debug/punit_atom/dev_power_state
config LCD_TRACE_BUFFER
bool "Trace ring buffer for LCD debugging"
default n
---help---
Trace ring buffer for dumping irq/softirq/lcd_enter events.
If unsure, say N.
endmenu
......@@ -619,6 +619,12 @@ END(irq_entries_start)
/* We entered an interrupt context - irqs are off: */
TRACE_IRQS_OFF
/* Trace IRQ into LCDs buffer, rdi = trap frame, rsi = event type */
pushq %rdi
movq $4, %rsi
call add_trace_entry_tf
popq %rdi
call \func /* rdi points to pt_regs */
.endm
......@@ -951,6 +957,14 @@ ENTRY(\sym)
subq $EXCEPTION_STKSZ, CPU_TSS_IST(\shift_ist)
.endif
/* Trace IRQ into LCDs buffer, rdi = trap frame, rsi = event type */
pushq %rdi
pushq %rsi
movq $6, %rsi
call add_trace_entry_tf
popq %rsi
popq %rdi
call \do_sym
.if \shift_ist != -1
......@@ -987,6 +1001,8 @@ ENTRY(\sym)
xorl %esi, %esi /* no error code */
.endif
call \do_sym
jmp error_exit /* %ebx: no swapgs flag */
......@@ -1523,6 +1539,12 @@ ENTRY(nmi_vmfunc_simple)
* done with the NMI stack.
*/
/* Trace IRQ into LCDs buffer, rdi = trap frame, rsi = event type */
movq %rsp, %rdi
movq $5, %rsi
call add_trace_entry_tf
movq %rsp, %rdi
movq $-1, %rsi
call do_nmi
......@@ -1581,6 +1603,11 @@ ENTRY(nmi_vmfunc_simple)
call paranoid_entry_vmfunc_nmi
// call paranoid_entry
/* Trace IRQ into LCDs buffer, rdi = trap frame, rsi = event type */
movq %rsp, %rdi
movq $5, %rsi
call add_trace_entry_tf
/* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */
movq %rsp, %rdi
movq $-1, %rsi
......
......@@ -41,6 +41,7 @@ CFLAGS_irq.o := -I$(src)/../include/asm/trace
obj-y := process_$(BITS).o signal.o
obj-$(CONFIG_COMPAT) += signal_compat.o
obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
obj-$(CONFIG_LCD_TRACE_BUFFER) += lcd_trace.o
obj-y += time.o ioport.o dumpstack.o nmi.o
obj-$(CONFIG_MODIFY_LDT_SYSCALL) += ldt.o
obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o
......
......@@ -15,7 +15,7 @@
#include <linux/nmi.h>
#include <asm/stacktrace.h>
#include <linux/lcd_trace.h>
#define N_EXCEPTION_STACKS_END \
(N_EXCEPTION_STACKS + DEBUG_STKSZ/EXCEPTION_STKSZ - 2)
......@@ -331,6 +331,8 @@ void show_regs(struct pt_regs *regs)
show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
0, KERN_DEFAULT);
dump_ring_trace_buffer();
printk(KERN_DEFAULT "Code: ");
ip = (u8 *)regs->ip - code_prologue;
......
#include <asm/ptrace.h>
#include <asm/current.h>
#include <linux/percpu.h>
#include <linux/sched.h>
#include <linux/lcd_trace.h>
DEFINE_PER_CPU_PAGE_ALIGNED(unsigned char, ring_buffer[RING_BUFFER_SIZE]);
DEFINE_PER_CPU(unsigned char, ring_head);
#define NUM_TRACE_ENTRIES (RING_BUFFER_SIZE / sizeof(struct ring_trace_entry))
char *trace_event_type_string[] = {
"xmit",
"msix_hndlr",
"napi_comp_done",
"irq",
"nmi",
"exception",
"softirq_rx_poll",
"net_rx_action"
};
asmlinkage __visible notrace void __add_trace_entry(trace_event_t type,
unsigned long rdi, unsigned long rsp, unsigned long eflags,
unsigned long ip)
{
int cpu = raw_smp_processor_id();
unsigned char *ring_buf_base = per_cpu(ring_buffer, cpu);
struct ring_trace_entry *ring_buf = (struct ring_trace_entry*) ring_buf_base;
unsigned char head_idx = __this_cpu_read(ring_head);
struct ring_trace_entry *entry = (struct ring_trace_entry*) &ring_buf[head_idx];
entry->rip = ip;
entry->rsp = rsp;
entry->rdi = rdi;
entry->eflags = eflags;
entry->lcd_stack = (unsigned long) current->lcd_stack;
entry->lcd_stack_bit = current->lcd_stack_bit;
entry->pid = current->pid;
entry->context = (!!in_irq() << IN_IRQ_SHIFT)
| (!!in_softirq() << IN_SOFTIRQ_SHIFT)
| (!!in_nmi() << IN_NMI_SHIFT);
entry->type = type;
snprintf(entry->name, PROC_NAME_MAX, current->comm);
__this_cpu_write(ring_head, (++head_idx % NUM_TRACE_ENTRIES));
}
__asm__(
" .text \n\t"
" .align 16 \n\t"
" .globl add_trace_entry \n\t"
" .type add_trace_entry, @function \n\t"
"add_trace_entry: \n\t"
/* rdi has event_type */
/* rsi has the arg rdi */
" movq %rsp, %rdx \n\t"
" pushfq \n\t"
" pop %rcx \n\t"
" movq 0(%rsp), %r8 \n\t"
" call __add_trace_entry \n\t"
" ret \n\t"
);
EXPORT_SYMBOL(add_trace_entry);
asmlinkage __visible notrace void add_trace_entry_tf(struct pt_regs *regs,
trace_event_t type)
{
__add_trace_entry(type, regs->di, regs->sp, regs->flags, regs->ip);
}
int __init ring_trace_init(void)
{
int cpu;
for_each_online_cpu(cpu) {
per_cpu(ring_head, cpu) = 0;
}
printk("LCD ring trace buffer initialized for %d cpus\n", num_online_cpus());
return 0;
}
late_initcall(ring_trace_init);
void dump_ring_trace_buffer(void)
{
unsigned char head_idx = __this_cpu_read(ring_head);
unsigned char *this_ring = per_cpu(ring_buffer, raw_smp_processor_id());
struct ring_trace_entry *trace_entries = (struct ring_trace_entry*) this_ring;
int i;
for (i = 0; i < NUM_TRACE_ENTRIES; i++, head_idx--) {
struct ring_trace_entry *entry = &trace_entries[head_idx % NUM_TRACE_ENTRIES];
if (i == 0)
printk("head ==> ");
printk("type:%16s cpu: %d [%c|%c|%c] comm: %s pid: %d rip: %08lx rsp: %08lx "
"rdi: %08lx lcd_stack: %08lx[esp_lcd_bmap: %x] "
"eflags: %lx [IF: %d]\n",
trace_event_type_string[entry->type - 1],
raw_smp_processor_id(),
entry->context & (IN_NMI) ? 'N' : '-',
entry->context & (IN_SOFTIRQ) ? 'S' : '-',
entry->context & (IN_IRQ) ? 'I' : '-',
entry->name, entry->pid, entry->rip,
entry->rsp, entry->rdi, entry->lcd_stack,
entry->lcd_stack_bit, entry->eflags,
!!(entry->eflags & IF_FLAG));
}
}
EXPORT_SYMBOL(dump_ring_trace_buffer);
......@@ -54,6 +54,8 @@ asmlinkage extern void ret_from_fork(void);
__visible DEFINE_PER_CPU(unsigned long, rsp_scratch);
#define EFLAGS_IF (1 << 9)
/* Prints also some state that isn't saved in the pt_regs */
void __show_regs(struct pt_regs *regs, int all)
{
......@@ -64,8 +66,8 @@ void __show_regs(struct pt_regs *regs, int all)
printk(KERN_EMERG "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
printk_address(regs->ip);
printk(KERN_EMERG "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss,
regs->sp, regs->flags);
printk(KERN_EMERG "RSP: %04lx:%016lx EFLAGS: %08lx [IF: %x]\n", regs->ss,
regs->sp, regs->flags, !!(regs->flags & EFLAGS_IF));
printk(KERN_EMERG "RAX: %016lx RBX: %016lx RCX: %016lx\n",
regs->ax, regs->bx, regs->cx);
printk(KERN_EMERG "RDX: %016lx RSI: %016lx RDI: %016lx\n",
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _TOOLS_LINUX_COMPILER_H_
#error "Please don't include <linux/compiler-gcc.h> directly, include <linux/compiler.h> instead."
#endif
/*
* Common definitions for all gcc versions go here.
*/
#define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
#if GCC_VERSION >= 70000 && !defined(__CHECKER__)
# define __fallthrough __attribute__ ((fallthrough))
#endif
#if GCC_VERSION >= 40300
# define __compiletime_error(message) __attribute__((error(message)))
#endif /* GCC_VERSION >= 40300 */
/* &a[0] degrades to a pointer: a different type from an array */
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
#ifndef __pure
#define __pure __attribute__((pure))
#endif
#ifndef __packed
#define __packed __attribute__((packed))
#endif
#ifndef __noreturn
#define __noreturn __attribute__((noreturn))
#endif
#ifndef __aligned
#define __aligned(x) __attribute__((aligned(x)))
#endif
#define __printf(a, b) __attribute__((format(printf, a, b)))
#define __scanf(a, b) __attribute__((format(scanf, a, b)))
#if GCC_VERSION >= 50100
#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
#endif
#ifndef _TOOLS_LINUX_COMPILER_H_
#define _TOOLS_LINUX_COMPILER_H_
#ifdef __GNUC__
#include <linux/compiler-gcc.h>
#endif
#ifndef __compiletime_error
# define __compiletime_error(message)
#endif
/* Optimization barrier */
/* The "volatile" is due to gcc bugs */
#define barrier() __asm__ __volatile__("": : :"memory")
......@@ -9,6 +17,15 @@
# define __always_inline inline __attribute__((always_inline))
#endif
#ifndef noinline
#define noinline
#endif
/* Are two types/vars the same type (ignoring qualifiers)? */
#ifndef __same_type
# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#endif
#ifdef __ANDROID__
/*
* FIXME: Big hammer to get rid of tons of:
......
......@@ -1572,13 +1572,13 @@ static int __bench_numa(const char *name)
"GB/sec,", "total-speed", "GB/sec total speed");
if (g->p.show_details >= 2) {
char tname[32];
char tname[14 + 2 * 10 + 1];
struct thread_data *td;
for (p = 0; p < g->p.nr_proc; p++) {
for (t = 0; t < g->p.nr_threads; t++) {
memset(tname, 0, 32);
memset(tname, 0, sizeof(tname));
td = g->threads + p*g->p.nr_threads + t;
snprintf(tname, 32, "process%d:thread%d", p, t);
snprintf(tname, sizeof(tname), "process%d:thread%d", p, t);
print_res(tname, td->speed_gbs,
"GB/sec", "thread-speed", "GB/sec/thread speed");
print_res(tname, td->system_time_ns / 1e9,
......
......@@ -642,6 +642,7 @@ repeat:
if (errno == EINTR)
continue;
/* Fall trhu */
__fallthrough;
default:
c = getc(stdin);
tcsetattr(0, TCSAFLUSH, &save);
......
......@@ -1779,15 +1779,14 @@ static int test_pmu_events(void)
}
while (!ret && (ent = readdir(dir))) {
#define MAX_NAME 100
struct evlist_test e;
char name[MAX_NAME];
char name[2 * NAME_MAX + 1 + 12 + 3];
/* Names containing . are special and cannot be used directly */
if (strchr(ent->d_name, '.'))
continue;
snprintf(name, MAX_NAME, "cpu/event=%s/u", ent->d_name);
snprintf(name, sizeof(name), "cpu/event=%s/u", ent->d_name);
e.name = name;
e.check = test__checkevent_pmu_events;
......@@ -1795,11 +1794,10 @@ static int test_pmu_events(void)
ret = test_event(&e);
if (ret)
break;
snprintf(name, MAX_NAME, "%s:u,cpu/event=%s/u", ent->d_name, ent->d_name);
snprintf(name, sizeof(name), "%s:u,cpu/event=%s/u", ent->d_name, ent->d_name);
e.name = name;
e.check = test__checkevent_pmu_events_mix;
ret = test_event(&e);
#undef MAX_NAME
}
closedir(dir);
......
......@@ -3185,6 +3185,7 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
case PERF_EVENT_UPDATE__SCALE:
ev_scale = (struct event_update_event_scale *) ev->data;
evsel->scale = ev_scale->scale;
__fallthrough;
case PERF_EVENT_UPDATE__CPUS:
ev_cpus = (struct event_update_event_cpus *) ev->data;
......
......@@ -22,6 +22,7 @@
#include <errno.h>
#include <stdint.h>
#include <inttypes.h>
#include <linux/compiler.h>
#include "../cache.h"
#include "../util.h"
......@@ -1676,6 +1677,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
switch (decoder->packet.type) {
case INTEL_PT_TIP_PGD:
decoder->continuous_period = false;
__fallthrough;
case INTEL_PT_TIP_PGE:
case INTEL_PT_TIP:
intel_pt_log("ERROR: Unexpected packet\n");
......@@ -1729,6 +1731,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
decoder->pge = false;
decoder->continuous_period = false;
intel_pt_clear_tx_flags(decoder);
__fallthrough;
case INTEL_PT_TNT:
decoder->have_tma = false;
intel_pt_log("ERROR: Unexpected packet\n");
......@@ -1769,6 +1772,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
switch (decoder->packet.type) {
case INTEL_PT_TIP_PGD:
decoder->continuous_period = false;
__fallthrough;
case INTEL_PT_TIP_PGE:
case INTEL_PT_TIP:
decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD;
......
......@@ -17,6 +17,7 @@
#include <string.h>
#include <endian.h>
#include <byteswap.h>
#include <linux/compiler.h>
#include "intel-pt-pkt-decoder.h"
......@@ -498,6 +499,7 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
case INTEL_PT_FUP:
if (!(packet->count))
return snprintf(buf, buf_len, "%s no ip", name);
__fallthrough;
case INTEL_PT_CYC:
case INTEL_PT_VMCS:
case INTEL_PT_MTC:
......
libperf-$(CONFIG_LIBPERL) += trace-event-perl.o
libperf-$(CONFIG_LIBPYTHON) += trace-event-python.o
CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default
CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-nested-externs -Wno-undef -Wno-switch-default
CFLAGS_trace-event-python.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow
......@@ -269,6 +269,8 @@ static int strfilter_node__sprint(struct strfilter_node *node, char *buf)
len = strfilter_node__sprint_pt(node->l, buf);
if (len < 0)
return len;
__fallthrough;
case '!':
if (buf) {
*(buf + len++) = *node->p;
......
......@@ -21,6 +21,8 @@ s64 perf_atoll(const char *str)
case 'b': case 'B':
if (*p)
goto out_err;
__fallthrough;
case '\0':
return length;
default:
......
......@@ -93,7 +93,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
{
DIR *proc;
int max_threads = 32, items, i;
char path[256];
char path[NAME_MAX + 1 + 6];
struct dirent *dirent, **namelist = NULL;
struct thread_map *threads = thread_map__alloc(max_threads);
......