From cb7ca29ccfb777175e9f35287c61d53617f45a36 Mon Sep 17 00:00:00 2001 From: jake Date: Sat, 20 Oct 2001 16:04:39 +0000 Subject: [PATCH] Add support for physical address hardware watchpoints. --- sys/sparc64/include/trap.h | 5 +++-- sys/sparc64/sparc64/trap.c | 29 ++++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/sys/sparc64/include/trap.h b/sys/sparc64/include/trap.h index 26651bcb9948..6a06430e45fe 100644 --- a/sys/sparc64/include/trap.h +++ b/sys/sparc64/include/trap.h @@ -64,8 +64,9 @@ #define T_FILL_RET 0x1e #define T_BREAKPOINT 0x1f #define T_SYSCALL 0x20 -#define T_RESTOREWP 0x21 -#define T_SOFT 0x22 +#define T_RSTRWP_PHYS 0x21 +#define T_RSTRWP_VIRT 0x22 +#define T_SOFT 0x23 #define T_KERNEL 0x40 #ifndef LOCORE diff --git a/sys/sparc64/sparc64/trap.c b/sys/sparc64/sparc64/trap.c index e9577a9a5f9e..8498b878721d 100644 --- a/sys/sparc64/sparc64/trap.c +++ b/sys/sparc64/sparc64/trap.c @@ -121,6 +121,8 @@ const char *trap_msg[] = { "fill", "breakpoint", "syscall", + "restore physical watchpoint", + "restore virtual watchpoint", "trap instruction", }; @@ -248,6 +250,20 @@ trap(struct trapframe *tf) if (error == 0) goto out; break; + case T_WATCH_PHYS | T_KERNEL: + TR3("trap: watch phys pa=%#lx tpc=%#lx, tnpc=%#lx", + watch_phys_get(&mask), tf->tf_tpc, tf->tf_tnpc); + PCPU_SET(wp_pstate, (tf->tf_tstate & TSTATE_PSTATE_MASK) >> + TSTATE_PSTATE_SHIFT); + tf->tf_tstate &= ~TSTATE_IE; + wrpr(pstate, rdpr(pstate), PSTATE_IE); + PCPU_SET(wp_insn, *((u_int *)tf->tf_tnpc)); + *((u_int *)tf->tf_tnpc) = 0x91d03002; /* ta %xcc, 2 */ + flush(tf->tf_tnpc); + PCPU_SET(wp_va, watch_phys_get(&mask)); + PCPU_SET(wp_mask, mask); + watch_phys_clear(); + goto out; case T_WATCH_VIRT | T_KERNEL: /* * At the moment, just print the information from the trap, @@ -260,8 +276,8 @@ trap(struct trapframe *tf) * disable interrupts temporarily. * This is obviously fragile and evilish. */ - printf("Virtual watchpoint triggered, tpc=0x%lx, tnpc=0x%lx\n", - tf->tf_tpc, tf->tf_tnpc); + TR3("trap: watch virt pa=%#lx tpc=%#lx, tnpc=%#lx", + watch_virt_get(&mask), tf->tf_tpc, tf->tf_tnpc); PCPU_SET(wp_pstate, (tf->tf_tstate & TSTATE_PSTATE_MASK) >> TSTATE_PSTATE_SHIFT); tf->tf_tstate &= ~TSTATE_IE; @@ -273,7 +289,14 @@ trap(struct trapframe *tf) PCPU_SET(wp_mask, mask); watch_virt_clear(); goto out; - case T_RESTOREWP | T_KERNEL: + case T_RSTRWP_PHYS | T_KERNEL: + tf->tf_tstate = (tf->tf_tstate & ~TSTATE_PSTATE_MASK) | + PCPU_GET(wp_pstate) << TSTATE_PSTATE_SHIFT; + watch_phys_set_mask(PCPU_GET(wp_va), PCPU_GET(wp_mask)); + *(u_int *)tf->tf_tpc = PCPU_GET(wp_insn); + flush(tf->tf_tpc); + goto out; + case T_RSTRWP_VIRT | T_KERNEL: /* * Undo the tweaks tone for T_WATCH, reset the watch point and * contunue execution.