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/arm/arm/debug_monitor.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  * Copyright (c) 2015 Juniper Networks Inc.
    3  * All rights reserved.
    4  *
    5  * Developed by Semihalf.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include "opt_ddb.h"
   33 
   34 #include <sys/param.h>
   35 #include <sys/types.h>
   36 #include <sys/kdb.h>
   37 #include <sys/pcpu.h>
   38 #include <sys/smp.h>
   39 #include <sys/systm.h>
   40 
   41 #include <machine/atomic.h>
   42 #include <machine/armreg.h>
   43 #include <machine/cpu.h>
   44 #include <machine/debug_monitor.h>
   45 #include <machine/kdb.h>
   46 #include <machine/pcb.h>
   47 #include <machine/reg.h>
   48 
   49 #include <ddb/ddb.h>
   50 #include <ddb/db_access.h>
   51 #include <ddb/db_sym.h>
   52 
   53 enum dbg_t {
   54         DBG_TYPE_BREAKPOINT = 0,
   55         DBG_TYPE_WATCHPOINT = 1,
   56 };
   57 
   58 struct dbg_wb_conf {
   59         enum dbg_t              type;
   60         enum dbg_access_t       access;
   61         db_addr_t               address;
   62         db_expr_t               size;
   63         u_int                   slot;
   64 };
   65 
   66 static int dbg_reset_state(void);
   67 static int dbg_setup_breakpoint(db_expr_t, db_expr_t, u_int);
   68 static int dbg_remove_breakpoint(u_int);
   69 static u_int dbg_find_slot(enum dbg_t, db_expr_t);
   70 static boolean_t dbg_check_slot_free(enum dbg_t, u_int);
   71 
   72 static int dbg_remove_xpoint(struct dbg_wb_conf *);
   73 static int dbg_setup_xpoint(struct dbg_wb_conf *);
   74 
   75 static int dbg_capable_var;     /* Indicates that machine is capable of using
   76                                    HW watchpoints/breakpoints */
   77 
   78 static uint32_t dbg_model;      /* Debug Arch. Model */
   79 static boolean_t dbg_ossr;      /* OS Save and Restore implemented */
   80 
   81 static uint32_t dbg_watchpoint_num;
   82 static uint32_t dbg_breakpoint_num;
   83 
   84 /* ID_DFR0 - Debug Feature Register 0 */
   85 #define ID_DFR0_CP_DEBUG_M_SHIFT        0
   86 #define ID_DFR0_CP_DEBUG_M_MASK         (0xF << ID_DFR0_CP_DEBUG_M_SHIFT)
   87 #define ID_DFR0_CP_DEBUG_M_NS           (0x0) /* Not supported */
   88 #define ID_DFR0_CP_DEBUG_M_V6           (0x2) /* v6 Debug arch. CP14 access */
   89 #define ID_DFR0_CP_DEBUG_M_V6_1         (0x3) /* v6.1 Debug arch. CP14 access */
   90 #define ID_DFR0_CP_DEBUG_M_V7           (0x4) /* v7 Debug arch. CP14 access */
   91 #define ID_DFR0_CP_DEBUG_M_V7_1         (0x5) /* v7.1 Debug arch. CP14 access */
   92 
   93 /* DBGDIDR - Debug ID Register */
   94 #define DBGDIDR_WRPS_SHIFT              28
   95 #define DBGDIDR_WRPS_MASK               (0xF << DBGDIDR_WRPS_SHIFT)
   96 #define DBGDIDR_WRPS_NUM(reg)           \
   97     ((((reg) & DBGDIDR_WRPS_MASK) >> DBGDIDR_WRPS_SHIFT) + 1)
   98 
   99 #define DBGDIDR_BRPS_SHIFT              24
  100 #define DBGDIDR_BRPS_MASK               (0xF << DBGDIDR_BRPS_SHIFT)
  101 #define DBGDIDR_BRPS_NUM(reg)           \
  102     ((((reg) & DBGDIDR_BRPS_MASK) >> DBGDIDR_BRPS_SHIFT) + 1)
  103 
  104 /* DBGPRSR - Device Powerdown and Reset Status Register */
  105 #define DBGPRSR_PU                      (1 << 0) /* Powerup status */
  106 
  107 /* DBGOSLSR - OS Lock Status Register */
  108 #define DBGOSLSR_OSLM0                  (1 << 0)
  109 
  110 /* DBGOSDLR - OS Double Lock Register */
  111 #define DBGPRSR_DLK                     (1 << 0) /* OS Double Lock set */
  112 
  113 /* DBGDSCR - Debug Status and Control Register */
  114 #define DBGSCR_MDBG_EN                  (1 << 15) /* Monitor debug-mode enable */
  115 
  116 /* DBGWVR - Watchpoint Value Register */
  117 #define DBGWVR_ADDR_MASK                (~0x3U)
  118 
  119 /* Watchpoints/breakpoints control register bitfields */
  120 #define DBG_WB_CTRL_LEN_1               (0x1 << 5)
  121 #define DBG_WB_CTRL_LEN_2               (0x3 << 5)
  122 #define DBG_WB_CTRL_LEN_4               (0xf << 5)
  123 #define DBG_WB_CTRL_LEN_8               (0xff << 5)
  124 #define DBG_WB_CTRL_LEN_MASK(x) ((x) & (0xff << 5))
  125 #define DBG_WB_CTRL_EXEC                (0x0 << 3)
  126 #define DBG_WB_CTRL_LOAD                (0x1 << 3)
  127 #define DBG_WB_CTRL_STORE               (0x2 << 3)
  128 #define DBG_WB_CTRL_ACCESS_MASK(x)      ((x) & (0x3 << 3))
  129 
  130 /* Common for breakpoint and watchpoint */
  131 #define DBG_WB_CTRL_PL1         (0x1 << 1)
  132 #define DBG_WB_CTRL_PL0         (0x2 << 1)
  133 #define DBG_WB_CTRL_PLX_MASK(x) ((x) & (0x3 << 1))
  134 #define DBG_WB_CTRL_E           (0x1 << 0)
  135 
  136 /*
  137  * Watchpoint/breakpoint helpers
  138  */
  139 #define DBG_BKPT_BT_SLOT        0       /* Slot for branch taken */
  140 #define DBG_BKPT_BNT_SLOT       1       /* Slot for branch not taken */
  141 
  142 #define OP2_SHIFT               4
  143 
  144 /* Opc2 numbers for coprocessor instructions */
  145 #define DBG_WB_BVR      4
  146 #define DBG_WB_BCR      5
  147 #define DBG_WB_WVR      6
  148 #define DBG_WB_WCR      7
  149 
  150 #define DBG_REG_BASE_BVR        (DBG_WB_BVR << OP2_SHIFT)
  151 #define DBG_REG_BASE_BCR        (DBG_WB_BCR << OP2_SHIFT)
  152 #define DBG_REG_BASE_WVR        (DBG_WB_WVR << OP2_SHIFT)
  153 #define DBG_REG_BASE_WCR        (DBG_WB_WCR << OP2_SHIFT)
  154 
  155 #define DBG_WB_READ(cn, cm, op2, val) do {                                      \
  156         __asm __volatile("mrc p14, 0, %0, " #cn "," #cm "," #op2 : "=r" (val)); \
  157 } while (0)
  158 
  159 #define DBG_WB_WRITE(cn, cm, op2, val) do {                                     \
  160         __asm __volatile("mcr p14, 0, %0, " #cn "," #cm "," #op2 :: "r" (val)); \
  161 } while (0)
  162 
  163 #define READ_WB_REG_CASE(op2, m, val)                   \
  164         case (((op2) << OP2_SHIFT) + m):                \
  165                 DBG_WB_READ(c0, c ## m, op2, val);      \
  166                 break
  167 
  168 #define WRITE_WB_REG_CASE(op2, m, val)                  \
  169         case (((op2) << OP2_SHIFT) + m):                \
  170                 DBG_WB_WRITE(c0, c ## m, op2, val);     \
  171                 break
  172 
  173 #define SWITCH_CASES_READ_WB_REG(op2, val)      \
  174         READ_WB_REG_CASE(op2,  0, val);         \
  175         READ_WB_REG_CASE(op2,  1, val);         \
  176         READ_WB_REG_CASE(op2,  2, val);         \
  177         READ_WB_REG_CASE(op2,  3, val);         \
  178         READ_WB_REG_CASE(op2,  4, val);         \
  179         READ_WB_REG_CASE(op2,  5, val);         \
  180         READ_WB_REG_CASE(op2,  6, val);         \
  181         READ_WB_REG_CASE(op2,  7, val);         \
  182         READ_WB_REG_CASE(op2,  8, val);         \
  183         READ_WB_REG_CASE(op2,  9, val);         \
  184         READ_WB_REG_CASE(op2, 10, val);         \
  185         READ_WB_REG_CASE(op2, 11, val);         \
  186         READ_WB_REG_CASE(op2, 12, val);         \
  187         READ_WB_REG_CASE(op2, 13, val);         \
  188         READ_WB_REG_CASE(op2, 14, val);         \
  189         READ_WB_REG_CASE(op2, 15, val)
  190 
  191 #define SWITCH_CASES_WRITE_WB_REG(op2, val)     \
  192         WRITE_WB_REG_CASE(op2,  0, val);        \
  193         WRITE_WB_REG_CASE(op2,  1, val);        \
  194         WRITE_WB_REG_CASE(op2,  2, val);        \
  195         WRITE_WB_REG_CASE(op2,  3, val);        \
  196         WRITE_WB_REG_CASE(op2,  4, val);        \
  197         WRITE_WB_REG_CASE(op2,  5, val);        \
  198         WRITE_WB_REG_CASE(op2,  6, val);        \
  199         WRITE_WB_REG_CASE(op2,  7, val);        \
  200         WRITE_WB_REG_CASE(op2,  8, val);        \
  201         WRITE_WB_REG_CASE(op2,  9, val);        \
  202         WRITE_WB_REG_CASE(op2, 10, val);        \
  203         WRITE_WB_REG_CASE(op2, 11, val);        \
  204         WRITE_WB_REG_CASE(op2, 12, val);        \
  205         WRITE_WB_REG_CASE(op2, 13, val);        \
  206         WRITE_WB_REG_CASE(op2, 14, val);        \
  207         WRITE_WB_REG_CASE(op2, 15, val)
  208 
  209 static uint32_t
  210 dbg_wb_read_reg(int reg, int n)
  211 {
  212         uint32_t val;
  213 
  214         val = 0;
  215 
  216         switch (reg + n) {
  217         SWITCH_CASES_READ_WB_REG(DBG_WB_WVR, val);
  218         SWITCH_CASES_READ_WB_REG(DBG_WB_WCR, val);
  219         SWITCH_CASES_READ_WB_REG(DBG_WB_BVR, val);
  220         SWITCH_CASES_READ_WB_REG(DBG_WB_BCR, val);
  221         default:
  222                 db_printf(
  223                     "trying to read from CP14 reg. using wrong opc2 %d\n",
  224                     reg >> OP2_SHIFT);
  225         }
  226 
  227         return (val);
  228 }
  229 
  230 static void
  231 dbg_wb_write_reg(int reg, int n, uint32_t val)
  232 {
  233 
  234         switch (reg + n) {
  235         SWITCH_CASES_WRITE_WB_REG(DBG_WB_WVR, val);
  236         SWITCH_CASES_WRITE_WB_REG(DBG_WB_WCR, val);
  237         SWITCH_CASES_WRITE_WB_REG(DBG_WB_BVR, val);
  238         SWITCH_CASES_WRITE_WB_REG(DBG_WB_BCR, val);
  239         default:
  240                 db_printf(
  241                     "trying to write to CP14 reg. using wrong opc2 %d\n",
  242                     reg >> OP2_SHIFT);
  243         }
  244         isb();
  245 }
  246 
  247 static __inline boolean_t
  248 dbg_capable(void)
  249 {
  250 
  251         return (atomic_cmpset_int(&dbg_capable_var, 0, 0) == 0);
  252 }
  253 
  254 boolean_t
  255 kdb_cpu_pc_is_singlestep(db_addr_t pc)
  256 {
  257         /*
  258          * XXX: If the platform fails to enable its debug arch.
  259          *      there will be no stepping capabilities
  260          */
  261         if (!dbg_capable())
  262                 return (FALSE);
  263 
  264         if (dbg_find_slot(DBG_TYPE_BREAKPOINT, pc) != ~0U)
  265                 return (TRUE);
  266 
  267         return (FALSE);
  268 }
  269 
  270 void
  271 kdb_cpu_set_singlestep(void)
  272 {
  273         db_expr_t inst;
  274         db_addr_t pc, brpc;
  275         uint32_t wcr;
  276         u_int i;
  277 
  278         if (!dbg_capable())
  279                 return;
  280 
  281         /*
  282          * Disable watchpoints, e.g. stepping over watched instruction will
  283          * trigger break exception instead of single-step exception and locks
  284          * CPU on that instruction for ever.
  285          */
  286         for (i = 0; i < dbg_watchpoint_num; i++) {
  287                 wcr = dbg_wb_read_reg(DBG_REG_BASE_WCR, i);
  288                 if ((wcr & DBG_WB_CTRL_E) != 0) {
  289                         dbg_wb_write_reg(DBG_REG_BASE_WCR, i,
  290                             (wcr & ~DBG_WB_CTRL_E));
  291                 }
  292         }
  293 
  294         pc = PC_REGS();
  295 
  296         inst = db_get_value(pc, sizeof(pc), FALSE);
  297         if (inst_branch(inst) || inst_call(inst) || inst_return(inst)) {
  298                 brpc = branch_taken(inst, pc);
  299                 dbg_setup_breakpoint(brpc, INSN_SIZE, DBG_BKPT_BT_SLOT);
  300         }
  301         pc = next_instr_address(pc, 0);
  302         dbg_setup_breakpoint(pc, INSN_SIZE, DBG_BKPT_BNT_SLOT);
  303 }
  304 
  305 void
  306 kdb_cpu_clear_singlestep(void)
  307 {
  308         uint32_t wvr, wcr;
  309         u_int i;
  310 
  311         if (!dbg_capable())
  312                 return;
  313 
  314         dbg_remove_breakpoint(DBG_BKPT_BT_SLOT);
  315         dbg_remove_breakpoint(DBG_BKPT_BNT_SLOT);
  316 
  317         /* Restore all watchpoints */
  318         for (i = 0; i < dbg_watchpoint_num; i++) {
  319                 wcr = dbg_wb_read_reg(DBG_REG_BASE_WCR, i);
  320                 wvr = dbg_wb_read_reg(DBG_REG_BASE_WVR, i);
  321                 /* Watchpoint considered not empty if address value is not 0 */
  322                 if ((wvr & DBGWVR_ADDR_MASK) != 0) {
  323                         dbg_wb_write_reg(DBG_REG_BASE_WCR, i,
  324                             (wcr | DBG_WB_CTRL_E));
  325                 }
  326         }
  327 }
  328 
  329 int
  330 dbg_setup_watchpoint(db_expr_t addr, db_expr_t size, enum dbg_access_t access)
  331 {
  332         struct dbg_wb_conf conf;
  333 
  334         if (access == HW_BREAKPOINT_X) {
  335                 db_printf("Invalid access type for watchpoint: %d\n", access);
  336                 return (EINVAL);
  337         }
  338 
  339         conf.address = addr;
  340         conf.size = size;
  341         conf.access = access;
  342         conf.type = DBG_TYPE_WATCHPOINT;
  343 
  344         return (dbg_setup_xpoint(&conf));
  345 }
  346 
  347 int
  348 dbg_remove_watchpoint(db_expr_t addr, db_expr_t size __unused)
  349 {
  350         struct dbg_wb_conf conf;
  351 
  352         conf.address = addr;
  353         conf.type = DBG_TYPE_WATCHPOINT;
  354 
  355         return (dbg_remove_xpoint(&conf));
  356 }
  357 
  358 static int
  359 dbg_setup_breakpoint(db_expr_t addr, db_expr_t size, u_int slot)
  360 {
  361         struct dbg_wb_conf conf;
  362 
  363         conf.address = addr;
  364         conf.size = size;
  365         conf.access = HW_BREAKPOINT_X;
  366         conf.type = DBG_TYPE_BREAKPOINT;
  367         conf.slot = slot;
  368 
  369         return (dbg_setup_xpoint(&conf));
  370 }
  371 
  372 static int
  373 dbg_remove_breakpoint(u_int slot)
  374 {
  375         struct dbg_wb_conf conf;
  376 
  377         /* Slot already cleared. Don't recurse */
  378         if (dbg_check_slot_free(DBG_TYPE_BREAKPOINT, slot))
  379                 return (0);
  380 
  381         conf.slot = slot;
  382         conf.type = DBG_TYPE_BREAKPOINT;
  383 
  384         return (dbg_remove_xpoint(&conf));
  385 }
  386 
  387 static const char *
  388 dbg_watchtype_str(uint32_t type)
  389 {
  390 
  391         switch (type) {
  392                 case DBG_WB_CTRL_EXEC:
  393                         return ("execute");
  394                 case DBG_WB_CTRL_STORE:
  395                         return ("write");
  396                 case DBG_WB_CTRL_LOAD:
  397                         return ("read");
  398                 case DBG_WB_CTRL_LOAD | DBG_WB_CTRL_STORE:
  399                         return ("read/write");
  400                 default:
  401                         return ("invalid");
  402         }
  403 }
  404 
  405 static int
  406 dbg_watchtype_len(uint32_t len)
  407 {
  408 
  409         switch (len) {
  410         case DBG_WB_CTRL_LEN_1:
  411                 return (1);
  412         case DBG_WB_CTRL_LEN_2:
  413                 return (2);
  414         case DBG_WB_CTRL_LEN_4:
  415                 return (4);
  416         case DBG_WB_CTRL_LEN_8:
  417                 return (8);
  418         default:
  419                 return (0);
  420         }
  421 }
  422 
  423 void
  424 dbg_show_watchpoint(void)
  425 {
  426         uint32_t wcr, len, type;
  427         uint32_t addr;
  428         boolean_t is_enabled;
  429         int i;
  430 
  431         if (!dbg_capable()) {
  432                 db_printf("Architecture does not support HW "
  433                     "breakpoints/watchpoints\n");
  434                 return;
  435         }
  436 
  437         db_printf("\nhardware watchpoints:\n");
  438         db_printf("  watch    status        type  len     address              symbol\n");
  439         db_printf("  -----  --------  ----------  ---  ----------  ------------------\n");
  440         for (i = 0; i < dbg_watchpoint_num; i++) {
  441                 wcr = dbg_wb_read_reg(DBG_REG_BASE_WCR, i);
  442                 if ((wcr & DBG_WB_CTRL_E) != 0)
  443                         is_enabled = TRUE;
  444                 else
  445                         is_enabled = FALSE;
  446 
  447                 type = DBG_WB_CTRL_ACCESS_MASK(wcr);
  448                 len = DBG_WB_CTRL_LEN_MASK(wcr);
  449                 addr = dbg_wb_read_reg(DBG_REG_BASE_WVR, i) & DBGWVR_ADDR_MASK;
  450                 db_printf("  %-5d  %-8s  %10s  %3d  0x%08x  ", i,
  451                     is_enabled ? "enabled" : "disabled",
  452                     is_enabled ? dbg_watchtype_str(type) : "",
  453                     is_enabled ? dbg_watchtype_len(len) : 0,
  454                     addr);
  455                 db_printsym((db_addr_t)addr, DB_STGY_ANY);
  456                 db_printf("\n");
  457         }
  458 }
  459 
  460 static boolean_t
  461 dbg_check_slot_free(enum dbg_t type, u_int slot)
  462 {
  463         uint32_t cr, vr;
  464         uint32_t max;
  465 
  466         switch(type) {
  467         case DBG_TYPE_BREAKPOINT:
  468                 max = dbg_breakpoint_num;
  469                 cr = DBG_REG_BASE_BCR;
  470                 vr = DBG_REG_BASE_BVR;
  471                 break;
  472         case DBG_TYPE_WATCHPOINT:
  473                 max = dbg_watchpoint_num;
  474                 cr = DBG_REG_BASE_WCR;
  475                 vr = DBG_REG_BASE_WVR;
  476                 break;
  477         default:
  478                 db_printf("%s: Unsupported event type %d\n", __func__, type);
  479                 return (FALSE);
  480         }
  481 
  482         if (slot >= max) {
  483                 db_printf("%s: Invalid slot number %d, max %d\n",
  484                     __func__, slot, max - 1);
  485                 return (FALSE);
  486         }
  487 
  488         if ((dbg_wb_read_reg(cr, slot) & DBG_WB_CTRL_E) == 0 &&
  489             (dbg_wb_read_reg(vr, slot) & DBGWVR_ADDR_MASK) == 0)
  490                 return (TRUE);
  491 
  492         return (FALSE);
  493 }
  494 
  495 static u_int
  496 dbg_find_free_slot(enum dbg_t type)
  497 {
  498         u_int max, i;
  499 
  500         switch(type) {
  501         case DBG_TYPE_BREAKPOINT:
  502                 max = dbg_breakpoint_num;
  503                 break;
  504         case DBG_TYPE_WATCHPOINT:
  505                 max = dbg_watchpoint_num;
  506                 break;
  507         default:
  508                 db_printf("Unsupported debug type\n");
  509                 return (~0U);
  510         }
  511 
  512         for (i = 0; i < max; i++) {
  513                 if (dbg_check_slot_free(type, i))
  514                         return (i);
  515         }
  516 
  517         return (~0U);
  518 }
  519 
  520 static u_int
  521 dbg_find_slot(enum dbg_t type, db_expr_t addr)
  522 {
  523         uint32_t reg_addr, reg_ctrl;
  524         u_int max, i;
  525 
  526         switch(type) {
  527         case DBG_TYPE_BREAKPOINT:
  528                 max = dbg_breakpoint_num;
  529                 reg_addr = DBG_REG_BASE_BVR;
  530                 reg_ctrl = DBG_REG_BASE_BCR;
  531                 break;
  532         case DBG_TYPE_WATCHPOINT:
  533                 max = dbg_watchpoint_num;
  534                 reg_addr = DBG_REG_BASE_WVR;
  535                 reg_ctrl = DBG_REG_BASE_WCR;
  536                 break;
  537         default:
  538                 db_printf("Unsupported debug type\n");
  539                 return (~0U);
  540         }
  541 
  542         for (i = 0; i < max; i++) {
  543                 if ((dbg_wb_read_reg(reg_addr, i) == addr) &&
  544                     ((dbg_wb_read_reg(reg_ctrl, i) & DBG_WB_CTRL_E) != 0))
  545                         return (i);
  546         }
  547 
  548         return (~0U);
  549 }
  550 
  551 static __inline boolean_t
  552 dbg_monitor_is_enabled(void)
  553 {
  554 
  555         return ((cp14_dbgdscrint_get() & DBGSCR_MDBG_EN) != 0);
  556 }
  557 
  558 static int
  559 dbg_enable_monitor(void)
  560 {
  561         uint32_t dbg_dscr;
  562 
  563         /* Already enabled? Just return */
  564         if (dbg_monitor_is_enabled())
  565                 return (0);
  566 
  567         dbg_dscr = cp14_dbgdscrint_get();
  568 
  569         switch (dbg_model) {
  570         case ID_DFR0_CP_DEBUG_M_V6:
  571         case ID_DFR0_CP_DEBUG_M_V6_1: /* fall through */
  572                 cp14_dbgdscr_v6_set(dbg_dscr | DBGSCR_MDBG_EN);
  573                 break;
  574         case ID_DFR0_CP_DEBUG_M_V7: /* fall through */
  575         case ID_DFR0_CP_DEBUG_M_V7_1:
  576                 cp14_dbgdscr_v7_set(dbg_dscr | DBGSCR_MDBG_EN);
  577                 break;
  578         default:
  579                 break;
  580         }
  581         isb();
  582 
  583         /* Verify that Monitor mode is set */
  584         if (dbg_monitor_is_enabled())
  585                 return (0);
  586 
  587         return (ENXIO);
  588 }
  589 
  590 static int
  591 dbg_setup_xpoint(struct dbg_wb_conf *conf)
  592 {
  593         struct pcpu *pcpu;
  594         struct dbreg *d;
  595         const char *typestr;
  596         uint32_t cr_size, cr_priv, cr_access;
  597         uint32_t reg_ctrl, reg_addr, ctrl, addr;
  598         boolean_t is_bkpt;
  599         u_int cpu;
  600         u_int i;
  601 
  602         if (!dbg_capable())
  603                 return (ENXIO);
  604 
  605         is_bkpt = (conf->type == DBG_TYPE_BREAKPOINT);
  606         typestr = is_bkpt ? "breakpoint" : "watchpoint";
  607 
  608         if (is_bkpt) {
  609                 if (dbg_breakpoint_num == 0) {
  610                         db_printf("Breakpoints not supported on this architecture\n");
  611                         return (ENXIO);
  612                 }
  613                 i = conf->slot;
  614                 if (!dbg_check_slot_free(DBG_TYPE_BREAKPOINT, i)) {
  615                         /*
  616                          * This should never happen. If it does it means that
  617                          * there is an erroneus scenario somewhere. Still, it can
  618                          * be done but let's inform the user.
  619                          */
  620                         db_printf("ERROR: Breakpoint already set. Replacing...\n");
  621                 }
  622         } else {
  623                 i = dbg_find_free_slot(DBG_TYPE_WATCHPOINT);
  624                 if (i == ~0U) {
  625                         db_printf("Can not find slot for %s, max %d slots supported\n",
  626                             typestr, dbg_watchpoint_num);
  627                         return (ENXIO);
  628                 }
  629         }
  630 
  631         /* Kernel access only */
  632         cr_priv = DBG_WB_CTRL_PL1;
  633 
  634         switch(conf->size) {
  635         case 1:
  636                 cr_size = DBG_WB_CTRL_LEN_1;
  637                 break;
  638         case 2:
  639                 cr_size = DBG_WB_CTRL_LEN_2;
  640                 break;
  641         case 4:
  642                 cr_size = DBG_WB_CTRL_LEN_4;
  643                 break;
  644         case 8:
  645                 cr_size = DBG_WB_CTRL_LEN_8;
  646                 break;
  647         default:
  648                 db_printf("Unsupported address size for %s\n", typestr);
  649                 return (EINVAL);
  650         }
  651 
  652         if (is_bkpt) {
  653                 cr_access = DBG_WB_CTRL_EXEC;
  654                 reg_ctrl = DBG_REG_BASE_BCR;
  655                 reg_addr = DBG_REG_BASE_BVR;
  656                 /* Always unlinked BKPT */
  657                 ctrl = (cr_size | cr_access | cr_priv | DBG_WB_CTRL_E);
  658         } else {
  659                 switch(conf->access) {
  660                 case HW_WATCHPOINT_R:
  661                         cr_access = DBG_WB_CTRL_LOAD;
  662                         break;
  663                 case HW_WATCHPOINT_W:
  664                         cr_access = DBG_WB_CTRL_STORE;
  665                         break;
  666                 case HW_WATCHPOINT_RW:
  667                         cr_access = DBG_WB_CTRL_LOAD | DBG_WB_CTRL_STORE;
  668                         break;
  669                 default:
  670                         db_printf("Unsupported exception level for %s\n", typestr);
  671                         return (EINVAL);
  672                 }
  673 
  674                 reg_ctrl = DBG_REG_BASE_WCR;
  675                 reg_addr = DBG_REG_BASE_WVR;
  676                 ctrl = (cr_size | cr_access | cr_priv | DBG_WB_CTRL_E);
  677         }
  678 
  679         addr = conf->address;
  680 
  681         dbg_wb_write_reg(reg_addr, i, addr);
  682         dbg_wb_write_reg(reg_ctrl, i, ctrl);
  683 
  684         /*
  685          * Save watchpoint settings for all CPUs.
  686          * We don't need to do the same with breakpoints since HW breakpoints
  687          * are only used to perform single stepping.
  688          */
  689         if (!is_bkpt) {
  690                 CPU_FOREACH(cpu) {
  691                         pcpu = pcpu_find(cpu);
  692                         /* Fill out the settings for watchpoint */
  693                         d = (struct dbreg *)pcpu->pc_dbreg;
  694                         d->dbg_wvr[i] = addr;
  695                         d->dbg_wcr[i] = ctrl;
  696                         /* Skip update command for the current CPU */
  697                         if (cpu != PCPU_GET(cpuid))
  698                                 pcpu->pc_dbreg_cmd = PC_DBREG_CMD_LOAD;
  699                 }
  700         }
  701         /* Ensure all data is written before waking other CPUs */
  702         atomic_thread_fence_rel();
  703 
  704         return (0);
  705 }
  706 
  707 static int
  708 dbg_remove_xpoint(struct dbg_wb_conf *conf)
  709 {
  710         struct pcpu *pcpu;
  711         struct dbreg *d;
  712         uint32_t reg_ctrl, reg_addr, addr;
  713         boolean_t is_bkpt;
  714         u_int cpu;
  715         u_int i;
  716 
  717         if (!dbg_capable())
  718                 return (ENXIO);
  719 
  720         is_bkpt = (conf->type == DBG_TYPE_BREAKPOINT);
  721         addr = conf->address;
  722 
  723         if (is_bkpt) {
  724                 i = conf->slot;
  725                 reg_ctrl = DBG_REG_BASE_BCR;
  726                 reg_addr = DBG_REG_BASE_BVR;
  727         } else {
  728                 i = dbg_find_slot(DBG_TYPE_WATCHPOINT, addr);
  729                 if (i == ~0U) {
  730                         db_printf("Can not find watchpoint for address 0%x\n", addr);
  731                         return (EINVAL);
  732                 }
  733                 reg_ctrl = DBG_REG_BASE_WCR;
  734                 reg_addr = DBG_REG_BASE_WVR;
  735         }
  736 
  737         dbg_wb_write_reg(reg_ctrl, i, 0);
  738         dbg_wb_write_reg(reg_addr, i, 0);
  739 
  740         /*
  741          * Save watchpoint settings for all CPUs.
  742          * We don't need to do the same with breakpoints since HW breakpoints
  743          * are only used to perform single stepping.
  744          */
  745         if (!is_bkpt) {
  746                 CPU_FOREACH(cpu) {
  747                         pcpu = pcpu_find(cpu);
  748                         /* Fill out the settings for watchpoint */
  749                         d = (struct dbreg *)pcpu->pc_dbreg;
  750                         d->dbg_wvr[i] = 0;
  751                         d->dbg_wcr[i] = 0;
  752                         /* Skip update command for the current CPU */
  753                         if (cpu != PCPU_GET(cpuid))
  754                                 pcpu->pc_dbreg_cmd = PC_DBREG_CMD_LOAD;
  755                 }
  756                 /* Ensure all data is written before waking other CPUs */
  757                 atomic_thread_fence_rel();
  758         }
  759 
  760         return (0);
  761 }
  762 
  763 static __inline uint32_t
  764 dbg_get_debug_model(void)
  765 {
  766         uint32_t dbg_m;
  767 
  768         dbg_m = ((cpuinfo.id_dfr0 & ID_DFR0_CP_DEBUG_M_MASK) >>
  769             ID_DFR0_CP_DEBUG_M_SHIFT);
  770 
  771         return (dbg_m);
  772 }
  773 
  774 static __inline boolean_t
  775 dbg_get_ossr(void)
  776 {
  777 
  778         switch (dbg_model) {
  779         case ID_DFR0_CP_DEBUG_M_V7:
  780                 if ((cp14_dbgoslsr_get() & DBGOSLSR_OSLM0) != 0)
  781                         return (TRUE);
  782 
  783                 return (FALSE);
  784         case ID_DFR0_CP_DEBUG_M_V7_1:
  785                 return (TRUE);
  786         default:
  787                 return (FALSE);
  788         }
  789 }
  790 
  791 static __inline boolean_t
  792 dbg_arch_supported(void)
  793 {
  794         uint32_t dbg_didr;
  795 
  796         switch (dbg_model) {
  797         case ID_DFR0_CP_DEBUG_M_V6:
  798         case ID_DFR0_CP_DEBUG_M_V6_1:
  799                 dbg_didr = cp14_dbgdidr_get();
  800                 /*
  801                  * read-all-zeroes is used by QEMU
  802                  * to indicate that ARMv6 debug support
  803                  * is not implemented. Real hardware has at
  804                  * least version bits set
  805                  */
  806                 if (dbg_didr == 0)
  807                         return (FALSE);
  808                 return (TRUE);
  809         case ID_DFR0_CP_DEBUG_M_V7:
  810         case ID_DFR0_CP_DEBUG_M_V7_1:   /* fall through */
  811                 return (TRUE);
  812         default:
  813                 /* We only support valid v6.x/v7.x modes through CP14 */
  814                 return (FALSE);
  815         }
  816 }
  817 
  818 static __inline uint32_t
  819 dbg_get_wrp_num(void)
  820 {
  821         uint32_t dbg_didr;
  822 
  823         dbg_didr = cp14_dbgdidr_get();
  824 
  825         return (DBGDIDR_WRPS_NUM(dbg_didr));
  826 }
  827 
  828 static __inline uint32_t
  829 dgb_get_brp_num(void)
  830 {
  831         uint32_t dbg_didr;
  832 
  833         dbg_didr = cp14_dbgdidr_get();
  834 
  835         return (DBGDIDR_BRPS_NUM(dbg_didr));
  836 }
  837 
  838 static int
  839 dbg_reset_state(void)
  840 {
  841         u_int cpuid;
  842         size_t i;
  843         int err;
  844 
  845         cpuid = PCPU_GET(cpuid);
  846         err = 0;
  847 
  848         switch (dbg_model) {
  849         case ID_DFR0_CP_DEBUG_M_V6:
  850         case ID_DFR0_CP_DEBUG_M_V6_1: /* fall through */
  851                 /*
  852                  * Arch needs monitor mode selected and enabled
  853                  * to be able to access breakpoint/watchpoint registers.
  854                  */
  855                 err = dbg_enable_monitor();
  856                 if (err != 0)
  857                         return (err);
  858                 goto vectr_clr;
  859         case ID_DFR0_CP_DEBUG_M_V7:
  860                 /* Is core power domain powered up? */
  861                 if ((cp14_dbgprsr_get() & DBGPRSR_PU) == 0)
  862                         err = ENXIO;
  863 
  864                 if (err != 0)
  865                         break;
  866 
  867                 if (dbg_ossr)
  868                         goto vectr_clr;
  869                 break;
  870         case ID_DFR0_CP_DEBUG_M_V7_1:
  871                 /* Is double lock set? */
  872                 if ((cp14_dbgosdlr_get() & DBGPRSR_DLK) != 0)
  873                         err = ENXIO;
  874 
  875                 break;
  876         default:
  877                 break;
  878         }
  879 
  880         if (err != 0) {
  881                 db_printf("Debug facility locked (CPU%d)\n", cpuid);
  882                 return (err);
  883         }
  884 
  885         /*
  886          * DBGOSLAR is always implemented for v7.1 Debug Arch. however is
  887          * optional for v7 (depends on OS save and restore support).
  888          */
  889         if (((dbg_model & ID_DFR0_CP_DEBUG_M_V7_1) != 0) || dbg_ossr) {
  890                 /*
  891                  * Clear OS lock.
  892                  * Writing any other value than 0xC5ACCESS will unlock.
  893                  */
  894                 cp14_dbgoslar_set(0);
  895                 isb();
  896         }
  897 
  898 vectr_clr:
  899         /*
  900          * After reset we must ensure that DBGVCR has a defined value.
  901          * Disable all vector catch events. Safe to use - required in all
  902          * implementations.
  903          */
  904         cp14_dbgvcr_set(0);
  905         isb();
  906 
  907         /*
  908          * We have limited number of {watch,break}points, each consists of
  909          * two registers:
  910          * - wcr/bcr regsiter configurates corresponding {watch,break}point
  911          *   behaviour
  912          * - wvr/bvr register keeps address we are hunting for
  913          *
  914          * Reset all breakpoints and watchpoints.
  915          */
  916         for (i = 0; i < dbg_watchpoint_num; ++i) {
  917                 dbg_wb_write_reg(DBG_REG_BASE_WCR, i, 0);
  918                 dbg_wb_write_reg(DBG_REG_BASE_WVR, i, 0);
  919         }
  920 
  921         for (i = 0; i < dbg_breakpoint_num; ++i) {
  922                 dbg_wb_write_reg(DBG_REG_BASE_BCR, i, 0);
  923                 dbg_wb_write_reg(DBG_REG_BASE_BVR, i, 0);
  924         }
  925 
  926         return (0);
  927 }
  928 
  929 void
  930 dbg_monitor_init(void)
  931 {
  932         int err;
  933 
  934         /* Fetch ARM Debug Architecture model */
  935         dbg_model = dbg_get_debug_model();
  936 
  937         if (!dbg_arch_supported()) {
  938                 db_printf("ARM Debug Architecture not supported\n");
  939                 return;
  940         }
  941 
  942         if (bootverbose) {
  943                 db_printf("ARM Debug Architecture %s\n",
  944                     (dbg_model == ID_DFR0_CP_DEBUG_M_V6) ? "v6" :
  945                     (dbg_model == ID_DFR0_CP_DEBUG_M_V6_1) ? "v6.1" :
  946                     (dbg_model == ID_DFR0_CP_DEBUG_M_V7) ? "v7" :
  947                     (dbg_model == ID_DFR0_CP_DEBUG_M_V7_1) ? "v7.1" : "unknown");
  948         }
  949 
  950         /* Do we have OS Save and Restore mechanism? */
  951         dbg_ossr = dbg_get_ossr();
  952 
  953         /* Find out many breakpoints and watchpoints we can use */
  954         dbg_watchpoint_num = dbg_get_wrp_num();
  955         dbg_breakpoint_num = dgb_get_brp_num();
  956 
  957         if (bootverbose) {
  958                 db_printf("%d watchpoints and %d breakpoints supported\n",
  959                     dbg_watchpoint_num, dbg_breakpoint_num);
  960         }
  961 
  962         err = dbg_reset_state();
  963         if (err == 0) {
  964                 err = dbg_enable_monitor();
  965                 if (err == 0) {
  966                         atomic_set_int(&dbg_capable_var, 1);
  967                         return;
  968                 }
  969         }
  970 
  971         db_printf("HW Breakpoints/Watchpoints not enabled on CPU%d\n",
  972             PCPU_GET(cpuid));
  973 }
  974 
  975 CTASSERT(sizeof(struct dbreg) == sizeof(((struct pcpu *)NULL)->pc_dbreg));
  976 
  977 void
  978 dbg_monitor_init_secondary(void)
  979 {
  980         u_int cpuid;
  981         int err;
  982         /*
  983          * This flag is set on the primary CPU
  984          * and its meaning is valid for other CPUs too.
  985          */
  986         if (!dbg_capable())
  987                 return;
  988 
  989         cpuid = PCPU_GET(cpuid);
  990 
  991         err = dbg_reset_state();
  992         if (err != 0) {
  993                 /*
  994                  * Something is very wrong.
  995                  * WPs/BPs will not work correctly on this CPU.
  996                  */
  997                 KASSERT(0, ("%s: Failed to reset Debug Architecture "
  998                     "state on CPU%d", __func__, cpuid));
  999                 /* Disable HW debug capabilities for all CPUs */
 1000                 atomic_set_int(&dbg_capable_var, 0);
 1001                 return;
 1002         }
 1003         err = dbg_enable_monitor();
 1004         if (err != 0) {
 1005                 KASSERT(0, ("%s: Failed to enable Debug Monitor"
 1006                     " on CPU%d", __func__, cpuid));
 1007                 atomic_set_int(&dbg_capable_var, 0);
 1008         }
 1009 }
 1010 
 1011 void
 1012 dbg_resume_dbreg(void)
 1013 {
 1014         struct dbreg *d;
 1015         u_int i;
 1016 
 1017         /*
 1018          * This flag is set on the primary CPU
 1019          * and its meaning is valid for other CPUs too.
 1020          */
 1021         if (!dbg_capable())
 1022                 return;
 1023 
 1024         atomic_thread_fence_acq();
 1025 
 1026         switch (PCPU_GET(dbreg_cmd)) {
 1027         case PC_DBREG_CMD_LOAD:
 1028                 d = (struct dbreg *)PCPU_PTR(dbreg);
 1029 
 1030                 /* Restore watchpoints */
 1031                 for (i = 0; i < dbg_watchpoint_num; i++) {
 1032                         dbg_wb_write_reg(DBG_REG_BASE_WVR, i, d->dbg_wvr[i]);
 1033                         dbg_wb_write_reg(DBG_REG_BASE_WCR, i, d->dbg_wcr[i]);
 1034                 }
 1035 
 1036                 PCPU_SET(dbreg_cmd, PC_DBREG_CMD_NONE);
 1037                 break;
 1038         }
 1039 }

Cache object: 07fac56d6cc25317a721eafa91f0c017


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