Subversion Repositories HelenOS

Rev

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

Rev 3139 Rev 3343
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>
40
#include <symtab.h>
41
#include <print.h>
41
#include <print.h>
42
#include <panic.h>
42
#include <panic.h>
43
#include <arch.h>
43
#include <arch.h>
44
#include <arch/cp0.h>
44
#include <arch/cp0.h>
45
#include <func.h>
45
#include <func.h>
46
 
46
 
47
bpinfo_t breakpoints[BKPOINTS_MAX];
47
bpinfo_t breakpoints[BKPOINTS_MAX];
48
SPINLOCK_INITIALIZE(bkpoint_lock);
48
SPINLOCK_INITIALIZE(bkpoint_lock);
49
 
49
 
50
static int cmd_print_breakpoints(cmd_arg_t *argv);
50
static int cmd_print_breakpoints(cmd_arg_t *argv);
51
static cmd_info_t bkpts_info = {
51
static cmd_info_t bkpts_info = {
52
    .name = "bkpts",
52
    .name = "bkpts",
53
    .description = "Print breakpoint table.",
53
    .description = "Print breakpoint table.",
54
    .func = cmd_print_breakpoints,
54
    .func = cmd_print_breakpoints,
55
    .argc = 0,
55
    .argc = 0,
56
};
56
};
57
 
57
 
58
static int cmd_del_breakpoint(cmd_arg_t *argv);
58
static int cmd_del_breakpoint(cmd_arg_t *argv);
59
static cmd_arg_t del_argv = {
59
static cmd_arg_t del_argv = {
60
    .type = ARG_TYPE_INT
60
    .type = ARG_TYPE_INT
61
};
61
};
62
static cmd_info_t delbkpt_info = {
62
static cmd_info_t delbkpt_info = {
63
    .name = "delbkpt",
63
    .name = "delbkpt",
64
    .description = "delbkpt <number> - Delete breakpoint.",
64
    .description = "delbkpt <number> - Delete breakpoint.",
65
    .func = cmd_del_breakpoint,
65
    .func = cmd_del_breakpoint,
66
    .argc = 1,
66
    .argc = 1,
67
    .argv = &del_argv
67
    .argv = &del_argv
68
};
68
};
69
 
69
 
70
static int cmd_add_breakpoint(cmd_arg_t *argv);
70
static int cmd_add_breakpoint(cmd_arg_t *argv);
71
static cmd_arg_t add_argv = {
71
static cmd_arg_t add_argv = {
72
    .type = ARG_TYPE_INT
72
    .type = ARG_TYPE_INT
73
};
73
};
74
static cmd_info_t addbkpt_info = {
74
static cmd_info_t addbkpt_info = {
75
    .name = "addbkpt",
75
    .name = "addbkpt",
76
    .description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch "
76
    .description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch "
77
        "insts unsupported.",
77
        "insts unsupported.",
78
    .func = cmd_add_breakpoint,
78
    .func = cmd_add_breakpoint,
79
    .argc = 1,
79
    .argc = 1,
80
    .argv = &add_argv
80
    .argv = &add_argv
81
};
81
};
82
 
82
 
83
static cmd_arg_t adde_argv[] = {
83
static cmd_arg_t adde_argv[] = {
84
    { .type = ARG_TYPE_INT },
84
    { .type = ARG_TYPE_INT },
85
    { .type = ARG_TYPE_INT }
85
    { .type = ARG_TYPE_INT }
86
};
86
};
87
static cmd_info_t addbkpte_info = {
87
static cmd_info_t addbkpte_info = {
88
    .name = "addbkpte",
88
    .name = "addbkpte",
89
    .description = "addebkpte <&symbol> <&func> - new bkpoint. Call "
89
    .description = "addebkpte <&symbol> <&func> - new bkpoint. Call "
90
        "func(or Nothing if 0).",
90
        "func(or Nothing if 0).",
91
    .func = cmd_add_breakpoint,
91
    .func = cmd_add_breakpoint,
92
    .argc = 2,
92
    .argc = 2,
93
    .argv = adde_argv
93
    .argv = adde_argv
94
};
94
};
95
 
95
 
