<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<!--[if !mso]><style>v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style><![endif]--><style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Aptos;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        font-size:12.0pt;
        font-family:"Aptos",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:#467886;
        text-decoration:underline;}
span.EmailStyle21
        {mso-style-type:personal-reply;
        font-family:"Aptos",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;
        mso-ligatures:none;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="#467886" vlink="#96607D" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b><span style="font-size:11.0pt;font-family:"Calibri",sans-serif">From:</span></b><span style="font-size:11.0pt;font-family:"Calibri",sans-serif"> Zhang, Jianxun <jianxun.zhang@intel.com>
<br>
<b>Sent:</b> Tuesday, March 4, 2025 12:38 PM<br>
<b>To:</b> Cavitt, Jonathan <jonathan.cavitt@intel.com>; intel-xe@lists.freedesktop.org<br>
<b>Cc:</b> Gupta, saurabhg <saurabhg.gupta@intel.com>; Zuo, Alex <alex.zuo@intel.com>; joonas.lahtinen@linux.intel.com; Brost, Matthew <matthew.brost@intel.com>; Lin, Shuicheng <shuicheng.lin@intel.com>; dri-devel@lists.freedesktop.org<br>
<b>Subject:</b> Re: [PATCH v5 6/6] drm/xe/xe_vm: Implement xe_vm_get_property_ioctl<o:p></o:p></span></p>
</div>
</div>
<div>
<p class="MsoNormal"><span style="color:black"><o:p> </o:p></span></p>
</div>
<div class="MsoNormal" align="center" style="text-align:center">
<hr size="2" width="98%" align="center">
</div>
<div id="divRplyFwdMsg">
<p class="MsoNormal"><b><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black">From:</span></b><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black"> Cavitt, Jonathan <</span><a href="mailto:jonathan.cavitt@intel.com"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif">jonathan.cavitt@intel.com</span></a><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black">><br>
<b>Sent:</b> Tuesday, March 4, 2025 9:08 AM<br>
<b>To:</b> </span><a href="mailto:intel-xe@lists.freedesktop.org"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif">intel-xe@lists.freedesktop.org</span></a><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black"> <</span><a href="mailto:intel-xe@lists.freedesktop.org"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif">intel-xe@lists.freedesktop.org</span></a><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black">><br>
<b>Cc:</b> Gupta, saurabhg <</span><a href="mailto:saurabhg.gupta@intel.com"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif">saurabhg.gupta@intel.com</span></a><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black">>; Zuo,
 Alex <</span><a href="mailto:alex.zuo@intel.com"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif">alex.zuo@intel.com</span></a><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black">>; Cavitt, Jonathan <</span><a href="mailto:jonathan.cavitt@intel.com"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif">jonathan.cavitt@intel.com</span></a><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black">>;
</span><a href="mailto:joonas.lahtinen@linux.intel.com"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif">joonas.lahtinen@linux.intel.com</span></a><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black"> <</span><a href="mailto:joonas.lahtinen@linux.intel.com"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif">joonas.lahtinen@linux.intel.com</span></a><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black">>;
 Brost, Matthew <</span><a href="mailto:matthew.brost@intel.com"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif">matthew.brost@intel.com</span></a><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black">>; Zhang, Jianxun
 <</span><a href="mailto:jianxun.zhang@intel.com"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif">jianxun.zhang@intel.com</span></a><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black">>; Lin, Shuicheng <</span><a href="mailto:shuicheng.lin@intel.com"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif">shuicheng.lin@intel.com</span></a><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black">>;
</span><a href="mailto:dri-devel@lists.freedesktop.org"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif">dri-devel@lists.freedesktop.org</span></a><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black"> <</span><a href="mailto:dri-devel@lists.freedesktop.org"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif">dri-devel@lists.freedesktop.org</span></a><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black">><br>
<b>Subject:</b> [PATCH v5 6/6] drm/xe/xe_vm: Implement xe_vm_get_property_ioctl</span>
<o:p></o:p></p>
<div>
<p class="MsoNormal"> <o:p></o:p></p>
</div>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">Add support for userspace to request a list of observed failed<br>
pagefaults from a specified VM.<br>
<br>
v2:<br>
- Only allow querying of failed pagefaults (Matt Brost)<br>
<br>
v3:<br>
- Remove unnecessary size parameter from helper function, as it<br>
  is a property of the arguments. (jcavitt)<br>
- Remove unnecessary copy_from_user (Jainxun)<br>
- Set address_precision to 1 (Jainxun)<br>
- Report max size instead of dynamic size for memory allocation<br>
  purposes.  Total memory usage is reported separately.<br>
<br>
v4:<br>
- Return int from xe_vm_get_property_size (Shuicheng)<br>
- Fix memory leak (Shuicheng)<br>
- Remove unnecessary size variable (jcavitt)<br>
<br>
Signed-off-by: Jonathan Cavitt <</span><a href="mailto:jonathan.cavitt@intel.com"><span style="font-size:11.0pt">jonathan.cavitt@intel.com</span></a><span style="font-size:11.0pt">><br>
Suggested-by: Matthew Brost <</span><a href="mailto:matthew.brost@intel.com"><span style="font-size:11.0pt">matthew.brost@intel.com</span></a><span style="font-size:11.0pt">><br>
CC: Jainxun Zhang <</span><a href="mailto:jianxun.zhang@intel.com"><span style="font-size:11.0pt">jianxun.zhang@intel.com</span></a><span style="font-size:11.0pt">><br>
CC: Shuicheng Lin <</span><a href="mailto:shuicheng.lin@intel.com"><span style="font-size:11.0pt">shuicheng.lin@intel.com</span></a><span style="font-size:11.0pt">><br>
---<br>
 drivers/gpu/drm/xe/xe_device.c |  3 ++<br>
 drivers/gpu/drm/xe/xe_vm.c     | 75 ++++++++++++++++++++++++++++++++++<br>
 drivers/gpu/drm/xe/xe_vm.h     |  2 +<br>
 3 files changed, 80 insertions(+)<br>
<br>
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c<br>
index 9454b51f7ad8..43accae152ff 100644<br>
--- a/drivers/gpu/drm/xe/xe_device.c<br>
+++ b/drivers/gpu/drm/xe/xe_device.c<br>
@@ -193,6 +193,9 @@ static const struct drm_ioctl_desc xe_ioctls[] = {<br>
         DRM_IOCTL_DEF_DRV(XE_WAIT_USER_FENCE, xe_wait_user_fence_ioctl,<br>
                           DRM_RENDER_ALLOW),<br>
         DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl, DRM_RENDER_ALLOW),<br>
+       DRM_IOCTL_DEF_DRV(XE_VM_GET_PROPERTY, xe_vm_get_property_ioctl,<br>
+                         DRM_RENDER_ALLOW),<br>
+<br>
 };<br>
 <br>
 static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)<br>
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c<br>
index 6211b971bbbd..1e78103fb0f6 100644<br>
--- a/drivers/gpu/drm/xe/xe_vm.c<br>
+++ b/drivers/gpu/drm/xe/xe_vm.c<br>
@@ -3234,6 +3234,81 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)<br>
         return err;<br>
 }<br>
 <br>
