Пример #1
0
void set_tss_gate(int nr, long base, int dpl, long limit) {
    char *addr = ((char*)gdt) + _TSS(nr);
    *(short*)addr = limit;
    *(short*)(addr + 2) = base & 0xffff;
    *(addr + 4) = (base >> 16) & 0xff;
    *(addr + 5) = 0x80 + ((dpl & 0x03) << 5) + 0x09;
    *(addr + 6) = 0x00;
    *(addr + 7) = (base >> 24) & 0xff;
}
Пример #2
0
void init_schedule() {
    current = (struct task_t *)0;
    tasks_count = 0;
    register_task(0);
    tasks[0].t_counter = 0;
    tasks[0].t_priority = 0;
    current = &tasks[0];
    asm volatile ("pushfl; andl $0xffffbfff, (%esp); popfl");   /* clear NT */
    asm volatile ("ltr %%ax"::"a"(_TSS(0)));
    asm volatile ("lldt %%ax"::"a"(_LDT(0)));
}
Пример #3
0
static void switch_to(int next) {
    struct {long a,b;} tmp;
    if (&tasks[next] == current) {
        return ;
    }
    if (current) {
        current->t_state = TASK_READY;
    }
    current = &tasks[next];
    current->t_state = TASK_RUNNING;
    tmp.b = _TSS(next);
    asm volatile (
        "ljmp %0"
        ::"m"(*&tmp.a)
    );
}
Пример #4
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));
	/* 挂载系统调用处理程序 */
Пример #5
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;
}