]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: revamp and split up DTrace headers; add ioctl() debugging machinery
authorNick Alcock <nick.alcock@oracle.com>
Mon, 29 Apr 2013 12:57:15 +0000 (13:57 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Mon, 29 Jun 2015 21:41:43 +0000 (22:41 +0100)
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 <sys/types.h>,
<ctf/types.h>, and <unistd.h>; for kernelspace, the set is <linux/types.h> and a
newly-introduced header included as <dtrace/types.h>.  We avoid exposing this
requirement to header users by arranging for the header included as "dtrace.h"
in kernelspace and as <sys/dtrace.h> 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 <linux/dtrace_cpu.h> 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 <linux/dtrace/blah.h>

   in both userspace and kernelspace.

   #include <linux/include/dtrace.h> 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 <linux/dtrace/ioctl.h> 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 <linux/dtrace_cpu_defines.h>, 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.)

   <linux/dtrace/universal.h> 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 <dtrace/blah.h>:

   - <dtrace/types.h>: 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.

   - <dtrace/provider.h>: The provider API, and its corresponding
     <dtrace/provider_defines.h> defines header.  This includes <dtrace/types.h>
     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.

   - <dtrace/dtrace_impl.h> and <dtrace/dtrace_impl_defines.h>.

     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;
<dtrace/types.h> 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 <unistd.h> 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 <nick.alcock@oracle.com>
include/linux/dtrace_cpu.h
include/linux/dtrace_cpu_defines.h [new file with mode: 0644]
include/linux/dtrace_ioctl.h [deleted file]
include/linux/dtrace_os.h
include/linux/dtrace_psinfo.h

index a066486c549d04a32381e5aa052e937d016e6481..1508de06b56718e7a7a2cfca1e1cdcf0618a40a1 100644 (file)
@@ -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 <linux/ktime.h>
 #include <linux/mutex.h>
-
-#define CPUC_SIZE      (sizeof (uint16_t) + sizeof(uint8_t) + \
-                        sizeof(uintptr_t) + sizeof(struct mutex))
-#define CPUC_PADSIZE   (192 - CPUC_SIZE)
+#include <linux/dtrace_cpu_defines.h>
 
 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 (file)
index 0000000..a6709be
--- /dev/null
@@ -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 (file)
index 7bec9b6..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Copyright (C) 2011, 2012, 2013 Oracle, Inc. */
-
-#ifndef _DTRACE_IOCTL_H_
-#define _DTRACE_IOCTL_H_
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-#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
index da541b304b2684e5640318c74e3938eaa03d30e5..969d79fc3919e2035998f2333e1a7ad269d54725 100644 (file)
@@ -1,12 +1,14 @@
 /* Copyright (C) 2011, 2012, 2013 Oracle, Inc. */
 
-#ifndef _DTRACE_OS_H_
-#define _DTRACE_OS_H_
-
-#include <asm/asm-offsets.h>
+#ifndef _LINUX_DTRACE_OS_H_
+#define _LINUX_DTRACE_OS_H_
 
 typedef uint32_t dtrace_id_t;
 
+#ifndef HEADERS_CHECK
+
+#include <asm/asm-offsets.h>
+
 #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_ */
index 7c6c6c1723a45a2a2cb3ee310b0f4c329520147e..f9a149c94b0be08763a53c51ed32014138ad4854 100644 (file)
@@ -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_ */