+static int xe_vm_get_property_size(struct xe_vm *vm, u32 property)<br>
+{<br>
+       switch (property) {<br>
+       case DRM_XE_VM_GET_PROPERTY_FAULTS:<br>
+               return MAX_PFS * sizeof(struct drm_xe_pf);<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">> I still think returning the number of faults back to user space is better and clearer.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">> But the intention is to use this ioctl on any properties, so perhaps it is why a size in byte is chosen.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">This is a workaround for the issue you pointed out in the previous revision that caused the get<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">property ioctl to fail if the number of faults in the system changed between the first and second<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">calls.  Getting the precise size of the data field would reintroduce that issue, and keeping the lock<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">between the first and second calls to prevent the list from changing between calls would violate<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">several design principles (E.G., what happens if the user only calls the ioctl once?)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">> But first of all, should we regard faults as a property?<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">I think this question would be better answered by Matthew Brost, as this was at least<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">in part his suggestion.  Though I suppose we could make this an extension of xe_query<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">and just ask userspace to pass in additional information W.R.T. the VM ID as a part of<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">the query structure.  On the other hand, we’ll probably want the property ioctl extended<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">in the future to be able to report additional information, which has no precedence in<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">the query ioctl and thus would bloat the query ioctl with additional queries.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><br>
+       default:<br>
+               return -EINVAL;<br>
+       }<br>
+}<br>
+<br>
+static int fill_property_pfs(struct xe_vm *vm,<br>
+                            struct drm_xe_vm_get_property *args)<br>
+{<br>
+       struct drm_xe_pf __user *usr_ptr = u64_to_user_ptr(args->ptr);<br>
+       struct drm_xe_pf *fault_list;<br>
+       struct drm_xe_pf *fault;<br>
+       struct xe_vm_pf_entry *entry;<br>
+       int ret, i = 0;<br>
+<br>
+       fault_list = kzalloc(args->size, GFP_KERNEL);<br>
+       if (!fault_list)<br>
+               return -ENOMEM;<br>
+<br>
+       spin_lock(&vm->pfs.lock);<br>
+       list_for_each_entry(entry, &vm->pfs.list, list) {<br>
+               struct xe_pagefault *pf = entry->pf;<br>
+<br>
+               fault = &fault_list[i++];<br>
+               fault->address = pf->page_addr;<br>
+               fault->address_type = pf->address_type;<br>
+               fault->address_precision = 1;<br>
+       }<br>
+       args->value = vm->pfs.len;<br>
+       spin_unlock(&vm->pfs.lock);<br>
+<br>
+       ret = copy_to_user(usr_ptr, &fault_list, args->size);<br>
+       kfree(fault_list);<br>
+<br>
+       return ret ? -EFAULT : 0;<br>
+}<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">> How about this to get rid of fault_list? The assumption is put_user is sufficient on types of data to return.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">> It also deletes the copied data though KMD may still want to  keep them.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">> <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">> This is Just an idea, It makes copied size is unclear so more refactor would be needed.)<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">> <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">> static int fill_property_pfs(struct xe_vm *vm,<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>                        struct drm_xe_vm_get_property *args)<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">> {<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>       struct drm_xe_pf __user *usr_ptr = u64_to_user_ptr(args->ptr);<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>       struct xe_vm_pf_entry *entry;<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>       struct xe_vm_pf_entry *tmp_entry;<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>       int ret = 0;<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>       spin_lock(&vm->pfs.lock);<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>       list_for_each_entry_safe(entry, tmp_entry,  &vm->pfs.list, list)  {<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>             ret = put_user(entry->pf->page_addr, &usr_ptr->address);<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>             if (ret)<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>                   break;<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>             ret = put_user(entry->pf->address_type, &usr_ptr->address_type);<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>             if (ret)<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>                   break;<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>             ret = put_user(1, &usr_ptr->address_precision);<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>             if (ret)<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>                   break;<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>             usr_ptr++;<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>             list_del(entry->list);<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>       }<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>       spin_unlock(&vm->pfs.lock);<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">>       return ret;<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">> }<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">I’ll consider it once we can get a finalization on whether this needs to be a separate ioctl<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">or an extension of xe_query.  Though either way I’ll have to pass on clearing the list on query.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">The information should stay persistent until the VM is closed or until it’s lost due to hitting<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">the list size limit.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;color:black">-Jonathan Cavitt<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:11.0pt"><br>
+<br>
+int xe_vm_get_property_ioctl(struct drm_device *drm, void *data,<br>
+                            struct drm_file *file)<br>
+{<br>
+       struct xe_device *xe = to_xe_device(drm);<br>
+       struct xe_file *xef = to_xe_file(file);<br>
+       struct drm_xe_vm_get_property *args = data;<br>
+       struct xe_vm *vm;<br>
+       int size;<br>
+<br>
+       if (XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1]))<br>
+               return -EINVAL;<br>
+<br>
+       vm = xe_vm_lookup(xef, args->vm_id);<br>
+       if (XE_IOCTL_DBG(xe, !vm))<br>
+               return -ENOENT;<br>
+<br>
+       size = xe_vm_get_property_size(vm, args->property);<br>
+       if (size < 0) {<br>
+               return size;<br>
+       } else if (args->size != size) {<br>
+               if (args->size)<br>
+                       return -EINVAL;<br>
+               args->size = size;<br>
+               return 0;<br>
+       }<br>
+<br>
+       switch (args->property) {<br>
+       case DRM_XE_VM_GET_PROPERTY_FAULTS:<br>
+               return fill_property_pfs(vm, args);<br>
+       default:<br>
+               return -EINVAL;<br>
+       }<br>
+}<br>
+<br>
 /**<br>
  * xe_vm_bind_kernel_bo - bind a kernel BO to a VM<br>
  * @vm: VM to bind the BO to<br>
diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h<br>
index 4d94ab5c8ea4..bf6604465aa3 100644<br>
--- a/drivers/gpu/drm/xe/xe_vm.h<br>
+++ b/drivers/gpu/drm/xe/xe_vm.h<br>
@@ -184,6 +184,8 @@ int xe_vm_destroy_ioctl(struct drm_device *dev, void *data,<br>
                         struct drm_file *file);<br>
 int xe_vm_bind_ioctl(struct drm_device *dev, void *data,<br>
                      struct drm_file *file);<br>
+int xe_vm_get_property_ioctl(struct drm_device *dev, void *data,<br>
+                            struct drm_file *file);<br>
 <br>
 void xe_vm_close_and_put(struct xe_vm *vm);<br>
 <br>
--<br>
2.43.0<o:p></o:p></span></p>
</div>
</div>
</body>
</html>