@@ -8,6 +8,7 @@
#include "xe_svm.h"
#include <linux/hmm.h>
#include <linux/scatterlist.h>
+#include "xe_pt.h"
DEFINE_HASHTABLE(xe_svm_table, XE_MAX_SVM_PROCESS);
@@ -54,7 +54,6 @@ struct xe_svm {
struct xe_svm_range {
/** @svm: pointer of the xe_svm that this range belongs to */
struct xe_svm *svm;
-
/** @notifier: The mmu interval notifer used to keep track of CPU
* side address range change. Driver will get a callback with this
* notifier if anything changed from CPU side, such as range is
@@ -10,6 +10,7 @@
#include <linux/mutex.h>
#include <linux/mm.h>
#include "xe_svm.h"
+#include "xe_pt.h"
/**
* xe_svm_range_from_addr() - retrieve svm_range contains a virtual address
@@ -59,8 +60,42 @@ bool xe_svm_range_belongs_to_vma(struct mm_struct *mm,
return (vma1 == vma) && (vma2 == vma);
}
+static bool xe_svm_range_invalidate(struct mmu_interval_notifier *mni,
+ const struct mmu_notifier_range *range,
+ unsigned long cur_seq)
+{
+ struct xe_svm_range *svm_range =
+ container_of(mni, struct xe_svm_range, notifier);
+ struct xe_svm *svm = svm_range->svm;
+ unsigned long length = range->end - range->start;
+
+ /*
+ * MMU_NOTIFY_RELEASE is called upon process exit to notify driver
+ * to release any process resources, such as zap GPU page table
+ * mapping or unregister mmu notifier etc. We already clear GPU
+ * page table and unregister mmu notifier in in xe_destroy_svm,
+ * upon process exit. So just simply return here.
+ */
+ if (range->event == MMU_NOTIFY_RELEASE)
+ return true;
+
+ if (mmu_notifier_range_blockable(range))
+ mutex_lock(&svm->mutex);
+ else if (!mutex_trylock(&svm->mutex))
+ return false;
+
+ mmu_interval_set_seq(mni, cur_seq);
+ xe_invalidate_svm_range(svm->vm, range->start, length);
+ mutex_unlock(&svm->mutex);
+
+ if (range->event == MMU_NOTIFY_UNMAP)
+ queue_work(system_unbound_wq, &svm_range->unregister_notifier_work);
+
+ return true;
+}
+
static const struct mmu_interval_notifier_ops xe_svm_mni_ops = {
- .invalidate = NULL,
+ .invalidate = xe_svm_range_invalidate,
};
/**