96
static struct {
96
static struct {
97
    uint32_t andmask;
97
    uint32_t andmask;
98
    uint32_t value;
98
    uint32_t value;
99
} jmpinstr[] = {
99
} jmpinstr[] = {
100
    {0xf3ff0000, 0x41000000}, /* BCzF */
100
    {0xf3ff0000, 0x41000000}, /* BCzF */
101
    {0xf3ff0000, 0x41020000}, /* BCzFL */
101
    {0xf3ff0000, 0x41020000}, /* BCzFL */
102
    {0xf3ff0000, 0x41010000}, /* BCzT */
102
    {0xf3ff0000, 0x41010000}, /* BCzT */
103
    {0xf3ff0000, 0x41030000}, /* BCzTL */
103
    {0xf3ff0000, 0x41030000}, /* BCzTL */
104
    {0xfc000000, 0x10000000}, /* BEQ */
104
    {0xfc000000, 0x10000000}, /* BEQ */
105
    {0xfc000000, 0x50000000}, /* BEQL */
105
    {0xfc000000, 0x50000000}, /* BEQL */
106
    {0xfc1f0000, 0x04010000}, /* BEQL */
106
    {0xfc1f0000, 0x04010000}, /* BEQL */
107
    {0xfc1f0000, 0x04110000}, /* BGEZAL */
107
    {0xfc1f0000, 0x04110000}, /* BGEZAL */
108
    {0xfc1f0000, 0x04130000}, /* BGEZALL */
108
    {0xfc1f0000, 0x04130000}, /* BGEZALL */
109
    {0xfc1f0000, 0x04030000}, /* BGEZL */
109
    {0xfc1f0000, 0x04030000}, /* BGEZL */
110
    {0xfc1f0000, 0x1c000000}, /* BGTZ */
110
    {0xfc1f0000, 0x1c000000}, /* BGTZ */
111
    {0xfc1f0000, 0x5c000000}, /* BGTZL */
111
    {0xfc1f0000, 0x5c000000}, /* BGTZL */
112
    {0xfc1f0000, 0x18000000}, /* BLEZ */
112
    {0xfc1f0000, 0x18000000}, /* BLEZ */
113
    {0xfc1f0000, 0x58000000}, /* BLEZL */
113
    {0xfc1f0000, 0x58000000}, /* BLEZL */
114
    {0xfc1f0000, 0x04000000}, /* BLTZ */
114
    {0xfc1f0000, 0x04000000}, /* BLTZ */
115
    {0xfc1f0000, 0x04100000}, /* BLTZAL */
115
    {0xfc1f0000, 0x04100000}, /* BLTZAL */
116
    {0xfc1f0000, 0x04120000}, /* BLTZALL */
116
    {0xfc1f0000, 0x04120000}, /* BLTZALL */
117
    {0xfc1f0000, 0x04020000}, /* BLTZL */
117
    {0xfc1f0000, 0x04020000}, /* BLTZL */
118
    {0xfc000000, 0x14000000}, /* BNE */
118
    {0xfc000000, 0x14000000}, /* BNE */
119
    {0xfc000000, 0x54000000}, /* BNEL */
119
    {0xfc000000, 0x54000000}, /* BNEL */
120
    {0xfc000000, 0x08000000}, /* J */
120
    {0xfc000000, 0x08000000}, /* J */
121
    {0xfc000000, 0x0c000000}, /* JAL */
121
    {0xfc000000, 0x0c000000}, /* JAL */
122
    {0xfc1f07ff, 0x00000009}, /* JALR */
122
    {0xfc1f07ff, 0x00000009}, /* JALR */
123
    {0, 0} /* EndOfTable */
123
    {0, 0} /* EndOfTable */
124
};
124
};
125
 
125
 
126
/** Test, if the given instruction is a jump or branch instruction
126
/** Test, if the given instruction is a jump or branch instruction
127
 *
127
 *
128
 * @param instr Instruction code
128
 * @param instr Instruction code
129
 * @return true - it is jump instruction, false otherwise
129
 * @return true - it is jump instruction, false otherwise
130
 */
130
 */
131
static bool is_jump(unative_t instr)
131
static bool is_jump(unative_t instr)
132
{
132
{
133
    int i;
133
    int i;
134
 
134
 
135
    for (i = 0; jmpinstr[i].andmask; i++) {
135
    for (i = 0; jmpinstr[i].andmask; i++) {
136
        if ((instr & jmpinstr[i].andmask) == jmpinstr[i].value)
136
        if ((instr & jmpinstr[i].andmask) == jmpinstr[i].value)
137
            return true;
137
            return true;
138
    }
138
    }
139
 
139
 
140
    return false;
140
    return false;
141
}
141
}
142
 
