The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/cddl/dev/kinst/kinst.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * SPDX-License-Identifier: CDDL 1.0
    3  *
    4  * Copyright 2022 Christos Margiolis <christos@FreeBSD.org>
    5  */
    6 
    7 #include <sys/param.h>
    8 #include <sys/systm.h>
    9 #include <sys/conf.h>
   10 #include <sys/kernel.h>
   11 #include <sys/linker.h>
   12 #include <sys/module.h>
   13 
   14 #include <sys/dtrace.h>
   15 
   16 #include "kinst.h"
   17 
   18 MALLOC_DEFINE(M_KINST, "kinst", "Kernel Instruction Tracing");
   19 
   20 static d_open_t         kinst_open;
   21 static d_close_t        kinst_close;
   22 static d_ioctl_t        kinst_ioctl;
   23 
   24 static void     kinst_provide_module(void *, modctl_t *);
   25 static void     kinst_getargdesc(void *, dtrace_id_t, void *,
   26                     dtrace_argdesc_t *);
   27 static void     kinst_destroy(void *, dtrace_id_t, void *);
   28 static void     kinst_enable(void *, dtrace_id_t, void *);
   29 static void     kinst_disable(void *, dtrace_id_t, void *);
   30 static int      kinst_load(void *);
   31 static int      kinst_unload(void *);
   32 static int      kinst_modevent(module_t, int, void *);
   33 
   34 static dtrace_pattr_t kinst_attr = {
   35 { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
   36 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
   37 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
   38 { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
   39 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
   40 };
   41 
   42 static const dtrace_pops_t kinst_pops = {
   43         .dtps_provide           = NULL,
   44         .dtps_provide_module    = kinst_provide_module,
   45         .dtps_enable            = kinst_enable,
   46         .dtps_disable           = kinst_disable,
   47         .dtps_suspend           = NULL,
   48         .dtps_resume            = NULL,
   49         .dtps_getargdesc        = kinst_getargdesc,
   50         .dtps_getargval         = NULL,
   51         .dtps_usermode          = NULL,
   52         .dtps_destroy           = kinst_destroy
   53 };
   54 
   55 static struct cdevsw kinst_cdevsw = {
   56         .d_name                 = "kinst",
   57         .d_version              = D_VERSION,
   58         .d_flags                = D_TRACKCLOSE,
   59         .d_open                 = kinst_open,
   60         .d_close                = kinst_close,
   61         .d_ioctl                = kinst_ioctl,
   62 };
   63 
   64 static dtrace_provider_id_t     kinst_id;
   65 struct kinst_probe_list *kinst_probetab;
   66 static struct cdev      *kinst_cdev;
   67 
   68 void
   69 kinst_probe_create(struct kinst_probe *kp, linker_file_t lf)
   70 {
   71         kp->kp_id = dtrace_probe_create(kinst_id, lf->filename,
   72             kp->kp_func, kp->kp_name, 3, kp);
   73 
   74         LIST_INSERT_HEAD(KINST_GETPROBE(kp->kp_patchpoint), kp, kp_hashnext);
   75 }
   76 
   77 static int
   78 kinst_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused,
   79     struct thread *td __unused)
   80 {
   81         return (0);
   82 }
   83 
   84 static int
   85 kinst_close(struct cdev *dev __unused, int fflag __unused, int devtype __unused,
   86     struct thread *td __unused)
   87 {
   88         dtrace_condense(kinst_id);
   89         return (0);
   90 }
   91 
   92 static int
   93 kinst_linker_file_cb(linker_file_t lf, void *arg)
   94 {
   95         dtrace_kinst_probedesc_t *pd;
   96 
   97         pd = arg;
   98         if (pd->kpd_mod[0] != '\0' && strcmp(pd->kpd_mod, lf->filename) != 0)
   99                 return (0);
  100 
  101         /*
  102          * Invoke kinst_make_probe_function() once for each function symbol in
  103          * the module "lf".
  104          */
  105         return (linker_file_function_listall(lf, kinst_make_probe, arg));
  106 }
  107 
  108 static int
  109 kinst_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t addr,
  110     int flags __unused, struct thread *td __unused)
  111 {
  112         dtrace_kinst_probedesc_t *pd;
  113         int error = 0;
  114 
  115         switch (cmd) {
  116         case KINSTIOC_MAKEPROBE:
  117                 pd = (dtrace_kinst_probedesc_t *)addr;
  118                 pd->kpd_func[sizeof(pd->kpd_func) - 1] = '\0';
  119                 pd->kpd_mod[sizeof(pd->kpd_mod) - 1] = '\0';
  120 
  121                 /* Loop over all functions in the kernel and loaded modules. */
  122                 error = linker_file_foreach(kinst_linker_file_cb, pd);
  123                 break;
  124         default:
  125                 error = ENOTTY;
  126                 break;
  127         }
  128 
  129         return (error);
  130 }
  131 
  132 static void
  133 kinst_provide_module(void *arg, modctl_t *lf)
  134 {
  135 }
  136 
  137 static void
  138 kinst_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *desc)
  139 {
  140         desc->dtargd_ndx = DTRACE_ARGNONE;
  141 }
  142 
  143 static void
  144 kinst_destroy(void *arg, dtrace_id_t id, void *parg)
  145 {
  146         struct kinst_probe *kp = parg;
  147 
  148         LIST_REMOVE(kp, kp_hashnext);
  149         free(kp, M_KINST);
  150 }
  151 
  152 static void
  153 kinst_enable(void *arg, dtrace_id_t id, void *parg)
  154 {
  155         struct kinst_probe *kp = parg;
  156         static bool warned = false;
  157 
  158         if (!warned) {
  159                 KINST_LOG(
  160                     "kinst: This provider is experimental, exercise caution");
  161                 warned = true;
  162         }
  163 
  164         kinst_patch_tracepoint(kp, kp->kp_patchval);
  165 }
  166 
  167 static void
  168 kinst_disable(void *arg, dtrace_id_t id, void *parg)
  169 {
  170         struct kinst_probe *kp = parg;
  171 
  172         kinst_patch_tracepoint(kp, kp->kp_savedval);
  173 }
  174 
  175 static int
  176 kinst_load(void *dummy)
  177 {
  178         int error;
  179 
  180         error = kinst_trampoline_init();
  181         if (error != 0)
  182                 return (error);
  183         error = kinst_md_init();
  184         if (error != 0) {
  185                 kinst_trampoline_deinit();
  186                 return (error);
  187         }
  188 
  189         error = dtrace_register("kinst", &kinst_attr, DTRACE_PRIV_USER, NULL,
  190             &kinst_pops, NULL, &kinst_id);
  191         if (error != 0) {
  192                 kinst_md_deinit();
  193                 kinst_trampoline_deinit();
  194                 return (error);
  195         }
  196         kinst_probetab = malloc(KINST_PROBETAB_MAX *
  197             sizeof(struct kinst_probe_list), M_KINST, M_WAITOK | M_ZERO);
  198         for (int i = 0; i < KINST_PROBETAB_MAX; i++)
  199                 LIST_INIT(&kinst_probetab[i]);
  200         kinst_cdev = make_dev(&kinst_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
  201             "dtrace/kinst");
  202         dtrace_invop_add(kinst_invop);
  203         return (0);
  204 }
  205 
  206 static int
  207 kinst_unload(void *dummy)
  208 {
  209         free(kinst_probetab, M_KINST);
  210         kinst_md_deinit();
  211         kinst_trampoline_deinit();
  212         dtrace_invop_remove(kinst_invop);
  213         destroy_dev(kinst_cdev);
  214 
  215         return (dtrace_unregister(kinst_id));
  216 }
  217 
  218 static int
  219 kinst_modevent(module_t mod __unused, int type, void *data __unused)
  220 {
  221         int error = 0;
  222 
  223         switch (type) {
  224         case MOD_LOAD:
  225                 break;
  226         case MOD_UNLOAD:
  227                 break;
  228         case MOD_SHUTDOWN:
  229                 break;
  230         default:
  231                 error = EOPNOTSUPP;
  232                 break;
  233         }
  234 
  235         return (error);
  236 }
  237 
  238 SYSINIT(kinst_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, kinst_load, NULL);
  239 SYSUNINIT(kinst_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, kinst_unload,
  240     NULL);
  241 
  242 DEV_MODULE(kinst, kinst_modevent, NULL);
  243 MODULE_VERSION(kinst, 1);
  244 MODULE_DEPEND(kinst, dtrace, 1, 1, 1);
  245 MODULE_DEPEND(kinst, opensolaris, 1, 1, 1);

Cache object: 589d26ca32d0d54cc1f6d6bc9cb353b4


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.