Blame view

common/iotrace.c 3.79 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
aa53233a1   Simon Glass   Add an I/O tracin...
2
3
  /*
   * Copyright (c) 2014 Google, Inc.
aa53233a1   Simon Glass   Add an I/O tracin...
4
5
6
7
8
   */
  
  #define IOTRACE_IMPL
  
  #include <common.h>
0eb25b619   Joe Hershberger   common: Make sure...
9
  #include <mapmem.h>
1045315df   Simon Glass   common: Move get_...
10
  #include <time.h>
aa53233a1   Simon Glass   Add an I/O tracin...
11
  #include <asm/io.h>
3db711085   Simon Glass   crc32: Use the cr...
12
  #include <u-boot/crc.h>
aa53233a1   Simon Glass   Add an I/O tracin...
13
14
  
  DECLARE_GLOBAL_DATA_PTR;
aa53233a1   Simon Glass   Add an I/O tracin...
15
16
17
18
  /**
   * struct iotrace - current trace status and checksum
   *
   * @start:	Start address of iotrace buffer
e0212dfa1   Ramon Fried   iotrace: fix beha...
19
20
   * @size:	Actual size of iotrace buffer in bytes
   * @needed_size: Needed of iotrace buffer in bytes
aa53233a1   Simon Glass   Add an I/O tracin...
21
   * @offset:	Current write offset into iotrace buffer
a74440b27   Ramon Fried   iotrace: add IO r...
22
23
   * @region_start: Address of IO region to trace
   * @region_size: Size of region to trace. if 0 will trace all address space
aa53233a1   Simon Glass   Add an I/O tracin...
24
25
26
27
28
29
   * @crc32:	Current value of CRC chceksum of trace records
   * @enabled:	true if enabled, false if disabled
   */
  static struct iotrace {
  	ulong start;
  	ulong size;
e0212dfa1   Ramon Fried   iotrace: fix beha...
30
  	ulong needed_size;
aa53233a1   Simon Glass   Add an I/O tracin...
31
  	ulong offset;
a74440b27   Ramon Fried   iotrace: add IO r...
32
33
  	ulong region_start;
  	ulong region_size;
aa53233a1   Simon Glass   Add an I/O tracin...
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  	u32 crc32;
  	bool enabled;
  } iotrace;
  
  static void add_record(int flags, const void *ptr, ulong value)
  {
  	struct iotrace_record srec, *rec = &srec;
  
  	/*
  	 * We don't support iotrace before relocation. Since the trace buffer
  	 * is set up by a command, it can't be enabled at present. To change
  	 * this we would need to set the iotrace buffer at build-time. See
  	 * lib/trace.c for how this might be done if you are interested.
  	 */
  	if (!(gd->flags & GD_FLG_RELOC) || !iotrace.enabled)
  		return;
a74440b27   Ramon Fried   iotrace: add IO r...
50
51
52
53
  	if (iotrace.region_size)
  		if ((ulong)ptr < iotrace.region_start ||
  		    (ulong)ptr > iotrace.region_start + iotrace.region_size)
  			return;
aa53233a1   Simon Glass   Add an I/O tracin...
54
55
56
57
58
  	/* Store it if there is room */
  	if (iotrace.offset + sizeof(*rec) < iotrace.size) {
  		rec = (struct iotrace_record *)map_sysmem(
  					iotrace.start + iotrace.offset,
  					sizeof(value));
e0212dfa1   Ramon Fried   iotrace: fix beha...
59
60
61
62
63
  	} else {
  		WARN_ONCE(1, "WARNING: iotrace buffer exhausted, please check needed length using \"iotrace stats\"
  ");
  		iotrace.needed_size += sizeof(struct iotrace_record);
  		return;
aa53233a1   Simon Glass   Add an I/O tracin...
64
  	}
e0212dfa1   Ramon Fried   iotrace: fix beha...
65

b5e0e360f   Ramon Fried   common: iotrace: ...
66
  	rec->timestamp = timer_get_us();
aa53233a1   Simon Glass   Add an I/O tracin...
67
68
69
70
71
72
73
  	rec->flags = flags;
  	rec->addr = map_to_sysmem(ptr);
  	rec->value = value;
  
  	/* Update our checksum */
  	iotrace.crc32 = crc32(iotrace.crc32, (unsigned char *)rec,
  			      sizeof(*rec));
e0212dfa1   Ramon Fried   iotrace: fix beha...
74
  	iotrace.needed_size += sizeof(struct iotrace_record);
aa53233a1   Simon Glass   Add an I/O tracin...
75
76
77
78
79
80
81
82
83
84
85
86
  	iotrace.offset += sizeof(struct iotrace_record);
  }
  
  u32 iotrace_readl(const void *ptr)
  {
  	u32 v;
  
  	v = readl(ptr);
  	add_record(IOT_32 | IOT_READ, ptr, v);
  
  	return v;
  }
9859dc76e   Simon Glass   trace: Remove the...
87
  void iotrace_writel(ulong value, void *ptr)
aa53233a1   Simon Glass   Add an I/O tracin...
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  {
  	add_record(IOT_32 | IOT_WRITE, ptr, value);
  	writel(value, ptr);
  }
  
  u16 iotrace_readw(const void *ptr)
  {
  	u32 v;
  
  	v = readw(ptr);
  	add_record(IOT_16 | IOT_READ, ptr, v);
  
  	return v;
  }
9859dc76e   Simon Glass   trace: Remove the...
102
  void iotrace_writew(ulong value, void *ptr)
aa53233a1   Simon Glass   Add an I/O tracin...
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  {
  	add_record(IOT_16 | IOT_WRITE, ptr, value);
  	writew(value, ptr);
  }
  
  u8 iotrace_readb(const void *ptr)
  {
  	u32 v;
  
  	v = readb(ptr);
  	add_record(IOT_8 | IOT_READ, ptr, v);
  
  	return v;
  }
9859dc76e   Simon Glass   trace: Remove the...
117
  void iotrace_writeb(ulong value, void *ptr)
aa53233a1   Simon Glass   Add an I/O tracin...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
  {
  	add_record(IOT_8 | IOT_WRITE, ptr, value);
  	writeb(value, ptr);
  }
  
  void iotrace_reset_checksum(void)
  {
  	iotrace.crc32 = 0;
  }
  
  u32 iotrace_get_checksum(void)
  {
  	return iotrace.crc32;
  }
a74440b27   Ramon Fried   iotrace: add IO r...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  void iotrace_set_region(ulong start, ulong size)
  {
  	iotrace.region_start = start;
  	iotrace.region_size = size;
  }
  
  void iotrace_reset_region(void)
  {
  	iotrace.region_start = 0;
  	iotrace.region_size = 0;
  }
  
  void iotrace_get_region(ulong *start, ulong *size)
  {
  	*start = iotrace.region_start;
  	*size = iotrace.region_size;
  }
aa53233a1   Simon Glass   Add an I/O tracin...
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  void iotrace_set_enabled(int enable)
  {
  	iotrace.enabled = enable;
  }
  
  int iotrace_get_enabled(void)
  {
  	return iotrace.enabled;
  }
  
  void iotrace_set_buffer(ulong start, ulong size)
  {
  	iotrace.start = start;
  	iotrace.size = size;
  	iotrace.offset = 0;
  	iotrace.crc32 = 0;
  }
e0212dfa1   Ramon Fried   iotrace: fix beha...
166
  void iotrace_get_buffer(ulong *start, ulong *size, ulong *needed_size, ulong *offset, ulong *count)
aa53233a1   Simon Glass   Add an I/O tracin...
167
168
169
  {
  	*start = iotrace.start;
  	*size = iotrace.size;
e0212dfa1   Ramon Fried   iotrace: fix beha...
170
  	*needed_size = iotrace.needed_size;
aa53233a1   Simon Glass   Add an I/O tracin...
171
172
173
  	*offset = iotrace.offset;
  	*count = iotrace.offset / sizeof(struct iotrace_record);
  }