コード例 #1
0
ファイル: proc.c プロジェクト: Aresthu/ucore_plus
/**
 * The hook called before 'do_execve' successfully return.
 *     What we need to do here are:
 *       1. create a new host container if the process doesn't have one yet;
 *       2. create the stack for syscall stub;
 *       3. unmap umUcore kernel area in the child and erasing the info in the page table;
 *       4. copy arguments to the user stack of the child, and free the kernel's copy;
 *       5. call 'userspace'.
 *     If everything is done, the current thread becomes a monitor thread forever.
 * @param argc the number of arguments
 * @param kargv the copy of the arguments in the kernel
 */
int do_execve_arch_hook(int argc, char **kargv)
{
	if (current->arch.host == NULL) {
		current->arch.host = kmalloc(sizeof(struct host_container));
		if (current->arch.host == NULL)
			return -1;
	}

	void *stub_stack = boot_alloc_page();
	if (stub_stack == NULL)
		goto free_host;
	int ret = start_userspace(stub_stack);
	if (ret <= 0)
		goto free_stub_stack;

	current->arch.host->stub_stack = stub_stack;
	current->arch.host->host_pid = ret;
	current->arch.host->nr_threads = 1;

	/* unmap kernel area */
	if (host_munmap(current, (void *)KERNBASE, KERNTOP - KERNBASE) < 0)
		panic("unmap kernel area failed\n");

	/* erase kernel maps in the page table */
	int valid_size = KERNBASE / PTSIZE * sizeof(pte_t);
	memset((void *)((int)(current->mm->pgdir) + valid_size),
	       0, PGSIZE - valid_size);

	/* Copy arguments */
	current->arch.regs.is_user = 1;
	uintptr_t stacktop = USTACKTOP - argc * PGSIZE;
	char **uargv = (char **)(stacktop - argc * sizeof(char *));
	int i, addr;
	for (i = 0; i < argc; i++) {
		addr = stacktop + i * PGSIZE;
		assert(copy_to_user
		       (current->mm, uargv + i, &addr, sizeof(int)));
		assert(copy_to_user
		       (current->mm, (void *)addr, kargv[i],
			strlen(kargv[i]) + 1));
	}
	stacktop = (uintptr_t) uargv - sizeof(int);
	copy_to_user(current->mm, (void *)stacktop, &argc, sizeof(int));

	/* The copy of the args in the kernel will never be used again and we will not return,
	 *     so free them here.
	 */
	while (argc > 0) {
		kfree(kargv[--argc]);
	}
	userspace(&(current->arch.regs));
	/* should never comes here */

free_stub_stack:
	free_page(kva2page(stub_stack));
free_host:
	kfree(current->arch.host);
	current->arch.host = NULL;
	return -1;
}
コード例 #2
0
ファイル: pmm.c プロジェクト: PungiZhang/ucore_plus-next
//pmm_init - setup a pmm to manage physical memory, build PDT&PT to setup paging mechanism 
//         - check the correctness of pmm & paging mechanism, print PDT&PT
void
pmm_init(void) {
	init_pmm_manager ();
	page_init ();
	
#ifndef NOCHECK
    //check_alloc_page();
#endif

	boot_pgdir = boot_alloc_page ();
	memset (boot_pgdir, 0, PGSIZE);
	boot_pgdir_pa = PADDR (boot_pgdir);
	current_pgdir_pa = boot_pgdir_pa;

#ifndef NOCHECK
	//check_pgdir ();
#endif

	static_assert(KERNBASE % PTSIZE == 0 && KERNTOP % PTSIZE == 0);

	boot_pgdir[PDX(VPT)] = PADDR(boot_pgdir) | PTE_P | PTE_SPR_R | PTE_SPR_W | PTE_A | PTE_D;
    boot_map_segment(boot_pgdir, KERNBASE, RAM_SIZE, 0, PTE_SPR_R | PTE_SPR_W | PTE_A | PTE_D);

	enable_paging ();
#ifndef NOCHECK
	//check_boot_pgdir ();
#endif
	
    print_pgdir (kprintf);

	slab_init ();
}
コード例 #3
0
ファイル: pmm.c プロジェクト: lhh520/os-4-risc-v
//pmm_init - setup a pmm to manage physical memory, build PDT&PT to setup paging mechanism 
//         - check the correctness of pmm & paging mechanism, print PDT&PT
void
pmm_init(void) {
    //We need to alloc/free the physical memory (granularity is 4KB or other size). 
    //So a framework of physical memory manager (struct pmm_manager)is defined in pmm.h
    //First we should init a physical memory manager(pmm) based on the framework.
    //Then pmm can alloc/free the physical memory. 
    //Now the first_fit/best_fit/worst_fit/buddy_system pmm are available.
    init_pmm_manager();

    // detect physical memory space, reserve already used memory,
    // then use pmm->init_memmap to create free page list
    page_init();

    //use pmm->check to verify the correctness of the alloc/free function in a pmm
    check_alloc_page();

    // create boot_pgdir, an initial page directory(Page Directory Table, PDT)
    boot_pgdir = boot_alloc_page();
    memset(boot_pgdir, 0, PGSIZE);
    boot_cr3 = PADDR(boot_pgdir);

    check_pgdir();


    static_assert(KERNBASE % PTSIZE == 0 && KERNTOP % PTSIZE == 0);

    // recursively insert boot_pgdir in itself
    // to form a virtual page table at virtual address VPT
 //   cprintf("haah1\n");
    // map all physical memory to linear memory with base linear addr KERNBASE
    //linear_addr KERNBASE~KERNBASE+KMEMSIZE = phy_addr 0~KMEMSIZE
    //But shouldn't use this map until enable_paging() & gdt_init() finished.
    boot_map_segment(boot_pgdir, 0, KMEMSIZE, 0, PTE_TYPE_URWX_SRWX | PTE_R | PTE_V);
    boot_pgdir[PDX(VPT)] = PADDR(boot_pgdir) | PTE_TYPE_TABLE | PTE_R | PTE_V;
   // pgdir_alloc_page(boot_pgdir, USTACKTOP-PGSIZE , PTE_TYPE_URW_SRW);
    //cprintf("haha2\n");
    //temporary map: 
    //virtual_addr 3G~3G+4M = linear_addr 0~4M = linear_addr 3G~3G+4M = phy_addr 0~4M     
    //boot_pgdir[0] = boot_pgdir[PDX(KERNBASE)];
    //cprintf("OK!\n");
    enable_paging();
//    cprintf("haah\n");
    //reload gdt(third time,the last time) to map all physical memory
    //virtual_addr 0~4G=liear_addr 0~4G
    //then set kernel stack(ss:esp) in TSS, setup TSS in gdt, load TSS
    //gdt_init();

    //disable the map of virtual_addr 0~4M
    //boot_pgdir[0] = 0;

    //now the basic virtual memory map(see memalyout.h) is established.
    //check the correctness of the basic virtual memory map.
    check_boot_pgdir();

    print_pgdir();

    kmalloc_init();

}
コード例 #4
0
ファイル: pmm.c プロジェクト: haozhun/ucore_plus
/**
 * Initialize page management mechanism.
 *     Parts of no use are deleted, while no extra parts except a check is added.
 *     arch/x86/mm/pmm.c should be a good reference.
 */
