static void fix_processor_context(void)
{
	int cpu = smp_processor_id();
	struct tss_struct *t = &per_cpu(init_tss, cpu);

	set_tss_desc(cpu, t);	/*
				 * This just modifies memory; should not be
				 * necessary. But... This is necessary, because
				 * 386 hardware has concept of busy TSS or some
				 * similar stupidity.
				 */

	load_TR_desc();				/* This does ltr */
	load_LDT(&current->active_mm->context);	/* This does lldt */

	/*
	 * Now maybe reload the debug registers
	 */
	if (current->thread.debugreg7) {
		set_debugreg(current->thread.debugreg0, 0);
		set_debugreg(current->thread.debugreg1, 1);
		set_debugreg(current->thread.debugreg2, 2);
		set_debugreg(current->thread.debugreg3, 3);
		/* no 4 and 5 */
		set_debugreg(current->thread.debugreg6, 6);
		set_debugreg(current->thread.debugreg7, 7);
	}

}
Beispiel #2
0
/*
 * 复制进程结构。NOTE! 其参数须与sys_fork()同步。其他说明参见sys_fork().
 */
void copy_process(int nr, long gs, long fs, long es, long ds, 
				long edi, long esi, long ebp, long edx, long ecx, long ebx,
				long eip, long cs, long eflags, long esp, long ss)
{
	if(nr<0 || nr>=NR_PROC)
		panic("copy_process: nr of process is too small or big.");
	if(0 == nr)
		panic("copy_process: trying to alter the proc_struct of process 0.");

	struct proc_struct * p = proc[nr];

	/* 复制进程结构 */
	memcpy(p, current, sizeof(struct proc_struct));
	/* 调整新进程结构 */
	p->state = UNINTERRUPTIBLE;
	p->counter = p->priority;
	p->pid = last_pid;
	p->fpid = current->pid;
	p->utime = 0;
	p->ktime = 0;
	p->cutime = 0;
	p->cktime = 0;
	/* NOTE! 子进程与父进程的用户态虚拟地址空间相同,都是3GB-4GB,故无需调整 */
	/* 调整新进程tss结构 */
	p->tss.back_link = NULL;
	p->tss.esp0 = (unsigned long)p + PAGE_SIZE;
	p->tss.eip = eip;
	p->tss.eflags = eflags;
	p->tss.eax = 0;		/* NOTE! fork调用的子进程返回值为0 */
	p->tss.ebx = ebx;
	p->tss.ecx = ecx;
	p->tss.edx = edx;
	p->tss.esp = esp;
	p->tss.ebp = ebp;
	p->tss.esi = esi;
	p->tss.edi = edi;
	p->tss.es = es & 0xffff;	/* 低16位有效 */
	p->tss.cs = cs & 0xffff;
	p->tss.ss = ss & 0xffff;
	p->tss.ds = ds & 0xffff;
	p->tss.fs = fs & 0xffff;
	p->tss.gs = gs & 0xffff;
	p->tss.ldt = _LDT(nr);
	p->tss.trace_bitmap = 0x80000000;

	share_page_dir(&(p->tss.cr3));
	/*
	 * IDT、TSS段均属于系统段,其描述符均是线性地址,我们将其全部放
	 * 入内核地址空间。同时也要注意:下面一定要强制类型转换,否则,
	 * ldt的地址加上n个ldt的大小了,关于这一点,要是迷糊的话,翻翻
	 * C语言基本语法,好好理解下吧 :-)
	 */
	set_ldt_desc(nr, V_KERNEL_ZONE_START+(unsigned long)&(p->ldt));
	set_tss_desc(nr, V_KERNEL_ZONE_START+(unsigned long)&(p->tss));
}
Beispiel #3
0
__init void km_arch_trim()
{
	unsigned long i;
	
	unsigned long *p = hal_x86_get_init_pgtable();
	
	/*
	 Kernel part in 4mb page;
		1,低端。
		2,高端
	*/
	for(i = 0; i < HAL_GET_BASIC_KADDRESS(0) / 0x400000; i++)
		p[i] = 0;																//Mask as invalid;
	for(i = (HAL_GET_BASIC_KADDRESS(0) + CONFIG_HAL_KERNEL_MEM_LEN) / 0x400000; i < 1024; i++)
		p[i] = 0;																//Mask as invalid;
	
	write_cr3((unsigned long)hal_x86_get_init_pgtable() - HAL_GET_BASIC_KADDRESS(0));

	/*
	 load tr
	 */
	set_tss_desc(0, &init_tss);
	load_TR_desc();
	
	/*
	 打开WP功能
	 */
	do {
		unsigned long i = read_cr0();
		//if(open)
		i |= 1 << 16;
		//else
		//	i &= ~(1 << 16);
		write_cr0(i);
	} while (0);
}
Beispiel #4
0
bool init_tss(void)
{
    uintptr_t stack = early_malloc(1);
    if (stack == 0)
    {
        return false;
    }
    memset((void *)stack, 0, 0x1000);

    tss.rsp0 = stack + 0x1000;

    stack = early_malloc(1);
    if (stack == 0)
    {
        return false;
    }
    memset((void *)stack, 0, 0x1000);
    tss.ist[0] = stack + 0x1000;

    set_tss_desc((uintptr_t)&tss);

    __asm__ volatile("ltr %w0" ::"r"(TASK_STATE_SEGMENT));
    return true;
}
Beispiel #5
0
}

