Message ID | 20210922223701.17521-1-quic_eberman@quicinc.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [1/1] firmware: smccc: Add tracepoints when SMCCC calls are made | expand |
On Wed, Sep 22, 2021 at 03:37:00PM -0700, Elliot Berman wrote: > Add trace events for SMCCC calls. These traces allow for convenient > mechanism for kernel to log SMC/HVC instructions without requiring > extracting traces from firmware. SMCCC spec currently [1] allows for 7 > argument registers and 4 result registers. I think you've missed additions in recent versions of the spec. Since SMCCCv1.2 (which is described in version of the document you've linked), SMC64 calls may pass up to 17 argument registers (x1-x17) and receive up to 18 result registers (x0-x17). SMC32 calls have up to 7 argument registers (r1-r7) and up to 8 return registers (r0-r7). What do you want to use this for? What specifically do you want to trace. I'm worried that this is a very low level transport, and hooking this means tracing a bunch of unrelated users (e.g. PSCI, ARCH_WORKAROUND* calls, vendor-specific SMC interfaces), and potentially gets in the way of some of those use-cases (e.g. tracng this means it cannot be used from noinstr code, which we likely need to be able to do in future). Generally I'd prefer to have tracepoints in specific drivers rather than in the SMCCC transport. > The first argument should > always be a function identifier, so use that to match the exit trace. > > [1]: ARM DEN 0028D (https://developer.arm.com/documentation/den0028/d/) > > Signed-off-by: Elliot Berman <quic_eberman@quicinc.com> > --- > drivers/firmware/smccc/Kconfig | 8 ++ > drivers/firmware/smccc/Makefile | 1 + > drivers/firmware/smccc/arm-smccc-traces.c | 14 ++++ > include/linux/arm-smccc.h | 38 +++++++-- > include/trace/events/arm_smccc.h | 99 +++++++++++++++++++++++ > 5 files changed, 154 insertions(+), 6 deletions(-) > create mode 100644 drivers/firmware/smccc/arm-smccc-traces.c > create mode 100644 include/trace/events/arm_smccc.h > > diff --git a/drivers/firmware/smccc/Kconfig b/drivers/firmware/smccc/Kconfig > index 15e7466179a6..fb7d2da1558e 100644 > --- a/drivers/firmware/smccc/Kconfig > +++ b/drivers/firmware/smccc/Kconfig > @@ -23,3 +23,11 @@ config ARM_SMCCC_SOC_ID > help > Include support for the SoC bus on the ARM SMCCC firmware based > platforms providing some sysfs information about the SoC variant. > + > +config TRACE_ARM_SMCCC > + bool "Trace ARM SMCCC Calls" > + depends on HAVE_ARM_SMCCC > + depends on TRACEPOINTS > + default y > + help > + Enable trace events to log SMC and HVC service calls. > diff --git a/drivers/firmware/smccc/Makefile b/drivers/firmware/smccc/Makefile > index 40d19144a860..be50ae665040 100644 > --- a/drivers/firmware/smccc/Makefile > +++ b/drivers/firmware/smccc/Makefile > @@ -2,3 +2,4 @@ > # > obj-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smccc.o kvm_guest.o > obj-$(CONFIG_ARM_SMCCC_SOC_ID) += soc_id.o > +obj-$(CONFIG_TRACE_ARM_SMCCC) += arm-smccc-traces.o > diff --git a/drivers/firmware/smccc/arm-smccc-traces.c b/drivers/firmware/smccc/arm-smccc-traces.c > new file mode 100644 > index 000000000000..9c6282644c02 > --- /dev/null > +++ b/drivers/firmware/smccc/arm-smccc-traces.c > @@ -0,0 +1,14 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * ARM SMCCC Trace points > + * > + * Copyright (C) 2021, The Linux Foundation. All rights reserved. > + */ > + > +#include <linux/export.h> > + > +#define CREATE_TRACE_POINTS > +#include <trace/events/arm_smccc.h> > + > +EXPORT_TRACEPOINT_SYMBOL_GPL(arm_smccc_start); > +EXPORT_TRACEPOINT_SYMBOL_GPL(arm_smccc_end); > diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h > index 7d1cabe15262..c214cebb1603 100644 > --- a/include/linux/arm-smccc.h > +++ b/include/linux/arm-smccc.h > @@ -190,6 +190,7 @@ > > #include <linux/linkage.h> > #include <linux/types.h> > +#include <trace/events/arm_smccc.h> > > enum arm_smccc_conduit { > SMCCC_CONDUIT_NONE, > @@ -343,13 +344,25 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, > unsigned long a5, unsigned long a6, unsigned long a7, > struct arm_smccc_res *res, struct arm_smccc_quirk *quirk); > > -#define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL) > +#define __arm_smccc(call, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, res, quirk) \ > + do { \ > + trace_arm_smccc_start(tracepoint_string(#call), \ > + (arg0), (arg1), (arg2), (arg3), (arg4), \ > + (arg5), (arg6), (arg7)); \ > + __arm_smccc_##call((arg0), (arg1), (arg2), (arg3), (arg4), (arg5), (arg6), (arg7),\ > + (res), (quirk)); \ > + trace_arm_smccc_end(tracepoint_string(#call), (arg0), \ > + (res)->a0, (res)->a1, (res)->a2, (res)->a3); \ > + } while (0) > + > > -#define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__) > +#define arm_smccc_smc(...) __arm_smccc(smc, __VA_ARGS__, NULL) > > -#define arm_smccc_hvc(...) __arm_smccc_hvc(__VA_ARGS__, NULL) > +#define arm_smccc_smc_quirk(...) __arm_smccc(smc, __VA_ARGS__) > > -#define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__) > +#define arm_smccc_hvc(...) __arm_smccc(hvc, __VA_ARGS__, NULL) > + > +#define arm_smccc_hvc_quirk(...) __arm_smccc(hvc, __VA_ARGS__) > > /* SMCCC v1.1 implementation madness follows */ > #ifdef CONFIG_ARM64 > @@ -450,22 +463,35 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, > : smccc_sve_clobbers "memory" > #define __constraints(count) ___constraints(count) > > +#define __trace_arg_0 ((unsigned long)arg0) > +#define __trace_arg_1 __trace_arg_0, ((unsigned long)arg1) > +#define __trace_arg_2 __trace_arg_1, ((unsigned long)arg2) > +#define __trace_arg_3 __trace_arg_2, ((unsigned long)arg3) > +#define __trace_arg_4 __trace_arg_3, ((unsigned long)arg4) > +#define __trace_arg_5 __trace_arg_4, ((unsigned long)arg5) > +#define __trace_arg_6 __trace_arg_5, ((unsigned long)arg6) > +#define __trace_arg_7 __trace_arg_6, ((unsigned long)arg7) > +#define ___trace_args(count) __trace_arg_##count > +#define __trace_args(count) ___trace_args(count) > + > /* > * We have an output list that is not necessarily used, and GCC feels > * entitled to optimise the whole sequence away. "volatile" is what > * makes it stick. > */ > -#define __arm_smccc_1_1(inst, ...) \ > +#define __arm_smccc_1_1(inst, a0, ...) \ > do { \ > register unsigned long r0 asm("r0"); \ > register unsigned long r1 asm("r1"); \ > register unsigned long r2 asm("r2"); \ > register unsigned long r3 asm("r3"); \ > __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \ > + trace_arm_smccc_start_vargs(tracepoint_string(inst), __trace_args(__count_args(a0, __VA_ARGS__))); \ > asm volatile(SMCCC_SVE_CHECK \ > inst "\n" : \ > "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3) \ > - __constraints(__count_args(__VA_ARGS__))); \ > + __constraints(__count_args(a0, __VA_ARGS__))); \ > + trace_arm_smccc_end(tracepoint_string(inst), a0, r0, r1, r2, r3); \ > if (___res) \ > *___res = (typeof(*___res)){r0, r1, r2, r3}; \ > } while (0) We have other functions for incoking SMCCC calls, e.g. * arm_smccc_smc() * arm_smccc_hvc() * arm_smccc_1_2_hvc() * arm_smccc_1_2_smc() ... so if you really need to hook all SMCCC calls I'd expect you need to hook those too, somehow Thanks, Mark. > diff --git a/include/trace/events/arm_smccc.h b/include/trace/events/arm_smccc.h > new file mode 100644 > index 000000000000..533377d2d066 > --- /dev/null > +++ b/include/trace/events/arm_smccc.h > @@ -0,0 +1,99 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved. > + */ > + > +#if IS_REACHABLE(CONFIG_TRACE_ARM_SMCCC) && !defined(__KVM_NVHE_HYPERVISOR__) > + > +#undef TRACE_SYSTEM > +#define TRACE_SYSTEM arm_smccc > + > +#if !defined(_TRACE_ARM_SMCCC_H) || defined(TRACE_HEADER_MULTI_READ) > +#define _TRACE_ARM_SMCCC_H > + > + > +#include <linux/tracepoint.h> > + > +TRACE_EVENT(arm_smccc_start, > + TP_PROTO(const char *call, unsigned long a0, unsigned long a1, unsigned long a2, > + unsigned long a3, unsigned long a4, unsigned long a5, unsigned long a6, > + unsigned long a7), > + > + TP_ARGS(call, a0, a1, a2, a3, a4, a5, a6, a7), > + > + TP_STRUCT__entry( > + __field(unsigned long, a0) > + __field(unsigned long, a1) > + __field(unsigned long, a2) > + __field(unsigned long, a3) > + __field(unsigned long, a4) > + __field(unsigned long, a5) > + __field(unsigned long, a6) > + __field(unsigned long, a7) > + __string(call, call) > + ), > + > + TP_fast_assign( > + __entry->a0 = a0; > + __entry->a1 = a1; > + __entry->a2 = a2; > + __entry->a3 = a3; > + __entry->a4 = a4; > + __entry->a5 = a5; > + __entry->a6 = a6; > + __entry->a7 = a7; > + > + __assign_str(call, call); > + ), > + > + TP_printk("call=%s fn=%04x args={%0lx %0lx %0lx %0lx %0lx %0lx %0lx}", > + __get_str(call), __entry->a0, __entry->a1, __entry->a2, > + __entry->a3, __entry->a4, __entry->a5, __entry->a6, __entry->a7) > +); > + > +TRACE_EVENT(arm_smccc_end, > + TP_PROTO(const char *call, unsigned long a0, unsigned long r0, unsigned long r1, > + unsigned long r2, unsigned long r3), > + > + TP_ARGS(call, a0, r0, r1, r2, r3), > + > + TP_STRUCT__entry( > + __field(unsigned long, a0) > + __field(unsigned long, r0) > + __field(unsigned long, r1) > + __field(unsigned long, r2) > + __field(unsigned long, r3) > + __string(call, call) > + ), > + > + TP_fast_assign( > + __entry->a0 = a0; > + __entry->r0 = r0; > + __entry->r1 = r1; > + __entry->r2 = r2; > + __entry->r3 = r3; > + > + __assign_str(call, call); > + ), > + > + TP_printk("call=%s fn=%04x res={%0lx %0lx %0lx %0lx}", > + __get_str(call), __entry->a0, __entry->r0, __entry->r1, > + __entry->r2, __entry->r3) > +); > + > +#define _trace_arm_smccc_start(call, a0, a1, a2, a3, a4, a5, a6, a7, ...) \ > + trace_arm_smccc_start(call, a0, a1, a2, a3, a4, a5, a6, a7) > + > +#define trace_arm_smccc_start_vargs(call, ...) \ > + _trace_arm_smccc_start(call, __VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0) > + > +#endif > + > +/* This part must be outside protection */ > +#include <trace/define_trace.h> > + > +#else > +#define trace_arm_smccc_start(...) > +#define trace_arm_smccc_end(...) > + > +#define trace_arm_smccc_start_vargs(...) > +#endif > -- > 2.33.0 >
On Thu 23 Sep 06:21 CDT 2021, Mark Rutland wrote: > On Wed, Sep 22, 2021 at 03:37:00PM -0700, Elliot Berman wrote: > > Add trace events for SMCCC calls. These traces allow for convenient > > mechanism for kernel to log SMC/HVC instructions without requiring > > extracting traces from firmware. SMCCC spec currently [1] allows for 7 > > argument registers and 4 result registers. > > I think you've missed additions in recent versions of the spec. Since > SMCCCv1.2 (which is described in version of the document you've linked), > SMC64 calls may pass up to 17 argument registers (x1-x17) and receive up > to 18 result registers (x0-x17). SMC32 calls have up to 7 argument > registers (r1-r7) and up to 8 return registers (r0-r7). > > What do you want to use this for? What specifically do you want to > trace. > > I'm worried that this is a very low level transport, and hooking this > means tracing a bunch of unrelated users (e.g. PSCI, ARCH_WORKAROUND* > calls, vendor-specific SMC interfaces), and potentially gets in the way > of some of those use-cases (e.g. tracng this means it cannot be used > from noinstr code, which we likely need to be able to do in future). > > Generally I'd prefer to have tracepoints in specific drivers rather than > in the SMCCC transport. > I agree, putting the tracepoint at this low level will essentially provide us with a hexdump of all SMC operations and one would more or less need to so some post processing to get something useful out of it. And in the few cases where the arguments are references to data buffers there's no way to trace that content (e.g. qcom_scm_assign_mem()). If we move it one step up we can provide trace data that's directly useful to a human, provide insights in the data, allow for proper filtering etc. Regards, Bjorn
diff --git a/drivers/firmware/smccc/Kconfig b/drivers/firmware/smccc/Kconfig index 15e7466179a6..fb7d2da1558e 100644 --- a/drivers/firmware/smccc/Kconfig +++ b/drivers/firmware/smccc/Kconfig @@ -23,3 +23,11 @@ config ARM_SMCCC_SOC_ID help Include support for the SoC bus on the ARM SMCCC firmware based platforms providing some sysfs information about the SoC variant. + +config TRACE_ARM_SMCCC + bool "Trace ARM SMCCC Calls" + depends on HAVE_ARM_SMCCC + depends on TRACEPOINTS + default y + help + Enable trace events to log SMC and HVC service calls. diff --git a/drivers/firmware/smccc/Makefile b/drivers/firmware/smccc/Makefile index 40d19144a860..be50ae665040 100644 --- a/drivers/firmware/smccc/Makefile +++ b/drivers/firmware/smccc/Makefile @@ -2,3 +2,4 @@ # obj-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smccc.o kvm_guest.o obj-$(CONFIG_ARM_SMCCC_SOC_ID) += soc_id.o +obj-$(CONFIG_TRACE_ARM_SMCCC) += arm-smccc-traces.o diff --git a/drivers/firmware/smccc/arm-smccc-traces.c b/drivers/firmware/smccc/arm-smccc-traces.c new file mode 100644 index 000000000000..9c6282644c02 --- /dev/null +++ b/drivers/firmware/smccc/arm-smccc-traces.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM SMCCC Trace points + * + * Copyright (C) 2021, The Linux Foundation. All rights reserved. + */ + +#include <linux/export.h> + +#define CREATE_TRACE_POINTS +#include <trace/events/arm_smccc.h> + +EXPORT_TRACEPOINT_SYMBOL_GPL(arm_smccc_start); +EXPORT_TRACEPOINT_SYMBOL_GPL(arm_smccc_end); diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index 7d1cabe15262..c214cebb1603 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h @@ -190,6 +190,7 @@ #include <linux/linkage.h> #include <linux/types.h> +#include <trace/events/arm_smccc.h> enum arm_smccc_conduit { SMCCC_CONDUIT_NONE, @@ -343,13 +344,25 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a5, unsigned long a6, unsigned long a7, struct arm_smccc_res *res, struct arm_smccc_quirk *quirk); -#define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL) +#define __arm_smccc(call, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, res, quirk) \ + do { \ + trace_arm_smccc_start(tracepoint_string(#call), \ + (arg0), (arg1), (arg2), (arg3), (arg4), \ + (arg5), (arg6), (arg7)); \ + __arm_smccc_##call((arg0), (arg1), (arg2), (arg3), (arg4), (arg5), (arg6), (arg7),\ + (res), (quirk)); \ + trace_arm_smccc_end(tracepoint_string(#call), (arg0), \ + (res)->a0, (res)->a1, (res)->a2, (res)->a3); \ + } while (0) + -#define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__) +#define arm_smccc_smc(...) __arm_smccc(smc, __VA_ARGS__, NULL) -#define arm_smccc_hvc(...) __arm_smccc_hvc(__VA_ARGS__, NULL) +#define arm_smccc_smc_quirk(...) __arm_smccc(smc, __VA_ARGS__) -#define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__) +#define arm_smccc_hvc(...) __arm_smccc(hvc, __VA_ARGS__, NULL) + +#define arm_smccc_hvc_quirk(...) __arm_smccc(hvc, __VA_ARGS__) /* SMCCC v1.1 implementation madness follows */ #ifdef CONFIG_ARM64 @@ -450,22 +463,35 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, : smccc_sve_clobbers "memory" #define __constraints(count) ___constraints(count) +#define __trace_arg_0 ((unsigned long)arg0) +#define __trace_arg_1 __trace_arg_0, ((unsigned long)arg1) +#define __trace_arg_2 __trace_arg_1, ((unsigned long)arg2) +#define __trace_arg_3 __trace_arg_2, ((unsigned long)arg3) +#define __trace_arg_4 __trace_arg_3, ((unsigned long)arg4) +#define __trace_arg_5 __trace_arg_4, ((unsigned long)arg5) +#define __trace_arg_6 __trace_arg_5, ((unsigned long)arg6) +#define __trace_arg_7 __trace_arg_6, ((unsigned long)arg7) +#define ___trace_args(count) __trace_arg_##count +#define __trace_args(count) ___trace_args(count) + /* * We have an output list that is not necessarily used, and GCC feels * entitled to optimise the whole sequence away. "volatile" is what * makes it stick. */ -#define __arm_smccc_1_1(inst, ...) \ +#define __arm_smccc_1_1(inst, a0, ...) \ do { \ register unsigned long r0 asm("r0"); \ register unsigned long r1 asm("r1"); \ register unsigned long r2 asm("r2"); \ register unsigned long r3 asm("r3"); \ __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \ + trace_arm_smccc_start_vargs(tracepoint_string(inst), __trace_args(__count_args(a0, __VA_ARGS__))); \ asm volatile(SMCCC_SVE_CHECK \ inst "\n" : \ "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3) \ - __constraints(__count_args(__VA_ARGS__))); \ + __constraints(__count_args(a0, __VA_ARGS__))); \ + trace_arm_smccc_end(tracepoint_string(inst), a0, r0, r1, r2, r3); \ if (___res) \ *___res = (typeof(*___res)){r0, r1, r2, r3}; \ } while (0) diff --git a/include/trace/events/arm_smccc.h b/include/trace/events/arm_smccc.h new file mode 100644 index 000000000000..533377d2d066 --- /dev/null +++ b/include/trace/events/arm_smccc.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#if IS_REACHABLE(CONFIG_TRACE_ARM_SMCCC) && !defined(__KVM_NVHE_HYPERVISOR__) + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM arm_smccc + +#if !defined(_TRACE_ARM_SMCCC_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_ARM_SMCCC_H + + +#include <linux/tracepoint.h> + +TRACE_EVENT(arm_smccc_start, + TP_PROTO(const char *call, unsigned long a0, unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4, unsigned long a5, unsigned long a6, + unsigned long a7), + + TP_ARGS(call, a0, a1, a2, a3, a4, a5, a6, a7), + + TP_STRUCT__entry( + __field(unsigned long, a0) + __field(unsigned long, a1) + __field(unsigned long, a2) + __field(unsigned long, a3) + __field(unsigned long, a4) + __field(unsigned long, a5) + __field(unsigned long, a6) + __field(unsigned long, a7) + __string(call, call) + ), + + TP_fast_assign( + __entry->a0 = a0; + __entry->a1 = a1; + __entry->a2 = a2; + __entry->a3 = a3; + __entry->a4 = a4; + __entry->a5 = a5; + __entry->a6 = a6; + __entry->a7 = a7; + + __assign_str(call, call); + ), + + TP_printk("call=%s fn=%04x args={%0lx %0lx %0lx %0lx %0lx %0lx %0lx}", + __get_str(call), __entry->a0, __entry->a1, __entry->a2, + __entry->a3, __entry->a4, __entry->a5, __entry->a6, __entry->a7) +); + +TRACE_EVENT(arm_smccc_end, + TP_PROTO(const char *call, unsigned long a0, unsigned long r0, unsigned long r1, + unsigned long r2, unsigned long r3), + + TP_ARGS(call, a0, r0, r1, r2, r3), + + TP_STRUCT__entry( + __field(unsigned long, a0) + __field(unsigned long, r0) + __field(unsigned long, r1) + __field(unsigned long, r2) + __field(unsigned long, r3) + __string(call, call) + ), + + TP_fast_assign( + __entry->a0 = a0; + __entry->r0 = r0; + __entry->r1 = r1; + __entry->r2 = r2; + __entry->r3 = r3; + + __assign_str(call, call); + ), + + TP_printk("call=%s fn=%04x res={%0lx %0lx %0lx %0lx}", + __get_str(call), __entry->a0, __entry->r0, __entry->r1, + __entry->r2, __entry->r3) +); + +#define _trace_arm_smccc_start(call, a0, a1, a2, a3, a4, a5, a6, a7, ...) \ + trace_arm_smccc_start(call, a0, a1, a2, a3, a4, a5, a6, a7) + +#define trace_arm_smccc_start_vargs(call, ...) \ + _trace_arm_smccc_start(call, __VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0) + +#endif + +/* This part must be outside protection */ +#include <trace/define_trace.h> + +#else +#define trace_arm_smccc_start(...) +#define trace_arm_smccc_end(...) + +#define trace_arm_smccc_start_vargs(...) +#endif
Add trace events for SMCCC calls. These traces allow for convenient mechanism for kernel to log SMC/HVC instructions without requiring extracting traces from firmware. SMCCC spec currently [1] allows for 7 argument registers and 4 result registers. The first argument should always be a function identifier, so use that to match the exit trace. [1]: ARM DEN 0028D (https://developer.arm.com/documentation/den0028/d/) Signed-off-by: Elliot Berman <quic_eberman@quicinc.com> --- drivers/firmware/smccc/Kconfig | 8 ++ drivers/firmware/smccc/Makefile | 1 + drivers/firmware/smccc/arm-smccc-traces.c | 14 ++++ include/linux/arm-smccc.h | 38 +++++++-- include/trace/events/arm_smccc.h | 99 +++++++++++++++++++++++ 5 files changed, 154 insertions(+), 6 deletions(-) create mode 100644 drivers/firmware/smccc/arm-smccc-traces.c create mode 100644 include/trace/events/arm_smccc.h