return err;
}
*/
+
+int get_user_pages_uprobe(struct task_struct *tsk, struct mm_struct *mm,
+ unsigned long start, int len, int write, int force,
+ struct page **pages, struct vm_area_struct **vmas);
/**
* hlist_replace_rcu - replace old entry by new one
* @old : the element to be replaced
if (ctask && ctask->active_mm)
{
- ret = get_user_pages_atomic (ctask, ctask->active_mm, (unsigned long) addr, 1, 0, 0, &tpage, NULL);
+ ret = get_user_pages_uprobe (ctask, ctask->active_mm, (unsigned long) addr, 1, 0, 0, &tpage, NULL);
if (ret <= 0)
DBPRINTF ("get_user_pages for task %d at %p failed!", current->pid, addr);
else
{
if (page_present (task->active_mm, (unsigned long) p->addr))
{
- ret = get_user_pages_atomic (task, task->active_mm, (unsigned long) p->addr, 1, 0, 0, &page, &vma);
+ ret = get_user_pages_uprobe (task, task->active_mm, (unsigned long) p->addr, 1, 0, 0, &page, &vma);
if (ret <= 0)
DBPRINTF ("get_user_pages for task %d at %p failed!", p->tgid, p->addr);
}
rp->nmissed = 0;
#if 0
- if (atomic)
- ret = get_user_pages_atomic (task, mm, (unsigned long) rp->kp.addr, 1, 1, 1, &pages[0], &vmas[0]);
- else
- ret = get_user_pages (task, mm, (unsigned long) rp->kp.addr, 1, 1, 1, &pages[0], &vmas[0]);
+ ret = get_user_pages_uprobe (task, mm, (unsigned long) rp->kp.addr, 1, 1, 1, &pages[0], &vmas[0]);
if (ret <= 0)
{
DBPRINTF ("get_user_pages for %p failed!", rp->kp.addr);
// if 2nd instruction is on the 2nd page
if ((((unsigned long) (rp->kp.addr + 1)) & ~PAGE_MASK) == 0)
{
- if (atomic)
- ret = get_user_pages_atomic (task, mm, (unsigned long) (rp->kp.addr + 1), 1, 1, 1, &pages[1], &vmas[1]);
- else
- ret = get_user_pages (task, mm, (unsigned long) (rp->kp.addr + 1), 1, 1, 1, &pages[1], &vmas[1]);
+ ret = get_user_pages_uprobe (task, mm, (unsigned long) (rp->kp.addr + 1), 1, 1, 1, &pages[1], &vmas[1]);
if (ret <= 0)
{
DBPRINTF ("get_user_pages for %p failed!", rp->kp.addr + 1);
#endif
return;
}
- if (atomic)
- ret = get_user_pages_atomic (task, mm, (unsigned long) rp->kp.addr, 1, 1, 1, &pages[0], &vmas[0]);
- else
- {
- down_read (&mm->mmap_sem);
- ret = get_user_pages (task, mm, (unsigned long) rp->kp.addr, 1, 1, 1, &pages[0], &vmas[0]);
- }
+ down_read (&mm->mmap_sem);
+ ret = get_user_pages_uprobe (task, mm, (unsigned long) rp->kp.addr, 1, 1, 1, &pages[0], &vmas[0]);
+
if (ret <= 0)
{
DBPRINTF ("get_user_pages for %p failed!", rp->kp.addr);
kaddrs[0] = kmap (pages[0]) + ((unsigned long) rp->kp.addr & ~PAGE_MASK);
if ((((unsigned long) (rp->kp.addr + 1)) & ~PAGE_MASK) == 0)
{
- if (atomic)
- ret = get_user_pages_atomic (task, mm, (unsigned long) (rp->kp.addr + 1), 1, 1, 1, &pages[1], &vmas[1]);
- else
- ret = get_user_pages (task, mm, (unsigned long) (rp->kp.addr + 1), 1, 1, 1, &pages[1], &vmas[1]);
+
+ ret = get_user_pages_uprobe (task, mm, (unsigned long) (rp->kp.addr + 1), 1, 1, 1, &pages[1], &vmas[1]);
if (ret <= 0)
{
DBPRINTF ("get_user_pages for %p failed!", rp->kp.addr + 1);
#define GUP_FLAGS_IGNORE_VMA_PERMISSIONS 0x4
#define GUP_FLAGS_IGNORE_SIGKILL 0x8
-
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
static inline int use_zero_page(struct vm_area_struct *vma)
{
/*
*/
return !vma->vm_ops || !vma->vm_ops->fault;
}
+#endif
int __get_user_pages_uprobe(struct task_struct *tsk, struct mm_struct *mm,
unsigned long start, int len, int flags,
return i ? : -EFAULT;
if (is_vm_hugetlb_page(vma)) {
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
+ i = follow_hugetlb_page(mm, vma, pages, vmas,
+ &start, &len, i);
+#else
i = follow_hugetlb_page(mm, vma, pages, vmas,
&start, &len, i, write);
+#endif
continue;
}
foll_flags = FOLL_TOUCH;
if (pages)
foll_flags |= FOLL_GET;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,30)
if (!write && use_zero_page(vma))
foll_flags |= FOLL_ANON;
+#endif
+#endif
do {
struct page *page;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
/*
* If we have a pending SIGKILL, don't keep faulting
* pages and potentially allocating memory, unless
if (unlikely(!ignore_sigkill &&
fatal_signal_pending(current)))
return i ? i : -ERESTARTSYS;
+#endif
if (write)
foll_flags |= FOLL_WRITE;
int ret;
ret = handle_mm_fault(mm, vma, start,
foll_flags & FOLL_WRITE);
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
+ if (ret & VM_FAULT_WRITE)
+ foll_flags &= ~FOLL_WRITE;
+
+ switch (ret & ~VM_FAULT_WRITE) {
+ case VM_FAULT_MINOR:
+ tsk->min_flt++;
+ break;
+ case VM_FAULT_MAJOR:
+ tsk->maj_flt++;
+ break;
+ case VM_FAULT_SIGBUS:
+ return i ? i : -EFAULT;
+ case VM_FAULT_OOM:
+ return i ? i : -ENOMEM;
+ default:
+ BUG();
+ }
+
+#else
if (ret & VM_FAULT_ERROR) {
- if (ret & VM_FAULT_OOM)
- return i ? i : -ENOMEM;
- else if (ret & VM_FAULT_SIGBUS)
- return i ? i : -EFAULT;
- BUG();
+ if (ret & VM_FAULT_OOM)
+ return i ? i : -ENOMEM;
+ else if (ret & VM_FAULT_SIGBUS)
+ return i ? i : -EFAULT;
+ BUG();
}
if (ret & VM_FAULT_MAJOR)
- tsk->maj_flt++;
+ tsk->maj_flt++;
else
- tsk->min_flt++;
-
+ tsk->min_flt++;
+
/*
* The VM_FAULT_WRITE bit tells us that
* do_wp_page has broken COW when necessary,
*/
if ((ret & VM_FAULT_WRITE) &&
!(vma->vm_flags & VM_WRITE))
- foll_flags &= ~FOLL_WRITE;
-
+ foll_flags &= ~FOLL_WRITE;
+
//cond_resched();
+#endif
+
}
+
if (IS_ERR(page))
return i ? i : PTR_ERR(page);
if (pages) {
pages[i] = page;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
+ flush_anon_page(page, start);
+#else
flush_anon_page(vma, page, start);
+#endif
flush_dcache_page(page);
}
if (vmas)
unsigned long start, int len, int write, int force,
struct page **pages, struct vm_area_struct **vmas)
{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
int flags = 0;
if (write)
return __get_user_pages_uprobe(tsk, mm,
start, len, flags,
pages, vmas);
+#else
+ return get_user_pages(tsk, mm,
+ start, len, write, force,
+ pages, vmas);
+#endif
}
int