patch-2.4.21 linux-2.4.21/arch/x86_64/mm/modutil.c
Next file: linux-2.4.21/arch/x86_64/mm/numa.c
Previous file: linux-2.4.21/arch/x86_64/mm/k8topology.c
Back to the patch index
Back to the overall index
- Lines: 101
- Date:
2003-06-13 07:51:32.000000000 -0700
- Orig file:
linux-2.4.20/arch/x86_64/mm/modutil.c
- Orig date:
2002-11-28 15:53:12.000000000 -0800
diff -urN linux-2.4.20/arch/x86_64/mm/modutil.c linux-2.4.21/arch/x86_64/mm/modutil.c
@@ -10,11 +10,23 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
+#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/system.h>
+#include <asm/proto.h>
-static struct vm_struct * modvmlist = NULL;
+extern char _text[], _end[];
+
+/* Kernel mapping to make the kernel alias visible to
+ /proc/kcore and /dev/mem
+
+ RED-PEN may want vsyscall mappings too
+ */
+
+static struct vm_struct kernel_mapping = {
+ .addr = (void *)KERNEL_TEXT_START,
+};
void module_unmap (void * addr)
{
@@ -26,9 +38,11 @@
printk("Trying to unmap module with bad address (%p)\n", addr);
return;
}
- for (p = &modvmlist ; (tmp = *p) ; p = &tmp->next) {
+ write_lock(&vmlist_lock);
+ for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
if (tmp->addr == addr) {
*p = tmp->next;
+ write_unlock(&vmlist_lock);
vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
kfree(tmp);
return;
@@ -45,24 +59,55 @@
size = PAGE_ALIGN(size);
if (!size || size > MODULES_LEN) return NULL;
+ area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
+ if (!area) return NULL;
+
+ memset(area, 0, sizeof(struct vm_struct));
+
+ size = round_up(size, PAGE_SIZE);
+
addr = (void *) MODULES_VADDR;
- for (p = &modvmlist; (tmp = *p) ; p = &tmp->next) {
+ write_lock(&vmlist_lock);
+ for (p = &vmlist; (tmp = *p) ; p = &tmp->next) {
+ void *next;
if (size + (unsigned long) addr < (unsigned long) tmp->addr)
break;
- addr = (void *) (tmp->size + (unsigned long) tmp->addr);
+ next = (void *) (tmp->size + (unsigned long) tmp->addr);
+ if (next > addr)
+ addr = next;
+ }
+ if ((unsigned long) addr + size >= MODULES_END) {
+ write_unlock(&vmlist_lock);
+ kfree(area);
+ return NULL;
}
- if ((unsigned long) addr + size >= MODULES_END) return NULL;
- area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
- if (!area) return NULL;
- area->size = size + PAGE_SIZE;
+ area->size = size;
area->addr = addr;
area->next = *p;
*p = area;
+ write_unlock(&vmlist_lock);
- if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size, GFP_KERNEL, PAGE_KERNEL)) {
+ if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size, GFP_KERNEL, PAGE_KERNEL_EXECUTABLE)) {
module_unmap(addr);
return NULL;
}
return addr;
}
+
+static int __init mod_vmlist_init(void)
+{
+ struct vm_struct *vm, **base;
+ write_lock(&vmlist_lock);
+ for (base = &vmlist, vm = *base; vm; base = &vm->next, vm = *base) {
+ if (vm->addr > (void *)KERNEL_TEXT_START)
+ break;
+ }
+ kernel_mapping.size = _end - _text;
+ kernel_mapping.next = vm;
+ *base = &kernel_mapping;
+ write_unlock(&vmlist_lock);
+ return 0;
+}
+
+__initcall(mod_vmlist_init);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)