Subversion Repositories HelenOS

Rev

Rev 4101 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4101 Rev 4132
1
/*
1
/*
2
 * Copyright (c) 2005 Ondrej Palkovsky
2
 * Copyright (c) 2005 Ondrej Palkovsky
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup mips32debug
29
/** @addtogroup mips32debug
30
 * @{
30
 * @{
31
 */
31
 */
32
/** @file
32
/** @file
33
 */
33
 */
34
 
34
 
35
#include <arch/debugger.h>
35
#include <arch/debugger.h>
36
#include <arch/barrier.h>
36
#include <arch/barrier.h>
37
#include <memstr.h>
37
#include <memstr.h>
38
#include <console/kconsole.h>
38
#include <console/kconsole.h>
39
#include <console/cmd.h>
39
#include <console/cmd.h>
40
#include <symtab.h>
-
 
41
#include <print.h>
40
#include <print.h>
42
#include <panic.h>
41
#include <panic.h>
43
#include <arch.h>
42
#include <arch.h>
44
#include <arch/cp0.h>
43
#include <arch/cp0.h>
45
#include <func.h>
44
#include <func.h>
46
 
45
 
-
 
46
#ifdef CONFIG_SYMTAB
-
 
47
#include <symtab.h>
-
 
48
#endif
-
 
49
 
47
bpinfo_t breakpoints[BKPOINTS_MAX];
50
bpinfo_t breakpoints[BKPOINTS_MAX];
48
SPINLOCK_INITIALIZE(bkpoint_lock);
51
SPINLOCK_INITIALIZE(bkpoint_lock);
49
 
52
 
50
#ifdef CONFIG_KCONSOLE
53
#ifdef CONFIG_KCONSOLE
51
 
54
 
52
static int cmd_print_breakpoints(cmd_arg_t *argv);
55
static int cmd_print_breakpoints(cmd_arg_t *argv);
53
static cmd_info_t bkpts_info = {
56
static cmd_info_t bkpts_info = {
54
    .name = "bkpts",
57
    .name = "bkpts",
55
    .description = "Print breakpoint table.",
58
    .description = "Print breakpoint table.",
56
    .func = cmd_print_breakpoints,
59
    .func = cmd_print_breakpoints,
57
    .argc = 0,
60
    .argc = 0,
58
};
61
};
59
 
62
 
60
static int cmd_del_breakpoint(cmd_arg_t *argv);
63
static int cmd_del_breakpoint(cmd_arg_t *argv);
61
static cmd_arg_t del_argv = {
64
static cmd_arg_t del_argv = {
62
    .type = ARG_TYPE_INT
65
    .type = ARG_TYPE_INT
63
};
66
};
64
static cmd_info_t delbkpt_info = {
67
static cmd_info_t delbkpt_info = {
65
    .name = "delbkpt",
68
    .name = "delbkpt",
66
    .description = "delbkpt <number> - Delete breakpoint.",
69
    .description = "delbkpt <number> - Delete breakpoint.",
67
    .func = cmd_del_breakpoint,
70
    .func = cmd_del_breakpoint,
68
    .argc = 1,
71
    .argc = 1,
69
    .argv = &del_argv
72
    .argv = &del_argv
70
};
73
};
71
 
74
 
72
static int cmd_add_breakpoint(cmd_arg_t *argv);
75
static int cmd_add_breakpoint(cmd_arg_t *argv);
73
static cmd_arg_t add_argv = {
76
static cmd_arg_t add_argv = {
74
    .type = ARG_TYPE_INT
77
    .type = ARG_TYPE_INT
75
};
78
};
76
static cmd_info_t addbkpt_info = {
79
static cmd_info_t addbkpt_info = {
77
    .name = "addbkpt",
80
    .name = "addbkpt",
78
    .description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch "
81
    .description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch "
79
        "insts unsupported.",
82
        "insts unsupported.",
80
    .func = cmd_add_breakpoint,
83
    .func = cmd_add_breakpoint,
81
    .argc = 1,
84
    .argc = 1,
82
    .argv = &add_argv
85
    .argv = &add_argv
83
};
86
};
84
 
87
 
85
static cmd_arg_t adde_argv[] = {
88
static cmd_arg_t adde_argv[] = {
86
    { .type = ARG_TYPE_INT },
89
    { .type = ARG_TYPE_INT },
87
    { .type = ARG_TYPE_INT }
90
    { .type = ARG_TYPE_INT }
88
};
91
};
89
static cmd_info_t addbkpte_info = {
92
static cmd_info_t addbkpte_info = {
90
    .name = "addbkpte",
93
    .name = "addbkpte",
91
    .description = "addebkpte <&symbol> <&func> - new bkpoint. Call "
94
    .description = "addebkpte <&symbol> <&func> - new bkpoint. Call "
92
        "func(or Nothing if 0).",
95
        "func(or Nothing if 0).",
93
    .func = cmd_add_breakpoint,
96
    .func = cmd_add_breakpoint,
94
    .argc = 2,
97
    .argc = 2,
95
    .argv = adde_argv
98
    .argv = adde_argv
96
};
99
};
97
 
100
 
98
static struct {
101
static struct {
99
    uint32_t andmask;
102
    uint32_t andmask;
100
    uint32_t value;
103
    uint32_t value;
101
} jmpinstr[] = {
104
} jmpinstr[] = {
102
    {0xf3ff0000, 0x41000000}, /* BCzF */
105
    {0xf3ff0000, 0x41000000}, /* BCzF */
103
    {0xf3ff0000, 0x41020000}, /* BCzFL */
106
    {0xf3ff0000, 0x41020000}, /* BCzFL */
104
    {0xf3ff0000, 0x41010000}, /* BCzT */
107
    {0xf3ff0000, 0x41010000}, /* BCzT */
105
    {0xf3ff0000, 0x41030000}, /* BCzTL */
108
    {0xf3ff0000, 0x41030000}, /* BCzTL */
106
    {0xfc000000, 0x10000000}, /* BEQ */
109
    {0xfc000000, 0x10000000}, /* BEQ */
107
    {0xfc000000, 0x50000000}, /* BEQL */
110
    {0xfc000000, 0x50000000}, /* BEQL */
108
    {0xfc1f0000, 0x04010000}, /* BEQL */
111
    {0xfc1f0000, 0x04010000}, /* BEQL */
109
    {0xfc1f0000, 0x04110000}, /* BGEZAL */
112
    {0xfc1f0000, 0x04110000}, /* BGEZAL */
110
    {0xfc1f0000, 0x04130000}, /* BGEZALL */
113
    {0xfc1f0000, 0x04130000}, /* BGEZALL */
111
    {0xfc1f0000, 0x04030000}, /* BGEZL */
114
    {0xfc1f0000, 0x04030000}, /* BGEZL */
112
    {0xfc1f0000, 0x1c000000}, /* BGTZ */
115
    {0xfc1f0000, 0x1c000000}, /* BGTZ */
113
    {0xfc1f0000, 0x5c000000}, /* BGTZL */
116
    {0xfc1f0000, 0x5c000000}, /* BGTZL */
114
    {0xfc1f0000, 0x18000000}, /* BLEZ */
117
    {0xfc1f0000, 0x18000000}, /* BLEZ */
115
    {0xfc1f0000, 0x58000000}, /* BLEZL */
118
    {0xfc1f0000, 0x58000000}, /* BLEZL */
116
    {0xfc1f0000, 0x04000000}, /* BLTZ */
119
    {0xfc1f0000, 0x04000000}, /* BLTZ */
117
    {0xfc1f0000, 0x04100000}, /* BLTZAL */
120
    {0xfc1f0000, 0x04100000}, /* BLTZAL */
118
    {0xfc1f0000, 0x04120000}, /* BLTZALL */
121
    {0xfc1f0000, 0x04120000}, /* BLTZALL */
119
    {0xfc1f0000, 0x04020000}, /* BLTZL */
122
    {0xfc1f0000, 0x04020000}, /* BLTZL */
120
    {0xfc000000, 0x14000000}, /* BNE */
123
    {0xfc000000, 0x14000000}, /* BNE */
121
    {0xfc000000, 0x54000000}, /* BNEL */
124
    {0xfc000000, 0x54000000}, /* BNEL */
122
    {0xfc000000, 0x08000000}, /* J */
125
    {0xfc000000, 0x08000000}, /* J */
123
    {0xfc000000, 0x0c000000}, /* JAL */
126
    {0xfc000000, 0x0c000000}, /* JAL */
124
    {0xfc1f07ff, 0x00000009}, /* JALR */
127
    {0xfc1f07ff, 0x00000009}, /* JALR */
125
    {0, 0} /* EndOfTable */
128
    {0, 0} /* EndOfTable */
126
};
129
};
127
 
