|
@@ -61,6 +61,15 @@ struct mmu_notifier_ops {
|
|
|
struct mm_struct *mm,
|
|
|
unsigned long address);
|
|
|
|
|
|
+ /*
|
|
|
+ * change_pte is called in cases that pte mapping to page is changed:
|
|
|
+ * for example, when ksm remaps pte to point to a new shared page.
|
|
|
+ */
|
|
|
+ void (*change_pte)(struct mmu_notifier *mn,
|
|
|
+ struct mm_struct *mm,
|
|
|
+ unsigned long address,
|
|
|
+ pte_t pte);
|
|
|
+
|
|
|
/*
|
|
|
* Before this is invoked any secondary MMU is still ok to
|
|
|
* read/write to the page previously pointed to by the Linux
|
|
@@ -154,6 +163,8 @@ extern void __mmu_notifier_mm_destroy(struct mm_struct *mm);
|
|
|
extern void __mmu_notifier_release(struct mm_struct *mm);
|
|
|
extern int __mmu_notifier_clear_flush_young(struct mm_struct *mm,
|
|
|
unsigned long address);
|
|
|
+extern void __mmu_notifier_change_pte(struct mm_struct *mm,
|
|
|
+ unsigned long address, pte_t pte);
|
|
|
extern void __mmu_notifier_invalidate_page(struct mm_struct *mm,
|
|
|
unsigned long address);
|
|
|
extern void __mmu_notifier_invalidate_range_start(struct mm_struct *mm,
|
|
@@ -175,6 +186,13 @@ static inline int mmu_notifier_clear_flush_young(struct mm_struct *mm,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static inline void mmu_notifier_change_pte(struct mm_struct *mm,
|
|
|
+ unsigned long address, pte_t pte)
|
|
|
+{
|
|
|
+ if (mm_has_notifiers(mm))
|
|
|
+ __mmu_notifier_change_pte(mm, address, pte);
|
|
|
+}
|
|
|
+
|
|
|
static inline void mmu_notifier_invalidate_page(struct mm_struct *mm,
|
|
|
unsigned long address)
|
|
|
{
|
|
@@ -236,6 +254,16 @@ static inline void mmu_notifier_mm_destroy(struct mm_struct *mm)
|
|
|
__young; \
|
|
|
})
|
|
|
|
|
|
+#define set_pte_at_notify(__mm, __address, __ptep, __pte) \
|
|
|
+({ \
|
|
|
+ struct mm_struct *___mm = __mm; \
|
|
|
+ unsigned long ___address = __address; \
|
|
|
+ pte_t ___pte = __pte; \
|
|
|
+ \
|
|
|
+ set_pte_at(___mm, ___address, __ptep, ___pte); \
|
|
|
+ mmu_notifier_change_pte(___mm, ___address, ___pte); \
|
|
|
+})
|
|
|
+
|
|
|
#else /* CONFIG_MMU_NOTIFIER */
|
|
|
|
|
|
static inline void mmu_notifier_release(struct mm_struct *mm)
|
|
@@ -248,6 +276,11 @@ static inline int mmu_notifier_clear_flush_young(struct mm_struct *mm,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static inline void mmu_notifier_change_pte(struct mm_struct *mm,
|
|
|
+ unsigned long address, pte_t pte)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
static inline void mmu_notifier_invalidate_page(struct mm_struct *mm,
|
|
|
unsigned long address)
|
|
|
{
|
|
@@ -273,6 +306,7 @@ static inline void mmu_notifier_mm_destroy(struct mm_struct *mm)
|
|
|
|
|
|
#define ptep_clear_flush_young_notify ptep_clear_flush_young
|
|
|
#define ptep_clear_flush_notify ptep_clear_flush
|
|
|
+#define set_pte_at_notify set_pte_at
|
|
|
|
|
|
#endif /* CONFIG_MMU_NOTIFIER */
|
|
|
|