@@ -1147,6 +1147,66 @@ svm_range_add_child(struct svm_range *prange, struct mm_struct *mm,
11471147 list_add_tail (& pchild -> child_list , & prange -> child_list );
11481148}
11491149
1150+ /**
1151+ * svm_range_split_by_granularity - collect ranges within granularity boundary
1152+ *
1153+ * @p: the process with svms list
1154+ * @mm: mm structure
1155+ * @addr: the vm fault address in pages, to split the prange
1156+ * @parent: parent range if prange is from child list
1157+ * @prange: prange to split
1158+ *
1159+ * Trims @prange to be a single aligned block of prange->granularity if
1160+ * possible. The head and tail are added to the child_list in @parent.
1161+ *
1162+ * Context: caller must hold mmap_read_lock and prange->lock
1163+ *
1164+ * Return:
1165+ * 0 - OK, otherwise error code
1166+ */
1167+ int
1168+ svm_range_split_by_granularity (struct kfd_process * p , struct mm_struct * mm ,
1169+ unsigned long addr , struct svm_range * parent ,
1170+ struct svm_range * prange )
1171+ {
1172+ struct svm_range * head , * tail ;
1173+ unsigned long start , last , size ;
1174+ int r ;
1175+
1176+ /* Align splited range start and size to granularity size, then a single
1177+ * PTE will be used for whole range, this reduces the number of PTE
1178+ * updated and the L1 TLB space used for translation.
1179+ */
1180+ size = 1UL << prange -> granularity ;
1181+ start = ALIGN_DOWN (addr , size );
1182+ last = ALIGN (addr + 1 , size ) - 1 ;
1183+
1184+ pr_debug ("svms 0x%p split [0x%lx 0x%lx] to [0x%lx 0x%lx] size 0x%lx\n" ,
1185+ prange -> svms , prange -> start , prange -> last , start , last , size );
1186+
1187+ if (start > prange -> start ) {
1188+ r = svm_range_split (prange , start , prange -> last , & head );
1189+ if (r )
1190+ return r ;
1191+ svm_range_add_child (parent , mm , head , SVM_OP_ADD_RANGE );
1192+ }
1193+
1194+ if (last < prange -> last ) {
1195+ r = svm_range_split (prange , prange -> start , last , & tail );
1196+ if (r )
1197+ return r ;
1198+ svm_range_add_child (parent , mm , tail , SVM_OP_ADD_RANGE );
1199+ }
1200+
1201+ /* xnack on, update mapping on GPUs with ACCESS_IN_PLACE */
1202+ if (p -> xnack_enabled && prange -> work_item .op == SVM_OP_ADD_RANGE ) {
1203+ prange -> work_item .op = SVM_OP_ADD_RANGE_AND_MAP ;
1204+ pr_debug ("change prange 0x%p [0x%lx 0x%lx] op %d\n" ,
1205+ prange , prange -> start , prange -> last ,
1206+ SVM_OP_ADD_RANGE_AND_MAP );
1207+ }
1208+ return 0 ;
1209+ }
11501210static bool
11511211svm_nodes_in_same_hive (struct kfd_node * node_a , struct kfd_node * node_b )
11521212{
0 commit comments