130
 
128
 
131
 
129
/** Test, if the given instruction is a jump or branch instruction
132
/** Test, if the given instruction is a jump or branch instruction
130
 *
133
 *
131
 * @param instr Instruction code
134
 * @param instr Instruction code
132
 * @return true - it is jump instruction, false otherwise
135
 * @return true - it is jump instruction, false otherwise
133
 *
136
 *
134
 */
137
 */
135
static bool is_jump(unative_t instr)
138
static bool is_jump(unative_t instr)
136
{
139
{
137
    int i;
140
    int i;
138
 
141
 
139
    for (i = 0; jmpinstr[i].andmask; i++) {
142
    for (i = 0; jmpinstr[i].andmask; i++) {
140
        if ((instr & jmpinstr[i].andmask) == jmpinstr[i].value)
143
        if ((instr & jmpinstr[i].andmask) == jmpinstr[i].value)
141
            return true;
144
            return true;
142
    }
145
    }
143
 
146
 
144
    return false;
147
    return false;
145
}
148
}
146
 
149
 
147
/** Add new breakpoint to table */
150
/** Add new breakpoint to table */
148
int cmd_add_breakpoint(cmd_arg_t *argv)
151
int cmd_add_breakpoint(cmd_arg_t *argv)
149
{
152
{
150
    bpinfo_t *cur = NULL;
153
    bpinfo_t *cur = NULL;
151
    ipl_t ipl;
154
    ipl_t ipl;
152
    int i;
155
    int i;
153
 
156
 
154
    if (argv->intval & 0x3) {
157
    if (argv->intval & 0x3) {
155
        printf("Not aligned instruction, forgot to use &symbol?\n");
158
        printf("Not aligned instruction, forgot to use &symbol?\n");
156
        return 1;
159
        return 1;
157
    }
160
    }
158
    ipl = interrupts_disable();
161
    ipl = interrupts_disable();
159
    spinlock_lock(&bkpoint_lock);
162
    spinlock_lock(&bkpoint_lock);
160
 
163
 
161
    /* Check, that the breakpoints do not conflict */
164
    /* Check, that the breakpoints do not conflict */
162
    for (i = 0; i < BKPOINTS_MAX; i++) {
165
    for (i = 0; i < BKPOINTS_MAX; i++) {
163
        if (breakpoints[i].address == (uintptr_t)argv->intval) {
166
        if (breakpoints[i].address == (uintptr_t)argv->intval) {
164
            printf("Duplicate breakpoint %d.\n", i);
167
            printf("Duplicate breakpoint %d.\n", i);
165
            spinlock_unlock(&bkpoint_lock);
168
            spinlock_unlock(&bkpoint_lock);
166
            return 0;
169
            return 0;
167
        } else if (breakpoints[i].address == (uintptr_t)argv->intval +
170
        } else if (breakpoints[i].address == (uintptr_t)argv->intval +
168
            sizeof(unative_t) || breakpoints[i].address ==
171
            sizeof(unative_t) || breakpoints[i].address ==
169
            (uintptr_t)argv->intval - sizeof(unative_t)) {
172
            (uintptr_t)argv->intval - sizeof(unative_t)) {
170
            printf("Adjacent breakpoints not supported, conflict "
173
            printf("Adjacent breakpoints not supported, conflict "
171
                "with %d.\n", i);
174
                "with %d.\n", i);
172
            spinlock_unlock(&bkpoint_lock);
175
            spinlock_unlock(&bkpoint_lock);
173
            return 0;
176
            return 0;
174
        }
177
        }
175
       
178
       
176
    }
179
    }
177
 
180
 
178
    for (i = 0; i < BKPOINTS_MAX; i++)
181
    for (i = 0; i < BKPOINTS_MAX; i++)
179
        if (!breakpoints[i].address) {
182
        if (!breakpoints[i].address) {
180
            cur = &breakpoints[i];
183
            cur = &breakpoints[i];
181
            break;
184
            break;
182
        }
185
        }
183
    if (!cur) {
186
    if (!cur) {
184
        printf("Too many breakpoints.\n");
187
        printf("Too many breakpoints.\n");
185
        spinlock_unlock(&bkpoint_lock);
188
        spinlock_unlock(&bkpoint_lock);
186
        interrupts_restore(ipl);
189
        interrupts_restore(ipl);
187
        return 0;
190
        return 0;
188
    }
191
    }
189
    cur->address = (uintptr_t) argv->intval;
192
    cur->address = (uintptr_t) argv->intval;
190
    printf("Adding breakpoint on address: %p\n", argv->intval);
193
    printf("Adding breakpoint on address: %p\n", argv->intval);
191
    cur->instruction = ((unative_t *)cur->address)[0];
194
    cur->instruction = ((unative_t *)cur->address)[0];
192
    cur->nextinstruction = ((unative_t *)cur->address)[1];
195
    cur->nextinstruction = ((unative_t *)cur->address)[1];
193
    if (argv == &add_argv) {
196
    if (argv == &add_argv) {
194
        cur->flags = 0;
197
        cur->flags = 0;
195
    } else { /* We are add extended */
198
    } else { /* We are add extended */
196
        cur->flags = BKPOINT_FUNCCALL;
199
        cur->flags = BKPOINT_FUNCCALL;
197
        cur->bkfunc = (void (*)(void *, istate_t *)) argv[1].intval;
200
        cur->bkfunc = (void (*)(void *, istate_t *)) argv[1].intval;
198
    }
201
    }
199
    if (is_jump(cur->instruction))
202
    if (is_jump(cur->instruction))
200
        cur->flags |= BKPOINT_ONESHOT;
203
        cur->flags |= BKPOINT_ONESHOT;
201
    cur->counter = 0;
204
    cur->counter = 0;
202
 
205
 
203
    /* Set breakpoint */
206
    /* Set breakpoint */
204
    *((unative_t *)cur->address) = 0x0d;
207
    *((unative_t *)cur->address) = 0x0d;
205
    smc_coherence(cur->address);
208
    smc_coherence(cur->address);
206
 
209
 
207
    spinlock_unlock(&bkpoint_lock);
210
    spinlock_unlock(&bkpoint_lock);
208
    interrupts_restore(ipl);
211
    interrupts_restore(ipl);
209
 
212
 
210
    return 1;
213
    return 1;
211
}
214
}
212
 
