linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: <graff.yang@gmail.com>
To: dhowells@redhat.com, tj@kernel.org, linux-kernel@vger.kernel.org
Cc: akpm@linux-foundation.org,
	uclinux-dist-devel@blackfin.uclinux.org,
	Graff Yang <graff.yang@gmail.com>
Subject: [PATCH] mm/nommu.c:Dynamic alloc/free percpu area for nommu
Date: Fri, 19 Mar 2010 17:02:04 +0800	[thread overview]
Message-ID: <1268989324-7575-1-git-send-email-graff.yang@gmail.com> (raw)

From: Graff Yang <graff.yang@gmail.com>

This patch supports dynamic alloc/free percpu area for nommu arch like
blackfin.
It allocates contiguous pages in funtion pcpu_get_vm_areas() instead of
getting none contiguous pages then vmap it in mmu arch.
As we can not get the real page structure through vmalloc_to_page(), so
it also modified the nommu version vmalloc_to_page()/vmalloc_to_pfn().

Signed-off-by: Graff Yang <graff.yang@gmail.com>
---
 mm/nommu.c |  114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 112 insertions(+), 2 deletions(-)

diff --git a/mm/nommu.c b/mm/nommu.c
index 605ace8..98bbdf4 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -255,13 +255,15 @@ EXPORT_SYMBOL(vmalloc_user);
 
 struct page *vmalloc_to_page(const void *addr)
 {
-	return virt_to_page(addr);
+	return (struct page *)
+			(virt_to_page(addr)->index) ? : virt_to_page(addr);
 }
 EXPORT_SYMBOL(vmalloc_to_page);
 
 unsigned long vmalloc_to_pfn(const void *addr)
 {
-	return page_to_pfn(virt_to_page(addr));
+	return page_to_pfn((struct page *)
+			(virt_to_page(addr)->index) ? : virt_to_page(addr));
 }
 EXPORT_SYMBOL(vmalloc_to_pfn);
 
@@ -2000,3 +2002,111 @@ int nommu_shrink_inode_mappings(struct inode *inode, size_t size,
 	up_write(&nommu_region_sem);
 	return 0;
 }
+
+#ifdef CONFIG_SMP
+int map_kernel_range_noflush(unsigned long addr, unsigned long size,
+					pgprot_t prot, struct page **pages)
+{
+	int i, nr_page = size >> PAGE_SHIFT;
+	for (i = 0; i < nr_page; i++, addr += PAGE_SIZE)
+		virt_to_page(addr)->index = (pgoff_t)pages[i];
+	return size >> PAGE_SHIFT;
+}
+
+void unmap_kernel_range_noflush(unsigned long addr, unsigned long size)
+{
+	int i, nr_page = size >> PAGE_SHIFT;
+	for (i = 0; i < nr_page; i++, addr += PAGE_SIZE)
+		virt_to_page(addr)->index = 0;
+}
+
+struct vm_struct **pcpu_get_vm_areas(const unsigned long *offsets,
+					const size_t *sizes, int nr_vms,
+						size_t align, gfp_t gfp_mask)
+{
+	struct vm_struct **vms;
+	int area, area2, first_area, last_area;
+	unsigned long start, end, first_start, last_end;
+	void *base;
+
+	gfp_mask &= GFP_RECLAIM_MASK;
+
+	/* verify parameters and allocate data structures */
+	BUG_ON(align & ~PAGE_MASK || !is_power_of_2(align));
+	first_area = last_area = 0;
+	for (area = 0; area < nr_vms; area++) {
+		start = offsets[area];
+		end = start + sizes[area];
+
+		/* is everything aligned properly? */
+		BUG_ON(!IS_ALIGNED(offsets[area], align));
+		BUG_ON(!IS_ALIGNED(sizes[area], align));
+
+		if (end < offsets[first_area])
+			first_area = area;
+
+		/* detect the area with the highest address */
+		if (start > offsets[last_area])
+			last_area = area;
+
+		for (area2 = 0; area2 < nr_vms; area2++) {
+			unsigned long start2 = offsets[area2];
+			unsigned long end2 = start2 + sizes[area2];
+
+			if (area2 == area)
+				continue;
+
+			BUG_ON(start2 >= start && start2 < end);
+			BUG_ON(end2 <= end && end2 > start);
+		}
+	}
+	first_start = offsets[first_area];
+	last_end = offsets[last_area] + sizes[last_area];
+
+	vms = kzalloc(sizeof(vms[0]) * nr_vms, gfp_mask);
+	if (!vms)
+		goto err_free;
+
+	for (area = 0; area < nr_vms; area++) {
+		vms[area] = kzalloc(sizeof(struct vm_struct), gfp_mask);
+		if (!vms[area])
+			goto err_free;
+	}
+
+	base = kmalloc(last_end - first_start, GFP_KERNEL | __GFP_COMP);
+	if (!base)
+		goto err_free;
+
+	for (area = 0; area < nr_vms; area++) {
+		struct vm_struct *vm = vms[area];
+
+		vm->flags = VM_ALLOC;
+		vm->addr = base + offsets[area];
+		vm->size = sizes[area];
+		vm->caller = NULL;
+	}
+	return vms;
+
+err_free:
+	for (area = 0; area < nr_vms; area++) {
+		if (vms)
+			kfree(vms[area]);
+	}
+	kfree(vms);
+	return NULL;
+}
+
+void pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms)
+{
+	int area;
+	void *vaddr = (void *)(-1UL);
+	for (area = 0; area < nr_vms; area++)
+		if (vms[area]) {
+			if (vms[area]->addr < vaddr)
+				vaddr = vms[area]->addr;
+			kfree(vms[area]);
+		}
+	kfree(vms);
+	vfree(vaddr);
+}
+#endif
-- 
1.6.4.4


             reply	other threads:[~2010-03-19  9:03 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-03-19  9:02 graff.yang [this message]
2010-03-20  4:06 ` [PATCH] mm/nommu.c:Dynamic alloc/free percpu area for nommu Tejun Heo
2010-03-22  2:33   ` graff yang
2010-04-01 10:20     ` Tejun Heo
2010-04-06  9:28       ` Sonic Zhang
2010-04-08  2:43         ` Tejun Heo
2010-04-08  9:40           ` Sonic Zhang
2010-04-08 23:33             ` Tejun Heo
2010-03-22  4:14   ` [Uclinux-dist-devel] [PATCH] mm/nommu.c:Dynamic alloc/freepercpu " Zhang, Sonic
2010-03-22 11:50 ` [PATCH] mm/nommu.c:Dynamic alloc/free percpu " David Howells
2010-03-23  2:33   ` graff yang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1268989324-7575-1-git-send-email-graff.yang@gmail.com \
    --to=graff.yang@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=dhowells@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=tj@kernel.org \
    --cc=uclinux-dist-devel@blackfin.uclinux.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).