From: "Ghimiray, Himal Prasad" <himal.prasad.ghimiray@intel.com>
To: Matthew Brost <matthew.brost@intel.com>
Cc: <intel-xe@lists.freedesktop.org>
Subject: Re: [PATCH v3 10/19] drm/xe: Implement madvise ioctl for xe
Date: Tue, 10 Jun 2025 10:22:42 +0530 [thread overview]
Message-ID: <405470cd-db73-4380-9a68-78c607d10003@intel.com> (raw)
In-Reply-To: <aDokTWyn942CBVXh@lstrano-desk.jf.intel.com>
On 31-05-2025 03:04, Matthew Brost wrote:
> On Tue, May 27, 2025 at 10:09:54PM +0530, Himal Prasad Ghimiray wrote:
>> This driver-specific ioctl enables UMDs to control the memory attributes
>> for GPU VMAs within a specified input range. If the start or end
>> addresses fall within an existing VMA, the VMA is split accordingly. The
>> attributes of the VMA are modified as provided by the users. The old
>> mappings of the VMAs are invalidated, and TLB invalidation is performed
>> if necessary.
>>
>> v2(Matthew brost)
>> - xe_vm_in_fault_mode can't be enabled by Mesa, hence allow ioctl in non
>> fault mode too
>> - fix tlb invalidation skip for same ranges in multiple op
>> - use helper for tlb invalidation
>> - use xe_svm_notifier_lock/unlock helper
>> - s/lockdep_assert_held/lockdep_assert_held_write
>> - Add kernel-doc
>>
>> Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
>> ---
>> drivers/gpu/drm/xe/Makefile | 1 +
>> drivers/gpu/drm/xe/xe_device.c | 2 +
>> drivers/gpu/drm/xe/xe_vm_madvise.c | 264 +++++++++++++++++++++++++++++
>> drivers/gpu/drm/xe/xe_vm_madvise.h | 15 ++
>> 4 files changed, 282 insertions(+)
>> create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.c
>> create mode 100644 drivers/gpu/drm/xe/xe_vm_madvise.h
>>
>> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
>> index c5d6681645ed..dc64bdcddfdc 100644
>> --- a/drivers/gpu/drm/xe/Makefile
>> +++ b/drivers/gpu/drm/xe/Makefile
>> @@ -117,6 +117,7 @@ xe-y += xe_bb.o \
>> xe_uc.o \
>> xe_uc_fw.o \
>> xe_vm.o \
>> + xe_vm_madvise.o \
>> xe_vram.o \
>> xe_vram_freq.o \
>> xe_vsec.o \
>> diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
>> index d4b6e623aa48..b9791c614749 100644
>> --- a/drivers/gpu/drm/xe/xe_device.c
>> +++ b/drivers/gpu/drm/xe/xe_device.c
>> @@ -61,6 +61,7 @@
>> #include "xe_ttm_stolen_mgr.h"
>> #include "xe_ttm_sys_mgr.h"
>> #include "xe_vm.h"
>> +#include "xe_vm_madvise.h"
>> #include "xe_vram.h"
>> #include "xe_vsec.h"
>> #include "xe_wait_user_fence.h"
>> @@ -197,6 +198,7 @@ static const struct drm_ioctl_desc xe_ioctls[] = {
>> DRM_IOCTL_DEF_DRV(XE_WAIT_USER_FENCE, xe_wait_user_fence_ioctl,
>> DRM_RENDER_ALLOW),
>> DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl, DRM_RENDER_ALLOW),
>> + DRM_IOCTL_DEF_DRV(XE_MADVISE, xe_vm_madvise_ioctl, DRM_RENDER_ALLOW),
>> };
>>
>> static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
>> diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
>> new file mode 100644
>> index 000000000000..f7edefe5f6cf
>> --- /dev/null
>> +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
>> @@ -0,0 +1,264 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright © 2024 Intel Corporation
>> + */
>> +
>> +#include "xe_vm_madvise.h"
>> +
>> +#include <linux/nospec.h>
>> +#include <drm/ttm/ttm_tt.h>
>> +#include <drm/xe_drm.h>
>> +
>> +#include "xe_bo.h"
>> +#include "xe_gt_tlb_invalidation.h"
>> +#include "xe_pt.h"
>> +#include "xe_svm.h"
>> +
>> +static struct xe_vma **get_vmas(struct xe_vm *vm, int *num_vmas,
>> + u64 addr, u64 range)
>> +{
>> + struct xe_vma **vmas, **__vmas;
>> + struct drm_gpuva *gpuva;
>> + int max_vmas = 8;
>> +
>> + lockdep_assert_held(&vm->lock);
>> +
>> + *num_vmas = 0;
>> + vmas = kmalloc_array(max_vmas, sizeof(*vmas), GFP_KERNEL);
>> + if (!vmas)
>> + return NULL;
>> +
>> + vm_dbg(&vm->xe->drm, "VMA's in range: start=0x%016llx, end=0x%016llx", addr, addr + range);
>> +
>> + drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, addr, addr + range) {
>> + struct xe_vma *vma = gpuva_to_vma(gpuva);
>> +
>> + if (*num_vmas == max_vmas) {
>> + max_vmas <<= 1;
>> + __vmas = krealloc(vmas, max_vmas * sizeof(*vmas), GFP_KERNEL);
>> + if (!__vmas) {
>> + kfree(vmas);
>> + return NULL;
>> + }
>> + vmas = __vmas;
>> + }
>> +
>> + vmas[*num_vmas] = vma;
>> + (*num_vmas)++;
>> + }
>> +
>> + vm_dbg(&vm->xe->drm, "*num_vmas = %d\n", *num_vmas);
>> +
>> + if (!*num_vmas) {
>> + kfree(vmas);
>> + return NULL;
>> + }
>> +
>> + return vmas;
>> +}
>> +
>> +static int madvise_preferred_mem_loc(struct xe_device *xe, struct xe_vm *vm,
>> + struct xe_vma **vmas, int num_vmas,
>> + struct drm_xe_madvise_ops ops)
>> +{
>> + /* Implementation pending */
>> + return 0;
>> +}
>> +
>> +static int madvise_atomic(struct xe_device *xe, struct xe_vm *vm,
>> + struct xe_vma **vmas, int num_vmas,
>> + struct drm_xe_madvise_ops ops)
>> +{
>> + /* Implementation pending */
>> + return 0;
>> +}
>> +
>> +static int madvise_pat_index(struct xe_device *xe, struct xe_vm *vm,
>> + struct xe_vma **vmas, int num_vmas,
>> + struct drm_xe_madvise_ops ops)
>> +{
>> + /* Implementation pending */
>> + return 0;
>> +}
>> +
>> +static int madvise_purgeable_state(struct xe_device *xe, struct xe_vm *vm,
>> + struct xe_vma **vmas, int num_vmas,
>> + struct drm_xe_madvise_ops ops)
>> +{
>> + /* Implementation pending */
>> + return 0;
>> +}
>> +
>> +typedef int (*madvise_func)(struct xe_device *xe, struct xe_vm *vm,
>> + struct xe_vma **vmas, int num_vmas, struct drm_xe_madvise_ops ops);
>> +
>> +static const madvise_func madvise_funcs[] = {
>> + [DRM_XE_VMA_ATTR_PREFERRED_LOC] = madvise_preferred_mem_loc,
>> + [DRM_XE_VMA_ATTR_ATOMIC] = madvise_atomic,
>> + [DRM_XE_VMA_ATTR_PAT] = madvise_pat_index,
>> + [DRM_XE_VMA_ATTR_PURGEABLE_STATE] = madvise_purgeable_state,
>> +};
>> +
>> +static void xe_zap_ptes_in_madvise_range(struct xe_vm *vm, u64 start, u64 end, u8 *tile_mask)
>> +{
>> + struct drm_gpuva *gpuva;
>> + struct xe_tile *tile;
>> + u8 id;
>> +
>> + lockdep_assert_held_write(&vm->lock);
>> +
>> + if (dma_resv_wait_timeout(xe_vm_resv(vm), DMA_RESV_USAGE_BOOKKEEP,
>> + false, MAX_SCHEDULE_TIMEOUT) <= 0)
>> + XE_WARN_ON(1);
>> +
>> + *tile_mask = xe_svm_ranges_zap_ptes_in_range(vm, start, end);
>> +
>> + drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end) {
>> + struct xe_vma *vma = gpuva_to_vma(gpuva);
>> +
>> + if (xe_vma_is_cpu_addr_mirror(vma))
>> + continue;
>> +
>> + if (xe_vma_is_userptr(vma)) {
>> + WARN_ON_ONCE(!mmu_interval_check_retry
>> + (&to_userptr_vma(vma)->userptr.notifier,
>> + to_userptr_vma(vma)->userptr.notifier_seq));
>> +
>> + WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(vma)),
>> + DMA_RESV_USAGE_BOOKKEEP));
>> + }
>> +
>> + if (xe_vma_bo(vma))
>> + xe_bo_lock(xe_vma_bo(vma), false);
>> +
>> + for_each_tile(tile, vm->xe, id) {
>> + if (xe_pt_zap_ptes(tile, vma))
>> + *tile_mask |= BIT(id);
>> + }
>> +
>> + if (xe_vma_bo(vma))
>> + xe_bo_unlock(xe_vma_bo(vma));
>> + }
>> +}
>> +
>> +static int xe_vm_invalidate_madvise_range(struct xe_vm *vm, u64 start, u64 end)
>> +{
>> + u8 tile_mask = 0;
>> +
>> + xe_zap_ptes_in_madvise_range(vm, start, end, &tile_mask);
>> + if (!tile_mask)
>> + return 0;
>> +
>> + xe_device_wmb(vm->xe);
>> +
>> + return xe_vm_range_tilemask_tlb_invalidation(vm, start, end, tile_mask);
>> +}
>> +
>> +static int input_ranges_same(struct drm_xe_madvise_ops *old,
>> + struct drm_xe_madvise_ops *new)
>> +{
>> + return (new->start == old->start && new->range == old->range);
>> +}
>> +
>> +/**
>> + * xe_vm_madvise_ioctl - Handle MADVise ioctl for a VM
>> + * @dev: DRM device pointer
>> + * @data: Pointer to ioctl data (drm_xe_madvise*)
>> + * @file: DRM file pointer
>> + *
>> + * Handles the MADVISE ioctl to provide memory advice for vma's within
>> + * input range.
>> + *
>> + * Return: 0 on success or a negative error code on failure.
>> + */
>> +int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
>> +{
>> + struct xe_device *xe = to_xe_device(dev);
>> + struct xe_file *xef = to_xe_file(file);
>> + struct drm_xe_madvise_ops *advs_ops;
>> + struct drm_xe_madvise *args = data;
>> + struct xe_vm *vm;
>> + struct xe_vma **vmas = NULL;
>> + int num_vmas, err = 0;
>> + int i, j, attr_type;
>> + bool needs_invalidation;
>> +
>> + if (XE_IOCTL_DBG(xe, args->num_ops < 1))
>> + return -EINVAL;
>> +
>> + vm = xe_vm_lookup(xef, args->vm_id);
>> + if (XE_IOCTL_DBG(xe, !vm))
>> + return -EINVAL;
>> +
>> + down_write(&vm->lock);
>> +
>> + if (XE_IOCTL_DBG(xe, xe_vm_is_closed_or_banned(vm))) {
>> + err = -ENOENT;
>> + goto unlock_vm;
>> + }
>> +
>> + if (args->num_ops > 1) {
>> + u64 __user *madvise_user = u64_to_user_ptr(args->vector_of_ops);
>> +
>> + advs_ops = kvmalloc_array(args->num_ops, sizeof(struct drm_xe_madvise_ops),
>> + GFP_KERNEL | __GFP_ACCOUNT |
>> + __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
>> + if (!advs_ops) {
>> + err = args->num_ops > 1 ? -ENOBUFS : -ENOMEM;
>> + goto unlock_vm;
>> + }
>> +
>> + err = __copy_from_user(advs_ops, madvise_user,
>> + sizeof(struct drm_xe_madvise_ops) *
>> + args->num_ops);
>> + if (XE_IOCTL_DBG(xe, err)) {
>> + err = -EFAULT;
>> + goto free_advs_ops;
>> + }
>> + } else {
>> + advs_ops = &args->ops;
>> + }
>> +
>> + for (i = 0; i < args->num_ops; i++) {
>> + xe_vm_alloc_madvise_vma(vm, advs_ops[i].start, advs_ops[i].range);
>> +
>> + vmas = get_vmas(vm, &num_vmas, advs_ops[i].start, advs_ops[i].range);
>> + if (!vmas) {
>> + err = -ENOMEM;
>> + goto free_advs_ops;
>> + }
>> +
>> + attr_type = array_index_nospec(advs_ops[i].type, ARRAY_SIZE(madvise_funcs));
>> + err = madvise_funcs[attr_type](xe, vm, vmas, num_vmas, advs_ops[i]);
>> +
>> + kfree(vmas);
>> + vmas = NULL;
>> +
>> + if (err)
>> + goto free_advs_ops;
>> + }
>> +
>> + for (i = 0; i < args->num_ops; i++) {
>> + needs_invalidation = true;
>> + for (j = i + 1; j < args->num_ops; ++j) {
>> + if (input_ranges_same(&advs_ops[j], &advs_ops[i])) {
>> + needs_invalidation = false;
>> + break;
>> + }
>> + }
>> + if (needs_invalidation) {
>> + err = xe_vm_invalidate_madvise_range(vm, advs_ops[i].start,
>> + advs_ops[i].start + advs_ops[i].range);
>> + if (err)
>> + goto free_advs_ops;
>
> In additional to all the other comments around invalidations - you don't
> always need to issue TLB invalidations.
>
> - For pat_index, only if the VMAs pat_index changed + valid page tables
> - For atomic, only if the VMAs atomic mode changed + valid page tables +
> current placement would cause issues
> - Purgeable - never
> - Preferred placement - valid page tables + current placement != desired
> placement
>
> We likley can set a temp bit in the vfuncs in either the VMA (BO,
> userptr based) or the SVM range(s) which the invalidation func can parse
> / clear indicating an invalidation is required.
In the current implementation, I’m zapping PTEs for SVM ranges and
BO/Userptr-based VMAs within the madvise range, and issuing a TLB
invalidation for the entire madvise range. Should we instead issue TLB
invalidations at the granularity of the SVM range or the individual VMA
(BO or Userptr)? I don’t see how we can avoid TLB invalidation if some
VMAs require it and others don’t, given that we’re currently
invalidating the entire range.
>
> Matt
>
>> + }
>> + }
>> +
>> +free_advs_ops:
>> + if (args->num_ops > 1)
>> + kvfree(advs_ops);
>> +unlock_vm:
>> + up_write(&vm->lock);
>> + xe_vm_put(vm);
>> + return err;
>> +}
>> diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.h b/drivers/gpu/drm/xe/xe_vm_madvise.h
>> new file mode 100644
>> index 000000000000..c5cdd058c322
>> --- /dev/null
>> +++ b/drivers/gpu/drm/xe/xe_vm_madvise.h
>> @@ -0,0 +1,15 @@
>> +/* SPDX-License-Identifier: MIT */
>> +/*
>> + * Copyright © 2024 Intel Corporation
>> + */
>> +
>> +#ifndef _XE_VM_MADVISE_H_
>> +#define _XE_VM_MADVISE_H_
>> +
>> +struct drm_device;
>> +struct drm_file;
>> +
>> +int xe_vm_madvise_ioctl(struct drm_device *dev, void *data,
>> + struct drm_file *file);
>> +
>> +#endif
>> --
>> 2.34.1
>>
next prev parent reply other threads:[~2025-06-10 4:53 UTC|newest]
Thread overview: 74+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-27 16:39 [PATCH v3 00/19] MADVISE FOR XE Himal Prasad Ghimiray
2025-05-27 16:39 ` [PATCH v3 01/19] Introduce drm_gpuvm_sm_map_ops_flags enums for sm_map_ops Himal Prasad Ghimiray
2025-05-27 16:39 ` [PATCH v3 02/19] drm/xe/uapi: Add madvise interface Himal Prasad Ghimiray
2025-05-28 16:27 ` Matthew Brost
2025-05-28 17:03 ` Souza, Jose
2025-05-29 18:03 ` Matthew Brost
2025-05-29 18:00 ` Matthew Brost
2025-06-10 4:32 ` Ghimiray, Himal Prasad
2025-05-27 16:39 ` [PATCH v3 03/19] drm/xe/vm: Add attributes struct as member of vma Himal Prasad Ghimiray
2025-05-28 16:46 ` Matthew Brost
2025-05-27 16:39 ` [PATCH v3 04/19] drm/xe/vma: Move pat_index to vma attributes Himal Prasad Ghimiray
2025-05-28 22:51 ` Matthew Brost
2025-05-27 16:39 ` [PATCH v3 05/19] drm/xe/vma: Modify new_vma to accept struct xe_vma_mem_attr as parameter Himal Prasad Ghimiray
2025-05-28 22:58 ` Matthew Brost
2025-05-27 16:39 ` [PATCH v3 06/19] drm/gpusvm: Make drm_gpusvm_for_each_* macros public Himal Prasad Ghimiray
2025-05-28 23:01 ` Matthew Brost
2025-05-27 16:39 ` [PATCH v3 07/19] drm/xe/vm: Add a helper xe_vm_range_tilemask_tlb_invalidation() Himal Prasad Ghimiray
2025-05-28 23:12 ` Matthew Brost
2025-05-29 3:21 ` Ghimiray, Himal Prasad
2025-05-27 16:39 ` [PATCH v3 08/19] drm/xe/svm: Add xe_svm_ranges_zap_ptes_in_range() for PTE zapping Himal Prasad Ghimiray
2025-05-28 23:15 ` Matthew Brost
2025-05-29 3:06 ` Ghimiray, Himal Prasad
2025-05-29 4:00 ` Matthew Brost
2025-05-30 6:29 ` Matthew Brost
2025-06-10 4:31 ` Ghimiray, Himal Prasad
2025-05-27 16:39 ` [PATCH v3 09/19] drm/xe/svm: Split system allocator vma incase of madvise call Himal Prasad Ghimiray
2025-05-29 2:49 ` Matthew Brost
2025-05-29 3:14 ` Ghimiray, Himal Prasad
2025-05-27 16:39 ` [PATCH v3 10/19] drm/xe: Implement madvise ioctl for xe Himal Prasad Ghimiray
2025-05-29 22:43 ` Matthew Brost
2025-05-30 6:36 ` Matthew Brost
2025-05-30 21:34 ` Matthew Brost
2025-06-10 4:52 ` Ghimiray, Himal Prasad [this message]
2025-06-10 5:13 ` Matthew Brost
2025-05-27 16:39 ` [PATCH v3 11/19] drm/xe: Allow CPU address mirror VMA unbind with gpu bindings for madvise Himal Prasad Ghimiray
2025-05-29 22:54 ` Matthew Brost
2025-06-12 9:02 ` Ghimiray, Himal Prasad
2025-05-27 16:39 ` [PATCH v3 12/19] drm/xe/svm : Add svm ranges migration policy on atomic access Himal Prasad Ghimiray
2025-05-29 23:27 ` Matthew Brost
2025-05-29 23:38 ` Matthew Brost
2025-05-30 4:40 ` Matthew Brost
2025-05-27 16:39 ` [PATCH v3 13/19] drm/xe/madvise: Update migration policy based on preferred location Himal Prasad Ghimiray
2025-05-29 23:42 ` Matthew Brost
2025-05-27 16:39 ` [PATCH v3 14/19] drm/xe/svm: Support DRM_XE_SVM_ATTR_PAT memory attribute Himal Prasad Ghimiray
2025-05-30 0:24 ` Matthew Brost
2025-05-27 16:39 ` [PATCH v3 15/19] drm/xe/uapi: Add flag for consulting madvise hints on svm prefetch Himal Prasad Ghimiray
2025-05-28 16:29 ` Matthew Brost
2025-05-27 16:40 ` [PATCH v3 16/19] drm/xe/svm: Consult madvise preferred location in prefetch Himal Prasad Ghimiray
2025-05-30 4:24 ` Matthew Brost
2025-06-24 18:56 ` Matthew Brost
2025-05-27 16:40 ` [PATCH v3 17/19] drm/xe/uapi: Add UAPI for querying VMA count and memory attributes Himal Prasad Ghimiray
2025-05-28 17:02 ` Souza, Jose
2025-05-30 1:11 ` kernel test robot
2025-05-30 4:29 ` Matthew Brost
2025-05-27 16:40 ` [PATCH v3 18/19] drm/xe/bo: Add attributes field to xe_bo Himal Prasad Ghimiray
2025-05-28 23:47 ` Matthew Brost
2025-05-29 2:29 ` Ghimiray, Himal Prasad
2025-05-27 16:40 ` [PATCH v3 19/19] drm/xe/bo: Update atomic_access attribute on madvise Himal Prasad Ghimiray
2025-05-28 23:46 ` Matthew Brost
2025-05-29 3:03 ` Ghimiray, Himal Prasad
2025-05-29 18:24 ` Matthew Brost
2025-05-29 18:30 ` Matthew Brost
2025-05-27 21:35 ` ✓ CI.Patch_applied: success for MADVISE FOR XE Patchwork
2025-05-27 21:35 ` ✗ CI.checkpatch: warning " Patchwork
2025-05-27 21:37 ` ✓ CI.KUnit: success " Patchwork
2025-05-27 21:40 ` ✗ CI.Build: failure " Patchwork
2025-05-28 7:45 ` ✓ CI.Patch_applied: success " Patchwork
2025-05-28 7:45 ` ✗ CI.checkpatch: warning " Patchwork
2025-05-28 7:46 ` ✓ CI.KUnit: success " Patchwork
2025-05-28 7:50 ` ✗ CI.Build: failure " Patchwork
-- strict thread matches above, loose matches on Subject: below --
2025-05-29 18:52 [PATCH v3 05/19] drm/xe/vma: Modify new_vma to accept struct xe_vma_mem_attr as parameter kernel test robot
2025-06-02 6:19 ` Dan Carpenter
2025-05-29 23:18 [PATCH v3 09/19] drm/xe/svm: Split system allocator vma incase of madvise call kernel test robot
2025-06-02 6:31 ` Dan Carpenter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=405470cd-db73-4380-9a68-78c607d10003@intel.com \
--to=himal.prasad.ghimiray@intel.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=matthew.brost@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.