12b144498SSrikar Dronamraju #ifndef _LINUX_UPROBES_H 22b144498SSrikar Dronamraju #define _LINUX_UPROBES_H 32b144498SSrikar Dronamraju /* 47b2d81d4SIngo Molnar * User-space Probes (UProbes) 52b144498SSrikar Dronamraju * 62b144498SSrikar Dronamraju * This program is free software; you can redistribute it and/or modify 72b144498SSrikar Dronamraju * it under the terms of the GNU General Public License as published by 82b144498SSrikar Dronamraju * the Free Software Foundation; either version 2 of the License, or 92b144498SSrikar Dronamraju * (at your option) any later version. 102b144498SSrikar Dronamraju * 112b144498SSrikar Dronamraju * This program is distributed in the hope that it will be useful, 122b144498SSrikar Dronamraju * but WITHOUT ANY WARRANTY; without even the implied warranty of 132b144498SSrikar Dronamraju * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 142b144498SSrikar Dronamraju * GNU General Public License for more details. 152b144498SSrikar Dronamraju * 162b144498SSrikar Dronamraju * You should have received a copy of the GNU General Public License 172b144498SSrikar Dronamraju * along with this program; if not, write to the Free Software 182b144498SSrikar Dronamraju * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 192b144498SSrikar Dronamraju * 2035aa621bSIngo Molnar * Copyright (C) IBM Corporation, 2008-2012 212b144498SSrikar Dronamraju * Authors: 222b144498SSrikar Dronamraju * Srikar Dronamraju 232b144498SSrikar Dronamraju * Jim Keniston 2435aa621bSIngo Molnar * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> 252b144498SSrikar Dronamraju */ 262b144498SSrikar Dronamraju 272b144498SSrikar Dronamraju #include <linux/errno.h> 282b144498SSrikar Dronamraju #include <linux/rbtree.h> 292b144498SSrikar Dronamraju 302b144498SSrikar Dronamraju struct vm_area_struct; 31*d4b3b638SSrikar Dronamraju struct mm_struct; 32*d4b3b638SSrikar Dronamraju struct inode; 330326f5a9SSrikar Dronamraju 342b144498SSrikar Dronamraju #ifdef CONFIG_ARCH_SUPPORTS_UPROBES 352b144498SSrikar Dronamraju # include <asm/uprobes.h> 362b144498SSrikar Dronamraju #endif 372b144498SSrikar Dronamraju 382b144498SSrikar Dronamraju /* flags that denote/change uprobes behaviour */ 397b2d81d4SIngo Molnar 402b144498SSrikar Dronamraju /* Have a copy of original instruction */ 41900771a4SSrikar Dronamraju #define UPROBE_COPY_INSN 0x1 427b2d81d4SIngo Molnar 432b144498SSrikar Dronamraju /* Dont run handlers when first register/ last unregister in progress*/ 44900771a4SSrikar Dronamraju #define UPROBE_RUN_HANDLER 0x2 450326f5a9SSrikar Dronamraju /* Can skip singlestep */ 460326f5a9SSrikar Dronamraju #define UPROBE_SKIP_SSTEP 0x4 472b144498SSrikar Dronamraju 482b144498SSrikar Dronamraju struct uprobe_consumer { 492b144498SSrikar Dronamraju int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs); 502b144498SSrikar Dronamraju /* 512b144498SSrikar Dronamraju * filter is optional; If a filter exists, handler is run 522b144498SSrikar Dronamraju * if and only if filter returns true. 532b144498SSrikar Dronamraju */ 542b144498SSrikar Dronamraju bool (*filter)(struct uprobe_consumer *self, struct task_struct *task); 552b144498SSrikar Dronamraju 562b144498SSrikar Dronamraju struct uprobe_consumer *next; 572b144498SSrikar Dronamraju }; 582b144498SSrikar Dronamraju 592b144498SSrikar Dronamraju #ifdef CONFIG_UPROBES 600326f5a9SSrikar Dronamraju enum uprobe_task_state { 610326f5a9SSrikar Dronamraju UTASK_RUNNING, 620326f5a9SSrikar Dronamraju UTASK_BP_HIT, 630326f5a9SSrikar Dronamraju UTASK_SSTEP, 640326f5a9SSrikar Dronamraju UTASK_SSTEP_ACK, 650326f5a9SSrikar Dronamraju UTASK_SSTEP_TRAPPED, 660326f5a9SSrikar Dronamraju }; 670326f5a9SSrikar Dronamraju 680326f5a9SSrikar Dronamraju /* 690326f5a9SSrikar Dronamraju * uprobe_task: Metadata of a task while it singlesteps. 700326f5a9SSrikar Dronamraju */ 710326f5a9SSrikar Dronamraju struct uprobe_task { 720326f5a9SSrikar Dronamraju enum uprobe_task_state state; 730326f5a9SSrikar Dronamraju struct arch_uprobe_task autask; 740326f5a9SSrikar Dronamraju 750326f5a9SSrikar Dronamraju struct uprobe *active_uprobe; 760326f5a9SSrikar Dronamraju 770326f5a9SSrikar Dronamraju unsigned long xol_vaddr; 780326f5a9SSrikar Dronamraju unsigned long vaddr; 790326f5a9SSrikar Dronamraju }; 800326f5a9SSrikar Dronamraju 81*d4b3b638SSrikar Dronamraju /* 82*d4b3b638SSrikar Dronamraju * On a breakpoint hit, thread contests for a slot. It frees the 83*d4b3b638SSrikar Dronamraju * slot after singlestep. Currently a fixed number of slots are 84*d4b3b638SSrikar Dronamraju * allocated. 85*d4b3b638SSrikar Dronamraju */ 86*d4b3b638SSrikar Dronamraju struct xol_area { 87*d4b3b638SSrikar Dronamraju wait_queue_head_t wq; /* if all slots are busy */ 88*d4b3b638SSrikar Dronamraju atomic_t slot_count; /* number of in-use slots */ 89*d4b3b638SSrikar Dronamraju unsigned long *bitmap; /* 0 = free slot */ 90*d4b3b638SSrikar Dronamraju struct page *page; 91*d4b3b638SSrikar Dronamraju 92*d4b3b638SSrikar Dronamraju /* 93*d4b3b638SSrikar Dronamraju * We keep the vma's vm_start rather than a pointer to the vma 94*d4b3b638SSrikar Dronamraju * itself. The probed process or a naughty kernel module could make 95*d4b3b638SSrikar Dronamraju * the vma go away, and we must handle that reasonably gracefully. 96*d4b3b638SSrikar Dronamraju */ 97*d4b3b638SSrikar Dronamraju unsigned long vaddr; /* Page(s) of instruction slots */ 98*d4b3b638SSrikar Dronamraju }; 99*d4b3b638SSrikar Dronamraju 100*d4b3b638SSrikar Dronamraju struct uprobes_state { 101*d4b3b638SSrikar Dronamraju struct xol_area *xol_area; 102*d4b3b638SSrikar Dronamraju }; 1035cb4ac3aSSrikar Dronamraju extern int __weak set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); 104e3343e6aSSrikar Dronamraju extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr, bool verify); 1055cb4ac3aSSrikar Dronamraju extern bool __weak is_swbp_insn(uprobe_opcode_t *insn); 106e3343e6aSSrikar Dronamraju extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); 107e3343e6aSSrikar Dronamraju extern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); 1087b2d81d4SIngo Molnar extern int uprobe_mmap(struct vm_area_struct *vma); 1090326f5a9SSrikar Dronamraju extern void uprobe_free_utask(struct task_struct *t); 1100326f5a9SSrikar Dronamraju extern void uprobe_copy_process(struct task_struct *t); 1110326f5a9SSrikar Dronamraju extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs); 1120326f5a9SSrikar Dronamraju extern int uprobe_post_sstep_notifier(struct pt_regs *regs); 1130326f5a9SSrikar Dronamraju extern int uprobe_pre_sstep_notifier(struct pt_regs *regs); 1140326f5a9SSrikar Dronamraju extern void uprobe_notify_resume(struct pt_regs *regs); 1150326f5a9SSrikar Dronamraju extern bool uprobe_deny_signal(void); 1160326f5a9SSrikar Dronamraju extern bool __weak arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs); 117*d4b3b638SSrikar Dronamraju extern void uprobe_clear_state(struct mm_struct *mm); 118*d4b3b638SSrikar Dronamraju extern void uprobe_reset_state(struct mm_struct *mm); 1190326f5a9SSrikar Dronamraju #else /* !CONFIG_UPROBES */ 120*d4b3b638SSrikar Dronamraju struct uprobes_state { 121*d4b3b638SSrikar Dronamraju }; 1227b2d81d4SIngo Molnar static inline int 123e3343e6aSSrikar Dronamraju uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc) 1242b144498SSrikar Dronamraju { 1252b144498SSrikar Dronamraju return -ENOSYS; 1262b144498SSrikar Dronamraju } 1277b2d81d4SIngo Molnar static inline void 128e3343e6aSSrikar Dronamraju uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc) 1292b144498SSrikar Dronamraju { 1302b144498SSrikar Dronamraju } 1317b2d81d4SIngo Molnar static inline int uprobe_mmap(struct vm_area_struct *vma) 1322b144498SSrikar Dronamraju { 1332b144498SSrikar Dronamraju return 0; 1342b144498SSrikar Dronamraju } 1350326f5a9SSrikar Dronamraju static inline void uprobe_notify_resume(struct pt_regs *regs) 1360326f5a9SSrikar Dronamraju { 1370326f5a9SSrikar Dronamraju } 1380326f5a9SSrikar Dronamraju static inline bool uprobe_deny_signal(void) 1390326f5a9SSrikar Dronamraju { 1400326f5a9SSrikar Dronamraju return false; 1410326f5a9SSrikar Dronamraju } 1420326f5a9SSrikar Dronamraju static inline unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) 1430326f5a9SSrikar Dronamraju { 1440326f5a9SSrikar Dronamraju return 0; 1450326f5a9SSrikar Dronamraju } 1460326f5a9SSrikar Dronamraju static inline void uprobe_free_utask(struct task_struct *t) 1470326f5a9SSrikar Dronamraju { 1480326f5a9SSrikar Dronamraju } 1490326f5a9SSrikar Dronamraju static inline void uprobe_copy_process(struct task_struct *t) 1500326f5a9SSrikar Dronamraju { 1510326f5a9SSrikar Dronamraju } 152*d4b3b638SSrikar Dronamraju static inline void uprobe_clear_state(struct mm_struct *mm) 153*d4b3b638SSrikar Dronamraju { 154*d4b3b638SSrikar Dronamraju } 155*d4b3b638SSrikar Dronamraju static inline void uprobe_reset_state(struct mm_struct *mm) 156*d4b3b638SSrikar Dronamraju { 157*d4b3b638SSrikar Dronamraju } 1580326f5a9SSrikar Dronamraju #endif /* !CONFIG_UPROBES */ 1592b144498SSrikar Dronamraju #endif /* _LINUX_UPROBES_H */ 160