Fix hardware watchpoints and add an extract function so we can easily find

the physical addresses of things (to feed to the physical watchpoint).
This commit is contained in:
eeh 2002-06-14 17:12:05 +00:00
parent 5b5608e8b2
commit 923804f36a

View File

@ -1,4 +1,4 @@
/* $NetBSD: db_interface.c,v 1.64 2002/05/14 02:34:15 eeh Exp $ */
/* $NetBSD: db_interface.c,v 1.65 2002/06/14 17:12:05 eeh Exp $ */
/*
* Copyright (c) 1996-2002 Eduardo Horvath. All rights reserved.
@ -244,6 +244,7 @@ void db_traptrace __P((db_expr_t, int, db_expr_t, char *));
void db_dump_buf __P((db_expr_t, int, db_expr_t, char *));
void db_dump_espcmd __P((db_expr_t, int, db_expr_t, char *));
void db_watch __P((db_expr_t, int, db_expr_t, char *));
void db_pm_extract __P((db_expr_t, int, db_expr_t, char *));
static void db_dump_pmap __P((struct pmap*));
static void db_print_trace_entry __P((struct traptrace *, int));
@ -588,6 +589,23 @@ db_pmap_kernel(addr, have_addr, count, modif)
}
}
void
db_pm_extract(addr, have_addr, count, modif)
db_expr_t addr;
int have_addr;
db_expr_t count;
char *modif;
{
if (have_addr) {
paddr_t pa;
if (pmap_extract(pmap_kernel(), addr, &pa))
db_printf("pa = %llx\n", (long long)pa);
else
db_printf("%p not found\n", (void *)addr);
} else
db_printf("pmap_extract: no address\n");
}
void
db_pmap_cmd(addr, have_addr, count, modif)
@ -911,7 +929,11 @@ db_traptrace(addr, have_addr, count, modif)
}
/*
* Use physical or virtual watchpoint registers -- ugh
* Use physical or virtul watchpoint registers -- ugh
*
* UltraSPARC I and II have both a virtual and physical
* watchpoint register. They are controlled by the LSU
* control register.
*/
void
db_watch(addr, have_addr, count, modif)
@ -921,38 +943,85 @@ db_watch(addr, have_addr, count, modif)
char *modif;
{
int phys = 0;
int read = 0;
int width = 8; /* Default to 8 bytes */
int64_t mask = 0xff;
#define WATCH_VR (1L<<22)
#define WATCH_VW (1L<<21)
#define WATCH_PR (1L<<24)
#define WATCH_PW (1L<<23)
#define WATCH_PM (((u_int64_t)0xffffL)<<33)
#define WATCH_VM (((u_int64_t)0xffffL)<<25)
#define WATCH_VR (1L<<22)
#define WATCH_VW (1L<<21)
#define WATCH_PR (1L<<24)
#define WATCH_PW (1L<<23)
#define WATCH_PM_SHIFT 33
#define WATCH_PM (((u_int64_t)0xffffL)<<WATCH_PM_SHIFT)
#define WATCH_VM_SHIFT 25
#define WATCH_VM (((u_int64_t)0xffffL)<<WATCH_VM_SHIFT)
{
register char c, *cp = modif;
if (modif)
while ((c = *cp++) != 0)
if (c == 'p')
switch (c) {
case 'p':
/* Physical watchpoint */
phys = 1;
break;
case 'r':
/* Trap reads too */
read = 1;
break;
case 'b':
width = 1;
mask = 0x1 << (addr & 0x7);
break;
case 'h':
width = 2;
mask = 0x3 << (addr & 0x6);
break;
case 'l':
width = 4;
mask = 0x7 << (addr & 0x4);
break;
case 'L':
width = 8;
mask = 0xf;
break;
default:
break;
}
}
if (have_addr) {
/* turn on the watchpoint */
int64_t tmp = ldxa(0, ASI_MCCR);
if (phys) {
tmp &= ~(WATCH_PM|WATCH_PR|WATCH_PW);
tmp &= ~WATCH_PM;
tmp |= WATCH_PW | (mask << WATCH_PM_SHIFT);
if (read) tmp |= WATCH_PR;
stxa(PHYSICAL_WATCHPOINT, ASI_DMMU, addr);
db_printf("Setting physical watchpoint to %llx-%llx\n",
(long long)addr, (long long)addr + width);
} else {
tmp &= ~(WATCH_VM|WATCH_VR|WATCH_VW);
tmp &= ~WATCH_VM;
tmp |= WATCH_VW | (mask << WATCH_VM_SHIFT);
if (read) tmp |= WATCH_VR;
stxa(VIRTUAL_WATCHPOINT, ASI_DMMU, addr);
db_printf("Setting virtual watchpoint to %llx-%llx\n",
(long long)addr, (long long)addr + width);
}
stxa(0, ASI_MCCR, tmp);
} else {
/* turn off the watchpoint */
int64_t tmp = ldxa(0, ASI_MCCR);
if (phys) tmp &= ~(WATCH_PM);
else tmp &= ~(WATCH_VM);
if (phys) {
tmp &= ~(WATCH_PM|WATCH_PR|WATCH_PW);
db_printf("Disabling physical watchpoint\n");
} else {
tmp &= ~(WATCH_VM|WATCH_VR|WATCH_VW);
db_printf("Disabling virtual watchpoint\n");
}
stxa(0, ASI_MCCR, tmp);
}
}
@ -986,6 +1055,7 @@ const struct db_command db_machine_command_table[] = {
#if NESP_SBUS
{ "esp", db_esp, 0, 0 },
#endif
{ "extract", db_pm_extract, 0, 0 },
{ "fpstate", db_dump_fpstate,0, 0 },
{ "kmap", db_pmap_kernel, 0, 0 },
{ "lock", db_lock, 0, 0 },