lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 19 Mar 2010 17:02:04 +0800
From:	<graff.yang@...il.com>
To:	dhowells@...hat.com, tj@...nel.org, linux-kernel@...r.kernel.org
CC:	akpm@...ux-foundation.org, uclinux-dist-devel@...ckfin.uclinux.org,
	Graff Yang <graff.yang@...il.com>
Subject: [PATCH] mm/nommu.c:Dynamic alloc/free percpu area for nommu

From: Graff Yang <graff.yang@...il.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@...il.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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