summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorjlemon <jlemon@FreeBSD.org>1999-07-09 04:16:00 +0000
committerjlemon <jlemon@FreeBSD.org>1999-07-09 04:16:00 +0000
commitfb9048b07bd1c35bc75d6a5619a8a66c0cf40b4f (patch)
tree5035c891109a8a7303adbff335bde82a04b1c903 /sys/amd64
parent8402d41bdeafb13d775baf552ba6f1faba0aadca (diff)
downloadFreeBSD-src-fb9048b07bd1c35bc75d6a5619a8a66c0cf40b4f.zip
FreeBSD-src-fb9048b07bd1c35bc75d6a5619a8a66c0cf40b4f.tar.gz
Implement support for hardware debug registers on the i386.
Submitted by: Brian Dean <brdean@unx.sas.com>
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/cpu_switch.S40
-rw-r--r--sys/amd64/amd64/genassym.c9
-rw-r--r--sys/amd64/amd64/machdep.c83
-rw-r--r--sys/amd64/amd64/swtch.s40
-rw-r--r--sys/amd64/include/md_var.h4
-rw-r--r--sys/amd64/include/pcb.h11
-rw-r--r--sys/amd64/include/ptrace.h4
-rw-r--r--sys/amd64/include/reg.h15
8 files changed, 198 insertions, 8 deletions
diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S
index 428b0ae..82c9737 100644
--- a/sys/amd64/amd64/cpu_switch.S
+++ b/sys/amd64/amd64/cpu_switch.S
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: swtch.s,v 1.82 1999/06/01 18:19:45 jlemon Exp $
+ * $Id: swtch.s,v 1.83 1999/07/03 06:33:24 alc Exp $
*/
#include "npx.h"
@@ -480,6 +480,26 @@ ENTRY(cpu_switch)
movl %edi,PCB_EDI(%edx)
movl %gs,PCB_GS(%edx)
+ /* test if debug regisers should be saved */
+ movb PCB_FLAGS(%edx),%al
+ andb $PCB_DBREGS,%al
+ jz 1f /* no, skip over */
+ movl %dr7,%eax /* yes, do the save */
+ movl %eax,PCB_DR7(%edx)
+ andl $0x0000ff00, %eax /* disable all watchpoints */
+ movl %eax,%dr7
+ movl %dr6,%eax
+ movl %eax,PCB_DR6(%edx)
+ movl %dr3,%eax
+ movl %eax,PCB_DR3(%edx)
+ movl %dr2,%eax
+ movl %eax,PCB_DR2(%edx)
+ movl %dr1,%eax
+ movl %eax,PCB_DR1(%edx)
+ movl %dr0,%eax
+ movl %eax,PCB_DR0(%edx)
+1:
+
#ifdef SMP
movl _mp_lock, %eax
/* XXX FIXME: we should be saving the local APIC TPR */
@@ -718,6 +738,24 @@ swtch_com:
cpu_switch_load_gs:
movl PCB_GS(%edx),%gs
+ /* test if debug regisers should be restored */
+ movb PCB_FLAGS(%edx),%al
+ andb $PCB_DBREGS,%al
+ jz 1f /* no, skip over */
+ movl PCB_DR6(%edx),%eax /* yes, do the restore */
+ movl %eax,%dr6
+ movl PCB_DR3(%edx),%eax
+ movl %eax,%dr3
+ movl PCB_DR2(%edx),%eax
+ movl %eax,%dr2
+ movl PCB_DR1(%edx),%eax
+ movl %eax,%dr1
+ movl PCB_DR0(%edx),%eax
+ movl %eax,%dr0
+ movl PCB_DR7(%edx),%eax
+ movl %eax,%dr7
+1:
+
sti
ret
diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c
index 3e92787..dc5a18d 100644
--- a/sys/amd64/amd64/genassym.c
+++ b/sys/amd64/amd64/genassym.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)genassym.c 5.11 (Berkeley) 5/10/91
- * $Id: genassym.c,v 1.71 1999/06/28 09:21:41 peter Exp $
+ * $Id: genassym.c,v 1.72 1999/07/06 07:13:32 cracauer Exp $
*/
#include "opt_user_ldt.h"
@@ -128,6 +128,13 @@ main()
printf("#define\tTSS_ESP0 %#x\n", OS(i386tss, tss_esp0));
printf("#define\tPCB_USERLDT %#x\n", OS(pcb, pcb_ldt));
printf("#define\tPCB_GS %#x\n", OS(pcb, pcb_gs));
+ printf("#define\tPCB_DR0 %#x\n", OS(pcb, pcb_dr0));
+ printf("#define\tPCB_DR1 %#x\n", OS(pcb, pcb_dr1));
+ printf("#define\tPCB_DR2 %#x\n", OS(pcb, pcb_dr2));
+ printf("#define\tPCB_DR3 %#x\n", OS(pcb, pcb_dr3));
+ printf("#define\tPCB_DR6 %#x\n", OS(pcb, pcb_dr6));
+ printf("#define\tPCB_DR7 %#x\n", OS(pcb, pcb_dr7));
+ printf("#define\tPCB_DBREGS %#x\n", PCB_DBREGS );
printf("#define\tPCB_EXT %#x\n", OS(pcb, pcb_ext));
#ifdef SMP
printf("#define\tPCB_MPNEST %#x\n", OS(pcb, pcb_mpnest));
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index ec11c98..423de12 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
- * $Id: machdep.c,v 1.353 1999/07/06 07:13:33 cracauer Exp $
+ * $Id: machdep.c,v 1.354 1999/07/08 06:05:48 mckusick Exp $
*/
#include "apm.h"
@@ -1927,6 +1927,87 @@ set_fpregs(p, fpregs)
return (0);
}
+int
+fill_dbregs(p, dbregs)
+ struct proc *p;
+ struct dbreg *dbregs;
+{
+ struct pcb *pcb;
+
+ pcb = &p->p_addr->u_pcb;
+ dbregs->dr0 = pcb->pcb_dr0;
+ dbregs->dr1 = pcb->pcb_dr1;
+ dbregs->dr2 = pcb->pcb_dr2;
+ dbregs->dr3 = pcb->pcb_dr3;
+ dbregs->dr4 = 0;
+ dbregs->dr5 = 0;
+ dbregs->dr6 = pcb->pcb_dr6;
+ dbregs->dr7 = pcb->pcb_dr7;
+ return (0);
+}
+
+int
+set_dbregs(p, dbregs)
+ struct proc *p;
+ struct dbreg *dbregs;
+{
+ struct pcb *pcb;
+
+ pcb = &p->p_addr->u_pcb;
+
+ /*
+ * Don't let a process set a breakpoint that is not within the
+ * process's address space. If a process could do this, it
+ * could halt the system by setting a breakpoint in the kernel
+ * (if ddb was enabled). Thus, we need to check to make sure
+ * that no breakpoints are being enabled for addresses outside
+ * process's address space, unless, perhaps, we were called by
+ * uid 0.
+ *
+ * XXX - what about when the watched area of the user's
+ * address space is written into from within the kernel
+ * ... wouldn't that still cause a breakpoint to be generated
+ * from within kernel mode?
+ */
+
+ if (p->p_cred->pc_ucred->cr_uid != 0) {
+ if (dbregs->dr7 & 0x3) {
+ /* dr0 is enabled */
+ if (dbregs->dr0 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+
+ if (dbregs->dr7 & (0x3<<2)) {
+ /* dr1 is enabled */
+ if (dbregs->dr1 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+
+ if (dbregs->dr7 & (0x3<<4)) {
+ /* dr2 is enabled */
+ if (dbregs->dr2 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+
+ if (dbregs->dr7 & (0x3<<6)) {
+ /* dr3 is enabled */
+ if (dbregs->dr3 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+ }
+
+ pcb->pcb_dr0 = dbregs->dr0;
+ pcb->pcb_dr1 = dbregs->dr1;
+ pcb->pcb_dr2 = dbregs->dr2;
+ pcb->pcb_dr3 = dbregs->dr3;
+ pcb->pcb_dr6 = dbregs->dr6;
+ pcb->pcb_dr7 = dbregs->dr7;
+
+ pcb->pcb_flags |= PCB_DBREGS;
+
+ return (0);
+}
+
#ifndef DDB
void
Debugger(const char *msg)
diff --git a/sys/amd64/amd64/swtch.s b/sys/amd64/amd64/swtch.s
index 428b0ae..82c9737 100644
--- a/sys/amd64/amd64/swtch.s
+++ b/sys/amd64/amd64/swtch.s
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: swtch.s,v 1.82 1999/06/01 18:19:45 jlemon Exp $
+ * $Id: swtch.s,v 1.83 1999/07/03 06:33:24 alc Exp $
*/
#include "npx.h"
@@ -480,6 +480,26 @@ ENTRY(cpu_switch)
movl %edi,PCB_EDI(%edx)
movl %gs,PCB_GS(%edx)
+ /* test if debug regisers should be saved */
+ movb PCB_FLAGS(%edx),%al
+ andb $PCB_DBREGS,%al
+ jz 1f /* no, skip over */
+ movl %dr7,%eax /* yes, do the save */
+ movl %eax,PCB_DR7(%edx)
+ andl $0x0000ff00, %eax /* disable all watchpoints */
+ movl %eax,%dr7
+ movl %dr6,%eax
+ movl %eax,PCB_DR6(%edx)
+ movl %dr3,%eax
+ movl %eax,PCB_DR3(%edx)
+ movl %dr2,%eax
+ movl %eax,PCB_DR2(%edx)
+ movl %dr1,%eax
+ movl %eax,PCB_DR1(%edx)
+ movl %dr0,%eax
+ movl %eax,PCB_DR0(%edx)
+1:
+
#ifdef SMP
movl _mp_lock, %eax
/* XXX FIXME: we should be saving the local APIC TPR */
@@ -718,6 +738,24 @@ swtch_com:
cpu_switch_load_gs:
movl PCB_GS(%edx),%gs
+ /* test if debug regisers should be restored */
+ movb PCB_FLAGS(%edx),%al
+ andb $PCB_DBREGS,%al
+ jz 1f /* no, skip over */
+ movl PCB_DR6(%edx),%eax /* yes, do the restore */
+ movl %eax,%dr6
+ movl PCB_DR3(%edx),%eax
+ movl %eax,%dr3
+ movl PCB_DR2(%edx),%eax
+ movl %eax,%dr2
+ movl PCB_DR1(%edx),%eax
+ movl %eax,%dr1
+ movl PCB_DR0(%edx),%eax
+ movl %eax,%dr0
+ movl PCB_DR7(%edx),%eax
+ movl %eax,%dr7
+1:
+
sti
ret
diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h
index 35b6545..491eb46 100644
--- a/sys/amd64/include/md_var.h
+++ b/sys/amd64/include/md_var.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: md_var.h,v 1.28 1999/01/08 16:29:58 bde Exp $
+ * $Id: md_var.h,v 1.29 1999/04/28 01:04:02 luoqi Exp $
*/
#ifndef _MACHINE_MD_VAR_H_
@@ -64,6 +64,7 @@ typedef void alias_for_inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss));
struct proc;
struct reg;
struct fpreg;
+struct dbreg;
void bcopyb __P((const void *from, void *to, size_t len));
void busdma_swi __P((void));
@@ -80,6 +81,7 @@ void doreti_popl_fs __P((void)) __asm(__STRING(doreti_popl_fs));
void doreti_popl_fs_fault __P((void)) __asm(__STRING(doreti_popl_fs_fault));
int fill_fpregs __P((struct proc *, struct fpreg *));
int fill_regs __P((struct proc *p, struct reg *regs));
+int fill_dbregs __P((struct proc *p, struct dbreg *dbregs));
void fillw __P((int /*u_short*/ pat, void *base, size_t cnt));
void i486_bzero __P((void *buf, size_t len));
void i586_bcopy __P((const void *from, void *to, size_t len));
diff --git a/sys/amd64/include/pcb.h b/sys/amd64/include/pcb.h
index 2dbc707..5cee924 100644
--- a/sys/amd64/include/pcb.h
+++ b/sys/amd64/include/pcb.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)pcb.h 5.10 (Berkeley) 5/12/91
- * $Id: pcb.h,v 1.27 1999/04/28 01:04:05 luoqi Exp $
+ * $Id: pcb.h,v 1.28 1999/06/01 18:20:06 jlemon Exp $
*/
#ifndef _I386_PCB_H_
@@ -54,11 +54,20 @@ struct pcb {
int pcb_esp;
int pcb_ebx;
int pcb_eip;
+
+ int pcb_dr0;
+ int pcb_dr1;
+ int pcb_dr2;
+ int pcb_dr3;
+ int pcb_dr6;
+ int pcb_dr7;
+
caddr_t pcb_ldt; /* per process (user) LDT */
int pcb_ldt_len; /* number of LDT entries */
struct save87 pcb_savefpu; /* floating point state for 287/387 */
u_char pcb_flags;
#define FP_SOFTFP 0x01 /* process using software fltng pnt emulator */
+#define PCB_DBREGS 0x02 /* process using debug registers */
caddr_t pcb_onfault; /* copyin/out fault recovery */
#ifdef SMP
u_long pcb_mpnest;
diff --git a/sys/amd64/include/ptrace.h b/sys/amd64/include/ptrace.h
index ec3d5aa..2c43a2e 100644
--- a/sys/amd64/include/ptrace.h
+++ b/sys/amd64/include/ptrace.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ptrace.h 8.1 (Berkeley) 6/11/93
- * $Id: ptrace.h,v 1.5 1997/02/22 09:35:03 peter Exp $
+ * $Id: ptrace.h,v 1.6 1998/05/19 00:00:12 tegge Exp $
*/
#ifndef _MACHINE_PTRACE_H_
@@ -44,6 +44,8 @@
#define PT_SETREGS (PT_FIRSTMACH + 2)
#define PT_GETFPREGS (PT_FIRSTMACH + 3)
#define PT_SETFPREGS (PT_FIRSTMACH + 4)
+#define PT_GETDBREGS (PT_FIRSTMACH + 5)
+#define PT_SETDBREGS (PT_FIRSTMACH + 6)
#ifdef KERNEL
int ptrace_read_u_check __P((struct proc *p, vm_offset_t off, size_t len));
diff --git a/sys/amd64/include/reg.h b/sys/amd64/include/reg.h
index 2470116..994bdfd 100644
--- a/sys/amd64/include/reg.h
+++ b/sys/amd64/include/reg.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)reg.h 5.5 (Berkeley) 1/18/91
- * $Id: reg.h,v 1.17 1999/04/03 22:19:59 jdp Exp $
+ * $Id: reg.h,v 1.18 1999/04/28 01:04:06 luoqi Exp $
*/
#ifndef _MACHINE_REG_H_
@@ -118,6 +118,18 @@ struct fpreg {
unsigned char fpr_pad[64];
};
+struct dbreg {
+ unsigned int dr0; /* debug address register 0 */
+ unsigned int dr1; /* debug address register 1 */
+ unsigned int dr2; /* debug address register 2 */
+ unsigned int dr3; /* debug address register 3 */
+ unsigned int dr4; /* reserved */
+ unsigned int dr5; /* reserved */
+ unsigned int dr6; /* debug status register */
+ unsigned int dr7; /* debug control register */
+};
+
+
#ifdef KERNEL
/*
* XXX these interfaces are MI, so they should be declared in a MI place.
@@ -125,6 +137,7 @@ struct fpreg {
int set_fpregs __P((struct proc *, struct fpreg *));
int set_regs __P((struct proc *p, struct reg *regs));
void setregs __P((struct proc *, u_long, u_long, u_long));
+int set_dbregs __P((struct proc *p, struct dbreg *dbregs));
#endif
#endif /* !_MACHINE_REG_H_ */
OpenPOWER on IntegriCloud