142
 
143
/** Add new breakpoint to table */
143
/** Add new breakpoint to table */
144
int cmd_add_breakpoint(cmd_arg_t *argv)
144
int cmd_add_breakpoint(cmd_arg_t *argv)
145
{
145
{
146
    bpinfo_t *cur = NULL;
146
    bpinfo_t *cur = NULL;
147
    ipl_t ipl;
147
    ipl_t ipl;
148
    int i;
148
    int i;
149
 
149
 
150
    if (argv->intval & 0x3) {
150
    if (argv->intval & 0x3) {
151
        printf("Not aligned instruction, forgot to use &symbol?\n");
151
        printf("Not aligned instruction, forgot to use &symbol?\n");
152
        return 1;
152
        return 1;
153
    }
153
    }
154
    ipl = interrupts_disable();
154
    ipl = interrupts_disable();
155
    spinlock_lock(&bkpoint_lock);
155
    spinlock_lock(&bkpoint_lock);
156
 
156
 
157
    /* Check, that the breakpoints do not conflict */
157
    /* Check, that the breakpoints do not conflict */
158
    for (i = 0; i < BKPOINTS_MAX; i++) {
158
    for (i = 0; i < BKPOINTS_MAX; i++) {
159
        if (breakpoints[i].address == (uintptr_t)argv->intval) {
159
        if (breakpoints[i].address == (uintptr_t)argv->intval) {
160
            printf("Duplicate breakpoint %d.\n", i);
160
            printf("Duplicate breakpoint %d.\n", i);
161
            spinlock_unlock(&bkpoints_lock);
161
            spinlock_unlock(&bkpoints_lock);
162
            return 0;
162
            return 0;
163
        } else if (breakpoints[i].address == (uintptr_t)argv->intval +
163
        } else if (breakpoints[i].address == (uintptr_t)argv->intval +
164
            sizeof(unative_t) || breakpoints[i].address ==
164
            sizeof(unative_t) || breakpoints[i].address ==
165
            (uintptr_t)argv->intval - sizeof(unative_t)) {
165
            (uintptr_t)argv->intval - sizeof(unative_t)) {
166
            printf("Adjacent breakpoints not supported, conflict "
166
            printf("Adjacent breakpoints not supported, conflict "
167
                "with %d.\n", i);
167
                "with %d.\n", i);
168
            spinlock_unlock(&bkpoints_lock);
168
            spinlock_unlock(&bkpoints_lock);
169
            return 0;
169
            return 0;
170
        }
170
        }
171
           
171
           
172
    }
172
    }
173
 
173
 
174
    for (i = 0; i < BKPOINTS_MAX; i++)
174
    for (i = 0; i < BKPOINTS_MAX; i++)
175
        if (!breakpoints[i].address) {
175
        if (!breakpoints[i].address) {
176
            cur = &breakpoints[i];
176
            cur = &breakpoints[i];
177
            break;
177
            break;
178
        }
178
        }
179
    if (!cur) {
179
    if (!cur) {
180
        printf("Too many breakpoints.\n");
180
        printf("Too many breakpoints.\n");
181
        spinlock_unlock(&bkpoint_lock);
181
        spinlock_unlock(&bkpoint_lock);
182
        interrupts_restore(ipl);
182
        interrupts_restore(ipl);
183
        return 0;
183
        return 0;
184
    }
184
    }
185
    cur->address = (uintptr_t) argv->intval;
185
    cur->address = (uintptr_t) argv->intval;
186
    printf("Adding breakpoint on address: %p\n", argv->intval);
186
    printf("Adding breakpoint on address: %p\n", argv->intval);
187
    cur->instruction = ((unative_t *)cur->address)[0];
187
    cur->instruction = ((unative_t *)cur->address)[0];
188
    cur->nextinstruction = ((unative_t *)cur->address)[1];
188
    cur->nextinstruction = ((unative_t *)cur->address)[1];
189
    if (argv == &add_argv) {
189
    if (argv == &add_argv) {
190
        cur->flags = 0;
190
        cur->flags = 0;
191
    } else { /* We are add extended */
191
    } else { /* We are add extended */
192
        cur->flags = BKPOINT_FUNCCALL;
192
        cur->flags = BKPOINT_FUNCCALL;
193
        cur->bkfunc = (void (*)(void *, istate_t *)) argv[1].intval;
193
        cur->bkfunc = (void (*)(void *, istate_t *)) argv[1].intval;
194
    }
194
    }
195
    if (is_jump(cur->instruction))
195
    if (is_jump(cur->instruction))
196
        cur->flags |= BKPOINT_ONESHOT;
196
        cur->flags |= BKPOINT_ONESHOT;
197
    cur->counter = 0;
197
    cur->counter = 0;
198
 
198
 
199
    /* Set breakpoint */
199
    /* Set breakpoint */
200
    *((unative_t *)cur->address) = 0x0d;
200
    *((unative_t *)cur->address) = 0x0d;
201
    smc_coherence(cur->address);
201
    smc_coherence(cur->address);
202
 
202
 
203
    spinlock_unlock(&bkpoint_lock);
203
    spinlock_unlock(&bkpoint_lock);
204
    interrupts_restore(ipl);
204
    interrupts_restore(ipl);
205
 
205
 
206
    return 1;
206
    return 1;
207
}
207
}
208
 