215
 
213
/** Remove breakpoint from table */
216
/** Remove breakpoint from table */
214
int cmd_del_breakpoint(cmd_arg_t *argv)
217
int cmd_del_breakpoint(cmd_arg_t *argv)
215
{
218
{
216
    bpinfo_t *cur;
219
    bpinfo_t *cur;
217
    ipl_t ipl;
220
    ipl_t ipl;
218
 
221
 
219
    if (argv->intval > BKPOINTS_MAX) {
222
    if (argv->intval > BKPOINTS_MAX) {
220
        printf("Invalid breakpoint number.\n");
223
        printf("Invalid breakpoint number.\n");
221
        return 0;
224
        return 0;
222
    }
225
    }
223
    ipl = interrupts_disable();
226
    ipl = interrupts_disable();
224
    spinlock_lock(&bkpoint_lock);
227
    spinlock_lock(&bkpoint_lock);
225
 
228
 
226
    cur = &breakpoints[argv->intval];
229
    cur = &breakpoints[argv->intval];
227
    if (!cur->address) {
230
    if (!cur->address) {
228
        printf("Breakpoint does not exist.\n");
231
        printf("Breakpoint does not exist.\n");
229
        spinlock_unlock(&bkpoint_lock);
232
        spinlock_unlock(&bkpoint_lock);
230
        interrupts_restore(ipl);
233
        interrupts_restore(ipl);
231
        return 0;
234
        return 0;
232
    }
235
    }
233
    if ((cur->flags & BKPOINT_INPROG) && (cur->flags & BKPOINT_ONESHOT)) {
236
    if ((cur->flags & BKPOINT_INPROG) && (cur->flags & BKPOINT_ONESHOT)) {
234
        printf("Cannot remove one-shot breakpoint in-progress\n");
237
        printf("Cannot remove one-shot breakpoint in-progress\n");
235
        spinlock_unlock(&bkpoint_lock);
238
        spinlock_unlock(&bkpoint_lock);
236
        interrupts_restore(ipl);
239
        interrupts_restore(ipl);
237
        return 0;
240
        return 0;
238
    }
241
    }
239
    ((uint32_t *)cur->address)[0] = cur->instruction;
242
    ((uint32_t *)cur->address)[0] = cur->instruction;
240
    smc_coherence(((uint32_t *)cur->address)[0]);
243
    smc_coherence(((uint32_t *)cur->address)[0]);
241
    ((uint32_t *)cur->address)[1] = cur->nextinstruction;
244
    ((uint32_t *)cur->address)[1] = cur->nextinstruction;
242
    smc_coherence(((uint32_t *)cur->address)[1]);
245
    smc_coherence(((uint32_t *)cur->address)[1]);
243
 
246
 
244
    cur->address = NULL;
247
    cur->address = NULL;
245
 
248
 
246
    spinlock_unlock(&bkpoint_lock);
249
    spinlock_unlock(&bkpoint_lock);
247
    interrupts_restore(ipl);
250
    interrupts_restore(ipl);
248
    return 1;
251
    return 1;
249
}
252
}
250
 
