[patch] my mmu notifier sample driver

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Nick Piggin
Date: Tuesday, February 19, 2008 - 1:44 am

Index: linux-2.6/drivers/char/mmu_notifier_skel.c
===================================================================
--- /dev/null
+++ linux-2.6/drivers/char/mmu_notifier_skel.c
@@ -0,0 +1,255 @@
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/mmu_notifier.h>
+#include <linux/radix-tree.h>
+#include <linux/seqlock.h>
+#include <asm/tlbflush.h>
+
+static DEFINE_SPINLOCK(mmn_lock);
+static RADIX_TREE(rmap_tree, GFP_ATOMIC);
+static seqcount_t rmap_seq = SEQCNT_ZERO;
+
+static int __rmap_add(unsigned long mem, unsigned long vaddr)
+{
+	int err;
+
+	err = radix_tree_insert(&rmap_tree, mem >> PAGE_SHIFT, (void *)vaddr);
+
+	return err;
+}
+
+static void __rmap_del(unsigned long mem)
+{
+	void *ret;
+
+	ret = radix_tree_delete(&rmap_tree, mem >> PAGE_SHIFT);
+	BUG_ON(!ret);
+}
+
+static unsigned long rmap_find(unsigned long mem)
+{
+	unsigned long vaddr;
+
+	rcu_read_lock();
+	vaddr = (unsigned long)radix_tree_lookup(&rmap_tree, mem >> PAGE_SHIFT);
+	rcu_read_unlock();
+
+	return vaddr;
+}
+
+static struct page *follow_page_atomic(struct mm_struct *mm, unsigned long address, int write)
+{
+	struct vm_area_struct *vma;
+
+	vma = find_vma(mm, address);
+        if (!vma || (vma->vm_start > address))
+                return NULL;
+
+	if (vma->vm_flags & (VM_IO | VM_PFNMAP))
+		return NULL;
+
+	return follow_page(vma, address, FOLL_GET|(write ? FOLL_WRITE : 0));
+}
+
+static int mmn_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long source_vaddr = (unsigned long)vmf->pgoff << PAGE_SHIFT;
+	unsigned long dest_vaddr = (unsigned long)vmf->virtual_address;
+	unsigned long pfn;
+	struct page *page;
+	pgprot_t prot;
+	int write = vmf->flags & FAULT_FLAG_WRITE;
+	int ret;
+
+	printk("mmn_vm_fault %s@vaddr=%lx sourcing from %lx\n", write ? "write" : "read", dest_vaddr, source_vaddr);
+
+	BUG_ON(mm != current->mm); /* disallow get_user_pages */
+
+again:
+	spin_lock(&mmn_lock);
+	write_seqcount_begin(&rmap_seq);
+	page = follow_page_atomic(mm, source_vaddr, write);
+	if (unlikely(!page)) {
+		write_seqcount_end(&rmap_seq);
+		spin_unlock(&mmn_lock);
+		ret = get_user_pages(current, mm, source_vaddr,
+					1, write, 0, &page, NULL);
+		if (ret != 1)
+			goto out_err;
+		put_page(page);
+		goto again;
+	}
+
+	ret = __rmap_add(source_vaddr, dest_vaddr);
+	if (ret)
+		goto out_lock;
+
+	pfn = page_to_pfn(page);
+	prot = vma->vm_page_prot;
+	if (!write)
+		vma->vm_page_prot = vm_get_page_prot(vma->vm_flags & ~(VM_WRITE|VM_MAYWRITE));
+	ret = vm_insert_pfn(vma, dest_vaddr, pfn);
+	vma->vm_page_prot = prot;
+	if (ret) {
+		if (ret == -EBUSY)
+			WARN_ON(1);
+		goto out_rmap;
+	}
+	write_seqcount_end(&rmap_seq);
+	spin_unlock(&mmn_lock);
+	put_page(page);
+
+        return VM_FAULT_NOPAGE;
+
+out_rmap:
+	__rmap_del(source_vaddr);
+out_lock:
+	write_seqcount_end(&rmap_seq);
+	spin_unlock(&mmn_lock);
+	put_page(page);
+out_err:
+	switch (ret) {
+	case -EFAULT:
+	case -EEXIST:
+	case -EBUSY:
+		return VM_FAULT_SIGBUS;
+	case -ENOMEM:
+		return VM_FAULT_OOM;
+	default:
+		BUG();
+	}
+}
+
+struct vm_operations_struct mmn_vm_ops = {
+        .fault = mmn_vm_fault,
+};
+
+static int mmu_notifier_busy;
+static struct mmu_notifier mmu_notifier;
+
+static int mmn_clear_young(struct mmu_notifier *mn, unsigned long address)
+{
+	unsigned long vaddr;
+	unsigned seq;
+	struct mm_struct *mm = mn->mm;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *ptep, pte;
+
+	do {
+		seq = read_seqcount_begin(&rmap_seq);
+		vaddr = rmap_find(address);
+	} while (read_seqcount_retry(&rmap_seq, seq));
+
+	if (vaddr == 0)
+		return 0;
+
+	printk("mmn_clear_young@vaddr=%lx sourced from %lx\n", vaddr, address);
+
+	spin_lock(&mmn_lock);
+        pgd = pgd_offset(mm, vaddr);
+        pud = pud_offset(pgd, vaddr);
+	if (pud) {
+		pmd = pmd_offset(pud, vaddr);
+		if (pmd) {
+			ptep = pte_offset_map(pmd, vaddr);
+			if (ptep) {
+				pte = *ptep;
+				if (!pte_present(pte)) {
+					/* x86 specific, don't have a vma */
+					ptep_get_and_clear(mm, vaddr, ptep);
+					__flush_tlb_one(vaddr);
+				}
+				pte_unmap(ptep);
+			}
+		}
+	}
+	__rmap_del(address);
+	spin_unlock(&mmn_lock);
+
+        return 1;
+}
+
+static void mmn_unmap(struct mmu_notifier *mn, unsigned long address)
+{
+	mmn_clear_young(mn, address);
+}
+
+static void mmn_release(struct mmu_notifier *mn)
+{
+	mmu_notifier_busy = 0;
+}
+
+static struct mmu_notifier_operations mmn_ops = {
+	.clear_young = mmn_clear_young,
+	.unmap = mmn_unmap,
+	.release = mmn_release,
+};
+
+static int mmn_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	int busy;
+
+	if ((vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE)
+		return -EINVAL;
+
+	spin_lock(&mmn_lock);
+	busy = mmu_notifier_busy;
+	if (!busy)
+		mmu_notifier_busy = 1;
+	spin_unlock(&mmn_lock);
+	if (busy)
+		return -EBUSY;
+
+	vma->vm_flags |= VM_PFNMAP;
+	vma->vm_ops = &mmn_vm_ops;
+
+	mmu_notifier_init(&mmu_notifier, &mmn_ops, current->mm);
+	mmu_notifier_register(&mmu_notifier);
+
+	return 0;
+}
+
+static const struct file_operations mmn_fops =
+{
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.mmap		= mmn_mmap,
+};
+
+static struct miscdevice mmn_miscdev =
+{
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "mmn",
+	.fops	= &mmn_fops
+};
+
+static int __init mmn_init(void)
+{
+	if (misc_register(&mmn_miscdev)) {
+		printk(KERN_ERR "mmn: unable to register device\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static void __exit mmn_exit(void)
+{
+	misc_deregister(&mmn_miscdev);
+}
+
+MODULE_DESCRIPTION("mmu_notifier skeleton driver");
+MODULE_LICENSE("GPL");
+
+module_init(mmn_init);
+module_exit(mmn_exit);
+
Index: linux-2.6/drivers/char/Kconfig
===================================================================
--- linux-2.6.orig/drivers/char/Kconfig
+++ linux-2.6/drivers/char/Kconfig
@@ -4,6 +4,10 @@
 
 menu "Character devices"
 
+config MMU_NOTIFIER_SKEL
+	tristate "MMU Notifier skeleton driver"
+	default n
+
 config VT
 	bool "Virtual terminal" if EMBEDDED
 	depends on !S390
Index: linux-2.6/drivers/char/Makefile
===================================================================
--- linux-2.6.orig/drivers/char/Makefile
+++ linux-2.6/drivers/char/Makefile
@@ -97,6 +97,7 @@ obj-$(CONFIG_CS5535_GPIO)	+= cs5535_gpio
 obj-$(CONFIG_GPIO_VR41XX)	+= vr41xx_giu.o
 obj-$(CONFIG_GPIO_TB0219)	+= tb0219.o
 obj-$(CONFIG_TELCLOCK)		+= tlclk.o
+obj-$(CONFIG_MMU_NOTIFIER_SKEL) += mmu_notifier_skel.o
 
 obj-$(CONFIG_MWAVE)		+= mwave/
 obj-$(CONFIG_AGP)		+= agp/
--
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[patch] my mmu notifiers, Nick Piggin, (Tue Feb 19, 1:43 am)
[patch] my mmu notifier sample driver, Nick Piggin, (Tue Feb 19, 1:44 am)
Re: [patch] my mmu notifiers, Robin Holt, (Tue Feb 19, 4:59 am)
Re: [patch] my mmu notifiers, Andrea Arcangeli, (Tue Feb 19, 6:58 am)
Re: [patch] my mmu notifiers, Jack Steiner, (Tue Feb 19, 7:27 am)
Re: [patch] my mmu notifiers, Nick Piggin, (Tue Feb 19, 3:59 pm)
Re: [patch] my mmu notifiers, Nick Piggin, (Tue Feb 19, 4:04 pm)
Re: [patch] my mmu notifiers, Nick Piggin, (Tue Feb 19, 4:11 pm)
Re: [patch] my mmu notifiers, Jack Steiner, (Tue Feb 19, 4:40 pm)
Re: [patch] my mmu notifiers, Andrea Arcangeli, (Tue Feb 19, 5:46 pm)
Re: [patch] my mmu notifiers, Andrea Arcangeli, (Tue Feb 19, 5:52 pm)
Re: [patch] my mmu notifiers, Andrea Arcangeli, (Tue Feb 19, 6:09 pm)
Re: [patch] my mmu notifiers, Robin Holt, (Tue Feb 19, 7:46 pm)
Re: [patch] my mmu notifiers, Robin Holt, (Tue Feb 19, 7:49 pm)
[PATCH] mmu notifiers #v6, Andrea Arcangeli, (Wed Feb 20, 3:39 am)
[PATCH] KVM swapping (+ seqlock fix) with mmu notifiers #v6, Andrea Arcangeli, (Wed Feb 20, 3:45 am)
Re: [PATCH] mmu notifiers #v6, Robin Holt, (Wed Feb 20, 4:33 am)
Re: [PATCH] mmu notifiers #v6, Andrea Arcangeli, (Wed Feb 20, 5:03 am)
Re: [PATCH] mmu notifiers #v6, Robin Holt, (Wed Feb 20, 5:24 am)
Re: [PATCH] mmu notifiers #v6, Andrea Arcangeli, (Wed Feb 20, 5:32 am)
Re: [PATCH] mmu notifiers #v6, Robin Holt, (Wed Feb 20, 6:15 am)
Re: [PATCH] mmu notifiers #v6, Robin Holt, (Wed Feb 20, 7:41 am)
Re: [PATCH] mmu notifiers #v6, Andrea Arcangeli, (Wed Feb 20, 8:34 am)
Re: [PATCH] mmu notifiers #v6, Jack Steiner, (Wed Feb 20, 2:03 pm)
Re: [patch] my mmu notifiers, Nick Piggin, (Wed Feb 20, 9:42 pm)
Re: [patch] my mmu notifiers, Nick Piggin, (Wed Feb 20, 9:47 pm)
Re: [PATCH] mmu notifiers #v6, Nick Piggin, (Wed Feb 20, 9:54 pm)
Re: [PATCH] mmu notifiers #v6, Nick Piggin, (Wed Feb 20, 10:02 pm)
Re: [PATCH] mmu notifiers #v6, Andrea Arcangeli, (Thu Feb 21, 7:40 am)
Re: [PATCH] mmu notifiers #v6, Jack Steiner, (Thu Feb 21, 9:10 am)
Re: [patch] my mmu notifiers, Jack Steiner, (Fri Feb 22, 9:31 am)
[PATCH] mmu notifiers #v7, Andrea Arcangeli, (Wed Feb 27, 12:26 pm)
Re: [PATCH] mmu notifiers #v7, Peter Zijlstra, (Wed Feb 27, 1:04 pm)
[PATCH] KVM swapping with mmu notifiers #v7, Andrea Arcangeli, (Wed Feb 27, 3:06 pm)
Re: [patch] my mmu notifiers, Christoph Lameter, (Wed Feb 27, 3:50 pm)
Re: [patch] my mmu notifiers, Christoph Lameter, (Wed Feb 27, 3:55 pm)
Re: [patch] my mmu notifiers, Christoph Lameter, (Wed Feb 27, 3:56 pm)
Re: [PATCH] mmu notifiers #v7, Christoph Lameter, (Wed Feb 27, 4:06 pm)
Re: [kvm-devel] [PATCH] mmu notifiers #v7, Andrea Arcangeli, (Wed Feb 27, 4:43 pm)
Re: [kvm-devel] [PATCH] mmu notifiers #v7, Christoph Lameter, (Wed Feb 27, 5:08 pm)
Re: [kvm-devel] [PATCH] mmu notifiers #v7, Andrea Arcangeli, (Wed Feb 27, 5:21 pm)
Re: [kvm-devel] [PATCH] mmu notifiers #v7, Christoph Lameter, (Wed Feb 27, 5:24 pm)
Re: [PATCH] KVM swapping with mmu notifiers #v7, izik eidus, (Thu Feb 28, 1:42 am)
Re: [PATCH] mmu notifiers #v7, Christoph Lameter, (Thu Feb 28, 12:48 pm)
Re: [PATCH] mmu notifiers #v7, Andrea Arcangeli, (Thu Feb 28, 2:52 pm)
Re: [PATCH] mmu notifiers #v7, Christoph Lameter, (Thu Feb 28, 3:00 pm)
Re: [PATCH] mmu notifiers #v7, Christoph Lameter, (Thu Feb 28, 4:05 pm)
Re: [PATCH] mmu notifiers #v7, Jack Steiner, (Thu Feb 28, 4:17 pm)
Re: [PATCH] mmu notifiers #v7, Andrea Arcangeli, (Thu Feb 28, 5:24 pm)
Re: [PATCH] mmu notifiers #v7, Andrea Arcangeli, (Thu Feb 28, 5:40 pm)
Re: [PATCH] mmu notifiers #v7, Andrew Morton, (Thu Feb 28, 5:56 pm)
Re: [PATCH] mmu notifiers #v7, Christoph Lameter, (Thu Feb 28, 6:03 pm)
Re: [PATCH] mmu notifiers #v7, Christoph Lameter, (Thu Feb 28, 6:13 pm)
Re: [PATCH] mmu notifiers #v7, Andrea Arcangeli, (Fri Feb 29, 6:09 am)
Re: [PATCH] mmu notifiers #v7, Christoph Lameter, (Fri Feb 29, 12:46 pm)
[PATCH] mmu notifiers #v8, Andrea Arcangeli, (Sun Mar 2, 8:54 am)
Re: [PATCH] mmu notifiers #v8 + xpmem, Andrea Arcangeli, (Sun Mar 2, 9:03 am)
Re: [PATCH] mmu notifiers #v8 + xpmem, Peter Zijlstra, (Sun Mar 2, 9:23 am)
Re: [PATCH] mmu notifiers #v8, Nick Piggin, (Sun Mar 2, 8:29 pm)
Re: [PATCH] mmu notifiers #v8, Nick Piggin, (Sun Mar 2, 8:33 pm)
Re: [PATCH] mmu notifiers #v8, Nick Piggin, (Sun Mar 2, 8:34 pm)
Re: [PATCH] mmu notifiers #v8, Nick Piggin, (Sun Mar 2, 8:39 pm)
Re: [PATCH] mmu notifiers #v8, Andrea Arcangeli, (Mon Mar 3, 5:51 am)
Re: [PATCH] mmu notifiers #v8, Nick Piggin, (Mon Mar 3, 6:10 am)
Re: [PATCH] mmu notifiers #v8, Andrea Arcangeli, (Mon Mar 3, 6:24 am)
Re: [PATCH] mmu notifiers #v8, Jack Steiner, (Mon Mar 3, 8:18 am)
Re: [PATCH] mmu notifiers #v8, Nick Piggin, (Mon Mar 3, 9:59 am)
Re: [PATCH] mmu notifiers #v8, Jack Steiner, (Mon Mar 3, 11:06 am)
Re: [PATCH] mmu notifiers #v8, Avi Kivity, (Mon Mar 3, 11:09 am)
Re: [PATCH] mmu notifiers #v8, Jack Steiner, (Mon Mar 3, 11:23 am)
Re: [PATCH] mmu notifiers #v8, Nick Piggin, (Mon Mar 3, 11:45 am)
Re: [PATCH] mmu notifiers #v8, Christoph Lameter, (Mon Mar 3, 12:01 pm)
Re: [PATCH] mmu notifiers #v8, Christoph Lameter, (Mon Mar 3, 12:02 pm)
Re: [PATCH] mmu notifiers #v8, Christoph Lameter, (Mon Mar 3, 12:03 pm)
Re: [PATCH] mmu notifiers #v8, Christoph Lameter, (Mon Mar 3, 12:04 pm)
Re: [PATCH] mmu notifiers #v8, Jack Steiner, (Mon Mar 3, 12:15 pm)
Re: [PATCH] mmu notifiers #v8, Andrea Arcangeli, (Mon Mar 3, 2:15 pm)
[PATCH] mmu notifiers #v9, Andrea Arcangeli, (Mon Mar 3, 2:37 pm)
[PATCH] KVM swapping with mmu notifiers #v9, Andrea Arcangeli, (Mon Mar 3, 3:05 pm)
Re: [PATCH] KVM swapping with mmu notifiers #v9, izik eidus, (Mon Mar 3, 5:44 pm)
[RFC] Notifier for Externally Mapped Memory (EMM), Christoph Lameter, (Tue Mar 4, 12:31 am)
[Early draft] Conversion of i_mmap_lock to semaphore, Christoph Lameter, (Tue Mar 4, 12:34 am)
Re: [PATCH] mmu notifiers #v8, Peter Zijlstra, (Tue Mar 4, 3:35 am)
Re: [PATCH] KVM swapping with mmu notifiers #v9, Andrea Arcangeli, (Tue Mar 4, 6:21 am)
Re: [RFC] Notifier for Externally Mapped Memory (EMM), Andrea Arcangeli, (Tue Mar 4, 6:30 am)
Re: [PATCH] mmu notifiers #v8, Jack Steiner, (Tue Mar 4, 7:44 am)
Re: [RFC] Notifier for Externally Mapped Memory (EMM), Christoph Lameter, (Tue Mar 4, 12:00 pm)
Re: [RFC] Notifier for Externally Mapped Memory (EMM), Andrea Arcangeli, (Tue Mar 4, 3:20 pm)
Re: [RFC] Notifier for Externally Mapped Memory (EMM), Christoph Lameter, (Tue Mar 4, 3:35 pm)
Re: [RFC] Notifier for Externally Mapped Memory (EMM), Peter Zijlstra, (Tue Mar 4, 3:42 pm)
Re: [RFC] Notifier for Externally Mapped Memory (EMM), Christoph Lameter, (Tue Mar 4, 4:14 pm)
Re: [RFC] Notifier for Externally Mapped Memory (EMM), Peter Zijlstra, (Tue Mar 4, 4:25 pm)
Re: [RFC] Notifier for Externally Mapped Memory (EMM), Peter Zijlstra, (Tue Mar 4, 4:30 pm)
Re: [PATCH] mmu notifiers #v8, Nick Piggin, (Tue Mar 4, 5:37 pm)
Re: [PATCH] mmu notifiers #v8, Christoph Lameter, (Wed Mar 5, 11:48 am)
Re: [PATCH] mmu notifiers #v8, Nick Piggin, (Wed Mar 5, 7:59 pm)
[PATCH] 4/4 i_mmap_lock spinlock2rwsem (#v9 was 1/4), Andrea Arcangeli, (Fri Mar 7, 8:52 am)
Re: [PATCH] 2/4 move all invalidate_page outside of PT loc ..., Christoph Lameter, (Fri Mar 7, 12:54 pm)
Re: [PATCH] 4/4 i_mmap_lock spinlock2rwsem (#v9 was 1/4), Christoph Lameter, (Fri Mar 7, 1:03 pm)
Re: [PATCH] 4/4 i_mmap_lock spinlock2rwsem (#v9 was 1/4), Christoph Lameter, (Wed Mar 19, 2:27 pm)