208
 
209
/** Remove breakpoint from table */
209
/** Remove breakpoint from table */
210
int cmd_del_breakpoint(cmd_arg_t *argv)
210
int cmd_del_breakpoint(cmd_arg_t *argv)
211
{
211
{
212
    bpinfo_t *cur;
212
    bpinfo_t *cur;
213
    ipl_t ipl;
213
    ipl_t ipl;
214
 
214
 
215
    if (argv->intval > BKPOINTS_MAX) {
215
    if (argv->intval > BKPOINTS_MAX) {
216
        printf("Invalid breakpoint number.\n");
216
        printf("Invalid breakpoint number.\n");
217
        return 0;
217
        return 0;
218
    }
218
    }
219
    ipl = interrupts_disable();
219
    ipl = interrupts_disable();
220
    spinlock_lock(&bkpoint_lock);
220
    spinlock_lock(&bkpoint_lock);
221
 
221
 
222
    cur = &breakpoints[argv->intval];
222
    cur = &breakpoints[argv->intval];
223
    if (!cur->address) {
223
    if (!cur->address) {
224
        printf("Breakpoint does not exist.\n");
224
        printf("Breakpoint does not exist.\n");
225
        spinlock_unlock(&bkpoint_lock);
225
        spinlock_unlock(&bkpoint_lock);
226
        interrupts_restore(ipl);
226
        interrupts_restore(ipl);
227
        return 0;
227
        return 0;
228
    }
228
    }
229
    if ((cur->flags & BKPOINT_INPROG) && (cur->flags & BKPOINT_ONESHOT)) {
229
    if ((cur->flags & BKPOINT_INPROG) && (cur->flags & BKPOINT_ONESHOT)) {
230
        printf("Cannot remove one-shot breakpoint in-progress\n");
230
        printf("Cannot remove one-shot breakpoint in-progress\n");
231
        spinlock_unlock(&bkpoint_lock);
231
        spinlock_unlock(&bkpoint_lock);
232
        interrupts_restore(ipl);
232
        interrupts_restore(ipl);
233
        return 0;
233
        return 0;
234
    }
234
    }
235
    ((uint32_t *)cur->address)[0] = cur->instruction;
235
    ((uint32_t *)cur->address)[0] = cur->instruction;
236
    smc_coherence(((uint32_t *)cur->address)[0]);
236
    smc_coherence(((uint32_t *)cur->address)[0]);
237
    ((uint32_t *)cur->address)[1] = cur->nextinstruction;
237
    ((uint32_t *)cur->address)[1] = cur->nextinstruction;
238
    smc_coherence(((uint32_t *)cur->address)[1]);
238
    smc_coherence(((uint32_t *)cur->address)[1]);
239
 
239
 
240
    cur->address = NULL;
240
    cur->address = NULL;
241
 
241
 
242
    spinlock_unlock(&bkpoint_lock);
242
    spinlock_unlock(&bkpoint_lock);
243
    interrupts_restore(ipl);
243
    interrupts_restore(ipl);
244
    return 1;
244
    return 1;
245
}
245
}
246
 
