Commit c5e2e478 authored by Philip Yang's avatar Philip Yang Committed by Alex Deucher

drm/amdkfd: add svm ioctl GET_ATTR op

Get the intersection of attributes over all memory in the given
range
Signed-off-by: default avatarPhilip Yang <Philip.Yang@amd.com>
Signed-off-by: default avatarAlex Sierra <alex.sierra@amd.com>
Reviewed-by: default avatarFelix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: default avatarFelix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 42de677f
...@@ -706,6 +706,167 @@ svm_range_set_attr(struct kfd_process *p, uint64_t start, uint64_t size, ...@@ -706,6 +706,167 @@ svm_range_set_attr(struct kfd_process *p, uint64_t start, uint64_t size,
return r; 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 int
svm_ioctl(struct kfd_process *p, enum kfd_ioctl_svm_op op, uint64_t start, 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) uint64_t size, uint32_t nattrs, struct kfd_ioctl_svm_attribute *attrs)
...@@ -719,6 +880,9 @@ svm_ioctl(struct kfd_process *p, enum kfd_ioctl_svm_op op, uint64_t start, ...@@ -719,6 +880,9 @@ svm_ioctl(struct kfd_process *p, enum kfd_ioctl_svm_op op, uint64_t start,
case KFD_IOCTL_SVM_OP_SET_ATTR: case KFD_IOCTL_SVM_OP_SET_ATTR:
r = svm_range_set_attr(p, start, size, nattrs, attrs); r = svm_range_set_attr(p, start, size, nattrs, attrs);
break; break;
case KFD_IOCTL_SVM_OP_GET_ATTR:
r = svm_range_get_attr(p, start, size, nattrs, attrs);
break;
default: default:
r = EINVAL; r = EINVAL;
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment