void file_init(void) { if (!cpu_onboot()) return; spinlock_init(&file_lock); }
void mp_init(void) { uint8_t *p, *e; struct mp *mp; struct mpconf *conf; struct mpproc *proc; struct mpioapic *mpio; if (!cpu_onboot()) // only do once, on the boot CPU return; if ((conf = mpconfig(&mp)) == 0) return; // Not a multiprocessor machine - just use boot CPU. ismp = 1; lapic = (uint32_t *) conf->lapicaddr; for (p = (uint8_t *) (conf + 1), e = (uint8_t *) conf + conf->length; p < e;) { switch (*p) { case MPPROC: proc = (struct mpproc *) p; p += sizeof(struct mpproc); if (!(proc->flags & MPENAB)) continue; // processor disabled // Get a cpu struct and kernel stack for this CPU. cpu *c = (proc->flags & MPBOOT) ? &cpu_boot : cpu_alloc(); c->id = proc->apicid; #if LAB >= 9 c->num = ncpu; // also assign sequential CPU numbers #endif ncpu++; continue; case MPIOAPIC: mpio = (struct mpioapic *) p; p += sizeof(struct mpioapic); ioapicid = mpio->apicno; ioapic = (struct ioapic *) mpio->addr; continue; case MPBUS: case MPIOINTR: case MPLINTR: p += 8; continue; default: panic("mpinit: unknown config type %x\n", *p); } } if (mp->imcrp) { // Bochs doesn 't support IMCR, so this doesn' t run on Bochs. // But it would on real hardware. outb(0x22, 0x70); // Select IMCR outb(0x23, inb(0x23) | 1); // Mask external interrupts. } }
// Enable console interrupts. void cons_intenable(void) { if (!cpu_onboot()) // only do once, on the boot CPU return; kbd_intenable(); serial_intenable(); }
void proc_init(void) { if (!cpu_onboot()) return; spinlock_init(&proc_lock); proc_first = NULL; proc_last = NULL; }
void proc_init(void) { if (!cpu_onboot()) return; // your module initialization code here spinlock_init(&proc_lock); proc_head = proc_tail = NULL; }
// initialize the console devices void cons_init(void) { if (!cpu_onboot()) // only do once, on the boot CPU return; video_init(); kbd_init(); serial_init(); if (!serial_exists) warn("Serial port does not exist!\n"); }
void mem_init(void) { if (!cpu_onboot()) // only do once, on the boot CPU return; // Determine how much base (<640K) and extended (>1MB) memory // is available in the system (in bytes), // by reading the PC's BIOS-managed nonvolatile RAM (NVRAM). // The NVRAM tells us how many kilobytes there are. // Since the count is 16 bits, this gives us up to 64MB of RAM; // additional RAM beyond that would have to be detected another way. size_t basemem = ROUNDDOWN(nvram_read16(NVRAM_BASELO)*1024, PAGESIZE); size_t extmem = ROUNDDOWN(nvram_read16(NVRAM_EXTLO)*1024, PAGESIZE); warn("Assuming we have 1GB of memory!"); extmem = 1024*1024*1024 - MEM_EXT; // assume 1GB total memory // The maximum physical address is the top of extended memory. mem_max = MEM_EXT + extmem; // Compute the total number of physical pages (including I/O holes) mem_npage = mem_max / PAGESIZE; cprintf("Physical memory: %dK available, ", (int)(mem_max/1024)); cprintf("base = %dK, extended = %dK\n", (int)(basemem/1024), (int)(extmem/1024)); spinlock_init(&_freelist_lock); pageinfo *mem_pageinfo = (pageinfo*)ROUNDUP((uint32_t)end, (uint32_t)sizeof(pageinfo)); memset(mem_pageinfo, 0, sizeof(pageinfo)*mem_npage); pageinfo **freetail = &mem_freelist; int i; // Pages 0 and 1 are reserved. for (i = 2; i < mem_npage; i++) { // All of base memory otherwise is free after the kernel // and the pageinfo table all memory should be free if(i < basemem/4096 || i >= (uint32_t)(ROUNDUP(&mem_pageinfo[mem_npage],4096))/4096) { // A free page has no references to it. mem_pageinfo[i].refcount = 0; // Add the page to the end of the free list. *freetail = &mem_pageinfo[i]; freetail = &mem_pageinfo[i].free_next; } } *freetail = NULL; // null-terminate the freelist // Check to make sure the page allocator seems to work correctly. mem_check(); }
// initialize the console devices void cons_init(void) { if (!cpu_onboot()) // only do once, on the boot CPU return; spinlock_init(&cons_lock); video_init(); kbd_init(); serial_init(); cons_out_pos = 0; if (!serial_exists) warn("Serial port does not exist!\n"); }
// Initialize the programmable interval timer. void timer_init(void) { if (!cpu_onboot()) return; spinlock_init(&lock); // Initialize 8253 clock 0 to the maximum counter value, 65535. outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(IO_TIMER1, 0xff); outb(IO_TIMER1, 0xff); #if LAB >= 99 //cprintf(" Setup timer interrupts via 8259A\n"); //pic_enable(IRQ_TIMER); #endif }
void acpi_init(void) { if (!cpu_onboot()) return; int rev = 0; void *p = rsdpsearch(&rev); if (!p) return; #ifdef DEBUG cprintf("rsdp %p rev %u\n", p, rev); #endif ismp = 1; if (rev == 1) { struct acpi_rsdp *rsdp = p; struct acpi_rsdt *rsdt = mem_ptr(rsdp->rsdtaddr); #ifdef DEBUG cprintf("rsdp %p rsdt %p size %u\n", mem_phys(rsdp), mem_phys(rsdt), sizeof (struct acpi2_rsdp)); #endif rsdt_scan(rsdt); } else if (rev == 2) { struct acpi2_rsdp *rsdp = p; #ifdef DEBUG cprintf("rsdp %p rev %u\n", mem_phys(rsdp), rsdp->revision); #endif struct acpi_rsdt *rsdt = mem_ptr(rsdp->rsdtaddr); struct acpi2_xsdt *xsdt = mem_ptr(rsdp->xsdtaddr); #ifdef DEBUG cprintf("rsdp %p rsdt %p xsdt %p len %u size %u\n", mem_phys(rsdp), mem_phys(rsdt), mem_phys(xsdt), rsdp->length, sizeof (struct acpi2_rsdp)); #endif if (rsdt_scan(rsdt)) return; xsdt_scan(xsdt); } else { return; } }
void mem_init(void) { if (!cpu_onboot()) // only do once, on the boot CPU return; // Determine how much base (<640K) and extended (>1MB) memory // is available in the system (in bytes), // by reading the PC's BIOS-managed nonvolatile RAM (NVRAM). // The NVRAM tells us how many kilobytes there are. // Since the count is 16 bits, this gives us up to 64MB of RAM; // additional RAM beyond that would have to be detected another way. size_t basemem = ROUNDDOWN(nvram_read16(NVRAM_BASELO)*1024, PAGESIZE); size_t extmem = ROUNDDOWN(nvram_read16(NVRAM_EXTLO)*1024, PAGESIZE); warn("Assuming we have 1GB of memory!"); extmem = 1024*1024*1024 - MEM_EXT; // assume 1GB total memory // The maximum physical address is the top of extended memory. mem_max = MEM_EXT + extmem; // Compute the total number of physical pages (including I/O holes) mem_npage = mem_max / PAGESIZE; cprintf("Physical memory: %dK available, ", (int)(mem_max/1024)); cprintf("base = %dK, extended = %dK\n", (int)(basemem/1024), (int)(extmem/1024)); // Insert code here to: // (1) allocate physical memory for the mem_pageinfo array, // making it big enough to hold mem_npage entries. // (2) add all pageinfo structs in the array representing // available memory that is not in use for other purposes. // // For step (2), here is some incomplete/incorrect example code // that simply marks all mem_npage pages as free. // Which memory is actually free? // 1) Reserve page 0 for the real-mode IDT and BIOS structures // (do not allow this page to be used for anything else). // 2) Reserve page 1 for the AP bootstrap code (boot/bootother.S). // 3) Mark the rest of base memory as free. // 4) Then comes the IO hole [MEM_IO, MEM_EXT). // Mark it as in-use so that it can never be allocated. // 5) Then extended memory [MEM_EXT, ...). // Some of it is in use, some is free. // Which pages hold the kernel and the pageinfo array? // Hint: the linker places the kernel (see start and end above), // but YOU decide where to place the pageinfo array. // Change the code to reflect this. pageinfo **freetail = &mem_freelist; int i; for (i = 0; i < mem_npage; i++) { // A free page has no references to it. mem_pageinfo[i].refcount = 0; // Add the page to the end of the free list. *freetail = &mem_pageinfo[i]; freetail = &mem_pageinfo[i].free_next; } *freetail = NULL; // null-terminate the freelist // ...and remove this when you're ready. panic("mem_init() not implemented"); // Check to make sure the page allocator seems to work correctly. mem_check(); }
// 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 }