Implement support for hardware debug registers on the i386.

Submitted by:	Brian Dean <brdean@unx.sas.com>
This commit is contained in:
Jonathan Lemon 1999-07-09 04:16:00 +00:00
parent bd17e46e55
commit ab001a72be
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=48691
25 changed files with 458 additions and 24 deletions

View File

@ -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

View File

@ -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));

View File

@ -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)

View File

@ -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

View File

@ -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));

View File

@ -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;

View File

@ -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));

View File

@ -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_ */

View File

@ -362,6 +362,7 @@ miscfs/nullfs/null_vnops.c optional nullfs
miscfs/portal/portal_vfsops.c optional portal
miscfs/portal/portal_vnops.c optional portal
miscfs/procfs/procfs_ctl.c optional procfs
miscfs/procfs/procfs_dbregs.c standard
miscfs/procfs/procfs_fpregs.c standard
miscfs/procfs/procfs_map.c optional procfs
miscfs/procfs/procfs_mem.c standard

View File

@ -37,7 +37,7 @@
* @(#)procfs.h 8.9 (Berkeley) 5/14/95
*
* From:
* $Id: procfs.h,v 1.25 1999/05/04 08:00:10 phk Exp $
* $Id: procfs.h,v 1.26 1999/06/13 20:53:13 phk Exp $
*/
/*
@ -51,6 +51,7 @@ typedef enum {
Pmem, /* the process's memory image */
Pregs, /* the process's register set */
Pfpregs, /* the process's FP register set */
Pdbregs, /* the process's debug register set */
Pctl, /* process control */
Pstatus, /* process status */
Pnote, /* process notifier */
@ -124,6 +125,7 @@ vfs_namemap_t *vfs_findname __P((vfs_namemap_t *, char *, int));
/* <machine/reg.h> */
struct reg;
struct fpreg;
struct dbreg;
#define PFIND(pid) ((pid) ? pfind(pid) : &proc0)
@ -137,9 +139,12 @@ int procfs_read_regs __P((struct proc *, struct reg *));
int procfs_write_regs __P((struct proc *, struct reg *));
int procfs_read_fpregs __P((struct proc *, struct fpreg *));
int procfs_write_fpregs __P((struct proc *, struct fpreg *));
int procfs_read_dbregs __P((struct proc *, struct dbreg *));
int procfs_write_dbregs __P((struct proc *, struct dbreg *));
int procfs_donote __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_doregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_dofpregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_dodbregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_domem __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_doctl __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_dostatus __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
@ -155,6 +160,7 @@ int procfs_kmemaccess __P((struct proc *));
int procfs_validfile __P((struct proc *));
int procfs_validfpregs __P((struct proc *));
int procfs_validregs __P((struct proc *));
int procfs_validdbregs __P((struct proc *));
int procfs_validmap __P((struct proc *));
int procfs_validtype __P((struct proc *));

View File

@ -36,7 +36,7 @@
*
* @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95
*
* $Id: procfs_subr.c,v 1.23 1999/01/27 22:42:07 dillon Exp $
* $Id: procfs_subr.c,v 1.24 1999/04/30 13:04:21 phk Exp $
*/
#include <sys/param.h>
@ -167,6 +167,7 @@ procfs_allocvp(mp, vpp, pid, pfs_type)
case Pregs:
case Pfpregs:
case Pdbregs:
pfs->pfs_mode = (VREAD|VWRITE);
vp->v_type = VREG;
break;
@ -264,6 +265,10 @@ procfs_rw(ap)
rtval = procfs_dofpregs(curp, p, pfs, uio);
break;
case Pdbregs:
rtval = procfs_dodbregs(curp, p, pfs, uio);
break;
case Pctl:
rtval = procfs_doctl(curp, p, pfs, uio);
break;

View File

@ -36,7 +36,7 @@
*
* @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
*
* $Id: procfs_vnops.c,v 1.68 1999/05/04 08:01:55 phk Exp $
* $Id: procfs_vnops.c,v 1.69 1999/06/13 20:53:16 phk Exp $
*/
/*
@ -95,6 +95,7 @@ static struct proc_target {
{ DT_REG, N("mem"), Pmem, NULL },
{ DT_REG, N("regs"), Pregs, procfs_validregs },
{ DT_REG, N("fpregs"), Pfpregs, procfs_validfpregs },
{ DT_REG, N("dbregs"), Pdbregs, procfs_validdbregs },
{ DT_REG, N("ctl"), Pctl, NULL },
{ DT_REG, N("status"), Pstatus, NULL },
{ DT_REG, N("note"), Pnote, NULL },
@ -491,6 +492,7 @@ procfs_getattr(ap)
case Pctl:
case Pregs:
case Pfpregs:
case Pdbregs:
if (procp->p_flag & P_SUGID)
vap->va_mode &= ~((VREAD|VWRITE)|
((VREAD|VWRITE)>>3)|
@ -571,6 +573,10 @@ procfs_getattr(ap)
vap->va_bytes = vap->va_size = sizeof(struct fpreg);
break;
case Pdbregs:
vap->va_bytes = vap->va_size = sizeof(struct dbreg);
break;
case Ptype:
case Pmap:
case Pctl:

View File

@ -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));

View File

@ -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)

View File

@ -37,7 +37,7 @@
* @(#)procfs_machdep.c 8.3 (Berkeley) 1/27/94
*
* From:
* $Id: procfs_machdep.c,v 1.10 1997/07/20 08:37:22 bde Exp $
* $Id: procfs_machdep.c,v 1.11 1998/09/14 22:43:33 jdp Exp $
*/
/*
@ -59,6 +59,9 @@
* procfs_read_fpregs, procfs_write_fpregs
* deal with the floating point register set, otherwise as above.
*
* procfs_read_dbregs, procfs_write_dbregs
* deal with the processor debug register set, otherwise as above.
*
* procfs_sstep(proc)
* Arrange for the process to trap after executing a single instruction.
*
@ -100,6 +103,26 @@ procfs_write_regs(p, regs)
return (set_regs(p, regs));
}
int
procfs_read_dbregs(p, dbregs)
struct proc *p;
struct dbreg *dbregs;
{
if ((p->p_flag & P_INMEM) == 0)
return (EIO);
return (fill_dbregs(p, dbregs));
}
int
procfs_write_dbregs(p, dbregs)
struct proc *p;
struct dbreg *dbregs;
{
if ((p->p_flag & P_INMEM) == 0)
return (EIO);
return (set_dbregs(p, dbregs));
}
/*
* Ptrace doesn't support fpregs at all, and there are no security holes
* or translations for fpregs, so we can just copy them.

View File

@ -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

View File

@ -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));

View File

@ -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;

View File

@ -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));

View File

@ -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_ */

View File

@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: sys_process.c,v 1.45 1999/04/28 11:37:04 phk Exp $
* $Id: sys_process.c,v 1.46 1999/07/01 22:52:40 peter Exp $
*/
#include <sys/param.h>
@ -274,6 +274,12 @@ ptrace(curp, uap)
#endif
#ifdef PT_SETFPREGS
case PT_SETFPREGS:
#endif
#ifdef PT_GETDBREGS
case PT_GETDBREGS:
#endif
#ifdef PT_SETDBREGS
case PT_SETDBREGS:
#endif
/* not being traced... */
if ((p->p_flag & P_TRACED) == 0)
@ -502,6 +508,32 @@ ptrace(curp, uap)
}
#endif /* defined(PT_SETFPREGS) || defined(PT_GETFPREGS) */
#ifdef PT_SETDBREGS
case PT_SETDBREGS:
write = 1;
/* fallthrough */
#endif /* PT_SETDBREGS */
#ifdef PT_GETDBREGS
case PT_GETDBREGS:
/* write = 0 above */
#endif /* PT_SETDBREGS */
#if defined(PT_SETDBREGS) || defined(PT_GETDBREGS)
if (!procfs_validdbregs(p)) /* no P_SYSTEM procs please */
return EINVAL;
else {
iov.iov_base = uap->addr;
iov.iov_len = sizeof(struct dbreg);
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
uio.uio_offset = 0;
uio.uio_resid = sizeof(struct dbreg);
uio.uio_segflg = UIO_USERSPACE;
uio.uio_rw = write ? UIO_WRITE : UIO_READ;
uio.uio_procp = curp;
return (procfs_dodbregs(curp, p, NULL, &uio));
}
#endif /* defined(PT_SETDBREGS) || defined(PT_GETDBREGS) */
default:
break;
}