246
 
247
/** Print table of active breakpoints */
247
/** Print table of active breakpoints */
248
int cmd_print_breakpoints(cmd_arg_t *argv)
248
int cmd_print_breakpoints(cmd_arg_t *argv)
249
{
249
{
250
    unsigned int i;
250
    unsigned int i;
251
    char *symbol;
251
    char *symbol;
252
   
252
   
253
    printf("#  Count Address    INPROG ONESHOT FUNCCALL In symbol\n");
253
    printf("#  Count Address    INPROG ONESHOT FUNCCALL In symbol\n");
254
    printf("-- ----- ---------- ------ ------- -------- ---------\n");
254
    printf("-- ----- ---------- ------ ------- -------- ---------\n");
255
   
255
   
256
    for (i = 0; i < BKPOINTS_MAX; i++)
256
    for (i = 0; i < BKPOINTS_MAX; i++)
257
        if (breakpoints[i].address) {
257
        if (breakpoints[i].address) {
258
            symbol = get_symtab_entry(breakpoints[i].address);
258
            symbol = get_symtab_entry(breakpoints[i].address);
259
           
259
           
260
            printf("%-2u %-5d %#10zx %-6s %-7s %-8s %s\n", i,
260
            printf("%-2u %-5d %#10zx %-6s %-7s %-8s %s\n", i,
261
                breakpoints[i].counter, breakpoints[i].address,
261
                breakpoints[i].counter, breakpoints[i].address,
262
                ((breakpoints[i].flags & BKPOINT_INPROG) ? "true" :
262
                ((breakpoints[i].flags & BKPOINT_INPROG) ? "true" :
263
                "false"), ((breakpoints[i].flags & BKPOINT_ONESHOT)
263
                "false"), ((breakpoints[i].flags & BKPOINT_ONESHOT)
264
                ? "true" : "false"), ((breakpoints[i].flags &
264
                ? "true" : "false"), ((breakpoints[i].flags &
265
                BKPOINT_FUNCCALL) ? "true" : "false"), symbol);
265
                BKPOINT_FUNCCALL) ? "true" : "false"), symbol);
266
        }
266
        }
267
    return 1;
267
    return 1;
268
}
268
}
269
 
269
 
270
/** Initialize debugger */
270
/** Initialize debugger */
271
void debugger_init()
271
void debugger_init()
272
{
272
{
273
    int i;
273
    int i;
274
 
274
 
275
    for (i = 0; i < BKPOINTS_MAX; i++)
275
    for (i = 0; i < BKPOINTS_MAX; i++)
276
        breakpoints[i].address = NULL;
276
        breakpoints[i].address = NULL;
277
   
277
   
278
    cmd_initialize(&bkpts_info);
278
    cmd_initialize(&bkpts_info);
279
    if (!cmd_register(&bkpts_info))
279
    if (!cmd_register(&bkpts_info))
280
        panic("could not register command %s\n", bkpts_info.name);
280
        panic("could not register command %s\n", bkpts_info.name);
281
 
281
 
282
    cmd_initialize(&delbkpt_info);
282
    cmd_initialize(&delbkpt_info);
283
    if (!cmd_register(&delbkpt_info))
283
    if (!cmd_register(&delbkpt_info))
284
        panic("could not register command %s\n", delbkpt_info.name);
284
        panic("could not register command %s\n", delbkpt_info.name);
285
 
285
 
286
    cmd_initialize(&addbkpt_info);
286
    cmd_initialize(&addbkpt_info);
287
    if (!cmd_register(&addbkpt_info))
287
    if (!cmd_register(&addbkpt_info))
288
        panic("could not register command %s\n", addbkpt_info.name);
288
        panic("could not register command %s\n", addbkpt_info.name);
289
 
289
 
290
    cmd_initialize(&addbkpte_info);
290
    cmd_initialize(&addbkpte_info);
291
    if (!cmd_register(&addbkpte_info))
291
    if (!cmd_register(&addbkpte_info))
292
        panic("could not register command %s\n", addbkpte_info.name);
292
        panic("could not register command %s\n", addbkpte_info.name);
293
}
293
}
294
 
294
 
