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/fbt/riscv/fbt_isa.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  * CDDL HEADER START
    3  *
    4  * The contents of this file are subject to the terms of the
    5  * Common Development and Distribution License (the "License").
    6  * You may not use this file except in compliance with the License.
    7  *
    8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    9  * or http://www.opensolaris.org/os/licensing.
   10  * See the License for the specific language governing permissions
   11  * and limitations under the License.
   12  *
   13  * When distributing Covered Code, include this CDDL HEADER in each
   14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   15  * If applicable, add the following below this CDDL HEADER, with the
   16  * fields enclosed by brackets "[]" replaced with your own identifying
   17  * information: Portions Copyright [yyyy] [name of copyright owner]
   18  *
   19  * CDDL HEADER END
   20  *
   21  * Portions Copyright 2006-2008 John Birrell jb@freebsd.org
   22  * Portions Copyright 2013 Justin Hibbits jhibbits@freebsd.org
   23  * Portions Copyright 2013 Howard Su howardsu@freebsd.org
   24  * Portions Copyright 2016-2018 Ruslan Bukin <br@bsdpad.com>
   25  *
   26  * $FreeBSD$
   27  */
   28 
   29 /*
   30  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
   31  * Use is subject to license terms.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 #include <sys/param.h>
   36 
   37 #include <sys/dtrace.h>
   38 
   39 #include <machine/riscvreg.h>
   40 #include <machine/encoding.h>
   41 
   42 #include "fbt.h"
   43 
   44 #define FBT_C_PATCHVAL          MATCH_C_EBREAK
   45 #define FBT_PATCHVAL            MATCH_EBREAK
   46 #define FBT_ENTRY               "entry"
   47 #define FBT_RETURN              "return"
   48 #define FBT_AFRAMES             5
   49 
   50 int
   51 fbt_invop(uintptr_t addr, struct trapframe *frame, uintptr_t rval)
   52 {
   53         solaris_cpu_t *cpu;
   54         fbt_probe_t *fbt;
   55 
   56         cpu = &solaris_cpu[curcpu];
   57         fbt = fbt_probetab[FBT_ADDR2NDX(addr)];
   58 
   59         for (; fbt != NULL; fbt = fbt->fbtp_hashnext) {
   60                 if ((uintptr_t)fbt->fbtp_patchpoint == addr) {
   61                         cpu->cpu_dtrace_caller = frame->tf_ra - INSN_SIZE;
   62 
   63                         if (fbt->fbtp_roffset == 0) {
   64                                 dtrace_probe(fbt->fbtp_id, frame->tf_a[0],
   65                                     frame->tf_a[1], frame->tf_a[2],
   66                                     frame->tf_a[3], frame->tf_a[4]);
   67                         } else {
   68                                 dtrace_probe(fbt->fbtp_id, fbt->fbtp_roffset,
   69                                     frame->tf_a[0], frame->tf_a[1], 0, 0);
   70                         }
   71 
   72                         cpu->cpu_dtrace_caller = 0;
   73                         return (fbt->fbtp_savedval);
   74                 }
   75         }
   76 
   77         return (0);
   78 }
   79 
   80 void
   81 fbt_patch_tracepoint(fbt_probe_t *fbt, fbt_patchval_t val)
   82 {
   83 
   84         switch(fbt->fbtp_patchval) {
   85         case FBT_C_PATCHVAL:
   86                 *(uint16_t *)fbt->fbtp_patchpoint = (uint16_t)val;
   87                 fence_i();
   88                 break;
   89         case FBT_PATCHVAL:
   90                 *fbt->fbtp_patchpoint = val;
   91                 fence_i();
   92                 break;
   93         };
   94 }
   95 
   96 static int
   97 match_opcode(uint32_t insn, int match, int mask)
   98 {
   99 
  100         if (((insn ^ match) & mask) == 0)
  101                 return (1);
  102 
  103         return (0);
  104 }
  105 
  106 static int
  107 check_c_ret(uint32_t **instr)
  108 {
  109         uint16_t *instr1;
  110         int i;
  111 
  112         for (i = 0; i < 2; i++) {
  113                 instr1 = (uint16_t *)(*instr) + i;
  114                 if (match_opcode(*instr1, (MATCH_C_JR | (X_RA << RD_SHIFT)),
  115                     (MASK_C_JR | RD_MASK))) {
  116                         *instr = (uint32_t *)instr1;
  117                         return (1);
  118                 }
  119         }
  120 
  121         return (0);
  122 }
  123 
  124 static int
  125 check_c_sdsp(uint32_t **instr)
  126 {
  127         uint16_t *instr1;
  128         int i;
  129 
  130         for (i = 0; i < 2; i++) {
  131                 instr1 = (uint16_t *)(*instr) + i;
  132                 if (match_opcode(*instr1, (MATCH_C_SDSP | RS2_C_RA),
  133                     (MASK_C_SDSP | RS2_C_MASK))) {
  134                         *instr = (uint32_t *)instr1;
  135                         return (1);
  136                 }
  137         }
  138 
  139         return (0);
  140 }
  141 
  142 int
  143 fbt_provide_module_function(linker_file_t lf, int symindx,
  144     linker_symval_t *symval, void *opaque)
  145 {
  146         fbt_probe_t *fbt, *retfbt;
  147         uint32_t *instr, *limit;
  148         const char *name;
  149         char *modname;
  150         int patchval;
  151         int rval;
  152 
  153         modname = opaque;
  154         name = symval->name;
  155 
  156         /* Check if function is excluded from instrumentation */
  157         if (fbt_excluded(name))
  158                 return (0);
  159 
  160         /*
  161          * Some assembly-language exception handlers are not suitable for
  162          * instrumentation.
  163          */
  164         if (strcmp(name, "cpu_exception_handler") == 0)
  165                 return (0);
  166         if (strcmp(name, "cpu_exception_handler_user") == 0)
  167                 return (0);
  168         if (strcmp(name, "cpu_exception_handler_supervisor") == 0)
  169                 return (0);
  170         if (strcmp(name, "do_trap_supervisor") == 0)
  171                 return (0);
  172 
  173         instr = (uint32_t *)(symval->value);
  174         limit = (uint32_t *)(symval->value + symval->size);
  175 
  176         /* Look for sd operation */
  177         for (; instr < limit; instr++) {
  178                 /* Look for a non-compressed store of ra to sp */
  179                 if (match_opcode(*instr, (MATCH_SD | RS2_RA | RS1_SP),
  180                     (MASK_SD | RS2_MASK | RS1_MASK))) {
  181                         rval = DTRACE_INVOP_SD;
  182                         patchval = FBT_PATCHVAL;
  183                         break;
  184                 }
  185 
  186                 /* Look for a 'C'-compressed store of ra to sp. */
  187                 if (check_c_sdsp(&instr)) {
  188                         rval = DTRACE_INVOP_C_SDSP;
  189                         patchval = FBT_C_PATCHVAL;
  190                         break;
  191                 }
  192         }
  193 
  194         if (instr >= limit)
  195                 return (0);
  196 
  197         fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
  198         fbt->fbtp_name = name;
  199         fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
  200             name, FBT_ENTRY, FBT_AFRAMES, fbt);
  201         fbt->fbtp_patchpoint = instr;
  202         fbt->fbtp_ctl = lf;
  203         fbt->fbtp_loadcnt = lf->loadcnt;
  204         fbt->fbtp_savedval = *instr;
  205         fbt->fbtp_patchval = patchval;
  206         fbt->fbtp_rval = rval;
  207         fbt->fbtp_symindx = symindx;
  208 
  209         fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
  210         fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
  211 
  212         lf->fbt_nentries++;
  213 
  214         retfbt = NULL;
  215 again:
  216         for (; instr < limit; instr++) {
  217                 /* Look for non-compressed return */
  218                 if (match_opcode(*instr, (MATCH_JALR | (X_RA << RS1_SHIFT)),
  219                     (MASK_JALR | RD_MASK | RS1_MASK | IMM_MASK))) {
  220                         rval = DTRACE_INVOP_RET;
  221                         patchval = FBT_PATCHVAL;
  222                         break;
  223                 }
  224 
  225                 /* Look for 'C'-compressed return */
  226                 if (check_c_ret(&instr)) {
  227                         rval = DTRACE_INVOP_C_RET;
  228                         patchval = FBT_C_PATCHVAL;
  229                         break;
  230                 }
  231         }
  232 
  233         if (instr >= limit)
  234                 return (0);
  235 
  236         /*
  237          * We have a winner!
  238          */
  239         fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
  240         fbt->fbtp_name = name;
  241         if (retfbt == NULL) {
  242                 fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
  243                     name, FBT_RETURN, FBT_AFRAMES, fbt);
  244         } else {
  245                 retfbt->fbtp_probenext = fbt;
  246                 fbt->fbtp_id = retfbt->fbtp_id;
  247         }
  248         retfbt = fbt;
  249 
  250         fbt->fbtp_patchpoint = instr;
  251         fbt->fbtp_ctl = lf;
  252         fbt->fbtp_loadcnt = lf->loadcnt;
  253         fbt->fbtp_symindx = symindx;
  254         fbt->fbtp_rval = rval;
  255         fbt->fbtp_roffset = (uintptr_t)instr - (uintptr_t)symval->value;
  256         fbt->fbtp_savedval = *instr;
  257         fbt->fbtp_patchval = patchval;
  258         fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
  259         fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
  260 
  261         lf->fbt_nentries++;
  262 
  263         instr++;
  264         goto again;
  265 }

Cache object: 6d33a64ed8d93ee963b9be29bfab960e


[ 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.