--- zzzz-none-000/linux-4.4.60/kernel/trace/trace.c 2017-04-08 07:53:53.000000000 +0000 +++ wasp-540e-714/linux-4.4.60/kernel/trace/trace.c 2019-07-03 09:21:34.000000000 +0000 @@ -1763,11 +1763,151 @@ } EXPORT_SYMBOL_GPL(trace_current_buffer_discard_commit); +#ifdef CONFIG_SRD_TRACE + +#include +#include +#include + +#define SRD_NUM_ENTRIES (8 << 10) + +#define SRD_WITH_PARENT 0 +#define SRD_WITH_JIFFIES 0 + +struct srd_record { + void *ip; +#if SRD_WITH_PARENT + void *parent; +#endif +}; + +struct srd_percpu { + uint32_t index; +#if SRD_WITH_JIFFIES + uint32_t jiffies; +#endif +}; + +struct silent_reboot_debug { + atomic_t index; + struct srd_record *r; + dma_addr_t r_pa; + int ncpu; + struct srd_percpu cpu[CONFIG_NR_CPUS]; +} *srd; + +#define SRD_REC_SIZE_PER_CPU (SRD_NUM_ENTRIES * sizeof(*srd->r)) + +dma_addr_t srd_pa; +struct srd_record *srd_rec[CONFIG_NR_CPUS]; + +void srd_info_record(unsigned long ip, unsigned long parent_ip) +{ + unsigned long flags; + struct srd_record *r; + int index, cpu = smp_processor_id(); + + if (!srd || !srd->r) + return; + + local_irq_save(flags); + +#if SRD_WITH_JIFFIES + srd->cpu[cpu].jiffies = jiffies; +#endif + index = srd->cpu[cpu].index++; + + r = srd_rec[cpu] + (index % SRD_NUM_ENTRIES); + + r->ip = (void *)ip; +#if SRD_WITH_PARENT + r->parent = (void *)parent_ip; +#endif + + local_irq_restore(flags); +} + +#define SRD_PRINT_STR "srd: 0x%p -> 0x%p 0x%x\n" \ + "ip: 0x%p -> 0x%p 0x%x\n", \ + srd, (void *)srd_pa, \ + sizeof(*srd) / sizeof(uint32_t), \ + srd->r, (void *)srd->r_pa, \ + (SRD_REC_SIZE_PER_CPU * srd->ncpu) / sizeof(uint32_t) +static ssize_t +tracing_srd_read(struct file *filp, char __user *ubuf, + size_t cnt, loff_t *ppos) +{ + char str[256]; + int count; + + if (srd && !*ppos) { + count = snprintf(str, sizeof(str), SRD_PRINT_STR); + return simple_read_from_buffer(ubuf, cnt, ppos, str, count); + } else { + return 0; + } +} + +static const struct file_operations tracing_srd_fops = { + .read = tracing_srd_read, +}; + + +void srd_buf_init(struct dentry *d_tracer) +{ + int n = 0, cpu; + + /* + * Would have been ideal to do this in tracer_alloc_buffers. + * However, the dma-map subsystem is not up during early_initcall, + * and we get the following error + * __dma_alloc_remap: not initialised + * Backtrace: + * [] (dump_backtrace+0x0/0x120) from [] (dump_stack+0x20/0x24) + * r6:00001000 r5:c0d7b640 r4:ddf32000 r3:c0881f44 + * [] (dump_stack+0x0/0x24) from [] (arm_dma_alloc+0x3e0/0x410) + * [] (arm_dma_alloc+0x0/0x410) from [] (tracer_alloc_buffers+0x130/0x2c8) + * [] (tracer_alloc_buffers+0x0/0x2c8) from [] (do_one_initcall+0x40/0x17c) + * r7:00000000 r6:c071140c r5:c07368e4 r4:c07368e0 + * [] (do_one_initcall+0x0/0x17c) from [] (kernel_init+0x6c/0x1cc) + * r9:00000000 r8:00000000 r7:00000013 r6:c0066f28 r5:c07368e4 + * r4:c07368e0 + * [] (kernel_init+0x0/0x1cc) from [] (do_exit+0x0/0x864) + */ + + srd = dma_alloc_coherent(NULL, sizeof(*srd), &srd_pa, GFP_KERNEL); + if (!srd) + return; + + for_each_possible_cpu(cpu) + n++; + + srd->ncpu = n; + srd->r = dma_alloc_coherent(NULL, SRD_REC_SIZE_PER_CPU * n, + &srd->r_pa, GFP_KERNEL); + if (!srd->r) { + dma_free_coherent(NULL, sizeof(*srd), srd, srd_pa); + return; + } + + for_each_possible_cpu(cpu) + srd_rec[cpu] = &srd->r[cpu * SRD_NUM_ENTRIES]; + + printk(SRD_PRINT_STR); + + trace_create_file("srd", 0444, d_tracer, + srd, &tracing_srd_fops); +} +#endif /* CONFIG_SRD_TRACE */ + void trace_function(struct trace_array *tr, unsigned long ip, unsigned long parent_ip, unsigned long flags, int pc) { +#ifdef CONFIG_SRD_TRACE + srd_info_record(ip, parent_ip); +#else struct trace_event_call *call = &event_function; struct ring_buffer *buffer = tr->trace_buffer.buffer; struct ring_buffer_event *event; @@ -1783,6 +1923,7 @@ if (!call_filter_check_discard(call, entry, buffer, event)) __buffer_unlock_commit(buffer, event); +#endif /* CONFIG_SRD_TRACE */ } #ifdef CONFIG_STACKTRACE @@ -6993,6 +7134,10 @@ &ftrace_update_tot_cnt, &tracing_dyn_info_fops); #endif +#ifdef CONFIG_SRD_TRACE + srd_buf_init(d_tracer); +#endif /* CONFIG_SRD_TRACE */ + create_trace_instances(d_tracer); update_tracer_options(&global_trace);