void himem_revert( hil_t hil) { hil_t next; boolean_t wakeup = FALSE; spl_t ipl; while(hil) { if (hil->length) { bcopy((char *)phystokv(hil->low_page + hil->offset), (char *)phystokv(hil->high_addr), hil->length); } hil->high_addr = 0; hil->length = 0; hil->offset = 0; next = hil->next; ipl = splhi(); simple_lock(&hil_lock); if (!(hil->next = hil_head)) wakeup = TRUE; hil_head = hil; simple_unlock(&hil_lock); splx(ipl); hil = next; } if (wakeup) thread_wakeup((event_t)&hil_head); }
/** * pmap_copy_page * * Copy a specified page to another page. */ void pmap_copy_page( ppnum_t src, ppnum_t dst) { assert(src != vm_page_fictitious_addr); assert(dst != vm_page_fictitious_addr); memcpy((void *)phystokv(dst), (void *)phystokv(src), PAGE_SIZE); }
void bootstrap_create() { struct multiboot_module *bmod; if (!(boot_info->flags & MULTIBOOT_MODS) || (boot_info->mods_count == 0)) panic("No bootstrap code loaded with the kernel!"); if (boot_info->mods_count > 1) printf("Warning: only one boot module currently used by Mach\n"); bmod = (struct multiboot_module *)phystokv(boot_info->mods_addr); bootstrap_exec((void*)phystokv(bmod->mod_start)); /* XXX at this point, we could free all the memory used by the boot modules and the boot loader's descriptors and such. */ }
/* * copy_from_phys(src_addr_p, dst_addr_v, count) * * Copy physical memory to virtual memory. The virtual memory * is assumed to be present (e.g. the buffer pool). */ void copy_from_phys( vm_offset_t src_addr_p, vm_offset_t dst_addr_v, int count) { vm_offset_t src_addr_v; pmap_mapwindow_t *src_map; boolean_t mapped = src_addr_p >= phys_last_addr; assert(src_addr_p != vm_page_fictitious_addr); assert(pa_to_pte(src_addr_p + count-1) == pa_to_pte(src_addr_p)); if (mapped) { src_map = pmap_get_mapwindow(INTEL_PTE_R(src_addr_p)); src_addr_v = src_map->vaddr; } else src_addr_v = phystokv(src_addr_p); memcpy((void *)dst_addr_v, (void *)src_addr_v, count); if (mapped) pmap_put_mapwindow(src_map); }
void multiboot_main(unsigned int boot_info_pa) { int argc = 0; char **argv = 0; int ret; /* Copy the multiboot_info structure into our pre-reserved area. This avoids one loose fragment of memory that has to be avoided. */ boot_info = *(struct multiboot_info*)phystokv(boot_info_pa); /* * Initialize the processor tables. ie default handlers etc. */ base_cpu_setup(); /* * Initialize the floating point unit. */ /*base_fpu_init();*/ /* Initialize the memory allocator and find all available memory. */ base_multiboot_init_mem(); /* Parse the command line into nice POSIX-like args and environment. */ base_multiboot_init_cmdline(&argc, &argv); enable_interrupts(); /* Invoke the main program. */ ret = kernel_main(argc, argv, environ); printf( "base_multiboot_main.c: kernel main returned with code %d\n", ret ); while(1); }
/* * Map physical memory into kernel virtual space. */ int osenv_mem_map_phys(oskit_addr_t pa, oskit_size_t size, void **addr, int flags) { *addr = (void *)phystokv(pa); return (0); }
static errno_t startSync( phantom_disk_partition_t *p, void *to, long blockNo, int nBlocks, int isWrite ) { assert( p->block_size < PAGE_SIZE ); SHOW_FLOW( 3, "blk %d", blockNo ); pager_io_request rq; pager_io_request_init( &rq ); rq.phys_page = (physaddr_t)phystokv(to); // why? redundant? rq.disk_page = blockNo; rq.blockNo = blockNo; rq.nSect = nBlocks; rq.rc = 0; if(isWrite) rq.flag_pageout = 1; else rq.flag_pagein = 1; STAT_INC_CNT(STAT_CNT_BLOCK_SYNC_IO); STAT_INC_CNT( STAT_CNT_DISK_Q_SIZE ); // Will decrement on io done void *va; hal_pv_alloc( &rq.phys_page, &va, nBlocks * p->block_size ); errno_t ret = EINVAL; if(isWrite) memcpy( va, to, nBlocks * p->block_size ); int ei = hal_save_cli(); hal_spin_lock(&(rq.lock)); rq.flag_sleep = 1; // Don't return until done rq.sleep_tid = GET_CURRENT_THREAD()->tid; SHOW_FLOW0( 3, "start io" ); if( (ret = p->asyncIo( p, &rq )) ) { rq.flag_sleep = 0; hal_spin_unlock(&(rq.lock)); if( ei ) hal_sti(); //return ret; goto ret; } thread_block( THREAD_SLEEP_IO, &(rq.lock) ); SHOW_FLOW0( 3, "unblock" ); if( ei ) hal_sti(); if(!isWrite) memcpy( to, va, nBlocks * p->block_size ); ret = rq.rc; //return partAsyncIo( p, &rq ); //return p->asyncIo( p, rq ); ret: hal_pv_free( rq.phys_page, va, nBlocks * p->block_size ); return ret; }
vm_offset_t himem_convert( vm_offset_t phys_addr, vm_size_t length, int io_op, hil_t *hil) { hil_t h; spl_t ipl; vm_offset_t offset = phys_addr & (I386_PGBYTES - 1); assert (offset + length <= I386_PGBYTES); ipl = splhi(); simple_lock(&hil_lock); while (!(h = hil_head)) { printf("WARNING: out of HIMEM pages\n"); thread_sleep_simple_lock((event_t)&hil_head, simple_lock_addr(hil_lock), FALSE); simple_lock (&hil_lock); } hil_head = hil_head->next; simple_unlock(&hil_lock); splx(ipl); h->high_addr = phys_addr; if (io_op == D_WRITE) { bcopy((char *)phystokv(phys_addr), (char *)phystokv(h->low_page + offset), length); h->length = 0; } else { h->length = length; } h->offset = offset; assert(!*hil || (*hil)->high_addr); h->next = *hil; *hil = h; return(h->low_page + offset); }
static int boot_read(void *handle, vm_offset_t file_ofs, void *buf, vm_size_t size, vm_size_t *out_actual) { struct multiboot_module *mod = handle; if (mod->mod_start + file_ofs + size > mod->mod_end) return -1; memcpy(buf, (const char*) phystokv (mod->mod_start) + file_ofs, size); *out_actual = size; return 0; }
/* * Find devices. The system is alive. */ void machine_init(void) { /* * Initialize the console. */ cninit(); /* * Set up to use floating point. */ init_fpu(); #ifdef MACH_HYP hyp_init(); #else /* MACH_HYP */ #ifdef LINUX_DEV /* * Initialize Linux drivers. */ linux_init(); #endif /* * Find the devices */ probeio(); #endif /* MACH_HYP */ /* * Get the time */ inittodr(); #ifndef MACH_HYP /* * Tell the BIOS not to clear and test memory. */ *(unsigned short *)phystokv(0x472) = 0x1234; #endif /* MACH_HYP */ #if VM_MIN_KERNEL_ADDRESS == 0 /* * Unmap page 0 to trap NULL references. * * Note that this breaks accessing some BIOS areas stored there. */ pmap_unmap_page_zero(); #endif }
/* * pmap_copy_page copies the specified (machine independent) pages. */ void pmap_copy_page( vm_offset_t src, vm_offset_t dst) { vm_offset_t src_addr_v, dst_addr_v; pmap_mapwindow_t *src_map = NULL; pmap_mapwindow_t *dst_map; boolean_t src_mapped = src >= phys_last_addr; boolean_t dst_mapped = dst >= phys_last_addr; assert(src != vm_page_fictitious_addr); assert(dst != vm_page_fictitious_addr); if (src_mapped) { src_map = pmap_get_mapwindow(INTEL_PTE_R(src)); src_addr_v = src_map->vaddr; } else src_addr_v = phystokv(src); if (dst_mapped) { dst_map = pmap_get_mapwindow(INTEL_PTE_W(dst)); dst_addr_v = dst_map->vaddr; } else dst_addr_v = phystokv(dst); memcpy((void *) dst_addr_v, (void *) src_addr_v, PAGE_SIZE); if (src_mapped) pmap_put_mapwindow(src_map); if (dst_mapped) pmap_put_mapwindow(dst_map); }
static int read_exec(void *handle, vm_offset_t file_ofs, vm_size_t file_size, vm_offset_t mem_addr, vm_size_t mem_size, exec_sectype_t sec_type) { struct multiboot_module *mod = handle; vm_map_t user_map = current_task()->map; vm_offset_t start_page, end_page; vm_prot_t mem_prot = sec_type & EXEC_SECTYPE_PROT_MASK; int err; if (mod->mod_start + file_ofs + file_size > mod->mod_end) return -1; if (!(sec_type & EXEC_SECTYPE_ALLOC)) return 0; assert(mem_size > 0); assert(mem_size >= file_size); start_page = trunc_page(mem_addr); end_page = round_page(mem_addr + mem_size); #if 0 printf("reading bootstrap section %08x-%08x-%08x prot %d pages %08x-%08x\n", mem_addr, mem_addr+file_size, mem_addr+mem_size, mem_prot, start_page, end_page); #endif err = vm_allocate(user_map, &start_page, end_page - start_page, FALSE); assert(err == 0); assert(start_page == trunc_page(mem_addr)); if (file_size > 0) { err = copyout((char *)phystokv (mod->mod_start) + file_ofs, (void *)mem_addr, file_size); assert(err == 0); } if (mem_prot != VM_PROT_ALL) { err = vm_protect(user_map, start_page, end_page - start_page, FALSE, mem_prot); assert(err == 0); } return 0; }
/* * Compute physical memory size and other parameters. */ void mem_size_init(void) { vm_offset_t max_phys_size; /* Physical memory on all PCs starts at physical address 0. XX make it a constant. */ phys_first_addr = 0; #ifdef MACH_HYP if (boot_info.nr_pages >= 0x100000) { printf("Truncating memory size to 4GiB\n"); phys_last_addr = 0xffffffffU; } else phys_last_addr = boot_info.nr_pages * 0x1000; #else /* MACH_HYP */ vm_size_t phys_last_kb; if (boot_info.flags & MULTIBOOT_MEM_MAP) { struct multiboot_mmap *map, *map_end; map = (void*) phystokv(boot_info.mmap_addr); map_end = (void*) map + boot_info.mmap_count; while (map + 1 <= map_end) { if (map->Type == MB_ARD_MEMORY) { unsigned long long start = map->BaseAddr, end = map->BaseAddr + map->Length;; if (start >= 0x100000000ULL) { printf("Ignoring %luMiB RAM region above 4GiB\n", (unsigned long) (map->Length >> 20)); } else { if (end >= 0x100000000ULL) { printf("Truncating memory region to 4GiB\n"); end = 0x0ffffffffU; } if (end > phys_last_addr) phys_last_addr = end; printf("AT386 boot: physical memory map from 0x%lx to 0x%lx\n", (unsigned long) start, (unsigned long) end); } }
void pc_reset() { int i; /* Inform BIOS that this is a warm boot. */ *(unsigned short *)phystokv(0x472) = 0x1234; /* Try to reset using the keyboard controller. */ for (i = 0; i < 100; i++) { kb_command(KC_CMD_PULSE & ~KO_SYSRESET); } /* If that fails, try the ultimate kludge: clearing the IDT and causing a "triple fault" so that the processor is forced to reset itself. */ set_idt(&null_pdesc); asm("int $3"); }
void mb_util_cmdline(mbinfo_t *mbi, int *argc, char ***argv, char ***envp) { if (mbi->flags & MULTIBOOT_CMDLINE) { char *cl = (char*)phystokv(mbi->cmdline); unsigned cllen = strlen(cl); char *targ[1 + cllen], *tvar[cllen]; unsigned narg = 0, nvar = 0; char *tok; /* Parse out the tokens in the command line. XXX Might be good to handle quotes. */ for (tok = strtok(cl, delim); tok; tok = strtok(0, delim)) { if (strchr(tok, '=')) tvar[nvar++] = tok; else targ[narg++] = tok; } /* Copy the pointer arrays to permanent heap memory. */ *argv = _malloc(sizeof(char*) * (narg + nvar + 2)); if (!*argv) panic("No memory to parse command line"); memcpy(*argv, targ, sizeof(char*) * narg); (*argv)[narg] = 0; *argc = narg; *envp = &*argv[narg+1]; memcpy(*envp, tvar, sizeof(char*) * nvar); *envp[nvar] = 0; } else { /* No command line. */ *argc = 1; *argv = null_args; *envp = null_args + 1; } }
/* * pmap_zero_page zeros the specified (machine independent) page. */ void pmap_zero_page(vm_offset_t p) { assert(p != vm_page_fictitious_addr); vm_offset_t v; pmap_mapwindow_t *map; boolean_t mapped = p >= phys_last_addr; if (mapped) { map = pmap_get_mapwindow(INTEL_PTE_W(p)); v = map->vaddr; } else v = phystokv(p); memset((void*) v, 0, PAGE_SIZE); if (mapped) pmap_put_mapwindow(map); }
/* * Find devices. The system is alive. */ void machine_init() { /* * Initialize the console. */ cninit(); /* * Set up to use floating point. */ init_fpu(); #ifdef LINUX_DEV /* * Initialize Linux drivers. */ linux_init(); #endif /* * Find the devices */ probeio(); /* * Get the time */ inittodr(); /* * Tell the BIOS not to clear and test memory. */ *(unsigned short *)phystokv(0x472) = 0x1234; /* * Unmap page 0 to trap NULL references. */ pmap_unmap_page_zero(); }
void multiboot_main(oskit_addr_t boot_info_pa) { int argc = 0; char **argv = 0; int i; char **ep; /* Copy the multiboot_info structure into our pre-reserved area. This avoids one loose fragment of memory that has to be avoided. */ boot_info = *(struct multiboot_info*)phystokv(boot_info_pa); /* Identify the CPU and get the processor tables set up. */ base_cpu_setup(); /* Initialize the memory allocator and find all available memory. */ base_multiboot_init_mem(); /* Parse the command line into nice POSIX-like args and environment. */ base_multiboot_init_cmdline(&argc, &argv); /* Remove the -d flag because we don't want to be debugged, we want to debug our kids. */ for (i = 0; i < oskit_bootargc; i++) if (strcmp(oskit_bootargv[i], "-d") == 0) { int j; enable_debug_arg = oskit_bootargv[i]; for (j = i; j < oskit_bootargc; j++) oskit_bootargv[j] = oskit_bootargv[j + 1]; oskit_bootargc--; break; } /* Likewise for a "GDB_COM" environment variable. */ for (ep = environ; *ep; ++ep) if (strncmp(*ep, "GDB_COM=", 8) == 0) { enable_debug_arg = *ep; i = 0; do ep[i] = ep[i + 1]; while (ep[i++]); break; } /* Look for a return address. */ for (i = 0; i < oskit_bootargc; i++) if (strcmp(oskit_bootargv[i], "-retaddr") == 0 && i+1 < oskit_bootargc) { return_address = strtoul(oskit_bootargv[i+1], 0, 0); break; } /* Enable interrupts, since we may be using remote gdb. */ sti(); /* Initialize the console */ base_console_init(oskit_bootargc, oskit_bootargv); #ifdef GPROF if (enable_gprof) base_gprof_init(); #endif #ifdef __ELF__ /* Make sure deinit code gets called on exit. */ atexit(__oskit_fini); /* Call init code. */ __oskit_init(); #endif /* Invoke the main program. */ exit(main(argc, argv, environ)); }
static void common_thread_init(phantom_thread_t *t, int stacksize ) { //t->thread_flags = 0; t->priority = THREAD_PRIO_NORM; t->cpu_id = GET_CPU_ID(); #if CONF_NEW_CTTY t_make_ctty( t ); #else if( 0 == t->ctty ) t->ctty = wtty_init( WTTY_SMALL_BUF ); #endif // malloc uses mutex, so we have to use physalloc which is protected with spinlocks physaddr_t pa; t->stack_size = stacksize; //t->stack = calloc( 1, stacksize ); hal_pv_alloc( &pa, &(t->stack), stacksize+PAGE_SIZE ); hal_page_control( pa, t->stack, page_unmap, page_noaccess ); // poor man's guard page - TODO support in page fault t->stack_pa = pa; SHOW_FLOW( 5, "main stk va %p pa %p", t->stack, (void *)pa ); //assert(t->stack != 0); t->kstack_size = stacksize; //t->kstack = calloc( 1, stacksize ); hal_pv_alloc( &pa, &(t->kstack), stacksize+PAGE_SIZE ); hal_page_control( pa, t->kstack, page_unmap, page_noaccess ); // poor man's guard page - TODO support in page fault t->kstack_pa = pa; SHOW_FLOW( 5, "kern stk va %p pa %p", t->kstack, (void *)pa ); #if ARCH_mips // On mips we need unmapped kernel stack for mapping on MIPS is // done with exceptions too and unmapped stack is fault forever. // We achieve this by setting stack virtual address to its // physical address | 0x8000000 - this virt mem area is direct // mapped to physmem at 0 assert( (addr_t)phystokv(t->kstack_pa) > 0x80000000 ); assert( (addr_t)phystokv(t->kstack_pa) < 0xC0000000 ); t->kstack_top = phystokv(t->kstack_pa) +t->kstack_size-4; // Why -4? #else t->kstack_top = t->kstack+t->kstack_size-4; // Why -4? #endif //assert(t->kstack != 0); t->owner = 0; //t->u = 0; t->pid = NO_PID; t->thread_flags = 0;; t->waitcond = 0; hal_spin_init( &(t->waitlock)); queue_init(&(t->chain)); queue_init(&(t->runq_chain)); t->sw_unlock = 0; t->preemption_disabled = 0; }
void mb_util_lmm (mbinfo_t *mbi, lmm_t *lmm) { vm_offset_t min; extern char _start[], end[]; /* Memory regions to skip. */ vm_offset_t cmdline_start_pa = mbi->flags & MULTIBOOT_CMDLINE ? mbi->cmdline : 0; vm_offset_t cmdline_end_pa = cmdline_start_pa ? cmdline_start_pa+strlen((char*)phystokv(cmdline_start_pa))+1 : 0; /* Initialize the base memory allocator according to the PC's physical memory regions. */ lmm_init(lmm); /* Do the x86 init dance to build our initial regions */ lmm_add_region(&malloc_lmm, ®1mb, (void*)phystokv(0x00000000), 0x00100000, LMMF_1MB | LMMF_16MB, LMM_PRI_1MB); lmm_add_region(&malloc_lmm, ®16mb, (void*)phystokv(0x00100000), 0x00f00000, LMMF_16MB, LMM_PRI_16MB); lmm_add_region(&malloc_lmm, ®high, (void*)phystokv(0x01000000), 0xfeffffff, 0, LMM_PRI_HIGH); /* Add to the free list all the memory the boot loader told us about, carefully avoiding the areas occupied by boot information. as well as our own executable code, data, and bss. Start at the end of the BIOS data area. */ min = 0x500; do { vm_offset_t max = 0xffffffff; /* Skip the I/O and ROM area. */ skip(mbi->mem_lower * 1024, 0x100000); /* Stop at the end of upper memory. */ skip(0x100000 + mbi->mem_upper * 1024, 0xffffffff); /* Skip our own text, data, and bss. */ skip(kvtophys(_start), kvtophys(end)); /* FIXME: temporary state of affairs */ extern char __kimg_start[]; skip(kvtophys(__kimg_start), kvtophys(end)); /* Skip the important stuff the bootloader passed to us. */ skip(cmdline_start_pa, cmdline_end_pa); if ((mbi->flags & MULTIBOOT_MODS) && (mbi->mods_count > 0)) { struct multiboot_module *m = (struct multiboot_module*) phystokv(mbi->mods_addr); unsigned i; skip(mbi->mods_addr, mbi->mods_addr + mbi->mods_count * sizeof(*m)); for (i = 0; i < mbi->mods_count; i++) { if (m[i].string != 0) { char *s = (char*)phystokv(m[i].string); unsigned len = strlen(s); skip(m[i].string, m[i].string+len+1); } skip(m[i].mod_start, m[i].mod_end); } } /* We actually found a contiguous memory block that doesn't conflict with anything else! Whew! Add it to the free list. */ lmm_add_free(&malloc_lmm, (void *) min, max - min); /* Continue searching just past the end of this region. */ min = max; /* The skip() macro jumps to this label to restart with a different (higher) min address. */ retry:; } while (min < 0xffffffff); }
oskit_addr_t osenv_mem_get_virt(oskit_addr_t addr) { return ((oskit_addr_t)phystokv(addr)); }
boolean_t elf_db_sym_init (unsigned shdr_num, vm_size_t shdr_size, vm_offset_t shdr_addr, unsigned shdr_shndx, char *name, char *task_addr) { Elf32_Shdr *shdr, *symtab, *strtab; const char *shstrtab; int i; if (shdr_num == 0) return FALSE; if (shdr_size != sizeof *shdr) return FALSE; shdr = (Elf32_Shdr *) shdr_addr; if (shdr[shdr_shndx].sh_type != SHT_STRTAB) return FALSE; shstrtab = (const char *) phystokv (shdr[shdr_shndx].sh_addr); symtab = strtab = NULL; for (i = 0; i < shdr_num; i++) switch (shdr[i].sh_type) { case SHT_SYMTAB: if (symtab) db_printf ("Ignoring additional ELF symbol table at %d\n", i); else symtab = &shdr[i]; break; case SHT_STRTAB: if (strcmp (&shstrtab[shdr[i].sh_name], ".strtab") == 0) { if (strtab) db_printf ("Ignoring additional ELF string table at %d\n", i); else strtab = &shdr[i]; } break; } if (symtab == NULL || strtab == NULL) return FALSE; if (db_add_symbol_table (SYMTAB_ELF, (char *) phystokv (symtab->sh_addr), (char *) phystokv (symtab->sh_addr)+symtab->sh_size, name, (char *) phystokv (strtab->sh_addr), task_addr)) { db_printf ("Loaded ELF symbol table for %s (%d symbols)\n", name, symtab->sh_size / sizeof (Elf32_Sym)); return TRUE; } return FALSE; }
void cpu_machine_idle_init(boolean_t from_boot) { static const unsigned int *BootArgs_paddr = (unsigned int *)NULL; static const unsigned int *CpuDataEntries_paddr = (unsigned int *)NULL; static unsigned int resume_idle_cpu_paddr = (unsigned int )NULL; cpu_data_t *cpu_data_ptr = getCpuDatap(); if (from_boot) { unsigned int jtag = 0; unsigned int wfi; if (PE_parse_boot_argn("jtag", &jtag, sizeof (jtag))) { if (jtag != 0) idle_enable = FALSE; else idle_enable = TRUE; } else idle_enable = TRUE; if (!PE_parse_boot_argn("wfi", &wfi, sizeof (wfi))) wfi = 1; if (wfi == 0) bcopy_phys((addr64_t)ml_static_vtop((vm_offset_t)&patch_to_nop), (addr64_t)ml_static_vtop((vm_offset_t)&wfi_inst), sizeof(unsigned)); if (wfi == 2) wfi_fast = 0; LowExceptionVectorsAddr = (void *)ml_io_map(ml_vtophys((vm_offset_t)gPhysBase), PAGE_SIZE); /* Copy Exception Vectors low, but don't touch the sleep token */ bcopy((void *)&ExceptionLowVectorsBase, (void *)LowExceptionVectorsAddr, 0x90); bcopy(((void *)(((vm_offset_t)&ExceptionLowVectorsBase) + 0xA0)), ((void *)(((vm_offset_t)LowExceptionVectorsAddr) + 0xA0)), ARM_PGBYTES - 0xA0); start_cpu_paddr = ml_static_vtop((vm_offset_t)&start_cpu); BootArgs_paddr = (unsigned int *)ml_static_vtop((vm_offset_t)BootArgs); bcopy_phys((addr64_t)ml_static_vtop((vm_offset_t)&BootArgs_paddr), (addr64_t)((unsigned int)(gPhysBase) + ((unsigned int)&(ResetHandlerData.boot_args) - (unsigned int)&ExceptionLowVectorsBase)), 4); CpuDataEntries_paddr = (unsigned int *)ml_static_vtop((vm_offset_t)CpuDataEntries); bcopy_phys((addr64_t)ml_static_vtop((vm_offset_t)&CpuDataEntries_paddr), (addr64_t)((unsigned int)(gPhysBase) + ((unsigned int)&(ResetHandlerData.cpu_data_entries) - (unsigned int)&ExceptionLowVectorsBase)), 4); CleanPoC_DcacheRegion((vm_offset_t) phystokv(gPhysBase), PAGE_SIZE); resume_idle_cpu_paddr = (unsigned int)ml_static_vtop((vm_offset_t)&resume_idle_cpu); } if (cpu_data_ptr == &BootCpuData) { bcopy(((const void *)running_signature), (void *)(IOS_STATE), IOS_STATE_SIZE); }; cpu_data_ptr->cpu_reset_handler = resume_idle_cpu_paddr; clean_dcache((vm_offset_t)cpu_data_ptr, sizeof(cpu_data_t), FALSE); }
void multiboot_info_dump(struct multiboot_info *bi) { struct multiboot_module *m; unsigned i; printf("MultiBoot Info (flags: 0x%b)\n", bi->flags, MULTIBOOT_FLAGS_FORMAT); if (bi->flags & MULTIBOOT_MEMORY) printf(" PC Memory: lower %dK, upper %dK\n", bi->mem_lower, bi->mem_upper); if (bi->flags & MULTIBOOT_BOOT_DEVICE) printf(" Boot device: {%d,%d,%d,%d}\n", bi->boot_device[0], bi->boot_device[1], bi->boot_device[2], bi->boot_device[3]); if (bi->flags & MULTIBOOT_CMDLINE) printf(" Kernel command line: `%s'\n", (char *)phystokv(bi->cmdline)); if (bi->flags & MULTIBOOT_MODS) { printf(" Boot modules: %d\n", bi->mods_count); m = (struct multiboot_module *)phystokv(bi->mods_addr); for (i = 0; i < bi->mods_count; i++) { printf(" Module %d: %08x-%08x (size %d)\n", i, m[i].mod_start, m[i].mod_end, m[i].mod_end - m[i].mod_start); if (m[i].string) printf(" String: `%s' at %08x\n", (char*)phystokv(m[i].string), m[i].string); } } if (bi->flags & MULTIBOOT_AOUT_SYMS) printf(" Symbol table (a.out): start 0x%08x," " symtab 0x%08x, strtab 0x%08x\n", bi->syms.a.addr, bi->syms.a.tabsize, bi->syms.a.strsize); if (bi->flags & MULTIBOOT_ELF_SHDR) /* XXX */ printf(" Has MULTIBOOT_ELF_SHDR info\n"); if (bi->flags & MULTIBOOT_MEM_MAP) { struct AddrRangeDesc *rdesc; unsigned end; printf(" Memory Map:\n addr: 0x%08x," " count: %d\n", bi->mmap_addr, bi->mmap_count); /* XXX Count is currently the length in bytes of the * entire structure: GRUB and the multiboot spec * actually call it mmap_length. */ rdesc = (struct AddrRangeDesc *)bi->mmap_addr; end = bi->mmap_addr + bi->mmap_count; while (end > (int)rdesc) { /* * I'd rather use .0 precision for the High * entries (since they're guaranteed to be 0 * on a PC), but this works too. */ printf(" base: 0x"); if (rdesc->BaseAddrHigh) printf("%08lx", rdesc->BaseAddrHigh); printf("%08lx length: 0x", rdesc->BaseAddrLow); if (rdesc->LengthHigh) printf("%08lx", rdesc->LengthHigh); printf("%08lx type: ", rdesc->LengthLow); switch (rdesc->Type) { case 1: printf("memory\n"); break; case 2: printf("reserved\n"); break; default: printf("undefined (%ld)\n", rdesc->Type); } (char *)rdesc += rdesc->size + 4; }; } }
/* * The command-line comes to us as a string and contains booting-options, * environment-variable settings, and arguments to main(). * The format is like this: * progname [<booting-options and foo=bar> --] <args to main> * For example * kernel DISPLAY=host:0 -d -- -rf foo bar * which would be converted into * environ = {"DISPLAY=host:0", 0} * oskit_bootargv = {"-d", 0} * argv = {"kernel", "-rf", "foo", "bar", 0} * Actually, those would be pointers into * {"kernel", "-rf", "foo", "bar", 0, "DISPLAY=host:0", 0, "-d", 0} * If there is no "--" in the command line, then the entire thing is parsed * into argv, no environment vars or booting options are set. */ void base_multiboot_init_cmdline(int *argcp, char ***argvp) { int argc; char **argv; if (boot_info.flags & MULTIBOOT_CMDLINE) { char *cl = (char*)phystokv(boot_info.cmdline); unsigned cllen = strlen(cl); char *toks[1 + cllen]; unsigned ntoks, nargs, nvars, nbops; char *tok; unsigned i, dashdashi; char **argbuf; unsigned envc; /* * Parse out the tokens in the command line. * XXX Might be good to handle quotes. */ ntoks = 0; for (tok = strtok(cl, delim); tok; tok = strtok(0, delim)) toks[ntoks++] = tok; /* After this we assume at least one arg (progname). */ if (ntoks == 0) goto nocmdline; /* Look for a "--" and record its index. */ dashdashi = 0; for (i = 0; i < ntoks; i++) if (strcmp(toks[i], "--") == 0) { dashdashi = i; break; } /* Count number of args, env vars, and bootopts. */ nargs = 1; /* for progname */ nvars = 0; nbops = 0; for (i = 1; i < dashdashi; i++) if (strchr(toks[i], '=')) nvars++; else nbops++; for (i = dashdashi + 1; i < ntoks; i++) nargs++; /* * Now we know how big our argbuf is. * argv, environ, and oskit_bootargv will point into this. */ argbuf = lmm_alloc(&malloc_lmm, sizeof(char *) * (nargs + 1) + sizeof(char *) * (nvars + 1) + sizeof(char *) * (nbops + 1), 0); assert(argbuf); /* * Set up the pointers into argbuf, then fill them in. */ argv = argbuf; environ = argv + nargs + 1; oskit_bootargv = environ + nvars + 1; argc = 0; argv[argc++] = toks[0]; envc = 0; oskit_bootargc = 0; for (i = 1; i < dashdashi; i++) if (strchr(toks[i], '=')) environ[envc++] = toks[i]; else oskit_bootargv[oskit_bootargc++] = toks[i]; for (i = dashdashi + 1; i < ntoks; i++) argv[argc++] = toks[i]; argv[argc] = 0; environ[envc] = 0; oskit_bootargv[oskit_bootargc] = 0; } else { nocmdline: /* No command line. */ argc = 1; argv = null_args; environ = null_args + 1; oskit_bootargc = 0; oskit_bootargv = environ; } *argcp = argc; *argvp = argv; }
void bootstrap_create(void) { int compat; int n = 0; #ifdef MACH_XEN struct multiboot_module *bmods = ((struct multiboot_module *) boot_info.mod_start); if (bmods) for (n = 0; bmods[n].mod_start; n++) { bmods[n].mod_start = kvtophys(bmods[n].mod_start + (vm_offset_t) bmods); bmods[n].mod_end = kvtophys(bmods[n].mod_end + (vm_offset_t) bmods); bmods[n].string = kvtophys(bmods[n].string + (vm_offset_t) bmods); } boot_info.mods_count = n; boot_info.flags |= MULTIBOOT_MODS; #else /* MACH_XEN */ struct multiboot_module *bmods = ((struct multiboot_module *) phystokv(boot_info.mods_addr)); #endif /* MACH_XEN */ if (!(boot_info.flags & MULTIBOOT_MODS) || (boot_info.mods_count == 0)) panic ("No bootstrap code loaded with the kernel!"); compat = boot_info.mods_count == 1; if (compat) { char *p = strchr((char*)phystokv(bmods[0].string), ' '); if (p != 0) do ++p; while (*p == ' ' || *p == '\n'); compat = p == 0 || *p == '\0'; } if (compat) { printf("Loading single multiboot module in compat mode: %s\n", (char*)phystokv(bmods[0].string)); bootstrap_exec_compat(&bmods[0]); } else { int i, losers; /* Initialize boot script variables. We leak these send rights. */ losers = boot_script_set_variable ("host-port", VAL_PORT, (long) realhost.host_priv_self); if (losers) panic ("cannot set boot-script variable host-port: %s", boot_script_error_string (losers)); losers = boot_script_set_variable ("device-port", VAL_PORT, (long) master_device_port); if (losers) panic ("cannot set boot-script variable device-port: %s", boot_script_error_string (losers)); losers = boot_script_set_variable ("kernel-command-line", VAL_STR, (long) kernel_cmdline); if (losers) panic ("cannot set boot-script variable %s: %s", "kernel-command-line", boot_script_error_string (losers)); { /* Set the same boot script variables that the old Hurd's serverboot did, so an old Hurd and boot script previously used with serverboot can be used directly with this kernel. */ char *flag_string = alloca(1024); char *root_string = alloca(1024); /* * Get the (compatibility) boot flags and root name strings. */ get_compat_strings(flag_string, root_string); losers = boot_script_set_variable ("boot-args", VAL_STR, (long) flag_string); if (losers) panic ("cannot set boot-script variable %s: %s", "boot-args", boot_script_error_string (losers)); losers = boot_script_set_variable ("root-device", VAL_STR, (long) root_string); if (losers) panic ("cannot set boot-script variable %s: %s", "root-device", boot_script_error_string (losers)); } #if OSKIT_MACH { /* The oskit's "environ" array contains all the words from the multiboot command line that looked like VAR=VAL. We set each of these as boot-script variables, which can be used for things like ${root}. */ extern char **environ; char **ep; for (ep = environ; *ep != 0; ++ep) { size_t len = strlen (*ep) + 1; char *var = memcpy (alloca (len), *ep, len); char *val = strchr (var, '='); *val++ = '\0'; losers = boot_script_set_variable (var, VAL_STR, (long) val); if (losers) panic ("cannot set boot-script variable %s: %s", var, boot_script_error_string (losers)); } } #else /* GNUmach, not oskit-mach */ { /* Turn each `FOO=BAR' word in the command line into a boot script variable ${FOO} with value BAR. This matches what we get from oskit's environ in the oskit-mach case (above). */ int len = strlen (kernel_cmdline) + 1; char *s = memcpy (alloca (len), kernel_cmdline, len); char *word; while ((word = strsep (&s, " \t")) != 0) { char *eq = strchr (word, '='); if (eq == 0) continue; *eq++ = '\0'; losers = boot_script_set_variable (word, VAL_STR, (long) eq); if (losers) panic ("cannot set boot-script variable %s: %s", word, boot_script_error_string (losers)); } } #endif for (i = 0; i < boot_info.mods_count; ++i) { int err; char *line = (char*)phystokv(bmods[i].string); printf ("module %d: %s\n", i, line); err = boot_script_parse_line (&bmods[i], line); if (err) { printf ("\n\tERROR: %s", boot_script_error_string (err)); ++losers; } } printf ("%d multiboot modules\n", i); if (losers) panic ("%d of %d boot script commands could not be parsed", losers, boot_info.mods_count); losers = boot_script_exec (); if (losers) panic ("ERROR in executing boot script: %s", boot_script_error_string (losers)); } /* XXX we could free the memory used by the boot loader's descriptors and such. */ for (n = 0; n < boot_info.mods_count; n++) vm_page_create(bmods[n].mod_start, bmods[n].mod_end); }
void base_multiboot_init_mem(void) { unsigned int min; extern char _start_of_kernel[], end[]; /* Memory regions to skip. */ unsigned int cmdline_start_pa = boot_info.flags & MULTIBOOT_CMDLINE ? boot_info.cmdline : 0; unsigned int cmdline_end_pa = cmdline_start_pa ? cmdline_start_pa+strlen((char*)phystokv(cmdline_start_pa))+1 : 0; /* Initialize the base memory allocator according to the PC's physical memory regions. */ phys_lmm_init(); /* Add to the free list all the memory the boot loader told us about, carefully avoiding the areas occupied by boot information. as well as our own executable code, data, and bss. Start at the end of the BIOS data area. */ min = 0x500; do { unsigned int max = 0xffffffff; /* Skip the I/O and ROM area. */ skip(boot_info.mem_lower * 1024, 0x100000); /* Stop at the end of upper memory. */ skip(0x100000 + boot_info.mem_upper * 1024, 0xffffffff); /* Skip our own text, data, and bss. */ skip(kvtophys(_start_of_kernel), kvtophys(end)); /* Skip the important stuff the bootloader passed to us. */ skip(cmdline_start_pa, cmdline_end_pa); if ((boot_info.flags & MULTIBOOT_MODS) && (boot_info.mods_count > 0)) { struct multiboot_module *m = (struct multiboot_module*) phystokv(boot_info.mods_addr); unsigned i; skip(boot_info.mods_addr, boot_info.mods_addr + boot_info.mods_count * sizeof(*m)); for (i = 0; i < boot_info.mods_count; i++) { if (m[i].string != 0) { char *s = (char*)phystokv(m[i].string); unsigned len = strlen(s); skip(m[i].string, m[i].string+len+1); } skip(m[i].mod_start, m[i].mod_end); } } /* We actually found a contiguous memory block that doesn't conflict with anything else! Whew! Add it to the free list. */ phys_lmm_add(min, max - min); /* Continue searching just past the end of this region. */ min = max; /* The skip() macro jumps to this label to restart with a different (higher) min address. */ retry: min = min; } while (min < 0xffffffff); }
/* * Called after all CPUs have been found, but before the VM system * is running. The machine array must show which CPUs exist. */ void interrupt_stack_alloc(void) { register int i; int cpu_count; vm_offset_t stack_start; struct mp_desc_table *mpt; /* * Count the number of CPUs. */ cpu_count = 0; for (i = 0; i < NCPUS; i++) if (machine_slot[i].is_cpu) cpu_count++; /* * Allocate an interrupt stack for each CPU except for * the master CPU (which uses the bootstrap stack) */ stack_start = phystokv(avail_start); avail_start = round_page(avail_start + INTSTACK_SIZE*(cpu_count-1)); bzero((char *)stack_start, INTSTACK_SIZE*(cpu_count-1)); /* * Set up pointers to the top of the interrupt stack. */ for (i = 0; i < NCPUS; i++) { if (i == master_cpu) { interrupt_stack[i] = (vm_offset_t) intstack; int_stack_top[i] = (vm_offset_t) eintstack; } else if (machine_slot[i].is_cpu) { interrupt_stack[i] = stack_start; int_stack_top[i] = stack_start + INTSTACK_SIZE; stack_start += INTSTACK_SIZE; } } /* * Allocate descriptor tables for each CPU except for * the master CPU (which already has them initialized) */ mpt = (struct mp_desc_table *) phystokv(avail_start); avail_start = round_page((vm_offset_t)avail_start + sizeof(struct mp_desc_table)*(cpu_count-1)); for (i = 0; i < NCPUS; i++) if (i != master_cpu) mp_desc_table[i] = mpt++; /* * Set up the barrier address. All thread stacks MUST * be above this address. */ #if AT386 /* * intstack is at higher addess than stack_start for AT mps * so int_stack_high must point at eintstack. * XXX * But what happens if a kernel stack gets allocated below * 1 Meg ? Probably never happens, there is only 640 K available * There. */ int_stack_high = (vm_offset_t) eintstack; #else /* AT386 */ int_stack_high = stack_start; #endif /* AT386 */ }
void ptab_free(oskit_addr_t ptab_pa) { assert(ptab_pa); lmm_free_page(&malloc_lmm, (void*)phystokv(ptab_pa)); }