15d5314d6SJason Wessel /*
25d5314d6SJason Wessel * Kernel Debugger Architecture Independent Breakpoint Handler
35d5314d6SJason Wessel *
45d5314d6SJason Wessel * This file is subject to the terms and conditions of the GNU General Public
55d5314d6SJason Wessel * License. See the file "COPYING" in the main directory of this archive
65d5314d6SJason Wessel * for more details.
75d5314d6SJason Wessel *
85d5314d6SJason Wessel * Copyright (c) 1999-2004 Silicon Graphics, Inc. All Rights Reserved.
95d5314d6SJason Wessel * Copyright (c) 2009 Wind River Systems, Inc. All Rights Reserved.
105d5314d6SJason Wessel */
115d5314d6SJason Wessel
125d5314d6SJason Wessel #include <linux/string.h>
135d5314d6SJason Wessel #include <linux/kernel.h>
145d5314d6SJason Wessel #include <linux/init.h>
155d5314d6SJason Wessel #include <linux/kdb.h>
165d5314d6SJason Wessel #include <linux/kgdb.h>
175d5314d6SJason Wessel #include <linux/smp.h>
185d5314d6SJason Wessel #include <linux/sched.h>
195d5314d6SJason Wessel #include <linux/interrupt.h>
205d5314d6SJason Wessel #include "kdb_private.h"
215d5314d6SJason Wessel
225d5314d6SJason Wessel /*
235d5314d6SJason Wessel * Table of kdb_breakpoints
245d5314d6SJason Wessel */
255d5314d6SJason Wessel kdb_bp_t kdb_breakpoints[KDB_MAXBPT];
265d5314d6SJason Wessel
kdb_setsinglestep(struct pt_regs * regs)275d5314d6SJason Wessel static void kdb_setsinglestep(struct pt_regs *regs)
285d5314d6SJason Wessel {
295d5314d6SJason Wessel KDB_STATE_SET(DOING_SS);
305d5314d6SJason Wessel }
315d5314d6SJason Wessel
325d5314d6SJason Wessel static char *kdb_rwtypes[] = {
335d5314d6SJason Wessel "Instruction(i)",
345d5314d6SJason Wessel "Instruction(Register)",
355d5314d6SJason Wessel "Data Write",
365d5314d6SJason Wessel "I/O",
375d5314d6SJason Wessel "Data Access"
385d5314d6SJason Wessel };
395d5314d6SJason Wessel
kdb_bptype(kdb_bp_t * bp)405d5314d6SJason Wessel static char *kdb_bptype(kdb_bp_t *bp)
415d5314d6SJason Wessel {
425d5314d6SJason Wessel if (bp->bp_type < 0 || bp->bp_type > 4)
435d5314d6SJason Wessel return "";
445d5314d6SJason Wessel
455d5314d6SJason Wessel return kdb_rwtypes[bp->bp_type];
465d5314d6SJason Wessel }
475d5314d6SJason Wessel
kdb_parsebp(int argc,const char ** argv,int * nextargp,kdb_bp_t * bp)485d5314d6SJason Wessel static int kdb_parsebp(int argc, const char **argv, int *nextargp, kdb_bp_t *bp)
495d5314d6SJason Wessel {
505d5314d6SJason Wessel int nextarg = *nextargp;
515d5314d6SJason Wessel int diag;
525d5314d6SJason Wessel
535d5314d6SJason Wessel bp->bph_length = 1;
545d5314d6SJason Wessel if ((argc + 1) != nextarg) {
55f9f2bac2SRasmus Villemoes if (strncasecmp(argv[nextarg], "datar", sizeof("datar")) == 0)
565d5314d6SJason Wessel bp->bp_type = BP_ACCESS_WATCHPOINT;
57f9f2bac2SRasmus Villemoes else if (strncasecmp(argv[nextarg], "dataw", sizeof("dataw")) == 0)
585d5314d6SJason Wessel bp->bp_type = BP_WRITE_WATCHPOINT;
59f9f2bac2SRasmus Villemoes else if (strncasecmp(argv[nextarg], "inst", sizeof("inst")) == 0)
605d5314d6SJason Wessel bp->bp_type = BP_HARDWARE_BREAKPOINT;
615d5314d6SJason Wessel else
625d5314d6SJason Wessel return KDB_ARGCOUNT;
635d5314d6SJason Wessel
645d5314d6SJason Wessel bp->bph_length = 1;
655d5314d6SJason Wessel
665d5314d6SJason Wessel nextarg++;
675d5314d6SJason Wessel
685d5314d6SJason Wessel if ((argc + 1) != nextarg) {
695d5314d6SJason Wessel unsigned long len;
705d5314d6SJason Wessel
715d5314d6SJason Wessel diag = kdbgetularg((char *)argv[nextarg],
725d5314d6SJason Wessel &len);
735d5314d6SJason Wessel if (diag)
745d5314d6SJason Wessel return diag;
755d5314d6SJason Wessel
765d5314d6SJason Wessel
775d5314d6SJason Wessel if (len > 8)
785d5314d6SJason Wessel return KDB_BADLENGTH;
795d5314d6SJason Wessel
805d5314d6SJason Wessel bp->bph_length = len;
815d5314d6SJason Wessel nextarg++;
825d5314d6SJason Wessel }
835d5314d6SJason Wessel
845d5314d6SJason Wessel if ((argc + 1) != nextarg)
855d5314d6SJason Wessel return KDB_ARGCOUNT;
865d5314d6SJason Wessel }
875d5314d6SJason Wessel
885d5314d6SJason Wessel *nextargp = nextarg;
895d5314d6SJason Wessel return 0;
905d5314d6SJason Wessel }
915d5314d6SJason Wessel
_kdb_bp_remove(kdb_bp_t * bp)925d5314d6SJason Wessel static int _kdb_bp_remove(kdb_bp_t *bp)
935d5314d6SJason Wessel {
945d5314d6SJason Wessel int ret = 1;
955d5314d6SJason Wessel if (!bp->bp_installed)
965d5314d6SJason Wessel return ret;
975d5314d6SJason Wessel if (!bp->bp_type)
985d5314d6SJason Wessel ret = dbg_remove_sw_break(bp->bp_addr);
995d5314d6SJason Wessel else
1005d5314d6SJason Wessel ret = arch_kgdb_ops.remove_hw_breakpoint(bp->bp_addr,
1015d5314d6SJason Wessel bp->bph_length,
1025d5314d6SJason Wessel bp->bp_type);
1035d5314d6SJason Wessel if (ret == 0)
1045d5314d6SJason Wessel bp->bp_installed = 0;
1055d5314d6SJason Wessel return ret;
1065d5314d6SJason Wessel }
1075d5314d6SJason Wessel
kdb_handle_bp(struct pt_regs * regs,kdb_bp_t * bp)1085d5314d6SJason Wessel static void kdb_handle_bp(struct pt_regs *regs, kdb_bp_t *bp)
1095d5314d6SJason Wessel {
1105d5314d6SJason Wessel if (KDB_DEBUG(BP))
1115d5314d6SJason Wessel kdb_printf("regs->ip = 0x%lx\n", instruction_pointer(regs));
1125d5314d6SJason Wessel
1135d5314d6SJason Wessel /*
1145d5314d6SJason Wessel * Setup single step
1155d5314d6SJason Wessel */
1165d5314d6SJason Wessel kdb_setsinglestep(regs);
1175d5314d6SJason Wessel
1185d5314d6SJason Wessel /*
1195d5314d6SJason Wessel * Reset delay attribute
1205d5314d6SJason Wessel */
1215d5314d6SJason Wessel bp->bp_delay = 0;
1225d5314d6SJason Wessel bp->bp_delayed = 1;
1235d5314d6SJason Wessel }
1245d5314d6SJason Wessel
_kdb_bp_install(struct pt_regs * regs,kdb_bp_t * bp)1255d5314d6SJason Wessel static int _kdb_bp_install(struct pt_regs *regs, kdb_bp_t *bp)
1265d5314d6SJason Wessel {
1275d5314d6SJason Wessel int ret;
1285d5314d6SJason Wessel /*
1295d5314d6SJason Wessel * Install the breakpoint, if it is not already installed.
1305d5314d6SJason Wessel */
1315d5314d6SJason Wessel
1325d5314d6SJason Wessel if (KDB_DEBUG(BP))
1335d5314d6SJason Wessel kdb_printf("%s: bp_installed %d\n",
1345d5314d6SJason Wessel __func__, bp->bp_installed);
1355d5314d6SJason Wessel if (!KDB_STATE(SSBPT))
1365d5314d6SJason Wessel bp->bp_delay = 0;
1375d5314d6SJason Wessel if (bp->bp_installed)
1385d5314d6SJason Wessel return 1;
1395d5314d6SJason Wessel if (bp->bp_delay || (bp->bp_delayed && KDB_STATE(DOING_SS))) {
1405d5314d6SJason Wessel if (KDB_DEBUG(BP))
1415d5314d6SJason Wessel kdb_printf("%s: delayed bp\n", __func__);
1425d5314d6SJason Wessel kdb_handle_bp(regs, bp);
1435d5314d6SJason Wessel return 0;
1445d5314d6SJason Wessel }
1455d5314d6SJason Wessel if (!bp->bp_type)
1465d5314d6SJason Wessel ret = dbg_set_sw_break(bp->bp_addr);
1475d5314d6SJason Wessel else
1485d5314d6SJason Wessel ret = arch_kgdb_ops.set_hw_breakpoint(bp->bp_addr,
1495d5314d6SJason Wessel bp->bph_length,
1505d5314d6SJason Wessel bp->bp_type);
1515d5314d6SJason Wessel if (ret == 0) {
1525d5314d6SJason Wessel bp->bp_installed = 1;
1535d5314d6SJason Wessel } else {
1545d5314d6SJason Wessel kdb_printf("%s: failed to set breakpoint at 0x%lx\n",
1555d5314d6SJason Wessel __func__, bp->bp_addr);
1561ba0c172SJason Wessel if (!bp->bp_type) {
1571ba0c172SJason Wessel kdb_printf("Software breakpoints are unavailable.\n"
158d2aa1acaSKees Cook " Boot the kernel with rodata=off\n"
1591ba0c172SJason Wessel " OR use hw breaks: help bph\n");
1601ba0c172SJason Wessel }
1615d5314d6SJason Wessel return 1;
1625d5314d6SJason Wessel }
1635d5314d6SJason Wessel return 0;
1645d5314d6SJason Wessel }
1655d5314d6SJason Wessel
1665d5314d6SJason Wessel /*
1675d5314d6SJason Wessel * kdb_bp_install
1685d5314d6SJason Wessel *
1695d5314d6SJason Wessel * Install kdb_breakpoints prior to returning from the
1705d5314d6SJason Wessel * kernel debugger. This allows the kdb_breakpoints to be set
1715d5314d6SJason Wessel * upon functions that are used internally by kdb, such as
1725d5314d6SJason Wessel * printk(). This function is only called once per kdb session.
1735d5314d6SJason Wessel */
kdb_bp_install(struct pt_regs * regs)1745d5314d6SJason Wessel void kdb_bp_install(struct pt_regs *regs)
1755d5314d6SJason Wessel {
1765d5314d6SJason Wessel int i;
1775d5314d6SJason Wessel
1785d5314d6SJason Wessel for (i = 0; i < KDB_MAXBPT; i++) {
1795d5314d6SJason Wessel kdb_bp_t *bp = &kdb_breakpoints[i];
1805d5314d6SJason Wessel
1815d5314d6SJason Wessel if (KDB_DEBUG(BP)) {
1825d5314d6SJason Wessel kdb_printf("%s: bp %d bp_enabled %d\n",
1835d5314d6SJason Wessel __func__, i, bp->bp_enabled);
1845d5314d6SJason Wessel }
1855d5314d6SJason Wessel if (bp->bp_enabled)
1865d5314d6SJason Wessel _kdb_bp_install(regs, bp);
1875d5314d6SJason Wessel }
1885d5314d6SJason Wessel }
1895d5314d6SJason Wessel
1905d5314d6SJason Wessel /*
1915d5314d6SJason Wessel * kdb_bp_remove
1925d5314d6SJason Wessel *
1935d5314d6SJason Wessel * Remove kdb_breakpoints upon entry to the kernel debugger.
1945d5314d6SJason Wessel *
1955d5314d6SJason Wessel * Parameters:
1965d5314d6SJason Wessel * None.
1975d5314d6SJason Wessel * Outputs:
1985d5314d6SJason Wessel * None.
1995d5314d6SJason Wessel * Returns:
2005d5314d6SJason Wessel * None.
2015d5314d6SJason Wessel * Locking:
2025d5314d6SJason Wessel * None.
2035d5314d6SJason Wessel * Remarks:
2045d5314d6SJason Wessel */
kdb_bp_remove(void)2055d5314d6SJason Wessel void kdb_bp_remove(void)
2065d5314d6SJason Wessel {
2075d5314d6SJason Wessel int i;
2085d5314d6SJason Wessel
2095d5314d6SJason Wessel for (i = KDB_MAXBPT - 1; i >= 0; i--) {
2105d5314d6SJason Wessel kdb_bp_t *bp = &kdb_breakpoints[i];
2115d5314d6SJason Wessel
2125d5314d6SJason Wessel if (KDB_DEBUG(BP)) {
2135d5314d6SJason Wessel kdb_printf("%s: bp %d bp_enabled %d\n",
2145d5314d6SJason Wessel __func__, i, bp->bp_enabled);
2155d5314d6SJason Wessel }
2165d5314d6SJason Wessel if (bp->bp_enabled)
2175d5314d6SJason Wessel _kdb_bp_remove(bp);
2185d5314d6SJason Wessel }
2195d5314d6SJason Wessel }
2205d5314d6SJason Wessel
2215d5314d6SJason Wessel
2225d5314d6SJason Wessel /*
2235d5314d6SJason Wessel * kdb_printbp
2245d5314d6SJason Wessel *
2255d5314d6SJason Wessel * Internal function to format and print a breakpoint entry.
2265d5314d6SJason Wessel *
2275d5314d6SJason Wessel * Parameters:
2285d5314d6SJason Wessel * None.
2295d5314d6SJason Wessel * Outputs:
2305d5314d6SJason Wessel * None.
2315d5314d6SJason Wessel * Returns:
2325d5314d6SJason Wessel * None.
2335d5314d6SJason Wessel * Locking:
2345d5314d6SJason Wessel * None.
2355d5314d6SJason Wessel * Remarks:
2365d5314d6SJason Wessel */
2375d5314d6SJason Wessel
kdb_printbp(kdb_bp_t * bp,int i)2385d5314d6SJason Wessel static void kdb_printbp(kdb_bp_t *bp, int i)
2395d5314d6SJason Wessel {
2405d5314d6SJason Wessel kdb_printf("%s ", kdb_bptype(bp));
2415d5314d6SJason Wessel kdb_printf("BP #%d at ", i);
2425d5314d6SJason Wessel kdb_symbol_print(bp->bp_addr, NULL, KDB_SP_DEFAULT);
2435d5314d6SJason Wessel
2445d5314d6SJason Wessel if (bp->bp_enabled)
2455d5314d6SJason Wessel kdb_printf("\n is enabled ");
2465d5314d6SJason Wessel else
2475d5314d6SJason Wessel kdb_printf("\n is disabled");
2485d5314d6SJason Wessel
24933f765f6SRandy Dunlap kdb_printf(" addr at %016lx, hardtype=%d installed=%d\n",
2505d5314d6SJason Wessel bp->bp_addr, bp->bp_type, bp->bp_installed);
2515d5314d6SJason Wessel
2525d5314d6SJason Wessel kdb_printf("\n");
2535d5314d6SJason Wessel }
2545d5314d6SJason Wessel
2555d5314d6SJason Wessel /*
2565d5314d6SJason Wessel * kdb_bp
2575d5314d6SJason Wessel *
2585d5314d6SJason Wessel * Handle the bp commands.
2595d5314d6SJason Wessel *
2605d5314d6SJason Wessel * [bp|bph] <addr-expression> [DATAR|DATAW]
2615d5314d6SJason Wessel *
2625d5314d6SJason Wessel * Parameters:
2635d5314d6SJason Wessel * argc Count of arguments in argv
2645d5314d6SJason Wessel * argv Space delimited command line arguments
2655d5314d6SJason Wessel * Outputs:
2665d5314d6SJason Wessel * None.
2675d5314d6SJason Wessel * Returns:
2685d5314d6SJason Wessel * Zero for success, a kdb diagnostic if failure.
2695d5314d6SJason Wessel * Locking:
2705d5314d6SJason Wessel * None.
2715d5314d6SJason Wessel * Remarks:
2725d5314d6SJason Wessel *
2735d5314d6SJason Wessel * bp Set breakpoint on all cpus. Only use hardware assist if need.
2745d5314d6SJason Wessel * bph Set breakpoint on all cpus. Force hardware register
2755d5314d6SJason Wessel */
2765d5314d6SJason Wessel
kdb_bp(int argc,const char ** argv)2775d5314d6SJason Wessel static int kdb_bp(int argc, const char **argv)
2785d5314d6SJason Wessel {
2795d5314d6SJason Wessel int i, bpno;
2805d5314d6SJason Wessel kdb_bp_t *bp, *bp_check;
2815d5314d6SJason Wessel int diag;
2825d5314d6SJason Wessel char *symname = NULL;
2835d5314d6SJason Wessel long offset = 0ul;
2845d5314d6SJason Wessel int nextarg;
2855d5314d6SJason Wessel kdb_bp_t template = {0};
2865d5314d6SJason Wessel
2875d5314d6SJason Wessel if (argc == 0) {
2885d5314d6SJason Wessel /*
2895d5314d6SJason Wessel * Display breakpoint table
2905d5314d6SJason Wessel */
2915d5314d6SJason Wessel for (bpno = 0, bp = kdb_breakpoints; bpno < KDB_MAXBPT;
2925d5314d6SJason Wessel bpno++, bp++) {
2935d5314d6SJason Wessel if (bp->bp_free)
2945d5314d6SJason Wessel continue;
2955d5314d6SJason Wessel kdb_printbp(bp, bpno);
2965d5314d6SJason Wessel }
2975d5314d6SJason Wessel
2985d5314d6SJason Wessel return 0;
2995d5314d6SJason Wessel }
3005d5314d6SJason Wessel
3015d5314d6SJason Wessel nextarg = 1;
3025d5314d6SJason Wessel diag = kdbgetaddrarg(argc, argv, &nextarg, &template.bp_addr,
3035d5314d6SJason Wessel &offset, &symname);
3045d5314d6SJason Wessel if (diag)
3055d5314d6SJason Wessel return diag;
3065d5314d6SJason Wessel if (!template.bp_addr)
3075d5314d6SJason Wessel return KDB_BADINT;
3085d5314d6SJason Wessel
3095d5314d6SJason Wessel /*
310f2d10ff4SDaniel Thompson * This check is redundant (since the breakpoint machinery should
311f2d10ff4SDaniel Thompson * be doing the same check during kdb_bp_install) but gives the
312f2d10ff4SDaniel Thompson * user immediate feedback.
313f2d10ff4SDaniel Thompson */
314f2d10ff4SDaniel Thompson diag = kgdb_validate_break_address(template.bp_addr);
315f2d10ff4SDaniel Thompson if (diag)
316f2d10ff4SDaniel Thompson return diag;
317f2d10ff4SDaniel Thompson
318f2d10ff4SDaniel Thompson /*
3195d5314d6SJason Wessel * Find an empty bp structure to allocate
3205d5314d6SJason Wessel */
3215d5314d6SJason Wessel for (bpno = 0, bp = kdb_breakpoints; bpno < KDB_MAXBPT; bpno++, bp++) {
3225d5314d6SJason Wessel if (bp->bp_free)
3235d5314d6SJason Wessel break;
3245d5314d6SJason Wessel }
3255d5314d6SJason Wessel
3265d5314d6SJason Wessel if (bpno == KDB_MAXBPT)
3275d5314d6SJason Wessel return KDB_TOOMANYBPT;
3285d5314d6SJason Wessel
3295d5314d6SJason Wessel if (strcmp(argv[0], "bph") == 0) {
3305d5314d6SJason Wessel template.bp_type = BP_HARDWARE_BREAKPOINT;
3315d5314d6SJason Wessel diag = kdb_parsebp(argc, argv, &nextarg, &template);
3325d5314d6SJason Wessel if (diag)
3335d5314d6SJason Wessel return diag;
3345d5314d6SJason Wessel } else {
3355d5314d6SJason Wessel template.bp_type = BP_BREAKPOINT;
3365d5314d6SJason Wessel }
3375d5314d6SJason Wessel
3385d5314d6SJason Wessel /*
3395d5314d6SJason Wessel * Check for clashing breakpoints.
3405d5314d6SJason Wessel *
3415d5314d6SJason Wessel * Note, in this design we can't have hardware breakpoints
3425d5314d6SJason Wessel * enabled for both read and write on the same address.
3435d5314d6SJason Wessel */
3445d5314d6SJason Wessel for (i = 0, bp_check = kdb_breakpoints; i < KDB_MAXBPT;
3455d5314d6SJason Wessel i++, bp_check++) {
3465d5314d6SJason Wessel if (!bp_check->bp_free &&
3475d5314d6SJason Wessel bp_check->bp_addr == template.bp_addr) {
3485d5314d6SJason Wessel kdb_printf("You already have a breakpoint at "
3495d5314d6SJason Wessel kdb_bfd_vma_fmt0 "\n", template.bp_addr);
3505d5314d6SJason Wessel return KDB_DUPBPT;
3515d5314d6SJason Wessel }
3525d5314d6SJason Wessel }
3535d5314d6SJason Wessel
3545d5314d6SJason Wessel template.bp_enabled = 1;
3555d5314d6SJason Wessel
3565d5314d6SJason Wessel /*
3575d5314d6SJason Wessel * Actually allocate the breakpoint found earlier
3585d5314d6SJason Wessel */
3595d5314d6SJason Wessel *bp = template;
3605d5314d6SJason Wessel bp->bp_free = 0;
3615d5314d6SJason Wessel
3625d5314d6SJason Wessel kdb_printbp(bp, bpno);
3635d5314d6SJason Wessel
3645d5314d6SJason Wessel return 0;
3655d5314d6SJason Wessel }
3665d5314d6SJason Wessel
3675d5314d6SJason Wessel /*
3685d5314d6SJason Wessel * kdb_bc
3695d5314d6SJason Wessel *
3705d5314d6SJason Wessel * Handles the 'bc', 'be', and 'bd' commands
3715d5314d6SJason Wessel *
3725d5314d6SJason Wessel * [bd|bc|be] <breakpoint-number>
3735d5314d6SJason Wessel * [bd|bc|be] *
3745d5314d6SJason Wessel *
3755d5314d6SJason Wessel * Parameters:
3765d5314d6SJason Wessel * argc Count of arguments in argv
3775d5314d6SJason Wessel * argv Space delimited command line arguments
3785d5314d6SJason Wessel * Outputs:
3795d5314d6SJason Wessel * None.
3805d5314d6SJason Wessel * Returns:
3815d5314d6SJason Wessel * Zero for success, a kdb diagnostic for failure
3825d5314d6SJason Wessel * Locking:
3835d5314d6SJason Wessel * None.
3845d5314d6SJason Wessel * Remarks:
3855d5314d6SJason Wessel */
kdb_bc(int argc,const char ** argv)3865d5314d6SJason Wessel static int kdb_bc(int argc, const char **argv)
3875d5314d6SJason Wessel {
3885d5314d6SJason Wessel unsigned long addr;
3895d5314d6SJason Wessel kdb_bp_t *bp = NULL;
3905d5314d6SJason Wessel int lowbp = KDB_MAXBPT;
3915d5314d6SJason Wessel int highbp = 0;
3925d5314d6SJason Wessel int done = 0;
3935d5314d6SJason Wessel int i;
3945d5314d6SJason Wessel int diag = 0;
3955d5314d6SJason Wessel
3965d5314d6SJason Wessel int cmd; /* KDBCMD_B? */
3975d5314d6SJason Wessel #define KDBCMD_BC 0
3985d5314d6SJason Wessel #define KDBCMD_BE 1
3995d5314d6SJason Wessel #define KDBCMD_BD 2
4005d5314d6SJason Wessel
4015d5314d6SJason Wessel if (strcmp(argv[0], "be") == 0)
4025d5314d6SJason Wessel cmd = KDBCMD_BE;
4035d5314d6SJason Wessel else if (strcmp(argv[0], "bd") == 0)
4045d5314d6SJason Wessel cmd = KDBCMD_BD;
4055d5314d6SJason Wessel else
4065d5314d6SJason Wessel cmd = KDBCMD_BC;
4075d5314d6SJason Wessel
4085d5314d6SJason Wessel if (argc != 1)
4095d5314d6SJason Wessel return KDB_ARGCOUNT;
4105d5314d6SJason Wessel
4115d5314d6SJason Wessel if (strcmp(argv[1], "*") == 0) {
4125d5314d6SJason Wessel lowbp = 0;
4135d5314d6SJason Wessel highbp = KDB_MAXBPT;
4145d5314d6SJason Wessel } else {
4155d5314d6SJason Wessel diag = kdbgetularg(argv[1], &addr);
4165d5314d6SJason Wessel if (diag)
4175d5314d6SJason Wessel return diag;
4185d5314d6SJason Wessel
4195d5314d6SJason Wessel /*
4205d5314d6SJason Wessel * For addresses less than the maximum breakpoint number,
4215d5314d6SJason Wessel * assume that the breakpoint number is desired.
4225d5314d6SJason Wessel */
4235d5314d6SJason Wessel if (addr < KDB_MAXBPT) {
4245d5314d6SJason Wessel lowbp = highbp = addr;
4255d5314d6SJason Wessel highbp++;
4265d5314d6SJason Wessel } else {
4275d5314d6SJason Wessel for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT;
4285d5314d6SJason Wessel i++, bp++) {
4295d5314d6SJason Wessel if (bp->bp_addr == addr) {
4305d5314d6SJason Wessel lowbp = highbp = i;
4315d5314d6SJason Wessel highbp++;
4325d5314d6SJason Wessel break;
4335d5314d6SJason Wessel }
4345d5314d6SJason Wessel }
4355d5314d6SJason Wessel }
4365d5314d6SJason Wessel }
4375d5314d6SJason Wessel
4385d5314d6SJason Wessel /*
4395d5314d6SJason Wessel * Now operate on the set of breakpoints matching the input
4405d5314d6SJason Wessel * criteria (either '*' for all, or an individual breakpoint).
4415d5314d6SJason Wessel */
4425d5314d6SJason Wessel for (bp = &kdb_breakpoints[lowbp], i = lowbp;
4435d5314d6SJason Wessel i < highbp;
4445d5314d6SJason Wessel i++, bp++) {
4455d5314d6SJason Wessel if (bp->bp_free)
4465d5314d6SJason Wessel continue;
4475d5314d6SJason Wessel
4485d5314d6SJason Wessel done++;
4495d5314d6SJason Wessel
4505d5314d6SJason Wessel switch (cmd) {
4515d5314d6SJason Wessel case KDBCMD_BC:
4525d5314d6SJason Wessel bp->bp_enabled = 0;
4535d5314d6SJason Wessel
4545d5314d6SJason Wessel kdb_printf("Breakpoint %d at "
4555d5314d6SJason Wessel kdb_bfd_vma_fmt " cleared\n",
4565d5314d6SJason Wessel i, bp->bp_addr);
4575d5314d6SJason Wessel
4585d5314d6SJason Wessel bp->bp_addr = 0;
4595d5314d6SJason Wessel bp->bp_free = 1;
4605d5314d6SJason Wessel
4615d5314d6SJason Wessel break;
4625d5314d6SJason Wessel case KDBCMD_BE:
4635d5314d6SJason Wessel bp->bp_enabled = 1;
4645d5314d6SJason Wessel
4655d5314d6SJason Wessel kdb_printf("Breakpoint %d at "
4665d5314d6SJason Wessel kdb_bfd_vma_fmt " enabled",
4675d5314d6SJason Wessel i, bp->bp_addr);
4685d5314d6SJason Wessel
4695d5314d6SJason Wessel kdb_printf("\n");
4705d5314d6SJason Wessel break;
4715d5314d6SJason Wessel case KDBCMD_BD:
4725d5314d6SJason Wessel if (!bp->bp_enabled)
4735d5314d6SJason Wessel break;
4745d5314d6SJason Wessel
4755d5314d6SJason Wessel bp->bp_enabled = 0;
4765d5314d6SJason Wessel
4775d5314d6SJason Wessel kdb_printf("Breakpoint %d at "
4785d5314d6SJason Wessel kdb_bfd_vma_fmt " disabled\n",
4795d5314d6SJason Wessel i, bp->bp_addr);
4805d5314d6SJason Wessel
4815d5314d6SJason Wessel break;
4825d5314d6SJason Wessel }
4835d5314d6SJason Wessel if (bp->bp_delay && (cmd == KDBCMD_BC || cmd == KDBCMD_BD)) {
4845d5314d6SJason Wessel bp->bp_delay = 0;
4855d5314d6SJason Wessel KDB_STATE_CLEAR(SSBPT);
4865d5314d6SJason Wessel }
4875d5314d6SJason Wessel }
4885d5314d6SJason Wessel
4895d5314d6SJason Wessel return (!done) ? KDB_BPTNOTFOUND : 0;
4905d5314d6SJason Wessel }
4915d5314d6SJason Wessel
4925d5314d6SJason Wessel /*
4935d5314d6SJason Wessel * kdb_ss
4945d5314d6SJason Wessel *
49536dfea42SVincent * Process the 'ss' (Single Step) command.
4965d5314d6SJason Wessel *
4975d5314d6SJason Wessel * ss
4985d5314d6SJason Wessel *
4995d5314d6SJason Wessel * Parameters:
5005d5314d6SJason Wessel * argc Argument count
5015d5314d6SJason Wessel * argv Argument vector
5025d5314d6SJason Wessel * Outputs:
5035d5314d6SJason Wessel * None.
5045d5314d6SJason Wessel * Returns:
50536dfea42SVincent * KDB_CMD_SS for success, a kdb error if failure.
5065d5314d6SJason Wessel * Locking:
5075d5314d6SJason Wessel * None.
5085d5314d6SJason Wessel * Remarks:
5095d5314d6SJason Wessel *
5105d5314d6SJason Wessel * Set the arch specific option to trigger a debug trap after the next
5115d5314d6SJason Wessel * instruction.
5125d5314d6SJason Wessel */
5135d5314d6SJason Wessel
kdb_ss(int argc,const char ** argv)5145d5314d6SJason Wessel static int kdb_ss(int argc, const char **argv)
5155d5314d6SJason Wessel {
5165d5314d6SJason Wessel if (argc != 0)
5175d5314d6SJason Wessel return KDB_ARGCOUNT;
5185d5314d6SJason Wessel /*
5195d5314d6SJason Wessel * Set trace flag and go.
5205d5314d6SJason Wessel */
5215d5314d6SJason Wessel KDB_STATE_SET(DOING_SS);
5225d5314d6SJason Wessel return KDB_CMD_SS;
5235d5314d6SJason Wessel }
5245d5314d6SJason Wessel
525e4f291b3SSumit Garg static kdbtab_t bptab[] = {
526*e868f0a3SSumit Garg { .name = "bp",
527*e868f0a3SSumit Garg .func = kdb_bp,
528*e868f0a3SSumit Garg .usage = "[<vaddr>]",
529*e868f0a3SSumit Garg .help = "Set/Display breakpoints",
530*e868f0a3SSumit Garg .flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS,
531e4f291b3SSumit Garg },
532*e868f0a3SSumit Garg { .name = "bl",
533*e868f0a3SSumit Garg .func = kdb_bp,
534*e868f0a3SSumit Garg .usage = "[<vaddr>]",
535*e868f0a3SSumit Garg .help = "Display breakpoints",
536*e868f0a3SSumit Garg .flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS,
537e4f291b3SSumit Garg },
538*e868f0a3SSumit Garg { .name = "bc",
539*e868f0a3SSumit Garg .func = kdb_bc,
540*e868f0a3SSumit Garg .usage = "<bpnum>",
541*e868f0a3SSumit Garg .help = "Clear Breakpoint",
542*e868f0a3SSumit Garg .flags = KDB_ENABLE_FLOW_CTRL,
543e4f291b3SSumit Garg },
544*e868f0a3SSumit Garg { .name = "be",
545*e868f0a3SSumit Garg .func = kdb_bc,
546*e868f0a3SSumit Garg .usage = "<bpnum>",
547*e868f0a3SSumit Garg .help = "Enable Breakpoint",
548*e868f0a3SSumit Garg .flags = KDB_ENABLE_FLOW_CTRL,
549e4f291b3SSumit Garg },
550*e868f0a3SSumit Garg { .name = "bd",
551*e868f0a3SSumit Garg .func = kdb_bc,
552*e868f0a3SSumit Garg .usage = "<bpnum>",
553*e868f0a3SSumit Garg .help = "Disable Breakpoint",
554*e868f0a3SSumit Garg .flags = KDB_ENABLE_FLOW_CTRL,
555e4f291b3SSumit Garg },
556*e868f0a3SSumit Garg { .name = "ss",
557*e868f0a3SSumit Garg .func = kdb_ss,
558*e868f0a3SSumit Garg .usage = "",
559*e868f0a3SSumit Garg .help = "Single Step",
560*e868f0a3SSumit Garg .minlen = 1,
561*e868f0a3SSumit Garg .flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS,
562e4f291b3SSumit Garg },
563e4f291b3SSumit Garg };
564e4f291b3SSumit Garg
565e4f291b3SSumit Garg static kdbtab_t bphcmd = {
566*e868f0a3SSumit Garg .name = "bph",
567*e868f0a3SSumit Garg .func = kdb_bp,
568*e868f0a3SSumit Garg .usage = "[<vaddr>]",
569*e868f0a3SSumit Garg .help = "[datar [length]|dataw [length]] Set hw brk",
570*e868f0a3SSumit Garg .flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS,
571e4f291b3SSumit Garg };
572e4f291b3SSumit Garg
5735d5314d6SJason Wessel /* Initialize the breakpoint table and register breakpoint commands. */
5745d5314d6SJason Wessel
kdb_initbptab(void)5755d5314d6SJason Wessel void __init kdb_initbptab(void)
5765d5314d6SJason Wessel {
5775d5314d6SJason Wessel int i;
5785d5314d6SJason Wessel kdb_bp_t *bp;
5795d5314d6SJason Wessel
5805d5314d6SJason Wessel /*
5815d5314d6SJason Wessel * First time initialization.
5825d5314d6SJason Wessel */
5835d5314d6SJason Wessel memset(&kdb_breakpoints, '\0', sizeof(kdb_breakpoints));
5845d5314d6SJason Wessel
5855d5314d6SJason Wessel for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++)
5865d5314d6SJason Wessel bp->bp_free = 1;
5875d5314d6SJason Wessel
588e4f291b3SSumit Garg kdb_register_table(bptab, ARRAY_SIZE(bptab));
5895d5314d6SJason Wessel if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT)
590e4f291b3SSumit Garg kdb_register_table(&bphcmd, 1);
5915d5314d6SJason Wessel }
592