1 /*
2  * Copyright (C) 2018-2022 Intel Corporation.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <types.h>
8 #include <asm/per_cpu.h>
9 #include <ticks.h>
10 #include <trace.h>
11 
12 #define TRACE_CUSTOM			0xFCU
13 #define TRACE_FUNC_ENTER		0xFDU
14 #define TRACE_FUNC_EXIT			0xFEU
15 #define TRACE_STR			0xFFU
16 
17 /* sizeof(trace_entry) == 4 x 64bit */
18 struct trace_entry {
19 	uint64_t tsc; /* TSC */
20 	uint64_t id:48;
21 	uint8_t n_data; /* nr of data in trace_entry */
22 	uint8_t cpu; /* pcpu id of trace_entry */
23 
24 	union {
25 		struct {
26 			uint32_t a, b, c, d;
27 		} fields_32;
28 		struct {
29 			uint8_t a1, a2, a3, a4;
30 			uint8_t b1, b2, b3, b4;
31 			uint8_t c1, c2, c3, c4;
32 			uint8_t d1, d2, d3, d4;
33 		} fields_8;
34 		struct {
35 			uint64_t e;
36 			uint64_t f;
37 		} fields_64;
38 		char str[16];
39 	} payload;
40 } __aligned(8);
41 
trace_check(uint16_t cpu_id)42 static inline bool trace_check(uint16_t cpu_id)
43 {
44 	if (per_cpu(sbuf, cpu_id)[ACRN_TRACE] == NULL) {
45 		return false;
46 	}
47 
48 	return true;
49 }
50 
trace_put(uint16_t cpu_id,uint32_t evid,uint32_t n_data,struct trace_entry * entry)51 static inline void trace_put(uint16_t cpu_id, uint32_t evid, uint32_t n_data, struct trace_entry *entry)
52 {
53 	struct shared_buf *sbuf = per_cpu(sbuf, cpu_id)[ACRN_TRACE];
54 
55 	entry->tsc = cpu_ticks();
56 	entry->id = evid;
57 	entry->n_data = (uint8_t)n_data;
58 	entry->cpu = (uint8_t)cpu_id;
59 	(void)sbuf_put(sbuf, (uint8_t *)entry, sizeof(*entry));
60 }
61 
TRACE_2L(uint32_t evid,uint64_t e,uint64_t f)62 void TRACE_2L(uint32_t evid, uint64_t e, uint64_t f)
63 {
64 	struct trace_entry entry;
65 	uint16_t cpu_id = get_pcpu_id();
66 
67 	if (!trace_check(cpu_id)) {
68 		return;
69 	}
70 
71 	entry.payload.fields_64.e = e;
72 	entry.payload.fields_64.f = f;
73 	trace_put(cpu_id, evid, 2U, &entry);
74 }
75 
TRACE_4I(uint32_t evid,uint32_t a,uint32_t b,uint32_t c,uint32_t d)76 void TRACE_4I(uint32_t evid, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
77 {
78 	struct trace_entry entry;
79 	uint16_t cpu_id = get_pcpu_id();
80 
81 	if (!trace_check(cpu_id)) {
82 		return;
83 	}
84 
85 	entry.payload.fields_32.a = a;
86 	entry.payload.fields_32.b = b;
87 	entry.payload.fields_32.c = c;
88 	entry.payload.fields_32.d = d;
89 	trace_put(cpu_id, evid, 4U, &entry);
90 }
91 
TRACE_6C(uint32_t evid,uint8_t a1,uint8_t a2,uint8_t a3,uint8_t a4,uint8_t b1,uint8_t b2)92 void TRACE_6C(uint32_t evid, uint8_t a1, uint8_t a2, uint8_t a3, uint8_t a4, uint8_t b1, uint8_t b2)
93 {
94 	struct trace_entry entry;
95 	uint16_t cpu_id = get_pcpu_id();
96 
97 	if (!trace_check(cpu_id)) {
98 		return;
99 	}
100 
101 	entry.payload.fields_8.a1 = a1;
102 	entry.payload.fields_8.a2 = a2;
103 	entry.payload.fields_8.a3 = a3;
104 	entry.payload.fields_8.a4 = a4;
105 	entry.payload.fields_8.b1 = b1;
106 	entry.payload.fields_8.b2 = b2;
107 	/* payload.fields_8.b3/b4 not used, but is put in trace buf */
108 	trace_put(cpu_id, evid, 8U, &entry);
109 }
110 
111 #define TRACE_ENTER TRACE_16STR(TRACE_FUNC_ENTER, __func__)
112 #define TRACE_EXIT TRACE_16STR(TRACE_FUNC_EXIT, __func__)
113 
TRACE_16STR(uint32_t evid,const char name[])114 void TRACE_16STR(uint32_t evid, const char name[])
115 {
116 	struct trace_entry entry;
117 	uint16_t cpu_id = get_pcpu_id();
118 	size_t len, i;
119 
120 	if (!trace_check(cpu_id)) {
121 		return;
122 	}
123 
124 	entry.payload.fields_64.e = 0UL;
125 	entry.payload.fields_64.f = 0UL;
126 
127 	len = strnlen_s(name, 20U);
128 	len = (len > 16U) ? 16U : len;
129 	for (i = 0U; i < len; i++) {
130 		entry.payload.str[i] = name[i];
131 	}
132 
133 	entry.payload.str[15] = 0;
134 	trace_put(cpu_id, evid, 16U, &entry);
135 }
136