#ifdef CONFIG_MMU_NOTIFIER
static void scif_mmu_notifier_release(struct mmu_notifier *mn,
struct mm_struct *mm);
-static void scif_mmu_notifier_invalidate_page(struct mmu_notifier *mn,
- struct mm_struct *mm,
- unsigned long address);
-static void scif_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
+static int scif_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
struct mm_struct *mm,
- unsigned long start, unsigned long end);
+ unsigned long start, unsigned long end,
+ bool blockable);
static void scif_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
struct mm_struct *mm,
unsigned long start, unsigned long end);
.release = scif_mmu_notifier_release,
.clear_flush_young = NULL,
.change_pte = NULL,/*TODO*/
- .invalidate_page = scif_mmu_notifier_invalidate_page,
.invalidate_range_start = scif_mmu_notifier_invalidate_range_start,
.invalidate_range_end = scif_mmu_notifier_invalidate_range_end};
return;
}
-static void scif_mmu_notifier_invalidate_page(struct mmu_notifier *mn,
- struct mm_struct *mm,
- unsigned long address)
-{
- struct endpt *ep;
- struct rma_mmu_notifier *mmn;
- mmn = container_of(mn, struct rma_mmu_notifier, ep_mmu_notifier);
- ep = mmn->ep;
- micscif_rma_destroy_tcw(mmn, ep, true, address, PAGE_SIZE);
- pr_debug("%s address 0x%lx\n", __func__, address);
- return;
-}
-
-static void scif_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
+static int scif_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
struct mm_struct *mm,
- unsigned long start, unsigned long end)
+ unsigned long start, unsigned long end,
+ bool blockable)
{
struct endpt *ep;
struct rma_mmu_notifier *mmn;
mmn = container_of(mn, struct rma_mmu_notifier, ep_mmu_notifier);
ep = mmn->ep;
+ /*
+ * The kernel file `include/linux/mmu_notifier.h` states the following
+ * regarding the invalidate_range_start() callback:
+ *
+ * If blockable argument is set to false then the callback cannot
+ * sleep and has to return with -EAGAIN. 0 should be returned
+ * otherwise.
+ *
+ * The following function executes spin_lock_irqsave(), which feels like it
+ * qualifies as 'sleep'. However, returning -EAGAIN would require me to
+ * understand the location and function of all code that calls this
+ * callback. I do not yet have that understanding.
+ *
+ * For now, maintain the original behavior of calling
+ * micscif_rma_destroy_tcw() every time, accepting the spinlock. If this
+ * becomes problematic, either figure out all the code that can call this
+ * function and teach it to understand -EAGAIN, or investigate the `#ifdef
+ * CONFIG_MMU_NOTIFIER`.
+ *
+ * If you ended up here while tracking down a bug and pulling your hair
+ * out, sorry. :-(
+ */
micscif_rma_destroy_tcw(mmn, ep, true, (uint64_t)start, (uint64_t)(end - start));
pr_debug("%s start=%lx, end=%lx\n", __func__, start, end);
- return;
+ return 0;
}
static void scif_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,