aboutsummaryrefslogtreecommitdiff
path: root/sys/sparc64/sparc64/trap.c
diff options
context:
space:
mode:
authorJake Burkholder <jake@FreeBSD.org>2001-10-20 16:04:39 +0000
committerJake Burkholder <jake@FreeBSD.org>2001-10-20 16:04:39 +0000
commit209cf80d43a40deda9daf3fcb08f466fc1b9556d (patch)
tree440034bd5bbeef65a3eef45cdbf78e72ba4043b5 /sys/sparc64/sparc64/trap.c
parent6c3dcb97354db760c63210bed9eb4b2c31a183c8 (diff)
downloadsrc-209cf80d43a40deda9daf3fcb08f466fc1b9556d.tar.gz
src-209cf80d43a40deda9daf3fcb08f466fc1b9556d.zip
Add support for physical address hardware watchpoints.
Notes
Notes: svn path=/head/; revision=85236
Diffstat (limited to 'sys/sparc64/sparc64/trap.c')
-rw-r--r--sys/sparc64/sparc64/trap.c29
1 files changed, 26 insertions, 3 deletions
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.