void
pmm_init (void)
{
    check_vpm ();

    init_pmm_manager ();

    page_init ();

    check_alloc_page ();

    boot_pgdir = boot_alloc_page();
    memset(boot_pgdir, 0, PGSIZE);
    check_pgdir();

    /* register kernel code and data pages in the table so that it won't raise bad segv. */
    boot_map_segment (boot_pgdir, KERNBASE, mem_size, 0, PTE_W);

    check_boot_pgdir ();
    print_pgdir (kprintf);

    slab_init ();
}
コード例 #5
0
ファイル: proc.c プロジェクト: Aresthu/ucore_plus
/**
 * Make a copy of the current thread/process, giving the parent the child's pid and the child 0.
 *     This is called in do_fork after all structures in the child's PCB are ready.
 * @param clone_flags we need this to determine whether we're creating a 'thread' or a 'process'
 * @param proc the PCB of the child
 * @param user_stack the stack used by the child
 * @param tf the struct containing 'fn' and 'arg'
 * @return 0 if succeeds, or -1 otherwise
 */
int
copy_thread(uint32_t clone_flags, struct proc_struct *proc,
	    uintptr_t user_stack, struct trapframe *tf)
{
	int pid;
	void *stub_stack;

	/* If 'do_fork' is called by the kernel, 'current' should be idle,
	 *     and we're actually creating a kernel thread .
	 * If 'do_fork' is called by the user (i.e. syscall), 'current' is a user PCB,
	 *     and we need to create another user process.
	 */
	if (RUN_AS_USER) {
		if (clone_flags & CLONE_VM) {
			/* Use current host process as its container */
			proc->arch.host = current->arch.host;
			proc->arch.host->nr_threads++;
		} else {
			/* Create a new child process */
			proc->arch.host =
			    kmalloc(sizeof(struct host_container));
			if (proc->arch.host == NULL)
				goto exit;

			stub_stack = boot_alloc_page();
			if (stub_stack == NULL)
				goto exit_free_host;
			pid = start_userspace(stub_stack);

			if (pid < 0)
				goto exit_free_stub;

			/* Initialize host process descriptor */
			proc->arch.forking = 0;
			proc->arch.host->host_pid = pid;
			proc->arch.host->nr_threads = 1;
			proc->arch.host->stub_stack =
			    (struct stub_stack *)stub_stack;
			/* unmap kernel area. */
			if (host_munmap
			    (proc, (void *)KERNBASE, KERNTOP - KERNBASE) < 0)
				panic("unmap kernel area failed \n");
		}
		/* The child should have the same regs as the parent's. */
		memcpy(&(proc->arch.regs.regs), &(current->arch.regs.regs),
		       sizeof(struct user_regs_struct));

		/* make the child return 0 for the syscall */
		proc->arch.regs.regs.eax = 0;

		proc->arch.regs.regs.esp = user_stack;

		/* The current thread will run in 'userspace' */
		proc->context.switch_buf->__ebx = (uint32_t) userspace;
		proc->context.switch_buf->__ebp =
		    (uint32_t) & (proc->arch.regs);
	} else {
		/* For kernel thread */
		proc->context.switch_buf->__ebx = (uint32_t) (tf->fn);
		proc->context.switch_buf->__ebp = (uint32_t) (tf->arg);
	}
	/* All new threads/processes start running from 'kernel_thread_entry'
	 *     for the 'processes' actually means 'monitor threads' to the kernel.
	 */
	proc->context.switch_buf->__eip = (uint32_t) kernel_thread_entry;
	proc->context.switch_buf->__esp = proc->kstack + KSTACKSIZE;

	return 0;

exit_free_stub:
	free_page(kva2page(stub_stack));
exit_free_host:
	kfree(proc->arch.host);
exit:
	return -1;
}