forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-11 04dd17822334871b23ea2862f7798fb0e0007777
kernel/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
....@@ -255,11 +255,23 @@
255255 }
256256
257257 static bool
258
-nvkm_vmm_unref_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes)
258
+nvkm_vmm_unref_ptes(struct nvkm_vmm_iter *it, bool pfn, u32 ptei, u32 ptes)
259259 {
260260 const struct nvkm_vmm_desc *desc = it->desc;
261261 const int type = desc->type == SPT;
262262 struct nvkm_vmm_pt *pgt = it->pt[0];
263
+ bool dma;
264
+
265
+ if (pfn) {
266
+ /* Need to clear PTE valid bits before we dma_unmap_page(). */
267
+ dma = desc->func->pfn_clear(it->vmm, pgt->pt[type], ptei, ptes);
268
+ if (dma) {
269
+ /* GPU may have cached the PT, flush before unmap. */
270
+ nvkm_vmm_flush_mark(it);
271
+ nvkm_vmm_flush(it);
272
+ desc->func->pfn_unmap(it->vmm, pgt->pt[type], ptei, ptes);
273
+ }
274
+ }
263275
264276 /* Drop PTE references. */
265277 pgt->refs[type] -= ptes;
....@@ -349,7 +361,7 @@
349361 }
350362
351363 static bool
352
-nvkm_vmm_ref_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes)
364
+nvkm_vmm_ref_ptes(struct nvkm_vmm_iter *it, bool pfn, u32 ptei, u32 ptes)
353365 {
354366 const struct nvkm_vmm_desc *desc = it->desc;
355367 const int type = desc->type == SPT;
....@@ -379,7 +391,7 @@
379391 }
380392
381393 static bool
382
-nvkm_vmm_sparse_unref_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes)
394
+nvkm_vmm_sparse_unref_ptes(struct nvkm_vmm_iter *it, bool pfn, u32 ptei, u32 ptes)
383395 {
384396 struct nvkm_vmm_pt *pt = it->pt[0];
385397 if (it->desc->type == PGD)
....@@ -387,14 +399,14 @@
387399 else
388400 if (it->desc->type == LPT)
389401 memset(&pt->pte[ptei], 0x00, sizeof(pt->pte[0]) * ptes);
390
- return nvkm_vmm_unref_ptes(it, ptei, ptes);
402
+ return nvkm_vmm_unref_ptes(it, pfn, ptei, ptes);
391403 }
392404
393405 static bool
394
-nvkm_vmm_sparse_ref_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes)
406
+nvkm_vmm_sparse_ref_ptes(struct nvkm_vmm_iter *it, bool pfn, u32 ptei, u32 ptes)
395407 {
396408 nvkm_vmm_sparse_ptes(it->desc, it->pt[0], ptei, ptes);
397
- return nvkm_vmm_ref_ptes(it, ptei, ptes);
409
+ return nvkm_vmm_ref_ptes(it, pfn, ptei, ptes);
398410 }
399411
400412 static bool
....@@ -487,8 +499,8 @@
487499
488500 static inline u64
489501 nvkm_vmm_iter(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page,
490
- u64 addr, u64 size, const char *name, bool ref,
491
- bool (*REF_PTES)(struct nvkm_vmm_iter *, u32, u32),
502
+ u64 addr, u64 size, const char *name, bool ref, bool pfn,
503
+ bool (*REF_PTES)(struct nvkm_vmm_iter *, bool pfn, u32, u32),
492504 nvkm_vmm_pte_func MAP_PTES, struct nvkm_vmm_map *map,
493505 nvkm_vmm_pxe_func CLR_PTES)
494506 {
....@@ -548,7 +560,7 @@
548560 }
549561
550562 /* Handle PTE updates. */
551
- if (!REF_PTES || REF_PTES(&it, ptei, ptes)) {
563
+ if (!REF_PTES || REF_PTES(&it, pfn, ptei, ptes)) {
552564 struct nvkm_mmu_pt *pt = pgt->pt[type];
553565 if (MAP_PTES || CLR_PTES) {
554566 if (MAP_PTES)
....@@ -568,7 +580,7 @@
568580 it.pte[it.lvl]++;
569581 }
570582 }
571
- };
583
+ }
572584
573585 nvkm_vmm_flush(&it);
574586 return ~0ULL;
....@@ -590,7 +602,7 @@
590602 nvkm_vmm_ptes_sparse_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page,
591603 u64 addr, u64 size)
592604 {
593
- nvkm_vmm_iter(vmm, page, addr, size, "sparse unref", false,
605
+ nvkm_vmm_iter(vmm, page, addr, size, "sparse unref", false, false,
594606 nvkm_vmm_sparse_unref_ptes, NULL, NULL,
595607 page->desc->func->invalid ?
596608 page->desc->func->invalid : page->desc->func->unmap);
....@@ -602,8 +614,8 @@
602614 {
603615 if ((page->type & NVKM_VMM_PAGE_SPARSE)) {
604616 u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "sparse ref",
605
- true, nvkm_vmm_sparse_ref_ptes, NULL,
606
- NULL, page->desc->func->sparse);
617
+ true, false, nvkm_vmm_sparse_ref_ptes,
618
+ NULL, NULL, page->desc->func->sparse);
607619 if (fail != ~0ULL) {
608620 if ((size = fail - addr))
609621 nvkm_vmm_ptes_sparse_put(vmm, page, addr, size);
....@@ -666,11 +678,11 @@
666678
667679 static void
668680 nvkm_vmm_ptes_unmap_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page,
669
- u64 addr, u64 size, bool sparse)
681
+ u64 addr, u64 size, bool sparse, bool pfn)
670682 {
671683 const struct nvkm_vmm_desc_func *func = page->desc->func;
672684 nvkm_vmm_iter(vmm, page, addr, size, "unmap + unref",
673
- false, nvkm_vmm_unref_ptes, NULL, NULL,
685
+ false, pfn, nvkm_vmm_unref_ptes, NULL, NULL,
674686 sparse ? func->sparse : func->invalid ? func->invalid :
675687 func->unmap);
676688 }
....@@ -681,10 +693,10 @@
681693 nvkm_vmm_pte_func func)
682694 {
683695 u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "ref + map", true,
684
- nvkm_vmm_ref_ptes, func, map, NULL);
696
+ false, nvkm_vmm_ref_ptes, func, map, NULL);
685697 if (fail != ~0ULL) {
686698 if ((size = fail - addr))
687
- nvkm_vmm_ptes_unmap_put(vmm, page, addr, size, false);
699
+ nvkm_vmm_ptes_unmap_put(vmm, page, addr, size, false, false);
688700 return -ENOMEM;
689701 }
690702 return 0;
....@@ -692,10 +704,11 @@
692704
693705 static void
694706 nvkm_vmm_ptes_unmap(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page,
695
- u64 addr, u64 size, bool sparse)
707
+ u64 addr, u64 size, bool sparse, bool pfn)
696708 {
697709 const struct nvkm_vmm_desc_func *func = page->desc->func;
698
- nvkm_vmm_iter(vmm, page, addr, size, "unmap", false, NULL, NULL, NULL,
710
+ nvkm_vmm_iter(vmm, page, addr, size, "unmap", false, pfn,
711
+ NULL, NULL, NULL,
699712 sparse ? func->sparse : func->invalid ? func->invalid :
700713 func->unmap);
701714 }
....@@ -705,7 +718,7 @@
705718 u64 addr, u64 size, struct nvkm_vmm_map *map,
706719 nvkm_vmm_pte_func func)
707720 {
708
- nvkm_vmm_iter(vmm, page, addr, size, "map", false,
721
+ nvkm_vmm_iter(vmm, page, addr, size, "map", false, false,
709722 NULL, func, map, NULL);
710723 }
711724
....@@ -713,7 +726,7 @@
713726 nvkm_vmm_ptes_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page,
714727 u64 addr, u64 size)
715728 {
716
- nvkm_vmm_iter(vmm, page, addr, size, "unref", false,
729
+ nvkm_vmm_iter(vmm, page, addr, size, "unref", false, false,
717730 nvkm_vmm_unref_ptes, NULL, NULL, NULL);
718731 }
719732
....@@ -721,7 +734,7 @@
721734 nvkm_vmm_ptes_get(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page,
722735 u64 addr, u64 size)
723736 {
724
- u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "ref", true,
737
+ u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "ref", true, false,
725738 nvkm_vmm_ref_ptes, NULL, NULL, NULL);
726739 if (fail != ~0ULL) {
727740 if (fail != addr)
....@@ -763,8 +776,23 @@
763776 new->part = vma->part;
764777 new->user = vma->user;
765778 new->busy = vma->busy;
779
+ new->mapped = vma->mapped;
766780 list_add(&new->head, &vma->head);
767781 return new;
782
+}
783
+
784
+static inline void
785
+nvkm_vmm_free_remove(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
786
+{
787
+ rb_erase(&vma->tree, &vmm->free);
788
+}
789
+
790
+static inline void
791
+nvkm_vmm_free_delete(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
792
+{
793
+ nvkm_vmm_free_remove(vmm, vma);
794
+ list_del(&vma->head);
795
+ kfree(vma);
768796 }
769797
770798 static void
....@@ -795,7 +823,21 @@
795823 rb_insert_color(&vma->tree, &vmm->free);
796824 }
797825
798
-void
826
+static inline void
827
+nvkm_vmm_node_remove(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
828
+{
829
+ rb_erase(&vma->tree, &vmm->root);
830
+}
831
+
832
+static inline void
833
+nvkm_vmm_node_delete(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
834
+{
835
+ nvkm_vmm_node_remove(vmm, vma);
836
+ list_del(&vma->head);
837
+ kfree(vma);
838
+}
839
+
840
+static void
799841 nvkm_vmm_node_insert(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
800842 {
801843 struct rb_node **ptr = &vmm->root.rb_node;
....@@ -834,11 +876,112 @@
834876 return NULL;
835877 }
836878
879
+#define node(root, dir) (((root)->head.dir == &vmm->list) ? NULL : \
880
+ list_entry((root)->head.dir, struct nvkm_vma, head))
881
+
882
+static struct nvkm_vma *
883
+nvkm_vmm_node_merge(struct nvkm_vmm *vmm, struct nvkm_vma *prev,
884
+ struct nvkm_vma *vma, struct nvkm_vma *next, u64 size)
885
+{
886
+ if (next) {
887
+ if (vma->size == size) {
888
+ vma->size += next->size;
889
+ nvkm_vmm_node_delete(vmm, next);
890
+ if (prev) {
891
+ prev->size += vma->size;
892
+ nvkm_vmm_node_delete(vmm, vma);
893
+ return prev;
894
+ }
895
+ return vma;
896
+ }
897
+ BUG_ON(prev);
898
+
899
+ nvkm_vmm_node_remove(vmm, next);
900
+ vma->size -= size;
901
+ next->addr -= size;
902
+ next->size += size;
903
+ nvkm_vmm_node_insert(vmm, next);
904
+ return next;
905
+ }
906
+
907
+ if (prev) {
908
+ if (vma->size != size) {
909
+ nvkm_vmm_node_remove(vmm, vma);
910
+ prev->size += size;
911
+ vma->addr += size;
912
+ vma->size -= size;
913
+ nvkm_vmm_node_insert(vmm, vma);
914
+ } else {
915
+ prev->size += vma->size;
916
+ nvkm_vmm_node_delete(vmm, vma);
917
+ }
918
+ return prev;
919
+ }
920
+
921
+ return vma;
922
+}
923
+
924
+struct nvkm_vma *
925
+nvkm_vmm_node_split(struct nvkm_vmm *vmm,
926
+ struct nvkm_vma *vma, u64 addr, u64 size)
927
+{
928
+ struct nvkm_vma *prev = NULL;
929
+
930
+ if (vma->addr != addr) {
931
+ prev = vma;
932
+ if (!(vma = nvkm_vma_tail(vma, vma->size + vma->addr - addr)))
933
+ return NULL;
934
+ vma->part = true;
935
+ nvkm_vmm_node_insert(vmm, vma);
936
+ }
937
+
938
+ if (vma->size != size) {
939
+ struct nvkm_vma *tmp;
940
+ if (!(tmp = nvkm_vma_tail(vma, vma->size - size))) {
941
+ nvkm_vmm_node_merge(vmm, prev, vma, NULL, vma->size);
942
+ return NULL;
943
+ }
944
+ tmp->part = true;
945
+ nvkm_vmm_node_insert(vmm, tmp);
946
+ }
947
+
948
+ return vma;
949
+}
950
+
951
+static void
952
+nvkm_vma_dump(struct nvkm_vma *vma)
953
+{
954
+ printk(KERN_ERR "%016llx %016llx %c%c%c%c%c%c%c%c%c %p\n",
955
+ vma->addr, (u64)vma->size,
956
+ vma->used ? '-' : 'F',
957
+ vma->mapref ? 'R' : '-',
958
+ vma->sparse ? 'S' : '-',
959
+ vma->page != NVKM_VMA_PAGE_NONE ? '0' + vma->page : '-',
960
+ vma->refd != NVKM_VMA_PAGE_NONE ? '0' + vma->refd : '-',
961
+ vma->part ? 'P' : '-',
962
+ vma->user ? 'U' : '-',
963
+ vma->busy ? 'B' : '-',
964
+ vma->mapped ? 'M' : '-',
965
+ vma->memory);
966
+}
967
+
968
+static void
969
+nvkm_vmm_dump(struct nvkm_vmm *vmm)
970
+{
971
+ struct nvkm_vma *vma;
972
+ list_for_each_entry(vma, &vmm->list, head) {
973
+ nvkm_vma_dump(vma);
974
+ }
975
+}
976
+
837977 static void
838978 nvkm_vmm_dtor(struct nvkm_vmm *vmm)
839979 {
840980 struct nvkm_vma *vma;
841981 struct rb_node *node;
982
+
983
+ if (0)
984
+ nvkm_vmm_dump(vmm);
842985
843986 while ((node = rb_first(&vmm->root))) {
844987 struct nvkm_vma *vma = rb_entry(node, typeof(*vma), tree);
....@@ -872,16 +1015,32 @@
8721015 }
8731016 }
8741017
875
-int
1018
+static int
1019
+nvkm_vmm_ctor_managed(struct nvkm_vmm *vmm, u64 addr, u64 size)
1020
+{
1021
+ struct nvkm_vma *vma;
1022
+ if (!(vma = nvkm_vma_new(addr, size)))
1023
+ return -ENOMEM;
1024
+ vma->mapref = true;
1025
+ vma->sparse = false;
1026
+ vma->used = true;
1027
+ vma->user = true;
1028
+ nvkm_vmm_node_insert(vmm, vma);
1029
+ list_add_tail(&vma->head, &vmm->list);
1030
+ return 0;
1031
+}
1032
+
1033
+static int
8761034 nvkm_vmm_ctor(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu,
877
- u32 pd_header, u64 addr, u64 size, struct lock_class_key *key,
878
- const char *name, struct nvkm_vmm *vmm)
1035
+ u32 pd_header, bool managed, u64 addr, u64 size,
1036
+ struct lock_class_key *key, const char *name,
1037
+ struct nvkm_vmm *vmm)
8791038 {
8801039 static struct lock_class_key _key;
8811040 const struct nvkm_vmm_page *page = func->page;
8821041 const struct nvkm_vmm_desc *desc;
8831042 struct nvkm_vma *vma;
884
- int levels, bits = 0;
1043
+ int levels, bits = 0, ret;
8851044
8861045 vmm->func = func;
8871046 vmm->mmu = mmu;
....@@ -909,11 +1068,6 @@
9091068 if (WARN_ON(levels > NVKM_VMM_LEVELS_MAX))
9101069 return -EINVAL;
9111070
912
- vmm->start = addr;
913
- vmm->limit = size ? (addr + size) : (1ULL << bits);
914
- if (vmm->start > vmm->limit || vmm->limit > (1ULL << bits))
915
- return -EINVAL;
916
-
9171071 /* Allocate top-level page table. */
9181072 vmm->pd = nvkm_vmm_pt_new(desc, false, NULL);
9191073 if (!vmm->pd)
....@@ -936,67 +1090,272 @@
9361090 vmm->free = RB_ROOT;
9371091 vmm->root = RB_ROOT;
9381092
939
- if (!(vma = nvkm_vma_new(vmm->start, vmm->limit - vmm->start)))
940
- return -ENOMEM;
1093
+ if (managed) {
1094
+ /* Address-space will be managed by the client for the most
1095
+ * part, except for a specified area where NVKM allocations
1096
+ * are allowed to be placed.
1097
+ */
1098
+ vmm->start = 0;
1099
+ vmm->limit = 1ULL << bits;
1100
+ if (addr + size < addr || addr + size > vmm->limit)
1101
+ return -EINVAL;
9411102
942
- nvkm_vmm_free_insert(vmm, vma);
943
- list_add(&vma->head, &vmm->list);
1103
+ /* Client-managed area before the NVKM-managed area. */
1104
+ if (addr && (ret = nvkm_vmm_ctor_managed(vmm, 0, addr)))
1105
+ return ret;
1106
+
1107
+ /* NVKM-managed area. */
1108
+ if (size) {
1109
+ if (!(vma = nvkm_vma_new(addr, size)))
1110
+ return -ENOMEM;
1111
+ nvkm_vmm_free_insert(vmm, vma);
1112
+ list_add_tail(&vma->head, &vmm->list);
1113
+ }
1114
+
1115
+ /* Client-managed area after the NVKM-managed area. */
1116
+ addr = addr + size;
1117
+ size = vmm->limit - addr;
1118
+ if (size && (ret = nvkm_vmm_ctor_managed(vmm, addr, size)))
1119
+ return ret;
1120
+ } else {
1121
+ /* Address-space fully managed by NVKM, requiring calls to
1122
+ * nvkm_vmm_get()/nvkm_vmm_put() to allocate address-space.
1123
+ */
1124
+ vmm->start = addr;
1125
+ vmm->limit = size ? (addr + size) : (1ULL << bits);
1126
+ if (vmm->start > vmm->limit || vmm->limit > (1ULL << bits))
1127
+ return -EINVAL;
1128
+
1129
+ if (!(vma = nvkm_vma_new(vmm->start, vmm->limit - vmm->start)))
1130
+ return -ENOMEM;
1131
+
1132
+ nvkm_vmm_free_insert(vmm, vma);
1133
+ list_add(&vma->head, &vmm->list);
1134
+ }
1135
+
9441136 return 0;
9451137 }
9461138
9471139 int
9481140 nvkm_vmm_new_(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu,
949
- u32 hdr, u64 addr, u64 size, struct lock_class_key *key,
950
- const char *name, struct nvkm_vmm **pvmm)
1141
+ u32 hdr, bool managed, u64 addr, u64 size,
1142
+ struct lock_class_key *key, const char *name,
1143
+ struct nvkm_vmm **pvmm)
9511144 {
9521145 if (!(*pvmm = kzalloc(sizeof(**pvmm), GFP_KERNEL)))
9531146 return -ENOMEM;
954
- return nvkm_vmm_ctor(func, mmu, hdr, addr, size, key, name, *pvmm);
1147
+ return nvkm_vmm_ctor(func, mmu, hdr, managed, addr, size, key, name, *pvmm);
9551148 }
9561149
957
-#define node(root, dir) ((root)->head.dir == &vmm->list) ? NULL : \
958
- list_entry((root)->head.dir, struct nvkm_vma, head)
1150
+static struct nvkm_vma *
1151
+nvkm_vmm_pfn_split_merge(struct nvkm_vmm *vmm, struct nvkm_vma *vma,
1152
+ u64 addr, u64 size, u8 page, bool map)
1153
+{
1154
+ struct nvkm_vma *prev = NULL;
1155
+ struct nvkm_vma *next = NULL;
1156
+
1157
+ if (vma->addr == addr && vma->part && (prev = node(vma, prev))) {
1158
+ if (prev->memory || prev->mapped != map)
1159
+ prev = NULL;
1160
+ }
1161
+
1162
+ if (vma->addr + vma->size == addr + size && (next = node(vma, next))) {
1163
+ if (!next->part ||
1164
+ next->memory || next->mapped != map)
1165
+ next = NULL;
1166
+ }
1167
+
1168
+ if (prev || next)
1169
+ return nvkm_vmm_node_merge(vmm, prev, vma, next, size);
1170
+ return nvkm_vmm_node_split(vmm, vma, addr, size);
1171
+}
1172
+
1173
+int
1174
+nvkm_vmm_pfn_unmap(struct nvkm_vmm *vmm, u64 addr, u64 size)
1175
+{
1176
+ struct nvkm_vma *vma = nvkm_vmm_node_search(vmm, addr);
1177
+ struct nvkm_vma *next;
1178
+ u64 limit = addr + size;
1179
+ u64 start = addr;
1180
+
1181
+ if (!vma)
1182
+ return -EINVAL;
1183
+
1184
+ do {
1185
+ if (!vma->mapped || vma->memory)
1186
+ continue;
1187
+
1188
+ size = min(limit - start, vma->size - (start - vma->addr));
1189
+
1190
+ nvkm_vmm_ptes_unmap_put(vmm, &vmm->func->page[vma->refd],
1191
+ start, size, false, true);
1192
+
1193
+ next = nvkm_vmm_pfn_split_merge(vmm, vma, start, size, 0, false);
1194
+ if (!WARN_ON(!next)) {
1195
+ vma = next;
1196
+ vma->refd = NVKM_VMA_PAGE_NONE;
1197
+ vma->mapped = false;
1198
+ }
1199
+ } while ((vma = node(vma, next)) && (start = vma->addr) < limit);
1200
+
1201
+ return 0;
1202
+}
1203
+
1204
+/*TODO:
1205
+ * - Avoid PT readback (for dma_unmap etc), this might end up being dealt
1206
+ * with inside HMM, which would be a lot nicer for us to deal with.
1207
+ * - Support for systems without a 4KiB page size.
1208
+ */
1209
+int
1210
+nvkm_vmm_pfn_map(struct nvkm_vmm *vmm, u8 shift, u64 addr, u64 size, u64 *pfn)
1211
+{
1212
+ const struct nvkm_vmm_page *page = vmm->func->page;
1213
+ struct nvkm_vma *vma, *tmp;
1214
+ u64 limit = addr + size;
1215
+ u64 start = addr;
1216
+ int pm = size >> shift;
1217
+ int pi = 0;
1218
+
1219
+ /* Only support mapping where the page size of the incoming page
1220
+ * array matches a page size available for direct mapping.
1221
+ */
1222
+ while (page->shift && (page->shift != shift ||
1223
+ page->desc->func->pfn == NULL))
1224
+ page++;
1225
+
1226
+ if (!page->shift || !IS_ALIGNED(addr, 1ULL << shift) ||
1227
+ !IS_ALIGNED(size, 1ULL << shift) ||
1228
+ addr + size < addr || addr + size > vmm->limit) {
1229
+ VMM_DEBUG(vmm, "paged map %d %d %016llx %016llx\n",
1230
+ shift, page->shift, addr, size);
1231
+ return -EINVAL;
1232
+ }
1233
+
1234
+ if (!(vma = nvkm_vmm_node_search(vmm, addr)))
1235
+ return -ENOENT;
1236
+
1237
+ do {
1238
+ bool map = !!(pfn[pi] & NVKM_VMM_PFN_V);
1239
+ bool mapped = vma->mapped;
1240
+ u64 size = limit - start;
1241
+ u64 addr = start;
1242
+ int pn, ret = 0;
1243
+
1244
+ /* Narrow the operation window to cover a single action (page
1245
+ * should be mapped or not) within a single VMA.
1246
+ */
1247
+ for (pn = 0; pi + pn < pm; pn++) {
1248
+ if (map != !!(pfn[pi + pn] & NVKM_VMM_PFN_V))
1249
+ break;
1250
+ }
1251
+ size = min_t(u64, size, pn << page->shift);
1252
+ size = min_t(u64, size, vma->size + vma->addr - addr);
1253
+
1254
+ /* Reject any operation to unmanaged regions, and areas that
1255
+ * have nvkm_memory objects mapped in them already.
1256
+ */
1257
+ if (!vma->mapref || vma->memory) {
1258
+ ret = -EINVAL;
1259
+ goto next;
1260
+ }
1261
+
1262
+ /* In order to both properly refcount GPU page tables, and
1263
+ * prevent "normal" mappings and these direct mappings from
1264
+ * interfering with each other, we need to track contiguous
1265
+ * ranges that have been mapped with this interface.
1266
+ *
1267
+ * Here we attempt to either split an existing VMA so we're
1268
+ * able to flag the region as either unmapped/mapped, or to
1269
+ * merge with adjacent VMAs that are already compatible.
1270
+ *
1271
+ * If the region is already compatible, nothing is required.
1272
+ */
1273
+ if (map != mapped) {
1274
+ tmp = nvkm_vmm_pfn_split_merge(vmm, vma, addr, size,
1275
+ page -
1276
+ vmm->func->page, map);
1277
+ if (WARN_ON(!tmp)) {
1278
+ ret = -ENOMEM;
1279
+ goto next;
1280
+ }
1281
+
1282
+ if ((tmp->mapped = map))
1283
+ tmp->refd = page - vmm->func->page;
1284
+ else
1285
+ tmp->refd = NVKM_VMA_PAGE_NONE;
1286
+ vma = tmp;
1287
+ }
1288
+
1289
+ /* Update HW page tables. */
1290
+ if (map) {
1291
+ struct nvkm_vmm_map args;
1292
+ args.page = page;
1293
+ args.pfn = &pfn[pi];
1294
+
1295
+ if (!mapped) {
1296
+ ret = nvkm_vmm_ptes_get_map(vmm, page, addr,
1297
+ size, &args, page->
1298
+ desc->func->pfn);
1299
+ } else {
1300
+ nvkm_vmm_ptes_map(vmm, page, addr, size, &args,
1301
+ page->desc->func->pfn);
1302
+ }
1303
+ } else {
1304
+ if (mapped) {
1305
+ nvkm_vmm_ptes_unmap_put(vmm, page, addr, size,
1306
+ false, true);
1307
+ }
1308
+ }
1309
+
1310
+next:
1311
+ /* Iterate to next operation. */
1312
+ if (vma->addr + vma->size == addr + size)
1313
+ vma = node(vma, next);
1314
+ start += size;
1315
+
1316
+ if (ret) {
1317
+ /* Failure is signalled by clearing the valid bit on
1318
+ * any PFN that couldn't be modified as requested.
1319
+ */
1320
+ while (size) {
1321
+ pfn[pi++] = NVKM_VMM_PFN_NONE;
1322
+ size -= 1 << page->shift;
1323
+ }
1324
+ } else {
1325
+ pi += size >> page->shift;
1326
+ }
1327
+ } while (vma && start < limit);
1328
+
1329
+ return 0;
1330
+}
9591331
9601332 void
9611333 nvkm_vmm_unmap_region(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
9621334 {
1335
+ struct nvkm_vma *prev = NULL;
9631336 struct nvkm_vma *next;
9641337
9651338 nvkm_memory_tags_put(vma->memory, vmm->mmu->subdev.device, &vma->tags);
9661339 nvkm_memory_unref(&vma->memory);
1340
+ vma->mapped = false;
9671341
968
- if (vma->part) {
969
- struct nvkm_vma *prev = node(vma, prev);
970
- if (!prev->memory) {
971
- prev->size += vma->size;
972
- rb_erase(&vma->tree, &vmm->root);
973
- list_del(&vma->head);
974
- kfree(vma);
975
- vma = prev;
976
- }
977
- }
978
-
979
- next = node(vma, next);
980
- if (next && next->part) {
981
- if (!next->memory) {
982
- vma->size += next->size;
983
- rb_erase(&next->tree, &vmm->root);
984
- list_del(&next->head);
985
- kfree(next);
986
- }
987
- }
1342
+ if (vma->part && (prev = node(vma, prev)) && prev->mapped)
1343
+ prev = NULL;
1344
+ if ((next = node(vma, next)) && (!next->part || next->mapped))
1345
+ next = NULL;
1346
+ nvkm_vmm_node_merge(vmm, prev, vma, next, vma->size);
9881347 }
9891348
9901349 void
991
-nvkm_vmm_unmap_locked(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
1350
+nvkm_vmm_unmap_locked(struct nvkm_vmm *vmm, struct nvkm_vma *vma, bool pfn)
9921351 {
9931352 const struct nvkm_vmm_page *page = &vmm->func->page[vma->refd];
9941353
9951354 if (vma->mapref) {
996
- nvkm_vmm_ptes_unmap_put(vmm, page, vma->addr, vma->size, vma->sparse);
1355
+ nvkm_vmm_ptes_unmap_put(vmm, page, vma->addr, vma->size, vma->sparse, pfn);
9971356 vma->refd = NVKM_VMA_PAGE_NONE;
9981357 } else {
999
- nvkm_vmm_ptes_unmap(vmm, page, vma->addr, vma->size, vma->sparse);
1358
+ nvkm_vmm_ptes_unmap(vmm, page, vma->addr, vma->size, vma->sparse, pfn);
10001359 }
10011360
10021361 nvkm_vmm_unmap_region(vmm, vma);
....@@ -1007,7 +1366,7 @@
10071366 {
10081367 if (vma->memory) {
10091368 mutex_lock(&vmm->mutex);
1010
- nvkm_vmm_unmap_locked(vmm, vma);
1369
+ nvkm_vmm_unmap_locked(vmm, vma, false);
10111370 mutex_unlock(&vmm->mutex);
10121371 }
10131372 }
....@@ -1141,6 +1500,7 @@
11411500 nvkm_memory_tags_put(vma->memory, vmm->mmu->subdev.device, &vma->tags);
11421501 nvkm_memory_unref(&vma->memory);
11431502 vma->memory = nvkm_memory_ref(map->memory);
1503
+ vma->mapped = true;
11441504 vma->tags = map->tags;
11451505 return 0;
11461506 }
....@@ -1163,18 +1523,14 @@
11631523 struct nvkm_vma *prev, *next;
11641524
11651525 if ((prev = node(vma, prev)) && !prev->used) {
1166
- rb_erase(&prev->tree, &vmm->free);
1167
- list_del(&prev->head);
11681526 vma->addr = prev->addr;
11691527 vma->size += prev->size;
1170
- kfree(prev);
1528
+ nvkm_vmm_free_delete(vmm, prev);
11711529 }
11721530
11731531 if ((next = node(vma, next)) && !next->used) {
1174
- rb_erase(&next->tree, &vmm->free);
1175
- list_del(&next->head);
11761532 vma->size += next->size;
1177
- kfree(next);
1533
+ nvkm_vmm_free_delete(vmm, next);
11781534 }
11791535
11801536 nvkm_vmm_free_insert(vmm, vma);
....@@ -1190,14 +1546,16 @@
11901546
11911547 if (vma->mapref || !vma->sparse) {
11921548 do {
1193
- const bool map = next->memory != NULL;
1549
+ const bool mem = next->memory != NULL;
1550
+ const bool map = next->mapped;
11941551 const u8 refd = next->refd;
11951552 const u64 addr = next->addr;
11961553 u64 size = next->size;
11971554
11981555 /* Merge regions that are in the same state. */
11991556 while ((next = node(next, next)) && next->part &&
1200
- (next->memory != NULL) == map &&
1557
+ (next->mapped == map) &&
1558
+ (next->memory != NULL) == mem &&
12011559 (next->refd == refd))
12021560 size += next->size;
12031561
....@@ -1207,7 +1565,8 @@
12071565 * the page tree.
12081566 */
12091567 nvkm_vmm_ptes_unmap_put(vmm, &page[refd], addr,
1210
- size, vma->sparse);
1568
+ size, vma->sparse,
1569
+ !mem);
12111570 } else
12121571 if (refd != NVKM_VMA_PAGE_NONE) {
12131572 /* Drop allocation-time PTE references. */
....@@ -1222,7 +1581,7 @@
12221581 */
12231582 next = vma;
12241583 do {
1225
- if (next->memory)
1584
+ if (next->mapped)
12261585 nvkm_vmm_unmap_region(vmm, next);
12271586 } while ((next = node(vma, next)) && next->part);
12281587
....@@ -1250,7 +1609,7 @@
12501609 }
12511610
12521611 /* Remove VMA from the list of allocated nodes. */
1253
- rb_erase(&vma->tree, &vmm->root);
1612
+ nvkm_vmm_node_remove(vmm, vma);
12541613
12551614 /* Merge VMA back into the free list. */
12561615 vma->page = NVKM_VMA_PAGE_NONE;
....@@ -1357,7 +1716,7 @@
13571716 tail = ALIGN_DOWN(tail, vmm->func->page_block);
13581717
13591718 if (addr <= tail && tail - addr >= size) {
1360
- rb_erase(&this->tree, &vmm->free);
1719
+ nvkm_vmm_free_remove(vmm, this);
13611720 vma = this;
13621721 break;
13631722 }
....@@ -1443,7 +1802,7 @@
14431802 }
14441803
14451804 static bool
1446
-nvkm_vmm_boot_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes)
1805
+nvkm_vmm_boot_ptes(struct nvkm_vmm_iter *it, bool pfn, u32 ptei, u32 ptes)
14471806 {
14481807 const struct nvkm_vmm_desc *desc = it->desc;
14491808 const int type = desc->type == SPT;
....@@ -1465,7 +1824,7 @@
14651824 if (ret)
14661825 return ret;
14671826
1468
- nvkm_vmm_iter(vmm, page, vmm->start, limit, "bootstrap", false,
1827
+ nvkm_vmm_iter(vmm, page, vmm->start, limit, "bootstrap", false, false,
14691828 nvkm_vmm_boot_ptes, NULL, NULL, NULL);
14701829 vmm->bootstrapped = true;
14711830 return 0;
....@@ -1505,7 +1864,8 @@
15051864 struct nvkm_mmu *mmu = device->mmu;
15061865 struct nvkm_vmm *vmm = NULL;
15071866 int ret;
1508
- ret = mmu->func->vmm.ctor(mmu, addr, size, argv, argc, key, name, &vmm);
1867
+ ret = mmu->func->vmm.ctor(mmu, false, addr, size, argv, argc,
1868
+ key, name, &vmm);
15091869 if (ret)
15101870 nvkm_vmm_unref(&vmm);
15111871 *pvmm = vmm;