コード例 #1
0
ファイル: event.c プロジェクト: HackLinux/ucorebook_code
int
ipc_event_recv(int *pid_store, int *event_store, unsigned int timeout) {
    if (event_store == NULL) {
        return -E_INVAL;
    }

    struct mm_struct *mm = current->mm;
    if (pid_store != NULL) {
        if (!user_mem_check(mm, (uintptr_t)pid_store, sizeof(int), 1)) {
            return -E_INVAL;
        }
    }
    if (!user_mem_check(mm, (uintptr_t)event_store, sizeof(int), 1)) {
        return -E_INVAL;
    }

    unsigned long saved_ticks;
    timer_t __timer, *timer = ipc_timer_init(timeout, &saved_ticks, &__timer);

    int pid, event, ret;
    if ((ret = recv_event(&pid, &event, timer)) == 0) {
        lock_mm(mm);
        {
            ret = -E_INVAL;
            if (pid_store == NULL || copy_to_user(mm, pid_store, &pid, sizeof(int))) {
                if (copy_to_user(mm, event_store, &event, sizeof(int))) {
                    ret = 0;
                }
            }
        }
        unlock_mm(mm);
        return ret;
    }
    return ipc_check_timeout(timeout, saved_ticks);
}
コード例 #2
0
ファイル: sem.c プロジェクト: TySag/project
int ipc_sem_get_value(sem_t sem_id, int *value_store)
{
	assert(current->sem_queue != NULL);
	if (value_store == NULL) {
		return -E_INVAL;
	}

	struct mm_struct *mm = current->mm;
	if (!user_mem_check(mm, (uintptr_t) value_store, sizeof(int), 1)) {
		return -E_INVAL;
	}

	sem_undo_t *semu;
	sem_queue_t *sem_queue = current->sem_queue;
	down(&(sem_queue->sem));
	semu = semu_list_search(&(sem_queue->semu_list), sem_id);
	up(&(sem_queue->sem));

	int ret = -E_INVAL;
	if (semu != NULL) {
		int value = semu->sem->value;
		lock_mm(mm);
		{
			if (copy_to_user(mm, value_store, &value, sizeof(int))) {
				ret = 0;
			}
		}
		unlock_mm(mm);
	}
	return ret;
}
コード例 #3
0
ファイル: sysfile.c プロジェクト: zhaohuakai/ucore_plus
int sysfile_write(int fd, void *base, size_t len)
{
	int ret = 0;
	struct mm_struct *mm = pls_read(current)->mm;
	if (len == 0) {
		return 0;
	}
	if (!file_testfd(fd, 0, 1)) {
		return -E_INVAL;
	}
	/* for linux inode */
	if (__is_linux_devfile(fd)) {
		/* use 8byte int, in case of 64bit off_t
		 * config in linux kernel */
		size_t alen = 0;
		ret = linux_devfile_write(fd, base, len, &alen);
		if (ret)
			return ret;
		return alen;
	}
	void *buffer;
	if ((buffer = kmalloc(IOBUF_SIZE)) == NULL) {
		return -E_NO_MEM;
	}

	size_t copied = 0, alen;
	while (len != 0) {
		if ((alen = IOBUF_SIZE) > len) {
			alen = len;
		}
		lock_mm(mm);
		{
			if (!copy_from_user(mm, buffer, base, alen, 0)) {
				ret = -E_INVAL;
			}
		}
		unlock_mm(mm);
		if (ret == 0) {
			ret = file_write(fd, buffer, alen, &alen);
			if (alen != 0) {
				assert(len >= alen);
				base += alen, len -= alen, copied += alen;
			}
		}
		if (ret != 0 || alen == 0) {
			goto out;
		}
	}

out:
	kfree(buffer);
	if (copied != 0) {
		return copied;
	}
	return ret;
}
コード例 #4
0
ファイル: uaccess.c プロジェクト: chyyuu/ucore-arch-arm
unsigned long __ucore_copy_from_user(void *to, const void *from, unsigned long n)
{
  int ret = 0;
  struct mm_struct *mm = pls_read(current)->mm;
  lock_mm(mm);
  ret = copy_from_user(mm, to, from, n, 0);
  unlock_mm(mm);
  if(ret)
    return 0;
  return n;
}
コード例 #5
0
ファイル: proc.c プロジェクト: chyyuu/ucore-arch-arm
// copy_mm - process "proc" duplicate OR share process "current"'s mm according clone_flags
//         - if clone_flags & CLONE_VM, then "share" ; else "duplicate"
static int
copy_mm(uint32_t clone_flags, struct proc_struct *proc) {
    struct mm_struct *mm, *oldmm = current->mm;

    /* current is a kernel thread */
    if (oldmm == NULL) {
        return 0;
    }
    if (clone_flags & CLONE_VM) {
        mm = oldmm;
        goto good_mm;
    }

    int ret = -E_NO_MEM;
    if ((mm = mm_create()) == NULL) {
        goto bad_mm;
    }
    if (setup_pgdir(mm) != 0) {
        goto bad_pgdir_cleanup_mm;
    }

    lock_mm(oldmm);
    {
        ret = dup_mmap(mm, oldmm);
    }
    unlock_mm(oldmm);

    if (ret != 0) {
        goto bad_dup_cleanup_mmap;
    }

good_mm:
    if (mm != oldmm) {
        mm->brk_start = oldmm->brk_start;
        mm->brk = oldmm->brk;
        bool intr_flag;
        local_intr_save(intr_flag);
        {
            list_add(&(proc_mm_list), &(mm->proc_mm_link));
        }
        local_intr_restore(intr_flag);
    }
    mm_count_inc(mm);
    proc->mm = mm;
	set_pgdir (proc, mm->pgdir);
    return 0;
bad_dup_cleanup_mmap:
    exit_mmap(mm);
    put_pgdir(mm);
bad_pgdir_cleanup_mm:
    mm_destroy(mm);
bad_mm:
    return ret;
}
コード例 #6
0
ファイル: sysfile.c プロジェクト: zhaohuakai/ucore_plus
int sysfile_read(int fd, void *base, size_t len)
{
	int ret = 0;
	struct mm_struct *mm = pls_read(current)->mm;
	if (len == 0) {
		return 0;
	}
	if (!file_testfd(fd, 1, 0)) {
		return -E_INVAL;
	}
	/* for linux inode */
	if (__is_linux_devfile(fd)) {
		size_t alen = 0;
		ret = linux_devfile_read(fd, base, len, &alen);
		if (ret)
			return ret;
		return alen;
	}
	void *buffer;
	if ((buffer = kmalloc(IOBUF_SIZE)) == NULL) {
		return -E_NO_MEM;
	}

	size_t copied = 0, alen;
	while (len != 0) {
		if ((alen = IOBUF_SIZE) > len) {
			alen = len;
		}
		ret = file_read(fd, buffer, alen, &alen);
		if (alen != 0) {
			lock_mm(mm);
			{
				if (copy_to_user(mm, base, buffer, alen)) {
					assert(len >= alen);
					base += alen, len -= alen, copied +=
					    alen;
				} else if (ret == 0) {
					ret = -E_INVAL;
				}
			}
			unlock_mm(mm);
		}
		if (ret != 0 || alen == 0) {
			goto out;
		}
	}

out:
	kfree(buffer);
	if (copied != 0) {
		return copied;
	}
	return ret;
}
コード例 #7
0
ファイル: mod.c プロジェクト: chyyuu/ucore-driver
int do_cleanup_module(const char __user * name_user)
{
	struct module *mod;
	char name[MODULE_NAME_LEN];
	int ret = 0, forced = 0;

	struct mm_struct *mm = current->mm;
	lock_mm(mm);

	int length = strlen(name_user);
	if (!copy_from_user(mm, name, name_user, length, 1)) {
		unlock_mm(mm);
		return -E_INVAL;
	}
	unlock_mm(mm);
	name[length] = '\0';

	mod = find_module(name);

	if (!mod) {
		ret = -E_NOENT;
		goto out;
		//return -E_NOENT;
	}
	if (!list_empty(&mod->modules_which_use_me)) {
		ret = -E_INVAL;
		goto out;
	}

	if (mod->state != MODULE_STATE_LIVE) {
		kprintf("do_cleanup_module: %s already dying\n", mod->name);
		ret = -E_BUSY;
	}

	if (mod->init && !mod->exit) {
		kprintf("do_cleanup_module: %s can't be removed\n", mod->name);
		ret = -E_BUSY;
	}

	mod->waiter = current;
	mod->state = MODULE_STATE_GOING;

	if (mod->exit != NULL)
		mod->exit();

	strncpy(last_unloaded_module, mod->name, strlen(mod->name));
	free_module(mod);
	return ret;

out:
	return ret;

}
コード例 #8
0
ファイル: proc.c プロジェクト: xuchiheng/ucore_plus
// do_shmem - create a share memory with addr, len, flags(VM_READ/M_WRITE/VM_STACK)
int do_shmem(uintptr_t * addr_store, size_t len, uint32_t mmap_flags)
{
	struct mm_struct *mm = current->mm;
	if (mm == NULL) {
		panic("kernel thread call mmap!!.\n");
	}
	if (addr_store == NULL || len == 0) {
		return -E_INVAL;
	}

	int ret = -E_INVAL;

	uintptr_t addr;

	lock_mm(mm);
	if (!copy_from_user(mm, &addr, addr_store, sizeof(uintptr_t), 1)) {
		goto out_unlock;
	}

	uintptr_t start = ROUNDDOWN(addr, PGSIZE), end =
	    ROUNDUP(addr + len, PGSIZE);
	addr = start, len = end - start;

	uint32_t vm_flags = VM_READ;
	if (mmap_flags & MMAP_WRITE)
		vm_flags |= VM_WRITE;
	if (mmap_flags & MMAP_STACK)
		vm_flags |= VM_STACK;

	ret = -E_NO_MEM;
	if (addr == 0) {
		if ((addr = get_unmapped_area(mm, len)) == 0) {
			goto out_unlock;
		}
	}
	struct shmem_struct *shmem;
	if ((shmem = shmem_create(len)) == NULL) {
		goto out_unlock;
	}
	if ((ret = mm_map_shmem(mm, addr, vm_flags, shmem, NULL)) != 0) {
		assert(shmem_ref(shmem) == 0);
		shmem_destroy(shmem);
		goto out_unlock;
	}
	copy_to_user(mm, addr_store, &addr, sizeof(uintptr_t));
out_unlock:
	unlock_mm(mm);
	return ret;
}
コード例 #9
0
ファイル: sysfile.c プロジェクト: wwffcc/spoc_discussions
/* sysfile_read - read file */
int
sysfile_read(int fd, void *base, size_t len) {
    cprintf("sysfile_read fd = %d\n",fd);

    struct mm_struct *mm = current->mm;
    if (len == 0) {
        return 0;
    }
    if (!file_testfd(fd, 1, 0)) {
        return -E_INVAL;
    }
    void *buffer;
    if ((buffer = kmalloc(IOBUF_SIZE)) == NULL) {
        return -E_NO_MEM;
    }

    int ret = 0;
    size_t copied = 0, alen;
    while (len != 0) {
        if ((alen = IOBUF_SIZE) > len) {
            alen = len;
        }
        ret = file_read(fd, buffer, alen, &alen);
        if (alen != 0) {
            lock_mm(mm);
            {
                if (copy_to_user(mm, base, buffer, alen)) {
                    assert(len >= alen);
                    base += alen, len -= alen, copied += alen;
                }
                else if (ret == 0) {
                    ret = -E_INVAL;
                }
            }
            unlock_mm(mm);
        }
        if (ret != 0 || alen == 0) {
            goto out;
        }
    }

out:
    kfree(buffer);
    if (copied != 0) {
        return copied;
    }
    return ret;
}
コード例 #10
0
ファイル: proc.c プロジェクト: chyyuu/ucore-arch-arm
// do_munmap - delete vma with addr & len
int
do_munmap(uintptr_t addr, size_t len) {
    struct mm_struct *mm = current->mm;
    if (mm == NULL) {
        panic("kernel thread call munmap!!.\n");
    }
    if (len == 0) {
        return -E_INVAL;
    }
    int ret;
    lock_mm(mm);
    {
        ret = mm_unmap(mm, addr, len);
    }
    unlock_mm(mm);
    return ret;
}
コード例 #11
0
ファイル: sysfile.c プロジェクト: spinlock/ucore
int
sysfile_write(int fd, void *base, size_t len) {
    struct mm_struct *mm = current->mm;
    if (len == 0) {
        return 0;
    }
    if (!file_testfd(fd, 0, 1)) {
        return -E_INVAL;
    }
    void *buffer;
    if ((buffer = kmalloc(IOBUF_SIZE)) == NULL) {
        return -E_NO_MEM;
    }

    int ret = 0;
    size_t copied = 0, alen;
    while (len != 0) {
        if ((alen = IOBUF_SIZE) > len) {
            alen = len;
        }
        lock_mm(mm);
        {
            if (!copy_from_user(mm, buffer, base, alen, 0)) {
                ret = -E_INVAL;
            }
        }
        unlock_mm(mm);
        if (ret == 0) {
            ret = file_write(fd, buffer, alen, &alen);
            if (alen != 0) {
                assert(len >= alen);
                base += alen, len -= alen, copied += alen;
            }
        }
        if (ret != 0 || alen == 0) {
            goto out;
        }
    }

out:
    kfree(buffer);
    if (copied != 0) {
        return copied;
    }
    return ret;
}
コード例 #12
0
ファイル: proc.c プロジェクト: chyyuu/ucore-arch-arm
// do_brk - adjust(increase/decrease) the size of process heap, align with page size
// NOTE: will change the process vma
int
do_brk(uintptr_t *brk_store) {
    struct mm_struct *mm = current->mm;
    if (mm == NULL) {
        panic("kernel thread call sys_brk!!.\n");
    }
    if (brk_store == NULL) {
        return -E_INVAL;
    }

    uintptr_t brk;

    lock_mm(mm);
    if (!copy_from_user(mm, &brk, brk_store, sizeof(uintptr_t), 1)) {
        unlock_mm(mm);
        return -E_INVAL;
    }

    if (brk < mm->brk_start) {
        goto out_unlock;
    }
    uintptr_t newbrk = ROUNDUP(brk, PGSIZE), oldbrk = mm->brk;
    assert(oldbrk % PGSIZE == 0);
    if (newbrk == oldbrk) {
        goto out_unlock;
    }
    if (newbrk < oldbrk) {
        if (mm_unmap(mm, newbrk, oldbrk - newbrk) != 0) {
            goto out_unlock;
        }
    }
    else {
        if (find_vma_intersection(mm, oldbrk, newbrk + PGSIZE) != NULL) {
            goto out_unlock;
        }
        if (mm_brk(mm, oldbrk, newbrk - oldbrk) != 0) {
            goto out_unlock;
        }
    }
    mm->brk = newbrk;
out_unlock:
	copy_to_user (mm, brk_store, &mm->brk, sizeof (uintptr_t));
    unlock_mm(mm);
    return 0;
}
コード例 #13
0
ファイル: sysfile.c プロジェクト: wwffcc/spoc_discussions
/* sysfile_get cwd - get current working directory */
int
sysfile_getcwd(char *buf, size_t len) {
    struct mm_struct *mm = current->mm;
    if (len == 0) {
        return -E_INVAL;
    }

    int ret = -E_INVAL;
    lock_mm(mm);
    {
        if (user_mem_check(mm, (uintptr_t)buf, len, 1)) {
            struct iobuf __iob, *iob = iobuf_init(&__iob, buf, len, 0);
            ret = vfs_getcwd(iob);
        }
    }
    unlock_mm(mm);
    return ret;
}
コード例 #14
0
ファイル: sysfile.c プロジェクト: wwffcc/spoc_discussions
/* sysfile_fstat - stat file */
int
sysfile_fstat(int fd, struct stat *__stat) {
    struct mm_struct *mm = current->mm;
    int ret;
    struct stat __local_stat, *stat = &__local_stat;
    if ((ret = file_fstat(fd, stat)) != 0) {
        return ret;
    }

    lock_mm(mm);
    {
        if (!copy_to_user(mm, __stat, stat, sizeof(struct stat))) {
            ret = -E_INVAL;
        }
    }
    unlock_mm(mm);
    return ret;
}
コード例 #15
0
ファイル: arch_signal.c プロジェクト: Aresthu/ucore_plus
// set user stack for signal handler, also set eip to handler
int __sig_setup_frame(int sign, struct sigaction *act, sigset_t oldset,
		      struct trapframe *tf)
{
	struct mm_struct *mm = current->mm;
	uintptr_t stack = current->signal_info.sas_ss_sp;
	if (stack == 0) {
		stack = tf->tf_esp;
	}
	struct sigframe *kframe = kmalloc(sizeof(struct sigframe));
	if (!kframe)
		return -E_NO_MEM;
	memset(kframe, 0, sizeof(struct sigframe));