253
 
251
/** Print table of active breakpoints */
254
/** Print table of active breakpoints */
252
int cmd_print_breakpoints(cmd_arg_t *argv)
255
int cmd_print_breakpoints(cmd_arg_t *argv)
253
{
256
{
254
    unsigned int i;
257
    unsigned int i;
255
    char *symbol;
258
    char *symbol;
256
   
259
   
257
    printf("#  Count Address    INPROG ONESHOT FUNCCALL In symbol\n");
260
    printf("#  Count Address    INPROG ONESHOT FUNCCALL In symbol\n");
258
    printf("-- ----- ---------- ------ ------- -------- ---------\n");
261
    printf("-- ----- ---------- ------ ------- -------- ---------\n");
259
   
262
   
260
    for (i = 0; i < BKPOINTS_MAX; i++)
263
    for (i = 0; i < BKPOINTS_MAX; i++)
261
        if (breakpoints[i].address) {
264
        if (breakpoints[i].address) {
-
 
265
#ifdef CONFIG_SYMTAB
262
            symbol = get_symtab_entry(breakpoints[i].address);
266
            symbol = get_symtab_entry(breakpoints[i].address);
-
 
267
#else
-
 
268
            symbol = "n/a";
-
 
269
#endif
263
           
270
           
264
            printf("%-2u %-5d %#10zx %-6s %-7s %-8s %s\n", i,
271
            printf("%-2u %-5d %#10zx %-6s %-7s %-8s %s\n", i,
265
                breakpoints[i].counter, breakpoints[i].address,
272
                breakpoints[i].counter, breakpoints[i].address,
266
                ((breakpoints[i].flags & BKPOINT_INPROG) ? "true" :
273
                ((breakpoints[i].flags & BKPOINT_INPROG) ? "true" :
267
                "false"), ((breakpoints[i].flags & BKPOINT_ONESHOT)
274
                "false"), ((breakpoints[i].flags & BKPOINT_ONESHOT)
268
                ? "true" : "false"), ((breakpoints[i].flags &
275
                ? "true" : "false"), ((breakpoints[i].flags &
269
                BKPOINT_FUNCCALL) ? "true" : "false"), symbol);
276
                BKPOINT_FUNCCALL) ? "true" : "false"), symbol);
270
        }
277
        }
271
    return 1;
278
    return 1;
272
}
279
}
273
 
