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/mips/mips/db_interface.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: db_machdep.c,v 1.2 1998/09/15 10:50:13 pefo Exp $ */
    2 
    3 /*-
    4  * SPDX-License-Identifier: BSD-4-Clause
    5  *
    6  * Copyright (c) 1998 Per Fogelstrom, Opsycon AB
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed under OpenBSD by
   19  *      Per Fogelstrom, Opsycon AB, Sweden.
   20  * 4. The name of the author may not be used to endorse or promote products
   21  *    derived from this software without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
   24  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
   27  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  *
   35  *      JNPR: db_interface.c,v 1.6.2.1 2007/08/29 12:24:49 girish
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __FBSDID("$FreeBSD: stable/12/sys/mips/mips/db_interface.c 327097 2017-12-22 23:27:03Z kib $");
   40 
   41 #include <sys/types.h>
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/cons.h>
   45 #include <sys/lock.h>
   46 #include <vm/vm.h>
   47 #include <vm/vm_object.h>
   48 #include <vm/vm_page.h>
   49 #include <vm/pmap.h>
   50 #include <vm/vm_map.h>
   51 #include <sys/user.h>
   52 #include <sys/proc.h>
   53 #include <sys/reboot.h>
   54 
   55 #include <machine/cache.h>
   56 #include <machine/db_machdep.h>
   57 #include <machine/mips_opcode.h>
   58 #include <machine/vmparam.h>
   59 #include <machine/md_var.h>
   60 #include <machine/setjmp.h>
   61 
   62 #include <ddb/ddb.h>
   63 #include <ddb/db_sym.h>
   64 #include <ddb/db_access.h>
   65 #include <ddb/db_output.h>
   66 #include <ddb/db_variables.h>
   67 #include <sys/kdb.h>
   68 
   69 static db_varfcn_t db_frame;
   70 
   71 #define DB_OFFSET(x)    (db_expr_t *)offsetof(struct trapframe, x)
   72 struct db_variable db_regs[] = {
   73         { "at",  DB_OFFSET(ast),        db_frame },
   74         { "v0",  DB_OFFSET(v0),         db_frame },
   75         { "v1",  DB_OFFSET(v1),         db_frame },
   76         { "a0",  DB_OFFSET(a0),         db_frame },
   77         { "a1",  DB_OFFSET(a1),         db_frame },
   78         { "a2",  DB_OFFSET(a2),         db_frame },
   79         { "a3",  DB_OFFSET(a3),         db_frame },
   80 #if defined(__mips_n32) || defined(__mips_n64)
   81         { "a4",  DB_OFFSET(a4),         db_frame },
   82         { "a5",  DB_OFFSET(a5),         db_frame },
   83         { "a6",  DB_OFFSET(a6),         db_frame },
   84         { "a7",  DB_OFFSET(a7),         db_frame },
   85         { "t0",  DB_OFFSET(t0),         db_frame },
   86         { "t1",  DB_OFFSET(t1),         db_frame },
   87         { "t2",  DB_OFFSET(t2),         db_frame },
   88         { "t3",  DB_OFFSET(t3),         db_frame },
   89 #else
   90         { "t0",  DB_OFFSET(t0),         db_frame },
   91         { "t1",  DB_OFFSET(t1),         db_frame },
   92         { "t2",  DB_OFFSET(t2),         db_frame },
   93         { "t3",  DB_OFFSET(t3),         db_frame },
   94         { "t4",  DB_OFFSET(t4),         db_frame },
   95         { "t5",  DB_OFFSET(t5),         db_frame },
   96         { "t6",  DB_OFFSET(t6),         db_frame },
   97         { "t7",  DB_OFFSET(t7),         db_frame },
   98 #endif
   99         { "s0",  DB_OFFSET(s0),         db_frame },
  100         { "s1",  DB_OFFSET(s1),         db_frame },
  101         { "s2",  DB_OFFSET(s2),         db_frame },
  102         { "s3",  DB_OFFSET(s3),         db_frame },
  103         { "s4",  DB_OFFSET(s4),         db_frame },
  104         { "s5",  DB_OFFSET(s5),         db_frame },
  105         { "s6",  DB_OFFSET(s6),         db_frame },
  106         { "s7",  DB_OFFSET(s7),         db_frame },
  107         { "t8",  DB_OFFSET(t8),         db_frame },
  108         { "t9",  DB_OFFSET(t9),         db_frame },
  109         { "k0",  DB_OFFSET(k0),         db_frame },
  110         { "k1",  DB_OFFSET(k1),         db_frame },
  111         { "gp",  DB_OFFSET(gp),         db_frame },
  112         { "sp",  DB_OFFSET(sp),         db_frame },
  113         { "s8",  DB_OFFSET(s8),         db_frame },
  114         { "ra",  DB_OFFSET(ra),         db_frame },
  115         { "sr",  DB_OFFSET(sr),         db_frame },
  116         { "lo",  DB_OFFSET(mullo),      db_frame },
  117         { "hi",  DB_OFFSET(mulhi),      db_frame },
  118         { "bad", DB_OFFSET(badvaddr),   db_frame },
  119         { "cs",  DB_OFFSET(cause),      db_frame },
  120         { "pc",  DB_OFFSET(pc),         db_frame },
  121 };
  122 struct db_variable *db_eregs = db_regs + nitems(db_regs);
  123 
  124 int (*do_db_log_stack_trace_cmd)(char *);
  125 
  126 static int
  127 db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
  128 {
  129         register_t *reg;
  130 
  131         if (kdb_frame == NULL)
  132                 return (0);
  133 
  134         reg = (register_t *)((uintptr_t)kdb_frame + (size_t)(intptr_t)vp->valuep);
  135         if (op == DB_VAR_GET)
  136                 *valuep = *reg;
  137         else
  138                 *reg = *valuep;
  139         return (1);
  140 }
  141 
  142 int
  143 db_read_bytes(vm_offset_t addr, size_t size, char *data)
  144 {
  145         jmp_buf jb;
  146         void *prev_jb;
  147         int ret;
  148 
  149         prev_jb = kdb_jmpbuf(jb);
  150         ret = setjmp(jb);
  151         if (ret == 0) {
  152                 /*
  153                  * 'addr' could be a memory-mapped I/O address.  Try to
  154                  * do atomic load/store in unit of size requested.
  155                  * size == 8 is only atomic on 64bit or n32 kernel.
  156                  */
  157                 if ((size == 2 || size == 4 || size == 8) &&
  158                     ((addr & (size -1)) == 0) &&
  159                     (((vm_offset_t)data & (size -1)) == 0)) {
  160                         switch (size) {
  161                         case 2:
  162                                 *(uint16_t *)data = *(uint16_t *)addr;
  163                                 break;
  164                         case 4:
  165                                 *(uint32_t *)data = *(uint32_t *)addr;
  166                                 break;
  167                         case 8:
  168                                 *(uint64_t *)data = *(uint64_t *)addr;
  169                                 break;
  170                         }
  171                 } else {
  172                         char *src;
  173 
  174                         src = (char *)addr;
  175                         while (size-- > 0)
  176                                 *data++ = *src++;
  177                 }
  178         }
  179 
  180         (void)kdb_jmpbuf(prev_jb);
  181         return (ret);
  182 }
  183 
  184 int
  185 db_write_bytes(vm_offset_t addr, size_t size, char *data)
  186 {
  187         int ret;
  188         jmp_buf jb;
  189         void *prev_jb;
  190 
  191         prev_jb = kdb_jmpbuf(jb);
  192         ret = setjmp(jb);
  193 
  194         if (ret == 0) {
  195                 /*
  196                  * 'addr' could be a memory-mapped I/O address.  Try to
  197                  * do atomic load/store in unit of size requested.
  198                  * size == 8 is only atomic on 64bit or n32 kernel.
  199                  */
  200                 if ((size == 2 || size == 4 || size == 8) &&
  201                     ((addr & (size -1)) == 0) &&
  202                     (((vm_offset_t)data & (size -1)) == 0)) {
  203                         switch (size) {
  204                         case 2:
  205                                 *(uint16_t *)addr = *(uint16_t *)data;
  206                                 break;
  207                         case 4:
  208                                 *(uint32_t *)addr = *(uint32_t *)data;
  209                                 break;
  210                         case 8:
  211                                 *(uint64_t *)addr = *(uint64_t *)data;
  212                                 break;
  213                         }
  214                 } else {
  215                         char *dst;
  216                         size_t len = size;
  217 
  218                         dst = (char *)addr;
  219                         while (len-- > 0)
  220                                 *dst++ = *data++;
  221                 }
  222 
  223                 mips_icache_sync_range((db_addr_t) addr, size);
  224                 mips_dcache_wbinv_range((db_addr_t) addr, size);
  225         }
  226         (void)kdb_jmpbuf(prev_jb);
  227         return (ret);
  228 }
  229 
  230 /*
  231  *      To do a single step ddb needs to know the next address
  232  *      that we will get to. It means that we need to find out
  233  *      both the address for a branch taken and for not taken, NOT! :-)
  234  *      MipsEmulateBranch will do the job to find out _exactly_ which
  235  *      address we will end up at so the 'dual bp' method is not
  236  *      requiered.
  237  */
  238 db_addr_t
  239 next_instr_address(db_addr_t pc, boolean_t bd)
  240 {
  241         db_addr_t next;
  242 
  243         next = (db_addr_t)MipsEmulateBranch(kdb_frame, pc, 0, 0);
  244         return (next);
  245 }
  246 
  247 
  248 /*
  249  *      Decode instruction and figure out type.
  250  */
  251 int
  252 db_inst_type(int ins)
  253 {
  254         InstFmt inst;
  255         int     ityp = 0;
  256 
  257         inst.word = ins;
  258         switch ((int)inst.JType.op) {
  259         case OP_SPECIAL:
  260                 switch ((int)inst.RType.func) {
  261                 case OP_JR:
  262                         ityp = IT_BRANCH;
  263                         break;
  264                 case OP_JALR:
  265                 case OP_SYSCALL:
  266                         ityp = IT_CALL;
  267                         break;
  268                 }
  269                 break;
  270 
  271         case OP_BCOND:
  272                 switch ((int)inst.IType.rt) {
  273                 case OP_BLTZ:
  274                 case OP_BLTZL:
  275                 case OP_BGEZ:
  276                 case OP_BGEZL:
  277                         ityp = IT_BRANCH;
  278                         break;
  279 
  280                 case OP_BLTZAL:
  281                 case OP_BLTZALL:
  282                 case OP_BGEZAL:
  283                 case OP_BGEZALL:
  284                         ityp = IT_CALL;
  285                         break;
  286                 }
  287                 break;
  288 
  289         case OP_JAL:
  290                 ityp = IT_CALL;
  291                 break;
  292 
  293         case OP_J:
  294         case OP_BEQ:
  295         case OP_BEQL:
  296         case OP_BNE:
  297         case OP_BNEL:
  298         case OP_BLEZ:
  299         case OP_BLEZL:
  300         case OP_BGTZ:
  301         case OP_BGTZL:
  302                 ityp = IT_BRANCH;
  303                 break;
  304 
  305         case OP_COP1:
  306                 switch (inst.RType.rs) {
  307                 case OP_BCx:
  308                 case OP_BCy:
  309                         ityp = IT_BRANCH;
  310                         break;
  311                 }
  312                 break;
  313 
  314         case OP_LB:
  315         case OP_LH:
  316         case OP_LW:
  317         case OP_LD:
  318         case OP_LBU:
  319         case OP_LHU:
  320         case OP_LWU:
  321         case OP_LWC1:
  322                 ityp = IT_LOAD;
  323                 break;
  324 
  325         case OP_SB:
  326         case OP_SH:
  327         case OP_SW:
  328         case OP_SD:  
  329         case OP_SWC1:
  330                 ityp = IT_STORE;
  331                 break;
  332         }
  333         return (ityp);
  334 }
  335 
  336 /*
  337  * Return the next pc if the given branch is taken.
  338  * MachEmulateBranch() runs analysis for branch delay slot.
  339  */
  340 db_addr_t
  341 branch_taken(int inst, db_addr_t pc)
  342 {
  343         db_addr_t ra;
  344         register_t fpucsr;
  345 
  346         /* TBD: when is fsr set */
  347         fpucsr = (curthread) ? curthread->td_pcb->pcb_regs.fsr : 0;
  348         ra = (db_addr_t)MipsEmulateBranch(kdb_frame, pc, fpucsr, 0);
  349         return (ra);
  350 }

Cache object: c67bc8c214a72f2e1373dcbab8132997


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