// Allocate and initialize a new proc as child 'cn' of parent 'p'. // Returns NULL if no physical memory available. proc * proc_alloc(proc *p, uint32_t cn) { pageinfo *pi = mem_alloc(); if (!pi) return NULL; mem_incref(pi); proc *cp = (proc*)mem_pi2ptr(pi); memset(cp, 0, sizeof(proc)); spinlock_init(&cp->lock); cp->parent = p; cp->state = PROC_STOP; // Integer register state cp->sv.tf.eflags = (FL_IOPL_MASK & FL_IOPL_3) | FL_IF; cp->sv.tf.cs = CPU_GDT_UCODE | 3; cp->sv.tf.ds = CPU_GDT_UDATA | 3; cp->sv.tf.es = CPU_GDT_UDATA | 3; cp->sv.tf.cs = CPU_GDT_UCODE | 3; cp->sv.tf.ss = CPU_GDT_UDATA | 3; if (p) p->child[cn] = cp; return cp; }
// Allocate and initialize a new proc as child 'cn' of parent 'p'. // Returns NULL if no physical memory available. proc * proc_alloc(proc *p, uint32_t cn) { pageinfo *pi = mem_alloc(); if (!pi) return NULL; mem_incref(pi); proc *cp = (proc*)mem_pi2ptr(pi); memset(cp, 0, sizeof(proc)); spinlock_init(&cp->lock); cp->parent = p; cp->state = PROC_STOP; cp->home = RRCONS(net_node, mem_phys(cp), 0); //Page directories - we might need this stuff, idk, merge conflict // cp->pdir = pmap_newpdir(); // cp->rpdir = pmap_newpdir(); // Integer register state cp->sv.tf.ds = CPU_GDT_UDATA | 3; cp->sv.tf.es = CPU_GDT_UDATA | 3; cp->sv.tf.cs = CPU_GDT_UCODE | 3; cp->sv.tf.ss = CPU_GDT_UDATA | 3; cp->pdir = pmap_newpdir(); if (!cp->pdir) return NULL; cp->rpdir = pmap_newpdir(); if (!cp->rpdir) { pmap_freepdir(mem_ptr2pi(cp->pdir)); return NULL; } if (p) p->child[cn] = cp; return cp; }
// // Check the physical page allocator (mem_alloc(), mem_free()) // for correct operation after initialization via mem_init(). // void mem_check() { pageinfo *pp, *pp0, *pp1, *pp2; pageinfo *fl; int i; // if there's a page that shouldn't be on // the free list, try to make sure it // eventually causes trouble. int freepages = 0; for (pp = mem_freelist; pp != 0; pp = pp->free_next) { memset(mem_pi2ptr(pp), 0x97, 128); freepages++; } cprintf("mem_check: %d free pages\n", freepages); assert(freepages < mem_npage); // can't have more free than total! assert(freepages > 16000); // make sure it's in the right ballpark // should be able to allocate three pages pp0 = pp1 = pp2 = 0; pp0 = mem_alloc(); assert(pp0 != 0); pp1 = mem_alloc(); assert(pp1 != 0); pp2 = mem_alloc(); assert(pp2 != 0); assert(pp0); assert(pp1 && pp1 != pp0); assert(pp2 && pp2 != pp1 && pp2 != pp0); assert(mem_pi2phys(pp0) < mem_npage*PAGESIZE); assert(mem_pi2phys(pp1) < mem_npage*PAGESIZE); assert(mem_pi2phys(pp2) < mem_npage*PAGESIZE); // temporarily steal the rest of the free pages fl = mem_freelist; mem_freelist = 0; // should be no free memory assert(mem_alloc() == 0); // free and re-allocate? mem_free(pp0); mem_free(pp1); mem_free(pp2); pp0 = pp1 = pp2 = 0; pp0 = mem_alloc(); assert(pp0 != 0); pp1 = mem_alloc(); assert(pp1 != 0); pp2 = mem_alloc(); assert(pp2 != 0); assert(pp0); assert(pp1 && pp1 != pp0); assert(pp2 && pp2 != pp1 && pp2 != pp0); assert(mem_alloc() == 0); // give free list back mem_freelist = fl; // free the pages we took mem_free(pp0); mem_free(pp1); mem_free(pp2); cprintf("mem_check() succeeded!\n"); }
// Called first from entry.S on the bootstrap processor, // and later from boot/bootother.S on all other processors. // As a rule, "init" functions in PIOS are called once on EACH processor. void init(void) { extern char start[], edata[], end[]; // Before anything else, complete the ELF loading process. // Clear all uninitialized global data (BSS) in our program, // ensuring that all static/global variables start out zero. if (cpu_onboot()) memset(edata, 0, end - edata); // Initialize the console. // Can't call cprintf until after we do this! cons_init(); extern uint8_t _binary_obj_boot_bootother_start[], _binary_obj_boot_bootother_size[]; uint8_t *code = (uint8_t*)lowmem_bootother_vec; memmove(code, _binary_obj_boot_bootother_start, (uint32_t) _binary_obj_boot_bootother_size); // Lab 1: test cprintf and debug_trace cprintf("1234 decimal is %o octal!\n", 1234); debug_check(); // Initialize and load the bootstrap CPU's GDT, TSS, and IDT. cpu_init(); trap_init(); // Physical memory detection/initialization. // Can't call mem_alloc until after we do this! mem_init(); // Lab 2: check spinlock implementation if (cpu_onboot()) spinlock_check(); // Initialize the paged virtual memory system. pmap_init(); // Find and start other processors in a multiprocessor system mp_init(); // Find info about processors in system pic_init(); // setup the legacy PIC (mainly to disable it) ioapic_init(); // prepare to handle external device interrupts lapic_init(); // setup this CPU's local APIC cpu_bootothers(); // Get other processors started // cprintf("CPU %d (%s) has booted\n", cpu_cur()->id, // cpu_onboot() ? "BP" : "AP"); file_init(); // Create root directory and console I/O files // Lab 4: uncomment this when you can handle IRQ_SERIAL and IRQ_KBD. //cons_intenable(); // Let the console start producing interrupts // Initialize the process management code. proc_init(); // Initialize the process management code. proc_init(); if(!cpu_onboot()) proc_sched(); proc *root = proc_root = proc_alloc(NULL,0); elfhdr *ehs = (elfhdr *)ROOTEXE_START; assert(ehs->e_magic == ELF_MAGIC); proghdr *phs = (proghdr *) ((void *) ehs + ehs->e_phoff); proghdr *ep = phs + ehs->e_phnum; for (; phs < ep; phs++) { if (phs->p_type != ELF_PROG_LOAD) continue; void *fa = (void *) ehs + ROUNDDOWN(phs->p_offset, PAGESIZE); uint32_t va = ROUNDDOWN(phs->p_va, PAGESIZE); uint32_t zva = phs->p_va + phs->p_filesz; uint32_t eva = ROUNDUP(phs->p_va + phs->p_memsz, PAGESIZE); uint32_t perm = SYS_READ | PTE_P | PTE_U; if(phs->p_flags & ELF_PROG_FLAG_WRITE) perm |= SYS_WRITE | PTE_W; for (; va < eva; va += PAGESIZE, fa += PAGESIZE) { pageinfo *pi = mem_alloc(); assert(pi != NULL); if(va < ROUNDDOWN(zva, PAGESIZE)) memmove(mem_pi2ptr(pi), fa, PAGESIZE); else if (va < zva && phs->p_filesz) { memset(mem_pi2ptr(pi),0, PAGESIZE); memmove(mem_pi2ptr(pi), fa, zva-va); } else memset(mem_pi2ptr(pi), 0, PAGESIZE); pte_t *pte = pmap_insert(root->pdir, pi, va, perm); assert(pte != NULL); } } root->sv.tf.eip = ehs->e_entry; root->sv.tf.eflags |= FL_IF; pageinfo *pi = mem_alloc(); assert(pi != NULL); pte_t *pte = pmap_insert(root->pdir, pi, VM_STACKHI-PAGESIZE, SYS_READ | SYS_WRITE | PTE_P | PTE_U | PTE_W); assert(pte != NULL); root->sv.tf.esp = VM_STACKHI; proc_ready(root); proc_sched(); // Initialize the I/O system. // Lab 1: change this so it enters user() in user mode, // running on the user_stack declared above, // instead of just calling user() directly. user(); // FIXME: Maybe get rid of this }