1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 * Description: LOG BUFFER READER MODULE.
15 * Author:
16 * Create: 2018-10-15
17 */
18 #include "panic.h"
19 #include "securec.h"
20 #include "log_memory_section.h"
21 #include "stdint.h"
22 #include "diag_log.h"
23 #include "log_buffer_reader.h"
24 /*
25 * Private type definitions
26 */
27 typedef struct {
28 uint8_t *log_buffer_start;
29 uint32_t log_buffer_size;
30 volatile uint32_t lb_next_to_consume; // == not disdarded yet
31 } log_buffer_reader_control_t;
32
33 /*
34 * Private variable declarations
35 */
36 /** Array of pointers to the section control structures for the different regions in the shared memory */
37 static log_memory_section_control_t *g_section_control[LOG_MEMORY_REGION_MAX_NUMBER];
38
39 /** Internal control for the different log regions */
40 static log_buffer_reader_control_t g_buffer_reader_control[LOG_MEMORY_REGION_MAX_NUMBER];
41
42 /*
43 * Private function definitions
44 */
circled_index(const log_buffer_reader_control_t * lmscontrol,uint32_t index_in)45 static uint32_t circled_index(const log_buffer_reader_control_t *lmscontrol, uint32_t index_in)
46 {
47 uint32_t index_out;
48
49 if (index_in < lmscontrol->log_buffer_size) {
50 index_out = index_in;
51 } else {
52 index_out = index_in - lmscontrol->log_buffer_size;
53 }
54 if (index_out >= lmscontrol->log_buffer_size) {
55 panic(PANIC_LOG, __LINE__);
56 }
57 return index_out;
58 }
59
log_buffer_copy_consecutive(const log_buffer_reader_control_t * lmscontrol,uint8_t * destination_p,uint32_t index_in,uint32_t len)60 static void log_buffer_copy_consecutive(const log_buffer_reader_control_t *lmscontrol,
61 uint8_t *destination_p, uint32_t index_in, uint32_t len)
62 {
63 if (destination_p == NULL) {
64 panic(PANIC_LOG, __LINE__);
65 return;
66 }
67 if (len >= lmscontrol->log_buffer_size) {
68 panic(PANIC_LOG, __LINE__);
69 return;
70 }
71 errno_t sec_ret;
72
73 if (index_in + len <= lmscontrol->log_buffer_size) {
74 sec_ret = memcpy_s((void *)destination_p, len, (void *)(lmscontrol->log_buffer_start + index_in), len);
75 } else {
76 uint32_t l1;
77 l1 = lmscontrol->log_buffer_size - index_in;
78 // copy first part
79 sec_ret = memcpy_s(destination_p, l1, (void *)(lmscontrol->log_buffer_start + index_in), l1);
80 if (sec_ret != EOK) {
81 return;
82 }
83 // copy second part
84 sec_ret = memcpy_s((void *)(destination_p + l1), len - l1, (void *)lmscontrol->log_buffer_start, len - l1);
85 }
86 if (sec_ret != EOK) {
87 return;
88 }
89 }
90
log_buffer_get_used(const log_buffer_reader_control_t * lmscontrol,uint32_t read_i,uint32_t write_i)91 static uint32_t log_buffer_get_used(const log_buffer_reader_control_t *lmscontrol, uint32_t read_i, uint32_t write_i)
92 {
93 uint32_t in_use;
94 /* Check how much space is available. Use -1 to ensure the log_section_control->write ==
95 * log_section_control->read means the buffer is EMPTY.
96 * Without the -1, the log_section_control->write COULD wrap and catch up with log_section_control->read. */
97 if (read_i <= write_i) {
98 in_use = write_i - read_i;
99 } else {
100 /* log_section_control->write has wrapped, but log_section_control->read has not yet. */
101 in_use = (lmscontrol->log_buffer_size - read_i) + write_i;
102 }
103 return in_use;
104 }
105
log_buffer_reader_get_msg_header(log_memory_region_section_t lmsec,const log_buffer_header_t * lb_header,uint32_t m_index)106 static log_reader_ret_t log_buffer_reader_get_msg_header(log_memory_region_section_t lmsec,
107 const log_buffer_header_t *lb_header, uint32_t m_index)
108 {
109 const log_buffer_reader_control_t *lmsec_reader_control = &g_buffer_reader_control[lmsec];
110 uint32_t in_use;
111 uint32_t l_write_i;
112
113 if (lb_header == NULL) {
114 return LOG_READER_RET_ERROR_IN_PARAMS;
115 }
116
117 // Get the write index and check if there is at least a header to read
118 l_write_i = g_section_control[lmsec]->write;
119 if (l_write_i >= g_buffer_reader_control[lmsec].log_buffer_size) {
120 return LOG_READER_RET_ERROR_CORRUPT_SHARED_MEMORY;
121 }
122
123 in_use = log_buffer_get_used(lmsec_reader_control, m_index, l_write_i); // data between the index and the write
124 if (in_use == 0) {
125 return LOG_READER_RET_THERE_IS_NO_NEXT_MESSAGE;
126 } else if (in_use < sizeof(log_buffer_header_t) || (in_use >= g_buffer_reader_control[lmsec].log_buffer_size)) {
127 return LOG_READER_RET_ERROR_CORRUPT_SHARED_MEMORY;
128 } else {
129 log_buffer_copy_consecutive(lmsec_reader_control, (uint8_t *)lb_header, m_index, sizeof(log_buffer_header_t));
130 return LOG_READER_RET_OK;
131 }
132 }
133
134 /*
135 * Public function definitions
136 */
log_buffer_reader_init(void)137 log_reader_ret_t log_buffer_reader_init(void)
138 {
139 log_memory_section_params_t ms_params;
140 log_reader_ret_t ret_val;
141
142 // Initialize the control structures for the different regions
143 for (uint8_t lmsec = LOG_MEMORY_REGION_SECTION_0; lmsec < LOG_MEMORY_REGION_MAX_NUMBER; lmsec++) {
144 uint32_t l_read_i;
145 log_memory_section_get((log_memory_region_section_t)lmsec, &ms_params);
146 g_section_control[lmsec] = log_memory_section_get_control((log_memory_region_section_t)lmsec);
147
148 if (!pointer_in_log_memory_region((uintptr_t)ms_params.start)) {
149 panic(PANIC_LOG, __LINE__);
150 return LOG_READER_RET_ERROR_OVERFLOW_ON_DISCARDING;
151 }
152 if (!pointer_in_log_memory_region((uintptr_t)ms_params.start + ms_params.length - 1)) {
153 panic(PANIC_LOG, __LINE__);
154 return LOG_READER_RET_ERROR_OVERFLOW_ON_DISCARDING;
155 }
156
157 if (!pointer_in_log_memory_region((uintptr_t)ms_params.start) ||
158 !pointer_in_log_memory_region((uint32_t)((uintptr_t)ms_params.start) + ms_params.length - 1)) {
159 return LOG_READER_RET_ERROR_CORRUPT_SHARED_MEMORY;
160 }
161
162 g_buffer_reader_control[lmsec].log_buffer_start = ms_params.start; // first element
163 g_buffer_reader_control[lmsec].log_buffer_size = ms_params.length; // buffer size
164
165 l_read_i = g_section_control[lmsec]->read;
166
167 if (l_read_i >= g_buffer_reader_control[lmsec].log_buffer_size) {
168 return LOG_READER_RET_ERROR_CORRUPT_SHARED_MEMORY;
169 }
170
171 g_buffer_reader_control[lmsec].lb_next_to_consume = l_read_i;
172 ret_val = LOG_READER_RET_OK;
173 }
174 return ret_val;
175 }
176
log_buffer_reader_lock_next(log_memory_region_section_t * lmsec,const log_buffer_header_t * lb_header)177 log_reader_ret_t log_buffer_reader_lock_next(log_memory_region_section_t *lmsec, const log_buffer_header_t *lb_header)
178 {
179 log_reader_ret_t helper_log_ret;
180
181 // when the log buffer is full,"read" is modified by unknown,so Synchronize to the "consume".
182 for (uint8_t i_lmsec = LOG_MEMORY_REGION_SECTION_0; i_lmsec < LOG_MEMORY_REGION_MAX_NUMBER; i_lmsec++) {
183 uint32_t read = g_section_control[i_lmsec]->read;
184 if (g_buffer_reader_control[i_lmsec].lb_next_to_consume != read) {
185 g_buffer_reader_control[i_lmsec].lb_next_to_consume = g_section_control[i_lmsec]->read;
186 }
187 }
188
189 *lmsec = LOG_MEMORY_REGION_MAX_NUMBER;
190
191 for (uint8_t i_lmsec = LOG_MEMORY_REGION_SECTION_0; i_lmsec < LOG_MEMORY_REGION_MAX_NUMBER; i_lmsec++) {
192 helper_log_ret = log_buffer_reader_get_msg_header((log_memory_region_section_t)i_lmsec, lb_header,
193 g_buffer_reader_control[i_lmsec].lb_next_to_consume);
194 if (helper_log_ret == LOG_READER_RET_OK) {
195 *lmsec = i_lmsec;
196 break;
197 }
198 }
199
200 #if CORE_NUMS > 1
201 log_buffer_header_t c_lb_header = { 0 }; // candidate header
202 if (*lmsec < (LOG_MEMORY_REGION_MAX_NUMBER - 1)) {
203 errno_t sec_ret;
204 // There is already one candidate
205 for (uint32_t i_lmsec = ((uint32_t)*lmsec + 1); i_lmsec < LOG_MEMORY_REGION_MAX_NUMBER; i_lmsec++) {
206 helper_log_ret = log_buffer_reader_get_msg_header((log_memory_region_section_t)i_lmsec, &c_lb_header,
207 g_buffer_reader_control[i_lmsec].lb_next_to_consume);
208 if (helper_log_ret != LOG_READER_RET_OK) {
209 continue;
210 }
211 if ((lb_header->time_us - c_lb_header.time_us) == 0) {
212 continue;
213 }
214 sec_ret = memcpy_s((void *)lb_header, sizeof(log_buffer_header_t),
215 (const void *)&c_lb_header, sizeof(log_buffer_header_t));
216 if (sec_ret != EOK) {
217 return LOG_READER_RET_ERROR;
218 }
219 *lmsec = i_lmsec;
220 }
221 }
222 #endif
223 if (*lmsec == LOG_MEMORY_REGION_MAX_NUMBER) {
224 // no new messages found
225 return LOG_READER_RET_THERE_IS_NO_NEXT_MESSAGE;
226 }
227 return LOG_READER_RET_OK;
228 }
229
log_buffer_get_used_space(log_memory_region_section_t lmsec,uint32_t * used_space)230 log_reader_ret_t log_buffer_get_used_space(log_memory_region_section_t lmsec, uint32_t *used_space)
231 {
232 log_reader_ret_t ret_value;
233 uint32_t l_write_i;
234 const log_buffer_reader_control_t *lmsec_reader_control;
235
236 ret_value = LOG_READER_RET_OK;
237
238 lmsec_reader_control = &g_buffer_reader_control[lmsec];
239
240 l_write_i = g_section_control[lmsec]->write;
241 if (l_write_i >= g_buffer_reader_control[lmsec].log_buffer_size) {
242 return LOG_READER_RET_ERROR_CORRUPT_SHARED_MEMORY;
243 }
244 *used_space = log_buffer_get_used(lmsec_reader_control,
245 lmsec_reader_control->lb_next_to_consume,
246 l_write_i); // data between the index and the write
247
248 return ret_value;
249 }
250
log_buffer_reader_claim_next(log_memory_region_section_t lmsec,uint8_t ** r1,uint32_t * len1,uint8_t ** r2,uint32_t * len2)251 log_reader_ret_t log_buffer_reader_claim_next(log_memory_region_section_t lmsec, uint8_t **r1,
252 uint32_t *len1, uint8_t **r2, uint32_t *len2)
253 {
254 uint32_t ret_r1;
255 log_buffer_header_t lb_header = { 0 };
256 const log_buffer_reader_control_t *lmsec_reader_control = &g_buffer_reader_control[lmsec];
257 log_reader_ret_t ret_value;
258 uint32_t l_write_i;
259 uint32_t new_next_to_consume;
260
261 // Get the next message header
262 ret_value = log_buffer_reader_get_msg_header(lmsec, &lb_header, lmsec_reader_control->lb_next_to_consume);
263 if (ret_value == LOG_READER_RET_OK) {
264 if (lb_header.length <= sizeof(log_buffer_header_t)) {
265 uapi_diag_error_log(0, "[log_reader][header]length error, len = 0x%x", lb_header.length);
266 return LOG_READER_RET_ERROR;
267 }
268 // Get the buffer pointers
269 ret_r1 = circled_index(lmsec_reader_control,
270 lmsec_reader_control->lb_next_to_consume + sizeof(log_buffer_header_t));
271 if (ret_r1 + (lb_header.length - sizeof(log_buffer_header_t)) <= lmsec_reader_control->log_buffer_size) {
272 /* 'Normal' case */
273 *r1 = lmsec_reader_control->log_buffer_start + ret_r1;
274 *len1 = lb_header.length - (uint32_t)sizeof(log_buffer_header_t);
275 *r2 = NULL;
276 *len2 = 0;
277 } else {
278 /* message divided at the end of the buffer case */
279 *r1 = lmsec_reader_control->log_buffer_start + ret_r1;
280 *len1 = lmsec_reader_control->log_buffer_size - ret_r1;
281 *r2 = lmsec_reader_control->log_buffer_start;
282 *len2 = (lb_header.length - (uint32_t)sizeof(log_buffer_header_t)) - *len1;
283 }
284 if ((*len1 > lmsec_reader_control->log_buffer_size) || (*len2 > lmsec_reader_control->log_buffer_size)) {
285 uapi_diag_error_log(0, "[log_reader][data]length error, len1 = 0x%x, len2 = 0x%x", *len1, *len2);
286 return LOG_READER_RET_ERROR_OVERFLOW_ON_DISCARDING;
287 }
288
289 // Assert if log_section_control->read tries to overflow lb_next_to_consume
290 l_write_i = g_section_control[lmsec]->write;
291 new_next_to_consume = circled_index(lmsec_reader_control,
292 lmsec_reader_control->lb_next_to_consume + lb_header.length);
293 // equivalent to: if (write > next_to_consume) {
294 if (((lmsec_reader_control->lb_next_to_consume >= l_write_i) ||
295 ((new_next_to_consume <= l_write_i) ||
296 (new_next_to_consume > lmsec_reader_control->lb_next_to_consume))) &&
297 ((lmsec_reader_control->lb_next_to_consume <= l_write_i) ||
298 ((new_next_to_consume <= lmsec_reader_control->lb_next_to_consume) ||
299 (new_next_to_consume > l_write_i)))) {
300 // Move the lb_next_to_consume data
301 log_buffer_reader_control_t *writable_lmsec_reader_control = &g_buffer_reader_control[lmsec];
302 writable_lmsec_reader_control->lb_next_to_consume = new_next_to_consume;
303 ret_value = LOG_READER_RET_OK;
304 } else {
305 uapi_diag_error_log(0, "[log_reader][pointer]write_p=0x%x, read_p=0x%x, new_read_p=0x%x\r\n", l_write_i,
306 lmsec_reader_control->lb_next_to_consume, new_next_to_consume);
307 ret_value = LOG_READER_RET_ERROR_CORRUPT_SHARED_MEMORY;
308 }
309 }
310
311 return ret_value;
312 }
313
log_buffer_reader_discard(log_memory_region_section_t lmsec)314 log_reader_ret_t log_buffer_reader_discard(log_memory_region_section_t lmsec)
315 {
316 log_buffer_header_t lb_header;
317 const log_buffer_reader_control_t *lmscontrol = &g_buffer_reader_control[lmsec];
318 log_reader_ret_t ret_value;
319 uint32_t l_read_i;
320 uint32_t new_lb_read;
321
322 if (lmsec >= LOG_MEMORY_REGION_MAX_NUMBER) {
323 return LOG_READER_RET_ERROR_IN_PARAMS;
324 }
325
326 memset_s((void *)&lb_header, sizeof(log_buffer_header_t), 0, sizeof(log_buffer_header_t));
327
328 // Get last read pointer message header message header
329 l_read_i = g_section_control[lmsec]->read;
330 ret_value = log_buffer_reader_get_msg_header(lmsec, &lb_header, l_read_i);
331 if (ret_value == LOG_READER_RET_OK) {
332 new_lb_read = circled_index(lmscontrol, l_read_i + lb_header.length);
333 if (((lmscontrol->lb_next_to_consume <= l_read_i) ||
334 ((new_lb_read <= lmscontrol->lb_next_to_consume) &&
335 (new_lb_read > l_read_i))) &&
336 ((lmscontrol->lb_next_to_consume >= l_read_i) ||
337 ((new_lb_read <= lmscontrol->lb_next_to_consume) ||
338 (new_lb_read > l_read_i))) &&
339 (new_lb_read < lmscontrol->log_buffer_size)) {
340 g_section_control[lmsec]->read = new_lb_read;
341 } else {
342 return LOG_READER_RET_ERROR_CORRUPT_SHARED_MEMORY; // Trying to overflow
343 }
344 }
345
346 return LOG_READER_RET_OK;
347 }
348
log_buffer_reader_error_recovery(log_memory_region_section_t lmsec)349 void log_buffer_reader_error_recovery(log_memory_region_section_t lmsec)
350 {
351 g_section_control[lmsec]->read = g_section_control[lmsec]->write;
352 }