16fc729afSOlivier Houchard /* $NetBSD: db_interface.c,v 1.33 2003/08/25 04:51:10 mrg Exp $ */
26fc729afSOlivier Houchard
3d8315c79SWarner Losh /*-
46fc729afSOlivier Houchard * Copyright (c) 1996 Scott K. Stevens
56fc729afSOlivier Houchard *
66fc729afSOlivier Houchard * Mach Operating System
76fc729afSOlivier Houchard * Copyright (c) 1991,1990 Carnegie Mellon University
86fc729afSOlivier Houchard * All Rights Reserved.
96fc729afSOlivier Houchard *
106fc729afSOlivier Houchard * Permission to use, copy, modify and distribute this software and its
116fc729afSOlivier Houchard * documentation is hereby granted, provided that both the copyright
126fc729afSOlivier Houchard * notice and this permission notice appear in all copies of the
136fc729afSOlivier Houchard * software, derivative works or modified versions, and any portions
146fc729afSOlivier Houchard * thereof, and that both notices appear in supporting documentation.
156fc729afSOlivier Houchard *
166fc729afSOlivier Houchard * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
176fc729afSOlivier Houchard * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
186fc729afSOlivier Houchard * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
196fc729afSOlivier Houchard *
206fc729afSOlivier Houchard * Carnegie Mellon requests users of this software to return to
216fc729afSOlivier Houchard *
226fc729afSOlivier Houchard * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
236fc729afSOlivier Houchard * School of Computer Science
246fc729afSOlivier Houchard * Carnegie Mellon University
256fc729afSOlivier Houchard * Pittsburgh PA 15213-3890
266fc729afSOlivier Houchard *
276fc729afSOlivier Houchard * any improvements or extensions that they make and grant Carnegie the
286fc729afSOlivier Houchard * rights to redistribute these changes.
296fc729afSOlivier Houchard *
306fc729afSOlivier Houchard * From: db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU)
316fc729afSOlivier Houchard */
326fc729afSOlivier Houchard
336fc729afSOlivier Houchard /*
346fc729afSOlivier Houchard * Interface to new debugger.
356fc729afSOlivier Houchard */
366fc729afSOlivier Houchard
376fc729afSOlivier Houchard #include "opt_ddb.h"
386fc729afSOlivier Houchard
396fc729afSOlivier Houchard #include <sys/param.h>
40a89156f5SMichal Meloun #include <sys/cons.h>
416fc729afSOlivier Houchard #include <sys/proc.h>
426fc729afSOlivier Houchard #include <sys/reboot.h>
436fc729afSOlivier Houchard #include <sys/exec.h>
449ebe15a1SOlivier Houchard #ifdef KDB
459ebe15a1SOlivier Houchard #include <sys/kdb.h>
469ebe15a1SOlivier Houchard #endif
476fc729afSOlivier Houchard
486fc729afSOlivier Houchard #include <vm/vm.h>
496fc729afSOlivier Houchard #include <vm/pmap.h>
506fc729afSOlivier Houchard #include <vm/vm_map.h>
516fc729afSOlivier Houchard #include <vm/vm_extern.h>
526fc729afSOlivier Houchard
536fc729afSOlivier Houchard #include <machine/db_machdep.h>
54a89156f5SMichal Meloun #include <machine/cpu.h>
55232e189aSZbigniew Bodek #include <machine/machdep.h>
566fc729afSOlivier Houchard #include <machine/vmparam.h>
576fc729afSOlivier Houchard
586fc729afSOlivier Houchard #include <ddb/ddb.h>
596fc729afSOlivier Houchard #include <ddb/db_access.h>
606fc729afSOlivier Houchard #include <ddb/db_command.h>
616fc729afSOlivier Houchard #include <ddb/db_output.h>
626fc729afSOlivier Houchard #include <ddb/db_variables.h>
636fc729afSOlivier Houchard #include <ddb/db_sym.h>
64a89156f5SMichal Meloun
652f6d0d8fSOlivier Houchard static int nil = 0;
666fc729afSOlivier Houchard
676fc729afSOlivier Houchard int db_access_und_sp (struct db_variable *, db_expr_t *, int);
686fc729afSOlivier Houchard int db_access_abt_sp (struct db_variable *, db_expr_t *, int);
696fc729afSOlivier Houchard int db_access_irq_sp (struct db_variable *, db_expr_t *, int);
706fc729afSOlivier Houchard
7131897fe8SOlivier Houchard static db_varfcn_t db_frame;
7231897fe8SOlivier Houchard
732f6d0d8fSOlivier Houchard #define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x)
746fc729afSOlivier Houchard struct db_variable db_regs[] = {
7531897fe8SOlivier Houchard { "spsr", DB_OFFSET(tf_spsr), db_frame },
7631897fe8SOlivier Houchard { "r0", DB_OFFSET(tf_r0), db_frame },
7731897fe8SOlivier Houchard { "r1", DB_OFFSET(tf_r1), db_frame },
7831897fe8SOlivier Houchard { "r2", DB_OFFSET(tf_r2), db_frame },
7931897fe8SOlivier Houchard { "r3", DB_OFFSET(tf_r3), db_frame },
8031897fe8SOlivier Houchard { "r4", DB_OFFSET(tf_r4), db_frame },
8131897fe8SOlivier Houchard { "r5", DB_OFFSET(tf_r5), db_frame },
8231897fe8SOlivier Houchard { "r6", DB_OFFSET(tf_r6), db_frame },
8331897fe8SOlivier Houchard { "r7", DB_OFFSET(tf_r7), db_frame },
8431897fe8SOlivier Houchard { "r8", DB_OFFSET(tf_r8), db_frame },
8531897fe8SOlivier Houchard { "r9", DB_OFFSET(tf_r9), db_frame },
8631897fe8SOlivier Houchard { "r10", DB_OFFSET(tf_r10), db_frame },
8731897fe8SOlivier Houchard { "r11", DB_OFFSET(tf_r11), db_frame },
8831897fe8SOlivier Houchard { "r12", DB_OFFSET(tf_r12), db_frame },
8931897fe8SOlivier Houchard { "usr_sp", DB_OFFSET(tf_usr_sp), db_frame },
9031897fe8SOlivier Houchard { "usr_lr", DB_OFFSET(tf_usr_lr), db_frame },
9131897fe8SOlivier Houchard { "svc_sp", DB_OFFSET(tf_svc_sp), db_frame },
9231897fe8SOlivier Houchard { "svc_lr", DB_OFFSET(tf_svc_lr), db_frame },
9331897fe8SOlivier Houchard { "pc", DB_OFFSET(tf_pc), db_frame },
946fc729afSOlivier Houchard { "und_sp", &nil, db_access_und_sp, },
956fc729afSOlivier Houchard { "abt_sp", &nil, db_access_abt_sp, },
966fc729afSOlivier Houchard { "irq_sp", &nil, db_access_irq_sp, },
976fc729afSOlivier Houchard };
986fc729afSOlivier Houchard
9933495e5dSPedro F. Giffuni struct db_variable *db_eregs = db_regs + nitems(db_regs);
1006fc729afSOlivier Houchard
1016fc729afSOlivier Houchard int
db_access_und_sp(struct db_variable * vp,db_expr_t * valp,int rw)1026fc729afSOlivier Houchard db_access_und_sp(struct db_variable *vp, db_expr_t *valp, int rw)
1036fc729afSOlivier Houchard {
1046fc729afSOlivier Houchard
10531897fe8SOlivier Houchard if (rw == DB_VAR_GET) {
1066fc729afSOlivier Houchard *valp = get_stackptr(PSR_UND32_MODE);
10731897fe8SOlivier Houchard return (1);
10831897fe8SOlivier Houchard }
1096fc729afSOlivier Houchard return (0);
1106fc729afSOlivier Houchard }
1116fc729afSOlivier Houchard
1126fc729afSOlivier Houchard int
db_access_abt_sp(struct db_variable * vp,db_expr_t * valp,int rw)1136fc729afSOlivier Houchard db_access_abt_sp(struct db_variable *vp, db_expr_t *valp, int rw)
1146fc729afSOlivier Houchard {
1156fc729afSOlivier Houchard
11631897fe8SOlivier Houchard if (rw == DB_VAR_GET) {
1176fc729afSOlivier Houchard *valp = get_stackptr(PSR_ABT32_MODE);
11831897fe8SOlivier Houchard return (1);
11931897fe8SOlivier Houchard }
1206fc729afSOlivier Houchard return (0);
1216fc729afSOlivier Houchard }
1226fc729afSOlivier Houchard
1236fc729afSOlivier Houchard int
db_access_irq_sp(struct db_variable * vp,db_expr_t * valp,int rw)1246fc729afSOlivier Houchard db_access_irq_sp(struct db_variable *vp, db_expr_t *valp, int rw)
1256fc729afSOlivier Houchard {
1266fc729afSOlivier Houchard
12731897fe8SOlivier Houchard if (rw == DB_VAR_GET) {
1286fc729afSOlivier Houchard *valp = get_stackptr(PSR_IRQ32_MODE);
12931897fe8SOlivier Houchard return (1);
13031897fe8SOlivier Houchard }
1316fc729afSOlivier Houchard return (0);
1326fc729afSOlivier Houchard }
1336fc729afSOlivier Houchard
db_frame(struct db_variable * vp,db_expr_t * valp,int rw)13431897fe8SOlivier Houchard int db_frame(struct db_variable *vp, db_expr_t *valp, int rw)
13531897fe8SOlivier Houchard {
13631897fe8SOlivier Houchard int *reg;
13731897fe8SOlivier Houchard
13831897fe8SOlivier Houchard if (kdb_frame == NULL)
13931897fe8SOlivier Houchard return (0);
14031897fe8SOlivier Houchard
14131897fe8SOlivier Houchard reg = (int *)((uintptr_t)kdb_frame + (db_expr_t)vp->valuep);
14231897fe8SOlivier Houchard if (rw == DB_VAR_GET)
14331897fe8SOlivier Houchard *valp = *reg;
14431897fe8SOlivier Houchard else
14531897fe8SOlivier Houchard *reg = *valp;
14631897fe8SOlivier Houchard return (1);
14731897fe8SOlivier Houchard }
14831897fe8SOlivier Houchard
1496fc729afSOlivier Houchard void
db_show_mdpcpu(struct pcpu * pc)1506fc729afSOlivier Houchard db_show_mdpcpu(struct pcpu *pc)
1516fc729afSOlivier Houchard {
152514ba655SSvatopluk Kraus
153514ba655SSvatopluk Kraus db_printf("curpmap = %p\n", pc->pc_curpmap);
1546fc729afSOlivier Houchard }
1555c2967f6SMichal Meloun
1566fc729afSOlivier Houchard int
db_validate_address(vm_offset_t addr)1576fc729afSOlivier Houchard db_validate_address(vm_offset_t addr)
1586fc729afSOlivier Houchard {
1596fc729afSOlivier Houchard struct proc *p = curproc;
1606fc729afSOlivier Houchard struct pmap *pmap;
1616fc729afSOlivier Houchard
1626fc729afSOlivier Houchard if (!p || !p->p_vmspace || !p->p_vmspace->vm_map.pmap ||
1636fc729afSOlivier Houchard #ifndef ARM32_NEW_VM_LAYOUT
1646fc729afSOlivier Houchard addr >= VM_MAXUSER_ADDRESS
1656fc729afSOlivier Houchard #else
1666fc729afSOlivier Houchard addr >= VM_MIN_KERNEL_ADDRESS
1676fc729afSOlivier Houchard #endif
1686fc729afSOlivier Houchard )
169480f7464SSvatopluk Kraus pmap = kernel_pmap;
1706fc729afSOlivier Houchard else
1716fc729afSOlivier Houchard pmap = p->p_vmspace->vm_map.pmap;
1726fc729afSOlivier Houchard
173*afb1a3e3SJohn Baldwin return (pmap_extract(pmap, addr) == 0);
1746fc729afSOlivier Houchard }
1756fc729afSOlivier Houchard
1766fc729afSOlivier Houchard /*
1776fc729afSOlivier Houchard * Read bytes from kernel address space for debugger.
1786fc729afSOlivier Houchard */
1792f6d0d8fSOlivier Houchard int
db_read_bytes(vm_offset_t addr,size_t size,char * data)180bf043855SJohn Baldwin db_read_bytes(vm_offset_t addr, size_t size, char *data)
1816fc729afSOlivier Houchard {
1826fc729afSOlivier Houchard char *src = (char *)addr;
1836fc729afSOlivier Houchard
1846fc729afSOlivier Houchard if (db_validate_address((u_int)src)) {
1856fc729afSOlivier Houchard db_printf("address %p is invalid\n", src);
1862f6d0d8fSOlivier Houchard return (-1);
1876fc729afSOlivier Houchard }
1886fc729afSOlivier Houchard
1896fc729afSOlivier Houchard if (size == 4 && (addr & 3) == 0 && ((uintptr_t)data & 3) == 0) {
1906fc729afSOlivier Houchard *((int*)data) = *((int*)src);
1912f6d0d8fSOlivier Houchard return (0);
1926fc729afSOlivier Houchard }
1936fc729afSOlivier Houchard
1946fc729afSOlivier Houchard if (size == 2 && (addr & 1) == 0 && ((uintptr_t)data & 1) == 0) {
1956fc729afSOlivier Houchard *((short*)data) = *((short*)src);
1962f6d0d8fSOlivier Houchard return (0);
1976fc729afSOlivier Houchard }
1986fc729afSOlivier Houchard
1996fc729afSOlivier Houchard while (size-- > 0) {
2006fc729afSOlivier Houchard if (db_validate_address((u_int)src)) {
2016fc729afSOlivier Houchard db_printf("address %p is invalid\n", src);
2022f6d0d8fSOlivier Houchard return (-1);
2036fc729afSOlivier Houchard }
2046fc729afSOlivier Houchard *data++ = *src++;
2056fc729afSOlivier Houchard }
2062f6d0d8fSOlivier Houchard return (0);
2076fc729afSOlivier Houchard }
2086fc729afSOlivier Houchard
2096fc729afSOlivier Houchard /*
2106fc729afSOlivier Houchard * Write bytes to kernel address space for debugger.
2116fc729afSOlivier Houchard */
2122f6d0d8fSOlivier Houchard int
db_write_bytes(vm_offset_t addr,size_t size,char * data)2136fc729afSOlivier Houchard db_write_bytes(vm_offset_t addr, size_t size, char *data)
2146fc729afSOlivier Houchard {
2156fc729afSOlivier Houchard char *dst;
2166fc729afSOlivier Houchard size_t loop;
2176fc729afSOlivier Houchard
2186fc729afSOlivier Houchard dst = (char *)addr;
2196fc729afSOlivier Houchard if (db_validate_address((u_int)dst)) {
2206fc729afSOlivier Houchard db_printf("address %p is invalid\n", dst);
2212f6d0d8fSOlivier Houchard return (0);
2226fc729afSOlivier Houchard }
2236fc729afSOlivier Houchard
2246fc729afSOlivier Houchard if (size == 4 && (addr & 3) == 0 && ((uintptr_t)data & 3) == 0)
2256fc729afSOlivier Houchard *((int*)dst) = *((int*)data);
2266fc729afSOlivier Houchard else
2276fc729afSOlivier Houchard if (size == 2 && (addr & 1) == 0 && ((uintptr_t)data & 1) == 0)
2286fc729afSOlivier Houchard *((short*)dst) = *((short*)data);
2296fc729afSOlivier Houchard else {
2306fc729afSOlivier Houchard loop = size;
2316fc729afSOlivier Houchard while (loop-- > 0) {
2326fc729afSOlivier Houchard if (db_validate_address((u_int)dst)) {
2336fc729afSOlivier Houchard db_printf("address %p is invalid\n", dst);
2342f6d0d8fSOlivier Houchard return (-1);
2356fc729afSOlivier Houchard }
2366fc729afSOlivier Houchard *dst++ = *data++;
2376fc729afSOlivier Houchard }
2386fc729afSOlivier Houchard }
2396fc729afSOlivier Houchard
2406fc729afSOlivier Houchard /* make sure the caches and memory are in sync */
241a89156f5SMichal Meloun icache_sync(addr, size);
2426fc729afSOlivier Houchard
2436fc729afSOlivier Houchard /* In case the current page tables have been modified ... */
244a89156f5SMichal Meloun tlb_flush_all();
2456fc729afSOlivier Houchard return (0);
2466fc729afSOlivier Houchard }
2476fc729afSOlivier Houchard
2489ebe15a1SOlivier Houchard static u_int
db_fetch_reg(int reg)2499ebe15a1SOlivier Houchard db_fetch_reg(int reg)
2509ebe15a1SOlivier Houchard {
2519ebe15a1SOlivier Houchard
2529ebe15a1SOlivier Houchard switch (reg) {
2539ebe15a1SOlivier Houchard case 0:
2549ebe15a1SOlivier Houchard return (kdb_frame->tf_r0);
2559ebe15a1SOlivier Houchard case 1:
2569ebe15a1SOlivier Houchard return (kdb_frame->tf_r1);
2579ebe15a1SOlivier Houchard case 2:
2589ebe15a1SOlivier Houchard return (kdb_frame->tf_r2);
2599ebe15a1SOlivier Houchard case 3:
2609ebe15a1SOlivier Houchard return (kdb_frame->tf_r3);
2619ebe15a1SOlivier Houchard case 4:
2629ebe15a1SOlivier Houchard return (kdb_frame->tf_r4);
2639ebe15a1SOlivier Houchard case 5:
2649ebe15a1SOlivier Houchard return (kdb_frame->tf_r5);
2659ebe15a1SOlivier Houchard case 6:
2669ebe15a1SOlivier Houchard return (kdb_frame->tf_r6);
2679ebe15a1SOlivier Houchard case 7:
2689ebe15a1SOlivier Houchard return (kdb_frame->tf_r7);
2699ebe15a1SOlivier Houchard case 8:
2709ebe15a1SOlivier Houchard return (kdb_frame->tf_r8);
2719ebe15a1SOlivier Houchard case 9:
2729ebe15a1SOlivier Houchard return (kdb_frame->tf_r9);
2739ebe15a1SOlivier Houchard case 10:
2749ebe15a1SOlivier Houchard return (kdb_frame->tf_r10);
2759ebe15a1SOlivier Houchard case 11:
2769ebe15a1SOlivier Houchard return (kdb_frame->tf_r11);
2779ebe15a1SOlivier Houchard case 12:
2789ebe15a1SOlivier Houchard return (kdb_frame->tf_r12);
2799ebe15a1SOlivier Houchard case 13:
2809ebe15a1SOlivier Houchard return (kdb_frame->tf_svc_sp);
2819ebe15a1SOlivier Houchard case 14:
2829ebe15a1SOlivier Houchard return (kdb_frame->tf_svc_lr);
2839ebe15a1SOlivier Houchard case 15:
2849ebe15a1SOlivier Houchard return (kdb_frame->tf_pc);
2859ebe15a1SOlivier Houchard default:
2869ebe15a1SOlivier Houchard panic("db_fetch_reg: botch");
2879ebe15a1SOlivier Houchard }
2889ebe15a1SOlivier Houchard }
2899ebe15a1SOlivier Houchard
290232e189aSZbigniew Bodek static u_int
db_branch_taken_read_int(void * cookie __unused,vm_offset_t offset,u_int * val)291232e189aSZbigniew Bodek db_branch_taken_read_int(void *cookie __unused, vm_offset_t offset, u_int *val)
292232e189aSZbigniew Bodek {
293232e189aSZbigniew Bodek u_int ret;
294232e189aSZbigniew Bodek
295232e189aSZbigniew Bodek db_read_bytes(offset, 4, (char *)&ret);
296232e189aSZbigniew Bodek *val = ret;
297232e189aSZbigniew Bodek
298232e189aSZbigniew Bodek return (0);
299232e189aSZbigniew Bodek }
300232e189aSZbigniew Bodek
301232e189aSZbigniew Bodek static u_int
db_branch_taken_fetch_reg(void * cookie __unused,int reg)302232e189aSZbigniew Bodek db_branch_taken_fetch_reg(void *cookie __unused, int reg)
303232e189aSZbigniew Bodek {
304232e189aSZbigniew Bodek
305232e189aSZbigniew Bodek return (db_fetch_reg(reg));
306232e189aSZbigniew Bodek }
307232e189aSZbigniew Bodek
3089ebe15a1SOlivier Houchard u_int
branch_taken(u_int insn,db_addr_t pc)3099ebe15a1SOlivier Houchard branch_taken(u_int insn, db_addr_t pc)
3109ebe15a1SOlivier Houchard {
311232e189aSZbigniew Bodek register_t new_pc;
312232e189aSZbigniew Bodek int ret;
3139ebe15a1SOlivier Houchard
314232e189aSZbigniew Bodek ret = arm_predict_branch(NULL, insn, (register_t)pc, &new_pc,
315232e189aSZbigniew Bodek db_branch_taken_fetch_reg, db_branch_taken_read_int);
316f0fe5e91SOlivier Houchard
317232e189aSZbigniew Bodek if (ret != 0)
318232e189aSZbigniew Bodek kdb_reenter();
319232e189aSZbigniew Bodek
320232e189aSZbigniew Bodek return (new_pc);
3219ebe15a1SOlivier Houchard }
322