From: Philip Yang <philip.y...@amd.com>

Get the intersection of attributes over all memory in the given
range

Signed-off-by: Philip Yang <philip.y...@amd.com>
Signed-off-by: Alex Sierra <alex.sie...@amd.com>
Signed-off-by: Felix Kuehling <felix.kuehl...@amd.com>
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 164 +++++++++++++++++++++++++++
 1 file changed, 164 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 21e6a7959bc7..de62265adeaa 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -707,6 +707,167 @@ svm_range_set_attr(struct kfd_process *p, uint64_t start, 
uint64_t size,
        return r;
 }
 
+static int
+svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size,
+                  uint32_t nattr, struct kfd_ioctl_svm_attribute *attrs)
+{
+       DECLARE_BITMAP(bitmap_access, MAX_GPU_INSTANCE);
+       DECLARE_BITMAP(bitmap_aip, MAX_GPU_INSTANCE);
+       bool get_preferred_loc = false;
+       bool get_prefetch_loc = false;
+       bool get_granularity = false;
+       bool get_accessible = false;
+       bool get_flags = false;
+       uint64_t last = start + size - 1UL;
+       struct mm_struct *mm = current->mm;
+       uint8_t granularity = 0xff;
+       struct interval_tree_node *node;
+       struct svm_range_list *svms;
+       struct svm_range *prange;
+       uint32_t prefetch_loc = KFD_IOCTL_SVM_LOCATION_UNDEFINED;
+       uint32_t location = KFD_IOCTL_SVM_LOCATION_UNDEFINED;
+       uint32_t flags = 0xffffffff;
+       int gpuidx;
+       uint32_t i;
+
+       pr_debug("svms 0x%p [0x%llx 0x%llx] nattr 0x%x\n", &p->svms, start,
+                start + size - 1, nattr);
+
+       mmap_read_lock(mm);
+       if (!svm_range_is_valid(mm, start, size)) {
+               pr_debug("invalid range\n");
+               mmap_read_unlock(mm);
+               return -EINVAL;
+       }
+       mmap_read_unlock(mm);
+
+       for (i = 0; i < nattr; i++) {
+               switch (attrs[i].type) {
+               case KFD_IOCTL_SVM_ATTR_PREFERRED_LOC:
+                       get_preferred_loc = true;
+                       break;
+               case KFD_IOCTL_SVM_ATTR_PREFETCH_LOC:
+                       get_prefetch_loc = true;
+                       break;
+               case KFD_IOCTL_SVM_ATTR_ACCESS:
+                       get_accessible = true;
+                       break;
+               case KFD_IOCTL_SVM_ATTR_SET_FLAGS:
+                       get_flags = true;
+                       break;
+               case KFD_IOCTL_SVM_ATTR_GRANULARITY:
+                       get_granularity = true;
+                       break;
+               case KFD_IOCTL_SVM_ATTR_CLR_FLAGS:
+               case KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE:
+               case KFD_IOCTL_SVM_ATTR_NO_ACCESS:
+                       fallthrough;
+               default:
+                       pr_debug("get invalid attr type 0x%x\n", attrs[i].type);
+                       return -EINVAL;
+               }
+       }
+
+       svms = &p->svms;
+
+       mutex_lock(&svms->lock);
+
+       node = interval_tree_iter_first(&svms->objects, start, last);
+       if (!node) {
+               pr_debug("range attrs not found return default values\n");
+               svm_range_set_default_attributes(&location, &prefetch_loc,
+                                                &granularity, &flags);
+               /* TODO: Automatically create SVM ranges and map them on
+                * GPU page faults
+               if (p->xnack_enabled)
+                       bitmap_fill(bitmap_access, MAX_GPU_INSTANCE);
+                */
+
+               goto fill_values;
+       }
+       bitmap_fill(bitmap_access, MAX_GPU_INSTANCE);
+       bitmap_fill(bitmap_aip, MAX_GPU_INSTANCE);
+
+       while (node) {
+               struct interval_tree_node *next;
+
+               prange = container_of(node, struct svm_range, it_node);
+               next = interval_tree_iter_next(node, start, last);
+
+               if (get_preferred_loc) {
+                       if (prange->preferred_loc ==
+                                       KFD_IOCTL_SVM_LOCATION_UNDEFINED ||
+                           (location != KFD_IOCTL_SVM_LOCATION_UNDEFINED &&
+                            location != prange->preferred_loc)) {
+                               location = KFD_IOCTL_SVM_LOCATION_UNDEFINED;
+                               get_preferred_loc = false;
+                       } else {
+                               location = prange->preferred_loc;
+                       }
+               }
+               if (get_prefetch_loc) {
+                       if (prange->prefetch_loc ==
+                                       KFD_IOCTL_SVM_LOCATION_UNDEFINED ||
+                           (prefetch_loc != KFD_IOCTL_SVM_LOCATION_UNDEFINED &&
+                            prefetch_loc != prange->prefetch_loc)) {
+                               prefetch_loc = KFD_IOCTL_SVM_LOCATION_UNDEFINED;
+                               get_prefetch_loc = false;
+                       } else {
+                               prefetch_loc = prange->prefetch_loc;
+                       }
+               }
+               if (get_accessible) {
+                       bitmap_and(bitmap_access, bitmap_access,
+                                  prange->bitmap_access, MAX_GPU_INSTANCE);
+                       bitmap_and(bitmap_aip, bitmap_aip,
+                                  prange->bitmap_aip, MAX_GPU_INSTANCE);
+               }
+               if (get_flags)
+                       flags &= prange->flags;
+
+               if (get_granularity && prange->granularity < granularity)
+                       granularity = prange->granularity;
+
+               node = next;
+       }
+fill_values:
+       mutex_unlock(&svms->lock);
+
+       for (i = 0; i < nattr; i++) {
+               switch (attrs[i].type) {
+               case KFD_IOCTL_SVM_ATTR_PREFERRED_LOC:
+                       attrs[i].value = location;
+                       break;
+               case KFD_IOCTL_SVM_ATTR_PREFETCH_LOC:
+                       attrs[i].value = prefetch_loc;
+                       break;
+               case KFD_IOCTL_SVM_ATTR_ACCESS:
+                       gpuidx = kfd_process_gpuidx_from_gpuid(p,
+                                                              attrs[i].value);
+                       if (gpuidx < 0) {
+                               pr_debug("invalid gpuid %x\n", attrs[i].value);
+                               return -EINVAL;
+                       }
+                       if (test_bit(gpuidx, bitmap_access))
+                               attrs[i].type = KFD_IOCTL_SVM_ATTR_ACCESS;
+                       else if (test_bit(gpuidx, bitmap_aip))
+                               attrs[i].type =
+                                       KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE;
+                       else
+                               attrs[i].type = KFD_IOCTL_SVM_ATTR_NO_ACCESS;
+                       break;
+               case KFD_IOCTL_SVM_ATTR_SET_FLAGS:
+                       attrs[i].value = flags;
+                       break;
+               case KFD_IOCTL_SVM_ATTR_GRANULARITY:
+                       attrs[i].value = (uint32_t)granularity;
+                       break;
+               }
+       }
+
+       return 0;
+}
+
 int
 svm_ioctl(struct kfd_process *p, enum kfd_ioctl_svm_op op, uint64_t start,
          uint64_t size, uint32_t nattrs, struct kfd_ioctl_svm_attribute *attrs)
@@ -720,6 +881,9 @@ svm_ioctl(struct kfd_process *p, enum kfd_ioctl_svm_op op, 
uint64_t start,
        case KFD_IOCTL_SVM_OP_SET_ATTR:
                r = svm_range_set_attr(p, start, size, nattrs, attrs);
                break;
+       case KFD_IOCTL_SVM_OP_GET_ATTR:
+               r = svm_range_get_attr(p, start, size, nattrs, attrs);
+               break;
        default:
                r = EINVAL;
                break;
-- 
2.31.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to