? tests/kernel/a.out Index: sys/arch/amd64/amd64/genassym.cf =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/amd64/genassym.cf,v retrieving revision 1.60 diff -u -r1.60 genassym.cf --- sys/arch/amd64/amd64/genassym.cf 20 Nov 2015 11:58:00 -0000 1.60 +++ sys/arch/amd64/amd64/genassym.cf 1 Dec 2016 20:24:21 -0000 @@ -96,6 +96,7 @@ include include include +include if defined(COMPAT_NETBSD32) include @@ -188,8 +189,17 @@ define PCB_ONFAULT offsetof(struct pcb, pcb_onfault) define PCB_FLAGS offsetof(struct pcb, pcb_flags) define PCB_COMPAT32 PCB_COMPAT32 +define PCB_USE_DBREGS PCB_USE_DBREGS define PCB_FS offsetof(struct pcb, pcb_fs) define PCB_GS offsetof(struct pcb, pcb_gs) +define PCB_DBREGS offsetof(struct pcb, pcb_dbregs) + +define DBREG_DBREGS_0 offsetof(struct dbreg, dbregs[0]) +define DBREG_DBREGS_1 offsetof(struct dbreg, dbregs[1]) +define DBREG_DBREGS_2 offsetof(struct dbreg, dbregs[2]) +define DBREG_DBREGS_3 offsetof(struct dbreg, dbregs[3]) +define DBREG_DBREGS_6 offsetof(struct dbreg, dbregs[6]) +define DBREG_DBREGS_7 offsetof(struct dbreg, dbregs[7]) define TF_RDI offsetof(struct trapframe, tf_rdi) define TF_RSI offsetof(struct trapframe, tf_rsi) Index: sys/arch/amd64/amd64/locore.S =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/amd64/locore.S,v retrieving revision 1.114 diff -u -r1.114 locore.S --- sys/arch/amd64/amd64/locore.S 25 Nov 2016 14:12:55 -0000 1.114 +++ sys/arch/amd64/amd64/locore.S 1 Dec 2016 20:24:21 -0000 @@ -1113,6 +1113,66 @@ movq %rax,TF_RIP(%rbx) no_RAS: + /* Is this process using CPU Debug Registers? */ + testl $PCB_USE_DBREGS,PCB_FLAGS(%r14) + jne no_dbregs + + movq PCB_DBREGS(%r14), %rsi +#ifndef XEN + movq DBREG_DBREGS_0(%rsi), %rax + movq %rax, %db0 + movq DBREG_DBREGS_1(%rsi), %rax + movq %rax, %db1 + movq DBREG_DBREGS_2(%rsi), %rax + movq %rax, %db2 + movq DBREG_DBREGS_3(%rsi), %rax + movq %rax, %db3 + movq DBREG_DBREGS_6(%rsi), %rax + movq %rax, %db6 + movq DBREG_DBREGS_7(%rsi), %rax + movq %rax, %db7 +#else + movq DBREG_DBREGS_0(%rsi), %rdi + call _C_LABEL(ldr0) + movq DBREG_DBREGS_1(%rsi), %rdi + call _C_LABEL(ldr1) + movq DBREG_DBREGS_2(%rsi), %rdi + call _C_LABEL(ldr2) + movq DBREG_DBREGS_3(%rsi), %rdi + call _C_LABEL(ldr3) + movq DBREG_DBREGS_6(%rsi), %rdi + call _C_LABEL(ldr6) + movq DBREG_DBREGS_6(%rsi), %rdi + call _C_LABEL(ldr6) +#endif + jmp finish_dbregs + +no_dbregs: +#ifndef XEN + xorq %rax, %rax + movq %rax, %db0 + movq %rax, %db1 + movq %rax, %db2 + movq %rax, %db3 + movq %rax, %db6 + movq %rax, %db7 +#else + xorq %rdi, %rdi + call _C_LABEL(ldr0) + xorq %rdi, %rdi + call _C_LABEL(ldr1) + xorq %rdi, %rdi + call _C_LABEL(ldr2) + xorq %rdi, %rdi + call _C_LABEL(ldr3) + xorq %rdi, %rdi + call _C_LABEL(ldr6) + xorq %rdi, %rdi + call _C_LABEL(ldr7) +#endif + +finish_dbregs: + /* * Restore cr0 including FPU state (may have CR0_TS set). Note that * IPL_SCHED prevents from FPU interrupt altering the LWP's saved cr0. Index: sys/arch/amd64/amd64/machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/amd64/machdep.c,v retrieving revision 1.234 diff -u -r1.234 machdep.c --- sys/arch/amd64/amd64/machdep.c 25 Nov 2016 11:57:36 -0000 1.234 +++ sys/arch/amd64/amd64/machdep.c 1 Dec 2016 20:24:21 -0000 @@ -175,6 +175,7 @@ #include #include #include +#include #include #include @@ -287,6 +288,8 @@ void (*initclock_func)(void) = xen_initclocks; #endif +struct pool x86_dbregspl; +struct dbreg lwp0_dbregs; /* * Size of memory segments, before any memory is stolen. @@ -476,6 +479,7 @@ pcb->pcb_gs = 0; pcb->pcb_rsp0 = (uvm_lwp_getuarea(l) + USPACE - 16) & ~0xf; pcb->pcb_iopl = SEL_KPL; + memset(pcb->pcb_dbregs, 0, sizeof(*pcb->pcb_dbregs)); pmap_kernel()->pm_ldt_sel = GSYSSEL(GLDT_SEL, SEL_KPL); pcb->pcb_cr0 = rcr0() & ~CR0_TS; @@ -1311,6 +1315,7 @@ fpu_save_area_clear(l, pack->ep_osversion >= 699002600 ? __NetBSD_NPXCW__ : __NetBSD_COMPAT_NPXCW__); pcb->pcb_flags = 0; + memset(pcb->pcb_dbregs, 0, sizeof(*pcb->pcb_dbregs)); l->l_proc->p_flag &= ~PK_32; @@ -1540,6 +1545,7 @@ struct region_descriptor region; struct mem_segment_descriptor *ldt_segp; int x; + struct pcb *pcb; #ifndef XEN int ist; #endif @@ -1558,8 +1564,8 @@ use_pae = 1; /* PAE always enabled in long mode */ + pcb = lwp_getpcb(&lwp0); #ifdef XEN - struct pcb *pcb = lwp_getpcb(&lwp0); mutex_init(&pte_lock, MUTEX_DEFAULT, IPL_VM); pcb->pcb_cr3 = xen_start_info.pt_base - KERNBASE; __PRINTK(("pcb_cr3 0x%lx\n", xen_start_info.pt_base - KERNBASE)); @@ -1821,6 +1827,12 @@ kgdb_connect(1); } #endif + + pcb->pcb_dbregs = &lwp0_dbregs; + memset(&lwp0_dbregs, 0, sizeof(struct dbreg)); + + pool_init(&x86_dbregspl, sizeof(struct dbreg), 16, 0, 0, "dbregs", + NULL, IPL_NONE); } void @@ -1879,6 +1891,9 @@ process_read_fpregs_xmm(l, (struct fxsave *)&mcp->__fpregs); *flags |= _UC_FPU; + + process_read_dbregs(l, (struct dbreg *)&mcp->__dbregs); + *flags |= _UC_DBREGS; } int @@ -1891,7 +1906,7 @@ int err, trapno; int64_t rflags; - CTASSERT(sizeof (mcontext_t) == 26 * 8 + 8 + 512); + CTASSERT(sizeof (mcontext_t) == 26 * 8 + 8 + 512 + 16 * 8); if ((flags & _UC_CPU) != 0) { error = cpu_mcontext_validate(l, mcp); @@ -1931,6 +1946,9 @@ if ((flags & _UC_FPU) != 0) process_write_fpregs_xmm(l, (const struct fxsave *)&mcp->__fpregs); + if ((flags & _UC_DBREGS) != 0) + process_write_dbregs(l, (const struct dbreg *)&mcp->__dbregs); + if ((flags & _UC_TLSBASE) != 0) lwp_setprivate(l, (void *)(uintptr_t)mcp->_mc_tlsbase); Index: sys/arch/amd64/amd64/process_machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/amd64/process_machdep.c,v retrieving revision 1.29 diff -u -r1.29 process_machdep.c --- sys/arch/amd64/amd64/process_machdep.c 15 Feb 2014 22:20:41 -0000 1.29 +++ sys/arch/amd64/amd64/process_machdep.c 1 Dec 2016 20:24:21 -0000 @@ -67,6 +67,7 @@ #include #include #include +#include static inline struct trapframe *process_frame(struct lwp *); #if 0 @@ -81,6 +82,87 @@ return (l->l_md.md_regs); } +void +reset_dbregs(void) +{ + ldr7(0); /* Turn off the control bits first */ + ldr0(0); + ldr1(0); + ldr2(0); + ldr3(0); + ldr6(0); +} + + +/* + * Return > 0 if a hardware breakpoint has been hit, and the + * breakpoint was in user space. Return 0, otherwise. + */ +int +user_dbreg_trap(void) +{ + u_int64_t dr7, dr6; /* debug registers dr6 and dr7 */ + u_int64_t bp; /* breakpoint bits extracted from dr6 */ + int nbp; /* number of breakpoints that triggered */ + vaddr_t addr[4]; /* breakpoint addresses */ + int i; + + dr7 = rdr7(); + if ((dr7 & 0x000000ff) == 0) { + /* + * all GE and LE bits in the dr7 register are zero, + * thus the trap couldn't have been caused by the + * hardware debug registers + */ + return 0; + } + + nbp = 0; + dr6 = rdr6(); + bp = dr6 & 0x0000000f; + + if (!bp) { + /* + * None of the breakpoint bits are set meaning this + * trap was not caused by any of the debug registers + */ + return 0; + } + + /* + * at least one of the breakpoints were hit, check to see + * which ones and if any of them are user space addresses + */ + + if (bp & 0x01) { + addr[nbp++] = (vaddr_t)rdr0(); + } + if (bp & 0x02) { + addr[nbp++] = (vaddr_t)rdr1(); + } + if (bp & 0x04) { + addr[nbp++] = (vaddr_t)rdr2(); + } + if (bp & 0x08) { + addr[nbp++] = (vaddr_t)rdr3(); + } + + for (i = 0; i < nbp; i++) { + if (addr[i] < (vaddr_t)VM_MAXUSER_ADDRESS) { + /* + * addr[i] is in user space + */ + return nbp; + } + } + + /* + * None of the breakpoints are in user space. + */ + return 0; +} + + int process_read_regs(struct lwp *l, struct reg *regs) { @@ -103,6 +185,16 @@ } int +process_read_dbregs(struct lwp *l, struct dbreg *regs) +{ + struct pcb *pcb = lwp_getpcb(l); + + memcpy(regs, pcb->pcb_dbregs, sizeof(*regs)); + + return 0; +} + +int process_write_regs(struct lwp *l, const struct reg *regp) { struct trapframe *tf = process_frame(l); @@ -134,6 +226,16 @@ } int +process_write_dbregs(struct lwp *l, const struct dbreg *regs) +{ + struct pcb *pcb = lwp_getpcb(l); + + memcpy(pcb->pcb_dbregs, regs, sizeof(*regs)); + + return 0; +} + +int process_sstep(struct lwp *l, int sstep) { struct trapframe *tf = process_frame(l); Index: sys/arch/amd64/amd64/trap.c =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/amd64/trap.c,v retrieving revision 1.87 diff -u -r1.87 trap.c --- sys/arch/amd64/amd64/trap.c 26 Oct 2016 22:02:14 -0000 1.87 +++ sys/arch/amd64/amd64/trap.c 1 Dec 2016 20:24:21 -0000 @@ -98,6 +98,7 @@ #include #include +#include #include #ifndef XEN @@ -673,6 +674,26 @@ } case T_TRCTRAP: + /* + * Ignore debug register trace traps due to + * accesses in the user's address space, which + * can happen under several conditions such as + * if a user sets a watchpoint on a buffer and + * then passes that buffer to a system call. + * We still want to get TRCTRAPS for addresses + * in kernel space because that is useful when + * debugging the kernel. + */ + if (user_dbreg_trap()) { + /* + * Reset breakpoint bits because the + * processor doesn't + */ + /* XXX check upper bits here */ + ldr6(rdr6() & 0xfffffff0); + break; + } + /* Check whether they single-stepped into a lcall. */ if (frame->tf_rip == (uint64_t)IDTVEC(oosyscall) || frame->tf_rip == (uint64_t)IDTVEC(osyscall) || Index: sys/arch/amd64/include/mcontext.h =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/include/mcontext.h,v retrieving revision 1.18 diff -u -r1.18 mcontext.h --- sys/arch/amd64/include/mcontext.h 12 May 2014 22:50:03 -0000 1.18 +++ sys/arch/amd64/include/mcontext.h 1 Dec 2016 20:24:21 -0000 @@ -58,10 +58,15 @@ */ typedef char __fpregset_t[512] __aligned(8); +#define _NDBREG 16 +typedef unsigned long __dbreg_t; +typedef __dbreg_t __dbregset_t[_NDBREG]; + typedef struct { __gregset_t __gregs; __greg_t _mc_tlsbase; __fpregset_t __fpregs; + __dbregset_t __dbregs; } mcontext_t; #define _UC_UCONTEXT_ALIGN (~0xf) @@ -75,13 +80,15 @@ #define _UC_TLSBASE 0x00080000 +#define _UC_DBREGS 0x00100000 + /* * mcontext extensions to handle signal delivery. */ #define _UC_SETSTACK 0x00010000 #define _UC_CLRSTACK 0x00020000 -#define __UCONTEXT_SIZE 784 +#define __UCONTEXT_SIZE 912 static __inline void * __lwp_getprivate_fast(void) @@ -140,16 +147,21 @@ int __fp_pad[33]; /* Historic padding */ } __fpregset32_t; +#define _NDBREG32 8 +typedef unsigned int __dbreg32_t; +typedef __dbreg32_t __dbregset32_t[_NDBREG32]; + typedef struct { __gregset32_t __gregs; __fpregset32_t __fpregs; uint32_t _mc_tlsbase; + __dbregset32_t __dbreg; } mcontext32_t; #define _UC_FXSAVE 0x20 /* FP state is in FXSAVE format in XMM space */ #define _UC_MACHINE32_PAD 4 -#define __UCONTEXT32_SIZE 776 +#define __UCONTEXT32_SIZE 808 #endif /* _KERNEL */ Index: sys/arch/amd64/include/netbsd32_machdep.h =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/include/netbsd32_machdep.h,v retrieving revision 1.20 diff -u -r1.20 netbsd32_machdep.h --- sys/arch/amd64/include/netbsd32_machdep.h 19 Oct 2016 09:44:00 -0000 1.20 +++ sys/arch/amd64/include/netbsd32_machdep.h 1 Dec 2016 20:24:21 -0000 @@ -114,6 +114,10 @@ char __data[108]; }; +struct dbreg32 { + int dbregs[8]; +}; + struct mtrr32 { uint64_t base; uint64_t len; @@ -137,8 +141,10 @@ int netbsd32_process_read_regs(struct lwp *, struct reg32 *); int netbsd32_process_read_fpregs(struct lwp *, struct fpreg32 *, size_t *); +int netbsd32_process_read_dbregs(struct lwp *, struct dbreg32 *, size_t *); int netbsd32_process_write_regs(struct lwp *, const struct reg32 *); int netbsd32_process_write_fpregs(struct lwp *, const struct fpreg32 *, size_t); +int netbsd32_process_write_dbregs(struct lwp *, const struct dbreg32 *, size_t); #endif /* _MACHINE_NETBSD32_H_ */ Index: sys/arch/amd64/include/pcb.h =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/include/pcb.h,v retrieving revision 1.25 diff -u -r1.25 pcb.h --- sys/arch/amd64/include/pcb.h 20 Feb 2014 18:19:10 -0000 1.25 +++ sys/arch/amd64/include/pcb.h 1 Dec 2016 20:24:21 -0000 @@ -73,6 +73,7 @@ #ifdef __x86_64__ #include +#include #define NIOPORTS 1024 /* # of ports we allow to be mapped */ @@ -80,6 +81,7 @@ int pcb_flags; #define PCB_USER_LDT 0x01 /* has user-set LDT */ #define PCB_COMPAT32 0x02 +#define PCB_USE_DBREGS 0x04 /* process is using debug registers */ u_int pcb_cr0; /* saved image of CR0 */ uint64_t pcb_rsp0; uint64_t pcb_cr2; /* page fault address (CR2) */ @@ -89,9 +91,10 @@ void *pcb_onfault; /* copyin/out fault recovery */ uint64_t pcb_fs; uint64_t pcb_gs; + struct dbreg *pcb_dbregs; int pcb_iopl; - uint32_t pcb_unused[11]; /* unused */ + uint32_t pcb_unused[9]; /* unused */ struct cpu_info *pcb_fpcpu; /* cpu holding our fp state. */ union savefpu pcb_savefpu __aligned(64); /* floating point state */ Index: sys/arch/amd64/include/ptrace.h =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/include/ptrace.h,v retrieving revision 1.7 diff -u -r1.7 ptrace.h --- sys/arch/amd64/include/ptrace.h 19 Oct 2016 09:44:00 -0000 1.7 +++ sys/arch/amd64/include/ptrace.h 1 Dec 2016 20:24:21 -0000 @@ -41,13 +41,17 @@ #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) #define PT_MACHDEP_STRINGS \ "PT_STEP", \ "PT_GETREGS", \ "PT_SETREGS", \ "PT_GETFPREGS", \ - "PT_SETFPREGS", + "PT_SETFPREGS", \ + "PT_GETDBREGS", \ + "PT_SETDBREGS", #include #define PTRACE_REG_PC(r) (r)->regs[_REG_RIP] @@ -67,12 +71,15 @@ #define process_read_regs32 netbsd32_process_read_regs #define process_read_fpregs32 netbsd32_process_read_fpregs +#define process_read_dbregs32 netbsd32_process_read_dbregs #define process_write_regs32 netbsd32_process_write_regs #define process_write_fpregs32 netbsd32_process_write_fpregs +#define process_write_dbregs32 netbsd32_process_write_dbregs #define process_reg32 struct reg32 #define process_fpreg32 struct fpreg32 +#define process_dbreg32 struct dbreg32 #endif /* COMPAT_NETBSD32 */ #endif /* _KERNEL_OPT */ Index: sys/arch/amd64/include/reg.h =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/include/reg.h,v retrieving revision 1.9 diff -u -r1.9 reg.h --- sys/arch/amd64/include/reg.h 11 Feb 2014 20:17:16 -0000 1.9 +++ sys/arch/amd64/include/reg.h 1 Dec 2016 20:24:21 -0000 @@ -56,7 +56,20 @@ struct fxsave fxstate; }; -#else /* __x86_64__ */ +/* + * Debug Registers + * + * DR0-DR3 Debug Address Registers + * DR4-DR5 Reserved + * DR6 Debug Status Register + * DR7 Debug Control Register + * DR8-DR15 Reserved + */ +struct dbreg { + long dbregs[_NDBREG]; +}; + +#else /* __x86_64__2 */ #include Index: sys/arch/i386/include/mcontext.h =================================================================== RCS file: /cvsroot/src/sys/arch/i386/include/mcontext.h,v retrieving revision 1.12 diff -u -r1.12 mcontext.h --- sys/arch/i386/include/mcontext.h 15 Feb 2014 22:20:42 -0000 1.12 +++ sys/arch/i386/include/mcontext.h 1 Dec 2016 20:24:21 -0000 @@ -90,10 +90,18 @@ } __fpregset_t; __CTASSERT(sizeof (__fpregset_t) == 512 + 33 * 4); +/* + * General register state + */ +#define _NDBREG 8 +typedef int __dbreg_t; +typedef __dbreg_t __dbregset_t[_NDBREG]; + typedef struct { __gregset_t __gregs; __fpregset_t __fpregs; __greg_t _mc_tlsbase; + __dbregset_t __dbregs; } mcontext_t; #define _UC_FXSAVE 0x20 /* FP state is in FXSAVE format in XMM space */ @@ -121,7 +129,7 @@ #define _UC_MACHINE_SET_PC(uc, pc) _UC_MACHINE_PC(uc) = (pc) -#define __UCONTEXT_SIZE 776 +#define __UCONTEXT_SIZE 808 static __inline void * __lwp_getprivate_fast(void) Index: sys/arch/i386/include/ptrace.h =================================================================== RCS file: /cvsroot/src/sys/arch/i386/include/ptrace.h,v retrieving revision 1.15 diff -u -r1.15 ptrace.h --- sys/arch/i386/include/ptrace.h 25 Sep 2015 16:05:17 -0000 1.15 +++ sys/arch/i386/include/ptrace.h 1 Dec 2016 20:24:21 -0000 @@ -87,6 +87,9 @@ #define PT_GETXMMREGS (PT_FIRSTMACH + 5) #define PT_SETXMMREGS (PT_FIRSTMACH + 6) +#define PT_GETDBREGS (PT_FIRSTMACH + 7) +#define PT_SETDBREGS (PT_FIRSTMACH + 8) + #define PT_MACHDEP_STRINGS \ "PT_STEP", \ "PT_GETREGS", \ @@ -94,7 +97,9 @@ "PT_GETFPREGS", \ "PT_SETFPREGS", \ "PT_GETXMMREGS", \ - "PT_SETXMMREGS", + "PT_SETXMMREGS", \ + "PT_GETDBREGS", \ + "PT_SETDBREGS", #include #define PTRACE_REG_PC(r) (r)->r_eip Index: sys/arch/x86/include/dbregs.h =================================================================== RCS file: /cvsroot/src/sys/arch/x86/include/dbregs.h,v retrieving revision 1.1 diff -u -r1.1 dbregs.h --- sys/arch/x86/include/dbregs.h 27 Nov 2016 14:49:21 -0000 1.1 +++ sys/arch/x86/include/dbregs.h 1 Dec 2016 20:24:22 -0000 @@ -35,6 +35,7 @@ struct lwp; struct dbreg; +int user_dbreg_trap(void); void reset_dbregs(void); int process_write_dbregs(struct lwp *lwp, const struct dbreg *regs); Index: sys/arch/x86/x86/vm_machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/x86/x86/vm_machdep.c,v retrieving revision 1.26 diff -u -r1.26 vm_machdep.c --- sys/arch/x86/x86/vm_machdep.c 8 Nov 2016 03:05:36 -0000 1.26 +++ sys/arch/x86/x86/vm_machdep.c 1 Dec 2016 20:24:22 -0000 @@ -105,6 +105,9 @@ #endif #include +#include + +extern struct pool x86_dbregspl; void cpu_proc_fork(struct proc *p1, struct proc *p2) @@ -157,6 +160,18 @@ /* Copy any additional fpu state */ fpu_save_area_fork(pcb2, pcb1); + pcb2->pcb_dbregs = pool_get(&x86_dbregspl, PR_WAITOK); + /* Inherit CPU Debug Registers within the same process */ + *pcb2->pcb_dbregs = *pcb1->pcb_dbregs; + + /* + * Clear the debug registers on the running + * CPU, otherwise they will end up affecting + * the next process we switch to. + */ + if (l2 == curlwp) + reset_dbregs(); + #if defined(XEN) pcb2->pcb_iopl = SEL_KPL; #endif @@ -241,6 +256,9 @@ void cpu_lwp_free(struct lwp *l, int proc) { + struct pcb *pcb; + + pcb = lwp_getpcb(l); /* If we were using the FPU, forget about it. */ fpusave_lwp(l, false); @@ -255,6 +273,13 @@ struct vm_page *empty_ptps = l->l_md.md_gc_ptp; l->l_md.md_gc_ptp = NULL; pmap_free_ptps(empty_ptps); + + /* Disable any hardware breakpoints. */ + if (pcb->pcb_flags & PCB_USE_DBREGS) { + reset_dbregs(); + } + + pool_put(&x86_dbregspl, pcb->pcb_dbregs); } /* Index: sys/kern/sys_ptrace.c =================================================================== RCS file: /cvsroot/src/sys/kern/sys_ptrace.c,v retrieving revision 1.2 diff -u -r1.2 sys_ptrace.c --- sys/kern/sys_ptrace.c 3 Nov 2016 03:57:05 -0000 1.2 +++ sys/kern/sys_ptrace.c 1 Dec 2016 20:24:22 -0000 @@ -169,6 +169,7 @@ .ptm_copyoutpiod = ptrace_copyoutpiod, .ptm_doregs = process_doregs, .ptm_dofpregs = process_dofpregs, + .ptm_dodbregs = process_dodbregs, }; static const struct syscall_package ptrace_syscalls[] = { Index: sys/kern/sys_ptrace_common.c =================================================================== RCS file: /cvsroot/src/sys/kern/sys_ptrace_common.c,v retrieving revision 1.5 diff -u -r1.5 sys_ptrace_common.c --- sys/kern/sys_ptrace_common.c 19 Nov 2016 19:06:12 -0000 1.5 +++ sys/kern/sys_ptrace_common.c 1 Dec 2016 20:24:22 -0000 @@ -202,6 +202,12 @@ #ifdef PT_SETFPREGS case PT_SETFPREGS: #endif +#ifdef PT_GETDBREGS + case PT_GETDBREGS: +#endif +#ifdef PT_SETDBREGS + case PT_SETDBREGS: +#endif case PT_SET_EVENT_MASK: case PT_GET_EVENT_MASK: case PT_GET_PROCESS_STATE: @@ -405,6 +411,12 @@ #ifdef PT_SETFPREGS case PT_SETFPREGS: #endif +#ifdef PT_GETDBREGS + case PT_GETDBREGS: +#endif +#ifdef PT_SETDBREGS + case PT_SETDBREGS: +#endif #ifdef __HAVE_PTRACE_MACHDEP PTRACE_MACHDEP_REQUEST_CASES #endif @@ -986,6 +998,50 @@ break; #endif +#ifdef PT_SETDBREGS + case PT_SETDBREGS: + write = 1; + /*FALLTHROUGH*/ +#endif +#ifdef PT_GETDBREGS + case PT_GETDBREGS: + /* write = 0 done above. */ +#endif +#if defined(PT_SETDBREGS) || defined(PT_GETDBREGS) + tmp = data; + if (tmp != 0 && t->p_nlwps > 1) { + lwp_delref(lt); + mutex_enter(t->p_lock); + lt = lwp_find(t, tmp); + if (lt == NULL) { + mutex_exit(t->p_lock); + error = ESRCH; + break; + } + lwp_addref(lt); + mutex_exit(t->p_lock); + } + if (!process_validdbregs(lt)) + error = EINVAL; + else { + error = proc_vmspace_getref(p, &vm); + if (error) + break; + iov.iov_base = addr; + iov.iov_len = PROC_DBREGSZ(p); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = 0; + uio.uio_resid = iov.iov_len; + uio.uio_rw = write ? UIO_WRITE : UIO_READ; + uio.uio_vmspace = vm; + + error = ptm->ptm_dodbregs(l, lt, &uio); + uvmspace_free(vm); + } + break; +#endif + #ifdef __HAVE_PTRACE_MACHDEP PTRACE_MACHDEP_REQUEST_CASES error = ptrace_machdep_dorequest(l, lt, req, addr, data); @@ -1103,6 +1159,55 @@ #endif } +int +process_dodbregs(struct lwp *curl /*tracer*/, + struct lwp *l /*traced*/, + struct uio *uio) +{ +#if defined(PT_GETDBREGS) || defined(PT_SETDBREGS) + int error; + struct dbreg r; + char *kv; + size_t kl; + + if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r)) + return EINVAL; + + kl = sizeof(r); + kv = (char *)&r; + + kv += uio->uio_offset; + kl -= uio->uio_offset; + if (kl > uio->uio_resid) + kl = uio->uio_resid; + + error = process_read_dbregs(l, &r); + if (error == 0) + error = uiomove(kv, kl, uio); + if (error == 0 && uio->uio_rw == UIO_WRITE) { + if (l->l_stat != LSSTOP) + error = EBUSY; + else + error = process_write_dbregs(l, &r); + } + uio->uio_offset = 0; + return error; +#else + return EINVAL; +#endif +} + +int +process_validdbregs(struct lwp *l) +{ + +#if defined(PT_SETDBREGS) || defined(PT_GETDBREGS) + return (l->l_flag & LW_SYSTEM) == 0; +#else + return 0; +#endif +} + static int process_auxv_offset(struct proc *p, struct uio *uio) { @@ -1151,4 +1256,3 @@ } return error; } - Index: sys/sys/proc.h =================================================================== RCS file: /cvsroot/src/sys/sys/proc.h,v retrieving revision 1.335 diff -u -r1.335 proc.h --- sys/sys/proc.h 19 Oct 2016 09:44:01 -0000 1.335 +++ sys/sys/proc.h 1 Dec 2016 20:24:22 -0000 @@ -561,6 +561,8 @@ sizeof(process_reg32) : sizeof(struct reg)) #define PROC_FPREGSZ(p) (((p)->p_flag & PK_32) ? \ sizeof(process_fpreg32) : sizeof(struct fpreg)) +#define PROC_DBREGSZ(p) (((p)->p_flag & PK_32) ? \ + sizeof(process_dbreg32) : sizeof(struct dbreg)) /* * PROCLIST_FOREACH: iterate on the given proclist, skipping PK_MARKER ones. Index: sys/sys/ptrace.h =================================================================== RCS file: /cvsroot/src/sys/sys/ptrace.h,v retrieving revision 1.49 diff -u -r1.49 ptrace.h --- sys/sys/ptrace.h 4 Nov 2016 18:14:04 -0000 1.49 +++ sys/sys/ptrace.h 1 Dec 2016 20:24:22 -0000 @@ -138,12 +138,22 @@ #define process_fpreg64 struct fpreg #endif #endif +#if defined(PT_GETDBREGS) || defined(PT_SETDBREGS) +struct dbreg; +#ifndef process_dbreg32 +#define process_dbreg32 struct dbreg +#endif +#ifndef process_dbreg64 +#define process_dbreg64 struct dbreg +#endif +#endif struct ptrace_methods { int (*ptm_copyinpiod)(struct ptrace_io_desc *, const void *); void (*ptm_copyoutpiod)(const struct ptrace_io_desc *, void *); int (*ptm_doregs)(struct lwp *, struct lwp *, struct uio *); int (*ptm_dofpregs)(struct lwp *, struct lwp *, struct uio *); + int (*ptm_dodbregs)(struct lwp *, struct lwp *, struct uio *); }; int ptrace_init(void); @@ -156,6 +166,9 @@ int process_dofpregs(struct lwp *, struct lwp *, struct uio *); int process_validfpregs(struct lwp *); +int process_dodbregs(struct lwp *, struct lwp *, struct uio *); +int process_validdbregs(struct lwp *); + int process_domem(struct lwp *, struct lwp *, struct uio *); void process_stoptrace(void); @@ -172,6 +185,15 @@ * will #define process_read_regs32 to netbsd32_process_read_regs (etc). * In all other cases these #defines drop the size suffix. */ +#ifdef PT_GETDBREGS +int process_read_dbregs(struct lwp *, struct dbreg *); +#ifndef process_read_dbregs32 +#define process_read_dbregs32 process_read_dbregs +#endif +#ifndef process_read_dbregs64 +#define process_read_dbregs64 process_read_dbregs +#endif +#endif #ifdef PT_GETFPREGS int process_read_fpregs(struct lwp *, struct fpreg *, size_t *); #ifndef process_read_fpregs32 @@ -192,6 +214,15 @@ #endif int process_set_pc(struct lwp *, void *); int process_sstep(struct lwp *, int); +#ifdef PT_SETDBREGS +int process_write_dbregs(struct lwp *, const struct dbreg *); +#ifndef process_write_dbregs32 +#define process_write_dbregs32 process_write_dbregs +#endif +#ifndef process_write_dbregs64 +#define process_write_dbregs64 process_write_dbregs +#endif +#endif #ifdef PT_SETFPREGS int process_write_fpregs(struct lwp *, const struct fpreg *, size_t); #ifndef process_write_fpregs32 Index: sys/sys/ucontext.h =================================================================== RCS file: /cvsroot/src/sys/sys/ucontext.h,v retrieving revision 1.18 diff -u -r1.18 ucontext.h --- sys/sys/ucontext.h 6 Mar 2013 18:16:58 -0000 1.18 +++ sys/sys/ucontext.h 1 Dec 2016 20:24:22 -0000 @@ -57,7 +57,7 @@ #define _UC_STACK 0x02 /* valid uc_stack */ #define _UC_CPU 0x04 /* valid GPR context in uc_mcontext */ #define _UC_FPU 0x08 /* valid FPU context in uc_mcontext */ -#define _UC_MD 0x400f0020 /* MD bits. see below */ +#define _UC_MD 0x401f0020 /* MD bits. see below */ /* * if your port needs more MD bits, please try to choose bits from _UC_MD @@ -99,6 +99,9 @@ * _UC_FXSAVE Context contains FPU context in that * is in FXSAVE format in XMM space * 0x00000020 i386, amd64 only + * + * _UC_DBREGS Debug registers + * 0x00100000 i386, amd64 only */ #ifdef _KERNEL