295
/** Handle breakpoint
295
/** Handle breakpoint
296
 *
296
 *
297
 * Find breakpoint in breakpoint table.
297
 * Find breakpoint in breakpoint table.
298
 * If found, call kconsole, set break on next instruction and reexecute.
298
 * If found, call kconsole, set break on next instruction and reexecute.
299
 * If we are on "next instruction", set it back on the first and reexecute.
299
 * If we are on "next instruction", set it back on the first and reexecute.
300
 * If breakpoint not found in breakpoint table, call kconsole and start
300
 * If breakpoint not found in breakpoint table, call kconsole and start
301
 * next instruction.
301
 * next instruction.
302
 */
302
 */
303
void debugger_bpoint(istate_t *istate)
303
void debugger_bpoint(istate_t *istate)
304
{
304
{
305
    bpinfo_t *cur = NULL;
305
    bpinfo_t *cur = NULL;
306
    uintptr_t fireaddr = istate->epc;
306
    uintptr_t fireaddr = istate->epc;
307
    int i;
307
    int i;
308
 
308
 
309
    /* test branch delay slot */
309
    /* test branch delay slot */
310
    if (cp0_cause_read() & 0x80000000)
310
    if (cp0_cause_read() & 0x80000000)
311
        panic("Breakpoint in branch delay slot not supported.\n");
311
        panic("Breakpoint in branch delay slot not supported.\n");
312
 
312
 
313
    spinlock_lock(&bkpoint_lock);
313
    spinlock_lock(&bkpoint_lock);
314
    for (i = 0; i < BKPOINTS_MAX; i++) {
314
    for (i = 0; i < BKPOINTS_MAX; i++) {
315
        /* Normal breakpoint */
315
        /* Normal breakpoint */
316
        if (fireaddr == breakpoints[i].address &&
316
        if (fireaddr == breakpoints[i].address &&
317
            !(breakpoints[i].flags & BKPOINT_REINST)) {
317
            !(breakpoints[i].flags & BKPOINT_REINST)) {
318
            cur = &breakpoints[i];
318
            cur = &breakpoints[i];
319
            break;
319
            break;
320
        }
320
        }
321
        /* Reinst only breakpoint */
321
        /* Reinst only breakpoint */
322
        if ((breakpoints[i].flags & BKPOINT_REINST) &&
322
        if ((breakpoints[i].flags & BKPOINT_REINST) &&
323
            (fireaddr == breakpoints[i].address + sizeof(unative_t))) {
323
            (fireaddr == breakpoints[i].address + sizeof(unative_t))) {
324
            cur = &breakpoints[i];
324
            cur = &breakpoints[i];
325
            break;
325
            break;
326
        }
326
        }
327
    }
327
    }
328
    if (cur) {
328
    if (cur) {
329
        if (cur->flags & BKPOINT_REINST) {
329
        if (cur->flags & BKPOINT_REINST) {
330
            /* Set breakpoint on first instruction */
330
            /* Set breakpoint on first instruction */
331
            ((uint32_t *)cur->address)[0] = 0x0d;
331
            ((uint32_t *)cur->address)[0] = 0x0d;
332
            smc_coherence(((uint32_t *)cur->address)[0]);
332
            smc_coherence(((uint32_t *)cur->address)[0]);
333
            /* Return back the second */
333
            /* Return back the second */
334
            ((uint32_t *)cur->address)[1] = cur->nextinstruction;
334
            ((uint32_t *)cur->address)[1] = cur->nextinstruction;
335
            smc_coherence(((uint32_t *)cur->address)[1]);
335
            smc_coherence(((uint32_t *)cur->address)[1]);
336
            cur->flags &= ~BKPOINT_REINST;
336
            cur->flags &= ~BKPOINT_REINST;
337
            spinlock_unlock(&bkpoint_lock);
337
            spinlock_unlock(&bkpoint_lock);
338
            return;
338
            return;
339
        }
339
        }
340
        if (cur->flags & BKPOINT_INPROG)
340
        if (cur->flags & BKPOINT_INPROG)
341
            printf("Warning: breakpoint recursion\n");
341
            printf("Warning: breakpoint recursion\n");
342
       
342
       
343
        if (!(cur->flags & BKPOINT_FUNCCALL))
343
        if (!(cur->flags & BKPOINT_FUNCCALL))
344
            printf("***Breakpoint %d: %p in %s.\n", i, fireaddr,
344
            printf("***Breakpoint %d: %p in %s.\n", i, fireaddr,
345
                get_symtab_entry(istate->epc));
345
                get_symtab_entry(istate->epc));
346
 
346
 
347
        /* Return first instruction back */
347
        /* Return first instruction back */
348
        ((uint32_t *)cur->address)[0] = cur->instruction;
348
        ((uint32_t *)cur->address)[0] = cur->instruction;
349
        smc_coherence(cur->address);
349
        smc_coherence(cur->address);
350
 
350
 
351
        if (! (cur->flags & BKPOINT_ONESHOT)) {
351
        if (! (cur->flags & BKPOINT_ONESHOT)) {
352
            /* Set Breakpoint on next instruction */
352
            /* Set Breakpoint on next instruction */
353
            ((uint32_t *)cur->address)[1] = 0x0d;
353
            ((uint32_t *)cur->address)[1] = 0x0d;
354
            cur->flags |= BKPOINT_REINST;
354
            cur->flags |= BKPOINT_REINST;
355
        }
355
        }
356
        cur->flags |= BKPOINT_INPROG;
356
        cur->flags |= BKPOINT_INPROG;
357
    } else {
357
    } else {
358
        printf("***Breakpoint %p in %s.\n", fireaddr,
358
        printf("***Breakpoint %p in %s.\n", fireaddr,
359
               get_symtab_entry(fireaddr));
359
               get_symtab_entry(fireaddr));
360
        /* Move on to next instruction */
360
        /* Move on to next instruction */
361
        istate->epc += 4;
361
        istate->epc += 4;
362
    }
362
    }
363
    if (cur)
363
    if (cur)
364
        cur->counter++;
364
        cur->counter++;
365
    if (cur && (cur->flags & BKPOINT_FUNCCALL)) {
365
    if (cur && (cur->flags & BKPOINT_FUNCCALL)) {
366
        /* Allow zero bkfunc, just for counting */
366
        /* Allow zero bkfunc, just for counting */
367
        if (cur->bkfunc)
367
        if (cur->bkfunc)
368
            cur->bkfunc(cur, istate);
368
            cur->bkfunc(cur, istate);
369
    } else {
369
    } else {
370
        printf("***Type 'exit' to exit kconsole.\n");
370
        printf("***Type 'exit' to exit kconsole.\n");
371
        /* This disables all other processors - we are not SMP,
371
        /* This disables all other processors - we are not SMP,
372
         * actually this gets us to cpu_halt, if scheduler() is run
372
         * actually this gets us to cpu_halt, if scheduler() is run
373
         * - we generally do not want scheduler to be run from debug,
373
         * - we generally do not want scheduler to be run from debug,
374
         *   so this is a good idea
374
         *   so this is a good idea
375
         */
375
         */
376
        atomic_set(&haltstate,1);
376
        atomic_set(&haltstate,1);
377
        spinlock_unlock(&bkpoint_lock);
377
        spinlock_unlock(&bkpoint_lock);
378
 
378
 
379
        kconsole("debug");
379
        kconsole("debug");
380
 
380
 
381
        spinlock_lock(&bkpoint_lock);
381
        spinlock_lock(&bkpoint_lock);
382
        atomic_set(&haltstate,0);
382
        atomic_set(&haltstate,0);
383
    }
383
    }
384
    if (cur && cur->address == fireaddr && (cur->flags & BKPOINT_INPROG)) {
384
    if (cur && cur->address == fireaddr && (cur->flags & BKPOINT_INPROG)) {
385
        /* Remove one-shot breakpoint */
385
        /* Remove one-shot breakpoint */
386
        if ((cur->flags & BKPOINT_ONESHOT))
386
        if ((cur->flags & BKPOINT_ONESHOT))
387
            cur->address = NULL;
387
            cur->address = NULL;
388
        /* Remove in-progress flag */
388
        /* Remove in-progress flag */
389
        cur->flags &= ~BKPOINT_INPROG;
389
        cur->flags &= ~BKPOINT_INPROG;
390
    }
390
    }
391
    spinlock_unlock(&bkpoint_lock);
391
    spinlock_unlock(&bkpoint_lock);
392
}
392
}
393
 
393
 
394
/** @}
394
/** @}
395
 */
395
 */
396
 
396