Branch data Line data Source code
1 : : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 2 : : /* 3 : : * This example code shows how to read from the trace buffer. 4 : : * 5 : : * Copyright 2013-2019 IBM Corp. 6 : : */ 7 : : 8 : : #include <external/trace/trace.h> 9 : : #include "../ccan/endian/endian.h" 10 : : #include "../ccan/short_types/short_types.h" 11 : : #include "trace.h" 12 : : #include <trace_types.h> 13 : : #include <errno.h> 14 : : 15 : : #if defined(__powerpc__) || defined(__powerpc64__) 16 : : #define rmb() lwsync() 17 : : #else 18 : : #define rmb() 19 : : #endif 20 : : 21 : 4379461 : bool trace_empty(const struct trace_reader *tr) 22 : : { 23 : : const struct trace_repeat *rep; 24 : : 25 : 4379461 : if (tr->rpos == be64_to_cpu(tr->tb->end)) 26 : 120523 : return true; 27 : : 28 : : /* 29 : : * If we have a single element only, and it's a repeat buffer 30 : : * we've already seen every repeat for (yet which may be 31 : : * incremented in future), we're also empty. 32 : : */ 33 : 4258938 : rep = (void *)tr->tb->buf + tr->rpos % be64_to_cpu(tr->tb->buf_size); 34 : 4258938 : if (be64_to_cpu(tr->tb->end) != tr->rpos + sizeof(*rep)) 35 : 2078770 : return false; 36 : : 37 : 2180168 : if (rep->type != TRACE_REPEAT) 38 : 16 : return false; 39 : : 40 : 2180152 : if (be16_to_cpu(rep->num) != tr->last_repeat) 41 : 1105555 : return false; 42 : : 43 : 1074597 : return true; 44 : : } 45 : : 46 : : /* You can't read in parallel, so some locking required in caller. */ 47 : 4379457 : bool trace_get(union trace *t, struct trace_reader *tr) 48 : : { 49 : : u64 start, rpos; 50 : : size_t len; 51 : : 52 : 8758914 : len = sizeof(*t) < be32_to_cpu(tr->tb->max_size) ? sizeof(*t) : 53 : 4379457 : be32_to_cpu(tr->tb->max_size); 54 : : 55 : 4379457 : if (trace_empty(tr)) 56 : 1195116 : return false; 57 : : 58 : 3184341 : again: 59 : : /* 60 : : * The actual buffer is slightly larger than tbsize, so this 61 : : * memcpy is always valid. 62 : : */ 63 : 3988437 : memcpy(t, tr->tb->buf + tr->rpos % be64_to_cpu(tr->tb->buf_size), len); 64 : : 65 : : rmb(); /* read barrier, so we read tr->tb->start after copying record. */ 66 : : 67 : 3988437 : start = be64_to_cpu(tr->tb->start); 68 : 3988437 : rpos = tr->rpos; 69 : : 70 : : /* Now, was that overwritten? */ 71 : 3988437 : if (rpos < start) { 72 : : /* Create overflow record. */ 73 : 31 : t->overflow.unused64 = 0; 74 : 31 : t->overflow.type = TRACE_OVERFLOW; 75 : 31 : t->overflow.len_div_8 = sizeof(t->overflow) / 8; 76 : 31 : t->overflow.bytes_missed = cpu_to_be64(start - rpos); 77 : 31 : tr->rpos = start; 78 : 31 : return true; 79 : : } 80 : : 81 : : /* Repeat entries need special handling */ 82 : 3988406 : if (t->hdr.type == TRACE_REPEAT) { 83 : 2689472 : u32 num = be16_to_cpu(t->repeat.num); 84 : : 85 : : /* In case we've read some already... */ 86 : 2689472 : t->repeat.num = cpu_to_be16(num - tr->last_repeat); 87 : : 88 : : /* Record how many repeats we saw this time. */ 89 : 2689472 : tr->last_repeat = num; 90 : : 91 : : /* Don't report an empty repeat buffer. */ 92 : 2689472 : if (t->repeat.num == 0) { 93 : : /* 94 : : * This can't be the last buffer, otherwise 95 : : * trace_empty would have returned true. 96 : : */ 97 : 804096 : assert(be64_to_cpu(tr->tb->end) > 98 : : rpos + t->hdr.len_div_8 * 8); 99 : : /* Skip to next entry. */ 100 : 804096 : tr->rpos = rpos + t->hdr.len_div_8 * 8; 101 : 804096 : tr->last_repeat = 0; 102 : 804096 : goto again; 103 : : } 104 : : } else { 105 : 1298934 : tr->last_repeat = 0; 106 : 1298934 : tr->rpos = rpos + t->hdr.len_div_8 * 8; 107 : : } 108 : : 109 : 3184310 : return true; 110 : : }