Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/cddl/dev/fbt/riscv/fbt_isa.c
48378 views
1
/*
2
* CDDL HEADER START
3
*
4
* The contents of this file are subject to the terms of the
5
* Common Development and Distribution License (the "License").
6
* You may not use this file except in compliance with the License.
7
*
8
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9
* or http://www.opensolaris.org/os/licensing.
10
* See the License for the specific language governing permissions
11
* and limitations under the License.
12
*
13
* When distributing Covered Code, include this CDDL HEADER in each
14
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15
* If applicable, add the following below this CDDL HEADER, with the
16
* fields enclosed by brackets "[]" replaced with your own identifying
17
* information: Portions Copyright [yyyy] [name of copyright owner]
18
*
19
* CDDL HEADER END
20
*
21
* Portions Copyright 2006-2008 John Birrell [email protected]
22
* Portions Copyright 2013 Justin Hibbits [email protected]
23
* Portions Copyright 2013 Howard Su [email protected]
24
* Portions Copyright 2016-2018 Ruslan Bukin <[email protected]>
25
*/
26
27
/*
28
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
29
* Use is subject to license terms.
30
*/
31
32
#include <sys/param.h>
33
34
#include <sys/dtrace.h>
35
36
#include <machine/riscvreg.h>
37
#include <machine/encoding.h>
38
39
#include "fbt.h"
40
41
#define FBT_C_PATCHVAL MATCH_C_EBREAK
42
#define FBT_PATCHVAL MATCH_EBREAK
43
#define FBT_AFRAMES 5
44
45
int
46
fbt_invop(uintptr_t addr, struct trapframe *frame, uintptr_t rval)
47
{
48
solaris_cpu_t *cpu;
49
fbt_probe_t *fbt;
50
51
cpu = &solaris_cpu[curcpu];
52
fbt = fbt_probetab[FBT_ADDR2NDX(addr)];
53
54
for (; fbt != NULL; fbt = fbt->fbtp_hashnext) {
55
if ((uintptr_t)fbt->fbtp_patchpoint == addr) {
56
cpu->cpu_dtrace_caller = frame->tf_ra - INSN_SIZE;
57
58
if (fbt->fbtp_roffset == 0) {
59
dtrace_probe(fbt->fbtp_id, frame->tf_a[0],
60
frame->tf_a[1], frame->tf_a[2],
61
frame->tf_a[3], frame->tf_a[4]);
62
} else {
63
dtrace_probe(fbt->fbtp_id, fbt->fbtp_roffset,
64
frame->tf_a[0], frame->tf_a[1], 0, 0);
65
}
66
67
cpu->cpu_dtrace_caller = 0;
68
return (fbt->fbtp_savedval);
69
}
70
}
71
72
return (0);
73
}
74
75
void
76
fbt_patch_tracepoint(fbt_probe_t *fbt, fbt_patchval_t val)
77
{
78
79
switch(fbt->fbtp_patchval) {
80
case FBT_C_PATCHVAL:
81
*(uint16_t *)fbt->fbtp_patchpoint = (uint16_t)val;
82
fence_i();
83
break;
84
case FBT_PATCHVAL:
85
*fbt->fbtp_patchpoint = val;
86
fence_i();
87
break;
88
};
89
}
90
91
int
92
fbt_provide_module_function(linker_file_t lf, int symindx,
93
linker_symval_t *symval, void *opaque)
94
{
95
fbt_probe_t *fbt, *retfbt;
96
uint32_t *instr, *limit;
97
const char *name;
98
char *modname;
99
int patchval;
100
int rval;
101
102
modname = opaque;
103
name = symval->name;
104
105
/* Check if function is excluded from instrumentation */
106
if (fbt_excluded(name))
107
return (0);
108
109
/*
110
* Some assembly-language exception handlers are not suitable for
111
* instrumentation.
112
*/
113
if (strcmp(name, "cpu_exception_handler") == 0)
114
return (0);
115
if (strcmp(name, "cpu_exception_handler_user") == 0)
116
return (0);
117
if (strcmp(name, "cpu_exception_handler_supervisor") == 0)
118
return (0);
119
if (strcmp(name, "do_trap_supervisor") == 0)
120
return (0);
121
122
instr = (uint32_t *)(symval->value);
123
limit = (uint32_t *)(symval->value + symval->size);
124
125
/* Look for sd operation */
126
for (; instr < limit; instr++) {
127
/* Look for a non-compressed store of ra to sp */
128
if (dtrace_instr_sdsp(&instr)) {
129
rval = DTRACE_INVOP_SD;
130
patchval = FBT_PATCHVAL;
131
break;
132
}
133
134
/* Look for a 'C'-compressed store of ra to sp. */
135
if (dtrace_instr_c_sdsp(&instr)) {
136
rval = DTRACE_INVOP_C_SDSP;
137
patchval = FBT_C_PATCHVAL;
138
break;
139
}
140
}
141
142
if (instr >= limit)
143
return (0);
144
145
fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
146
fbt->fbtp_name = name;
147
fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
148
name, FBT_ENTRY, FBT_AFRAMES, fbt);
149
fbt->fbtp_patchpoint = instr;
150
fbt->fbtp_ctl = lf;
151
fbt->fbtp_loadcnt = lf->loadcnt;
152
fbt->fbtp_savedval = *instr;
153
fbt->fbtp_patchval = patchval;
154
fbt->fbtp_rval = rval;
155
fbt->fbtp_symindx = symindx;
156
157
fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
158
fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
159
160
lf->fbt_nentries++;
161
162
retfbt = NULL;
163
again:
164
for (; instr < limit; instr++) {
165
/* Look for non-compressed return */
166
if (dtrace_instr_ret(&instr)) {
167
rval = DTRACE_INVOP_RET;
168
patchval = FBT_PATCHVAL;
169
break;
170
}
171
172
/* Look for 'C'-compressed return */
173
if (dtrace_instr_c_ret(&instr)) {
174
rval = DTRACE_INVOP_C_RET;
175
patchval = FBT_C_PATCHVAL;
176
break;
177
}
178
}
179
180
if (instr >= limit)
181
return (0);
182
183
/*
184
* We have a winner!
185
*/
186
fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
187
fbt->fbtp_name = name;
188
if (retfbt == NULL) {
189
fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
190
name, FBT_RETURN, FBT_AFRAMES, fbt);
191
} else {
192
retfbt->fbtp_probenext = fbt;
193
fbt->fbtp_id = retfbt->fbtp_id;
194
}
195
retfbt = fbt;
196
197
fbt->fbtp_patchpoint = instr;
198
fbt->fbtp_ctl = lf;
199
fbt->fbtp_loadcnt = lf->loadcnt;
200
fbt->fbtp_symindx = symindx;
201
fbt->fbtp_rval = rval;
202
fbt->fbtp_roffset = (uintptr_t)instr - (uintptr_t)symval->value;
203
fbt->fbtp_savedval = *instr;
204
fbt->fbtp_patchval = patchval;
205
fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
206
fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
207
208
lf->fbt_nentries++;
209
210
instr++;
211
goto again;
212
}
213
214