View File

@ -37,7 +37,7 @@
* @(#)procfs.h 8.9 (Berkeley) 5/14/95
*
* From:
* $Id: procfs.h,v 1.25 1999/05/04 08:00:10 phk Exp $
* $Id: procfs.h,v 1.26 1999/06/13 20:53:13 phk Exp $
*/
/*
@ -51,6 +51,7 @@ typedef enum {
Pmem, /* the process's memory image */
Pregs, /* the process's register set */
Pfpregs, /* the process's FP register set */
Pdbregs, /* the process's debug register set */
Pctl, /* process control */
Pstatus, /* process status */
Pnote, /* process notifier */
@ -124,6 +125,7 @@ vfs_namemap_t *vfs_findname __P((vfs_namemap_t *, char *, int));
/* <machine/reg.h> */
struct reg;
struct fpreg;
struct dbreg;
#define PFIND(pid) ((pid) ? pfind(pid) : &proc0)
@ -137,9 +139,12 @@ int procfs_read_regs __P((struct proc *, struct reg *));
int procfs_write_regs __P((struct proc *, struct reg *));
int procfs_read_fpregs __P((struct proc *, struct fpreg *));
int procfs_write_fpregs __P((struct proc *, struct fpreg *));
int procfs_read_dbregs __P((struct proc *, struct dbreg *));
int procfs_write_dbregs __P((struct proc *, struct dbreg *));
int procfs_donote __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_doregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_dofpregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_dodbregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_domem __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_doctl __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_dostatus __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
@ -155,6 +160,7 @@ int procfs_kmemaccess __P((struct proc *));
int procfs_validfile __P((struct proc *));
int procfs_validfpregs __P((struct proc *));
int procfs_validregs __P((struct proc *));
int procfs_validdbregs __P((struct proc *));
int procfs_validmap __P((struct proc *));
int procfs_validtype __P((struct proc *));

View File

@ -36,7 +36,7 @@
*
* @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95
*
* $Id: procfs_subr.c,v 1.23 1999/01/27 22:42:07 dillon Exp $
* $Id: procfs_subr.c,v 1.24 1999/04/30 13:04:21 phk Exp $
*/
#include <sys/param.h>
@ -167,6 +167,7 @@ procfs_allocvp(mp, vpp, pid, pfs_type)
case Pregs:
case Pfpregs:
case Pdbregs:
pfs->pfs_mode = (VREAD|VWRITE);
vp->v_type = VREG;
break;
@ -264,6 +265,10 @@ procfs_rw(ap)
rtval = procfs_dofpregs(curp, p, pfs, uio);
break;
case Pdbregs:
rtval = procfs_dodbregs(curp, p, pfs, uio);
break;
case Pctl:
rtval = procfs_doctl(curp, p, pfs, uio);
break;

View File

@ -36,7 +36,7 @@
*
* @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
*
* $Id: procfs_vnops.c,v 1.68 1999/05/04 08:01:55 phk Exp $
* $Id: procfs_vnops.c,v 1.69 1999/06/13 20:53:16 phk Exp $
*/
/*
@ -95,6 +95,7 @@ static struct proc_target {
{ DT_REG, N("mem"), Pmem, NULL },
{ DT_REG, N("regs"), Pregs, procfs_validregs },
{ DT_REG, N("fpregs"), Pfpregs, procfs_validfpregs },
{ DT_REG, N("dbregs"), Pdbregs, procfs_validdbregs },
{ DT_REG, N("ctl"), Pctl, NULL },
{ DT_REG, N("status"), Pstatus, NULL },
{ DT_REG, N("note"), Pnote, NULL },
@ -491,6 +492,7 @@ procfs_getattr(ap)
case Pctl:
case Pregs:
case Pfpregs:
case Pdbregs:
if (procp->p_flag & P_SUGID)
vap->va_mode &= ~((VREAD|VWRITE)|
((VREAD|VWRITE)>>3)|
@ -571,6 +573,10 @@ procfs_getattr(ap)
vap->va_bytes = vap->va_size = sizeof(struct fpreg);
break;
case Pdbregs:
vap->va_bytes = vap->va_size = sizeof(struct dbreg);
break;
case Ptype:
case Pmap:
case Pctl:

View File

@ -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));