Exemplo n.º 1
0
// 设置新任务的代码和数据段基址、限长并复制页表。
// nr 为新任务号;p 是新任务数据结构的指针。
int copy_mem (int nr, struct task_struct *p)
{
	unsigned long old_data_base, new_data_base, data_limit;
	unsigned long old_code_base, new_code_base, code_limit;

	code_limit = get_limit (0x0f);	// 取局部描述符表中代码段描述符项中段限长。
	data_limit = get_limit (0x17);	// 取局部描述符表中数据段描述符项中段限长。
	old_code_base = get_base (current->ldt[1]);	// 取原代码段基址。
	old_data_base = get_base (current->ldt[2]);	// 取原数据段基址。
	if (old_data_base != old_code_base)	// 0.11 版不支持代码和数据段分立的情况。
		panic ("We don't support separate I&D");
	if (data_limit < code_limit)	// 如果数据段长度 < 代码段长度也不对。
		panic ("Bad data_limit");
	new_data_base = new_code_base = nr * 0x4000000;	// 新基址=任务号*64Mb(任务大小)。
	p->start_code = new_code_base;
	set_base (p->ldt[1], new_code_base);	// 设置代码段描述符中基址域。
	set_base (p->ldt[2], new_data_base);	// 设置数据段描述符中基址域。
	if (copy_page_tables (old_data_base, new_data_base, data_limit))
    {				// 复制代码和数据段。
		free_page_tables (new_data_base, data_limit);	// 如果出错则释放申请的内存。
		return -ENOMEM;
    }
	return 0;
}
Exemplo n.º 2
0
Arquivo: fork.c Projeto: bdmalab/wos
int do_fork(unsigned int esp)
{
	struct task_struct *tsk;
	struct regs *reg = (struct regs *)(esp + 4);
	int pid;

	DbgPrint("cs: 0x%x, eip: 0x%x, ds: 0x%x, eax: 0x%x, ebx: 0x%x\n"
		"ecx: 0x%x, es: 0x%x, fs: 0x%x, eflags: 0x%x\n"
		"ss: 0x%x, esp: 0x%x, orig_eax: 0x%x\n",
		reg->orig_cs, reg->orig_eip, reg->ds, reg->eax, reg->ebx, 
		reg->ecx, reg->es, reg->fs, reg->eflags, 
		reg->ss, reg->esp, reg->error_code);

	pid = get_pid();
	if (pid == -1) {
		printk("Get new pid failed.\n");
		return -1;
	}
	DbgPrint("Get new pid: %d\n", pid);

	tsk = (struct task_struct *)alloc_page(0);
	if (!tsk) {
		DbgPrint("Alloc tsk page failed.\n");
		return -1;
	}
	printk("Alloc task_struct page at: 0x%x\n", tsk);

	*tsk = *current;
	tsk->tss.prev_task_link = 0;
	tsk->tss.esp0 = (unsigned int)tsk + PAGE_SIZE - 4;
	tsk->tss.ss0 = KERNEL_DATA_SEL;
	tsk->tss.esp1 = 0;
	tsk->tss.ss1 = 0;
	tsk->tss.esp2 = 0;
	tsk->tss.ss2 = 0;
	tsk->tss.eip = reg->orig_eip;
	tsk->tss.eflags = reg->eflags;
	tsk->tss.eax = 0;
	tsk->tss.ebx = reg->ebx;
	tsk->tss.ecx = reg->ecx;
	tsk->tss.edx = reg->edx;
	tsk->tss.esp = reg->esp;
	tsk->tss.ebp = reg->ebp;
	tsk->tss.esi = reg->esi;
	tsk->tss.edi = reg->edi;
	tsk->tss.es = reg->es;
	tsk->tss.cs = reg->orig_cs;
	tsk->tss.ss = reg->ss;
	tsk->tss.ds = reg->ds;
	tsk->tss.fs = reg->fs;
	tsk->tss.gs = USER_DATA_SEL;
	tsk->tss.ldt_sel = LDT_SEL(pid);
	tsk->tss.io_map = 0x80000000;

	tsk->pid = pid;
	tsk->tss_sel = TSS_SEL(pid);
	tsk->ldt_sel = LDT_SEL(pid);
	tsk->state = TASK_RUNABLE;
	tsk->counter = DEFAULT_COUNTER;
	tsk->priority = DEFAULT_PRIORITY;

	set_tss_desc(new_gdt, (unsigned int)&(tsk->tss), TSS_LIMIT, TSS_TYPE, TSS_IDX(pid));
	set_ldt_desc(new_gdt, (unsigned int)&(tsk->ldt), LDT_LIMIT, LDT_TYPE, LDT_IDX(pid));

	set_gdt_desc(tsk->ldt, CODE_BASE, USER_CODE_LIMIT, USER_CODE_TYPE, 1);
	set_gdt_desc(tsk->ldt, DATA_BASE, USER_DATA_LIMIT, USER_DATA_TYPE, 2);

	//setup_task_pages(tsk);
	copy_page_tables(tsk);

	list_add_tail(&(tsk->list), &task_list_head);

/*
	printk("cs: 0x%x, eip: 0x%x, ds: 0x%x, eax: 0x%x, ebx: 0x%x\n"
		"ecx: 0x%x, es: 0x%x, fs: 0x%x, eflags: 0x%x\n"
		"ss: 0x%x, esp: 0x%x\n",
		tsk->tss.cs, tsk->tss.eip, tsk->tss.ds, tsk->tss.eax, tsk->tss.ebx, 
		tsk->tss.ecx, tsk->tss.es, tsk->tss.fs, tsk->tss.eflags, 
		tsk->tss.ss, tsk->tss.esp);
*/
	printk("task esp0: 0x%x, esp: 0x%x\n", tsk->tss.esp0, tsk->tss.esp);

	return pid;
}
Exemplo n.º 3
0
/*
 * Setup then Resume from the hibernate image using swsusp_arch_suspend_exit().
 *
 * Memory allocated by get_safe_page() will be dealt with by the hibernate code,
 * we don't need to free it here.
 */