280
 
274
#endif
281
#endif
275
 
282
 
276
/** Initialize debugger */
283
/** Initialize debugger */
277
void debugger_init()
284
void debugger_init()
278
{
285
{
279
    int i;
286
    int i;
280
 
287
 
281
    for (i = 0; i < BKPOINTS_MAX; i++)
288
    for (i = 0; i < BKPOINTS_MAX; i++)
282
        breakpoints[i].address = NULL;
289
        breakpoints[i].address = NULL;
283
 
290
 
284
#ifdef CONFIG_KCONSOLE
291
#ifdef CONFIG_KCONSOLE
285
    cmd_initialize(&bkpts_info);
292
    cmd_initialize(&bkpts_info);
286
    if (!cmd_register(&bkpts_info))
293
    if (!cmd_register(&bkpts_info))
287
        printf("Cannot register command %s\n", bkpts_info.name);
294
        printf("Cannot register command %s\n", bkpts_info.name);
288
 
295
 
289
    cmd_initialize(&delbkpt_info);
296
    cmd_initialize(&delbkpt_info);
290
    if (!cmd_register(&delbkpt_info))
297
    if (!cmd_register(&delbkpt_info))
291
        printf("Cannot register command %s\n", delbkpt_info.name);
298
        printf("Cannot register command %s\n", delbkpt_info.name);
292
 
299
 
293
    cmd_initialize(&addbkpt_info);
300
    cmd_initialize(&addbkpt_info);
294
    if (!cmd_register(&addbkpt_info))
301
    if (!cmd_register(&addbkpt_info))
295
        printf("Cannot register command %s\n", addbkpt_info.name);
302
        printf("Cannot register command %s\n", addbkpt_info.name);
296
 
303
 
297
    cmd_initialize(&addbkpte_info);
304
    cmd_initialize(&addbkpte_info);
298
    if (!cmd_register(&addbkpte_info))
305
    if (!cmd_register(&addbkpte_info))
299
        printf("Cannot register command %s\n", addbkpte_info.name);
306
        printf("Cannot register command %s\n", addbkpte_info.name);
300
#endif
307
#endif
301
}
308
}
302
 
309
 
303
/** Handle breakpoint
310
/** Handle breakpoint
304
 *
311
 *
305
 * Find breakpoint in breakpoint table.
312
 * Find breakpoint in breakpoint table.
306
 * If found, call kconsole, set break on next instruction and reexecute.
313
 * If found, call kconsole, set break on next instruction and reexecute.
307
 * If we are on "next instruction", set it back on the first and reexecute.
314
 * If we are on "next instruction", set it back on the first and reexecute.
308
 * If breakpoint not found in breakpoint table, call kconsole and start
315
 * If breakpoint not found in breakpoint table, call kconsole and start
309
 * next instruction.
316
 * next instruction.
310
 */
317
 */
