/* * Initialize mips and configure to run kernel */ void mips_proc0_init(void) { #ifdef SMP if (platform_processor_id() != 0) panic("BSP must be processor number 0"); #endif proc_linkup0(&proc0, &thread0); KASSERT((kstack0 & PAGE_MASK) == 0, ("kstack0 is not aligned on a page boundary: 0x%0lx", (long)kstack0)); thread0.td_kstack = kstack0; thread0.td_kstack_pages = KSTACK_PAGES; /* * Do not use cpu_thread_alloc to initialize these fields * thread0 is the only thread that has kstack located in KSEG0 * while cpu_thread_alloc handles kstack allocated in KSEG2. */ thread0.td_pcb = (struct pcb *)(thread0.td_kstack + thread0.td_kstack_pages * PAGE_SIZE) - 1; thread0.td_frame = &thread0.td_pcb->pcb_regs; /* Steal memory for the dynamic per-cpu area. */ dpcpu_init((void *)pmap_steal_memory(DPCPU_SIZE), 0); PCPU_SET(curpcb, thread0.td_pcb); /* * There is no need to initialize md_upte array for thread0 as it's * located in .bss section and should be explicitly zeroed during * kernel initialization. */ }
void RealView_framebuffer_init(void) { gRealviewPl111Base = ml_io_map(REALVIEW_PL111_BASE, PAGE_SIZE); /* * The hardware demands a framebuffer, but the framebuffer has to be given * in a hardware address. */ void *framebuffer = pmap_steal_memory(1024 * 768 * 4); void *framebuffer_phys = pmap_extract(kernel_pmap, framebuffer); uint32_t depth = 2; uint32_t width = 1024; uint32_t height = 768; uint32_t pitch = (width * depth); uint32_t fb_length = (pitch * width); uint32_t timingRegister, controlRegister; /* * Set framebuffer address */ HARDWARE_REGISTER(gRealviewPl111Base + PL111_UPPER_FB) = framebuffer_phys; HARDWARE_REGISTER(gRealviewPl111Base + PL111_LOWER_FB) = framebuffer_phys; /* * Initialize timings to 1024x768x16 */ HARDWARE_REGISTER(gRealviewPl111Base + PL111_TIMINGS_0) = LCDTIMING0_PPL(width); HARDWARE_REGISTER(gRealviewPl111Base + PL111_TIMINGS_1) = LCDTIMING1_LPP(height); /* * Enable the TFT/LCD Display */ HARDWARE_REGISTER(gRealviewPl111Base + PL111_CONTROL) = LCDCONTROL_LCDEN | LCDCONTROL_LCDTFT | LCDCONTROL_LCDPWR | LCDCONTROL_LCDBPP(5); PE_state.video.v_baseAddr = (unsigned long) framebuffer_phys; PE_state.video.v_rowBytes = width * 4; PE_state.video.v_width = width; PE_state.video.v_height = height; PE_state.video.v_depth = 4 * (8); // 16bpp kprintf(KPRINTF_PREFIX "framebuffer initialized\n"); bzero(framebuffer, (pitch * height)); char tempbuf[16]; if (PE_parse_boot_argn("-graphics-mode", tempbuf, sizeof(tempbuf))) { /* * BootX like framebuffer. */ memset(framebuffer, 0xb9, PE_state.video.v_rowBytes * PE_state.video.v_height); initialize_screen((void *) &PE_state.video, kPEGraphicsMode); } else { initialize_screen((void *) &PE_state.video, kPETextMode); } }
void RealView_framebuffer_init(void) { gRealviewPl111Base = ml_io_map(REALVIEW_PL111_BASE, PAGE_SIZE); /* * The hardware demands a framebuffer, but the framebuffer has to be given * in a hardware address. */ void* framebuffer = pmap_steal_memory(1024 * 768 * 4); void* framebuffer_phys = pmap_get_phys(kernel_pmap, framebuffer); uint32_t depth = 2; uint32_t width = 1024; uint32_t height = 768; uint32_t pitch = (width * depth); uint32_t fb_length = (pitch * width); uint32_t timingRegister, controlRegister; /* Set framebuffer address */ HARDWARE_REGISTER(gRealviewPl111Base + PL111_UPPER_FB) = framebuffer_phys; HARDWARE_REGISTER(gRealviewPl111Base + PL111_LOWER_FB) = framebuffer_phys; /* Initialize timings to 1024x768x16 */ HARDWARE_REGISTER(gRealviewPl111Base + PL111_TIMINGS_0) = LCDTIMING0_PPL(width); HARDWARE_REGISTER(gRealviewPl111Base + PL111_TIMINGS_1) = LCDTIMING1_LPP(height); /* Enable the TFT/LCD Display */ HARDWARE_REGISTER(gRealviewPl111Base + PL111_CONTROL) = LCDCONTROL_LCDEN | LCDCONTROL_LCDTFT | LCDCONTROL_LCDPWR | LCDCONTROL_LCDBPP(4); PE_state.video.v_baseAddr = (unsigned long)framebuffer_phys; PE_state.video.v_rowBytes = width * 2; PE_state.video.v_width = width; PE_state.video.v_height = height; PE_state.video.v_depth = 2 * (8); // 16bpp kprintf(KPRINTF_PREFIX "framebuffer initialized\n"); bzero(framebuffer, (pitch * height)); initialize_screen((void*)&PE_state.video, kPEAcquireScreen); initialize_screen((void*)&PE_state.video, kPEEnableScreen); }
void hppa_init() { extern int kernel_text, end; struct pdc_hwtlb pdc_hwtlb PDC_ALIGNMENT; struct pdc_coproc pdc_coproc PDC_ALIGNMENT; vm_offset_t v, vstart, vend; register int pdcerr; int usehpt; /* init PDC iface, so we can call em easy */ pdc_init(); /* calculate cpu speed */ cpu_hzticks = (PAGE0->mem_10msec * 100) / hz; delay_init(); /* * get cache parameters from the PDC */ if ((pdcerr = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_DFLT, &pdc_cache)) < 0) { #ifdef DIAGNOSTIC printf("Warning: PDC_CACHE call Ret'd %d\n", pdcerr); #endif } dcache_line_mask = pdc_cache.dc_conf.cc_line * 16 - 1; dcache_size = pdc_cache.dc_size; dcache_stride = pdc_cache.dc_stride; icache_stride = pdc_cache.ic_stride; /* * purge TLBs and flush caches */ if (pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, PDC_BTLB_PURGE_ALL) < 0) printf("WARNING: BTLB purge failed\n"); ptlball(); fcacheall(); /* calculate HPT size */ hpt_hashsize = PAGE0->imm_max_mem / NBPG; mtctl(hpt_hashsize - 1, CR_HPTMASK); /* * If we want to use the HW TLB support, ensure that it exists. */ if (pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_INFO, &pdc_hwtlb) && !pdc_hwtlb.min_size && !pdc_hwtlb.max_size) { printf("WARNING: no HW tlb walker\n"); usehpt = 0; } else { usehpt = 1; #ifdef DEBUG printf("hwtlb: %u-%u, %u/", pdc_hwtlb.min_size, pdc_hwtlb.max_size, hpt_hashsize); #endif if (hpt_hashsize > pdc_hwtlb.max_size) hpt_hashsize = pdc_hwtlb.max_size; else if (hpt_hashsize < pdc_hwtlb.min_size) hpt_hashsize = pdc_hwtlb.min_size; #ifdef DEBUG printf("%u (0x%x)\n", hpt_hashsize, hpt_hashsize * sizeof(struct hpt_entry)); #endif } totalphysmem = PAGE0->imm_max_mem / NBPG; resvmem = ((vm_offset_t)&kernel_text) / NBPG; vstart = hppa_round_page(&end); vend = VM_MAX_KERNEL_ADDRESS; /* we hope this won't fail */ hppa_ex = extent_create("mem", 0x0, 0xffffffff, M_DEVBUF, (caddr_t)mem_ex_storage, sizeof(mem_ex_storage), EX_NOCOALESCE|EX_NOWAIT); if (extent_alloc_region(hppa_ex, 0, (vm_offset_t)PAGE0->imm_max_mem, EX_NOWAIT)) panic("cannot reserve main memory"); /* * Allocate space for system data structures. We are given * a starting virtual address and we return a final virtual * address; along the way we set each data structure pointer. * * We call allocsys() with 0 to find out how much space we want, * allocate that much and fill it with zeroes, and the call * allocsys() again with the correct base virtual address. */ v = vstart; #define valloc(name, type, num) \ (name) = (type *)v; v = (vm_offset_t)((name)+(num)) #ifdef REAL_CLISTS valloc(cfree, struct cblock, nclist); #endif valloc(callout, struct callout, ncallout); nswapmap = maxproc * 2; valloc(swapmap, struct map, nswapmap); #ifdef SYSVSHM valloc(shmsegs, struct shmid_ds, shminfo.shmmni); #endif #ifdef SYSVSEM valloc(sema, struct semid_ds, seminfo.semmni); valloc(sem, struct sem, seminfo.semmns); /* This is pretty disgusting! */ valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int)); #endif #ifdef SYSVMSG valloc(msgpool, char, msginfo.msgmax); valloc(msgmaps, struct msgmap, msginfo.msgseg); valloc(msghdrs, struct msg, msginfo.msgtql); valloc(msqids, struct msqid_ds, msginfo.msgmni); #endif #ifndef BUFCACHEPERCENT #define BUFCACHEPERCENT 10 #endif /* BUFCACHEPERCENT */ if (bufpages == 0) bufpages = totalphysmem / BUFCACHEPERCENT / CLSIZE; if (nbuf == 0) { nbuf = bufpages; if (nbuf < 16) nbuf = 16; } /* Restrict to at most 70% filled kvm */ if (nbuf * MAXBSIZE > (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) * 7 / 10) nbuf = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / MAXBSIZE * 7 / 10; /* More buffer pages than fits into the buffers is senseless. */ if (bufpages > nbuf * MAXBSIZE / CLBYTES) bufpages = nbuf * MAXBSIZE / CLBYTES; if (nswbuf == 0) { nswbuf = (nbuf / 2) & ~1; /* force even */ if (nswbuf > 256) nswbuf = 256; /* sanity */ } valloc(swbuf, struct buf, nswbuf); valloc(buf, struct buf, nbuf); #undef valloc bzero ((void *)vstart, (v - vstart)); vstart = v; pmap_bootstrap(&vstart, &vend); physmem = totalphysmem - btoc(vstart); /* alloc msgbuf */ if (!(msgbufp = (void *)pmap_steal_memory(sizeof(struct msgbuf), NULL, NULL))) panic("cannot allocate msgbuf"); msgbufmapped = 1; #ifdef DEBUG printf("mem: %x+%x, %x\n", physmem, resvmem, totalphysmem); #endif /* Turn on the HW TLB assist */ if (usehpt) { if ((pdcerr = pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_CONFIG, &pdc_hwtlb, hpt_table, sizeof(struct hpt_entry) * hpt_hashsize, PDC_TLB_WORD3)) < 0) { printf("Warning: HW TLB init failed (%d), disabled\n", pdcerr); usehpt = 0; } else printf("HW TLB(%d entries at 0x%x) initialized (%d)\n", hpt_hashsize, hpt_table, pdcerr); } /* * Locate any coprocessors and enable them by setting up the CCR. * SFU's are ignored (since we dont have any). Also, initialize * the floating point registers here. */ if ((pdcerr = pdc_call((iodcio_t)pdc, 0, PDC_COPROC, PDC_COPROC_DFLT, &pdc_coproc)) < 0) printf("WARNING: PDC_COPROC call Ret'd %d\n", pdcerr); else { #ifdef DEBUG printf("pdc_coproc: %x, %x\n", pdc_coproc.ccr_enable, pdc_coproc.ccr_present); #endif } copr_sfu_config = pdc_coproc.ccr_enable; mtctl(copr_sfu_config & CCR_MASK, CR_CCR); /* fprinit(&fpcopr_version); fpcopr_version = (fpcopr_version & 0x003ff800) >> 11; mtctl(CR_CCR, 0); */ /* * Clear the FAULT light (so we know when we get a real one) * PDC_COPROC apparently turns it on (for whatever reason). */ pdcerr = PDC_OSTAT(PDC_OSTAT_RUN) | 0xCEC0; (void) (*pdc)(PDC_CHASSIS, PDC_CHASSIS_DISP, pdcerr); #ifdef DDB ddb_init(); #endif #ifdef DEBUG printf("hppa_init: leaving\n"); #endif kernelmapped++; }
caddr_t mips_init(int argc, void *argv, caddr_t boot_esym) { char *cp; int i; caddr_t sd; u_int cputype; vaddr_t tlb_handler, xtlb_handler; extern char start[], edata[], end[]; extern char exception[], e_exception[]; extern char *hw_vendor, *hw_prod; extern void tlb_miss; extern void tlb_miss_err_r5k; extern void xtlb_miss; extern void xtlb_miss_err_r5k; /* * Make sure we can access the extended address space. * Note that r10k and later do not allow XUSEG accesses * from kernel mode unless SR_UX is set. */ setsr(getsr() | SR_KX | SR_UX); #ifdef notyet /* * Make sure KSEG0 cacheability match what we intend to use. * * XXX This does not work as expected on IP30. Does ARCBios * XXX depend on this? */ cp0_setcfg((cp0_getcfg() & ~0x07) | CCA_CACHED); #endif /* * Clear the compiled BSS segment in OpenBSD code. */ bzero(edata, end - edata); /* * Reserve space for the symbol table, if it exists. */ ssym = (char *)*(u_int64_t *)end; /* Attempt to locate ELF header and symbol table after kernel. */ if (end[0] == ELFMAG0 && end[1] == ELFMAG1 && end[2] == ELFMAG2 && end[3] == ELFMAG3 ) { /* ELF header exists directly after kernel. */ ssym = end; esym = boot_esym; ekern = esym; } else if (((long)ssym - (long)end) >= 0 && ((long)ssym - (long)end) <= 0x1000 && ssym[0] == ELFMAG0 && ssym[1] == ELFMAG1 && ssym[2] == ELFMAG2 && ssym[3] == ELFMAG3 ) { /* Pointers exist directly after kernel. */ esym = (char *)*((u_int64_t *)end + 1); ekern = esym; } else { /* Pointers aren't setup either... */ ssym = NULL; esym = NULL; ekern = end; } /* * Initialize the system type and set up memory layout. * Note that some systems have a more complex memory setup. */ bios_ident(); /* * Determine system type and set up configuration record data. */ hw_vendor = "SGI"; switch (sys_config.system_type) { #if defined(TGT_O2) case SGI_O2: bios_printf("Found SGI-IP32, setting up.\n"); hw_prod = "O2"; strlcpy(cpu_model, "IP32", sizeof(cpu_model)); ip32_setup(); sys_config.cpu[0].clock = 180000000; /* Reasonable default */ cp = Bios_GetEnvironmentVariable("cpufreq"); if (cp && atoi(cp, 10, NULL) > 100) sys_config.cpu[0].clock = atoi(cp, 10, NULL) * 1000000; break; #endif #if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000) case SGI_O200: bios_printf("Found SGI-IP27, setting up.\n"); hw_prod = "Origin 200"; strlcpy(cpu_model, "IP27", sizeof(cpu_model)); ip27_setup(); break; case SGI_O300: bios_printf("Found SGI-IP35, setting up.\n"); hw_prod = "Origin 300"; /* IP27 is intentional, we use the same kernel */ strlcpy(cpu_model, "IP27", sizeof(cpu_model)); ip27_setup(); break; #endif #if defined(TGT_OCTANE) case SGI_OCTANE: bios_printf("Found SGI-IP30, setting up.\n"); hw_prod = "Octane"; strlcpy(cpu_model, "IP30", sizeof(cpu_model)); ip30_setup(); sys_config.cpu[0].clock = 175000000; /* Reasonable default */ cp = Bios_GetEnvironmentVariable("cpufreq"); if (cp && atoi(cp, 10, NULL) > 100) sys_config.cpu[0].clock = atoi(cp, 10, NULL) * 1000000; break; #endif default: bios_printf("Kernel doesn't support this system type!\n"); bios_printf("Halting system.\n"); Bios_Halt(); while(1); } /* * Read and store console type. */ cp = Bios_GetEnvironmentVariable("ConsoleOut"); if (cp != NULL && *cp != '\0') strlcpy(bios_console, cp, sizeof bios_console); /* Disable serial console if ARCS is telling us to use video. */ if (strncmp(bios_console, "video", 5) == 0) comconsaddr = 0; /* * Look at arguments passed to us and compute boothowto. */ boothowto = RB_AUTOBOOT; dobootopts(argc, argv); /* * Figure out where we supposedly booted from. */ cp = Bios_GetEnvironmentVariable("OSLoadPartition"); if (cp == NULL) cp = "unknown"; if (strlcpy(osloadpartition, cp, sizeof osloadpartition) >= sizeof osloadpartition) bios_printf("Value of `OSLoadPartition' is too large.\n" "The kernel might not be able to find out its root device.\n"); /* * Read platform-specific environment variables. */ switch (sys_config.system_type) { #if defined(TGT_O2) case SGI_O2: /* Get Ethernet address from ARCBIOS. */ cp = Bios_GetEnvironmentVariable("eaddr"); if (cp != NULL && strlen(cp) > 0) strlcpy(bios_enaddr, cp, sizeof bios_enaddr); break; #endif default: break; } /* * Set pagesize to enable use of page macros and functions. * Commit available memory to UVM system. */ uvmexp.pagesize = PAGE_SIZE; uvm_setpagesize(); for (i = 0; i < MAXMEMSEGS && mem_layout[i].mem_first_page != 0; i++) { u_int32_t fp, lp; u_int32_t firstkernpage, lastkernpage; unsigned int freelist; paddr_t firstkernpa, lastkernpa; if (IS_XKPHYS((vaddr_t)start)) firstkernpa = XKPHYS_TO_PHYS((vaddr_t)start); else firstkernpa = KSEG0_TO_PHYS((vaddr_t)start); if (IS_XKPHYS((vaddr_t)ekern)) lastkernpa = XKPHYS_TO_PHYS((vaddr_t)ekern); else lastkernpa = KSEG0_TO_PHYS((vaddr_t)ekern); firstkernpage = atop(trunc_page(firstkernpa)); lastkernpage = atop(round_page(lastkernpa)); fp = mem_layout[i].mem_first_page; lp = mem_layout[i].mem_last_page; freelist = mem_layout[i].mem_freelist; /* Account for kernel and kernel symbol table. */ if (fp >= firstkernpage && lp < lastkernpage) continue; /* In kernel. */ if (lp < firstkernpage || fp > lastkernpage) { uvm_page_physload(fp, lp, fp, lp, freelist); continue; /* Outside kernel. */ } if (fp >= firstkernpage) fp = lastkernpage; else if (lp < lastkernpage) lp = firstkernpage; else { /* Need to split! */ u_int32_t xp = firstkernpage; uvm_page_physload(fp, xp, fp, xp, freelist); fp = lastkernpage; } if (lp > fp) uvm_page_physload(fp, lp, fp, lp, freelist); } switch (sys_config.system_type) { #if defined(TGT_O2) || defined(TGT_OCTANE) case SGI_O2: case SGI_OCTANE: sys_config.cpu[0].type = (cp0_get_prid() >> 8) & 0xff; sys_config.cpu[0].vers_maj = (cp0_get_prid() >> 4) & 0x0f; sys_config.cpu[0].vers_min = cp0_get_prid() & 0x0f; sys_config.cpu[0].fptype = (cp1_get_prid() >> 8) & 0xff; sys_config.cpu[0].fpvers_maj = (cp1_get_prid() >> 4) & 0x0f; sys_config.cpu[0].fpvers_min = cp1_get_prid() & 0x0f; /* * Configure TLB. */ switch(sys_config.cpu[0].type) { case MIPS_RM7000: /* Rev A (version >= 2) CPU's have 64 TLB entries. */ if (sys_config.cpu[0].vers_maj < 2) { sys_config.cpu[0].tlbsize = 48; } else { sys_config.cpu[0].tlbsize = 64; } break; case MIPS_R10000: case MIPS_R12000: case MIPS_R14000: sys_config.cpu[0].tlbsize = 64; break; default: sys_config.cpu[0].tlbsize = 48; break; } break; #endif default: break; } /* * Configure cache. */ switch(sys_config.cpu[0].type) { case MIPS_R10000: case MIPS_R12000: case MIPS_R14000: cputype = MIPS_R10000; break; case MIPS_R5000: case MIPS_RM7000: case MIPS_RM52X0: case MIPS_RM9000: cputype = MIPS_R5000; break; default: /* * If we can't identify the cpu type, it must be * r10k-compatible on Octane and Origin families, and * it is likely to be r5k-compatible on O2. */ switch (sys_config.system_type) { case SGI_O2: cputype = MIPS_R5000; break; default: case SGI_OCTANE: case SGI_O200: case SGI_O300: cputype = MIPS_R10000; break; } break; } switch (cputype) { case MIPS_R10000: Mips10k_ConfigCache(); sys_config._SyncCache = Mips10k_SyncCache; sys_config._InvalidateICache = Mips10k_InvalidateICache; sys_config._InvalidateICachePage = Mips10k_InvalidateICachePage; sys_config._SyncDCachePage = Mips10k_SyncDCachePage; sys_config._HitSyncDCache = Mips10k_HitSyncDCache; sys_config._IOSyncDCache = Mips10k_IOSyncDCache; sys_config._HitInvalidateDCache = Mips10k_HitInvalidateDCache; break; default: case MIPS_R5000: Mips5k_ConfigCache(); sys_config._SyncCache = Mips5k_SyncCache; sys_config._InvalidateICache = Mips5k_InvalidateICache; sys_config._InvalidateICachePage = Mips5k_InvalidateICachePage; sys_config._SyncDCachePage = Mips5k_SyncDCachePage; sys_config._HitSyncDCache = Mips5k_HitSyncDCache; sys_config._IOSyncDCache = Mips5k_IOSyncDCache; sys_config._HitInvalidateDCache = Mips5k_HitInvalidateDCache; break; } /* * Last chance to call the BIOS. Wiping the TLB means the BIOS' data * areas are demapped on most systems. */ delay(20*1000); /* Let any UART FIFO drain... */ sys_config.cpu[0].tlbwired = UPAGES / 2; tlb_set_wired(0); tlb_flush(sys_config.cpu[0].tlbsize); tlb_set_wired(sys_config.cpu[0].tlbwired); /* * Get a console, very early but after initial mapping setup. */ consinit(); printf("Initial setup done, switching console.\n"); /* * Init message buffer. */ msgbufbase = (caddr_t)pmap_steal_memory(MSGBUFSIZE, NULL,NULL); initmsgbuf(msgbufbase, MSGBUFSIZE); /* * Allocate U page(s) for proc[0], pm_tlbpid 1. */ proc0.p_addr = proc0paddr = curprocpaddr = (struct user *)pmap_steal_memory(USPACE, NULL, NULL); proc0.p_md.md_regs = (struct trap_frame *)&proc0paddr->u_pcb.pcb_regs; tlb_set_pid(1); /* * Allocate system data structures. */ i = (vsize_t)allocsys(NULL); sd = (caddr_t)pmap_steal_memory(i, NULL, NULL); allocsys(sd); /* * Bootstrap VM system. */ pmap_bootstrap(); /* * Copy down exception vector code. */ bcopy(exception, (char *)CACHE_ERR_EXC_VEC, e_exception - exception); bcopy(exception, (char *)GEN_EXC_VEC, e_exception - exception); /* * Build proper TLB refill handler trampolines. */ switch (cputype) { case MIPS_R5000: /* * R5000 processors need a specific chip bug workaround * in their tlb handlers. Theoretically only revision 1 * of the processor need it, but there is evidence * later versions also need it. * * This is also necessary on RM52x0; we test on the `rounded' * cputype value instead of sys_config.cpu[0].type; this * causes RM7k and RM9k to be included, just to be on the * safe side. */ tlb_handler = (vaddr_t)&tlb_miss_err_r5k; xtlb_handler = (vaddr_t)&xtlb_miss_err_r5k; break; default: tlb_handler = (vaddr_t)&tlb_miss; xtlb_handler = (vaddr_t)&xtlb_miss; break; } build_trampoline(TLB_MISS_EXC_VEC, tlb_handler); build_trampoline(XTLB_MISS_EXC_VEC, xtlb_handler); /* * Turn off bootstrap exception vectors. */ setsr(getsr() & ~SR_BOOT_EXC_VEC); proc0.p_md.md_regs->sr = getsr(); /* * Clear out the I and D caches. */ Mips_SyncCache(); #ifdef DDB db_machine_init(); if (boothowto & RB_KDB) Debugger(); #endif /* * Return new stack pointer. */ return ((caddr_t)proc0paddr + USPACE - 64); }
/* * Do all the stuff that locore normally does before calling main(). */ void mach_init(long fwhandle, long magic, long bootdata, long reserved) { void *kernend, *p0; u_long first, last; extern char edata[], end[]; int i; uint32_t config; /* XXX this code must run on the target CPU */ config = mips3_cp0_config_read(); config &= ~MIPS3_CONFIG_K0_MASK; config |= 0x05; /* XXX. cacheable coherent */ mips3_cp0_config_write(config); /* Zero BSS. XXXCGD: uh, is this really necessary still? */ memset(edata, 0, end - edata); /* * Copy the bootinfo structure from the boot loader. * this has to be done before mips_vector_init is * called because we may need CFE's TLB handler */ if (magic == BOOTINFO_MAGIC) memcpy(&bootinfo, (struct bootinfo_v1 *)bootdata, sizeof bootinfo); else if (reserved == CFE_EPTSEAL) { magic = BOOTINFO_MAGIC; bzero(&bootinfo, sizeof bootinfo); bootinfo.version = BOOTINFO_VERSION; bootinfo.fwhandle = fwhandle; bootinfo.fwentry = bootdata; bootinfo.ssym = (vaddr_t)end; bootinfo.esym = (vaddr_t)end; } kernend = (void *)mips_round_page(end); #if NKSYMS || defined(DDB) || defined(LKM) if (magic == BOOTINFO_MAGIC) { ksym_start = (void *)bootinfo.ssym; ksym_end = (void *)bootinfo.esym; kernend = (void *)mips_round_page((vaddr_t)ksym_end); } #endif consinit(); uvm_setpagesize(); /* * Copy exception-dispatch code down to exception vector. * Initialize locore-function vector. * Clear out the I and D caches. */ mips_vector_init(); #ifdef DEBUG printf("fwhandle=%08X magic=%08X bootdata=%08X reserved=%08X\n", (u_int)fwhandle, (u_int)magic, (u_int)bootdata, (u_int)reserved); #endif strcpy(cpu_model, "sb1250"); if (magic == BOOTINFO_MAGIC) { int idx; int added; uint64_t start, len, type; cfe_init(bootinfo.fwhandle, bootinfo.fwentry); cfe_present = 1; idx = 0; physmem = 0; mem_cluster_cnt = 0; while (cfe_enummem(idx, 0, &start, &len, &type) == 0) { added = 0; printf("Memory Block #%d start %08"PRIx64"X len %08"PRIx64"X: %s: ", idx, start, len, (type == CFE_MI_AVAILABLE) ? "Available" : "Reserved"); if ((type == CFE_MI_AVAILABLE) && (mem_cluster_cnt < VM_PHYSSEG_MAX)) { /* * XXX Ignore memory above 256MB for now, it * XXX needs special handling. */ if (start < (256*1024*1024)) { physmem += btoc(((int) len)); mem_clusters[mem_cluster_cnt].start = (long) start; mem_clusters[mem_cluster_cnt].size = (long) len; mem_cluster_cnt++; added = 1; } } if (added) printf("added to map\n"); else printf("not added to map\n"); idx++; } } else { /* * Handle the case of not being called from the firmware. */ /* XXX hardwire to 32MB; should be kernel config option */ physmem = 32 * 1024 * 1024 / 4096; mem_clusters[0].start = 0; mem_clusters[0].size = ctob(physmem); mem_cluster_cnt = 1; } for (i = 0; i < sizeof(bootinfo.boot_flags); i++) { switch (bootinfo.boot_flags[i]) { case '\0': break; case ' ': continue; case '-': while (bootinfo.boot_flags[i] != ' ' && bootinfo.boot_flags[i] != '\0') { switch (bootinfo.boot_flags[i]) { case 'a': boothowto |= RB_ASKNAME; break; case 'd': boothowto |= RB_KDB; break; case 's': boothowto |= RB_SINGLE; break; } i++; } } } /* * Load the rest of the available pages into the VM system. * The first chunk is tricky because we have to avoid the * kernel, but the rest are easy. */ first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); last = mem_clusters[0].start + mem_clusters[0].size; uvm_page_physload(atop(first), atop(last), atop(first), atop(last), VM_FREELIST_DEFAULT); for (i = 1; i < mem_cluster_cnt; i++) { first = round_page(mem_clusters[i].start); last = mem_clusters[i].start + mem_clusters[i].size; uvm_page_physload(atop(first), atop(last), atop(first), atop(last), VM_FREELIST_DEFAULT); } /* * Initialize error message buffer (at end of core). */ mips_init_msgbuf(); /* * Allocate space for proc0's USPACE */ p0 = (void *)pmap_steal_memory(USPACE, NULL, NULL); lwp0.l_addr = proc0paddr = (struct user *)p0; lwp0.l_md.md_regs = (struct frame *)((char *)p0 + USPACE) - 1; proc0paddr->u_pcb.pcb_context[11] = MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */ pmap_bootstrap(); /* * Initialize debuggers, and break into them, if appropriate. */ #if NKSYMS || defined(DDB) || defined(LKM) ksyms_init(((uintptr_t)ksym_end - (uintptr_t)ksym_start), ksym_start, ksym_end); #endif if (boothowto & RB_KDB) { #if defined(DDB) Debugger(); #endif } }
void gzalloc_configure(void) { char temp_buf[16]; if (PE_parse_boot_argn("-gzalloc_mode", temp_buf, sizeof (temp_buf))) { gzalloc_mode = TRUE; gzalloc_min = GZALLOC_MIN_DEFAULT; #if ZONE_DEBUG gzalloc_min += (typeof(gzalloc_min))ZONE_DEBUG_OFFSET; #endif gzalloc_max = ~0U; } if (PE_parse_boot_argn("gzalloc_min", &gzalloc_min, sizeof(gzalloc_min))) { #if ZONE_DEBUG gzalloc_min += (typeof(gzalloc_min))ZONE_DEBUG_OFFSET; #endif gzalloc_mode = TRUE; gzalloc_max = ~0U; } if (PE_parse_boot_argn("gzalloc_max", &gzalloc_max, sizeof(gzalloc_max))) { #if ZONE_DEBUG gzalloc_max += (typeof(gzalloc_min))ZONE_DEBUG_OFFSET; #endif gzalloc_mode = TRUE; if (gzalloc_min == ~0U) gzalloc_min = 0; } if (PE_parse_boot_argn("gzalloc_size", &gzalloc_size, sizeof(gzalloc_size))) { #if ZONE_DEBUG gzalloc_size += (typeof(gzalloc_min))ZONE_DEBUG_OFFSET; #endif gzalloc_min = gzalloc_max = gzalloc_size; gzalloc_mode = TRUE; } (void)PE_parse_boot_argn("gzalloc_fc_size", &gzfc_size, sizeof(gzfc_size)); if (PE_parse_boot_argn("-gzalloc_wp", temp_buf, sizeof (temp_buf))) { gzalloc_prot = VM_PROT_READ; } if (PE_parse_boot_argn("-gzalloc_uf_mode", temp_buf, sizeof (temp_buf))) { gzalloc_uf_mode = TRUE; gzalloc_guard = KMA_GUARD_FIRST; } if (PE_parse_boot_argn("-gzalloc_noconsistency", temp_buf, sizeof (temp_buf))) { gzalloc_consistency_checks = FALSE; } #if DEBUG if (gzalloc_mode == FALSE) { gzalloc_min = 8192; gzalloc_max = 16384; gzalloc_prot = VM_PROT_READ; gzalloc_mode = TRUE; } #endif if (PE_parse_boot_argn("-nogzalloc_mode", temp_buf, sizeof (temp_buf))) gzalloc_mode = FALSE; if (gzalloc_mode) { gzalloc_reserve_size = GZALLOC_RESERVE_SIZE_DEFAULT; gzalloc_reserve = (vm_offset_t) pmap_steal_memory(gzalloc_reserve_size); } }
caddr_t mips_init(int argc, void *argv, caddr_t boot_esym) { char *cp; int i; u_int cputype; vaddr_t xtlb_handler; extern char start[], edata[], end[]; extern char exception[], e_exception[]; extern char *hw_vendor; #ifdef MULTIPROCESSOR /* * Set curcpu address on primary processor. */ setcurcpu(&cpu_info_primary); #endif /* * Make sure we can access the extended address space. * Note that r10k and later do not allow XUSEG accesses * from kernel mode unless SR_UX is set. */ setsr(getsr() | SR_KX | SR_UX); /* * Clear the compiled BSS segment in OpenBSD code. */ bzero(edata, end - edata); /* * Reserve space for the symbol table, if it exists. */ ssym = (char *)*(u_int64_t *)end; /* Attempt to locate ELF header and symbol table after kernel. */ if (end[0] == ELFMAG0 && end[1] == ELFMAG1 && end[2] == ELFMAG2 && end[3] == ELFMAG3 ) { /* ELF header exists directly after kernel. */ ssym = end; esym = boot_esym; ekern = esym; } else if (((long)ssym - (long)end) >= 0 && ((long)ssym - (long)end) <= 0x1000 && ssym[0] == ELFMAG0 && ssym[1] == ELFMAG1 && ssym[2] == ELFMAG2 && ssym[3] == ELFMAG3 ) { /* Pointers exist directly after kernel. */ esym = (char *)*((u_int64_t *)end + 1); ekern = esym; } else { /* Pointers aren't setup either... */ ssym = NULL; esym = NULL; ekern = end; } /* * Initialize the system type and set up memory layout. * Note that some systems have a more complex memory setup. */ bios_ident(); /* * Read and store ARCBios variables for future reference. */ cp = Bios_GetEnvironmentVariable("ConsoleOut"); if (cp != NULL && *cp != '\0') strlcpy(bios_console, cp, sizeof(bios_console)); cp = Bios_GetEnvironmentVariable("gfx"); if (cp != NULL && *cp != '\0') strlcpy(bios_graphics, cp, sizeof(bios_graphics)); cp = Bios_GetEnvironmentVariable("keybd"); if (cp != NULL && *cp != '\0') strlcpy(bios_keyboard, cp, sizeof(bios_keyboard)); /* * Determine system type and set up configuration record data. */ hw_vendor = "SGI"; switch (sys_config.system_type) { #ifdef TGT_O2 case SGI_O2: bios_printf("Found SGI-IP32, setting up.\n"); strlcpy(cpu_model, "IP32", sizeof(cpu_model)); ip32_setup(); break; #endif #ifdef TGT_ORIGIN case SGI_IP27: bios_printf("Found SGI-IP27, setting up.\n"); strlcpy(cpu_model, "IP27", sizeof(cpu_model)); ip27_setup(); break; case SGI_IP35: bios_printf("Found SGI-IP35, setting up.\n"); /* IP27 is intentional, we use the same kernel */ strlcpy(cpu_model, "IP27", sizeof(cpu_model)); ip27_setup(); break; #endif #ifdef TGT_OCTANE case SGI_OCTANE: bios_printf("Found SGI-IP30, setting up.\n"); strlcpy(cpu_model, "IP30", sizeof(cpu_model)); ip30_setup(); break; #endif default: bios_printf("Kernel doesn't support this system type!\n"); bios_printf("Halting system.\n"); Bios_Halt(); while(1); } /* * Look at arguments passed to us and compute boothowto. */ boothowto = RB_AUTOBOOT; dobootopts(argc, argv); /* * Figure out where we supposedly booted from. */ cp = Bios_GetEnvironmentVariable("OSLoadPartition"); if (cp == NULL) cp = "unknown"; if (strlcpy(osloadpartition, cp, sizeof osloadpartition) >= sizeof osloadpartition) bios_printf("Value of `OSLoadPartition' is too large.\n" "The kernel might not be able to find out its root device.\n"); /* * Read platform-specific environment variables. */ switch (sys_config.system_type) { #ifdef TGT_O2 case SGI_O2: /* Get Ethernet address from ARCBIOS. */ cp = Bios_GetEnvironmentVariable("eaddr"); if (cp != NULL && strlen(cp) > 0) strlcpy(bios_enaddr, cp, sizeof bios_enaddr); break; #endif default: break; } /* * Set pagesize to enable use of page macros and functions. * Commit available memory to UVM system. */ uvmexp.pagesize = PAGE_SIZE; uvm_setpagesize(); for (i = 0; i < MAXMEMSEGS && mem_layout[i].mem_last_page != 0; i++) { uint64_t fp, lp; uint64_t firstkernpage, lastkernpage; unsigned int freelist; paddr_t firstkernpa, lastkernpa; if (IS_XKPHYS((vaddr_t)start)) firstkernpa = XKPHYS_TO_PHYS((vaddr_t)start); else firstkernpa = CKSEG0_TO_PHYS((vaddr_t)start); if (IS_XKPHYS((vaddr_t)ekern)) lastkernpa = XKPHYS_TO_PHYS((vaddr_t)ekern); else lastkernpa = CKSEG0_TO_PHYS((vaddr_t)ekern); firstkernpage = atop(trunc_page(firstkernpa)); lastkernpage = atop(round_page(lastkernpa)); fp = mem_layout[i].mem_first_page; lp = mem_layout[i].mem_last_page; freelist = mem_layout[i].mem_freelist; /* Account for kernel and kernel symbol table. */ if (fp >= firstkernpage && lp < lastkernpage) continue; /* In kernel. */ if (lp < firstkernpage || fp > lastkernpage) { uvm_page_physload(fp, lp, fp, lp, freelist); continue; /* Outside kernel. */ } if (fp >= firstkernpage) fp = lastkernpage; else if (lp < lastkernpage) lp = firstkernpage; else { /* Need to split! */ uint64_t xp = firstkernpage; uvm_page_physload(fp, xp, fp, xp, freelist); fp = lastkernpage; } if (lp > fp) { uvm_page_physload(fp, lp, fp, lp, freelist); } } /* * Configure cache. */ switch (bootcpu_hwinfo.type) { #ifdef CPU_R10000 case MIPS_R10000: case MIPS_R12000: case MIPS_R14000: cputype = MIPS_R10000; break; #endif #ifdef CPU_R5000 case MIPS_R5000: case MIPS_RM52X0: cputype = MIPS_R5000; break; #endif #ifdef CPU_RM7000 case MIPS_RM7000: case MIPS_RM9000: cputype = MIPS_R5000; break; #endif default: /* * If we can't identify the cpu type, it must be * r10k-compatible on Octane and Origin families, and * it is likely to be r5k-compatible on O2. */ switch (sys_config.system_type) { case SGI_O2: cputype = MIPS_R5000; break; default: case SGI_OCTANE: case SGI_IP27: case SGI_IP35: cputype = MIPS_R10000; break; } break; } switch (cputype) { default: #if defined(CPU_R5000) || defined(CPU_RM7000) case MIPS_R5000: Mips5k_ConfigCache(curcpu()); sys_config._SyncCache = Mips5k_SyncCache; sys_config._InvalidateICache = Mips5k_InvalidateICache; sys_config._SyncDCachePage = Mips5k_SyncDCachePage; sys_config._HitSyncDCache = Mips5k_HitSyncDCache; sys_config._IOSyncDCache = Mips5k_IOSyncDCache; sys_config._HitInvalidateDCache = Mips5k_HitInvalidateDCache; break; #endif #ifdef CPU_R10000 case MIPS_R10000: Mips10k_ConfigCache(curcpu()); sys_config._SyncCache = Mips10k_SyncCache; sys_config._InvalidateICache = Mips10k_InvalidateICache; sys_config._SyncDCachePage = Mips10k_SyncDCachePage; sys_config._HitSyncDCache = Mips10k_HitSyncDCache; sys_config._IOSyncDCache = Mips10k_IOSyncDCache; sys_config._HitInvalidateDCache = Mips10k_HitInvalidateDCache; break; #endif } /* * Last chance to call the BIOS. Wiping the TLB means the BIOS' data * areas are demapped on most systems. */ delay(20*1000); /* Let any UART FIFO drain... */ tlb_set_page_mask(TLB_PAGE_MASK); tlb_set_wired(0); tlb_flush(bootcpu_hwinfo.tlbsize); tlb_set_wired(UPAGES / 2); /* * Get a console, very early but after initial mapping setup. */ consinit(); printf("Initial setup done, switching console.\n"); /* * Init message buffer. */ msgbufbase = (caddr_t)pmap_steal_memory(MSGBUFSIZE, NULL, NULL); initmsgbuf(msgbufbase, MSGBUFSIZE); /* * Allocate U page(s) for proc[0], pm_tlbpid 1. */ proc0.p_addr = proc0paddr = curcpu()->ci_curprocpaddr = (struct user *)pmap_steal_memory(USPACE, NULL, NULL); proc0.p_md.md_regs = (struct trap_frame *)&proc0paddr->u_pcb.pcb_regs; tlb_set_pid(1); /* * Bootstrap VM system. */ pmap_bootstrap(); /* * Copy down exception vector code. */ bcopy(exception, (char *)CACHE_ERR_EXC_VEC, e_exception - exception); bcopy(exception, (char *)GEN_EXC_VEC, e_exception - exception); /* * Build proper TLB refill handler trampolines. */ switch (cputype) { #if defined(CPU_R5000) || defined(CPU_RM7000) case MIPS_R5000: { /* * R5000 processors need a specific chip bug workaround * in their tlb handlers. Theoretically only revision 1 * of the processor need it, but there is evidence * later versions also need it. * * This is also necessary on RM52x0 and most RM7k/RM9k, * and is a documented errata for these chips. */ extern void xtlb_miss_err_r5k; xtlb_handler = (vaddr_t)&xtlb_miss_err_r5k; } break; #endif default: { extern void xtlb_miss; xtlb_handler = (vaddr_t)&xtlb_miss; } break; } build_trampoline(TLB_MISS_EXC_VEC, xtlb_handler); build_trampoline(XTLB_MISS_EXC_VEC, xtlb_handler); /* * Turn off bootstrap exception vectors. */ setsr(getsr() & ~SR_BOOT_EXC_VEC); proc0.p_md.md_regs->sr = getsr(); /* * Clear out the I and D caches. */ Mips_SyncCache(curcpu()); #ifdef DDB db_machine_init(); if (boothowto & RB_KDB) Debugger(); #endif /* * Return new stack pointer. */ return ((caddr_t)proc0paddr + USPACE - 64); }