Skip to content

Commit ad4c89f

Browse files
kvanheesnickalcock
authored andcommitted
dtrace, arm: arm64 port
This provides an arm64 implementation of DTrace. Signed-off-by: Nick Alcock <[email protected]> Signed-off-by: Kris Van Hees <[email protected]> Signed-off-by: Tomas Jedlicka <[email protected]> Signed-off-by: Eugene Loh <[email protected]> Signed-off-by: David Mc Lean <[email protected]> Signed-off-by: Vincent Lim <[email protected]>
1 parent 28cc52a commit ad4c89f

35 files changed

+2225
-14
lines changed

arch/arm64/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,9 @@ config PGTABLE_LEVELS
282282
config ARCH_SUPPORTS_UPROBES
283283
def_bool y
284284

285+
config ARCH_SUPPORTS_DTRACE
286+
def_bool y
287+
285288
config ARCH_PROC_KCORE_TEXT
286289
def_bool y
287290

arch/arm64/dtrace/Makefile.arch

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#
2+
# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
3+
#
4+
5+
DTARCHDIR = ../arch/arm64/dtrace
6+
7+
ccflags-y += -Iarch/arm64/dtrace/include -Idtrace
8+
9+
dtrace-obj += dtrace_asm_arm64.o dtrace_isa_arm64.o
10+
fasttrap-obj += fasttrap_arm64.o
11+
fbt-obj += fbt_arm64.o
12+
sdt-obj += sdt_arm64.o
13+
14+
dtrace-y += $(addprefix $(DTARCHDIR)/, $(dtrace-obj))
15+
fasttrap-y += $(addprefix $(DTARCHDIR)/, $(fasttrap-obj))
16+
fbt-y += $(addprefix $(DTARCHDIR)/, $(fbt-obj))
17+
sdt-y += $(addprefix $(DTARCHDIR)/, $(sdt-obj))

arch/arm64/dtrace/dtrace_asm_arm64.S

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Dynamic Tracing for Linux - ARM64 specific assembly
4+
*
5+
* Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
6+
*
7+
* This program is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation; either version 2 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*/
17+
18+
#include <linux/linkage.h>
19+
20+
ENTRY(dtrace_caller)
21+
mov x0, #-1
22+
ret
23+
ENDPROC(dtrace_caller)
24+
25+
ENTRY(dtrace_copy)
26+
ret
27+
ENDPROC(dtrace_copy)
28+
29+
ENTRY(dtrace_copystr)
30+
ret
31+
ENDPROC(dtrace_copystr)
32+
33+
ENTRY(dtrace_fuword8_nocheck)
34+
ldrb w0, [x0]
35+
ret
36+
ENDPROC(dtrace_fuword8_nocheck)
37+
38+
ENTRY(dtrace_fuword16_nocheck)
39+
ldrh w0, [x0]
40+
ret
41+
ENDPROC(dtrace_fuword16_nocheck)
42+
43+
ENTRY(dtrace_fuword32_nocheck)
44+
ldr w0, [x0]
45+
ret
46+
ENDPROC(dtrace_fuword32_nocheck)
47+
48+
ENTRY(dtrace_fuword64_nocheck)
49+
ldr x0, [x0]
50+
ret
51+
ENDPROC(dtrace_fuword64_nocheck)

arch/arm64/dtrace/dtrace_isa_arm64.c

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* FILE: dtrace_isa_arm64.c
4+
* DESCRIPTION: DTrace - arm64 architecture specific support functions
5+
*
6+
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
7+
*
8+
* This program is free software; you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License as published by
10+
* the Free Software Foundation; either version 2 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU General Public License for more details.
17+
*/
18+
19+
#include <asm/stacktrace.h>
20+
#include <linux/ptrace.h>
21+
22+
#include "dtrace.h"
23+
24+
uintptr_t _userlimit = 0x0000ffffffffffffLL;
25+
26+
void dtrace_copyin_arch(uintptr_t uaddr, uintptr_t kaddr, size_t size,
27+
volatile uint16_t *flags)
28+
{
29+
}
30+
31+
void dtrace_copyinstr_arch(uintptr_t uaddr, uintptr_t kaddr, size_t size,
32+
volatile uint16_t *flags)
33+
{
34+
}
35+
36+
void dtrace_copyout(uintptr_t uaddr, uintptr_t kaddr, size_t size,
37+
volatile uint16_t *flags)
38+
{
39+
}
40+
41+
void dtrace_copyoutstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
42+
volatile uint16_t *flags)
43+
{
44+
}
45+
46+
#define DTRACE_FUWORD(bits) \
47+
uint##bits##_t dtrace_fuword##bits(void *uaddr) \
48+
{ \
49+
extern uint##bits##_t dtrace_fuword##bits##_nocheck(void *);\
50+
\
51+
if ((uintptr_t)uaddr > _userlimit) { \
52+
DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); \
53+
this_cpu_core->cpuc_dtrace_illval = (uintptr_t)uaddr; \
54+
} \
55+
\
56+
return dtrace_fuword##bits##_nocheck(uaddr); \
57+
}
58+
59+
DTRACE_FUWORD(8)
60+
DTRACE_FUWORD(16)
61+
DTRACE_FUWORD(32)
62+
DTRACE_FUWORD(64)
63+
64+
static int dtrace_unwind_frame(struct task_struct *task,
65+
struct stackframe *frame)
66+
{
67+
unsigned long fp = frame->fp;
68+
69+
if (fp & 0xf)
70+
return -EINVAL;
71+
72+
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
73+
frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp));
74+
frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 8));
75+
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
76+
77+
if (!frame->fp && !frame->pc)
78+
return -EINVAL;
79+
80+
return 0;
81+
}
82+
83+
uint64_t dtrace_getarg(int argno, int aframes)
84+
{
85+
uint64_t *st;
86+
uint64_t val;
87+
int i;
88+
struct stackframe frame;
89+
struct task_struct *task = current;
90+
91+
if (argno < 7)
92+
return 0;
93+
94+
if (this_cpu_core->cpu_dtrace_regs)
95+
st = (uint64_t *)this_cpu_core->cpu_dtrace_regs->regs[29];
96+
else {
97+
frame.fp = (unsigned long)__builtin_frame_address(0);
98+
frame.pc = (unsigned long)dtrace_getarg;
99+
100+
aframes += 1; /* Count this function. */
101+
for (i = 0; i < aframes; i++) {
102+
if (dtrace_unwind_frame(task, &frame) < 0)
103+
break;
104+
}
105+
106+
/*
107+
* If we cannot traverse the expected number of stack frames,
108+
* there is something wrong with the stack.
109+
*/
110+
if (i < aframes) {
111+
DTRACE_CPUFLAG_SET(CPU_DTRACE_BADSTACK);
112+
113+
return 0;
114+
}
115+
116+
st = (uint64_t *)frame.fp;
117+
}
118+
119+
/*
120+
* The first 7 arguments (arg0 through arg6) are passed in registers
121+
* to dtrace_probe(). The remaining arguments (arg7 through arg9) are
122+
* passed on the stack.
123+
*
124+
* Stack layout:
125+
* bp[0] = pushed fp from caller
126+
* bp[1] = return address
127+
* bp[2] = 8th argument (arg7 -> argno = 7)
128+
* bp[3] = 9th argument (arg8 -> argno = 8)
129+
* ...
130+
*/
131+
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
132+
val = READ_ONCE_NOCHECK(st[2 + (argno - 7)]);
133+
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
134+
135+
return val;
136+
}
137+
138+
ulong_t dtrace_getreg(struct task_struct *task, uint_t reg)
139+
{
140+
struct pt_regs *rp = task_pt_regs(task);
141+
142+
return regs_get_register(rp, reg * sizeof(uint64_t));
143+
}
144+
145+
void pdata_init(dtrace_module_t *pdata, struct module *mp)
146+
{
147+
/*
148+
* Throw away existing data as we don't support reusal at
149+
* the moment.
150+
*/
151+
if (mp->pdata != NULL)
152+
pdata_cleanup(pdata, mp);
153+
154+
pdata->sdt_tab = NULL;
155+
pdata->fbt_tab = NULL;
156+
}
157+
158+
void pdata_cleanup(dtrace_module_t *pdata, struct module *mp)
159+
{
160+
if (pdata->sdt_tab != NULL)
161+
dtrace_free_text(pdata->sdt_tab);
162+
if (pdata->fbt_tab != NULL)
163+
dtrace_free_text(pdata->fbt_tab);
164+
}

0 commit comments

Comments
 (0)