311
void debugger_bpoint(istate_t *istate)
318
void debugger_bpoint(istate_t *istate)
312
{
319
{
313
    bpinfo_t *cur = NULL;
320
    bpinfo_t *cur = NULL;
314
    uintptr_t fireaddr = istate->epc;
321
    uintptr_t fireaddr = istate->epc;
315
    int i;
322
    int i;
316
 
323
 
317
    /* test branch delay slot */
324
    /* test branch delay slot */
318
    if (cp0_cause_read() & 0x80000000)
325
    if (cp0_cause_read() & 0x80000000)
319
        panic("Breakpoint in branch delay slot not supported.");
326
        panic("Breakpoint in branch delay slot not supported.");
320
 
327
 
321
    spinlock_lock(&bkpoint_lock);
328
    spinlock_lock(&bkpoint_lock);
322
    for (i = 0; i < BKPOINTS_MAX; i++) {
329
    for (i = 0; i < BKPOINTS_MAX; i++) {
323
        /* Normal breakpoint */
330
        /* Normal breakpoint */
324
        if (fireaddr == breakpoints[i].address &&
331
        if (fireaddr == breakpoints[i].address &&
325
            !(breakpoints[i].flags & BKPOINT_REINST)) {
332
            !(breakpoints[i].flags & BKPOINT_REINST)) {
326
            cur = &breakpoints[i];
333
            cur = &breakpoints[i];
327
            break;
334
            break;
328
        }
335
        }
329
        /* Reinst only breakpoint */
336
        /* Reinst only breakpoint */
330
        if ((breakpoints[i].flags & BKPOINT_REINST) &&
337
        if ((breakpoints[i].flags & BKPOINT_REINST) &&
331
            (fireaddr == breakpoints[i].address + sizeof(unative_t))) {
338
            (fireaddr == breakpoints[i].address + sizeof(unative_t))) {
332
            cur = &breakpoints[i];
339
            cur = &breakpoints[i];
333
            break;
340
            break;
334
        }
341
        }
335
    }
342
    }
336
    if (cur) {
343
    if (cur) {
337
        if (cur->flags & BKPOINT_REINST) {
344
        if (cur->flags & BKPOINT_REINST) {
338
            /* Set breakpoint on first instruction */
345
            /* Set breakpoint on first instruction */
339
            ((uint32_t *)cur->address)[0] = 0x0d;
346
            ((uint32_t *)cur->address)[0] = 0x0d;
340
            smc_coherence(((uint32_t *)cur->address)[0]);
347
            smc_coherence(((uint32_t *)cur->address)[0]);
341
            /* Return back the second */
348
            /* Return back the second */
342
            ((uint32_t *)cur->address)[1] = cur->nextinstruction;
349
            ((uint32_t *)cur->address)[1] = cur->nextinstruction;
343
            smc_coherence(((uint32_t *)cur->address)[1]);
350
            smc_coherence(((uint32_t *)cur->address)[1]);
344
            cur->flags &= ~BKPOINT_REINST;
351
            cur->flags &= ~BKPOINT_REINST;
345
            spinlock_unlock(&bkpoint_lock);
352
            spinlock_unlock(&bkpoint_lock);
346
            return;
353
            return;
347
        }
354
        }
348
        if (cur->flags & BKPOINT_INPROG)
355
        if (cur->flags & BKPOINT_INPROG)
349
            printf("Warning: breakpoint recursion\n");
356
            printf("Warning: breakpoint recursion\n");
350
       
357
       
351
        if (!(cur->flags & BKPOINT_FUNCCALL))
358
        if (!(cur->flags & BKPOINT_FUNCCALL)) {
-
 
359
#ifdef CONFIG_SYMTAB
352
            printf("***Breakpoint %d: %p in %s.\n", i, fireaddr,
360
            printf("***Breakpoint %d: %p in %s.\n", i, fireaddr,
353
                get_symtab_entry(istate->epc));
361
                get_symtab_entry(istate->epc));
-
 
362
#else
-
 
363
            printf("***Breakpoint %d: %p.\n", i, fireaddr);
-
 
364
#endif
-
 
365
        }
354
 
366
 
355
        /* Return first instruction back */
367
        /* Return first instruction back */
356
        ((uint32_t *)cur->address)[0] = cur->instruction;
368
        ((uint32_t *)cur->address)[0] = cur->instruction;
357
        smc_coherence(cur->address);
369
        smc_coherence(cur->address);
358
 
370
 
359
        if (! (cur->flags & BKPOINT_ONESHOT)) {
371
        if (! (cur->flags & BKPOINT_ONESHOT)) {
360
            /* Set Breakpoint on next instruction */
372
            /* Set Breakpoint on next instruction */
361
            ((uint32_t *)cur->address)[1] = 0x0d;
373
            ((uint32_t *)cur->address)[1] = 0x0d;
362
            cur->flags |= BKPOINT_REINST;
374
            cur->flags |= BKPOINT_REINST;
363
        }
375
        }
364
        cur->flags |= BKPOINT_INPROG;
376
        cur->flags |= BKPOINT_INPROG;
365
    } else {
377
    } else {
-
 
378
#ifdef CONFIG_SYMTAB
366
        printf("***Breakpoint %p in %s.\n", fireaddr,
379
        printf("***Breakpoint %p in %s.\n", fireaddr,
367
               get_symtab_entry(fireaddr));
380
               get_symtab_entry(fireaddr));
-
 
381
#else
-
 
382
        printf("***Breakpoint %p.\n", fireaddr);   
-
 
383
#endif
368
        /* Move on to next instruction */
384
        /* Move on to next instruction */
369
        istate->epc += 4;
385
        istate->epc += 4;
370
    }
386
    }
371
    if (cur)
387
    if (cur)
372
        cur->counter++;
388
        cur->counter++;
373
    if (cur && (cur->flags & BKPOINT_FUNCCALL)) {
389
    if (cur && (cur->flags & BKPOINT_FUNCCALL)) {
374
        /* Allow zero bkfunc, just for counting */
390
        /* Allow zero bkfunc, just for counting */
375
        if (cur->bkfunc)
391
        if (cur->bkfunc)
376
            cur->bkfunc(cur, istate);
392
            cur->bkfunc(cur, istate);
377
    } else {
393
    } else {
378
#ifdef CONFIG_KCONSOLE
394
#ifdef CONFIG_KCONSOLE
379
        /* This disables all other processors - we are not SMP,
395
        /* This disables all other processors - we are not SMP,
380
         * actually this gets us to cpu_halt, if scheduler() is run
396
         * actually this gets us to cpu_halt, if scheduler() is run
381
         * - we generally do not want scheduler to be run from debug,
397
         * - we generally do not want scheduler to be run from debug,
382
         *   so this is a good idea
398
         *   so this is a good idea
383
         */
399
         */
384
        atomic_set(&haltstate, 1);
400
        atomic_set(&haltstate, 1);
385
        spinlock_unlock(&bkpoint_lock);
401
        spinlock_unlock(&bkpoint_lock);
386
       
402
       
387
        kconsole("debug", "Debug console ready.\n", false);
403
        kconsole("debug", "Debug console ready.\n", false);
388
       
404
       
389
        spinlock_lock(&bkpoint_lock);
405
        spinlock_lock(&bkpoint_lock);
390
        atomic_set(&haltstate, 0);
406
        atomic_set(&haltstate, 0);
391
#endif
407
#endif
392
    }
408
    }
393
    if (cur && cur->address == fireaddr && (cur->flags & BKPOINT_INPROG)) {
409
    if (cur && cur->address == fireaddr && (cur->flags & BKPOINT_INPROG)) {
394
        /* Remove one-shot breakpoint */
410
        /* Remove one-shot breakpoint */
395
        if ((cur->flags & BKPOINT_ONESHOT))
411
        if ((cur->flags & BKPOINT_ONESHOT))
396
            cur->address = NULL;
412
            cur->address = NULL;
397
        /* Remove in-progress flag */
413
        /* Remove in-progress flag */
398
        cur->flags &= ~BKPOINT_INPROG;
414
        cur->flags &= ~BKPOINT_INPROG;
399
    }
415
    }
400
    spinlock_unlock(&bkpoint_lock);
416
    spinlock_unlock(&bkpoint_lock);
401
}
417
}
402
 
418
 
403
/** @}
419
/** @}
404
 */
420
 */
405
 
421