exec32.c 2.17 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6
/*
 * Support for 32-bit Linux for S390 ELF binaries.
 *
 * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
 * Author(s): Gerhard Tonn (ton@de.ibm.com)
 *
Andrew Morton's avatar
Andrew Morton committed
7
 * Separated from binfmt_elf32.c to reduce exports for module enablement.
Linus Torvalds's avatar
Linus Torvalds committed
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 */

#include <linux/config.h>
#include <linux/slab.h>
#include <linux/file.h>
#include <linux/mman.h>
#include <linux/a.out.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
#include <linux/spinlock.h>
23
#include <linux/binfmts.h>
Linus Torvalds's avatar
Linus Torvalds committed
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
#define __NO_VERSION__
#include <linux/module.h>

#include <asm/uaccess.h>
#include <asm/pgalloc.h>
#include <asm/mmu_context.h>

#ifdef CONFIG_KMOD
#include <linux/kmod.h>
#endif


extern void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long address);

#undef STACK_TOP
#define STACK_TOP TASK31_SIZE

int setup_arg_pages32(struct linux_binprm *bprm)
{
	unsigned long stack_base;
	struct vm_area_struct *mpnt;
45
	struct mm_struct *mm = current->mm;
Linus Torvalds's avatar
Linus Torvalds committed
46 47 48
	int i;

	stack_base = STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE;
49
	mm->arg_start = bprm->p + stack_base;
Linus Torvalds's avatar
Linus Torvalds committed
50 51 52 53 54 55 56 57 58 59

	bprm->p += stack_base;
	if (bprm->loader)
		bprm->loader += stack_base;
	bprm->exec += stack_base;

	mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
	if (!mpnt) 
		return -ENOMEM; 
	
60 61 62 63 64 65
	if (!vm_enough_memory((STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
		kmem_cache_free(vm_area_cachep, mpnt);
		return -ENOMEM;
	}

	down_write(&mm->mmap_sem);
Linus Torvalds's avatar
Linus Torvalds committed
66
	{
67
		mpnt->vm_mm = mm;
Linus Torvalds's avatar
Linus Torvalds committed
68 69 70 71 72 73 74
		mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
		mpnt->vm_end = STACK_TOP;
		mpnt->vm_page_prot = PAGE_COPY;
		mpnt->vm_flags = VM_STACK_FLAGS;
		mpnt->vm_ops = NULL;
		mpnt->vm_pgoff = 0;
		mpnt->vm_file = NULL;
75
		INIT_LIST_HEAD(&mpnt->shared);
Linus Torvalds's avatar
Linus Torvalds committed
76
		mpnt->vm_private_data = (void *) 0;
77 78
		insert_vm_struct(mm, mpnt);
		mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
Linus Torvalds's avatar
Linus Torvalds committed
79 80 81 82 83 84 85 86 87 88
	} 

	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
		struct page *page = bprm->page[i];
		if (page) {
			bprm->page[i] = NULL;
			put_dirty_page(current,page,stack_base);
		}
		stack_base += PAGE_SIZE;
	}
89
	up_write(&mm->mmap_sem);
Linus Torvalds's avatar
Linus Torvalds committed
90 91 92 93
	
	return 0;
}

Linus Torvalds's avatar
Linus Torvalds committed
94
EXPORT_SYMBOL(setup_arg_pages32);