int swsusp_arch_resume(void)
{
	int rc = 0;
	void *zero_page;
	size_t exit_size;
	pgd_t *tmp_pg_dir;
	phys_addr_t phys_hibernate_exit;
	void __noreturn (*hibernate_exit)(phys_addr_t, phys_addr_t, void *,
					  void *, phys_addr_t, phys_addr_t);

	/*
	 * Restoring the memory image will overwrite the ttbr1 page tables.
	 * Create a second copy of just the linear map, and use this when
	 * restoring.
	 */
	tmp_pg_dir = (pgd_t *)get_safe_page(GFP_ATOMIC);
	if (!tmp_pg_dir) {
		pr_err("Failed to allocate memory for temporary page tables.\n");
		rc = -ENOMEM;
		goto out;
	}
	rc = copy_page_tables(tmp_pg_dir, PAGE_OFFSET, 0);
	if (rc)
		goto out;

	/*
	 * We need a zero page that is zero before & after resume in order to
	 * to break before make on the ttbr1 page tables.
	 */
	zero_page = (void *)get_safe_page(GFP_ATOMIC);
	if (!zero_page) {
		pr_err("Failed to allocate zero page.\n");
		rc = -ENOMEM;
		goto out;
	}

	/*
	 * Locate the exit code in the bottom-but-one page, so that *NULL
	 * still has disastrous affects.
	 */
	hibernate_exit = (void *)PAGE_SIZE;
	exit_size = __hibernate_exit_text_end - __hibernate_exit_text_start;
	/*
	 * Copy swsusp_arch_suspend_exit() to a safe page. This will generate
	 * a new set of ttbr0 page tables and load them.
	 */
	rc = create_safe_exec_page(__hibernate_exit_text_start, exit_size,
				   (unsigned long)hibernate_exit,
				   &phys_hibernate_exit,
				   (void *)get_safe_page, GFP_ATOMIC);
	if (rc) {
		pr_err("Failed to create safe executable page for hibernate_exit code.\n");
		goto out;
	}

	/*
	 * The hibernate exit text contains a set of el2 vectors, that will
	 * be executed at el2 with the mmu off in order to reload hyp-stub.
	 */
	__flush_dcache_area(hibernate_exit, exit_size);

	/*
	 * KASLR will cause the el2 vectors to be in a different location in
	 * the resumed kernel. Load hibernate's temporary copy into el2.
	 *
	 * We can skip this step if we booted at EL1, or are running with VHE.
	 */
	if (el2_reset_needed()) {
		phys_addr_t el2_vectors = phys_hibernate_exit;  /* base */
		el2_vectors += hibernate_el2_vectors -
			       __hibernate_exit_text_start;     /* offset */

		__hyp_set_vectors(el2_vectors);
	}

	hibernate_exit(virt_to_phys(tmp_pg_dir), resume_hdr.ttbr1_el1,
		       resume_hdr.reenter_kernel, restore_pblist,
		       resume_hdr.__hyp_stub_vectors, virt_to_phys(zero_page));

out:
	return rc;
}