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
	
	Block a user