	kframe->sign = sign;
	kframe->tf = *tf;
	kframe->old_blocked = oldset;

	/* mov r7, #119 */
	kframe->retcode[0] = 0xe3a07077;
	/* swi #0 */
	kframe->retcode[1] = 0xef000000;

	/* 4byte align */
	struct sigframe *frame =
	    (struct sigframe *)((stack - sizeof(struct sigframe)) & 0xfffffff8);
	lock_mm(mm);
	{
		if (!copy_to_user(mm, frame, kframe, sizeof(struct sigframe))) {
			unlock_mm(mm);
			kfree(kframe);
			return -E_INVAL;
		}
	}
	unlock_mm(mm);
	kfree(kframe);
	frame->pretcode = (uintptr_t) frame->retcode;

	tf->tf_regs.reg_r[0] = sign;
	tf->tf_epc = (uintptr_t) act->sa_handler;
	tf->tf_esp = (uintptr_t) frame;
	tf->__tf_user_lr = (uint32_t) frame->pretcode;
	return 0;
}
コード例 #16
0
ファイル: proc.c プロジェクト: xuchiheng/ucore_plus
/* poring from linux */
int do_linux_brk(uintptr_t brk)
{
	uint32_t newbrk, oldbrk, retval;
	struct mm_struct *mm = current->mm;
	uint32_t min_brk;

	if (!mm) {
		panic("kernel thread call sys_brk!!.\n");
	}

	lock_mm(mm);

	min_brk = mm->brk_start;

	if (brk < min_brk)
		goto out_unlock;

	newbrk = ROUNDUP(brk, PGSIZE);
	oldbrk = ROUNDUP(mm->brk, PGSIZE);

	if (oldbrk == newbrk)
		goto set_brk;

	if (brk <= mm->brk) {
		if (!mm_unmap(mm, newbrk, oldbrk - newbrk))
			goto set_brk;
		goto out_unlock;
	}

	if (find_vma_intersection(mm, oldbrk, newbrk + PGSIZE))
		goto out_unlock;

	/* set the brk */
	if (mm_brk(mm, oldbrk, newbrk - oldbrk))
		goto out_unlock;

set_brk:
	mm->brk = brk;
out_unlock:
	retval = mm->brk;
	unlock_mm(mm);
	return retval;
}
コード例 #17
0
ファイル: sysfile.c プロジェクト: wwffcc/spoc_discussions
/* copy_path - copy path name */
static int
copy_path(char **to, const char *from) {
    struct mm_struct *mm = current->mm;
    char *buffer;
    if ((buffer = kmalloc(FS_MAX_FPATH_LEN + 1)) == NULL) {
        return -E_NO_MEM;
    }
    lock_mm(mm);
    if (!copy_string(mm, buffer, from, FS_MAX_FPATH_LEN + 1)) {
        unlock_mm(mm);
        goto failed_cleanup;
    }
    unlock_mm(mm);
    *to = buffer;
    return 0;

failed_cleanup:
    kfree(buffer);
    return -E_INVAL;
}
コード例 #18
0
ファイル: arch_signal.c プロジェクト: Aresthu/ucore_plus
// do syscall sigreturn, reset the user stack and eip
int do_sigreturn()
{
	struct mm_struct *mm = current->mm;
	if (!current)
		return -E_INVAL;
	struct sighand_struct *sighand = current->signal_info.sighand;
	if (!sighand)
		return -E_INVAL;

	struct sigframe *kframe = kmalloc(sizeof(struct sigframe));
	if (!kframe)
		return -E_NO_MEM;

	struct sigframe *frame =
	    (struct sigframe *)(current->tf->tf_esp);
	lock_mm(mm);
	{
		if (!copy_from_user
		    (mm, kframe, frame, sizeof(struct sigframe), 0)) {
			unlock_mm(mm);
			kfree(kframe);
			return -E_INVAL;
		}
	}
	unlock_mm(mm);
	/* check the trapframe */
	if (trap_in_kernel(&kframe->tf)) {
		do_exit(-E_KILLED);
		return -E_INVAL;
	}

	lock_sig(sighand);
	current->signal_info.blocked = kframe->old_blocked;
	sig_recalc_pending(current);
	unlock_sig(sighand);

	*(current->tf) = kframe->tf;
	kfree(kframe);

	return 0;
}
コード例 #19
0
ファイル: sysfile.c プロジェクト: spinlock/ucore
int
sysfile_pipe(int *fd_store) {
    struct mm_struct *mm = current->mm;
    int ret, fd[2];
    if (!user_mem_check(mm, (uintptr_t)fd_store, sizeof(fd), 1)) {
        return -E_INVAL;
    }
    if ((ret = file_pipe(fd)) == 0) {
        lock_mm(mm);
        {
            if (!copy_to_user(mm, fd_store, fd, sizeof(fd))) {
                ret = -E_INVAL;
            }
        }
        unlock_mm(mm);
        if (ret != 0) {
            file_close(fd[0]), file_close(fd[1]);
        }
    }
    return ret;
}
コード例 #20
0
ファイル: proc.c プロジェクト: chyyuu/ucore-arch-arm
/* from x86 bionic porting */
int
do_linux_brk(uintptr_t brk) {
    struct mm_struct *mm = current->mm;
    if (mm == NULL) {
        panic("kernel thread call sys_brk!!.\n");
    }

    if (brk == 0) {
        return mm->brk_start;
    }

    lock_mm(mm);
    if (brk < mm->brk_start) {
        goto out_unlock;
    }
    uintptr_t newbrk = ROUNDUP(brk, PGSIZE), oldbrk = mm->brk;
    assert(oldbrk % PGSIZE == 0);
    if (newbrk == oldbrk) {
        goto out_unlock;
    }
    if (newbrk < oldbrk) {
        if (mm_unmap(mm, newbrk, oldbrk - newbrk) != 0) {
            goto out_unlock;
        }
    }
    else {
        if (find_vma_intersection(mm, oldbrk, newbrk + PGSIZE) != NULL) {
            goto out_unlock;
        }
        if (mm_brk(mm, oldbrk, newbrk - oldbrk) != 0) {
            goto out_unlock;
        }
    }
    mm->brk = newbrk;
out_unlock:
    unlock_mm(mm);
    return newbrk;
}
コード例 #21
0
ファイル: proc.c プロジェクト: liangchao1992/ucore
// do_wait - wait one OR any children with PROC_ZOMBIE state, and free memory space of kernel stack
//         - proc struct of this child.
// NOTE: only after do_wait function, all resources of the child proces are free.
int do_wait(int pid, int *code_store)
{
	struct mm_struct *mm = current->mm;
	if (code_store != NULL) {
		if (!user_mem_check(mm, (uintptr_t) code_store, sizeof(int), 1)) {
			return -E_INVAL;
		}
	}

	struct proc_struct *proc, *cproc;
	bool intr_flag, haskid;
repeat:
	cproc = current;
	haskid = 0;
	if (pid != 0) {
		proc = find_proc(pid);
		if (proc != NULL) {
			do {
				if (proc->parent == cproc) {
					haskid = 1;
					if (proc->state == PROC_ZOMBIE) {
						goto found;
					}
					break;
				}
				cproc = next_thread(cproc);
			} while (cproc != current);
		}
	} else {
		do {
			proc = cproc->cptr;
			for (; proc != NULL; proc = proc->optr) {
				haskid = 1;
				if (proc->state == PROC_ZOMBIE) {
					goto found;
				}
			}
			cproc = next_thread(cproc);
		} while (cproc != current);
	}
	if (haskid) {
		current->state = PROC_SLEEPING;
		current->wait_state = WT_CHILD;
		schedule();
		may_killed();
		goto repeat;
	}
	return -E_BAD_PROC;

found:
	if (proc == idleproc || proc == initproc) {
		panic("wait idleproc or initproc.\n");
	}
	int exit_code = proc->exit_code;
	spin_lock_irqsave(&proc_lock, intr_flag);
	{
		unhash_proc(proc);
		remove_links(proc);
	}
	spin_unlock_irqrestore(&proc_lock, intr_flag);
	put_kstack(proc);
	kfree(proc);

	int ret = 0;
	if (code_store != NULL) {
		lock_mm(mm);
		{
			if (!copy_to_user
			    (mm, code_store, &exit_code, sizeof(int))) {
				ret = -E_INVAL;
			}
		}
		unlock_mm(mm);
	}
	return ret;
}
コード例 #22
0
ファイル: mod.c プロジェクト: chyyuu/ucore-driver
static noinline struct module *load_module(void __user * umod,
					   unsigned long len,
					   const char __user * uargs)
{
	struct elfhdr *hdr;
	struct secthdr *sechdrs;
	char *secstrings, *args, *modmagic, *strtab = NULL;
	//char *staging;

	unsigned int i;
	unsigned int symindex = 0;
	unsigned int strindex = 0;
	unsigned int modindex, versindex, infoindex, pcpuindex;
	struct module *mod;
	long err = 0;
	void *ptr = NULL;

	kprintf("load_module: umod=%p, len=%lu, uargs=%p\n", umod, len, uargs);

	if (len < sizeof(*hdr))
		return NULL;
	if (len > 64 * 1024 * 1024 || (hdr = kmalloc(len)) == NULL)
		return NULL;

	kprintf("load_module: copy_from_user\n");

	struct mm_struct *mm = current->mm;
	lock_mm(mm);
	if (!copy_from_user(mm, hdr, umod, len, 1)) {
		unlock_mm(mm);
		goto free_hdr;
	}
	unlock_mm(mm);

	kprintf("load_module: hdr:%p\n", hdr);
	// sanity check
	if (memcmp(&(hdr->e_magic), ELFMAG, SELFMAG) != 0
	    || hdr->e_type != ET_REL || !elf_check_arch(hdr)
	    || hdr->e_shentsize != sizeof(*sechdrs)) {
		kprintf("load_module: sanity check failed.\n");
		goto free_hdr;
	}

	if (len < hdr->e_shoff + hdr->e_shnum * sizeof(*sechdrs))
		goto truncated;

	sechdrs = (void *)hdr + hdr->e_shoff;
	secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
	sechdrs[0].sh_addr = 0;

	for (i = 1; i < hdr->e_shnum; i++) {
		if (sechdrs[i].sh_type != SHT_NOBITS
		    && len < sechdrs[i].sh_offset + sechdrs[i].sh_size)
			goto truncated;

		// mark sh_addr
		sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;

		if (sechdrs[i].sh_type == SHT_SYMTAB) {
			symindex = i;
			strindex = sechdrs[i].sh_link;
			strtab = (char *)hdr + sechdrs[strindex].sh_offset;
		}

	}

	modindex =
	    find_sec(hdr, sechdrs, secstrings, ".gnu.linkonce.this_module");

	if (!modindex) {
		kprintf("load_module: No module found in object.\n");
		goto free_hdr;
	}
	// temp: point mod into copy of data
	mod = (void *)sechdrs[modindex].sh_addr;

	if (symindex == 0) {
		kprintf("load_module: %s module has no symbols (stripped?).\n",
			mod->name);
		goto free_hdr;
	}
	versindex = find_sec(hdr, sechdrs, secstrings, "__versions");
	infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo");
	pcpuindex = 0;//find_pcpusec(hdr, sechdrs, secstrings);

	// don't keep modinfo and version
	sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
	sechdrs[versindex].sh_flags &= ~(unsigned long)SHF_ALLOC;

	// keep symbol and string tables
	sechdrs[symindex].sh_flags |= SHF_ALLOC;
	sechdrs[strindex].sh_flags |= SHF_ALLOC;

	/*if (!check_modstruct_version(sechdrs, versindex, mod)) {
		goto free_hdr;
	}*/

	/*
	   modmagic = get_modinfo(sechdrs, infoindex, "vermagic");

	   if (!modmagic) {
	   kprintf("load_module: bad vermagic\n");
	   goto free_hdr;
	   } else if (!same_magic(modmagic, vermagic, versindex)) {
	   ; 
	   // TODO: module magic is left for future use.
	   }
	 */

	//staging = get_modinfo(sechdrs, infoindex, "staging");
	// TODO: staging is left for future use.

	if (find_module(mod->name)) {
		kprintf("load_module: module %s exists\n", mod->name);
		goto free_mod;
	}

	mod->state = MODULE_STATE_COMING;

	// err = module_frob_arch_sections(hdr, sechdrs, secstrings, mod);
	// TODO: we do not need it for x86 or arm

	// TODO: percpu is no longer needed.

	layout_sections(mod, hdr, sechdrs, secstrings);

	ptr = module_alloc_update_bounds(mod->core_size);

	if (!ptr) {
		goto free_percpu;
	}
	memset(ptr, 0, mod->core_size);
	mod->module_core = ptr;

	ptr = module_alloc_update_bounds(mod->init_size);

	if (!ptr && mod->init_size) {
		goto free_core;
	}
	memset(ptr, 0, mod->init_size);
	mod->module_init = ptr;

	kprintf("load_module: final section addresses:\n");
	for (i = 0; i < hdr->e_shnum; i++) {
		void *dest;
		if (!(sechdrs[i].sh_flags & SHF_ALLOC)) {
			kprintf("\tSkipped %s\n",
				secstrings + sechdrs[i].sh_name);
			continue;
		}
		if (sechdrs[i].sh_entsize & INIT_OFFSET_MASK)
			dest =
			    mod->module_init +
			    (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK);
		else
			dest = mod->module_core + sechdrs[i].sh_entsize;
		if (sechdrs[i].sh_type != SHT_NOBITS)
			memcpy(dest, (void *)sechdrs[i].sh_addr,
			       sechdrs[i].sh_size);
		sechdrs[i].sh_addr = (unsigned long)dest;
		kprintf("\t0x%lx %s\n", sechdrs[i].sh_addr,
			secstrings + sechdrs[i].sh_name);
	}
	/* Module has been moved. */
	mod = (void *)sechdrs[modindex].sh_addr;

	/* Now we've moved module, initialize linked lists, etc. */
	module_unload_init(mod);

	/* Set up license info based on the info section */
	set_license(mod, get_modinfo(sechdrs, infoindex, "license"));

	err = simplify_symbols(sechdrs, symindex, strtab, versindex, pcpuindex,
			       mod);

	if (err < 0)
		goto cleanup;

	mod->syms = section_objs(hdr, sechdrs, secstrings, "__ksymtab",
				 sizeof(*mod->syms), &mod->num_syms);
	mod->crcs = section_addr(hdr, sechdrs, secstrings, "__kcrctab");

	// relocations
	for (i = 1; i < hdr->e_shnum; i++) {
		const char *strtab = (char *)sechdrs[strindex].sh_addr;
		unsigned int info = sechdrs[i].sh_info;

		/* Not a valid relocation section */
		if (info >= hdr->e_shnum)
			continue;

		/* Don't bother with non-allocated sections */
		if (!(sechdrs[info].sh_flags & SHF_ALLOC))
			continue;

		if (sechdrs[i].sh_type == SHT_REL)
			err = apply_relocate(sechdrs, strtab, symindex, i, mod);
		else if (sechdrs[i].sh_type == SHT_RELA)
			err =
			    apply_relocate_add(sechdrs, strtab, symindex, i,
					       mod);

		if (err < 0)
			goto cleanup;
	}

	err = verify_export_symbols(mod);
	if (err < 0)
		goto cleanup;

	// TODO: kallsyms is left for future use.
	//add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);

	err = module_finalize(hdr, sechdrs, mod);
	if (err < 0)
		goto cleanup;

	list_add(&modules, &mod->list);

	kfree(hdr);
	return mod;

cleanup:
	module_unload_free(mod);

free_init:
	module_free(mod, mod->module_init);

free_core:
	module_free(mod, mod->module_core);

free_percpu:

free_mod:

free_hdr:
	kfree(hdr);
	return NULL;

truncated:
	kprintf("load_module: module len %lu truncated.\n");
	goto free_hdr;
}
コード例 #23
0
ファイル: vmm.c プロジェクト: piyifan/ucore_plus-next
int do_pgfault(struct mm_struct *mm, machine_word_t error_code, uintptr_t addr)
{
	if (mm == NULL) {
		assert(current != NULL);
		/* Chen Yuheng 
		 * give handler a chance to deal with it 
		 */
		kprintf
		    ("page fault in kernel thread: pid = %d, name = %s, %d %08x.\n",
		     current->pid, current->name, error_code, addr);
		return -E_KILLED;
	}

	bool need_unlock = 1;
	if (!try_lock_mm(mm)) {
		if (current != NULL && mm->locked_by == current->pid) {
			need_unlock = 0;
		} else {
			lock_mm(mm);
		}
	}

	int ret = -E_INVAL;
	struct vma_struct *vma = find_vma(mm, addr);
	if (vma == NULL || vma->vm_start > addr) {
		goto failed;
	}
	if (vma->vm_flags & VM_STACK) {
		if (addr < vma->vm_start + PGSIZE) {
			goto failed;
		}
	}
	//kprintf("@ %x %08x\n", vma->vm_flags, vma->vm_start);
	//assert((vma->vm_flags & VM_IO)==0);
	if (vma->vm_flags & VM_IO) {
		ret = -E_INVAL;
		goto failed;
	}
	switch (error_code & 3) {
	default:
		/* default is 3: write, present */
	case 2:		/* write, not present */
		if (!(vma->vm_flags & VM_WRITE)) {
			goto failed;
		}
		break;
	case 1:		/* read, present */
		goto failed;
	case 0:		/* read, not present */
		if (!(vma->vm_flags & (VM_READ | VM_EXEC))) {
			goto failed;
		}
	}

	pte_perm_t perm, nperm;
#ifdef ARCH_ARM
	/* ARM9 software emulated PTE_xxx */
	perm = PTE_P | PTE_U;
	if (vma->vm_flags & VM_WRITE) {
		perm |= PTE_W;
	}
#else
	ptep_unmap(&perm);
	ptep_set_u_read(&perm);
	if (vma->vm_flags & VM_WRITE) {
		ptep_set_u_write(&perm);
	}
#endif
	addr = ROUNDDOWN(addr, PGSIZE);

	ret = -E_NO_MEM;

	pte_t *ptep;
	if ((ptep = get_pte(mm->pgdir, addr, 1)) == NULL) {
		goto failed;
	}
	if (ptep_invalid(ptep)) {
#ifdef UCONFIG_BIONIC_LIBC
		if (vma->mfile.file != NULL) {
			struct file *file = vma->mfile.file;
			off_t old_pos = file->pos, new_pos =
			    vma->mfile.offset + addr - vma->vm_start;
#ifdef SHARE_MAPPED_FILE
			struct mapped_addr *maddr =
			    find_maddr(file, new_pos, NULL);
			if (maddr == NULL) {
#endif // SHARE_MAPPED_FILE
				struct Page *page;
				if ((page = alloc_page()) == NULL) {
					assert(false);
					goto failed;
				}
				nperm = perm;
#ifdef ARCH_ARM
				/* ARM9 software emulated PTE_xxx */
				nperm &= ~PTE_W;
#else
				ptep_unset_s_write(&nperm);
#endif
				page_insert_pte(mm->pgdir, page, ptep, addr,
						nperm);

				if ((ret =
				     filestruct_setpos(file, new_pos)) != 0) {
					assert(false);
					goto failed;
				}
				filestruct_read(file, page2kva(page), PGSIZE);
				if ((ret =
				     filestruct_setpos(file, old_pos)) != 0) {
					assert(false);
					goto failed;
				}
#ifdef SHARE_MAPPED_FILE
				if ((maddr = (struct mapped_addr *)
				     kmalloc(sizeof(struct mapped_addr))) !=
				    NULL) {
					maddr->page = page;
					maddr->offset = new_pos;
					page->maddr = maddr;
					list_add(&
						 (file->node->mapped_addr_list),
						 &(maddr->list));
				} else {
					assert(false);
				}
			} else {
				nperm = perm;
#ifdef ARCH_ARM
				/* ARM9 software emulated PTE_xxx */
				nperm &= ~PTE_W;
#else
				ptep_unset_s_write(&nperm);
#endif
				page_insert_pte(mm->pgdir, maddr->page, ptep,
						addr, nperm);
			}
#endif //SHARE_MAPPED_FILE

		} else
#endif //UCONFIG_BIONIC_LIBC
		if (!(vma->vm_flags & VM_SHARE)) {
			if (pgdir_alloc_page(mm->pgdir, addr, perm) == NULL) {
				goto failed;
			}
#ifdef UCONFIG_BIONIC_LIBC
			if (vma->vm_flags & VM_ANONYMOUS) {
				memset((void *)addr, 0, PGSIZE);
			}
#endif //UCONFIG_BIONIC_LIBC
		} else {	//shared mem
			lock_shmem(vma->shmem);
			uintptr_t shmem_addr =
			    addr - vma->vm_start + vma->shmem_off;
			pte_t *sh_ptep =
			    shmem_get_entry(vma->shmem, shmem_addr, 1);
			if (sh_ptep == NULL || ptep_invalid(sh_ptep)) {
				unlock_shmem(vma->shmem);
				goto failed;
			}
			unlock_shmem(vma->shmem);
			if (ptep_present(sh_ptep)) {
				page_insert(mm->pgdir, pa2page(*sh_ptep), addr,
					    perm);
			} else {
#ifdef UCONFIG_SWAP
				swap_duplicate(*ptep);
				ptep_copy(ptep, sh_ptep);
#else
				panic("NO SWAP\n");
#endif
			}
		}
	} else {		//a present page, handle copy-on-write (cow) 
		struct Page *page, *newpage = NULL;
		bool cow =
		    ((vma->vm_flags & (VM_SHARE | VM_WRITE)) == VM_WRITE),
		    may_copy = 1;

#if 1
		if (!(!ptep_present(ptep)
		      || ((error_code & 2) && !ptep_u_write(ptep) && cow))) {
			//assert(PADDR(mm->pgdir) == rcr3());
			kprintf("%p %p %d %d %x\n", *ptep, addr, error_code,
				cow, vma->vm_flags);
			assert(0);
		}
#endif

		if (cow) {
			newpage = alloc_page();
		}
		if (ptep_present(ptep)) {
			page = pte2page(*ptep);
		} else {
#ifdef UCONFIG_SWAP
			if ((ret = swap_in_page(*ptep, &page)) != 0) {
				if (newpage != NULL) {
					free_page(newpage);
				}
				goto failed;
			}
#else
			assert(0);
#endif
			if (!(error_code & 2) && cow) {
#ifdef ARCH_ARM
//#warning ARM9 software emulated PTE_xxx
				perm &= ~PTE_W;
#else
				ptep_unset_s_write(&perm);
#endif
				may_copy = 0;
			}
		}

		if (cow && may_copy) {
#ifdef UCONFIG_SWAP
			if (page_ref(page) + swap_page_count(page) > 1) {
#else
			if (page_ref(page) > 1) {
#endif
				if (newpage == NULL) {
					goto failed;
				}
				memcpy(page2kva(newpage), page2kva(page),
				       PGSIZE);
				//kprintf("COW!\n");
				page = newpage, newpage = NULL;
			}
		}
#ifdef UCONFIG_BIONIC_LIBC
		else if (vma->mfile.file != NULL) {
#ifdef UCONFIG_SWAP
			assert(page_reg(page) + swap_page_count(page) == 1);
#else
			assert(page_ref(page) == 1);
#endif

#ifdef SHARE_MAPPED_FILE
			off_t offset = vma->mfile.offset + addr - vma->vm_start;
			struct mapped_addr *maddr =
			    find_maddr(vma->mfile.file, offset, page);
			if (maddr != NULL) {
				list_del(&(maddr->list));
				kfree(maddr);
				page->maddr = NULL;
				assert(find_maddr(vma->mfile.file, offset, page)
				       == NULL);
			} else {
			}
#endif //SHARE_MAPPED_FILE
		}
#endif //UCONFIG_BIONIC_LIBC
		else {
		}
		page_insert(mm->pgdir, page, addr, perm);
		if (newpage != NULL) {
			free_page(newpage);
		}
	}
	ret = 0;

failed:
	if (need_unlock) {
		unlock_mm(mm);
	}
	return ret;
}
コード例 #24
0
ファイル: proc.c プロジェクト: xuchiheng/ucore_plus
int do_mprotect(void *addr, size_t len, int prot)
{

	/*
	   return 0; 
	 */

	struct mm_struct *mm = current->mm;
	assert(mm != NULL);
	if (len == 0) {
		return -E_INVAL;
	}
	uintptr_t start = ROUNDDOWN(addr, PGSIZE);
	uintptr_t end = ROUNDUP(addr + len, PGSIZE);

	int ret = -E_INVAL;
	lock_mm(mm);

	while (1) {
		struct vma_struct *vma = find_vma(mm, start);
		uintptr_t last_end;
		if (vma != NULL) {
			last_end = vma->vm_end;
		}
		if (vma == NULL) {
			goto out;
		} else if (vma->vm_start == start && vma->vm_end == end) {
			if (prot & PROT_WRITE) {
				vma->vm_flags |= VM_WRITE;
			} else {
				vma->vm_flags &= ~VM_WRITE;
			}
		} else {
			uintptr_t this_end =
			    (end <= vma->vm_end) ? end : vma->vm_end;
			uintptr_t this_start =
			    (start >= vma->vm_start) ? start : vma->vm_start;

			struct mapped_file_struct mfile = vma->mfile;
			mfile.offset += this_start - vma->vm_start;
			uint32_t flags = vma->vm_flags;
			if ((ret =
			     mm_unmap_keep_pages(mm, this_start,
						 this_end - this_start)) != 0) {
				goto out;
			}
			if (prot & PROT_WRITE) {
				flags |= VM_WRITE;
			} else {
				flags &= ~VM_WRITE;
			}
			if ((ret =
			     mm_map(mm, this_start, this_end - this_start,
				    flags, &vma)) != 0) {
				goto out;
			}
			vma->mfile = mfile;
			if (vma->mfile.file != NULL) {
				filemap_acquire(mfile.file);
			}
		}

		ret = 0;

		if (end <= last_end)
			break;
		start = last_end;
	}

out:
	unlock_mm(mm);
	return ret;
}
コード例 #25
0
ファイル: vmm.c プロジェクト: jefjin/ucore
// do_pgfault - interrupt handler to process the page fault execption
int
do_pgfault(struct mm_struct *mm, uint32_t error_code, uintptr_t addr) {
    if (mm == NULL) {
        assert(current != NULL);
        panic("page fault in kernel thread: pid = %d, %d %08x.\n",
                current->pid, error_code, addr);
    }
    lock_mm(mm);

    int ret = -E_INVAL;
    struct vma_struct *vma = find_vma(mm, addr);
    if (vma == NULL || vma->vm_start > addr) {
        goto failed;
    }
    if (vma->vm_flags & VM_STACK) {
        if (addr < vma->vm_start + PGSIZE) {
            goto failed;
        }
    }

    switch (error_code & 3) {
    default:
            /* default is 3: write, present */
    case 2: /* write, not present */
        if (!(vma->vm_flags & VM_WRITE)) {
            goto failed;
        }
        break;
    case 1: /* read, present */
        goto failed;
    case 0: /* read, not present */
        if (!(vma->vm_flags & (VM_READ | VM_EXEC))) {
            goto failed;
        }
    }

    uint32_t perm = PTE_U;
    if (vma->vm_flags & VM_WRITE) {
        perm |= PTE_W;
    }
    addr = ROUNDDOWN(addr, PGSIZE);

    ret = -E_NO_MEM;
    pte_t *ptep;

    if ((ptep = get_pte(mm->pgdir, addr, 1)) == NULL) {
        goto failed;
    }
    if (*ptep == 0) {
        if (!(vma->vm_flags & VM_SHARE)) {
            if (pgdir_alloc_page(mm->pgdir, addr, perm) == NULL) {
                goto failed;
            }
        }
        else {
            lock_shmem(vma->shmem);
            uintptr_t shmem_addr = addr - vma->vm_start + vma->shmem_off;
            pte_t *sh_ptep = shmem_get_entry(vma->shmem, shmem_addr, 1);
            if (sh_ptep == NULL || *sh_ptep == 0) {
                unlock_shmem(vma->shmem);
                goto failed;
            }
            unlock_shmem(vma->shmem);
            if (*sh_ptep & PTE_P) {
                page_insert(mm->pgdir, pa2page(*sh_ptep), addr, perm);
            }
            else {
                swap_duplicate(*ptep);
                *ptep = *sh_ptep;
            }
        }
    }
    else {
        struct Page *page, *newpage = NULL;
        bool cow = ((vma->vm_flags & (VM_SHARE | VM_WRITE)) == VM_WRITE), may_copy = 1;

        assert(!(*ptep & PTE_P) || ((error_code & 2) && !(*ptep & PTE_W) && cow));
        if (cow) {
            newpage = alloc_page();
        }
        if (*ptep & PTE_P) {
            page = pte2page(*ptep);
        }
        else {
            if ((ret = swap_in_page(*ptep, &page)) != 0) {
                if (newpage != NULL) {
                    free_page(newpage);
                }
                goto failed;
            }
            if (!(error_code & 2) && cow) {
                perm &= ~PTE_W;
                may_copy = 0;
            }
        }

        if (cow && may_copy) {
            if (page_ref(page) + swap_page_count(page) > 1) {
                if (newpage == NULL) {
                    goto failed;
                }
                memcpy(page2kva(newpage), page2kva(page), PGSIZE);
                page = newpage, newpage = NULL;
            }
        }
        page_insert(mm->pgdir, page, addr, perm);
        if (newpage != NULL) {
            free_page(newpage);
        }
    }
    ret = 0;

failed:
    unlock_mm(mm);
    return ret;
}
コード例 #26
0
ファイル: proc.c プロジェクト: chyyuu/ucore-arch-arm
int
do_execve(const char *filename, const char **argv, const char **envp) {
    static_assert(EXEC_MAX_ARG_LEN >= FS_MAX_FPATH_LEN);
    
    struct mm_struct *mm = current->mm;

    char local_name[PROC_NAME_LEN + 1];
    memset(local_name, 0, sizeof(local_name));

    char *kargv[EXEC_MAX_ARG_NUM], *kenvp[EXEC_MAX_ENV_NUM];
    const char *path;

    int ret = -E_INVAL;
    lock_mm(mm);
#if 0
    if (name == NULL) {
        snprintf(local_name, sizeof(local_name), "<null> %d", current->pid);
    }
    else {
        if (!copy_string(mm, local_name, name, sizeof(local_name))) {
            unlock_mm(mm);
            return ret;
        }
    }
#endif
    snprintf(local_name, sizeof(local_name), "<null> %d", current->pid);

    int argc = 0, envc = 0;
    if ((ret = copy_kargv(mm, kargv, argv, EXEC_MAX_ARG_NUM, &argc)) != 0) {
      unlock_mm(mm);
      return ret;
    }
    if ((ret = copy_kargv(mm, kenvp, envp, EXEC_MAX_ENV_NUM, &envc)) != 0) {
      unlock_mm(mm);
      put_kargv(argc, kargv);
      return ret;
    }

#if 0
    int i;
    kprintf("## fn %s\n", filename);
    kprintf("## argc %d\n", argc);
    for(i=0;i<argc;i++)
      kprintf("## %08x %s\n", kargv[i], kargv[i]);
    kprintf("## envc %d\n", envc);
    for(i=0;i<envc;i++)
      kprintf("## %08x %s\n", kenvp[i], kenvp[i]);
#endif
    //path = argv[0];
    //copy_from_user (mm, &path, argv, sizeof (char*), 0);
    path = filename;
    unlock_mm(mm);

    /* linux never do this */
    //fs_closeall(current->fs_struct);

    /* sysfile_open will check the first argument path, thus we have to use a user-space pointer, and argv[0] may be incorrect */

    int fd;
    if ((ret = fd = sysfile_open(path, O_RDONLY)) < 0) {
      goto execve_exit;
    }

    if (mm != NULL) {
      mm->lapic = -1;
      mp_set_mm_pagetable(NULL);
      if (mm_count_dec(mm) == 0) {
        exit_mmap(mm);
        put_pgdir(mm);
        bool intr_flag;
        local_intr_save(intr_flag);
        {
          list_del(&(mm->proc_mm_link));
        }
            local_intr_restore(intr_flag);
            mm_destroy(mm);
        }
        current->mm = NULL;
    }
    put_sem_queue(current);

    ret = -E_NO_MEM;
    /* init signal */
    put_sighand(current);
    if ((current->signal_info.sighand = sighand_create()) == NULL) {
      goto execve_exit;
    }
    sighand_count_inc(current->signal_info.sighand);

    put_signal(current);
    if ((current->signal_info.signal = signal_create()) == NULL) {
      goto execve_exit;
    }
    signal_count_inc(current->signal_info.signal);

    if ((current->sem_queue = sem_queue_create()) == NULL) {
      goto execve_exit;
    }
    sem_queue_count_inc(current->sem_queue);

    if ((ret = load_icode(fd, argc, kargv, envc, kenvp)) != 0) {
      goto execve_exit;
    }

    set_proc_name(current, local_name);

	if (do_execve_arch_hook (argc, kargv) < 0)
		goto execve_exit;
	
    put_kargv(argc, kargv);
    return 0;

execve_exit:
    put_kargv(argc, kargv);
    put_kargv(envc, kenvp);
/* exec should return -1 if failed */
    //return ret;
    do_exit(ret);
    panic("already exit: %e.\n", ret);
}
コード例 #27
0
ファイル: file.c プロジェクト: cty12/ucore_plus
void *linux_regfile_mmap2(void *addr, size_t len, int prot, int flags, int fd,
			  size_t off)
{
	int subret = -E_INVAL;
	struct mm_struct *mm = current->mm;
	assert(mm != NULL);
	if (len == 0) {
		return -1;
	}
	lock_mm(mm);

	uintptr_t start = ROUNDDOWN(addr, PGSIZE);
	len = ROUNDUP(len, PGSIZE);

	uint32_t vm_flags = VM_READ;
	if (prot & PROT_WRITE) {
		vm_flags |= VM_WRITE;
	}
	if (prot & PROT_EXEC) {
		vm_flags |= VM_EXEC;
	}
	if (flags & MAP_STACK) {
		vm_flags |= VM_STACK;
	}
	if (flags & MAP_ANONYMOUS) {
		vm_flags |= VM_ANONYMOUS;
	}

	subret = -E_NO_MEM;
	if (start == 0 && (start = get_unmapped_area(mm, len)) == 0) {
		goto out_unlock;
	}
	uintptr_t end = start + len;
	struct vma_struct *vma = find_vma(mm, start);
	if (vma == NULL || vma->vm_start >= end) {
		vma = NULL;
	} else if (!(flags & MAP_FIXED)) {
		start = get_unmapped_area(mm, len);
		vma = NULL;
	} else if (!(vma->vm_flags & VM_ANONYMOUS)) {
		goto out_unlock;
	} else if (vma->vm_start == start && end == vma->vm_end) {
		vma->vm_flags = vm_flags;
	} else {
		assert(vma->vm_start <= start && end <= vma->vm_end);
		if ((subret = mm_unmap_keep_pages(mm, start, len)) != 0) {
			goto out_unlock;
		}
		vma = NULL;
	}
	if (vma == NULL
	    && (subret = mm_map(mm, start, len, vm_flags, &vma)) != 0) {
		goto out_unlock;
	}
	if (!(flags & MAP_ANONYMOUS)) {
		vma_mapfile(vma, fd, off << 12, NULL);
	}
	subret = 0;
out_unlock:
	unlock_mm(mm);
	return subret == 0 ? start : -1;
}
コード例 #28
0
ファイル: proc.c プロジェクト: chyyuu/ucore-arch-arm
int
do_linux_waitpid(int pid, int *code_store) {
    struct mm_struct *mm = current->mm;
    if (code_store != NULL) {
        if (!user_mem_check(mm, (uintptr_t)code_store, sizeof(int), 1)) {
            return -E_INVAL;
        }
    }

    struct proc_struct *proc, *cproc;
    bool intr_flag, haskid;
repeat:
    cproc = current;
    haskid = 0;
    if (pid > 0) {
        proc = find_proc(pid);
        if (proc != NULL) {
            do {
                if (proc->parent == cproc) {
                    haskid = 1;
                    if (proc->state == PROC_ZOMBIE) {
                        goto found;
                    }
                    break;
                }
                cproc = next_thread(cproc);
            } while (cproc != current);
        }
    }
    /* we do NOT have group id, so..*/
    else if(pid==0 || pid==-1){ /* pid == 0 */
        do {
            proc = cproc->cptr;
            for (; proc != NULL; proc = proc->optr) {
                haskid = 1;
                if (proc->state == PROC_ZOMBIE) {
                    goto found;
                }
            }
            cproc = next_thread(cproc);
        } while (cproc != current);
    }else{ //pid<-1
      //TODO
      return -E_INVAL;
    }
    if (haskid) {
        current->state = PROC_SLEEPING;
        current->wait_state = WT_CHILD;
        schedule();
        may_killed();
        goto repeat;
    }
    return -E_BAD_PROC;

found:
    if (proc == idleproc || proc == initproc) {
        panic("wait idleproc or initproc.\n");
    }
    int exit_code = proc->exit_code;
    int return_pid = proc->pid;
    local_intr_save(intr_flag);
    {
        unhash_proc(proc);
        remove_links(proc);
    }
    local_intr_restore(intr_flag);
    put_kstack(proc);
    kfree(proc);

    int ret = 0;
    if (code_store != NULL) {
        lock_mm(mm);
        {
            int status = exit_code << 8;
            if (!copy_to_user(mm, code_store, &status, sizeof(int))) {
                ret = -E_INVAL;
            }
        }
        unlock_mm(mm);
    }
    return (ret == 0) ? return_pid : ret;
}