Skip to content

Commit cfa3b80

Browse files
committed
Merge tag 'for-linus-hmm' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
Pull hmm updates from Jason Gunthorpe: "This series adds a selftest for hmm_range_fault() and several of the DEVICE_PRIVATE migration related actions, and another simplification for hmm_range_fault()'s API. - Simplify hmm_range_fault() with a simpler return code, no HMM_PFN_SPECIAL, and no customizable output PFN format - Add a selftest for hmm_range_fault() and DEVICE_PRIVATE related functionality" * tag 'for-linus-hmm' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: MAINTAINERS: add HMM selftests mm/hmm/test: add selftests for HMM mm/hmm/test: add selftest driver for HMM mm/hmm: remove the customizable pfn format from hmm_range_fault mm/hmm: remove HMM_PFN_SPECIAL drm/amdgpu: remove dead code after hmm_range_fault() mm/hmm: make hmm_range_fault return 0 or -1
2 parents 1940989 + f07e2f6 commit cfa3b80

File tree

18 files changed

+2934
-289
lines changed

18 files changed

+2934
-289
lines changed

Documentation/vm/hmm.rst

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ device must complete the update before the driver callback returns.
161161
When the device driver wants to populate a range of virtual addresses, it can
162162
use::
163163

164-
long hmm_range_fault(struct hmm_range *range);
164+
int hmm_range_fault(struct hmm_range *range);
165165

166166
It will trigger a page fault on missing or read-only entries if write access is
167167
requested (see below). Page faults use the generic mm page fault code path just
@@ -184,10 +184,7 @@ The usage pattern is::
184184
range.notifier = &interval_sub;
185185
range.start = ...;
186186
range.end = ...;
187-
range.pfns = ...;
188-
range.flags = ...;
189-
range.values = ...;
190-
range.pfn_shift = ...;
187+
range.hmm_pfns = ...;
191188

192189
if (!mmget_not_zero(interval_sub->notifier.mm))
193190
return -EFAULT;
@@ -229,15 +226,10 @@ The hmm_range struct has 2 fields, default_flags and pfn_flags_mask, that specif
229226
fault or snapshot policy for the whole range instead of having to set them
230227
for each entry in the pfns array.
231228

232-
For instance, if the device flags for range.flags are::
229+
For instance if the device driver wants pages for a range with at least read
230+
permission, it sets::
233231

234-
range.flags[HMM_PFN_VALID] = (1 << 63);
235-
range.flags[HMM_PFN_WRITE] = (1 << 62);
236-
237-
and the device driver wants pages for a range with at least read permission,
238-
it sets::
239-
240-
range->default_flags = (1 << 63);
232+
range->default_flags = HMM_PFN_REQ_FAULT;
241233
range->pfn_flags_mask = 0;
242234

243235
and calls hmm_range_fault() as described above. This will fill fault all pages
@@ -246,18 +238,18 @@ in the range with at least read permission.
246238
Now let's say the driver wants to do the same except for one page in the range for
247239
which it wants to have write permission. Now driver set::
248240

249-
range->default_flags = (1 << 63);
250-
range->pfn_flags_mask = (1 << 62);
251-
range->pfns[index_of_write] = (1 << 62);
241+
range->default_flags = HMM_PFN_REQ_FAULT;
242+
range->pfn_flags_mask = HMM_PFN_REQ_WRITE;
243+
range->pfns[index_of_write] = HMM_PFN_REQ_WRITE;
252244

253245
With this, HMM will fault in all pages with at least read (i.e., valid) and for the
254246
address == range->start + (index_of_write << PAGE_SHIFT) it will fault with
255247
write permission i.e., if the CPU pte does not have write permission set then HMM
256248
will call handle_mm_fault().
257249

258-
Note that HMM will populate the pfns array with write permission for any page
259-
that is mapped with CPU write permission no matter what values are set
260-
in default_flags or pfn_flags_mask.
250+
After hmm_range_fault completes the flag bits are set to the current state of
251+
the page tables, ie HMM_PFN_VALID | HMM_PFN_WRITE will be set if the page is
252+
writable.
261253

262254

263255
Represent and manage device memory from core kernel point of view

MAINTAINERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7768,7 +7768,9 @@ L: [email protected]
77687768
S: Maintained
77697769
F: Documentation/vm/hmm.rst
77707770
F: include/linux/hmm*
7771+
F: lib/test_hmm*
77717772
F: mm/hmm*
7773+
F: tools/testing/selftests/vm/*hmm*
77727774

77737775
HOST AP DRIVER
77747776
M: Jouni Malinen <[email protected]>

drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c

Lines changed: 18 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -766,18 +766,6 @@ struct amdgpu_ttm_tt {
766766
};
767767

768768
#ifdef CONFIG_DRM_AMDGPU_USERPTR
769-
/* flags used by HMM internal, not related to CPU/GPU PTE flags */
770-
static const uint64_t hmm_range_flags[HMM_PFN_FLAG_MAX] = {
771-
(1 << 0), /* HMM_PFN_VALID */
772-
(1 << 1), /* HMM_PFN_WRITE */
773-
};
774-
775-
static const uint64_t hmm_range_values[HMM_PFN_VALUE_MAX] = {
776-
0xfffffffffffffffeUL, /* HMM_PFN_ERROR */
777-
0, /* HMM_PFN_NONE */
778-
0xfffffffffffffffcUL /* HMM_PFN_SPECIAL */
779-
};
780-
781769
/**
782770
* amdgpu_ttm_tt_get_user_pages - get device accessible pages that back user
783771
* memory and start HMM tracking CPU page table update
@@ -816,18 +804,15 @@ int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo, struct page **pages)
816804
goto out;
817805
}
818806
range->notifier = &bo->notifier;
819-
range->flags = hmm_range_flags;
820-
range->values = hmm_range_values;
821-
range->pfn_shift = PAGE_SHIFT;
822807
range->start = bo->notifier.interval_tree.start;
823808
range->end = bo->notifier.interval_tree.last + 1;
824-
range->default_flags = hmm_range_flags[HMM_PFN_VALID];
809+
range->default_flags = HMM_PFN_REQ_FAULT;
825810
if (!amdgpu_ttm_tt_is_readonly(ttm))
826-
range->default_flags |= range->flags[HMM_PFN_WRITE];
811+
range->default_flags |= HMM_PFN_REQ_WRITE;
827812

828-
range->pfns = kvmalloc_array(ttm->num_pages, sizeof(*range->pfns),
829-
GFP_KERNEL);
830-
if (unlikely(!range->pfns)) {
813+
range->hmm_pfns = kvmalloc_array(ttm->num_pages,
814+
sizeof(*range->hmm_pfns), GFP_KERNEL);
815+
if (unlikely(!range->hmm_pfns)) {
831816
r = -ENOMEM;
832817
goto out_free_ranges;
833818
}
@@ -852,27 +837,23 @@ int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo, struct page **pages)
852837
down_read(&mm->mmap_sem);
853838
r = hmm_range_fault(range);
854839
up_read(&mm->mmap_sem);
855-
if (unlikely(r <= 0)) {
840+
if (unlikely(r)) {
856841
/*
857842
* FIXME: This timeout should encompass the retry from
858843
* mmu_interval_read_retry() as well.
859844
*/
860-
if ((r == 0 || r == -EBUSY) && !time_after(jiffies, timeout))
845+
if (r == -EBUSY && !time_after(jiffies, timeout))
861846
goto retry;
862847
goto out_free_pfns;
863848
}
864849

865-
for (i = 0; i < ttm->num_pages; i++) {
866-
/* FIXME: The pages cannot be touched outside the notifier_lock */
867-
pages[i] = hmm_device_entry_to_page(range, range->pfns[i]);
868-
if (unlikely(!pages[i])) {
869-
pr_err("Page fault failed for pfn[%lu] = 0x%llx\n",
870-
i, range->pfns[i]);
871-
r = -ENOMEM;
872-
873-
goto out_free_pfns;
874-
}
875-
}
850+
/*
851+
* Due to default_flags, all pages are HMM_PFN_VALID or
852+
* hmm_range_fault() fails. FIXME: The pages cannot be touched outside
853+
* the notifier_lock, and mmu_interval_read_retry() must be done first.
854+
*/
855+
for (i = 0; i < ttm->num_pages; i++)
856+
pages[i] = hmm_pfn_to_page(range->hmm_pfns[i]);
876857

