drm/amdkfd: add svm ioctl GET_ATTR op
Get the intersection of attributes over all memory in the given range Signed-off-by: Philip Yang <Philip.Yang@amd.com> Signed-off-by: Alex Sierra <alex.sierra@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
42de677f79
commit
c5e2e4781a
|
@ -706,6 +706,167 @@ out:
|
|||
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)
|
||||
|
@ -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:
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue