From: Nick Alcock Date: Mon, 29 Apr 2013 12:57:15 +0000 (+0100) Subject: dtrace: revamp and split up DTrace headers; add ioctl() debugging machinery X-Git-Tag: v4.1.12-92~313^2~83 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=4f22e663c4c237ccfda044d9cc5b5837dd0211c7;p=users%2Fjedix%2Flinux-maple.git dtrace: revamp and split up DTrace headers; add ioctl() debugging machinery It has always been annoying that we have a duplicate set of DTrace headers in userspace, and further annoying that the DTrace header we have is such a monolithic monster. This fixes both of these, at the cost of a (very) little extra complexity when maintaining the headers. It also adds automated machinery to verify that each of the new headers is 'standalone enough'. What does 'standalone enough' mean? This is the problem that has stopped us sharing DTrace headers between userspace and kernelspace for a long time: they depend on types that come from different places and have different definitions in the kernel and in userspace, and can never be made to come from the same place. So we fix this by dictating that the headers are standalone *given* that certain headers are included first. For userspace, this set is , , and ; for kernelspace, the set is and a newly-introduced header included as . We avoid exposing this requirement to header users by arranging for the header included as "dtrace.h" in kernelspace and as in userspace to include the prerequisite headers, and enough other headers that the users of those headers can keep using them exactly as they did before. (There is a single exception for dtrace/ioctl.h: see below.) Where have the headers gone? They have been split in two directions (and the Kbuild machinery has been adjusted to have its include paths point at the appropriate places). All DTrace headers, even in the global kernel tree, have had 'defines headers' split out of them, named ${header}_defines.h. These headers contain all typedefs, enums and #defines which do not depend on visibility into structure definitions declared in the main non-defines header, and opaque forwardings for all structure definitions declared in that header. This means that users can include the defines header if they only want opaque use of structures and relevant constants. (This has necessitated some mechanical changes to the DTrace headers to convert uses of foo_t typedefs into 'struct foo' where necessary. Not all uses have been converted: only those that need to be). A _defines header is always accompanied by a corresponding non _defines header (even if it is just one #include), but the reverse is not true. In addition to this split, the core dtrace.h header has been split into three pieces: - dtrace/include/uapi/linux/dtrace/*.h contains the majority of the headers, split into _defines and further by section roughly corresponding with the comment-delimited sections in the original file. The include paths have been set up so that these can be used via #include in both userspace and kernelspace. #include includes all the headers in the same order as they were originally. These headers are installed in userspace and used by dtrace-util. They should always contain a CDDL license header, and should not use any kernel-specific types (modulo those that userspace normally uses, such as those related to kernel-specific functionality such as ioctl()). If you use a new kernel-specific type, please add a definition of it to uts/common/sys/dtrace_types.h in userspace too. The old dtrace_ioctl.h has been renamed to and moved in here too. It has gained some extra machinery to help debug ioctl() type size conflicts. If you call dtrace_ioctl_sizes(), then dtrace_size_dbg_print() (not defined here) is repeatedly called with two parameters, the name of each ioctl() type and the size of that type. Please keep this list up to date, it is useful! There is one unfortunate exception to the userspace-types rule here: ioctl.h needs types from , which is not even a userspace-installed header. So userspace must provide a copy of this header with appropriate typedefs as well. (This should probably be fixed in due course.) defines constants and types used by virtually everything in any way related to dtrace. - dtrace/include/dtrace/*.h contains headers that are not shared with userspace, included as : - : this contains the kernel-side definitions of types used in the shared headers. (It has not been 'gardened' in any way, so probably contains a lot of other types as well). This header is installed into the same place as the shared userspace headers. This header needs a bit of care maintaining, as not everything kernel- side is allowable in it: see below. - : The provider API, and its corresponding defines header. This includes itself, so should be standalone -- however, this has not been in any way tested yet, unlike for the userspace headers. This header is also installed into the same place as the shared userspace headers. - and . These headers contain definitions used only by the DTrace core, and are not installed anywhere. Note that because of the rules regarding kernel-specific types in the UAPI DTrace headers, a number of uses of CONFIG_64BIT and CONFIG_BIG_ENDIAN have been reverted to their Solaris-era-and-userspace _LP64 and _LITTLE_ENDIAN forms; translates between the two. (We have also fixed up a couple of places in core DTrace where the nonexistent _BIG_ENDIAN was used.) There are several things called dtrace.h now, which might get confusing: - dtrace.h at the top level is for the DTrace core and included providers alone. Anything goes in here. It is never installed anywhere, and not even standalone providers can see it. - dtrace/include/uapi/linux/dtrace/dtrace.h is shared with userspace and with standalone providers, and needs to follow the same rules as all such shared headers. We have two new packages, dtrace-modules-$kver-headers and dtrace-modules-$kver-provider-headers; to make it easy for people to Require them, they provide features named 'dtrace-modules-headers' and 'dtrace-modules-provider-headers' using the same incrementing API version number as 'dtrace-kernel-interface' (both currently 1). dtrace-modules-headers serves much the same purpose as dtrace-kernel-interface, tracking changes in the userspace/kernelspace API: the dtrace-modules-provider-headers version number tracks changes in the DTrace core/provider API. The top-level Makefile has acquired two new rules, headers_install and headers_check. The former is a simple emulation of the top-level headers_install rule, and is used by the RPM build system. The latter checks to be sure that the userspace-side headers can be #included on their own (modulo only et al, as above), and that dtrace/ioctl.h has all its types in scope with appropriate sizes, since if they aren't everything will appear to work until userspace tries to invoke the ioctl() and gets an -ENOTTY error. The latter is particularly difficult, since the size-checking machinery only works for kernelspace builds, and the headers_check build is userspace. So that machinery hacks up a sort of halfway-house to the kernel environment, enough to do the ioctl() size checks but not enough to #include arbitrary kernel headers (among other things, there are no CONFIG constants here). This means that changes to those kernel-side headers which are included by this machinery (in particular dtrace/types.h, dtrace_os.h) need to include a headers_check run to make sure that machinery hasn't broken. In general, surrounding suspect definitions with an #ifndef HEADERS_CHECK should suffice: nearly all of dtrace_os.h is so surrounded (and if we ever move dtrace_id_t out into the shared headers, as perhaps we should, this problem will become less serious). (Feel free to make the headers_check dtrace/ioctl.h compilation environment more like that used for the real kernel.) Signed-off-by: Nick Alcock --- diff --git a/include/linux/dtrace_cpu.h b/include/linux/dtrace_cpu.h index a066486c549d..1508de06b567 100644 --- a/include/linux/dtrace_cpu.h +++ b/include/linux/dtrace_cpu.h @@ -1,14 +1,11 @@ /* Copyright (C) 2011, 2012, 2013 Oracle, Inc. */ -#ifndef _DTRACE_CPU_H_ -#define _DTRACE_CPU_H_ +#ifndef _LINUX_DTRACE_CPU_H_ +#define _LINUX_DTRACE_CPU_H_ #include #include - -#define CPUC_SIZE (sizeof (uint16_t) + sizeof(uint8_t) + \ - sizeof(uintptr_t) + sizeof(struct mutex)) -#define CPUC_PADSIZE (192 - CPUC_SIZE) +#include typedef struct cpu_core { uint16_t cpuc_dtrace_flags; @@ -24,43 +21,6 @@ typedef struct cpu_core { DECLARE_PER_CPU_SHARED_ALIGNED(cpu_core_t, dtrace_cpu_core); -#define per_cpu_core(cpu) (&per_cpu(dtrace_cpu_core, (cpu))) -#define this_cpu_core (&__get_cpu_var(dtrace_cpu_core)) - -#define DTRACE_CPUFLAG_ISSET(flag) \ - (this_cpu_core->cpuc_dtrace_flags & (flag)) - -#define DTRACE_CPUFLAG_SET(flag) \ - (this_cpu_core->cpuc_dtrace_flags |= (flag)) - -#define DTRACE_CPUFLAG_CLEAR(flag) \ - (this_cpu_core->cpuc_dtrace_flags &= ~(flag)) - -#define CPU_DTRACE_NOFAULT 0x0001 -#define CPU_DTRACE_DROP 0x0002 -#define CPU_DTRACE_BADADDR 0x0004 -#define CPU_DTRACE_BADALIGN 0x0008 -#define CPU_DTRACE_DIVZERO 0x0010 -#define CPU_DTRACE_ILLOP 0x0020 -#define CPU_DTRACE_NOSCRATCH 0x0040 -#define CPU_DTRACE_KPRIV 0x0080 -#define CPU_DTRACE_UPRIV 0x0100 -#define CPU_DTRACE_TUPOFLOW 0x0200 -#define CPU_DTRACE_ENTRY 0x0800 -#define CPU_DTRACE_BADSTACK 0x1000 - -#define CPU_DTRACE_FAULT (CPU_DTRACE_BADADDR | CPU_DTRACE_BADALIGN | \ - CPU_DTRACE_DIVZERO | CPU_DTRACE_ILLOP | \ - CPU_DTRACE_NOSCRATCH | CPU_DTRACE_KPRIV | \ - CPU_DTRACE_UPRIV | CPU_DTRACE_TUPOFLOW | \ - CPU_DTRACE_BADSTACK) -#define CPU_DTRACE_ERROR (CPU_DTRACE_FAULT | CPU_DTRACE_DROP) - -typedef uint32_t processorid_t; -typedef uint32_t psetid_t; -typedef uint32_t chipid_t; -typedef uint32_t lgrp_id_t; - typedef struct cpuinfo { processorid_t cpu_id; psetid_t cpu_pset; @@ -71,9 +31,6 @@ typedef struct cpuinfo { DECLARE_PER_CPU_SHARED_ALIGNED(cpuinfo_t, dtrace_cpu_info); -#define per_cpu_info(cpu) (&per_cpu(dtrace_cpu_info, (cpu))) -#define this_cpu_info (&__get_cpu_var(dtrace_cpu_info)) - extern void dtrace_cpu_init(void); -#endif /* _DTRACE_CPU_H_ */ +#endif /* _LINUX_DTRACE_CPU_H_ */ diff --git a/include/linux/dtrace_cpu_defines.h b/include/linux/dtrace_cpu_defines.h new file mode 100644 index 000000000000..a6709bee8cef --- /dev/null +++ b/include/linux/dtrace_cpu_defines.h @@ -0,0 +1,53 @@ +/* Copyright (C) 2011, 2012, 2013 Oracle, Inc. */ + +#ifndef _LINUX_DTRACE_CPU_DEFINES_H_ +#define _LINUX_DTRACE_CPU_DEFINES_H_ + +#define CPUC_SIZE (sizeof (uint16_t) + sizeof(uint8_t) + \ + sizeof(uintptr_t) + sizeof(struct mutex)) +#define CPUC_PADSIZE (192 - CPUC_SIZE) + +#define per_cpu_core(cpu) (&per_cpu(dtrace_cpu_core, (cpu))) +#define this_cpu_core (&__get_cpu_var(dtrace_cpu_core)) + +#define DTRACE_CPUFLAG_ISSET(flag) \ + (this_cpu_core->cpuc_dtrace_flags & (flag)) + +#define DTRACE_CPUFLAG_SET(flag) \ + (this_cpu_core->cpuc_dtrace_flags |= (flag)) + +#define DTRACE_CPUFLAG_CLEAR(flag) \ + (this_cpu_core->cpuc_dtrace_flags &= ~(flag)) + +#define CPU_DTRACE_NOFAULT 0x0001 +#define CPU_DTRACE_DROP 0x0002 +#define CPU_DTRACE_BADADDR 0x0004 +#define CPU_DTRACE_BADALIGN 0x0008 +#define CPU_DTRACE_DIVZERO 0x0010 +#define CPU_DTRACE_ILLOP 0x0020 +#define CPU_DTRACE_NOSCRATCH 0x0040 +#define CPU_DTRACE_KPRIV 0x0080 +#define CPU_DTRACE_UPRIV 0x0100 +#define CPU_DTRACE_TUPOFLOW 0x0200 +#define CPU_DTRACE_ENTRY 0x0800 +#define CPU_DTRACE_BADSTACK 0x1000 + +#define CPU_DTRACE_FAULT (CPU_DTRACE_BADADDR | CPU_DTRACE_BADALIGN | \ + CPU_DTRACE_DIVZERO | CPU_DTRACE_ILLOP | \ + CPU_DTRACE_NOSCRATCH | CPU_DTRACE_KPRIV | \ + CPU_DTRACE_UPRIV | CPU_DTRACE_TUPOFLOW | \ + CPU_DTRACE_BADSTACK) +#define CPU_DTRACE_ERROR (CPU_DTRACE_FAULT | CPU_DTRACE_DROP) + +typedef uint32_t processorid_t; +typedef uint32_t psetid_t; +typedef uint32_t chipid_t; +typedef uint32_t lgrp_id_t; + +struct cpu_core; +struct cpuinfo; + +#define per_cpu_info(cpu) (&per_cpu(dtrace_cpu_info, (cpu))) +#define this_cpu_info (&__get_cpu_var(dtrace_cpu_info)) + +#endif /* _LINUX_DTRACE_CPU_DEFINES_H_ */ diff --git a/include/linux/dtrace_ioctl.h b/include/linux/dtrace_ioctl.h deleted file mode 100644 index 7bec9b6fe7a2..000000000000 --- a/include/linux/dtrace_ioctl.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright (C) 2011, 2012, 2013 Oracle, Inc. */ - -#ifndef _DTRACE_IOCTL_H_ -#define _DTRACE_IOCTL_H_ - -#include -#include - -#define DTRACEIOC 0xd4 -#define DTRACEIOC_PROVIDER _IOR(DTRACEIOC, 1, dtrace_providerdesc_t) -#define DTRACEIOC_PROBES _IOR(DTRACEIOC, 2, dtrace_probedesc_t) -#define DTRACEIOC_BUFSNAP _IOR(DTRACEIOC, 4, dtrace_bufdesc_t) -#define DTRACEIOC_PROBEMATCH _IOR(DTRACEIOC, 5, dtrace_probedesc_t) -#define DTRACEIOC_ENABLE _IOW(DTRACEIOC, 6, void *) -#define DTRACEIOC_AGGSNAP _IOR(DTRACEIOC, 7, dtrace_bufdesc_t) -#define DTRACEIOC_EPROBE _IOW(DTRACEIOC, 8, dtrace_eprobedesc_t) -#define DTRACEIOC_PROBEARG _IOR(DTRACEIOC, 9, dtrace_argdesc_t) -#define DTRACEIOC_CONF _IOR(DTRACEIOC, 10, dtrace_conf_t) -#define DTRACEIOC_STATUS _IOR(DTRACEIOC, 11, dtrace_status_t) -#define DTRACEIOC_GO _IOW(DTRACEIOC, 12, processorid_t) -#define DTRACEIOC_STOP _IOW(DTRACEIOC, 13, processorid_t) -#define DTRACEIOC_AGGDESC _IOR(DTRACEIOC, 15, dtrace_aggdesc_t) -#define DTRACEIOC_FORMAT _IOR(DTRACEIOC, 16, dtrace_fmtdesc_t) -#define DTRACEIOC_DOFGET _IOR(DTRACEIOC, 17, dof_hdr_t) -#define DTRACEIOC_REPLICATE _IOR(DTRACEIOC, 18, void *) - -#define DTRACEHIOC 0xd8 -#define DTRACEHIOC_ADD _IOW(DTRACEHIOC, 1, dof_hdr_t) -#define DTRACEHIOC_REMOVE _IOW(DTRACEHIOC, 2, int) -#define DTRACEHIOC_ADDDOF _IOW(DTRACEHIOC, 3, dof_helper_t) - -#endif diff --git a/include/linux/dtrace_os.h b/include/linux/dtrace_os.h index da541b304b26..969d79fc3919 100644 --- a/include/linux/dtrace_os.h +++ b/include/linux/dtrace_os.h @@ -1,12 +1,14 @@ /* Copyright (C) 2011, 2012, 2013 Oracle, Inc. */ -#ifndef _DTRACE_OS_H_ -#define _DTRACE_OS_H_ - -#include +#ifndef _LINUX_DTRACE_OS_H_ +#define _LINUX_DTRACE_OS_H_ typedef uint32_t dtrace_id_t; +#ifndef HEADERS_CHECK + +#include + #define DTRACE_IDNONE 0 #define SCE_CLONE 0 @@ -80,4 +82,6 @@ extern void dtrace_task_cleanup(struct task_struct *tsk); extern void (*dtrace_helpers_cleanup)(struct task_struct *); extern void (*dtrace_fasttrap_probes_cleanup)(struct task_struct *); -#endif /* _DTRACE_OS_H_ */ +#endif + +#endif /* _LINUX_DTRACE_OS_H_ */ diff --git a/include/linux/dtrace_psinfo.h b/include/linux/dtrace_psinfo.h index 7c6c6c1723a4..f9a149c94b0b 100644 --- a/include/linux/dtrace_psinfo.h +++ b/include/linux/dtrace_psinfo.h @@ -1,7 +1,7 @@ /* Copyright (C) 2011, 2012, 2013 Oracle, Inc. */ -#ifndef _DTRACE_PSINFO_H_ -#define _DTRACE_PSINFO_H_ +#ifndef _LINUX_DTRACE_PSINFO_H_ +#define _LINUX_DTRACE_PSINFO_H_ #define PR_PSARGS_SZ 80 @@ -18,4 +18,4 @@ typedef struct dtrace_psinfo { extern dtrace_psinfo_t *dtrace_psinfo_alloc(struct task_struct *); extern void dtrace_psinfo_free(dtrace_psinfo_t *); -#endif /* _DTRACE_PSINFO_H_ */ +#endif /* _LINUX_DTRACE_PSINFO_H_ */