? tests/kernel/arch/amd64/t_ptrace_wait.c.2 Index: distrib/sets/lists/comp/md.amd64 =================================================================== RCS file: /cvsroot/src/distrib/sets/lists/comp/md.amd64,v retrieving revision 1.242 diff -u -r1.242 md.amd64 --- distrib/sets/lists/comp/md.amd64 11 Jan 2017 12:02:24 -0000 1.242 +++ distrib/sets/lists/comp/md.amd64 18 Feb 2017 05:47:25 -0000 @@ -552,7 +552,7 @@ ./usr/include/x86/cpu_ucode.h comp-c-include ./usr/include/x86/cputypes.h comp-c-include ./usr/include/x86/cpuvar.h comp-c-include -./usr/include/x86/dbregs.h comp-c-include +./usr/include/x86/dbregs.h comp-obsolete obsolete ./usr/include/x86/float.h comp-c-include ./usr/include/x86/fpu.h comp-c-include ./usr/include/x86/ieee.h comp-c-include Index: distrib/sets/lists/comp/md.i386 =================================================================== RCS file: /cvsroot/src/distrib/sets/lists/comp/md.i386,v retrieving revision 1.162 diff -u -r1.162 md.i386 --- distrib/sets/lists/comp/md.i386 11 Jan 2017 12:02:24 -0000 1.162 +++ distrib/sets/lists/comp/md.i386 18 Feb 2017 05:47:25 -0000 @@ -426,7 +426,7 @@ ./usr/include/x86/cpu_ucode.h comp-c-include ./usr/include/x86/cputypes.h comp-c-include ./usr/include/x86/cpuvar.h comp-c-include -./usr/include/x86/dbregs.h comp-c-include +./usr/include/x86/dbregs.h comp-obsolete obsolete ./usr/include/x86/float.h comp-c-include ./usr/include/x86/fpu.h comp-c-include ./usr/include/x86/ieee.h comp-c-include Index: sys/arch/amd64/amd64/machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/amd64/machdep.c,v retrieving revision 1.251 diff -u -r1.251 machdep.c --- sys/arch/amd64/amd64/machdep.c 5 Feb 2017 08:36:08 -0000 1.251 +++ sys/arch/amd64/amd64/machdep.c 18 Feb 2017 05:47:39 -0000 @@ -175,6 +175,7 @@ #include #include #include +#include #include #include @@ -282,6 +283,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. @@ -469,11 +472,11 @@ 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; l->l_md.md_regs = (struct trapframe *)pcb->pcb_rsp0 - 1; - memset(l->l_md.md_watchpoint, 0, sizeof(*l->l_md.md_watchpoint)); #if !defined(XEN) lldt(pmap_kernel()->pm_ldt_sel); @@ -1316,11 +1319,10 @@ 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; - memset(l->l_md.md_watchpoint, 0, sizeof(*l->l_md.md_watchpoint)); - tf = l->l_md.md_regs; tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL); tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL); @@ -1491,6 +1493,7 @@ struct region_descriptor region; struct mem_segment_descriptor *ldt_segp; int x; + struct pcb *pcb; #ifndef XEN extern paddr_t local_apic_pa; int ist; @@ -1510,8 +1513,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)); @@ -1774,6 +1777,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 Index: sys/arch/amd64/amd64/netbsd32_machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/amd64/netbsd32_machdep.c,v retrieving revision 1.103 diff -u -r1.103 netbsd32_machdep.c --- sys/arch/amd64/amd64/netbsd32_machdep.c 14 Feb 2017 09:03:48 -0000 1.103 +++ sys/arch/amd64/amd64/netbsd32_machdep.c 18 Feb 2017 05:47:39 -0000 @@ -138,8 +138,6 @@ p->p_flag |= PK_32; - memset(l->l_md.md_watchpoint, 0, sizeof(*l->l_md.md_watchpoint)); - tf = l->l_md.md_regs; tf->tf_ds = LSEL(LUDATA32_SEL, SEL_UPL); tf->tf_es = LSEL(LUDATA32_SEL, SEL_UPL); @@ -529,6 +527,24 @@ } int +netbsd32_process_read_dbregs(struct lwp *l, struct dbreg32 *regs, size_t *sz) +{ + struct pcb *pcb; + + pcb = lwp_getpcb(l); + + regs->dr[0] = pcb->pcb_dbregs->dr[0] & 0xffffffff; + regs->dr[1] = pcb->pcb_dbregs->dr[1] & 0xffffffff; + regs->dr[2] = pcb->pcb_dbregs->dr[2] & 0xffffffff; + regs->dr[3] = pcb->pcb_dbregs->dr[3] & 0xffffffff; + + regs->dr[6] = pcb->pcb_dbregs->dr[6] & 0xffffffff; + regs->dr[7] = pcb->pcb_dbregs->dr[7] & 0xffffffff; + + return 0; +} + +int netbsd32_process_write_regs(struct lwp *l, const struct reg32 *regs) { struct trapframe *tf; @@ -589,6 +605,25 @@ } int +netbsd32_process_write_dbregs(struct lwp *l, const struct dbreg32 *regs, + size_t sz) +{ + struct pcb *pcb; + + pcb = lwp_getpcb(l); + + pcb->pcb_dbregs->dr[0] = regs->dr[0]; + pcb->pcb_dbregs->dr[1] = regs->dr[1]; + pcb->pcb_dbregs->dr[2] = regs->dr[2]; + pcb->pcb_dbregs->dr[3] = regs->dr[3]; + + pcb->pcb_dbregs->dr[6] = regs->dr[6]; + pcb->pcb_dbregs->dr[7] = regs->dr[7]; + + return 0; +} + +int netbsd32_sysarch(struct lwp *l, const struct netbsd32_sysarch_args *uap, register_t *retval) { /* { Index: sys/arch/amd64/amd64/process_machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/amd64/process_machdep.c,v retrieving revision 1.31 diff -u -r1.31 process_machdep.c --- sys/arch/amd64/amd64/process_machdep.c 16 Jan 2017 21:35:59 -0000 1.31 +++ sys/arch/amd64/amd64/process_machdep.c 18 Feb 2017 05:47:39 -0000 @@ -44,21 +44,34 @@ * registers or privileged bits in the PSL. * The process is stopped at the time write_regs is called. * + * process_read_fpregs(proc, regs, sz) + * Get the current user-visible register set from the process + * and copy it into the regs structure (). + * The process is stopped at the time read_fpregs is called. + * + * process_write_fpregs(proc, regs, sz) + * Update the current register set from the passed in regs + * structure. Take care to avoid clobbering special CPU + * registers or privileged bits in the PSL. + * The process is stopped at the time write_fpregs is called. + * + * process_read_dbregs(proc, regs, sz) + * Get the current user-visible register set from the process + * and copy it into the regs structure (). + * The process is stopped at the time read_dbregs is called. + * + * process_write_dbregs(proc, regs, sz) + * Update the current register set from the passed in regs + * structure. Take care to avoid clobbering special CPU + * registers or privileged bits in the PSL. + * The process is stopped at the time write_dbregs is called. + * * process_sstep(proc) * Arrange for the process to trap after executing a single instruction. * * process_set_pc(proc) * Set the process's program counter. * - * process_count_watchpoints(proc, retval) - * Return the number of supported hardware watchpoints. - * - * process_read_watchpoint(proc, watchpoint) - * Read hardware watchpoint of the given index. - * - * process_write_watchpoint(proc, watchpoint) - * Write hardware watchpoint of the given index. - * */ @@ -114,6 +127,15 @@ } int +process_read_dbregs(struct lwp *l, struct dbreg *regs, size_t *sz) +{ + + x86_dbregs_read(l, regs); + + return 0; +} + +int process_write_regs(struct lwp *l, const struct reg *regp) { struct trapframe *tf = process_frame(l); @@ -145,6 +167,23 @@ } int +process_write_dbregs(struct lwp *l, const struct dbreg *regs, size_t sz) +{ + int error; + + /* + * Check for security violations. + */ + error = x86_dbregs_validate(regs); + if (error != 0) + return error; + + x86_dbregs_write(l, regs); + + return 0; +} + +int process_sstep(struct lwp *l, int sstep) { struct trapframe *tf = process_frame(l); @@ -168,85 +207,3 @@ return (0); } - -int -process_count_watchpoints(struct lwp *l, register_t *retval) -{ - - *retval = X86_HW_WATCHPOINTS; - - return (0); -} - -int -process_read_watchpoint(struct lwp *l, struct ptrace_watchpoint *pw) -{ - - pw->pw_type = PTRACE_PW_TYPE_DBREGS; - pw->pw_md.md_address = - (void*)(intptr_t)l->l_md.md_watchpoint[pw->pw_index].address; - pw->pw_md.md_condition = l->l_md.md_watchpoint[pw->pw_index].condition; - pw->pw_md.md_length = l->l_md.md_watchpoint[pw->pw_index].length; - - return (0); -} - -static void -update_mdl_x86_hw_watchpoints(struct lwp *l) -{ - size_t i; - - for (i = 0; i < X86_HW_WATCHPOINTS; i++) { - if (l->l_md.md_watchpoint[0].address != 0) { - return; - } - } - l->l_md.md_flags &= ~MDL_X86_HW_WATCHPOINTS; -} - -int -process_write_watchpoint(struct lwp *l, struct ptrace_watchpoint *pw) -{ - - if (pw->pw_index > X86_HW_WATCHPOINTS) - return (EINVAL); - - if (pw->pw_type != PTRACE_PW_TYPE_DBREGS) - return (EINVAL); - - if (pw->pw_md.md_address == 0) { - l->l_md.md_watchpoint[pw->pw_index].address = 0; - update_mdl_x86_hw_watchpoints(l); - return (0); - } - - if ((vaddr_t)pw->pw_md.md_address > VM_MAXUSER_ADDRESS) - return (EINVAL); - - switch (pw->pw_md.md_condition) { - case X86_HW_WATCHPOINT_DR7_CONDITION_EXECUTION: - case X86_HW_WATCHPOINT_DR7_CONDITION_DATA_WRITE: - case X86_HW_WATCHPOINT_DR7_CONDITION_DATA_READWRITE: - break; - default: - return (EINVAL); - } - - switch (pw->pw_md.md_length) { - case X86_HW_WATCHPOINT_DR7_LENGTH_BYTE: - case X86_HW_WATCHPOINT_DR7_LENGTH_TWOBYTES: - case X86_HW_WATCHPOINT_DR7_LENGTH_FOURBYTES: - break; - default: - return (EINVAL); - } - - l->l_md.md_watchpoint[pw->pw_index].address = - (vaddr_t)pw->pw_md.md_address; - l->l_md.md_watchpoint[pw->pw_index].condition = pw->pw_md.md_condition; - l->l_md.md_watchpoint[pw->pw_index].length = pw->pw_md.md_length; - - l->l_md.md_flags |= MDL_X86_HW_WATCHPOINTS; - - return (0); -} Index: sys/arch/amd64/amd64/trap.c =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/amd64/trap.c,v retrieving revision 1.91 diff -u -r1.91 trap.c --- sys/arch/amd64/amd64/trap.c 17 Feb 2017 01:14:31 -0000 1.91 +++ sys/arch/amd64/amd64/trap.c 18 Feb 2017 05:47:39 -0000 @@ -230,7 +230,7 @@ #endif ksiginfo_t ksi; void *onfault; - int type, error, wptnfo; + int type, error; uint64_t cr2; bool pfail; @@ -687,7 +687,7 @@ * in kernel space because that is useful when * debugging the kernel. */ - if (user_trap_x86_hw_watchpoint()) + if (x86_dbregs_user_trap()) break; /* Check whether they single-stepped into a lcall. */ @@ -710,10 +710,9 @@ KSI_INIT_TRAP(&ksi); ksi.ksi_signo = SIGTRAP; ksi.ksi_trap = type & ~T_USER; - if ((wptnfo = user_trap_x86_hw_watchpoint())) { + if (x86_dbregs_user_trap()) { + x86_dbregs_store_dr6(l); ksi.ksi_code = TRAP_DBREG; - ksi.ksi_trap2 = x86_hw_watchpoint_reg(wptnfo); - ksi.ksi_trap3 = x86_hw_watchpoint_type(wptnfo); } else if (type == (T_BPTFLT|T_USER)) ksi.ksi_code = TRAP_BRKPT; else Index: sys/arch/amd64/include/netbsd32_machdep.h =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/include/netbsd32_machdep.h,v retrieving revision 1.21 diff -u -r1.21 netbsd32_machdep.h --- sys/arch/amd64/include/netbsd32_machdep.h 6 Feb 2017 16:02:17 -0000 1.21 +++ sys/arch/amd64/include/netbsd32_machdep.h 18 Feb 2017 05:47:39 -0000 @@ -114,6 +114,10 @@ char __data[108]; }; +struct dbreg32 { + int dr[8]; +}; + struct x86_get_ldt_args32 { int32_t start; uint32_t desc; @@ -149,8 +153,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 18 Feb 2017 05:47:39 -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 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/proc.h =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/include/proc.h,v retrieving revision 1.20 diff -u -r1.20 proc.h --- sys/arch/amd64/include/proc.h 15 Dec 2016 12:04:17 -0000 1.20 +++ sys/arch/amd64/include/proc.h 18 Feb 2017 05:47:39 -0000 @@ -52,12 +52,10 @@ struct vm_page *md_gc_ptp; /* pages from pmap g/c */ int md_flags; /* machine-dependent flags */ volatile int md_astpending; - struct x86_hw_watchpoint md_watchpoint[X86_HW_WATCHPOINTS]; }; #define MDL_COMPAT32 0x0008 /* i386, always return via iret */ #define MDL_IRET 0x0010 /* force return via iret, not sysret */ -#define MDL_X86_HW_WATCHPOINTS 0x0020 /* has hardware watchpoints */ struct mdproc { int md_flags; Index: sys/arch/amd64/include/ptrace.h =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/include/ptrace.h,v retrieving revision 1.9 diff -u -r1.9 ptrace.h --- sys/arch/amd64/include/ptrace.h 16 Jan 2017 21:35:59 -0000 1.9 +++ sys/arch/amd64/include/ptrace.h 18 Feb 2017 05:47:39 -0000 @@ -41,9 +41,8 @@ #define PT_SETREGS (PT_FIRSTMACH + 2) #define PT_GETFPREGS (PT_FIRSTMACH + 3) #define PT_SETFPREGS (PT_FIRSTMACH + 4) -#define PT_READ_WATCHPOINT (PT_FIRSTMACH + 5) -#define PT_WRITE_WATCHPOINT (PT_FIRSTMACH + 6) -#define PT_COUNT_WATCHPOINTS (PT_FIRSTMACH + 7) +#define PT_GETDBREGS (PT_FIRSTMACH + 5) +#define PT_SETDBREGS (PT_FIRSTMACH + 6) #define PT_MACHDEP_STRINGS \ "PT_STEP", \ @@ -51,9 +50,8 @@ "PT_SETREGS", \ "PT_GETFPREGS", \ "PT_SETFPREGS", \ - "PT_READ_WATCHPOINT", \ - "PT_WRITE_WATCHPOINT", \ - "PT_COUNT_WATCHPOINTS" + "PT_GETDBREGS", \ + "PT_SETDBREGS", #include #define PTRACE_REG_PC(r) (r)->regs[_REG_RIP] @@ -65,50 +63,6 @@ #define PTRACE_BREAKPOINT_SIZE 1 #define PTRACE_BREAKPOINT_ADJ 1 -#define __HAVE_PTRACE_WATCHPOINTS - -/* - * The current list of supported hardware watchpoints - */ -#define PTRACE_PW_TYPE_DBREGS 1 - -struct mdpw { - union { - /* Debug Registers DR0-3, DR6, DR7 */ - struct { - void *_md_address; - int _md_condition; - int _md_length; - } _dbregs; - } _type; -}; - -/* - * This MD structure translates into x86_hw_watchpoint - * - * pw_address - 0 represents disabled hardware watchpoint - * - * conditions: - * 0b00 - execution - * 0b01 - data write - * 0b10 - io read/write (not implemented) - * 0b11 - data read/write - * - * length: - * 0b00 - 1 byte - * 0b01 - 2 bytes - * 0b10 - undefined (8 bytes in modern CPUs - not implemented) - * 0b11 - 4 bytes - * - * Helper symbols for conditions and length are available in - * - */ - -#define md_address _type._dbregs._md_address -#define md_condition _type._dbregs._md_condition -#define md_length _type._dbregs._md_length - - #ifdef _KERNEL_OPT #include "opt_compat_netbsd32.h" @@ -117,17 +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_watchpoint32 netbsd32_process_write_watchpoint -#define process_read_watchpoint32 netbsd32_process_read_watchpoint -#define process_count_watchpoint32 netbsd32_process_count_watchpoint +#define process_write_dbregs32 netbsd32_process_write_dbregs #define process_reg32 struct reg32 #define process_fpreg32 struct fpreg32 -#define process_watchpoint32 struct ptrace_watchpoint32 +#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 18 Feb 2017 05:47:39 -0000 @@ -56,6 +56,19 @@ struct fxsave fxstate; }; +/* + * Debug Registers + * + * DR0-DR3 Debug Address Registers + * DR4-DR5 Reserved + * DR6 Debug Status Register + * DR7 Debug Control Register + * DR8-DR15 Reserved + */ +struct dbreg { + long dr[16]; +}; + #else /* __x86_64__ */ #include Index: sys/arch/amd64/include/userret.h =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/include/userret.h,v retrieving revision 1.11 diff -u -r1.11 userret.h --- sys/arch/amd64/include/userret.h 16 Jan 2017 21:19:35 -0000 1.11 +++ sys/arch/amd64/include/userret.h 18 Feb 2017 05:47:39 -0000 @@ -78,15 +78,13 @@ static __inline void userret(struct lwp *l) { + struct pcb *pcb = lwp_getpcb(l); /* Invoke MI userret code */ mi_userret(l); - /* - * Allow to mix debug registers with single step. - */ - if (l->l_md.md_flags & MDL_X86_HW_WATCHPOINTS) - set_x86_hw_watchpoints(l); + if (pcb->pcb_flags & PCB_USE_DBREGS) + x86_dbregs_set(l); else - clear_x86_hw_watchpoints(); + x86_dbregs_clear(l); } Index: sys/arch/i386/i386/machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/i386/i386/machdep.c,v retrieving revision 1.778 diff -u -r1.778 machdep.c --- sys/arch/i386/i386/machdep.c 5 Feb 2017 10:42:21 -0000 1.778 +++ sys/arch/i386/i386/machdep.c 18 Feb 2017 05:47:39 -0000 @@ -143,6 +143,7 @@ #include #include +#include #include #include @@ -236,6 +237,9 @@ int i386_has_sse; int i386_has_sse2; +struct pool x86_dbregspl; +struct dbreg lwp0_dbregs; + vaddr_t idt_vaddr; paddr_t idt_paddr; vaddr_t gdt_vaddr; @@ -507,7 +511,7 @@ l->l_md.md_regs = (struct trapframe *)pcb->pcb_esp0 - 1; memcpy(&pcb->pcb_fsd, &gdtstore[GUDATA_SEL], sizeof(pcb->pcb_fsd)); memcpy(&pcb->pcb_gsd, &gdtstore[GUDATA_SEL], sizeof(pcb->pcb_gsd)); - memset(l->l_md.md_watchpoint, 0, sizeof(*l->l_md.md_watchpoint)); + memset(pcb->pcb_dbregs, 0, sizeof(*pcb->pcb_dbregs)); #ifndef XEN lldt(pmap_kernel()->pm_ldt_sel); @@ -840,8 +844,7 @@ memcpy(&pcb->pcb_fsd, &gdtstore[GUDATA_SEL], sizeof(pcb->pcb_fsd)); memcpy(&pcb->pcb_gsd, &gdtstore[GUDATA_SEL], sizeof(pcb->pcb_gsd)); - - memset(l->l_md.md_watchpoint, 0, sizeof(*l->l_md.md_watchpoint)); + memset(pcb->pcb_dbregs, 0, sizeof(*pcb->pcb_dbregs)); tf = l->l_md.md_regs; tf->tf_gs = GSEL(GUGS_SEL, SEL_UPL); @@ -1088,6 +1091,7 @@ extern int biostramp_image_size; extern u_char biostramp_image[]; #endif + struct pcb *pcb; KASSERT(first_avail % PAGE_SIZE == 0); @@ -1109,8 +1113,8 @@ use_pae = 0; #endif + pcb = lwp_getpcb(&lwp0); #ifdef XEN - struct pcb *pcb = lwp_getpcb(&lwp0); pcb->pcb_cr3 = PDPpaddr; __PRINTK(("pcb_cr3 0x%lx cr3 0x%lx\n", PDPpaddr, xpmap_ptom(PDPpaddr))); @@ -1402,6 +1406,12 @@ } rw_init(&svr4_fasttrap_lock); + + 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); } #include /* for NVRAM POST */ Index: sys/arch/i386/i386/process_machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/i386/i386/process_machdep.c,v retrieving revision 1.88 diff -u -r1.88 process_machdep.c --- sys/arch/i386/i386/process_machdep.c 16 Jan 2017 21:35:59 -0000 1.88 +++ sys/arch/i386/i386/process_machdep.c 18 Feb 2017 05:47:39 -0000 @@ -44,21 +44,34 @@ * registers or privileged bits in the PSL. * The process is stopped at the time write_regs is called. * + * process_read_fpregs(proc, regs, sz) + * Get the current user-visible register set from the process + * and copy it into the regs structure (). + * The process is stopped at the time read_fpregs is called. + * + * process_write_fpregs(proc, regs, sz) + * Update the current register set from the passed in regs + * structure. Take care to avoid clobbering special CPU + * registers or privileged bits in the PSL. + * The process is stopped at the time write_fpregs is called. + * + * process_read_dbregs(proc, regs) + * Get the current user-visible register set from the process + * and copy it into the regs structure (). + * The process is stopped at the time read_dbregs is called. + * + * process_write_dbregs(proc, regs) + * Update the current register set from the passed in regs + * structure. Take care to avoid clobbering special CPU + * registers or privileged bits in the PSL. + * The process is stopped at the time write_dbregs is called. + * * process_sstep(proc) * Arrange for the process to trap after executing a single instruction. * * process_set_pc(proc) * Set the process's program counter. * - * process_count_watchpoints(proc, retval) - * Return the number of supported hardware watchpoints. - * - * process_read_watchpoint(proc, watchpoint) - * Read hardware watchpoint of the given index. - * - * process_write_watchpoint(proc, watchpoint) - * Write hardware watchpoint of the given index. - * */ #include @@ -140,6 +153,16 @@ return 0; } +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; +} + #ifdef PTRACE_HOOKS int process_write_regs(struct lwp *l, const struct reg *regs) @@ -205,6 +228,15 @@ return 0; } +int +process_write_dbregs(struct lwp *l, 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) Index: sys/arch/i386/i386/trap.c =================================================================== RCS file: /cvsroot/src/sys/arch/i386/i386/trap.c,v retrieving revision 1.283 diff -u -r1.283 trap.c --- sys/arch/i386/i386/trap.c 17 Feb 2017 01:14:31 -0000 1.283 +++ sys/arch/i386/i386/trap.c 18 Feb 2017 05:47:39 -0000 @@ -1,3 +1,4 @@ + /* $NetBSD: trap.c,v 1.283 2017/02/17 01:14:31 kamil Exp $ */ /*- @@ -681,6 +682,19 @@ } 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 (x86_dbregs_user_trap()) + break; + /* Check whether they single-stepped into a lcall. */ if (frame->tf_eip == (int)IDTVEC(osyscall)) return; @@ -700,10 +714,9 @@ KSI_INIT_TRAP(&ksi); ksi.ksi_signo = SIGTRAP; ksi.ksi_trap = type & ~T_USER; - if ((wptnfo = user_trap_x86_hw_watchpoint())) { + if (x86_dbregs_user_trap()) { + x86_dbregs_store_dr6(l); ksi.ksi_code = TRAP_DBREG; - ksi.ksi_trap2 = x86_hw_watchpoint_reg(wptnfo); - ksi.ksi_trap3 = x86_hw_watchpoint_type(wptnfo); } else if (type == (T_BPTFLT|T_USER)) ksi.ksi_code = TRAP_BRKPT; else Index: sys/arch/i386/include/pcb.h =================================================================== RCS file: /cvsroot/src/sys/arch/i386/include/pcb.h,v retrieving revision 1.54 diff -u -r1.54 pcb.h --- sys/arch/i386/include/pcb.h 21 Apr 2014 19:13:22 -0000 1.54 +++ sys/arch/i386/include/pcb.h 18 Feb 2017 05:47:39 -0000 @@ -93,8 +93,11 @@ int vm86_flagmask; /* flag mask for vm86 mode */ void *vm86_userp; /* XXX performance hack */ char *pcb_iomap; /* I/O permission bitmap */ + int pcb_flags; +#define PCB_USE_DBREGS 0x01 /* process is using debug registers */ + struct dbreg *pcb_dbreg; /* CPU Debug Registers */ - int not_used[15]; + int not_used[13]; /* floating point state */ struct cpu_info *pcb_fpcpu; /* cpu holding our fp state. */ Index: sys/arch/i386/include/proc.h =================================================================== RCS file: /cvsroot/src/sys/arch/i386/include/proc.h,v retrieving revision 1.43 diff -u -r1.43 proc.h --- sys/arch/i386/include/proc.h 15 Dec 2016 12:04:18 -0000 1.43 +++ sys/arch/i386/include/proc.h 18 Feb 2017 05:47:39 -0000 @@ -50,12 +50,10 @@ volatile int md_astpending; /* AST pending for this process */ struct pmap *md_gc_pmap; /* pmap being garbage collected */ struct vm_page *md_gc_ptp; /* pages from pmap g/c */ - struct x86_hw_watchpoint md_watchpoint[X86_HW_WATCHPOINTS]; }; /* md_flags */ #define MDL_IOPL 0x0002 /* XEN: i/o privilege */ -#define MDL_X86_HW_WATCHPOINTS 0x0004 /* has hardware watchpoints */ struct mdproc { int md_flags; Index: sys/arch/i386/include/ptrace.h =================================================================== RCS file: /cvsroot/src/sys/arch/i386/include/ptrace.h,v retrieving revision 1.17 diff -u -r1.17 ptrace.h --- sys/arch/i386/include/ptrace.h 16 Jan 2017 21:35:59 -0000 1.17 +++ sys/arch/i386/include/ptrace.h 18 Feb 2017 05:47:39 -0000 @@ -86,9 +86,8 @@ /* The machine-dependent ptrace(2) requests. */ #define PT_GETXMMREGS (PT_FIRSTMACH + 5) #define PT_SETXMMREGS (PT_FIRSTMACH + 6) -#define PT_READ_WATCHPOINT (PT_FIRSTMACH + 7) -#define PT_WRITE_WATCHPOINT (PT_FIRSTMACH + 8) -#define PT_COUNT_WATCHPOINTS (PT_FIRSTMACH + 9) +#define PT_GETDBREGS (PT_FIRSTMACH + 7) +#define PT_SETDBREGS (PT_FIRSTMACH + 8) #define PT_MACHDEP_STRINGS \ "PT_STEP", \ @@ -98,9 +97,9 @@ "PT_SETFPREGS", \ "PT_GETXMMREGS", \ "PT_SETXMMREGS", \ - "PT_READ_WATCHPOINT", \ - "PT_WRITE_WATCHPOINT", \ - "PT_COUNT_WATCHPOINTS" + "PT_GETDBREGS", \ + "PT_SETDBREGS", + #include #define PTRACE_REG_PC(r) (r)->r_eip @@ -112,50 +111,6 @@ #define PTRACE_BREAKPOINT_SIZE 1 #define PTRACE_BREAKPOINT_ADJ sizeof(PTRACE_BREAKPOINT) -#define __HAVE_PTRACE_WATCHPOINTS - -/* - * The current list of supported hardware watchpoints - */ -#define PTRACE_PW_TYPE_DBREGS 1 - -struct mdpw { - union { - /* Debug Registers DR0-3, DR6, DR7 */ - struct { - void *_md_address; - int _md_condition; - int _md_length; - } _dbregs; - } _type; -}; - -/* - * This MD structure translates into x86_hw_watchpoint - * - * pw_address - 0 represents disabled hardware watchpoint - * - * conditions: - * 0b00 - execution - * 0b01 - data write - * 0b10 - io read/write (not implemented) - * 0b11 - data read/write - * - * length: - * 0b00 - 1 byte - * 0b01 - 2 bytes - * 0b10 - undefined - * 0b11 - 4 bytes - * - * Helper symbols for conditions and length are available in - * - */ - -#define md_address _type._dbregs._md_address -#define md_condition _type._dbregs._md_condition -#define md_length _type._dbregs._md_length - - #ifdef _KERNEL /* Index: sys/arch/i386/include/reg.h =================================================================== RCS file: /cvsroot/src/sys/arch/i386/include/reg.h,v retrieving revision 1.19 diff -u -r1.19 reg.h --- sys/arch/i386/include/reg.h 16 Jan 2008 09:37:08 -0000 1.19 +++ sys/arch/i386/include/reg.h 18 Feb 2017 05:47:39 -0000 @@ -107,4 +107,16 @@ char __data[512]; }; +/* + * Debug Registers + * + * DR0-DR3 Debug Address Registers + * DR4-DR5 Reserved + * DR6 Debug Status Register + * DR7 Debug Control Register + */ +struct dbreg { + int dr[8]; +}; + #endif /* !_I386_REG_H_ */ Index: sys/arch/i386/include/userret.h =================================================================== RCS file: /cvsroot/src/sys/arch/i386/include/userret.h,v retrieving revision 1.13 diff -u -r1.13 userret.h --- sys/arch/i386/include/userret.h 16 Jan 2017 21:19:14 -0000 1.13 +++ sys/arch/i386/include/userret.h 18 Feb 2017 05:47:39 -0000 @@ -74,15 +74,13 @@ static __inline void userret(struct lwp *l) { + struct pcb *pcb = lwp_getpcb(l); /* Invoke MI userret code */ mi_userret(l); - /* - * Allow to mix debug registers with single step. - */ - if (l->l_md.md_flags & MDL_X86_HW_WATCHPOINTS) - set_x86_hw_watchpoints(l); + if (pcb->pcb_flags & PCB_USE_DBREGS) + x86_dbregs_enable(l); else - clear_x86_hw_watchpoints(); + x86_dbregs_clear(l); } Index: sys/arch/x86/include/dbregs.h =================================================================== RCS file: /cvsroot/src/sys/arch/x86/include/dbregs.h,v retrieving revision 1.3 diff -u -r1.3 dbregs.h --- sys/arch/x86/include/dbregs.h 18 Jan 2017 05:12:00 -0000 1.3 +++ sys/arch/x86/include/dbregs.h 18 Feb 2017 05:47:40 -0000 @@ -30,23 +30,22 @@ #ifndef _X86_DBREGS_H_ #define _X86_DBREGS_H_ -#if defined(_KERNEL) - #include #include +#include /* * CPU Debug Status Register (DR6) * * Reserved bits: 4-12 and on x86_64 32-64 */ -#define X86_HW_WATCHPOINT_DR6_DR0_BREAKPOINT_CONDITION_DETECTED __BIT(0) -#define X86_HW_WATCHPOINT_DR6_DR1_BREAKPOINT_CONDITION_DETECTED __BIT(1) -#define X86_HW_WATCHPOINT_DR6_DR2_BREAKPOINT_CONDITION_DETECTED __BIT(2) -#define X86_HW_WATCHPOINT_DR6_DR3_BREAKPOINT_CONDITION_DETECTED __BIT(3) -#define X86_HW_WATCHPOINT_DR6_DEBUG_REGISTER_ACCESS_DETECTED __BIT(13) -#define X86_HW_WATCHPOINT_DR6_SINGLE_STEP __BIT(14) -#define X86_HW_WATCHPOINT_DR6_TASK_SWITCH __BIT(15) +#define X86_DR6_DR0_BREAKPOINT_CONDITION_DETECTED __BIT(0) +#define X86_DR6_DR1_BREAKPOINT_CONDITION_DETECTED __BIT(1) +#define X86_DR6_DR2_BREAKPOINT_CONDITION_DETECTED __BIT(2) +#define X86_DR6_DR3_BREAKPOINT_CONDITION_DETECTED __BIT(3) +#define X86_DR6_DEBUG_REGISTER_ACCESS_DETECTED __BIT(13) +#define X86_DR6_SINGLE_STEP __BIT(14) +#define X86_DR6_TASK_SWITCH __BIT(15) /* * CPU Debug Control Register (DR7) @@ -57,108 +56,90 @@ * * Reserved bits: 10, 12, 14-15 and on x86_64 32-64 */ -#define X86_HW_WATCHPOINT_DR7_LOCAL_DR0_BREAKPOINT __BIT(0) -#define X86_HW_WATCHPOINT_DR7_GLOBAL_DR0_BREAKPOINT __BIT(1) -#define X86_HW_WATCHPOINT_DR7_LOCAL_DR1_BREAKPOINT __BIT(2) -#define X86_HW_WATCHPOINT_DR7_GLOBAL_DR1_BREAKPOINT __BIT(3) -#define X86_HW_WATCHPOINT_DR7_LOCAL_DR2_BREAKPOINT __BIT(4) -#define X86_HW_WATCHPOINT_DR7_GLOBAL_DR2_BREAKPOINT __BIT(5) -#define X86_HW_WATCHPOINT_DR7_LOCAL_DR3_BREAKPOINT __BIT(6) -#define X86_HW_WATCHPOINT_DR7_GLOBAL_DR3_BREAKPOINT __BIT(7) -#define X86_HW_WATCHPOINT_DR7_LOCAL_EXACT_BREAKPOINT __BIT(8) -#define X86_HW_WATCHPOINT_DR7_GLOBAL_EXACT_BREAKPOINT __BIT(9) -#define X86_HW_WATCHPOINT_DR7_RESTRICTED_TRANSACTIONAL_MEMORY __BIT(11) -#define X86_HW_WATCHPOINT_DR7_GENERAL_DETECT_ENABLE __BIT(13) - -#define X86_HW_WATCHPOINT_DR7_DR0_CONDITION_MASK __BITS(16, 17) -#define X86_HW_WATCHPOINT_DR7_DR0_LENGTH_MASK __BITS(18, 19) -#define X86_HW_WATCHPOINT_DR7_DR1_CONDITION_MASK __BITS(20, 21) -#define X86_HW_WATCHPOINT_DR7_DR1_LENGTH_MASK __BITS(22, 23) -#define X86_HW_WATCHPOINT_DR7_DR2_CONDITION_MASK __BITS(24, 25) -#define X86_HW_WATCHPOINT_DR7_DR2_LENGTH_MASK __BITS(26, 27) -#define X86_HW_WATCHPOINT_DR7_DR3_CONDITION_MASK __BITS(28, 29) -#define X86_HW_WATCHPOINT_DR7_DR3_LENGTH_MASK __BITS(30, 31) - -#endif /* !defined(_KERNEL) */ +#define X86_DR7_LOCAL_DR0_BREAKPOINT __BIT(0) +#define X86_DR7_GLOBAL_DR0_BREAKPOINT __BIT(1) +#define X86_DR7_LOCAL_DR1_BREAKPOINT __BIT(2) +#define X86_DR7_GLOBAL_DR1_BREAKPOINT __BIT(3) +#define X86_DR7_LOCAL_DR2_BREAKPOINT __BIT(4) +#define X86_DR7_GLOBAL_DR2_BREAKPOINT __BIT(5) +#define X86_DR7_LOCAL_DR3_BREAKPOINT __BIT(6) +#define X86_DR7_GLOBAL_DR3_BREAKPOINT __BIT(7) +#define X86_DR7_LOCAL_EXACT_BREAKPOINT __BIT(8) +#define X86_DR7_GLOBAL_EXACT_BREAKPOINT __BIT(9) +#define X86_DR7_RESTRICTED_TRANSACTIONAL_MEMORY __BIT(11) +#define X86_DR7_GENERAL_DETECT_ENABLE __BIT(13) + +#define X86_DR7_DR0_CONDITION_MASK __BITS(16, 17) +#define X86_DR7_DR0_LENGTH_MASK __BITS(18, 19) +#define X86_DR7_DR1_CONDITION_MASK __BITS(20, 21) +#define X86_DR7_DR1_LENGTH_MASK __BITS(22, 23) +#define X86_DR7_DR2_CONDITION_MASK __BITS(24, 25) +#define X86_DR7_DR2_LENGTH_MASK __BITS(26, 27) +#define X86_DR7_DR3_CONDITION_MASK __BITS(28, 29) +#define X86_DR7_DR3_LENGTH_MASK __BITS(30, 31) /* - * X86_HW_WATCHPOINT_DR7_CONDITION_IO_READWRITE is currently unused + * X86_DR7_CONDITION_IO_READWRITE is currently unused * it requires DE (debug extension) flag in control register CR4 set * not all CPUs support it */ -enum x86_hw_watchpoint_condition { - X86_HW_WATCHPOINT_DR7_CONDITION_EXECUTION = 0x0, - X86_HW_WATCHPOINT_DR7_CONDITION_DATA_WRITE = 0x1, - X86_HW_WATCHPOINT_DR7_CONDITION_IO_READWRITE = 0x2, - X86_HW_WATCHPOINT_DR7_CONDITION_DATA_READWRITE = 0x3 +enum x86_dr7_condition { + X86_DR7_CONDITION_EXECUTION = 0x0, + X86_DR7_CONDITION_DATA_WRITE = 0x1, + X86_DR7_CONDITION_IO_READWRITE = 0x2, + X86_DR7_CONDITION_DATA_READWRITE = 0x3 }; /* * 0x2 is currently unimplemented - it reflects 8 bytes on modern CPUs */ -enum x86_hw_watchpoint_length { - X86_HW_WATCHPOINT_DR7_LENGTH_BYTE = 0x0, - X86_HW_WATCHPOINT_DR7_LENGTH_TWOBYTES = 0x1, +enum x86_dr7_length { + X86_DR7_LENGTH_BYTE = 0x0, + X86_DR7_LENGTH_TWOBYTES = 0x1, /* 0x2 undefined */ - X86_HW_WATCHPOINT_DR7_LENGTH_FOURBYTES = 0x3 + X86_DR7_LENGTH_FOURBYTES = 0x3 }; /* - * 0x2 is currently unimplemented - it reflects 8 bytes on modern CPUs + * The number of available watchpoint/breakpoint registers available since + * Intel 80386. New CPUs (x86_64) ship with up to 16 Debug Registers but they + * still offer the same number of watchpoints/breakpoints. */ -enum x86_hw_watchpoint_event { - X86_HW_WATCHPOINT_EVENT_NONE = 0x0, - X86_HW_WATCHPOINT_EVENT_FIRED = 0x1, - X86_HW_WATCHPOINT_EVENT_FIRED_AND_SSTEP = 0x2, -}; - -#if defined(_KMEMUSER) || defined(_KERNEL) +#define X86_DBREGS 4 /* - * The number of available watchpoint registers available since Intel 80386 - * New CPUs ship with up to 16 Debug Registers but they still offer four - * watchpoints, while there other registers are reserved + * Reset CPU Debug Registers - to be used after entering kernel context */ -#define X86_HW_WATCHPOINTS 4 +void x86_dbregs_clear(struct lwp *l); /* - * lwpid - 0 means all LWPs in the process - * address - 0 means that watchpoint is disabled + * Retrieve Debug Registers from LWP's PCB and save in regs */ -struct x86_hw_watchpoint { - vaddr_t address; - enum x86_hw_watchpoint_condition condition; - enum x86_hw_watchpoint_length length; -}; - -#endif /* !defined(_KMEMUSER) && !defined(_KERNEL) */ +void x86_dbregs_read(struct lwp *l, struct dbreg *regs); -#if defined(_KERNEL) /* * Set CPU Debug Registers - to be used before entering user-land context */ -void set_x86_hw_watchpoints(struct lwp *l); +void x86_dbregs_set(struct lwp *l); /* - * Reset CPU Debug Registers - to be used after entering kernel context + * Store DR6 in LWP - to be used in trap function */ -void clear_x86_hw_watchpoints(void); +void x86_dbregs_store_dr6(struct lwp *l); /* * Check if trap is triggered from user-land if so return nonzero value */ -int user_trap_x86_hw_watchpoint(void); +int x86_dbregs_user_trap(void); /* * Check if trap is triggered from user-land if so return nonzero value */ -int x86_hw_watchpoint_type(int); +int x86_dbregs_validate(const struct dbreg *regs); /* - * Return register that fired + * Write new Debug Registers from regs into LWP's PCB */ -int x86_hw_watchpoint_reg(int); - -#endif /* !defined(_KERNEL) */ +void x86_dbregs_write(struct lwp *l, const struct dbreg *regs); #endif /* !_X86_DBREGS_H_ */ Index: sys/arch/x86/x86/dbregs.c =================================================================== RCS file: /cvsroot/src/sys/arch/x86/x86/dbregs.c,v retrieving revision 1.4 diff -u -r1.4 dbregs.c --- sys/arch/x86/x86/dbregs.c 18 Jan 2017 12:15:21 -0000 1.4 +++ sys/arch/x86/x86/dbregs.c 18 Feb 2017 05:47:40 -0000 @@ -38,129 +38,113 @@ #include -static void -set_x86_hw_watchpoint(size_t idx, vaddr_t address, - enum x86_hw_watchpoint_condition condition, - enum x86_hw_watchpoint_length length) -{ - register_t dr; - - KASSERT(address < VM_MAXUSER_ADDRESS); - - /* Read the original DR7 value in order to save existing watchpoints */ - dr = rdr7(); - - switch (idx) { - case 0: - ldr0(address); - dr |= X86_HW_WATCHPOINT_DR7_GLOBAL_DR0_BREAKPOINT; - dr |= __SHIFTIN(condition, - X86_HW_WATCHPOINT_DR7_DR0_CONDITION_MASK); - dr |= __SHIFTIN(length, - X86_HW_WATCHPOINT_DR7_DR0_LENGTH_MASK); - break; - case 1: - ldr1(address); - dr |= X86_HW_WATCHPOINT_DR7_GLOBAL_DR1_BREAKPOINT; - dr |= __SHIFTIN(condition, - X86_HW_WATCHPOINT_DR7_DR1_CONDITION_MASK); - dr |= __SHIFTIN(length, - X86_HW_WATCHPOINT_DR7_DR1_LENGTH_MASK); - break; - case 2: - ldr2(address); - dr |= X86_HW_WATCHPOINT_DR7_GLOBAL_DR2_BREAKPOINT; - dr |= __SHIFTIN(condition, - X86_HW_WATCHPOINT_DR7_DR2_CONDITION_MASK); - dr |= __SHIFTIN(length, - X86_HW_WATCHPOINT_DR7_DR2_LENGTH_MASK); - break; - case 3: - ldr3(address); - dr |= X86_HW_WATCHPOINT_DR7_GLOBAL_DR3_BREAKPOINT; - dr |= __SHIFTIN(condition, - X86_HW_WATCHPOINT_DR7_DR3_CONDITION_MASK); - dr |= __SHIFTIN(length, - X86_HW_WATCHPOINT_DR7_DR3_LENGTH_MASK); - break; - } - - ldr7(dr); -} +#define X86_BREAKPOINT_CONDITION_DETECTED ( \ + X86_DR6_DR0_BREAKPOINT_CONDITION_DETECTED | \ + X86_DR6_DR1_BREAKPOINT_CONDITION_DETECTED | \ + X86_DR6_DR2_BREAKPOINT_CONDITION_DETECTED | \ + X86_DR6_DR3_BREAKPOINT_CONDITION_DETECTED ) + +#define X86_GLOBAL_BREAKPOINT ( \ + X86_DR7_GLOBAL_DR0_BREAKPOINT | \ + X86_DR7_GLOBAL_DR1_BREAKPOINT | \ + X86_DR7_GLOBAL_DR2_BREAKPOINT | \ + X86_DR7_GLOBAL_DR3_BREAKPOINT ) + +#define X86_DR6_MASK ( \ + X86_DR6_DR0_BREAKPOINT_CONDITION_DETECTED | \ + X86_DR6_DR1_BREAKPOINT_CONDITION_DETECTED | \ + X86_DR6_DR2_BREAKPOINT_CONDITION_DETECTED | \ + X86_DR6_DR3_BREAKPOINT_CONDITION_DETECTED | \ + X86_DR6_DEBUG_REGISTER_ACCESS_DETECTED | \ + X86_DR6_SINGLE_STEP | \ + X86_DR6_TASK_SWITCH ) + +#define X86_DR7_MASK ( \ + X86_DR7_LOCAL_DR0_BREAKPOINT | \ + X86_DR7_GLOBAL_DR0_BREAKPOINT | \ + X86_DR7_LOCAL_DR1_BREAKPOINT | \ + X86_DR7_GLOBAL_DR1_BREAKPOINT | \ + X86_DR7_LOCAL_DR2_BREAKPOINT | \ + X86_DR7_GLOBAL_DR2_BREAKPOINT | \ + X86_DR7_LOCAL_DR3_BREAKPOINT | \ + X86_DR7_GLOBAL_DR3_BREAKPOINT | \ + X86_DR7_LOCAL_EXACT_BREAKPOINT | \ + X86_DR7_GLOBAL_EXACT_BREAKPOINT | \ + X86_DR7_RESTRICTED_TRANSACTIONAL_MEMORY | \ + X86_DR7_GENERAL_DETECT_ENABLE | \ + X86_DR7_DR0_CONDITION_MASK | \ + X86_DR7_DR0_LENGTH_MASK | \ + X86_DR7_DR1_CONDITION_MASK | \ + X86_DR7_DR1_LENGTH_MASK | \ + X86_DR7_DR2_CONDITION_MASK | \ + X86_DR7_DR2_LENGTH_MASK | \ + X86_DR7_DR3_CONDITION_MASK | \ + X86_DR7_DR3_LENGTH_MASK ) void -set_x86_hw_watchpoints(struct lwp *l) +x86_dbregs_clear(struct lwp *l) { - size_t i; + struct pcb *pcb = lwp_getpcb(l); - /* Assert that there are available watchpoints */ - KASSERT(l->l_md.md_flags & MDL_X86_HW_WATCHPOINTS); - - /* Clear Debug Control Register (DR7) first */ - ldr7(0); - - /* - * Clear Debug Status Register (DR6) as these bits are never cleared - * automatically by the processor - * - * Clear BREAKPOINT_CONDITION_DETECTED bits and ignore the rest - */ - ldr6(rdr6() & - ~(X86_HW_WATCHPOINT_DR6_DR0_BREAKPOINT_CONDITION_DETECTED | - X86_HW_WATCHPOINT_DR6_DR1_BREAKPOINT_CONDITION_DETECTED | - X86_HW_WATCHPOINT_DR6_DR2_BREAKPOINT_CONDITION_DETECTED | - X86_HW_WATCHPOINT_DR6_DR3_BREAKPOINT_CONDITION_DETECTED)); - - for (i = 0; i < X86_HW_WATCHPOINTS; i++) { - if (l->l_md.md_watchpoint[i].address != 0) { - set_x86_hw_watchpoint(i, - l->l_md.md_watchpoint[i].address, - l->l_md.md_watchpoint[i].condition, - l->l_md.md_watchpoint[i].length); - } - } -} - -void -clear_x86_hw_watchpoints(void) -{ + KASSERT((pcb->pcb_flags & PCB_USE_DBREGS) == 0); /* * It's sufficient to just disable Debug Control Register (DR7) * it will deactivate hardware watchpoints */ ldr7(0); + /* * However at some point we need to clear Debug Status Registers (DR6) * CPU will never do it automatically * * Clear BREAKPOINT_CONDITION_DETECTED bits and ignore the rest */ - ldr6(rdr6() & - ~(X86_HW_WATCHPOINT_DR6_DR0_BREAKPOINT_CONDITION_DETECTED | - X86_HW_WATCHPOINT_DR6_DR1_BREAKPOINT_CONDITION_DETECTED | - X86_HW_WATCHPOINT_DR6_DR2_BREAKPOINT_CONDITION_DETECTED | - X86_HW_WATCHPOINT_DR6_DR3_BREAKPOINT_CONDITION_DETECTED)); + ldr6(rdr6() & ~X86_BREAKPOINT_CONDITION_DETECTED); +} + +void +x86_dbregs_read(struct lwp *l, struct dbreg *regs) +{ + struct pcb *pcb = lwp_getpcb(l); + + memcpy(regs, pcb->pcb_dbregs, sizeof(*regs)); +} + +void +x86_dbregs_set(struct lwp *l) +{ + struct pcb *pcb = lwp_getpcb(l); + + KASSERT(pcb->pcb_flags & PCB_USE_DBREGS); + + ldr0(pcb->pcb_dbregs->dr[0]); + ldr1(pcb->pcb_dbregs->dr[1]); + ldr2(pcb->pcb_dbregs->dr[2]); + ldr3(pcb->pcb_dbregs->dr[3]); + + ldr6(pcb->pcb_dbregs->dr[6]); + ldr7(pcb->pcb_dbregs->dr[7]); } -/* Local temporary bitfield concept to compose event and register that fired */ -#define DR_EVENT_MASK __BITS(7,0) -#define DR_REGISTER_MASK __BITS(15,8) +void +x86_dbregs_store_dr6(struct lwp *l) +{ + struct pcb *pcb = lwp_getpcb(l); + + KASSERT(pcb->pcb_flags & PCB_USE_DBREGS); + + pcb->pcb_dbregs->dr[6] = rdr6(); +} int -user_trap_x86_hw_watchpoint(void) +x86_dbregs_user_trap(void) { register_t dr7, dr6; /* debug registers dr6 and dr7 */ register_t bp; /* breakpoint bits extracted from dr6 */ - register_t dr; /* temporary value of dr0-dr3 */ - int rv; /* register and event that fired (if any) */ dr7 = rdr7(); - if ((dr7 & - (X86_HW_WATCHPOINT_DR7_GLOBAL_DR0_BREAKPOINT | - X86_HW_WATCHPOINT_DR7_GLOBAL_DR1_BREAKPOINT | - X86_HW_WATCHPOINT_DR7_GLOBAL_DR2_BREAKPOINT | - X86_HW_WATCHPOINT_DR7_GLOBAL_DR3_BREAKPOINT)) == 0) { + if ((dr7 & X86_GLOBAL_BREAKPOINT) == 0) { /* * all Global Breakpoint bits in the DR7 register are zero, * thus the trap couldn't have been caused by the @@ -170,11 +154,7 @@ } dr6 = rdr6(); - bp = dr6 & \ - (X86_HW_WATCHPOINT_DR6_DR0_BREAKPOINT_CONDITION_DETECTED | - X86_HW_WATCHPOINT_DR6_DR1_BREAKPOINT_CONDITION_DETECTED | - X86_HW_WATCHPOINT_DR6_DR2_BREAKPOINT_CONDITION_DETECTED | - X86_HW_WATCHPOINT_DR6_DR3_BREAKPOINT_CONDITION_DETECTED); + bp = dr6 & X86_BREAKPOINT_CONDITION_DETECTED; if (!bp) { /* @@ -185,88 +165,58 @@ } /* - * Clear Status Register (DR6) now as it's not done by CPU. - * - * Clear BREAKPOINT_CONDITION_DETECTED and SINGLE_STEP bits and ignore - * the rest. - */ - ldr6(dr6 & - ~(X86_HW_WATCHPOINT_DR6_DR0_BREAKPOINT_CONDITION_DETECTED | - X86_HW_WATCHPOINT_DR6_DR1_BREAKPOINT_CONDITION_DETECTED | - X86_HW_WATCHPOINT_DR6_DR2_BREAKPOINT_CONDITION_DETECTED | - X86_HW_WATCHPOINT_DR6_DR3_BREAKPOINT_CONDITION_DETECTED | - X86_HW_WATCHPOINT_DR6_SINGLE_STEP)); - - /* * at least one of the breakpoints were hit, check to see * which ones and if any of them are user space addresses */ - if (bp & X86_HW_WATCHPOINT_DR6_DR0_BREAKPOINT_CONDITION_DETECTED) { - dr = rdr0(); - if (dr < (vaddr_t)VM_MAXUSER_ADDRESS) { - rv = 0; - if (bp & X86_HW_WATCHPOINT_DR6_SINGLE_STEP) - rv |= X86_HW_WATCHPOINT_EVENT_FIRED_AND_SSTEP; - else - rv |= X86_HW_WATCHPOINT_EVENT_FIRED; - return rv; - } - - } - - if (bp & X86_HW_WATCHPOINT_DR6_DR1_BREAKPOINT_CONDITION_DETECTED) { - dr = rdr1(); - if (dr < (vaddr_t)VM_MAXUSER_ADDRESS) { - rv = __SHIFTIN(1, DR_REGISTER_MASK); - if (bp & X86_HW_WATCHPOINT_DR6_SINGLE_STEP) - rv |= X86_HW_WATCHPOINT_EVENT_FIRED_AND_SSTEP; - else - rv |= X86_HW_WATCHPOINT_EVENT_FIRED; - return rv; - } - - } - - if (bp & X86_HW_WATCHPOINT_DR6_DR2_BREAKPOINT_CONDITION_DETECTED) { - dr = rdr2(); - if (dr < (vaddr_t)VM_MAXUSER_ADDRESS) { - rv = __SHIFTIN(2, DR_REGISTER_MASK); - if (bp & X86_HW_WATCHPOINT_DR6_SINGLE_STEP) - rv |= X86_HW_WATCHPOINT_EVENT_FIRED_AND_SSTEP; - else - rv |= X86_HW_WATCHPOINT_EVENT_FIRED; - return rv; - } - - } - - if (bp & X86_HW_WATCHPOINT_DR6_DR3_BREAKPOINT_CONDITION_DETECTED) { - dr = rdr3(); - if (dr < (vaddr_t)VM_MAXUSER_ADDRESS) { - rv = __SHIFTIN(3, DR_REGISTER_MASK); - if (bp & X86_HW_WATCHPOINT_DR6_SINGLE_STEP) - rv |= X86_HW_WATCHPOINT_EVENT_FIRED_AND_SSTEP; - else - rv |= X86_HW_WATCHPOINT_EVENT_FIRED; - return rv; - } - - } + if (bp & X86_DR6_DR0_BREAKPOINT_CONDITION_DETECTED) + if (rdr0() < (vaddr_t)VM_MAXUSER_ADDRESS) + return 1; + + if (bp & X86_DR6_DR1_BREAKPOINT_CONDITION_DETECTED) + if (rdr1() < (vaddr_t)VM_MAXUSER_ADDRESS) + return 1; + + if (bp & X86_DR6_DR2_BREAKPOINT_CONDITION_DETECTED) + if (rdr2() < (vaddr_t)VM_MAXUSER_ADDRESS) + return 1; + + if (bp & X86_DR6_DR3_BREAKPOINT_CONDITION_DETECTED) + if (rdr3() < (vaddr_t)VM_MAXUSER_ADDRESS) + return 1; return 0; } int -x86_hw_watchpoint_type(int wptnfo) +x86_dbregs_validate(const struct dbreg *regs) { + size_t i; + + for (i = 0; i < X86_DBREGS; i++) + if (regs->dr[i] > (vaddr_t)VM_MAXUSER_ADDRESS) + return EINVAL; + + /* CPU Debug Status Register (DR6) */ + if (regs->dr[6] & ~X86_DR6_MASK) + return EINVAL; + + /* CPU Debug Control Register (DR7) */ + if (regs->dr[7] & ~X86_DR7_MASK) + return EINVAL; - return __SHIFTOUT(wptnfo, DR_EVENT_MASK); + return 0; } -int -x86_hw_watchpoint_reg(int wptnfo) +void +x86_dbregs_write(struct lwp *l, const struct dbreg *regs) { + struct pcb *pcb = lwp_getpcb(l); + + memcpy(pcb->pcb_dbregs, regs, sizeof(*regs)); - return __SHIFTOUT(wptnfo, DR_REGISTER_MASK); + if (regs->dr[7] & X86_GLOBAL_BREAKPOINT) + pcb->pcb_flags |= PCB_USE_DBREGS; + else + pcb->pcb_flags &= ~PCB_USE_DBREGS; } Index: sys/arch/x86/x86/vm_machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/x86/x86/vm_machdep.c,v retrieving revision 1.27 diff -u -r1.27 vm_machdep.c --- sys/arch/x86/x86/vm_machdep.c 15 Dec 2016 12:04:18 -0000 1.27 +++ sys/arch/x86/x86/vm_machdep.c 18 Feb 2017 05:47:40 -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,10 @@ /* Copy any additional fpu state */ fpu_save_area_fork(pcb2, pcb1); + pcb2->pcb_dbregs = pool_get(&x86_dbregspl, PR_WAITOK); + /* Never inherit CPU Debug Registers */ + memset(pcb2->pcb_dbregs, 0, sizeof(*pcb2->pcb_dbregs)); + #if defined(XEN) pcb2->pcb_iopl = SEL_KPL; #endif @@ -231,12 +238,6 @@ pcb2->pcb_esp = (int)sf; pcb2->pcb_ebp = (int)l2; #endif - - /* - * Do not inherit hardware watchpoints. If they are desired, userland - * should do it on its own. - */ - memset(l2->l_md.md_watchpoint, 0, sizeof(*l2->l_md.md_watchpoint)); } /* @@ -247,6 +248,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); @@ -261,6 +265,8 @@ struct vm_page *empty_ptps = l->l_md.md_gc_ptp; l->l_md.md_gc_ptp = NULL; pmap_free_ptps(empty_ptps); + + pool_put(&x86_dbregspl, pcb->pcb_dbregs); } /* Index: sys/compat/netbsd32/netbsd32_ptrace.c =================================================================== RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_ptrace.c,v retrieving revision 1.3 diff -u -r1.3 netbsd32_ptrace.c --- sys/compat/netbsd32/netbsd32_ptrace.c 15 Dec 2016 12:04:18 -0000 1.3 +++ sys/compat/netbsd32/netbsd32_ptrace.c 18 Feb 2017 05:47:40 -0000 @@ -58,8 +58,7 @@ static void netbsd32_copyoutpiod(const struct ptrace_io_desc *, void *); static int netbsd32_doregs(struct lwp *, struct lwp *, struct uio *); static int netbsd32_dofpregs(struct lwp *, struct lwp *, struct uio *); -static int netbsd32_dowatchpoint(struct lwp *, struct lwp *, int, - struct ptrace_watchpoint *, void *, register_t *); +static int netbsd32_dodbregs(struct lwp *, struct lwp *, struct uio *); static int @@ -168,13 +167,41 @@ } static int -netbsd32_dowatchpoint(struct lwp *curl /*tracer*/, struct lwp *l /*traced*/, - int write, struct ptrace_watchpoint *pw, void *addr, register_t *retval) +netbsd32_dodbregs(struct lwp *curl /*tracer*/, + struct lwp *l /*traced*/, + struct uio *uio) { +#if defined(PT_GETDBREGS) || defined(PT_SETDBREGS) + process_dbreg32 r32; + int error; + char *kv; + size_t kl; - /* unimplemented */ + KASSERT(l->l_proc->p_flag & PK_32); + if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r32)) + return EINVAL; + kl = sizeof(r32); + kv = (char *)&r32; + + kv += uio->uio_offset; + kl -= uio->uio_offset; + if (kl > uio->uio_resid) + kl = uio->uio_resid; + error = process_read_dbregs32(l, &r32, &kl); + 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_dbregs32(l, &r32, kl); + } + uio->uio_offset = 0; + return error; +#else return EINVAL; +#endif } static struct ptrace_methods netbsd32_ptm = { @@ -182,7 +209,7 @@ .ptm_copyoutpiod = netbsd32_copyoutpiod, .ptm_doregs = netbsd32_doregs, .ptm_dofpregs = netbsd32_dofpregs, - .ptm_dowatchpoint = netbsd32_dowatchpoint + .ptm_dodbregs = netbsd32_dodbregs }; Index: sys/kern/sys_ptrace.c =================================================================== RCS file: /cvsroot/src/sys/kern/sys_ptrace.c,v retrieving revision 1.3 diff -u -r1.3 sys_ptrace.c --- sys/kern/sys_ptrace.c 15 Dec 2016 12:04:18 -0000 1.3 +++ sys/kern/sys_ptrace.c 18 Feb 2017 05:47:40 -0000 @@ -169,7 +169,7 @@ .ptm_copyoutpiod = ptrace_copyoutpiod, .ptm_doregs = process_doregs, .ptm_dofpregs = process_dofpregs, - .ptm_dowatchpoint = process_dowatchpoint, + .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.14 diff -u -r1.14 sys_ptrace_common.c --- sys/kern/sys_ptrace_common.c 12 Feb 2017 06:09:52 -0000 1.14 +++ sys/kern/sys_ptrace_common.c 18 Feb 2017 05:47:40 -0000 @@ -202,10 +202,11 @@ #ifdef PT_SETFPREGS case PT_SETFPREGS: #endif -#ifdef __HAVE_PTRACE_WATCHPOINTS - case PT_READ_WATCHPOINT: - case PT_WRITE_WATCHPOINT: - case PT_COUNT_WATCHPOINTS: +#ifdef PT_GETDBREGS + case PT_GETDBREGS: +#endif +#ifdef PT_SETDBREGS + case PT_SETDBREGS: #endif case PT_SET_EVENT_MASK: case PT_GET_EVENT_MASK: @@ -305,9 +306,6 @@ struct ptrace_state ps; struct ptrace_lwpinfo pl; struct ptrace_siginfo psi; -#ifdef __HAVE_PTRACE_WATCHPOINTS - struct ptrace_watchpoint pw; -#endif struct vmspace *vm; int error, write, tmp, pheld; int signo = 0; @@ -422,10 +420,11 @@ #ifdef PT_SETFPREGS case PT_SETFPREGS: #endif -#ifdef __HAVE_PTRACE_WATCHPOINTS - case PT_READ_WATCHPOINT: - case PT_WRITE_WATCHPOINT: - case PT_COUNT_WATCHPOINTS: +#ifdef PT_GETDBREGS + case PT_GETDBREGS: +#endif +#ifdef PT_SETDBREGS + case PT_SETDBREGS: #endif #ifdef __HAVE_PTRACE_MACHDEP PTRACE_MACHDEP_REQUEST_CASES @@ -1159,29 +1158,17 @@ break; #endif -#ifdef __HAVE_PTRACE_WATCHPOINTS - /* - * The "write" variable is used as type of operation. - * Possible values: - * 0 - return the number of supported hardware watchpoints - * 1 - set new watchpoint value - * 2 - get existing watchpoint image - */ - case PT_WRITE_WATCHPOINT: +#ifdef PT_SETDBREGS + case PT_SETDBREGS: write = 1; - case PT_READ_WATCHPOINT: - /* write = 0 done above */ - - if (data != sizeof(pw)) { - DPRINTF(("ptrace(%d): %d != %zu\n", req, - data, sizeof(pe))); - error = EINVAL; - break; - } - error = copyin(addr, &pw, sizeof(pw)); - if (error) - break; - tmp = pw.pw_lwpid; + /*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); @@ -1194,15 +1181,23 @@ lwp_addref(lt); mutex_exit(t->p_lock); } - ++write; - case PT_COUNT_WATCHPOINTS: - if (!process_validwatchpoint(lt)) + if (!process_validdbregs(lt)) error = EINVAL; else { - lwp_lock(lt); - error = ptm->ptm_dowatchpoint(l, lt, write, &pw, addr, - retval); - lwp_unlock(lt); + 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 @@ -1324,6 +1319,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, &kl); + 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, kl); + } + 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) { @@ -1349,45 +1393,6 @@ #endif return 0; } - -int -process_dowatchpoint(struct lwp *curl /*tracer*/, struct lwp *l /*traced*/, - int operation, struct ptrace_watchpoint *pw, void *addr, - register_t *retval) -{ - -#ifdef __HAVE_PTRACE_WATCHPOINTS - int error; - - KASSERT(operation >= 0); - KASSERT(operation <= 2); - - switch (operation) { - case 0: - return process_count_watchpoints(l, retval); - case 1: - error = process_read_watchpoint(l, pw); - if (error) - return error; - return copyout(pw, addr, sizeof(*pw)); - default: - return process_write_watchpoint(l, pw); - } -#else - return EINVAL; -#endif -} - -int -process_validwatchpoint(struct lwp *l) -{ - -#ifdef __HAVE_PTRACE_WATCHPOINTS - return (l->l_flag & LW_SYSTEM) == 0; -#else - return 0; -#endif -} #endif /* PTRACE */ MODULE(MODULE_CLASS_EXEC, ptrace_common, ""); Index: sys/sys/proc.h =================================================================== RCS file: /cvsroot/src/sys/sys/proc.h,v retrieving revision 1.337 diff -u -r1.337 proc.h --- sys/sys/proc.h 14 Jan 2017 06:36:52 -0000 1.337 +++ sys/sys/proc.h 18 Feb 2017 05:47:40 -0000 @@ -573,6 +573,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.56 diff -u -r1.56 ptrace.h --- sys/sys/ptrace.h 12 Feb 2017 06:09:52 -0000 1.56 +++ sys/sys/ptrace.h 18 Feb 2017 05:47:40 -0000 @@ -139,20 +139,6 @@ #define PL_EVENT_SIGNAL 1 /* - * Hardware Watchpoints - * - * MD code handles switch informing whether a particular watchpoint is enabled - */ -typedef struct ptrace_watchpoint { - int pw_index; /* HW Watchpoint ID (count from 0) */ - lwpid_t pw_lwpid; /* LWP described */ - int pw_type; /* HW Watchpoint type w/ MD content */ -#ifdef __HAVE_PTRACE_WATCHPOINTS - struct mdpw pw_md; /* MD fields */ -#endif -} ptrace_watchpoint_t; - -/* * Signal Information structure */ typedef struct ptrace_siginfo { @@ -173,6 +159,7 @@ #define process_reg64 struct reg #endif #endif + #if defined(PT_GETFPREGS) || defined(PT_SETFPREGS) struct fpreg; #ifndef process_fpreg32 @@ -182,12 +169,14 @@ #define process_fpreg64 struct fpreg #endif #endif -#ifdef __HAVE_PTRACE_WATCHPOINTS -#ifndef process_watchpoint32 -#define process_watchpoint32 struct ptrace_watchpoint + +#if defined(PT_GETDBREGS) || defined(PT_SETDBREGS) +struct fpreg; +#ifndef process_dbreg32 +#define process_dbreg32 struct dbreg #endif -#ifndef process_watchpoint64 -#define process_watchpoint64 struct ptrace_watchpoint +#ifndef process_dbreg64 +#define process_dbreg64 struct dbreg #endif #endif @@ -196,8 +185,7 @@ 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_dowatchpoint)(struct lwp *, struct lwp *, int, - struct ptrace_watchpoint *, void *, register_t *); + int (*ptm_dodbregs)(struct lwp *, struct lwp *, struct uio *); }; int ptrace_init(void); @@ -210,9 +198,8 @@ int process_dofpregs(struct lwp *, struct lwp *, struct uio *); int process_validfpregs(struct lwp *); -int process_dowatchpoint(struct lwp *, struct lwp *, int, - struct ptrace_watchpoint *, void *, register_t *); -int process_validwatchpoint(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 *); @@ -230,6 +217,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 *, size_t *); +#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 @@ -250,6 +246,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 *, size_t); +#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 @@ -269,32 +274,6 @@ #endif #endif -#ifdef __HAVE_PTRACE_WATCHPOINTS -int process_count_watchpoints(struct lwp *, register_t *retval); -#ifndef process_count_watchpoints32 -#define process_count_watchpoints32 process_count_watchpoints -#endif -#ifndef process_count_watchpoints64 -#define process_count_watchpoints64 process_count_watchpoints -#endif - -int process_read_watchpoint(struct lwp *, struct ptrace_watchpoint *); -#ifndef process_read_watchpoint32 -#define process_read_watchpoint32 process_read_watchpoint -#endif -#ifndef process_read_watchpoint64 -#define process_read_watchpoint64 process_read_watchpoint -#endif - -int process_write_watchpoint(struct lwp *, struct ptrace_watchpoint *); -#ifndef process_write_watchpoint32 -#define process_write_watchpoint32 process_write_watchpoint -#endif -#ifndef process_write_watchpoint64 -#define process_write_watchpoint64 process_write_watchpoint -#endif -#endif - int ptrace_machdep_dorequest(struct lwp *, struct lwp *, int, void *, int);