877858
gtt->range = range;
878859
mmput(mm);
@@ -882,7 +863,7 @@ int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo, struct page **pages)
882863
out_unlock:
883864
up_read(&mm->mmap_sem);
884865
out_free_pfns:
885-
kvfree(range->pfns);
866+
kvfree(range->hmm_pfns);
886867
out_free_ranges:
887868
kfree(range);
888869
out:
@@ -907,7 +888,7 @@ bool amdgpu_ttm_tt_get_user_pages_done(struct ttm_tt *ttm)
907888
DRM_DEBUG_DRIVER("user_pages_done 0x%llx pages 0x%lx\n",
908889
gtt->userptr, ttm->num_pages);
909890

910-
WARN_ONCE(!gtt->range || !gtt->range->pfns,
891+
WARN_ONCE(!gtt->range || !gtt->range->hmm_pfns,
911892
"No user pages to check\n");
912893

913894
if (gtt->range) {
@@ -917,7 +898,7 @@ bool amdgpu_ttm_tt_get_user_pages_done(struct ttm_tt *ttm)
917898
*/
918899
r = mmu_interval_read_retry(gtt->range->notifier,
919900
gtt->range->notifier_seq);
920-
kvfree(gtt->range->pfns);
901+
kvfree(gtt->range->hmm_pfns);
921902
kfree(gtt->range);
922903
gtt->range = NULL;
923904
}
@@ -1008,8 +989,7 @@ static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm)
1008989

1009990
for (i = 0; i < ttm->num_pages; i++) {
1010991
if (ttm->pages[i] !=
1011-
hmm_device_entry_to_page(gtt->range,
1012-
gtt->range->pfns[i]))
992+
hmm_pfn_to_page(gtt->range->hmm_pfns[i]))
1013993
break;
1014994
}
1015995

drivers/gpu/drm/nouveau/nouveau_dmem.c

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ static inline struct nouveau_dmem *page_to_dmem(struct page *page)
8585
return container_of(page->pgmap, struct nouveau_dmem, pagemap);
8686
}
8787

88-
static unsigned long nouveau_dmem_page_addr(struct page *page)
88+
unsigned long nouveau_dmem_page_addr(struct page *page)
8989
{
9090
struct nouveau_dmem_chunk *chunk = page->zone_device_data;
9191
unsigned long idx = page_to_pfn(page) - chunk->pfn_first;
@@ -671,28 +671,3 @@ nouveau_dmem_migrate_vma(struct nouveau_drm *drm,
671671
out:
672672
return ret;
673673
}
674-
675-
void
676-
nouveau_dmem_convert_pfn(struct nouveau_drm *drm,
677-
struct hmm_range *range)
678-
{
679-
unsigned long i, npages;
680-
681-
npages = (range->end - range->start) >> PAGE_SHIFT;
682-
for (i = 0; i < npages; ++i) {
683-
struct page *page;
684-
uint64_t addr;
685-
686-
page = hmm_device_entry_to_page(range, range->pfns[i]);
687-
if (page == NULL)
688-
continue;
689-
690-
if (!is_device_private_page(page))
691-
continue;
692-
693-
addr = nouveau_dmem_page_addr(page);
694-
range->pfns[i] &= ((1UL << range->pfn_shift) - 1);
695-
range->pfns[i] |= (addr >> PAGE_SHIFT) << range->pfn_shift;
696-
range->pfns[i] |= NVIF_VMM_PFNMAP_V0_VRAM;
697-
}
698-
}

drivers/gpu/drm/nouveau/nouveau_dmem.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@ int nouveau_dmem_migrate_vma(struct nouveau_drm *drm,
3737
struct vm_area_struct *vma,
3838
unsigned long start,
3939
unsigned long end);
40+
unsigned long nouveau_dmem_page_addr(struct page *page);
4041

41-
void nouveau_dmem_convert_pfn(struct nouveau_drm *drm,
42-
struct hmm_range *range);
4342
#else /* IS_ENABLED(CONFIG_DRM_NOUVEAU_SVM) */
4443
static inline void nouveau_dmem_init(struct nouveau_drm *drm) {}
4544
static inline void nouveau_dmem_fini(struct nouveau_drm *drm) {}

0 commit comments

Comments
 (0)