Beispiel #1
0
/* int munmap(void* addr, size_t length) */
int sys_munmap(void)
{
	void* addr;
	size_t length;

	if(syscall_get_int((int*)&addr, 0)) return -1;
        if(syscall_get_int((int*)&length, 1)) return -1;

	/* Is the address okay? */
	uintptr_t address = (uintptr_t)addr;
	if(length == 0) return -1;
	/* Address must be page aligned */
	if(address != PGROUNDDOWN(address)) return -1;

	/* Address must be in the proper range */
	if(address < PGROUNDUP(rproc->heap_end) + PGSIZE ||
			address >= PGROUNDDOWN(rproc->mmap_start) ||
			address + length > PGROUNDDOWN(rproc->mmap_start))
		return -1;

	uintptr_t x;
	for(x = 0;x < length;x += PGSIZE)
		vm_unmappage(x + address, rproc->pgdir);

	return 0;
}
Beispiel #2
0
int vm_init(void)
{
	slock_init(&global_mem_lock);
#ifdef __ALLOW_VM_SHARE__
	vm_share_init(); /* Setup shared memory */
#endif

	/** 
	 * The boot loader has handled all of the messy work for us.
	 * All we need to do is pick up the free map head and kernel
	 * page directory.
	 */
	
	/* The boot strap directly mapped in the null guard page */
	vm_unmappage(0x0, k_pgdir);

	vmflags_t dir_flags = VM_DIR_READ | VM_DIR_WRIT;
	vmflags_t tbl_flags = VM_TBL_READ | VM_TBL_WRIT;

	/* Map pages in for our kernel stack */
	vm_mappages(KVM_KSTACK_S, KVM_KSTACK_E - KVM_KSTACK_S, k_pgdir, 
		dir_flags, tbl_flags);

	/* Add bootstrap code to the memory pool */
	int boot2_s = PGROUNDDOWN(KVM_BOOT2_S) + PGSIZE;
	int boot2_e = PGROUNDUP(KVM_BOOT2_E);

	int x;
	for(x = boot2_s;x < boot2_e;x += PGSIZE)
		pfree(x);	

	/* Clear the TLB */
	vm_enable_paging(k_pgdir);

	return 0;
}
Beispiel #3
0
int sig_handle(void)
{
	/* Make sure there is a signal being waited on. */
	if(!rproc->sig_queue)
		return 0;

	/* Not sure if interrupts will mess this up but better be sure */
	push_cli();

	/* Get the signal from the top of the queue */
	struct signal_t* sig = rproc->sig_queue;
	void (*sig_handler)(int sig_num) = 
		rproc->sigactions[sig->signum].sa_handler;
	int caught = 0; /* Did we catch the signal? */
	int terminated = 0; /* Did we get terminated? */
	int stopped = 0; /* Did we get stopped? */
	int core = 0; /* Should we dump the core? */
	int ignored = 0; /* Was the default action caught and ignored? */

	/* Does the user want us to use the default action? */
	if(rproc->sigactions[sig->signum].sa_handler == SIG_DFL)
		sig->catchable = 0; /* Make signal uncatchable */

	switch(rproc->sig_queue->default_action)
	{
		case SIGDEFAULT_KPANIC:
			panic("kernel: Invalid signal handled!\n");
			break;
		case SIGDEFAULT_TERM:
			if(sig->catchable)
			{
				caught = 1;
			} else {
				terminated = 1;
			}
			break;
		case SIGDEFAULT_CORE:
			if(sig->catchable)
			{
				caught = 1;
			} else { 
				core = terminated = 1;
			}
			break;
		case SIGDEFAULT_STOP:
			if(sig->catchable)
			{
				caught = 1;
			} else {
				stopped = 1;
			}
			break;
		case SIGDEFAULT_CONT:
			if(sig->catchable)
			{
				caught = 1;
			}
			break;
		case SIGDEFAULT_IGN:
			if(sig->catchable)
			{
				caught = 1;
			}
			break;
	}

	/** 
	 * If the user wants this signal to be ignored, ignore it. 
	 * EXCEPTIONS: if we are terminated, dumped or stopped then
	 * we must continue with the default action.
	 */
	if(rproc->sigactions[sig->signum].sa_handler == SIG_IGN)
	{
		if(!terminated && !stopped && !core)
			ignored = 1;
		caught = 0;
	}

	/* Were we able to catch the signal? */
	if(caught)
	{
		/* Do we have a signal stack? */
		if(!rproc->sig_stack_start)
		{
			/* TODO: probably don't use mmap here, this will */
			/*        change in the future.                  */

			/* Allocate a signal stack */
			int pages = SIG_DEFAULT_STACK + SIG_DEFAULT_GUARD;
			uint end = (uint)mmap(NULL, 
					pages * PGSIZE, 
					PROT_WRITE | PROT_READ,
					MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);

			/* Unmap all guard pages */
			int x;
			for(x = 0;x < SIG_DEFAULT_GUARD;x++)
			{
				vm_unmappage(end, rproc->pgdir);
				end += PGSIZE;
			}

			/* Set sig stack start */
			rproc->sig_stack_start = end + 
				(SIG_DEFAULT_STACK * PGSIZE);
		}

		/* Save the current trap frame if we need to */
		if(!rproc->sig_handling)
		{
			/* We weren't handling a signal until now */
			memmove(&rproc->sig_saved, 
					(char*)rproc->k_stack - sizeof(struct trap_frame),
					sizeof(struct trap_frame));
		}

		pstack_t stack = rproc->sig_stack_start;

		/* set the return address to the sig handler */
		rproc->tf->eip = (uintptr_t)sig_handler;

		vmflags_t dir_flags = VM_DIR_USRP | VM_DIR_READ | VM_DIR_WRIT;
		vmflags_t tbl_flags = VM_TBL_USRP | VM_TBL_READ | VM_TBL_WRIT;

		/* Push argument (sig) */
		stack -= sizeof(int);
		vm_memmove((void*)stack, &sig->signum, sizeof(int),
				rproc->pgdir, rproc->pgdir,
				dir_flags, tbl_flags);

		/* (safely) Push our magic return value */
		stack -= sizeof(int);
		uint32_t mag = SIG_MAGIC;
		vm_memmove((void*)stack, &mag, sizeof(int), 
				rproc->pgdir, rproc->pgdir,
				dir_flags, tbl_flags);

		/* Update stack pointer */
		rproc->tf->esp = stack;

		/* We are now actively handling this signal */
		rproc->sig_handling = 1;
	}

	pop_cli(); 

	/* Check to see if we need to dump the core */
	if(core)
	{
		/* Dump memory for gdb analysis */
#ifdef DEBUG
		cprintf("%s:%d: CORE DUMPED\n", rproc->name, rproc->pid);
#endif
		rproc->status_changed = 1;
		rproc->return_code = ((sig->signum & 0xFF) << 0x8) | 0x02;
		rproc->state = PROC_ZOMBIE;
		wake_parent(rproc);
		yield_withlock();
	}

	/* If we got stopped, we will enter scheduler. */
	if(stopped)
	{
#ifdef DEBUG
		cprintf("%s:%d: process stopped.\n", rproc->name, rproc->pid);
#endif

		rproc->status_changed = 1;
		rproc->state = PROC_STOPPED;
		rproc->return_code = ((sig->signum & 0xFF) << 0x08) | 0x04;
		/* Should we wake the parent? */
		if(!rproc->orphan && rproc->parent
				&& (rproc->parent->wait_options & WUNTRACED))
		{
			wake_parent(rproc);
		}
		sig_dequeue(rproc);
		yield_withlock();

		/* Should we wake our parent now that we've continued */
		rproc->status_changed = 1;
		if(!rproc->orphan && rproc->parent
				&& (rproc->parent->wait_options & WCONTINUED))
		{
			wake_parent(rproc);
		}

	}

	/* Check to see if we got terminated */
	if(terminated)
	{
#ifdef DEBUG
		cprintf("%s:%d: Process killed by signal. No core dumped.\n", 
				rproc->name, rproc->pid);
#endif

		rproc->status_changed = 1;
		rproc->return_code = ((sig->signum & 0xFF) << 0x08) | 0x01;
		rproc->state = PROC_ZOMBIE;
		wake_parent(rproc);
		yield_withlock();
	}

	if(ignored)
		sig_dequeue(rproc);

	return 0;
}