/*======================================================= init_prot() ========================================================*/ PUBLIC void init_prot() { init_8259A(); //初始化异常 (中断门 没有陷阱门) init_idt_desc( INT_VECTOR_DIVIDE, DA_386IGate, divide_error, PRIVILEGE_KRNL); init_idt_desc( INT_VECTOR_DEBUG, DA_386IGate, single_step_exception, PRIVILEGE_KRNL); init_idt_desc( INT_VECTOR_NMI, DA_386IGate, nmi, PRIVILEGE_KRNL); init_idt_desc( INT_VECTOR_BREAKPOINT, DA_386IGate, breakpoint_exception, PRIVILEGE_USER); init_idt_desc( INT_VECTOR_OVERFLOW, DA_386IGate , overflow, PRIVILEGE_USER); init_idt_desc( INT_VECTOR_BOUNDS, DA_386IGate, bounds_check, PRIVILEGE_KRNL); init_idt_desc( INT_VECTOR_INVAL_OP, DA_386IGate, inval_opcode, PRIVILEGE_KRNL); init_idt_desc( INT_VECTOR_COPROC_NOT, DA_386IGate, copr_not_available, PRIVILEGE_KRNL); init_idt_desc( INT_VECTOR_DOUBLE_FAULT, DA_386IGate, double_fault, PRIVILEGE_KRNL); init_idt_desc( INT_VECTOR_COPROC_SEG, DA_386IGate, copr_seg_overrun, PRIVILEGE_KRNL); init_idt_desc( INT_VECTOR_INVAL_TSS, DA_386IGate, inval_tss, PRIVILEGE_KRNL); init_idt_desc( INT_VECTOR_SEG_NOT, DA_386IGate, segment_not_present, PRIVILEGE_KRNL); init_idt_desc( INT_VECTOR_STACK_FAULT, DA_386IGate, stack_exception, PRIVILEGE_KRNL); init_idt_desc( INT_VECTOR_PROTECTION, DA_386IGate, general_protection, PRIVILEGE_KRNL); init_idt_desc( INT_VECTOR_PAGE_FAULT, DA_386IGate, page_fault, PRIVILEGE_KRNL); init_idt_desc( INT_VECTOR_COPROC_ERR, DA_386IGate, copr_error, PRIVILEGE_KRNL); /*初始化中断*/ init_idt_desc(INT_VECTOR_IRQ0 + 0, DA_386IGate , hint00 , PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 1, DA_386IGate , hint01 , PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 2, DA_386IGate , hint02 , PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 3, DA_386IGate , hint03 , PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 4, DA_386IGate , hint04 , PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 5, DA_386IGate , hint05 , PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 6, DA_386IGate , hint06 , PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 7, DA_386IGate , hint07 , PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 0, DA_386IGate , hint08 , PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 1, DA_386IGate , hint09 , PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 2, DA_386IGate , hint10 , PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 3, DA_386IGate , hint11 , PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 4, DA_386IGate , hint12 , PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 5, DA_386IGate , hint13 , PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 6, DA_386IGate , hint14 , PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 7, DA_386IGate , hint15 , PRIVILEGE_KRNL); /* 填充 GDT 中的 TSS */ memset(&tss,0,sizeof(tss)); tss.ss0 = SELECTOR_KERNEL_DS; init_descriptor(&gdt[INDEX_TSS], vir2phys(seg2phys(SELECTOR_KERNEL_DS),&tss), sizeof(tss) - 1, DA_386TSS); tss.iobase = sizeof(tss); /*没有I/O许可位图*/ /*填充 GDT 中进程的 LDT的描述符 */ init_descriptor(&gdt[INDEX_LDT_FIRST], vir2phys(seg2phys(SELECTOR_KERNEL_DS),proc_table[0].ldts), LDT_SIZE * sizeof(DESCRIPTOR) - 1, DA_LDT); }
phys_bytes pg_load() { phys_bytes phpagedir = vir2phys(pagedir); refresh_tlb(); write_ttbr0(phpagedir); return phpagedir; }
PUBLIC void arch_get_aout_headers(const int i, struct exec *h) { /* The bootstrap loader created an array of the a.out headers at * absolute address 'aout'. Get one element to h. */ phys_copy(aout + i * A_MINHDR, vir2phys(h), (phys_bytes) A_MINHDR); }
PRIVATE void cons_setc(const int pos, const int c) { char ch; ch= c; phys_copy(vir2phys((vir_bytes)&ch), COLOR_BASE+(20*80+pos)*2, 1); }
PUBLIC int arch_set_params(char *params, int size) { if(size > params_size) return E2BIG; phys_copy(vir2phys(params), seg2phys(mon_ds) + params_offset, size); return OK; }
PUBLIC int arch_get_params(char *params, int maxsize) { phys_copy(seg2phys(mon_ds) + params_offset, vir2phys(params), MIN(maxsize, params_size)); params[maxsize-1] = '\0'; return OK; }
static u32_t phys_get32(phys_bytes addr) { const u32_t v; int r; if(!vm_running) { phys_copy(addr, vir2phys(&v), sizeof(v)); return v; } if((r=lin_lin_copy(NULL, addr, proc_addr(SYSTEM), vir2phys(&v), sizeof(v))) != OK) { panic("lin_lin_copy for phys_get32 failed: %d", r); } return v; }
/* ** Name: void dp_pio16_user2nic(dpeth_t *dep, int pageno, int pktsize) ** Function: Copies a packet from user area to board (Prog. I/O, 16bits). */ static void dp_pio16_user2nic(dpeth_t *dep, int pageno, int pktsize) { u8_t two_bytes[2]; phys_bytes phys_user, phys_2bytes = vir2phys(two_bytes); vir_bytes ecount = (pktsize + 1) & NOT(0x0001); int bytes, ix = 0, odd_byte = 0; iovec_dat_t *iovp = &dep->de_write_iovec; outb_reg0(dep, DP_ISR, ISR_RDC); dp_read_setup(dep, ecount, pageno * DP_PAGESIZE); do { bytes = iovp->iod_iovec[ix].iov_size; if (bytes > pktsize) bytes = pktsize; phys_user = numap(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_addr, bytes); if (!phys_user) panic(UmapErrMsg); if (odd_byte) { phys_copy(phys_user, phys_2bytes + 1, (phys_bytes) 1); out_word(dep->de_data_port, *(u16_t *)two_bytes); pktsize--; bytes--; phys_user++; odd_byte = 0; if (!bytes) continue; } ecount = bytes & NOT(0x0001); if (ecount != 0) { phys_outsw(dep->de_data_port, phys_user, ecount); pktsize -= ecount; bytes -= ecount; phys_user += ecount; } if (bytes) { phys_copy(phys_user, phys_2bytes, (phys_bytes) 1); pktsize--; bytes--; phys_user++; odd_byte = 1; } if (++ix >= IOVEC_NR) { /* Next buffer of I/O vector */ dp_next_iovec(iovp); ix = 0; } } while (bytes > 0); if (odd_byte) out_word(dep->de_data_port, *(u16_t *) two_bytes); for (ix = 0; ix < 100; ix++) { if (inb_reg0(dep, DP_ISR) & ISR_RDC) break; } if (ix == 100) { panic(RdmaErrMsg); } return; }
/* ** Name: void dp_pio16_nic2user(dpeth_t *dep, int pageno, int pktsize) ** Function: Copies a packet from board to user area (Prog. I/O, 16bits). */ static void dp_pio16_nic2user(dpeth_t * dep, int nic_addr, int count) { phys_bytes phys_user; vir_bytes ecount; int bytes, i; u8_t two_bytes[2]; phys_bytes phys_2bytes; int odd_byte; ecount = (count + 1) & ~1; phys_2bytes = vir2phys(two_bytes); odd_byte = 0; dp_read_setup(dep, ecount, nic_addr); i = 0; while (count > 0) { if (i >= IOVEC_NR) { dp_next_iovec(iovp); i = 0; continue; } bytes = iovp->iod_iovec[i].iov_size; if (bytes > count) bytes = count; phys_user = numap(iovp->iod_proc_nr, iovp->iod_iovec[i].iov_addr, bytes); if (!phys_user) panic(UmapErrMsg); if (odd_byte) { phys_copy(phys_2bytes + 1, phys_user, (phys_bytes) 1); count--; bytes--; phys_user++; odd_byte = 0; if (!bytes) continue; } ecount = bytes & ~1; if (ecount != 0) { phys_insw(dep->de_data_port, phys_user, ecount); count -= ecount; bytes -= ecount; phys_user += ecount; } if (bytes) { *(u16_t *) two_bytes = in_word(dep->de_data_port); phys_copy(phys_2bytes, phys_user, (phys_bytes) 1); count--; bytes--; phys_user++; odd_byte = 1; } } return; }
u32_t *alloc_pagetable(phys_bytes *ph) { u32_t *ret; #define PG_PAGETABLES 24 static u32_t pagetables[PG_PAGETABLES][256] __aligned(1024); static int pt_inuse = 0; if(pt_inuse >= PG_PAGETABLES) panic("no more pagetables"); assert(sizeof(pagetables[pt_inuse]) == 1024); ret = pagetables[pt_inuse++]; *ph = vir2phys(ret); return ret; }
/*===========================================================================* * QueueMess * *===========================================================================*/ PRIVATE int QueueMess(endpoint_t ep, vir_bytes msg_lin, struct proc *dst) { int k; phys_bytes addr; NOREC_ENTER(queuemess); /* Queue a message from the src process (in memory) to the dst * process (using dst process table entry). Do actual copy to * kernel here; it's an error if the copy fails into kernel. */ vmassert(!(dst->p_misc_flags & MF_DELIVERMSG)); vmassert(dst->p_delivermsg_lin); vmassert(isokendpt(ep, &k)); #if 0 if(INMEMORY(dst)) { PHYS_COPY_CATCH(msg_lin, dst->p_delivermsg_lin, sizeof(message), addr); if(!addr) { PHYS_COPY_CATCH(vir2phys(&ep), dst->p_delivermsg_lin, sizeof(ep), addr); if(!addr) { NOREC_RETURN(queuemess, OK); } } } #endif PHYS_COPY_CATCH(msg_lin, vir2phys(&dst->p_delivermsg), sizeof(message), addr); if(addr) { NOREC_RETURN(queuemess, EFAULT); } dst->p_delivermsg.m_source = ep; dst->p_misc_flags |= MF_DELIVERMSG; NOREC_RETURN(queuemess, OK); }
/*===========================================================================* * main * *===========================================================================*/ PUBLIC void main() { /* Start the ball rolling. */ struct boot_image *ip; /* boot image pointer */ register struct proc *rp; /* process pointer */ register struct priv *sp; /* privilege structure pointer */ register int i, s; int hdrindex; /* index to array of a.out headers */ phys_clicks text_base; vir_clicks text_clicks, data_clicks; reg_t ktsb; /* kernel task stack base */ struct exec e_hdr; /* for a copy of an a.out header */ /* Initialize the interrupt controller. */ intr_init(1); /* Clear the process table. Anounce each slot as empty and set up mappings * for proc_addr() and proc_nr() macros. Do the same for the table with * privilege structures for the system processes. */ for (rp = BEG_PROC_ADDR, i = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++i) { rp->p_rts_flags = SLOT_FREE; /* initialize free slot */ rp->p_nr = i; /* proc number from ptr */ (pproc_addr + NR_TASKS)[i] = rp; /* proc ptr from number */ } for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) { sp->s_proc_nr = NONE; /* initialize as free */ sp->s_id = i; /* priv structure index */ ppriv_addr[i] = sp; /* priv ptr from number */ } /* Set up proc table entries for processes in boot image. The stacks of the * kernel tasks are initialized to an array in data space. The stacks * of the servers have been added to the data segment by the monitor, so * the stack pointer is set to the end of the data segment. All the * processes are in low memory on the 8086. On the 386 only the kernel * is in low memory, the rest is loaded in extended memory. */ /* Task stacks. */ ktsb = (reg_t) t_stack; for (i=0; i < NR_BOOT_PROCS; ++i) { ip = &image[i]; /* process' attributes */ rp = proc_addr(ip->proc_nr); /* get process pointer */ rp->p_max_priority = ip->priority; /* max scheduling priority */ rp->p_priority = ip->priority; /* current priority */ rp->p_quantum_size = ip->quantum; /* quantum size in ticks */ rp->p_ticks_left = ip->quantum; /* current credit */ strncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set process name */ (void) get_priv(rp, (ip->flags & SYS_PROC)); /* assign structure */ priv(rp)->s_flags = ip->flags; /* process flags */ priv(rp)->s_trap_mask = ip->trap_mask; /* allowed traps */ priv(rp)->s_call_mask = ip->call_mask; /* kernel call mask */ priv(rp)->s_ipc_to.chunk[0] = ip->ipc_to; /* restrict targets */ if (iskerneln(proc_nr(rp))) { /* part of the kernel? */ if (ip->stksize > 0) { /* HARDWARE stack size is 0 */ rp->p_priv->s_stack_guard = (reg_t *) ktsb; *rp->p_priv->s_stack_guard = STACK_GUARD; } ktsb += ip->stksize; /* point to high end of stack */ rp->p_reg.sp = ktsb; /* this task's initial stack ptr */ text_base = kinfo.code_base >> CLICK_SHIFT; /* processes that are in the kernel */ hdrindex = 0; /* all use the first a.out header */ } else { hdrindex = 1 + i-NR_TASKS; /* servers, drivers, INIT */ } /* The bootstrap loader created an array of the a.out headers at * absolute address 'aout'. Get one element to e_hdr. */ phys_copy(aout + hdrindex * A_MINHDR, vir2phys(&e_hdr), (phys_bytes) A_MINHDR); /* Convert addresses to clicks and build process memory map */ text_base = e_hdr.a_syms >> CLICK_SHIFT; text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT; if (!(e_hdr.a_flags & A_SEP)) text_clicks = 0; /* common I&D */ data_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT; rp->p_memmap[T].mem_phys = text_base; rp->p_memmap[T].mem_len = text_clicks; rp->p_memmap[D].mem_phys = text_base + text_clicks; rp->p_memmap[D].mem_len = data_clicks; rp->p_memmap[S].mem_phys = text_base + text_clicks + data_clicks; rp->p_memmap[S].mem_vir = data_clicks; /* empty - stack is in data */ /* Set initial register values. The processor status word for tasks * is different from that of other processes because tasks can * access I/O; this is not allowed to less-privileged processes */ rp->p_reg.pc = (reg_t) ip->initial_pc; rp->p_reg.psw = (iskernelp(rp)) ? INIT_TASK_PSW : INIT_PSW; /* Initialize the server stack pointer. Take it down one word * to give crtso.s something to use as "argc". */ if (isusern(proc_nr(rp))) { /* user-space process? */ rp->p_reg.sp = (rp->p_memmap[S].mem_vir + rp->p_memmap[S].mem_len) << CLICK_SHIFT; rp->p_reg.sp -= sizeof(reg_t); } /* Set ready. The HARDWARE task is never ready. */ if (rp->p_nr != HARDWARE) { rp->p_rts_flags = 0; /* runnable if no flags */ lock_enqueue(rp); /* add to scheduling queues */ } else { rp->p_rts_flags = NO_MAP; /* prevent from running */ } /* Code and data segments must be allocated in protected mode. */ alloc_segments(rp); }
PUBLIC __dead void arch_shutdown(int how) { u16_t magic; vm_stop(); /* Mask all interrupts, including the clock. */ outb( INT_CTLMASK, ~0); if(minix_panicing) { unsigned char unused_ch; /* We're panicing? Then retrieve and decode currently * loaded segment selectors. */ printseg("cs: ", 1, get_cpulocal_var(proc_ptr), read_cs()); printseg("ds: ", 0, get_cpulocal_var(proc_ptr), read_ds()); if(read_ds() != read_ss()) { printseg("ss: ", 0, NULL, read_ss()); } /* Printing is done synchronously over serial. */ if (do_serial_debug) reset(); /* Print accumulated diagnostics buffer and reset. */ mb_cls(); mb_print("Minix panic. System diagnostics buffer:\n\n"); mb_print(kmess_buf); mb_print("\nSystem has panicked, press any key to reboot"); while (!mb_read_char(&unused_ch)) ; reset(); } #if USE_BOOTPARAM if (how == RBT_DEFAULT) { how = mon_return ? RBT_HALT : RBT_RESET; } if(how != RBT_RESET) { /* return to boot monitor */ outb( INT_CTLMASK, 0); outb( INT2_CTLMASK, 0); /* Return to the boot monitor. Set * the program if not already done. */ if (how != RBT_MONITOR) arch_set_params("", 1); if (mon_return) arch_monitor(); /* monitor command with no monitor: reset or poweroff * depending on the parameters */ if (how == RBT_MONITOR) { how = RBT_RESET; } } switch (how) { case RBT_REBOOT: case RBT_RESET: /* Reset the system by forcing a processor shutdown. * First stop the BIOS memory test by setting a soft * reset flag. */ magic = STOP_MEM_CHECK; phys_copy(vir2phys(&magic), SOFT_RESET_FLAG_ADDR, SOFT_RESET_FLAG_SIZE); reset(); NOT_REACHABLE; case RBT_HALT: /* Poweroff without boot monitor */ arch_bios_poweroff(); NOT_REACHABLE; case RBT_PANIC: /* Allow user to read panic message */ for (; ; ) halt_cpu(); NOT_REACHABLE; default: /* Not possible! trigger panic */ assert(how != RBT_MONITOR); assert(how != RBT_DEFAULT); assert(how < RBT_INVALID); panic("unexpected value for how: %d", how); NOT_REACHABLE; } #else /* !USE_BOOTPARAM */ /* Poweroff without boot monitor */ arch_bios_poweroff(); #endif NOT_REACHABLE; }
phys_bytes pg_load() { phys_bytes phpagedir = vir2phys(pagedir); write_cr3(phpagedir); return phpagedir; }
PUBLIC __dead void arch_shutdown(int how) { static char mybuffer[sizeof(params_buffer)]; u16_t magic; vm_stop(); /* Mask all interrupts, including the clock. */ outb( INT_CTLMASK, ~0); if(minix_panicing) { /* We're panicing? Then retrieve and decode currently * loaded segment selectors. */ printseg("cs: ", 1, proc_ptr, read_cs()); printseg("ds: ", 0, proc_ptr, read_ds()); if(read_ds() != read_ss()) { printseg("ss: ", 0, NULL, read_ss()); } } if (how == RBT_DEFAULT) { how = mon_return ? RBT_HALT : RBT_RESET; } if(how != RBT_RESET) { /* return to boot monitor */ outb( INT_CTLMASK, 0); outb( INT2_CTLMASK, 0); /* Return to the boot monitor. Set * the program if not already done. */ if (how != RBT_MONITOR) arch_set_params("", 1); if(minix_panicing) { int source, dest; const char *lead = "echo \\n*** kernel messages:\\n"; const int leadlen = strlen(lead); strcpy(mybuffer, lead); #define DECSOURCE source = (source - 1 + _KMESS_BUF_SIZE) % _KMESS_BUF_SIZE dest = sizeof(mybuffer)-1; mybuffer[dest--] = '\0'; source = kmess.km_next; DECSOURCE; while(dest >= leadlen) { const char c = kmess.km_buf[source]; if(c == '\n') { mybuffer[dest--] = 'n'; mybuffer[dest] = '\\'; } else if(isprint(c) && c != '\'' && c != '"' && c != '\\' && c != ';') { mybuffer[dest] = c; } else mybuffer[dest] = ' '; DECSOURCE; dest--; } arch_set_params(mybuffer, strlen(mybuffer)+1); } if (mon_return) arch_monitor(); /* monitor command with no monitor: reset or poweroff * depending on the parameters */ if (how == RBT_MONITOR) { mybuffer[0] = '\0'; arch_get_params(mybuffer, sizeof(mybuffer)); if (strstr(mybuffer, "boot") || strstr(mybuffer, "menu") || strstr(mybuffer, "reset")) how = RBT_RESET; else how = RBT_HALT; } } switch (how) { case RBT_REBOOT: case RBT_RESET: /* Reset the system by forcing a processor shutdown. * First stop the BIOS memory test by setting a soft * reset flag. */ magic = STOP_MEM_CHECK; phys_copy(vir2phys(&magic), SOFT_RESET_FLAG_ADDR, SOFT_RESET_FLAG_SIZE); reset(); NOT_REACHABLE; case RBT_HALT: /* Poweroff without boot monitor */ arch_bios_poweroff(); NOT_REACHABLE; case RBT_PANIC: /* Allow user to read panic message */ for (; ; ) halt_cpu(); NOT_REACHABLE; default: /* Not possible! trigger panic */ assert(how != RBT_MONITOR); assert(how != RBT_DEFAULT); assert(how < RBT_INVALID); panic("unexpected value for how: %d", how); NOT_REACHABLE; } NOT_REACHABLE; }
/*init the first process*/ static void init_user_process() { TASK* p_task = NULL; /*struct task_struct* p_proc = proc_table + NR_SYSTEM_PROCS;*/ struct task_struct *tsk = NULL; union thread_union *thread_union = NULL; int i,j,prio, eflags; char privilege,rpl; unsigned int k_base,k_limit; get_kernel_map(&k_base,&k_limit); /*privilege = PRIVILEGE_USER;*/ /*rpl = RPL_USER;*/ /*eflags = 0x1202;*/ /*prio = USER_PRIO;*/ privilege = PRIVILEGE_TASK; rpl = RPL_TASK; eflags = 0x1202; prio = KERNEL_PRIOR; /*for(i = 0;i < NR_USER_PROCS; ++i,++p_proc)*/ for(i = 0;i < NR_USER_PROCS; ++i) { p_task = user_proc_table + i ; tsk = (struct task_struct *)kmem_get_obj(tsk_cachep); if(tsk == NULL) return; thread_union = (union thread_union*)kmem_get_obj(thread_union_cachep); if(thread_union == NULL) return; thread_union->thread_info.task = tsk; tsk->state = TASK_RUNNING; strcpy(tsk->command, p_task->command); // name of the process if((tsk->pid = get_pidmap()) < 0) return; tsk->parent = NULL; tsk->next = tsk->sibling = NULL; for(j = 0; j < NR_SIGNALS;++j) { tsk->sig_action[j].sa_flags = 0; tsk->sig_action[j].sa_handler = do_signal; } for(j = 0;j < NR_OPEN; ++j) { tsk->filp[j] = NULL; } tsk->signal = 0x0; //设置信号为空 tsk->ldt_sel = selector_ldt; init_descriptor(&gdt[selector_ldt>>3],vir2phys(seg2phys(SELECTOR_KERNEL_DS), tsk->ldts),LDT_SIZE * sizeof(DESCRIPTOR) - 1,DA_LDT); tsk->ldts[INDEX_LDT_C] = gdt[SELECTOR_KERNEL_CS >> 3]; tsk->ldts[INDEX_LDT_C].attr1 = DA_C | privilege << 5;// change the DPL tsk->ldts[INDEX_LDT_D] = gdt[SELECTOR_KERNEL_DS >> 3]; tsk->ldts[INDEX_LDT_D].attr1 = DA_DRW | privilege<< 5;// change the DPL /*init_descriptor(&tsk->ldts[INDEX_LDT_C],0,(k_base + k_limit) >> LIMIT_4K_SHIFT,DA_32 | DA_LIMIT_4K | DA_C| privilege <<5);*/ /*init_descriptor(&tsk->ldts[INDEX_LDT_D],0,(k_base + k_limit) >> LIMIT_4K_SHIFT,DA_32 | DA_LIMIT_4K | DA_DRW | privilege << 5);*/ char *stack = (char *)thread_union->stack; tsk->regs.esp = (unsigned int)(stack + sizeof(union thread_union)); tsk->regs.cs = (unsigned int)(((8 * 0) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl); tsk->regs.ds = (unsigned int)(((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl); tsk->regs.es = (unsigned int)(((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl); tsk->regs.fs = (unsigned int)(((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl); tsk->regs.ss = (unsigned int)(((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl); tsk->regs.gs = (unsigned int)((SELECTOR_KERNEL_GS & SA_RPL_MASK) | rpl); tsk->regs.eip = (unsigned int)p_task->initial_eip; tsk->regs.eflags = eflags; tsk->ticks = tsk->priority = prio; tsk->sched_entity.vruntime = i; tsk->sched_class = &rr_sched; tsk->sched_class->enqueue_task(&(sched_rq),tsk,0,0); p_task++; selector_ldt += 1 << 3; } k_reenter = 0; ticks = 0; }
/*init the first process*/ static void init_kernel_thread() { TASK* p_task = NULL; /*struct task_struct* p_proc = proc_table;*/ struct task_struct *tsk = NULL; union thread_union *thread_union = NULL; char* p_task_stack = task_stack + STACK_SIZE_TOTAL; int i,j,prio,eflags; char privilege,rpl; unsigned int k_base,k_limit; get_kernel_map(&k_base,&k_limit); privilege = PRIVILEGE_TASK; rpl = RPL_TASK; eflags = 0x1202; prio = KERNEL_PRIOR; printk(" PrettyOS SoftIRQ."); /*printk(" [email protected] .\n");*/ /*printk(" UESTC.\n");*/ /*disp_str("\t\tprocess init begins\n");*/ /*for(i = 0;i < NR_SYSTEM_PROCS ;++i, ++p_proc)*/ for(i = 0;i < NR_SYSTEM_PROCS ;++i) { p_task = task_table + i; tsk = (struct task_struct *)kmem_get_obj(tsk_cachep); if(tsk == NULL) return; thread_union = (union thread_union*)kmem_get_obj(thread_union_cachep); if(thread_union == NULL) return; thread_union->thread_info.task = tsk; tsk->state = TASK_RUNNING; strcpy(tsk->command, p_task->command); // name of the process if((tsk->pid = get_pidmap()) < 0) return; tsk->parent = NULL; tsk->next = tsk->sibling = NULL; /*proc_table[0].nr_tty = 0; // tty */ for(j = 0; j < NR_SIGNALS;++j) { tsk->sig_action[j].sa_flags = 0; tsk->sig_action[j].sa_handler = do_signal; } for(j = 0;j < NR_OPEN; ++j) { tsk->filp[j] = NULL; } tsk->signal = 0x0; //设置信号为空 tsk->ldt_sel = selector_ldt; init_descriptor(&gdt[selector_ldt>>3],vir2phys(seg2phys(SELECTOR_KERNEL_DS), tsk->ldts),LDT_SIZE * sizeof(DESCRIPTOR) - 1,DA_LDT); init_descriptor(&tsk->ldts[INDEX_LDT_C],0,(k_base + k_limit) >> LIMIT_4K_SHIFT,DA_32 | DA_LIMIT_4K | DA_C| privilege <<5); init_descriptor(&tsk->ldts[INDEX_LDT_D],0,(k_base + k_limit) >> LIMIT_4K_SHIFT,DA_32 | DA_LIMIT_4K | DA_DRW | privilege << 5); tsk->regs.esp = (unsigned int)p_task_stack; p_task_stack -= STACK_SIZE_DEFAULT; tsk->regs.cs = (unsigned int)(((8 * 0) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl); tsk->regs.ds = (unsigned int)(((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl); tsk->regs.es = (unsigned int)(((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl); tsk->regs.fs = (unsigned int)(((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl); tsk->regs.ss = (unsigned int)(((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl); tsk->regs.gs = (unsigned int)((SELECTOR_KERNEL_GS & SA_RPL_MASK) | rpl); tsk->regs.eip = (unsigned int)p_task->initial_eip; tsk->regs.eflags = eflags; tsk->ticks = tsk->priority = prio; tsk->sched_entity.vruntime = i; tsk->sched_class = &rr_sched; if(tsk->pid != INIT_PID) tsk->sched_class->enqueue_task(&(sched_rq),tsk,0,0); p_task++; selector_ldt += 1 << 3; } k_reenter = 0; ticks = 0; }
//-------------------------------------------------------------------------- // init_prot //-------------------------------------------------------------------------- void init_prot() { init_8259A(); // 全部初始化成中断门(没有陷阱门) init_idt_desc(INT_VECTOR_DIVIDE, DA_386IGate, divide_error, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_DEBUG, DA_386IGate, single_step_exception, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_NMI, DA_386IGate, nmi, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_BREAKPOINT, DA_386IGate, breakpoint_exception, PRIVILEGE_USER); init_idt_desc(INT_VECTOR_OVERFLOW, DA_386IGate, overflow, PRIVILEGE_USER); init_idt_desc(INT_VECTOR_BOUNDS, DA_386IGate, bounds_check, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_INVAL_OP, DA_386IGate, inval_opcode, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_COPROC_NOT, DA_386IGate, copr_not_available, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_DOUBLE_FAULT, DA_386IGate, double_fault, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_COPROC_SEG, DA_386IGate, copr_seg_overrun, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_INVAL_TSS, DA_386IGate, inval_tss, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_SEG_NOT, DA_386IGate, segment_not_present, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_STACK_FAULT, DA_386IGate, stack_exception, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_PROTECTION, DA_386IGate, general_protection, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_PAGE_FAULT, DA_386IGate, page_fault, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_COPROC_ERR, DA_386IGate, copr_error, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 0, DA_386IGate, hwint00, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 1, DA_386IGate, hwint01, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 2, DA_386IGate, hwint02, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 3, DA_386IGate, hwint03, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 4, DA_386IGate, hwint04, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 5, DA_386IGate, hwint05, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 6, DA_386IGate, hwint06, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ0 + 7, DA_386IGate, hwint07, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 0, DA_386IGate, hwint08, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 1, DA_386IGate, hwint09, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 2, DA_386IGate, hwint10, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 3, DA_386IGate, hwint11, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 4, DA_386IGate, hwint12, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 5, DA_386IGate, hwint13, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 6, DA_386IGate, hwint14, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_IRQ8 + 7, DA_386IGate, hwint15, PRIVILEGE_KRNL); init_idt_desc(INT_VECTOR_SYS_CALL, DA_386IGate, sys_call, PRIVILEGE_USER); //填充 GDT 中 TSS 这个描述符 memset(&tss, 0, sizeof(tss)); tss.ss0 = SELECTOR_KERNEL_DS; init_descriptor(&gdt[INDEX_TSS], vir2phys(seg2phys(SELECTOR_KERNEL_DS), &tss), sizeof(tss) - 1, DA_386TSS); tss.iobase = sizeof(tss); // 没有I/O许可位图 // 填充 GDT 中进程的 LDT 的描述符 int i; PROCESS* p_proc = proc_table; u16 selector_ldt = INDEX_LDT_FIRST << 3; for(i=0;i<NR_TASKS;i++){ init_descriptor(&gdt[selector_ldt>>3], vir2phys(seg2phys(SELECTOR_KERNEL_DS), proc_table[i].ldts), LDT_SIZE * sizeof(DESCRIPTOR) - 1, DA_LDT); p_proc++; selector_ldt += 1 << 3; } }
/** * \brief Set up tables for protected mode * All GDT slots are allocated at compile time */ void prot_init() { struct gate_table_s *gtp; struct desctableptr_s *dtp; unsigned ldt_index; struct proc *rp; static struct gate_table_s { void (*gate)(void); unsigned char vec_nr; unsigned char privilege; } gate_table[] = { { divide_error, DIVIDE_VECTOR, INTR_PRIVILEGE }, { single_step_exception, DEBUG_VECTOR, INTR_PRIVILEGE }, { nmi, NMI_VECTOR, INTR_PRIVILEGE }, { breakpoint_exception, BREAKPOINT_VECTOR, USER_PRIVILEGE }, { overflow, OVERFLOW_VECTOR, USER_PRIVILEGE }, { bounds_check, BOUNDS_VECTOR, INTR_PRIVILEGE }, { inval_opcode, INVAL_OP_VECTOR, INTR_PRIVILEGE }, { copr_not_available, COPROC_NOT_VECTOR, INTR_PRIVILEGE }, { double_fault, DOUBLE_FAULT_VECTOR, INTR_PRIVILEGE }, { copr_seg_overrun, COPROC_SEG_VECTOR, INTR_PRIVILEGE }, { inval_tss, INVAL_TSS_VECTOR, INTR_PRIVILEGE }, { segment_not_present, SEG_NOT_VECTOR, INTR_PRIVILEGE }, { stack_exception, STACK_FAULT_VECTOR, INTR_PRIVILEGE }, { general_protection, PROTECTION_VECTOR, INTR_PRIVILEGE }, { page_fault, PAGE_FAULT_VECTOR, INTR_PRIVILEGE }, { copr_error, COPROC_ERR_VECTOR, INTR_PRIVILEGE }, { hwint00, IRQ0_VECTOR + CLOCK_IRQ, INTR_PRIVILEGE }, { hwint01, IRQ0_VECTOR + KEYBOARD_IRQ, INTR_PRIVILEGE }, { hwint02, IRQ0_VECTOR + CASCADE_IRQ, INTR_PRIVILEGE }, { hwint03, IRQ0_VECTOR + ETHER_IRQ, INTR_PRIVILEGE }, { hwint04, IRQ0_VECTOR + RS232_IRQ, INTR_PRIVILEGE }, { hwint05, IRQ0_VECTOR + 5, INTR_PRIVILEGE }, { hwint06, IRQ0_VECTOR + 6, INTR_PRIVILEGE }, { hwint07, IRQ0_VECTOR + 7, INTR_PRIVILEGE }, { hwint08, IRQ0_VECTOR + 8, INTR_PRIVILEGE }, { hwint09, IRQ0_VECTOR + 9, INTR_PRIVILEGE }, { hwint10, IRQ0_VECTOR + 10, INTR_PRIVILEGE }, { hwint11, IRQ0_VECTOR + 11, INTR_PRIVILEGE }, { hwint12, IRQ0_VECTOR + 12, INTR_PRIVILEGE }, { hwint13, IRQ0_VECTOR + 13, INTR_PRIVILEGE }, { hwint14, IRQ0_VECTOR + IDE_IRQ, INTR_PRIVILEGE }, { hwint15, IRQ0_VECTOR + 15, INTR_PRIVILEGE }, { s_call, SYS_VECTOR, USER_PRIVILEGE }, // system call { level0_call, LEVEL0_VECTOR, TASK_PRIVILEGE }, }; /* since it is now in protected mode and it enters protected mode * in boot loader where global segment descriptor is set up to * map all physical memory, that is base is 0, and limit is MAX * physical memory - 1 * * so here when apply vir2phys ( kinfo.data_base + vir ), still * get vir */ // Build gdt and idt pointers in GDT where the BIOS expects them dtp = (struct desctableptr_s *) &gdt[GDT_INDEX]; *((u16_t *) dtp->limit) = (sizeof gdt) - 1; *((u32_t *) dtp->base) = vir2phys(gdt); dtp = (struct desctableptr_s *) &gdt[IDT_INDEX]; *((u16_t *) dtp->limit) = (sizeof idt) - 1; *((u32_t *) dtp->base) = vir2phys(idt); // Build segment descriptors for tasks and interrupt handlers init_codeseg(&gdt[CS_INDEX], kinfo.code_base, kinfo.code_size, INTR_PRIVILEGE); init_dataseg(&gdt[DS_INDEX], kinfo.data_base, kinfo.data_size, INTR_PRIVILEGE); init_dataseg(&gdt[ES_INDEX], 0L, 0, TASK_PRIVILEGE); // Build scratch descriptors for functions in klib88 init_dataseg(&gdt[DS_286_INDEX], 0L, 0, TASK_PRIVILEGE); init_dataseg(&gdt[ES_286_INDEX], 0L, 0, TASK_PRIVILEGE); /* Build local descriptors in GDT for LDT's in process table. * The LDT's are allocated at compile time in the process table, and * initialized whenever a process' map is initialized or changed. */ for (rp = BEG_PROC_ADDR, ldt_index = FIRST_LDT_INDEX; rp < END_PROC_ADDR; ++rp, ldt_index++) { init_dataseg(&gdt[ldt_index], vir2phys(rp->p_ldt), sizeof(rp->p_ldt), INTR_PRIVILEGE); gdt[ldt_index].access = PRESENT | LDT; rp->p_ldt_sel = ldt_index * DESC_SIZE; } /* Build main TSS. * This is used only to record the stack pointer to be used after an interrupt. * Actually it points to stackframe of proc * * The pointer is set up so that an interrupt automatically saves the * current process's registers eip:cs:eflags:esp:ss in the correct slots in the * process table. */ tss.ss0 = DS_SELECTOR; init_dataseg(&gdt[TSS_INDEX], vir2phys(&tss), sizeof(tss), INTR_PRIVILEGE); gdt[TSS_INDEX].access = PRESENT | (INTR_PRIVILEGE << DPL_SHIFT) | TSS_TYPE; // Build descriptors for interrupt gates in IDT for (gtp = &gate_table[0]; gtp < &gate_table[sizeof gate_table / sizeof gate_table[0]]; ++gtp) { int_gate(gtp->vec_nr, (vir_bytes) gtp->gate, PRESENT | INT_GATE_TYPE | (gtp->privilege << DPL_SHIFT)); } // Complete building of main TSS tss.iobase = sizeof tss; // empty i/o permissions map }
lock_enqueue(rp); /* add to scheduling queues */ } else { rp->p_rts_flags = NO_MAP; /* prevent from running */ } /* Code and data segments must be allocated in protected mode. */ alloc_segments(rp); } #if ENABLE_BOOTDEV /* Expect an image of the boot device to be loaded into memory as well. * The boot device is the last module that is loaded into memory, and, * for example, can contain the root FS (useful for embedded systems). */ hdrindex ++; phys_copy(aout + hdrindex * A_MINHDR,vir2phys(&e_hdr),(phys_bytes) A_MINHDR); if (e_hdr.a_flags & A_IMG) { kinfo.bootdev_base = e_hdr.a_syms; kinfo.bootdev_size = e_hdr.a_data; } #endif /* MINIX is now ready. All boot image processes are on the ready queue. * Return to the assembly code to start running the current process. */ bill_ptr = proc_addr(IDLE); /* it has to point somewhere */ announce(); /* print MINIX startup banner */ restart(); } /*===========================================================================*
/*===========================================================================* * main * *===========================================================================*/ PUBLIC void main() { /* Start the ball rolling. */ struct boot_image *ip; /* boot image pointer */ register struct proc *rp; /* process pointer */ register struct priv *sp; /* privilege structure pointer */ register int i, s; // a.out 头部数组的索引. int hdrindex; /* index to array of a.out headers */ phys_clicks text_base; vir_clicks text_clicks, data_clicks; // 内核任务栈的基地址(低端) reg_t ktsb; /* kernel task stack base */ // 用来放置 a.out 头部的一个副本. struct exec e_hdr; /* for a copy of an a.out header */ /* Initialize the interrupt controller. */ // 初始化 8259 中断控制器芯片. intr_init(1); /* Clear the process table. Anounce each slot as empty and set up mappings * for proc_addr() and proc_nr() macros. Do the same for the table with * privilege structures for the system processes. */ // 初如化进程表与进程指针表. // BEG_PROC_ADDR: 进程表地址; for (rp = BEG_PROC_ADDR, i = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++i) { // 将进程表中每一项都设置为空闲. rp->p_rts_flags = SLOT_FREE; /* initialize free slot */ // 进程号, i 的初值为 -NR_TASKS, 可见系统任务拥有负的进程号 rp->p_nr = i; /* proc number from ptr */ // 建立进程数组与进程指针数组之间的映射关系 (pproc_addr + NR_TASKS)[i] = rp; /* proc ptr from number */ } // 初始化优先级表 for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) { sp->s_proc_nr = NONE; /* initialize as free */ sp->s_id = i; /* priv structure index */ // 建立特权级表与特权级指针表之间的映射关系 ppriv_addr[i] = sp; /* priv ptr from number */ } /* Set up proc table entries for tasks and servers. The stacks of the * kernel tasks are initialized to an array in data space. The stacks * of the servers have been added to the data segment by the monitor, so * the stack pointer is set to the end of the data segment. All the * processes are in low memory on the 8086. On the 386 only the kernel * is in low memory, the rest is loaded in extended memory. */ /* * 为任务和服务进程设置进程表项. 内核任务的栈被初始化成一个在数据空间中的 * 数组. 服务进程的栈已经由控制器添加到数据段中, 所有它们的栈指针开始时 * 指向数据段的末尾. 所有的进程都在 8086 的低内存. 对于 386, 只有内核在 * 低内存, 剩下的都在扩展内存中. */ /* Task stacks. */ /* 任务栈 */ ktsb = (reg_t) t_stack; // 为那些包含在系统引导映像文件中的程序分配进程表项. for (i=0; i < NR_BOOT_PROCS; ++i) { ip = &image[i]; /* process' attributes */ // 获取进程指针 rp = proc_addr(ip->proc_nr); /* get process pointer */ // 最大调度优先级 rp->p_max_priority = ip->priority; /* max scheduling priority */ // 当前调度优先级 rp->p_priority = ip->priority; /* current priority */ // 时间片原子值 rp->p_quantum_size = ip->quantum; /* quantum size in ticks */ // 剩余时间片 rp->p_ticks_left = ip->quantum; /* current credit */ // 将程序名复制到进程表项中 strncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set process name */ // 为进程分配一个特权级结构体, 即 从系统特权级表中分配一项 (void) get_priv(rp, (ip->flags & SYS_PROC)); /* assign structure */ // 初始化特权级结构体的标志. priv(rp)->s_flags = ip->flags; /* process flags */ // 初始化特权级结构体的 允许的系统调用陷井 priv(rp)->s_trap_mask = ip->trap_mask; /* allowed traps */ priv(rp)->s_call_mask = ip->call_mask; /* kernel call mask */ // 初始化进程的消息发送位图 priv(rp)->s_ipc_to.chunk[0] = ip->ipc_to; /* restrict targets */ // 如果进程是内核任务 if (iskerneln(proc_nr(rp))) { /* part of the kernel? */ // 如果进程的栈大小大于 0, 设置进程的栈警戒字, if (ip->stksize > 0) { /* HARDWARE stack size is 0 */ // 设置内核任务栈警戒字指针. rp->p_priv->s_stack_guard = (reg_t *) ktsb; // 指针运算符(->) 要比取值运行符 (*) 的优先级要高. // 等价于: // *(rp->p_priv->s_stack_guard) = STACK_GUARD // 效果是在栈的最顶端(在低地址)放置一个特殊值, // 这个值就是栈警戒字. *rp->p_priv->s_stack_guard = STACK_GUARD; } ktsb += ip->stksize; /* point to high end of stack */ // 初始进程的栈指针 rp->p_reg.sp = ktsb; /* this task's initial stack ptr */ // kinfo ??? // 内核代码的基地址右移 CLICK_SHIFT 位, 赋给 text_base. text_base = kinfo.code_base >> CLICK_SHIFT; /* processes that are in the kernel */ // 内核任务使用同一个 a.out 头部信息 hdrindex = 0; /* all use the first a.out header */ } else { // 非内核任务, 计算它的 a.out 头部数组索引, 因为 0 号项 // 留给了内核任务, 所以需 加 1. hdrindex = 1 + i-NR_TASKS; /* servers, drivers, INIT */ } /* The bootstrap loader created an array of the a.out headers at * absolute address 'aout'. Get one element to e_hdr. */ /* * 引导加载程序会在绝对地址 'aout' 处放置一个 a.out 头部数组. * 从中取一项复制到 e_hdr. */ phys_copy(aout + hdrindex * A_MINHDR, vir2phys(&e_hdr), (phys_bytes) A_MINHDR); /* Convert addresses to clicks and build process memory map */ /* 将地址转换为以 click 为单位, 并建立进程内存映射 */ // 既然这里要设置 text_base, 那 146 行附近的 // text_base = kinfo.code_base >> CLICK_SHIFT; // 岂不是多余的?? // 将 a.out 头部的符号表大小右移 CLICK_SHIFT 位,赋给 text_base. text_base = e_hdr.a_syms >> CLICK_SHIFT; // 计算程序文本段大小, 以 click 为单位, 上取整. text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT; // 如果 a.out 头部指明它的 I/D 是合并的 ??? if (!(e_hdr.a_flags & A_SEP)) text_clicks = 0; /* common I&D */ // 计算程序占用的内存量, 以 click 为单位, 上取整. data_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT; // 初始化进程的内存映射数据结构 rp->p_memmap[T].mem_phys = text_base; rp->p_memmap[T].mem_len = text_clicks; rp->p_memmap[D].mem_phys = text_base + text_clicks; rp->p_memmap[D].mem_len = data_clicks; rp->p_memmap[S].mem_phys = text_base + text_clicks + data_clicks; rp->p_memmap[S].mem_vir = data_clicks; /* empty - stack is in data */ /* Set initial register values. The processor status word for tasks * is different from that of other processes because tasks can * access I/O; this is not allowed to less-privileged processes */ /* * 设置寄存器的初始值. 与其他进程相比, 内核任务的处理器状态字 * 稍有不同, 因为内核任务可以访问 I/O; 而对于非特权进来来说, 这是不 * 允许的. */ // 初始化进程的 PC 和 processor status word. rp->p_reg.pc = (reg_t) ip->initial_pc; rp->p_reg.psw = (iskernelp(rp)) ? INIT_TASK_PSW : INIT_PSW; /* Initialize the server stack pointer. Take it down one word * to give crtso.s something to use as "argc". */ /* * 初始化服务器进程的栈指针. 下移一个字的空间, 使得 crtso.s 有 * 空间放置 "argc". */ if (isusern(proc_nr(rp))) { /* user-space process? */ rp->p_reg.sp = (rp->p_memmap[S].mem_vir + rp->p_memmap[S].mem_len) << CLICK_SHIFT; rp->p_reg.sp -= sizeof(reg_t); } /* Set ready. The HARDWARE task is never ready. */ if (rp->p_nr != HARDWARE) { // 如果进程不是 HARDWARE, 清空进程标志, 并加入调度队列. rp->p_rts_flags = 0; /* runnable if no flags */ lock_enqueue(rp); /* add to scheduling queues */ } else { // 对于 HARDWARE 任务, 则阻止其运行. ??? rp->p_rts_flags = NO_MAP; /* prevent from running */ } /* Code and data segments must be allocated in protected mode. */ /* 数据与代码段必须在保护模式下分配 */ alloc_segments(rp); }
void pg_info(reg_t *pagedir_ph, u32_t **pagedir_v) { *pagedir_ph = vir2phys(pagedir); *pagedir_v = pagedir; }
/*===========================================================================* * main * *===========================================================================*/ PUBLIC void main() { /* Start the ball rolling. */ register struct proc *rp; register int t; int hdrindex; phys_clicks text_base; vir_clicks text_clicks; vir_clicks data_clicks; phys_bytes phys_b; reg_t ktsb; /* kernel task stack base */ struct memory *memp; struct tasktab *ttp; struct exec e_hdr; licznik_elementow = 0; /* Initialize the interrupt controller. */ intr_init(1); /* Interpret memory sizes. */ mem_init(); /* Clear the process table. * Set up mappings for proc_addr() and proc_number() macros. */ for (rp = BEG_PROC_ADDR, t = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++t) { rp->p_nr = t; /* proc number from ptr */ (pproc_addr + NR_TASKS)[t] = rp; /* proc ptr from number */ } /* Resolve driver selections in the task table. */ mapdrivers(); /* Set up proc table entries for tasks and servers. The stacks of the * kernel tasks are initialized to an array in data space. The stacks * of the servers have been added to the data segment by the monitor, so * the stack pointer is set to the end of the data segment. All the * processes are in low memory on the 8086. On the 386 only the kernel * is in low memory, the rest is loaded in extended memory. */ /* Task stacks. */ ktsb = (reg_t) t_stack; for (t = -NR_TASKS; t <= LOW_USER; ++t) { rp = proc_addr(t); /* t's process slot */ ttp = &tasktab[t + NR_TASKS]; /* t's task attributes */ strcpy(rp->p_name, ttp->name); if (t < 0) { if (ttp->stksize > 0) { rp->p_stguard = (reg_t *) ktsb; *rp->p_stguard = STACK_GUARD; } ktsb += ttp->stksize; rp->p_reg.sp = ktsb; text_base = code_base >> CLICK_SHIFT; /* tasks are all in the kernel */ hdrindex = 0; /* and use the first a.out header */ rp->p_priority = PPRI_TASK; } else { hdrindex = 1 + t; /* MM, FS, INIT follow the kernel */ rp->p_priority = t < LOW_USER ? PPRI_SERVER : PPRI_USER; } /* The bootstrap loader has created an array of the a.out headers at * absolute address 'aout'. */ phys_copy(aout + hdrindex * A_MINHDR, vir2phys(&e_hdr), (phys_bytes) A_MINHDR); text_base = e_hdr.a_syms >> CLICK_SHIFT; text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT; if (!(e_hdr.a_flags & A_SEP)) text_clicks = 0; /* Common I&D */ data_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT; rp->p_map[T].mem_phys = text_base; rp->p_map[T].mem_len = text_clicks; rp->p_map[D].mem_phys = text_base + text_clicks; rp->p_map[D].mem_len = data_clicks; rp->p_map[S].mem_phys = text_base + text_clicks + data_clicks; rp->p_map[S].mem_vir = data_clicks; /* empty - stack is in data */ /* Remove server memory from the free memory list. The boot monitor * promises to put processes at the start of memory chunks. */ for (memp = mem; memp < &mem[NR_MEMS]; memp++) { if (memp->base == text_base) { memp->base += text_clicks + data_clicks; memp->size -= text_clicks + data_clicks; } } /* Set initial register values. */ rp->p_reg.pc = (reg_t) ttp->initial_pc; rp->p_reg.psw = istaskp(rp) ? INIT_TASK_PSW : INIT_PSW; if (t >= 0) { /* Initialize the server stack pointer. Take it down one word * to give crtso.s something to use as "argc". */ rp->p_reg.sp = (rp->p_map[S].mem_vir + rp->p_map[S].mem_len) << CLICK_SHIFT; rp->p_reg.sp -= sizeof(reg_t); } if (!isidlehardware(t)) lock_ready(rp); /* IDLE, HARDWARE neveready */ rp->p_flags = 0; alloc_segments(rp); }
void init_trap() { int i; init_8259A(); //soft interrupt set_trap_gate(INT_VECTOR_DIVIDE,divide_error); set_trap_gate(INT_VECTOR_DEBUG, single_step_exception); set_trap_gate(INT_VECTOR_NMI, nmi); set_system_gate(INT_VECTOR_BREAKPOINT, breakpoint_exception); set_system_gate(INT_VECTOR_OVERFLOW, overflow); set_system_gate(INT_VECTOR_BOUNDS, bounds_check); set_trap_gate(INT_VECTOR_INVAL_OP, inval_opcode); set_trap_gate(INT_VECTOR_COPROC_NOT, copr_not_available); set_trap_gate(INT_VECTOR_DOUBLE_FAULT, double_fault); set_trap_gate(INT_VECTOR_COPROC_SEG, copr_seg_overrun); set_trap_gate(INT_VECTOR_INVAL_TSS, inval_tss); set_trap_gate(INT_VECTOR_SEG_NOT, segment_not_present); set_trap_gate(INT_VECTOR_STACK_FAULT, stack_exception); set_trap_gate(INT_VECTOR_PROTECTION, general_protection); set_trap_gate(INT_VECTOR_PAGE_FAULT, page_fault); set_trap_gate(INT_VECTOR_COPROC_ERR, copr_error); // hard interrupt IRQ0-IRQ15 set_intr_gate(INT_VECTOR_IRQ0 + 0, clock_intr); //clock interrupt set_intr_gate(INT_VECTOR_IRQ0 + 1, kb_intr); //keyboard interrupt set_intr_gate(INT_VECTOR_IRQ0 + 2, hwint02); set_intr_gate(INT_VECTOR_IRQ0 + 3, hwint03); set_intr_gate(INT_VECTOR_IRQ0 + 4, hwint04); set_intr_gate(INT_VECTOR_IRQ0 + 5, hwint05); set_intr_gate(INT_VECTOR_IRQ0 + 6, hwint06); set_intr_gate(INT_VECTOR_IRQ0 + 7, hwint07); set_intr_gate(INT_VECTOR_IRQ8 + 0, hwint08); set_intr_gate(INT_VECTOR_IRQ8 + 1, hwint09); set_intr_gate(INT_VECTOR_IRQ8 + 2, hwint10); set_intr_gate(INT_VECTOR_IRQ8 + 3, hwint11); set_intr_gate(INT_VECTOR_IRQ8 + 4, hwint12); set_intr_gate(INT_VECTOR_IRQ8 + 5, hwint13); set_intr_gate(INT_VECTOR_IRQ8 + 6, hd_intr);//hard disk interrupt set_intr_gate(INT_VECTOR_IRQ8 + 7, hwint15); //init 80 interrupt set_syscall_gate(INT_VECTOR_SYS_CALL, sys_call); memset((char *)&tss, 0, sizeof(tss)); tss.ss0 = SELECTOR_KERNEL_DS; //¿¿TSS init_descriptor(&gdt[INDEX_TSS], vir2phys(seg2phys(SELECTOR_KERNEL_DS), &tss), sizeof(tss) - 1, DA_386TSS); tss.iobase = sizeof(tss); PROCESS* p_proc = proc_table; t16 selector_ldt = INDEX_LDT_FIRST << 3; //¿¿GDT¿¿¿¿¿¿¿LDT for(i=0;i<NR_SYSTEM_PROCS + NR_USER_PROCS;i++) { init_descriptor(&gdt[selector_ldt>>3], vir2phys(seg2phys(SELECTOR_KERNEL_DS), proc_table[i].ldts), LDT_SIZE * sizeof(DESCRIPTOR) - 1, DA_LDT); p_proc++; selector_ldt += 1 << 3; } }