void sched_init(void)
{
	/* 初始化进程控制块指针数组 */
	/* nothing.在bss段,已被清零 */
	
	proc[0] = &init_proc.proc;
	current = proc[0];
	ticks = 0;

	/* 设置进程0的ldt和tss描述符 */
	set_ldt_desc(0, V_KERNEL_ZONE_START+(unsigned long)&(proc[0]->ldt));
	set_tss_desc(0, V_KERNEL_ZONE_START+(unsigned long)&(proc[0]->tss));
	/* 装载进程0的ldt和tss选择符,第一次需我们来加载 */
	lldt(_LDT(0));
	ltr(_TSS(0));
	/* 挂载时钟中断处理程序 */
	set_idt(INT_R0, timer_int, NR_TIMER_INT);
	/* 设置8253定时器芯片 */
	out_b(0x43, 0x36);
	out_b(0x40, (LATCH & 0xff));
	out_b(0x40, ((LATCH>>8) & 0xff));
	/* 挂载系统调用处理程序 */
Beispiel #6
0
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;
}
Beispiel #7
0
int sys_creat_task(unsigned int eip)
{
        struct task_struct *tsk;
        int pid;

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

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

	*tsk = *current;
        tsk->tss.prev_task_link = 0;
        tsk->tss.esp0 = (unsigned int)tsk + PAGE_SIZE;
        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 = eip;
        tsk->tss.eflags = 0x200;
        tsk->tss.eax = 0;
        tsk->tss.ebx = 0;
        tsk->tss.ecx = 0;
        tsk->tss.edx = 0;
        tsk->tss.esp = (unsigned int)alloc_page(0) + PAGE_SIZE;
	DbgPrint("Alloc tsk ring3 stack at 0x%x\n", tsk->tss.esp - PAGE_SIZE);
        tsk->tss.ebp = 0;
        tsk->tss.esi = 0;
        tsk->tss.edi = 0;
        tsk->tss.es = USER_DATA_SEL;
        tsk->tss.cs = USER_CODE_SEL;
        tsk->tss.ss = USER_DATA_SEL;
        tsk->tss.ds = USER_DATA_SEL;
        tsk->tss.fs = USER_DATA_SEL;
        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);

	return 0;
}
Beispiel #8
0
// 复制进程。
int copy_process (int nr, long ebp, long edi, long esi, long gs, long none,
				  long ebx, long ecx, long edx,
				  long fs, long es, long ds,
				  long eip, long cs, long eflags, long esp, long ss)
{
	struct task_struct *p;
	int i;
	struct file *f;
	struct i387_struct *p_i387;

	p = (struct task_struct *) get_free_page ();	// 为新任务数据结构分配内存。
	if (!p)			// 如果内存分配出错,则返回出错码并退出。
		return -EAGAIN;
	task[nr] = p;			// 将新任务结构指针放入任务数组中。
// 其中nr 为任务号,由前面find_empty_process()返回。
	*p = *current;		/* NOTE! this doesn't copy the supervisor stack */
/* 注意!这样做不会复制超级用户的堆栈 (只复制当前进程内容)。*/ 
	p->state = TASK_UNINTERRUPTIBLE;	// 将新进程的状态先置为不可中断等待状态。
	p->pid = last_pid;		// 新进程号。由前面调用find_empty_process()得到。
	p->father = current->pid;	// 设置父进程号。
	p->counter = p->priority;
	p->signal = 0;		// 信号位图置0。
	p->alarm = 0;
	p->leader = 0;		/* process leadership doesn't inherit */
/* 进程的领导权是不能继承的 */
	p->utime = p->stime = 0;	// 初始化用户态时间和核心态时间。
	p->cutime = p->cstime = 0;	// 初始化子进程用户态和核心态时间。
	p->start_time = jiffies;	// 当前滴答数时间。
// 以下设置任务状态段TSS 所需的数据(参见列表后说明)。
	p->tss.back_link = 0;
	p->tss.esp0 = PAGE_SIZE + (long) p;	// 堆栈指针(由于是给任务结构p 分配了1 页
// 新内存,所以此时esp0 正好指向该页顶端)。
	p->tss.ss0 = 0x10;		// 堆栈段选择符(内核数据段)[??]。
	p->tss.eip = eip;		// 指令代码指针。
	p->tss.eflags = eflags;	// 标志寄存器。
	p->tss.eax = 0;
	p->tss.ecx = ecx;
	p->tss.edx = edx;
	p->tss.ebx = ebx;
	p->tss.esp = esp;
	p->tss.ebp = ebp;
	p->tss.esi = esi;
	p->tss.edi = edi;
	p->tss.es = es & 0xffff;	// 段寄存器仅16 位有效。
	p->tss.cs = cs & 0xffff;
	p->tss.ss = ss & 0xffff;
	p->tss.ds = ds & 0xffff;
	p->tss.fs = fs & 0xffff;
	p->tss.gs = gs & 0xffff;
	p->tss.ldt = _LDT (nr);	// 该新任务nr 的局部描述符表选择符(LDT 的描述符在GDT 中)。
	p->tss.trace_bitmap = 0x80000000;
// 如果当前任务使用了协处理器,就保存其上下文。
	p_i387 = &p->tss.i387;
	if (last_task_used_math == current)
	_asm{
		mov ebx, p_i387
		clts
		fnsave [p_i387]
	}
//    __asm__ ("clts ; fnsave %0"::"m" (p->tss.i387));
// 设置新任务的代码和数据段基址、限长并复制页表。如果出错(返回值不是0),则复位任务数组中
// 相应项并释放为该新任务分配的内存页。
	if (copy_mem (nr, p))
	{				// 返回不为0 表示出错。
		task[nr] = NULL;
		free_page ((long) p);
		return -EAGAIN;
	}
// 如果父进程中有文件是打开的,则将对应文件的打开次数增1。
	for (i = 0; i < NR_OPEN; i++)
		if (f = p->filp[i])
			f->f_count++;
// 将当前进程(父进程)的pwd, root 和executable 引用次数均增1。
	if (current->pwd)
		current->pwd->i_count++;
	if (current->root)
		current->root->i_count++;
	if (current->executable)
		current->executable->i_count++;
// 在GDT 中设置新任务的TSS 和LDT 描述符项,数据从task 结构中取。
// 在任务切换时,任务寄存器tr 由CPU 自动加载。
	set_tss_desc (gdt + (nr << 1) + FIRST_TSS_ENTRY, &(p->tss));
	set_ldt_desc (gdt + (nr << 1) + FIRST_LDT_ENTRY, &(p->ldt));
	p->state = TASK_RUNNING;	/* do this last, just in case */
/* 最后再将新任务设置成可运行状态,以防万一 */
	return last_pid;		// 返回新进程号(与任务号是不同的)。
}
Beispiel #9
0
asmlinkage int sys_fork(struct pt_regs regs) {
    struct task_struct *tsk;
    int nr;
    long flags;
    unsigned long used_memory = 0;

    save_flags(flags); cli();

    // find a free entry in the process table
    nr = find_empty_process();

    if (nr < 0) {
        printk("fork: pids not available at the moment!\n");
        goto fork_no_entry;
    }

    // allocate a page for the process descriptor
    tsk = (struct task_struct *) get_free_page();

    if (!tsk) {
        goto fork_no_mem;
    }

    // copy descriptor: pid and counter will contain different values for
    // father and child
    *tsk = *current;
    tsk->pid = nr;
    tsk->counter = tsk->priority;

    // if we are forking the idle process, we assume its child will call an
    // exec just after the fork. In this case we do not duplicate code/data.
    // If we are forking whatever process, so it is necessary allocate a
    // page for it (containing code and data) e setup its LDT to the new
    // address space
    if (current->pid != 0) {
        // allocate memory for code/data
        tsk->mem = (char *) get_free_pages(current->used_pages);

        if (!tsk->mem) {
            goto fork_data_no_mem;
        }

        // total memory used by current process
        used_memory = current->used_pages * PAGE_SIZE;

        // copy process data
        memcpy(tsk->mem, current->mem, used_memory);

        // set up LDT
        set_code_desc(&(tsk->ldt[1]), (u_long) tsk->mem, used_memory);
        set_data_desc(&(tsk->ldt[2]), (u_long) tsk->mem, used_memory);
    }

    // setup TSS
    tsk->tss.back_link = 0;
    tsk->tss.esp0 = PAGE_SIZE + (unsigned long) tsk;
    tsk->tss.ss0 = KERNEL_DS;

    tsk->tss.esp1 = 0;
    tsk->tss.ss1 = 0;
    tsk->tss.esp2 = 0;
    tsk->tss.ss2 = 0;
    tsk->tss.cr3 = 0;

    tsk->tss.eip = regs.eip;
    tsk->tss.eflags = regs.eflags;

    tsk->tss.eax = 0;
    tsk->tss.ecx = regs.ecx;
    tsk->tss.edx = regs.edx;
    tsk->tss.ebx = regs.ebx;

    tsk->tss.esp = regs.esp;
    tsk->tss.ebp = regs.ebp;
    tsk->tss.esi = regs.esi;
    tsk->tss.edi = regs.edi;

    tsk->tss.es = regs.xes & 0xffff;
    tsk->tss.cs = regs.xcs & 0xffff;
    tsk->tss.ss = regs.xss & 0xffff;
    tsk->tss.ds = regs.xds & 0xffff;

    // it is not necessary set FS and GS

    tsk->tss.ldt = _LDT(nr);
    tsk->tss.trace = 0;
    tsk->tss.bitmap = 0xDFFF;
    tsk->tss.tr = _TSS(nr);

    set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY, &(tsk->tss));
    set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY, &(tsk->ldt), 3);
    task[nr] = tsk;

    restore_flags(flags);
    return nr;

fork_data_no_mem:
    free_page(tsk);
fork_no_mem:
    restore_flags(flags);
    return -ENOMEM;
fork_no_entry:
    restore_flags(flags);
    return -EAGAIN;
}