hmm.c (9f454612f602d02204b1f6e86b6bec2bfb368c4b) hmm.c (25f23a0c7127b65c4d8200ccda8a352ad5ce1e1d)
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *

--- 688 unchanged lines hidden (view full) ---

697{
698 unsigned long addr = range->start, i = 0;
699
700 for (; addr < range->end; addr += PAGE_SIZE, i++)
701 range->pfns[i] = range->values[HMM_PFN_SPECIAL];
702}
703
704/*
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *

--- 688 unchanged lines hidden (view full) ---

697{
698 unsigned long addr = range->start, i = 0;
699
700 for (; addr < range->end; addr += PAGE_SIZE, i++)
701 range->pfns[i] = range->values[HMM_PFN_SPECIAL];
702}
703
704/*
705 * hmm_vma_get_pfns() - snapshot CPU page table for a range of virtual addresses
706 * @range: range being snapshotted
707 * Returns: -EINVAL if invalid argument, -ENOMEM out of memory, -EPERM invalid
708 * vma permission, 0 success
705 * hmm_range_snapshot() - snapshot CPU page table for a range
706 * @range: range
707 * Returns: number of valid pages in range->pfns[] (from range start
708 * address). This may be zero. If the return value is negative,
709 * then one of the following values may be returned:
709 *
710 *
711 * -EINVAL invalid arguments or mm or virtual address are in an
712 * invalid vma (ie either hugetlbfs or device file vma).
713 * -EPERM For example, asking for write, when the range is
714 * read-only
715 * -EAGAIN Caller needs to retry
716 * -EFAULT Either no valid vma exists for this range, or it is
717 * illegal to access the range
718 *
710 * This snapshots the CPU page table for a range of virtual addresses. Snapshot
711 * validity is tracked by range struct. See hmm_vma_range_done() for further
712 * information.
719 * This snapshots the CPU page table for a range of virtual addresses. Snapshot
720 * validity is tracked by range struct. See hmm_vma_range_done() for further
721 * information.
713 *
714 * The range struct is initialized here. It tracks the CPU page table, but only
715 * if the function returns success (0), in which case the caller must then call
716 * hmm_vma_range_done() to stop CPU page table update tracking on this range.
717 *
718 * NOT CALLING hmm_vma_range_done() IF FUNCTION RETURNS 0 WILL LEAD TO SERIOUS
719 * MEMORY CORRUPTION ! YOU HAVE BEEN WARNED !
720 */
722 */
721int hmm_vma_get_pfns(struct hmm_range *range)
723long hmm_range_snapshot(struct hmm_range *range)
722{
723 struct vm_area_struct *vma = range->vma;
724 struct hmm_vma_walk hmm_vma_walk;
725 struct mm_walk mm_walk;
726 struct hmm *hmm;
727
728 range->hmm = NULL;
729

--- 37 unchanged lines hidden (view full) ---

767 spin_lock(&hmm->lock);
768 range->valid = true;
769 list_add_rcu(&range->list, &hmm->ranges);
770 spin_unlock(&hmm->lock);
771
772 hmm_vma_walk.fault = false;
773 hmm_vma_walk.range = range;
774 mm_walk.private = &hmm_vma_walk;
724{
725 struct vm_area_struct *vma = range->vma;
726 struct hmm_vma_walk hmm_vma_walk;
727 struct mm_walk mm_walk;
728 struct hmm *hmm;
729
730 range->hmm = NULL;
731

--- 37 unchanged lines hidden (view full) ---

769 spin_lock(&hmm->lock);
770 range->valid = true;
771 list_add_rcu(&range->list, &hmm->ranges);
772 spin_unlock(&hmm->lock);
773
774 hmm_vma_walk.fault = false;
775 hmm_vma_walk.range = range;
776 mm_walk.private = &hmm_vma_walk;
777 hmm_vma_walk.last = range->start;
775
776 mm_walk.vma = vma;
777 mm_walk.mm = vma->vm_mm;
778 mm_walk.pte_entry = NULL;
779 mm_walk.test_walk = NULL;
780 mm_walk.hugetlb_entry = NULL;
781 mm_walk.pmd_entry = hmm_vma_walk_pmd;
782 mm_walk.pte_hole = hmm_vma_walk_hole;
783
784 walk_page_range(range->start, range->end, &mm_walk);
785 /*
786 * Transfer hmm reference to the range struct it will be drop inside
787 * the hmm_vma_range_done() function (which _must_ be call if this
788 * function return 0).
789 */
790 range->hmm = hmm;
778
779 mm_walk.vma = vma;
780 mm_walk.mm = vma->vm_mm;
781 mm_walk.pte_entry = NULL;
782 mm_walk.test_walk = NULL;
783 mm_walk.hugetlb_entry = NULL;
784 mm_walk.pmd_entry = hmm_vma_walk_pmd;
785 mm_walk.pte_hole = hmm_vma_walk_hole;
786
787 walk_page_range(range->start, range->end, &mm_walk);
788 /*
789 * Transfer hmm reference to the range struct it will be drop inside
790 * the hmm_vma_range_done() function (which _must_ be call if this
791 * function return 0).
792 */
793 range->hmm = hmm;
791 return 0;
794 return (hmm_vma_walk.last - range->start) >> PAGE_SHIFT;
792}
795}
793EXPORT_SYMBOL(hmm_vma_get_pfns);
796EXPORT_SYMBOL(hmm_range_snapshot);
794
795/*
796 * hmm_vma_range_done() - stop tracking change to CPU page table over a range
797 * @range: range being tracked
798 * Returns: false if range data has been invalidated, true otherwise
799 *
800 * Range struct is used to track updates to the CPU page table after a call to
801 * either hmm_vma_get_pfns() or hmm_vma_fault(). Once the device driver is done

--- 487 unchanged lines hidden ---
797
798/*
799 * hmm_vma_range_done() - stop tracking change to CPU page table over a range
800 * @range: range being tracked
801 * Returns: false if range data has been invalidated, true otherwise
802 *
803 * Range struct is used to track updates to the CPU page table after a call to
804 * either hmm_vma_get_pfns() or hmm_vma_fault(). Once the device driver is done

--- 487 unchanged lines hidden ---