void main( void ) { errno = 0; intr_disable(); intr_init(); hw_init(); /* print a banner */ printf( "%s %s\n", os_name, os_version ); memory_init(); device_init(); vfs_init(); /* new line after all initialisation messages */ printf("\n"); kb_init(); console_init(); intr_enable(); /* fire up the shell! */ for(;;) { shell_start(); printf("Respawning shell\n"); } }
/** * The entry. */ int main(int argc, char *argv[], char *envp[]) { if (ginfo->status == STATUS_DEBUG) raise(SIGTRAP); cons_init(); const char *message = "(THU.CST) os is loading ..."; kprintf("%s\n\n", message); intr_init(); ide_init(); host_signal_init(); /* Only to initialize lcpu_count. */ mp_init(); pmm_init(); pmm_init_ap(); vmm_init(); sched_init(); proc_init(); swap_init(); fs_init(); sync_init(); umclock_init(); cpu_idle(); host_exit(SIGINT); return 0; }
void nucleos_shutdown(timer_t *tp) { /* This function is called from prepare_shutdown or stop_sequence to bring * down Nucleos. How to shutdown is in the argument: RBT_HALT (return to the * monitor), RBT_MONITOR (execute given code), RBT_RESET (hard reset). */ arch_stop_local_timer(); intr_init(INTS_ORIG, 0); arch_shutdown(tp ? tmr_arg(tp)->ta_int : RBT_PANIC); }
void cpu_configure(void) { intr_init(); splhigh(); if (config_rootfound("mainbus", NULL) == NULL) panic("no mainbus found"); spl0(); }
/* * Configure all devices on system */ void cpu_configure(void) { intr_init(); /* Kick off autoconfiguration. */ (void)splhigh(); if (config_rootfound("mainbus", "mainbus") == NULL) panic("no mainbus found"); (void)spl0(); }
void cpu_configure(void) { /* Start configuration */ splhigh(); intr_init(); if (config_rootfound("mainbus", NULL) == NULL) panic("no mainbus found"); /* Configuration is finished, turn on interrupts. */ spl0(); }
/* * Determine device configuration for a machine. */ void cpu_configure(void) { intr_init(); calc_delayconst(); /* Make sure that timers run at CPU frequency */ mtdcr(DCR_CPC0_CR1, mfdcr(DCR_CPC0_CR1) & ~CPC0_CR1_CETE); if (config_rootfound("plb", NULL) == NULL) panic("configure: mainbus not configured"); (void)spl0(); }
void platform_init(int argc, char **argv, char **envp, unsigned memsize) { /* clear BSS section */ bzero(__bss, __ebss - __bss); setup_kenv(argc, argv, envp); uart_init(); pcpu_init(); cpu_init(); tlb_init(); intr_init(); pm_bootstrap(memsize); thread_bootstrap(); kprintf("[startup] Switching to 'kernel-main' thread...\n"); }
/* * Configure all devices on system */ void cpu_configure(void) { intr_init(); /* Kick off autoconfiguration. */ if (config_rootfound("mainbus", NULL) == NULL) panic("no mainbus found"); /* * Hardware interrupts will be enabled in * sys/arch/mips/mips/mips3_clockintr.c:mips3_initclocks() * to avoid hardclock(9) by CPU INT5 before softclockintr is * initialized in initclocks(). */ }
/** * This is the first real C function ever called. It performs a lot of * hardware-specific initialization, then creates a pseudo-context to * execute the bootstrap function in. */ void kmain() { GDB_CALL_HOOK(boot); dbg_init(); dbgq(DBG_CORE, "Kernel binary:\n"); dbgq(DBG_CORE, " text: 0x%p-0x%p\n", &kernel_start_text, &kernel_end_text); dbgq(DBG_CORE, " data: 0x%p-0x%p\n", &kernel_start_data, &kernel_end_data); dbgq(DBG_CORE, " bss: 0x%p-0x%p\n", &kernel_start_bss, &kernel_end_bss); page_init(); pt_init(); slab_init(); pframe_init(); acpi_init(); apic_init(); pci_init(); intr_init(); gdt_init(); /* initialize slab allocators */ #ifdef __VM__ anon_init(); shadow_init(); #endif vmmap_init(); proc_init(); kthread_init(); #ifdef __DRIVERS__ bytedev_init(); blockdev_init(); #endif void *bstack = page_alloc(); pagedir_t *bpdir = pt_get(); KASSERT(NULL != bstack && "Ran out of memory while booting."); context_setup(&bootstrap_context, bootstrap, 0, NULL, bstack, PAGE_SIZE, bpdir); context_make_active(&bootstrap_context); panic("\nReturned to kmain()!!!\n"); }
void kernel_init(void) { console_init(); debug("Kernel: Booting"); debug("Kernel: Address 0x%08X~0x%08X, Used %d KB", _kernel_start, _kernel_end, (_kernel_end - _kernel_start + 1023) / 1024); mm_init(); intr_init(); dev_init(); syscall_init(); process_init(); }
void main(void) { intr_init(); init_pit(); outb(0x21, 0xf8); outb(0xa1, 0xff); put_irq_handler(0, keyborad_handler); put_irq_handler(12, mouse_handler); put_irq_handler(0, timer_handler); kprintf("\n%s %s.%s. Copyright (c) 2013 loulanguju\n", KERNEL_NAME, KERNEL_RELEASE, KERNEL_VERSION); kprintf("Executing in %s mode.\n\n", "32-bit protected"); while (1) {// do while } return ; }
/*===========================================================================* * shutdown * *===========================================================================*/ PUBLIC void minix_shutdown(timer_t *tp) { /* This function is called from prepare_shutdown or stop_sequence to bring * down MINIX. How to shutdown is in the argument: RBT_HALT (return to the * monitor), RBT_MONITOR (execute given code), RBT_RESET (hard reset). */ #ifdef CONFIG_SMP /* * FIXME * * we will need to stop timers on all cpus if SMP is enabled and put them in * such a state that we can perform the whole boot process once restarted from * monitor again */ if (ncpus > 1) smp_shutdown_aps(); #endif hw_intr_disable_all(); stop_local_timer(); intr_init(INTS_ORIG, 0); arch_shutdown(tp ? tmr_arg(tp)->ta_int : RBT_PANIC); }
/* * Determine device configuration for a machine. */ void cpu_configure(void) { intr_init(); calc_delayconst(); /* Make sure that timers run at CPU frequency */ mtdcr(DCR_CPC0_CR1, mfdcr(DCR_CPC0_CR1) & ~CPC0_CR1_CETE); if (config_rootfound("plb", &local_plb_devs) == NULL) panic("configure: plb not configured"); printf("biomask %x netmask %x ttymask %x\n", (u_short)imask[IPL_BIO], (u_short)imask[IPL_NET], (u_short)imask[IPL_TTY]); (void)spl0(); /* * Now allow hardware interrupts. */ asm volatile ("wrteei 1"); }
/* * Machine-dependent startup code */ void cpu_startup() { #ifdef DEBUG extern int pmapdebug; int opmapdebug = pmapdebug; #endif vaddr_t minaddr, maxaddr; extern struct user *proc0paddr; #ifdef DEBUG pmapdebug = 0; #endif /* * fix message buffer mapping */ pmap_map(MSGBUF_VA, MSGBUF_PA, MSGBUF_PA + MSGBUFSIZE, UVM_PROT_RW); initmsgbuf((caddr_t)(MSGBUF_VA + (CPU_ISSUN4 ? 4096 : 0)), MSGBUFSIZE); proc0.p_addr = proc0paddr; /* I would print this earlier, but I want it in the message buffer */ if (kap_maskcheck() == 0) { printf("WARNING: KAP M2C3 or earlier mask detected.\n" "THE PROCESSOR IN THIS MACHINE SUFFERS FROM SEVERE HARDWARE ISSUES.\n" "M2C3 PROCESSORS MAY RUN RELIABLY ENOUGH, OLDER WILL DEFINITELY NOT.\n\n"); } /* * Good {morning,afternoon,evening,night}. */ printf(version); /*identifycpu();*/ printf("real mem = %d (%dMB)\n", ptoa(physmem), ptoa(physmem) / 1024 / 1024); /* * Allocate a submap for exec arguments. This map effectively * limits the number of processes exec'ing at any time. */ minaddr = vm_map_min(kernel_map); exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); /* * Allocate a map for physio. Others use a submap of the kernel * map, but we want one completely separate, even though it uses * the same pmap. */ dvma_base = CPU_ISSUN4M ? DVMA4M_BASE : DVMA_BASE; dvma_end = CPU_ISSUN4M ? DVMA4M_END : DVMA_END; phys_map = uvm_map_create(pmap_kernel(), dvma_base, dvma_end, VM_MAP_INTRSAFE); if (phys_map == NULL) panic("unable to create DVMA map"); /* * Allocate DVMA space and dump into a privately managed * resource map for double mappings which is usable from * interrupt contexts. */ if (uvm_km_valloc_wait(phys_map, (dvma_end-dvma_base)) != dvma_base) panic("unable to allocate from DVMA map"); dvmamap_extent = extent_create("dvmamap", dvma_base, dvma_end, M_DEVBUF, NULL, 0, EX_NOWAIT); if (dvmamap_extent == 0) panic("unable to allocate extent for dvma"); #ifdef DEBUG pmapdebug = opmapdebug; #endif printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free), ptoa(uvmexp.free) / 1024 / 1024); /* * Set up buffers, so they can be used to read disk labels. */ bufinit(); /* Early interrupt handlers initialization */ intr_init(); }
/** * This is the first real C function ever called. It performs a lot of * hardware-specific initialization, then creates a pseudo-context to * execute the bootstrap function in. */ void kmain() { GDB_CALL_HOOK(boot); dbg_init(); dbgq(DBG_CORE, "Kernel binary:\n"); dbgq(DBG_CORE, " text: 0x%p-0x%p\n", &kernel_start_text, &kernel_end_text); dbgq(DBG_CORE, " data: 0x%p-0x%p\n", &kernel_start_data, &kernel_end_data); dbgq(DBG_CORE, " bss: 0x%p-0x%p\n", &kernel_start_bss, &kernel_end_bss); page_init(); pt_init(); slab_init(); pframe_init(); acpi_init(); apic_init(); pci_init(); intr_init(); gdt_init(); /* initialize slab allocators */ #ifdef __VM__ anon_init(); shadow_init(); #endif vmmap_init(); proc_init(); kthread_init(); #ifdef __DRIVERS__ bytedev_init(); blockdev_init(); #endif void *bstack = page_alloc(); pagedir_t *bpdir = pt_get(); KASSERT(NULL != bstack && "Ran out of memory while booting."); /* This little loop gives gdb a place to synch up with weenix. In the * past the weenix command started qemu was started with -S which * allowed gdb to connect and start before the boot loader ran, but * since then a bug has appeared where breakpoints fail if gdb connects * before the boot loader runs. See * * https://bugs.launchpad.net/qemu/+bug/526653 * * This loop (along with an additional command in init.gdb setting * gdb_wait to 0) sticks weenix at a known place so gdb can join a * running weenix, set gdb_wait to zero and catch the breakpoint in * bootstrap below. See Config.mk for how to set GDBWAIT correctly. * * DANGER: if GDBWAIT != 0, and gdb is not running, this loop will never * exit and weenix will not run. Make SURE the GDBWAIT is set the way * you expect. */ while (gdb_wait) ; context_setup(&bootstrap_context, bootstrap, 0, NULL, bstack, PAGE_SIZE, bpdir); context_make_active(&bootstrap_context); panic("\nReturned to kmain()!!!\n"); }
/*===========================================================================* * cstart * *===========================================================================*/ void cstart() { /* Perform system initializations prior to calling main(). Most settings are * determined with help of the environment strings passed by MINIX' loader. */ register char *value; /* value in key=value pair */ int h; /* low-level initialization */ prot_init(); /* determine verbosity */ if ((value = env_get(VERBOSEBOOTVARNAME))) verboseboot = atoi(value); /* Get clock tick frequency. */ value = env_get("hz"); if(value) system_hz = atoi(value); if(!value || system_hz < 2 || system_hz > 50000) /* sanity check */ system_hz = DEFAULT_HZ; DEBUGEXTRA(("cstart\n")); /* Record miscellaneous information for user-space servers. */ kinfo.nr_procs = NR_PROCS; kinfo.nr_tasks = NR_TASKS; strlcpy(kinfo.release, OS_RELEASE, sizeof(kinfo.release)); strlcpy(kinfo.version, OS_VERSION, sizeof(kinfo.version)); /* Load average data initialization. */ kloadinfo.proc_last_slot = 0; for(h = 0; h < _LOAD_HISTORY; h++) kloadinfo.proc_load_history[h] = 0; #ifdef USE_APIC value = env_get("no_apic"); if(value) config_no_apic = atoi(value); else config_no_apic = 1; value = env_get("apic_timer_x"); if(value) config_apic_timer_x = atoi(value); else config_apic_timer_x = 1; #endif #ifdef USE_WATCHDOG value = env_get("watchdog"); if (value) watchdog_enabled = atoi(value); #endif #ifdef CONFIG_SMP if (config_no_apic) config_no_smp = 1; value = env_get("no_smp"); if(value) config_no_smp = atoi(value); else config_no_smp = 0; #endif DEBUGEXTRA(("intr_init(0)\n")); intr_init(0); arch_init(); }
/*===========================================================================* * 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); }
int smd_core_platform_init(struct platform_device *pdev) { int i; int ret; uint32_t num_ss; struct smd_platform *smd_platform_data; struct smd_subsystem_config *smd_ss_config_list; struct smd_subsystem_config *cfg; struct interrupt_config *private_intr_config; int err_ret = 0; smd_platform_data = pdev->dev.platform_data; num_ss = smd_platform_data->num_ss_configs; smd_ss_config_list = smd_platform_data->smd_ss_configs; if (smd_platform_data->smd_ssr_config) disable_smsm_reset_handshake = smd_platform_data-> smd_ssr_config->disable_smsm_reset_handshake; for (i = 0; i < num_ss; i++) { cfg = &smd_ss_config_list[i]; private_intr_config = smd_get_intr_config(cfg->edge); if (!private_intr_config) { pr_err("%s: invalid edge\n", __func__); goto intr_failed; } ret = intr_init( &private_intr_config->smd, &cfg->smd_int, pdev ); if (ret < 0) { err_ret = ret; pr_err("smd: register irq failed on %s\n", cfg->smd_int.irq_name); goto intr_failed; } interrupt_stats[cfg->irq_config_id].smd_interrupt_id = cfg->smd_int.irq_id; if (cfg->smsm_int.irq_id) ret = intr_init( &private_intr_config->smsm, &cfg->smsm_int, pdev ); if (ret < 0) { err_ret = ret; pr_err("smd: register irq failed on %s\n", cfg->smsm_int.irq_name); goto intr_failed; } if (cfg->smsm_int.irq_id) interrupt_stats[cfg->irq_config_id].smsm_interrupt_id = cfg->smsm_int.irq_id; if (cfg->subsys_name) smd_set_edge_subsys_name(cfg->edge, cfg->subsys_name); smd_set_edge_initialized(cfg->edge); } SMD_INFO("smd_core_platform_init() done\n"); return 0; intr_failed: pr_err("smd: deregistering IRQs\n"); for (i = 0; i < num_ss; ++i) { cfg = &smd_ss_config_list[i]; if (cfg->smd_int.irq_id >= 0) free_irq(cfg->smd_int.irq_id, (void *)cfg->smd_int.dev_id ); if (cfg->smsm_int.irq_id >= 0) free_irq(cfg->smsm_int.irq_id, (void *)cfg->smsm_int.dev_id ); } return err_ret; }
/*===========================================================================* * 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); }
/* * Machine-dependent startup code */ void cpu_startup() { caddr_t v; int sz; #ifdef DEBUG extern int pmapdebug; int opmapdebug = pmapdebug; #endif vaddr_t minaddr, maxaddr; extern struct user *proc0paddr; #ifdef DEBUG pmapdebug = 0; #endif if (CPU_ISSUN4M) { extern int stackgap_random; stackgap_random = STACKGAP_RANDOM_SUN4M; } /* * fix message buffer mapping, note phys addr of msgbuf is 0 */ pmap_map(MSGBUF_VA, 0, MSGBUFSIZE, VM_PROT_READ|VM_PROT_WRITE); initmsgbuf((caddr_t)(MSGBUF_VA + (CPU_ISSUN4 ? 4096 : 0)), MSGBUFSIZE); proc0.p_addr = proc0paddr; /* * Good {morning,afternoon,evening,night}. */ printf(version); /*identifycpu();*/ printf("real mem = %u (%uMB)\n", ptoa(physmem), ptoa(physmem)/1024/1024); /* * Find out how much space we need, allocate it, * and then give everything true virtual addresses. */ sz = (int)allocsys((caddr_t)0); if ((v = (caddr_t)uvm_km_alloc(kernel_map, round_page(sz))) == 0) panic("startup: no room for tables"); if (allocsys(v) - v != sz) panic("startup: table size inconsistency"); /* * Determine how many buffers to allocate. * We allocate bufcachepercent% of memory for buffer space. */ if (bufpages == 0) bufpages = physmem * bufcachepercent / 100; /* Restrict to at most 25% filled kvm */ if (bufpages > (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4) bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4; /* * Allocate a submap for exec arguments. This map effectively * limits the number of processes exec'ing at any time. */ minaddr = vm_map_min(kernel_map); exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); /* * Allocate a map for physio. Others use a submap of the kernel * map, but we want one completely separate, even though it uses * the same pmap. */ dvma_base = CPU_ISSUN4M ? DVMA4M_BASE : DVMA_BASE; dvma_end = CPU_ISSUN4M ? DVMA4M_END : DVMA_END; #if defined(SUN4M) if (CPU_ISSUN4M) { /* * The DVMA space we want partially overrides kernel_map. * Allocate it in kernel_map as well to prevent it from being * used for other things. */ if (uvm_map(kernel_map, &dvma_base, vm_map_max(kernel_map) - dvma_base, NULL, UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, UVM_ADV_NORMAL, 0))) panic("startup: can not steal dvma map"); } #endif phys_map = uvm_map_create(pmap_kernel(), dvma_base, dvma_end, VM_MAP_INTRSAFE); if (phys_map == NULL) panic("unable to create DVMA map"); /* * Allocate DVMA space and dump into a privately managed * resource map for double mappings which is usable from * interrupt contexts. */ if (uvm_km_valloc_wait(phys_map, (dvma_end-dvma_base)) != dvma_base) panic("unable to allocate from DVMA map"); dvmamap_extent = extent_create("dvmamap", dvma_base, dvma_end, M_DEVBUF, NULL, 0, EX_NOWAIT); if (dvmamap_extent == 0) panic("unable to allocate extent for dvma"); #ifdef DEBUG pmapdebug = opmapdebug; #endif printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free), ptoa(uvmexp.free)/1024/1024); /* * Set up buffers, so they can be used to read disk labels. */ bufinit(); /* Early interrupt handlers initialization */ intr_init(); }
/* * Machine-dependent startup code */ void cpu_startup() { #ifdef DEBUG extern int pmapdebug; int opmapdebug = pmapdebug; #endif vaddr_t minaddr, maxaddr; paddr_t msgbufpa; extern struct user *proc0paddr; #ifdef DEBUG pmapdebug = 0; #endif if (CPU_ISSUN4M) { extern int stackgap_random; stackgap_random = STACKGAP_RANDOM_SUN4M; } /* * Re-map the message buffer from its temporary address * at KERNBASE to MSGBUF_VA. */ /* Get physical address of the message buffer */ pmap_extract(pmap_kernel(), (vaddr_t)KERNBASE, &msgbufpa); /* Invalidate the current mapping at KERNBASE. */ pmap_kremove((vaddr_t)KERNBASE, PAGE_SIZE); pmap_update(pmap_kernel()); /* Enter the new mapping */ pmap_map(MSGBUF_VA, msgbufpa, msgbufpa + PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE); /* Re-initialize the message buffer. */ initmsgbuf((caddr_t)(MSGBUF_VA + (CPU_ISSUN4 ? 4096 : 0)), MSGBUFSIZE); proc0.p_addr = proc0paddr; /* * Good {morning,afternoon,evening,night}. */ printf(version); /*identifycpu();*/ printf("real mem = %u (%uMB)\n", ptoa(physmem), ptoa(physmem)/1024/1024); /* * Allocate a submap for exec arguments. This map effectively * limits the number of processes exec'ing at any time. */ minaddr = vm_map_min(kernel_map); exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); /* * Allocate a map for physio. Others use a submap of the kernel * map, but we want one completely separate, even though it uses * the same pmap. */ dvma_base = CPU_ISSUN4M ? DVMA4M_BASE : DVMA_BASE; dvma_end = CPU_ISSUN4M ? DVMA4M_END : DVMA_END; dvmamap_extent = extent_create("dvmamap", dvma_base, dvma_end, M_DEVBUF, NULL, 0, EX_NOWAIT); if (dvmamap_extent == NULL) panic("unable to allocate extent for dvma"); #ifdef DEBUG pmapdebug = opmapdebug; #endif printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free), ptoa(uvmexp.free)/1024/1024); /* * Set up buffers, so they can be used to read disk labels. */ bufinit(); /* Early interrupt handlers initialization */ intr_init(); }
/*===========================================================================* * 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); }