/* * cpu_startup: allocate memory for variable-sized tables, * initialize CPU, and do autoconfiguration. */ void cpu_startup(void) { vaddr_t minaddr, maxaddr; #ifdef DEBUG extern int pmapdebug; int opmapdebug = pmapdebug; pmapdebug = 0; #endif cpu_setmodel("FIC8234"); if (fputype != FPU_NONE) m68k_make_fpu_idle_frame(); /* * Good {morning,afternoon,evening,night}. */ printf("%s%s", copyright, version); identifycpu(); printf("real mem = %d\n", ctob(physmem)); minaddr = 0; /* * Allocate a submap for physio */ phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, 0, false, NULL); #ifdef DEBUG pmapdebug = opmapdebug; #endif printf("avail mem = %ld\n", ptoa(uvmexp.free)); }
/* * cpu_startup: allocate memory for variable-sized tables. */ void cpu_startup() { vaddr_t minaddr, maxaddr; char pbuf[9]; extern void greeting __P((void)); if (fputype != FPU_NONE) m68k_make_fpu_idle_frame(); /* * Initialize the kernel crash dump header. */ cpu_init_kcore_hdr(); /* * Good {morning,afternoon,evening,night}. */ printf("%s%s", copyright, version); identifycpu(); format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); printf("total memory = %s\n", pbuf); minaddr = 0; /* * Allocate a submap for physio */ phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, 0, false, NULL); /* * Finally, allocate mbuf cluster submap. */ mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, nmbclusters * mclbytes, VM_MAP_INTRSAFE, false, NULL); format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); printf("avail memory = %s\n", pbuf); /* * Say "Hi" to the world */ greeting(); }
/* * cpu_startup: allocate memory for variable-sized tables, * initialize CPU, and do autoconfiguration. */ void cpu_startup(void) { u_quad_t vmememsize; vaddr_t minaddr, maxaddr; char pbuf[9]; u_int i; #ifdef DEBUG extern int pmapdebug; int opmapdebug = pmapdebug; pmapdebug = 0; #endif /* * If we have an FPU, initialise the cached idle frame */ if (fputype != FPU_NONE) m68k_make_fpu_idle_frame(); /* * Initialize the kernel crash dump header. */ cpu_init_kcore_hdr(); /* * Good {morning,afternoon,evening,night}. */ printf("%s%s", copyright, version); identifycpu(); format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); printf("total memory = %s", pbuf); for (vmememsize = 0, i = 1; i < mem_cluster_cnt; i++) vmememsize += mem_clusters[i].size; if (vmememsize != 0) { format_bytes(pbuf, sizeof(pbuf), mem_clusters[0].size); printf(" (%s on-board", pbuf); format_bytes(pbuf, sizeof(pbuf), vmememsize); printf(", %s VMEbus)", pbuf); } printf("\n"); minaddr = 0; /* * Allocate a submap for physio */ phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, 0, false, NULL); /* * Finally, allocate mbuf cluster submap. */ mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, nmbclusters * mclbytes, VM_MAP_INTRSAFE, false, NULL); #ifdef DEBUG pmapdebug = opmapdebug; #endif format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); printf("avail memory = %s\n", pbuf); /* * Set up CPU-specific registers, cache, etc. */ initcpu(); }
/* * The CPU ends up here when its ready to run * This is called from code in mptramp.s; at this point, we are running * in the idle pcb/idle stack of the new cpu. When this function returns, * this processor will enter the idle loop and start looking for work. * * XXX should share some of this with init386 in machdep.c */ void cpu_hatch(void *v) { struct cpu_info *ci = (struct cpu_info *)v; int s; cpu_init_msrs(ci); #ifdef DEBUG if (ci->ci_flags & CPUF_PRESENT) panic("%s: already running!?", ci->ci_dev->dv_xname); #endif ci->ci_flags |= CPUF_PRESENT; lapic_enable(); lapic_startclock(); if ((ci->ci_flags & CPUF_IDENTIFIED) == 0) { /* * We need to wait until we can identify, otherwise dmesg * output will be messy. */ while ((ci->ci_flags & CPUF_IDENTIFY) == 0) delay(10); identifycpu(ci); /* Signal we're done */ atomic_clearbits_int(&ci->ci_flags, CPUF_IDENTIFY); /* Prevent identifycpu() from running again */ atomic_setbits_int(&ci->ci_flags, CPUF_IDENTIFIED); } while ((ci->ci_flags & CPUF_GO) == 0) delay(10); #ifdef DEBUG if (ci->ci_flags & CPUF_RUNNING) panic("%s: already running!?", ci->ci_dev->dv_xname); #endif lcr0(ci->ci_idle_pcb->pcb_cr0); cpu_init_idt(); lapic_set_lvt(); gdt_init_cpu(ci); fpuinit(ci); lldt(0); cpu_init(ci); s = splhigh(); lcr8(0); enable_intr(); microuptime(&ci->ci_schedstate.spc_runtime); splx(s); SCHED_LOCK(s); cpu_switchto(NULL, sched_chooseproc()); }
void cpu_attach(struct device *parent, struct device *self, void *aux) { struct cpu_softc *sc = (void *) self; struct cpu_attach_args *caa = aux; struct cpu_info *ci; #if defined(MULTIPROCESSOR) int cpunum = sc->sc_dev.dv_unit; vaddr_t kstack; struct pcb *pcb; #endif /* * If we're an Application Processor, allocate a cpu_info * structure, otherwise use the primary's. */ if (caa->cpu_role == CPU_ROLE_AP) { ci = malloc(sizeof(*ci), M_DEVBUF, M_WAITOK|M_ZERO); #if defined(MULTIPROCESSOR) if (cpu_info[cpunum] != NULL) panic("cpu at apic id %d already attached?", cpunum); cpu_info[cpunum] = ci; #endif #ifdef TRAPLOG ci->ci_tlog_base = malloc(sizeof(struct tlog), M_DEVBUF, M_WAITOK); #endif } else { ci = &cpu_info_primary; #if defined(MULTIPROCESSOR) if (caa->cpu_number != lapic_cpu_number()) { panic("%s: running cpu is at apic %d" " instead of at expected %d", sc->sc_dev.dv_xname, lapic_cpu_number(), caa->cpu_number); } #endif } ci->ci_self = ci; sc->sc_info = ci; ci->ci_dev = self; ci->ci_apicid = caa->cpu_number; #ifdef MULTIPROCESSOR ci->ci_cpuid = cpunum; #else ci->ci_cpuid = 0; /* False for APs, but they're not used anyway */ #endif ci->ci_func = caa->cpu_func; simple_lock_init(&ci->ci_slock); #if defined(MULTIPROCESSOR) /* * Allocate USPACE pages for the idle PCB and stack. * XXX should we just sleep here? */ kstack = (vaddr_t)km_alloc(USPACE, &kv_any, &kp_zero, &kd_nowait); if (kstack == 0) { if (caa->cpu_role != CPU_ROLE_AP) { panic("cpu_attach: unable to allocate idle stack for" " primary"); } printf("%s: unable to allocate idle stack\n", sc->sc_dev.dv_xname); return; } pcb = ci->ci_idle_pcb = (struct pcb *)kstack; pcb->pcb_kstack = kstack + USPACE - 16; pcb->pcb_rbp = pcb->pcb_rsp = kstack + USPACE - 16; pcb->pcb_pmap = pmap_kernel(); pcb->pcb_cr0 = rcr0(); pcb->pcb_cr3 = pcb->pcb_pmap->pm_pdirpa; #endif /* further PCB init done later. */ printf(": "); switch (caa->cpu_role) { case CPU_ROLE_SP: printf("(uniprocessor)\n"); ci->ci_flags |= CPUF_PRESENT | CPUF_SP | CPUF_PRIMARY; cpu_intr_init(ci); identifycpu(ci); cpu_init(ci); break; case CPU_ROLE_BP: printf("apid %d (boot processor)\n", caa->cpu_number); ci->ci_flags |= CPUF_PRESENT | CPUF_BSP | CPUF_PRIMARY; cpu_intr_init(ci); identifycpu(ci); cpu_init(ci); #if NLAPIC > 0 /* * Enable local apic */ lapic_enable(); lapic_calibrate_timer(ci); #endif #if NIOAPIC > 0 ioapic_bsp_id = caa->cpu_number; #endif break; case CPU_ROLE_AP: /* * report on an AP */ printf("apid %d (application processor)\n", caa->cpu_number); #if defined(MULTIPROCESSOR) cpu_intr_init(ci); gdt_alloc_cpu(ci); sched_init_cpu(ci); cpu_start_secondary(ci); ncpus++; if (ci->ci_flags & CPUF_PRESENT) { ci->ci_next = cpu_info_list->ci_next; cpu_info_list->ci_next = ci; } #else printf("%s: not started\n", sc->sc_dev.dv_xname); #endif break; default: panic("unknown processor type??"); } cpu_vm_init(ci); #if defined(MULTIPROCESSOR) if (mp_verbose) { printf("%s: kstack at 0x%lx for %d bytes\n", sc->sc_dev.dv_xname, kstack, USPACE); printf("%s: idle pcb at %p, idle sp at 0x%lx\n", sc->sc_dev.dv_xname, pcb, pcb->pcb_rsp); } #endif }
/* * cpu_startup: allocate memory for variable-sized tables, * initialize cpu, and do autoconfiguration. */ cpu_startup() { register unsigned i; register caddr_t v, firstaddr; int base, residual; vm_offset_t minaddr, maxaddr; vm_size_t size; #ifdef BUFFERS_UNMANAGED vm_offset_t bufmemp; caddr_t buffermem; int ix; #endif #ifdef DEBUG extern int pmapdebug; int opmapdebug = pmapdebug; pmapdebug = 0; #endif /* * Initialize error message buffer (at end of core). * avail_end was pre-decremented in pmap_bootstrap to compensate. */ for (i = 0; i < btoc(sizeof (struct msgbuf)); i++) pmap_enter(kernel_pmap, (vm_offset_t)msgbufp, avail_end + i * NBPG, VM_PROT_ALL, TRUE); msgbufmapped = 1; /* * Good {morning,afternoon,evening,night}. */ printf(version); identifycpu(); printf("real mem = %d\n", ctob(physmem)); /* * Allocate space for system data structures. * The first available real memory address is in "firstaddr". * The first available kernel virtual address is in "v". * As pages of kernel virtual memory are allocated, "v" is incremented. * As pages of memory are allocated and cleared, * "firstaddr" is incremented. * An index into the kernel page table corresponding to the * virtual memory address maintained in "v" is kept in "mapaddr". */ /* * Make two passes. The first pass calculates how much memory is * needed and allocates it. The second pass assigns virtual * addresses to the various data structures. */ firstaddr = 0; again: v = (caddr_t)firstaddr; #define valloc(name, type, num) \ (name) = (type *)v; v = (caddr_t)((name)+(num)) #define valloclim(name, type, num, lim) \ (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) valloc(cfree, struct cblock, nclist); valloc(callout, struct callout, ncallout); valloc(swapmap, struct map, nswapmap = maxproc * 2); #ifdef SYSVSHM valloc(shmsegs, struct shmid_ds, shminfo.shmmni); #endif /* * Determine how many buffers to allocate. * Since HPs tend to be long on memory and short on disk speed, * we allocate more buffer space than the BSD standard of * use 10% of memory for the first 2 Meg, 5% of remaining. * We just allocate a flat 10%. Insure a minimum of 16 buffers. * We allocate 1/2 as many swap buffer headers as file i/o buffers. */ if (bufpages == 0) bufpages = physmem / 10 / CLSIZE; if (nbuf == 0) { nbuf = bufpages; if (nbuf < 16) nbuf = 16; } 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); /* * End of first pass, size has been calculated so allocate memory */ if (firstaddr == 0) { size = (vm_size_t)(v - firstaddr); firstaddr = (caddr_t) kmem_alloc(kernel_map, round_page(size)); if (firstaddr == 0) panic("startup: no room for tables"); #ifdef BUFFERS_UNMANAGED buffermem = (caddr_t) kmem_alloc(kernel_map, bufpages*CLBYTES); if (buffermem == 0) panic("startup: no room for buffers"); #endif goto again; } /* * End of second pass, addresses have been assigned */ if ((vm_size_t)(v - firstaddr) != size) panic("startup: table size inconsistency"); /* * Now allocate buffers proper. They are different than the above * in that they usually occupy more virtual memory than physical. */ size = MAXBSIZE * nbuf; buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers, &maxaddr, size, TRUE); minaddr = (vm_offset_t)buffers; if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0, &minaddr, size, FALSE) != KERN_SUCCESS) panic("startup: cannot allocate buffers"); base = bufpages / nbuf; residual = bufpages % nbuf; #ifdef BUFFERS_UNMANAGED bufmemp = (vm_offset_t) buffermem; #endif for (i = 0; i < nbuf; i++) { vm_size_t curbufsize; vm_offset_t curbuf; /* * First <residual> buffers get (base+1) physical pages * allocated for them. The rest get (base) physical pages. * * The rest of each buffer occupies virtual space, * but has no physical memory allocated for it. */ curbuf = (vm_offset_t)buffers + i * MAXBSIZE; curbufsize = CLBYTES * (i < residual ? base+1 : base); #ifdef BUFFERS_UNMANAGED /* * Move the physical pages over from buffermem. */ for (ix = 0; ix < curbufsize/CLBYTES; ix++) { vm_offset_t pa; pa = pmap_extract(kernel_pmap, bufmemp); if (pa == 0) panic("startup: unmapped buffer"); pmap_remove(kernel_pmap, bufmemp, bufmemp+CLBYTES); pmap_enter(kernel_pmap, (vm_offset_t)(curbuf + ix * CLBYTES), pa, VM_PROT_READ|VM_PROT_WRITE, TRUE); bufmemp += CLBYTES; } #else vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE); vm_map_simplify(buffer_map, curbuf); #endif } #ifdef BUFFERS_UNMANAGED #if 0 /* * We would like to free the (now empty) original address range * but too many bad things will happen if we try. */ kmem_free(kernel_map, (vm_offset_t)buffermem, bufpages*CLBYTES); #endif #endif /* * Allocate a submap for exec arguments. This map effectively * limits the number of processes exec'ing at any time. */ exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 16*NCARGS, TRUE); /* * Allocate a submap for physio */ phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, TRUE); /* * Finally, allocate mbuf pool. Since mclrefcnt is an off-size * we use the more space efficient malloc in place of kmem_alloc. */ mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES, M_MBUF, M_NOWAIT); bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES); mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr, VM_MBUF_SIZE, FALSE); /* * Initialize callouts */ callfree = callout; for (i = 1; i < ncallout; i++) callout[i-1].c_next = &callout[i]; callout[i-1].c_next = NULL; #ifdef DEBUG pmapdebug = opmapdebug; #endif printf("avail mem = %d\n", ptoa(cnt.v_free_count)); printf("using %d buffers containing %d bytes of memory\n", nbuf, bufpages * CLBYTES); /* * Set up CPU-specific registers, cache, etc. */ initcpu(); /* * Set up buffers, so they can be used to read disk labels. */ bufinit(); /* * Configure the system. */ configure(); }
void cpu_startup() { caddr_t v; int sz, i; vsize_t size; int base, residual; vaddr_t minaddr, maxaddr, uarea_pages; /* * Initialize error message buffer (at end of core). * avail_end was pre-decremented in luna88k_bootstrap() to compensate. */ for (i = 0; i < btoc(MSGBUFSIZE); i++) pmap_kenter_pa((paddr_t)msgbufp + i * NBPG, avail_end + i * NBPG, VM_PROT_READ | VM_PROT_WRITE); pmap_update(pmap_kernel()); initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE)); /* Determine the machine type from FUSE ROM data */ get_fuse_rom_data(); if (strncmp(fuse_rom_data, "MNAME=LUNA88K+", 14) == 0) { machtype = LUNA_88K2; } /* Determine the 'auto-boot' device from NVRAM data */ get_nvram_data(); get_autoboot_device(); /* * Good {morning,afternoon,evening,night}. */ printf(version); identifycpu(); printf("real mem = %d\n", ctob(physmem)); /* * Check front DIP switch setting */ printf("dipsw = 0x%x\n", dipswitch); /* Check DIP switch 1 - 1 */ if ((0x8000 & dipswitch) == 0) { boothowto |= RB_SINGLE; } /* Check DIP switch 1 - 3 */ if ((0x2000 & dipswitch) == 0) { boothowto |= RB_ASKNAME; } /* Check DIP switch 1 - 4 */ if ((0x1000 & dipswitch) == 0) { boothowto |= RB_CONFIG; } /* * Check frame buffer depth. */ switch (hwplanebits) { case 0: /* No frame buffer */ case 1: case 4: case 8: break; default: printf("unexpected frame buffer depth = %d\n", hwplanebits); hwplanebits = 0; break; } #if 0 /* just for test */ /* * Get boot arguments */ { char buf[256]; char **p = (volatile char **)0x00001120; strncpy(buf, *p, 256); if (buf[255] != '\0') buf[255] = '\0'; printf("boot arg: (0x%x) %s\n", *p, buf); } #endif /* * 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_zalloc(kernel_map, round_page(sz))) == 0) panic("startup: no room for tables"); if (allocsys(v) - v != sz) panic("startup: table size inconsistency"); /* * Grab UADDR virtual address */ uarea_pages = UADDR; uvm_map(kernel_map, (vaddr_t *)&uarea_pages, USPACE, NULL, UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, UVM_ADV_NORMAL, 0)); if (uarea_pages != UADDR) panic("uarea_pages %lx: UADDR not free", uarea_pages); /* * Grab the OBIO space that we hardwired in pmap_bootstrap */ obiova = OBIO_START; uvm_map(kernel_map, (vaddr_t *)&obiova, OBIO_SIZE, NULL, UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, UVM_ADV_NORMAL, 0)); if (obiova != OBIO_START) panic("obiova %lx: OBIO not free", obiova); /* * Now allocate buffers proper. They are different than the above * in that they usually occupy more virtual memory than physical. */ size = MAXBSIZE * nbuf; if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size), NULL, UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, UVM_ADV_NORMAL, 0))) panic("cpu_startup: cannot allocate VM for buffers"); minaddr = (vaddr_t)buffers; if ((bufpages / nbuf) >= btoc(MAXBSIZE)) { /* don't want to alloc more physical mem than needed */ bufpages = btoc(MAXBSIZE) * nbuf; } base = bufpages / nbuf; residual = bufpages % nbuf; for (i = 0; i < nbuf; i++) { vsize_t curbufsize; vaddr_t curbuf; struct vm_page *pg; /* * Each buffer has MAXBSIZE bytes of VM space allocated. Of * that MAXBSIZE space, we allocate and map (base+1) pages * for the first "residual" buffers, and then we allocate * "base" pages for the rest. */ curbuf = (vaddr_t)buffers + (i * MAXBSIZE); curbufsize = PAGE_SIZE * ((i < residual) ? (base+1) : base); while (curbufsize) { pg = uvm_pagealloc(NULL, 0, NULL, 0); if (pg == NULL) panic("cpu_startup: not enough memory for " "buffer cache"); pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), VM_PROT_READ | VM_PROT_WRITE); curbuf += PAGE_SIZE; curbufsize -= PAGE_SIZE; } } pmap_update(pmap_kernel()); /* * Allocate a submap for exec arguments. This map effectively * limits the number of processes exec'ing at any time. */ exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); /* * Allocate map for physio. */ phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, 0, FALSE, NULL); printf("avail mem = %ld (%d pages)\n", ptoa(uvmexp.free), uvmexp.free); printf("using %d buffers containing %d bytes of memory\n", nbuf, bufpages * PAGE_SIZE); /* * Set up buffers, so they can be used to read disk labels. */ bufinit(); /* * Initialize the autovectored interrupt list. */ isrinit(); /* * Configure the system. */ if (boothowto & RB_CONFIG) { #ifdef BOOT_CONFIG user_config(); #else printf("kernel does not support -c; continuing..\n"); #endif } /* * Say hello to the world on LCD. */ greeting(); }
/* * cpu_startup: allocate memory for variable-sized tables, * initialize cpu, and do autoconfiguration. * * This is called early in init_main.c:main(), after the * kernel memory allocator is ready for use, but before * the creation of processes 1,2, and mountroot, etc. */ void cpu_startup() { caddr_t v; int sz, i; vsize_t size; int base, residual; vaddr_t minaddr, maxaddr; char pbuf[9]; /* * Initialize message buffer (for kernel printf). * This is put in physical pages four through seven * so it will always be in the same place after a * reboot. (physical pages 0-3 are reserved by the PROM * for its vector table and other stuff.) * Its mapping was prepared in pmap_bootstrap(). * Also, offset some to avoid PROM scribbles. */ v = (caddr_t) (NBPG * 4); msgbufaddr = (caddr_t)(v + MSGBUFOFF); initmsgbuf(msgbufaddr, MSGBUFSIZE); #ifdef DDB { extern int end[]; extern char *esym; ddb_init(end[0], end + 1, (int*)esym); } #endif /* DDB */ /* * Good {morning,afternoon,evening,night}. */ printf(version); identifycpu(); fputype = FPU_NONE; #ifdef FPU_EMULATE printf("fpu: emulator\n"); #else printf("fpu: no math support\n"); #endif format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); printf("total memory = %s\n", pbuf); /* * XXX fredette - we force a small number of buffers * to help me debug this on my low-memory machine. * this should go away at some point, allowing the * normal automatic buffer-sizing to happen. */ bufpages = 37; /* * Get scratch page for dumpsys(). */ if ((dumppage = uvm_km_alloc(kernel_map, NBPG)) == 0) panic("startup: alloc dumppage"); /* * Find out how much space we need, allocate it, * and then give everything true virtual addresses. */ sz = (int)allocsys(NULL, NULL); if ((v = (caddr_t)uvm_km_alloc(kernel_map, round_page(sz))) == 0) panic("startup: no room for tables"); if (allocsys(v, NULL) - v != sz) panic("startup: table size inconsistency"); /* * Now allocate buffers proper. They are different than the above * in that they usually occupy more virtual memory than physical. */ size = MAXBSIZE * nbuf; if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size), NULL, UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, UVM_ADV_NORMAL, 0)) != 0) panic("startup: cannot allocate VM for buffers"); minaddr = (vaddr_t)buffers; if ((bufpages / nbuf) >= btoc(MAXBSIZE)) { /* don't want to alloc more physical mem than needed */ bufpages = btoc(MAXBSIZE) * nbuf; } base = bufpages / nbuf; residual = bufpages % nbuf; for (i = 0; i < nbuf; i++) { vsize_t curbufsize; vaddr_t curbuf; struct vm_page *pg; /* * Each buffer has MAXBSIZE bytes of VM space allocated. Of * that MAXBSIZE space, we allocate and map (base+1) pages * for the first "residual" buffers, and then we allocate * "base" pages for the rest. */ curbuf = (vaddr_t) buffers + (i * MAXBSIZE); curbufsize = NBPG * ((i < residual) ? (base+1) : base); while (curbufsize) { pg = uvm_pagealloc(NULL, 0, NULL, 0); if (pg == NULL) panic("cpu_startup: not enough memory for " "buffer cache"); pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), VM_PROT_READ|VM_PROT_WRITE); curbuf += PAGE_SIZE; curbufsize -= PAGE_SIZE; } } pmap_update(pmap_kernel()); /* * Allocate a submap for exec arguments. This map effectively * limits the number of processes exec'ing at any time. */ exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); /* * We don't use a submap for physio, and use a separate map * for DVMA allocations. Our vmapbuf just maps pages into * the kernel map (any kernel mapping is OK) and then the * device drivers clone the kernel mappings into DVMA space. */ /* * Finally, allocate mbuf cluster submap. */ mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, nmbclusters * mclbytes, VM_MAP_INTRSAFE, FALSE, NULL); format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); printf("avail memory = %s\n", pbuf); format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG); printf("using %d buffers containing %s of memory\n", nbuf, pbuf); /* * Allocate a virtual page (for use by /dev/mem) * This page is handed to pmap_enter() therefore * it has to be in the normal kernel VA range. */ vmmap = uvm_km_valloc_wait(kernel_map, NBPG); /* * Allocate dma map for devices on the bus. */ dvmamap = extent_create("dvmamap", DVMA_MAP_BASE, DVMA_MAP_BASE + DVMA_MAP_AVAIL, M_DEVBUF, 0, 0, EX_NOWAIT); if (dvmamap == NULL) panic("unable to allocate DVMA map"); /* * Set up CPU-specific registers, cache, etc. */ initcpu(); /* * Set up buffers, so they can be used to read disk labels. */ bufinit(); }
void cpu_startup() { vaddr_t minaddr, maxaddr; /* Determine the machine type from FUSE ROM data. */ get_fuse_rom_data(); if (strncmp(fuse_rom_data, "MNAME=LUNA88K+", 14) == 0) { machtype = LUNA_88K2; } /* Determine the 'auto-boot' device from NVRAM data */ get_nvram_data(); get_autoboot_device(); /* * Good {morning,afternoon,evening,night}. */ printf(version); identifycpu(); printf("real mem = %u (%uMB)\n", ptoa(physmem), ptoa(physmem) / 1024 / 1024); /* * Check front DIP switch setting */ #ifdef DEBUG printf("dipsw = 0x%x\n", dipswitch); #endif /* Check DIP switch 1 - 1 */ if ((0x8000 & dipswitch) == 0) { boothowto |= RB_SINGLE; } /* Check DIP switch 1 - 3 */ if ((0x2000 & dipswitch) == 0) { boothowto |= RB_ASKNAME; } /* Check DIP switch 1 - 4 */ if ((0x1000 & dipswitch) == 0) { boothowto |= RB_CONFIG; } /* * Check frame buffer depth. */ switch (hwplanebits) { case 0: /* No frame buffer */ case 1: case 4: case 8: break; default: printf("unexpected frame buffer depth = %d\n", hwplanebits); hwplanebits = 0; break; } #if 0 /* just for test */ /* * Get boot arguments */ { char buf[256]; char **p = (volatile char **)0x00001120; strncpy(buf, *p, 256); if (buf[255] != '\0') buf[255] = '\0'; printf("boot arg: (0x%x) %s\n", *p, buf); } #endif /* * 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 map for physio. */ phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, 0, FALSE, NULL); 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(); /* * Initialize the autovectored interrupt list. */ isrinit(); /* * Configure the system. */ if (boothowto & RB_CONFIG) { #ifdef BOOT_CONFIG user_config(); #else printf("kernel does not support -c; continuing..\n"); #endif } }
/* * cpu_startup: allocate memory for variable-sized tables, * initialize CPU, and do autoconfiguration. * * This is called early in init_main.c:main(), after the * kernel memory allocator is ready for use, but before * the creation of processes 1,2, and mountroot, etc. */ void cpu_startup(void) { void *v; vaddr_t minaddr, maxaddr; char pbuf[9]; /* * Initialize message buffer (for kernel printf). * This is put in physical pages four through seven * so it will always be in the same place after a * reboot. (physical pages 0-3 are reserved by the PROM * for its vector table and other stuff.) * Its mapping was prepared in pmap_bootstrap(). * Also, offset some to avoid PROM scribbles. */ v = (void *) (PAGE_SIZE * 4); msgbufaddr = (void *)((char *)v + MSGBUFOFF); initmsgbuf(msgbufaddr, MSGBUFSIZE); #if NKSYMS || defined(DDB) || defined(LKM) { extern int nsym; extern char *ssym, *esym; ksyms_init(nsym, ssym, esym); } #endif /* DDB */ /* * Good {morning,afternoon,evening,night}. */ printf("%s%s", copyright, version); identifycpu(); fputype = FPU_NONE; #ifdef FPU_EMULATE printf("fpu: emulator\n"); #else printf("fpu: no math support\n"); #endif format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); printf("total memory = %s\n", pbuf); /* * XXX fredette - we force a small number of buffers * to help me debug this on my low-memory machine. * this should go away at some point, allowing the * normal automatic buffer-sizing to happen. */ bufpages = 37; /* * Get scratch page for dumpsys(). */ if ((dumppage = uvm_km_alloc(kernel_map, PAGE_SIZE,0, UVM_KMF_WIRED)) == 0) panic("startup: alloc dumppage"); minaddr = 0; /* * Allocate a submap for physio */ phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, 0, false, NULL); /* * Finally, allocate mbuf cluster submap. */ mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, nmbclusters * mclbytes, VM_MAP_INTRSAFE, false, NULL); format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); printf("avail memory = %s\n", pbuf); /* * Allocate a virtual page (for use by /dev/mem) * This page is handed to pmap_enter() therefore * it has to be in the normal kernel VA range. */ vmmap = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_VAONLY | UVM_KMF_WAITVA); /* * Allocate DMA map for devices on the bus. */ dvmamap = extent_create("dvmamap", DVMA_MAP_BASE, DVMA_MAP_BASE + DVMA_MAP_AVAIL, M_DEVBUF, 0, 0, EX_NOWAIT); if (dvmamap == NULL) panic("unable to allocate DVMA map"); /* * Set up CPU-specific registers, cache, etc. */ initcpu(); }
void cpu_attach(struct device *parent, struct device *self, void *aux) { struct cpu_info *ci = (struct cpu_info *)self; struct cpu_attach_args *caa = (struct cpu_attach_args *)aux; #ifdef MULTIPROCESSOR int cpunum = ci->ci_dev.dv_unit; vaddr_t kstack; struct pcb *pcb; #endif if (caa->cpu_role == CPU_ROLE_AP) { #ifdef MULTIPROCESSOR if (cpu_info[cpunum] != NULL) panic("cpu at apic id %d already attached?", cpunum); cpu_info[cpunum] = ci; #endif } else { ci = &cpu_info_primary; #ifdef MULTIPROCESSOR if (caa->cpu_number != lapic_cpu_number()) { panic("%s: running cpu is at apic %d" " instead of at expected %d", self->dv_xname, lapic_cpu_number(), caa->cpu_number); } #endif bcopy(self, &ci->ci_dev, sizeof *self); } ci->ci_self = ci; ci->ci_apicid = caa->cpu_number; #ifdef MULTIPROCESSOR ci->ci_cpuid = cpunum; #else ci->ci_cpuid = 0; /* False for APs, so what, they're not used */ #endif ci->ci_signature = caa->cpu_signature; ci->ci_feature_flags = caa->feature_flags; ci->ci_func = caa->cpu_func; #ifdef MULTIPROCESSOR /* * Allocate UPAGES contiguous pages for the idle PCB and stack. */ kstack = uvm_km_alloc(kernel_map, USPACE); if (kstack == 0) { if (cpunum == 0) { /* XXX */ panic("cpu_attach: unable to allocate idle stack for" " primary"); } printf("%s: unable to allocate idle stack\n", ci->ci_dev.dv_xname); return; } pcb = ci->ci_idle_pcb = (struct pcb *)kstack; memset(pcb, 0, USPACE); pcb->pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); pcb->pcb_tss.tss_esp0 = kstack + USPACE - 16 - sizeof (struct trapframe); pcb->pcb_tss.tss_esp = kstack + USPACE - 16 - sizeof (struct trapframe); pcb->pcb_pmap = pmap_kernel(); pcb->pcb_cr3 = pcb->pcb_pmap->pm_pdirpa; #endif ci->ci_curpmap = pmap_kernel(); /* further PCB init done later. */ printf(": "); switch (caa->cpu_role) { case CPU_ROLE_SP: printf("(uniprocessor)\n"); ci->ci_flags |= CPUF_PRESENT | CPUF_SP | CPUF_PRIMARY; identifycpu(ci); #ifdef MTRR mem_range_attach(); #endif cpu_init(ci); cpu_init_mwait(&ci->ci_dev); break; case CPU_ROLE_BP: printf("apid %d (boot processor)\n", caa->cpu_number); ci->ci_flags |= CPUF_PRESENT | CPUF_BSP | CPUF_PRIMARY; identifycpu(ci); #ifdef MTRR mem_range_attach(); #endif cpu_init(ci); #if NLAPIC > 0 /* * Enable local apic */ lapic_enable(); lapic_calibrate_timer(ci); #endif #if NIOAPIC > 0 ioapic_bsp_id = caa->cpu_number; #endif cpu_init_mwait(&ci->ci_dev); break; case CPU_ROLE_AP: /* * report on an AP */ printf("apid %d (application processor)\n", caa->cpu_number); #ifdef MULTIPROCESSOR gdt_alloc_cpu(ci); ci->ci_flags |= CPUF_PRESENT | CPUF_AP; identifycpu(ci); sched_init_cpu(ci); ci->ci_next = cpu_info_list->ci_next; cpu_info_list->ci_next = ci; ncpus++; #endif break; default: panic("unknown processor type??"); } #ifdef MULTIPROCESSOR if (mp_verbose) { printf("%s: kstack at 0x%lx for %d bytes\n", ci->ci_dev.dv_xname, kstack, USPACE); printf("%s: idle pcb at %p, idle sp at 0x%x\n", ci->ci_dev.dv_xname, pcb, pcb->pcb_esp); } #endif }
/* * cpu_startup: allocate memory for variable-sized tables, * initialize cpu, and do autoconfiguration. */ void cpu_startup() { unsigned i; caddr_t v; vaddr_t minaddr, maxaddr; vsize_t size; #ifdef DEBUG extern int pmapdebug; int opmapdebug = pmapdebug; pmapdebug = 0; #endif /* * Initialize error message buffer (at end of core). * avail_end was pre-decremented in pmap_bootstrap to compensate. */ for (i = 0; i < atop(MSGBUFSIZE); i++) pmap_kenter_pa((vaddr_t)msgbufp + i * PAGE_SIZE, avail_end + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE); pmap_update(pmap_kernel()); initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE)); /* * Good {morning,afternoon,evening,night}. */ printf("%s", 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. */ size = (vsize_t)allocsys((caddr_t)0); if ((v = (caddr_t) uvm_km_zalloc(kernel_map, round_page(size))) == 0) panic("startup: no room for tables"); if (allocsys(v) - v != size) 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 submap for physio. */ phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, 0, FALSE, NULL); #ifdef DEBUG pmapdebug = opmapdebug; #endif /* * Set up buffers, so they can be used to read disk labels. */ bufinit(); printf("avail mem = %u (%uMB)\n", ptoa(uvmexp.free), ptoa(uvmexp.free) / 1024 / 1024); /* * Configure the system. */ if (boothowto & RB_CONFIG) { #ifdef BOOT_CONFIG user_config(); #else printf("kernel does not support -c; continuing..\n"); #endif } }
/* * cpu_startup: allocate memory for variable-sized tables, * initialize CPU, and do autoconfiguration. * * This is called early in init_main.c:main(), after the * kernel memory allocator is ready for use, but before * the creation of processes 1,2, and mountroot, etc. */ void cpu_startup(void) { char *v; vaddr_t minaddr, maxaddr; char pbuf[9]; /* * Initialize message buffer (for kernel printf). * This is put in physical page zero so it will * always be in the same place after a reboot. * Its mapping was prepared in pmap_bootstrap(). * Also, offset some to avoid PROM scribbles. */ v = (char *)KERNBASE; msgbufaddr = v + MSGBUFOFF; initmsgbuf(msgbufaddr, MSGBUFSIZE); /* * Good {morning,afternoon,evening,night}. */ printf("%s%s", copyright, version); identifycpu(); initfpu(); /* also prints FPU type */ format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); printf("total memory = %s\n", pbuf); /* * Get scratch page for dumpsys(). */ dumppage = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_WIRED); if (dumppage == 0) panic("startup: alloc dumppage"); minaddr = 0; /* * Allocate a submap for physio */ phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, 0, false, NULL); /* * Finally, allocate mbuf cluster submap. */ mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, nmbclusters * mclbytes, VM_MAP_INTRSAFE, false, NULL); format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); printf("avail memory = %s\n", pbuf); /* * Allocate a virtual page (for use by /dev/mem) * This page is handed to pmap_enter() therefore * it has to be in the normal kernel VA range. */ vmmap = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_VAONLY | UVM_KMF_WAITVA); /* * Create the DVMA maps. */ dvma_init(); /* * Set up CPU-specific registers, cache, etc. */ initcpu(); }
/* * cpu_startup: allocate memory for variable-sized tables, * initialize cpu, and do autoconfiguration. */ void cpu_startup() { extern char *kernel_text, *etext; unsigned i; caddr_t v; int base, residual; u_quad_t vmememsize; vaddr_t minaddr, maxaddr; vsize_t size; #ifdef DEBUG extern int pmapdebug; int opmapdebug = pmapdebug; pmapdebug = 0; #endif /* * Initialize the kernel crash dump header. */ cpu_init_kcore_hdr(); /* * Good {morning,afternoon,evening,night}. */ printf(version); identifycpu(); printf("real mem = %d", ctob(physmem)); for (vmememsize = 0, i = 1; i < mem_cluster_cnt; i++) vmememsize += mem_clusters[i].size; if (vmememsize != 0) printf(" (%qu on-board, %qu VMEbus)", mem_clusters[0].size, vmememsize); printf("\n"); /* * Find out how much space we need, allocate it, * and then give everything true virtual addresses. */ size = (vsize_t)allocsys((caddr_t)0); if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(size))) == 0) panic("startup: no room for tables"); if ((allocsys(v) - v) != size) panic("startup: talbe size inconsistency"); /* * Now allocate buffers proper. They are different than the above * in that they usually occupy more virtual memory than physical. */ size = MAXBSIZE * nbuf; if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size), NULL, UVM_UNKNOWN_OFFSET, UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, UVM_ADV_NORMAL, 0)) != KERN_SUCCESS) panic("startup: cannot allocate VM for buffers"); minaddr = (vaddr_t)buffers; base = bufpages / nbuf; residual = bufpages % nbuf; for (i = 0; i < nbuf; i++) { vsize_t curbufsize; vaddr_t curbuf; struct vm_page *pg; /* * Each buffer has MAXBSIZE bytes of VM space allocated. Of * that MAXBSIZE space, we allocate and map (base+1) pages * for the first "residual" buffers, and then we allocate * "base" pages for the rest. */ curbuf = (vaddr_t) buffers + (i * MAXBSIZE); curbufsize = CLBYTES * ((i < residual) ? (base+1) : base); while (curbufsize) { pg = uvm_pagealloc(NULL, 0, NULL, 0); if (pg == NULL) panic("cpu_startup: not enough memory for " "buffer cache"); #ifdef PMAP_NEW pmap_kenter_pgs(curbuf, &pg, 1); #else pmap_enter(kernel_map->pmap, curbuf, VM_PAGE_TO_PHYS(pg), VM_PROT_READ|VM_PROT_WRITE, TRUE, VM_PROT_READ|VM_PROT_WRITE); #endif curbuf += PAGE_SIZE; curbufsize -= PAGE_SIZE; } } /* * Allocate a submap for exec arguments. This map effectively * limits the number of processes exec'ing at any time. */ exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 16*NCARGS, TRUE, FALSE, NULL); /* * Allocate a submap for physio */ phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, TRUE, FALSE, NULL); /* * Finally, allocate mbuf cluster submap. */ mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, VM_MBUF_SIZE, FALSE, FALSE, NULL); /* * Initialize callouts */ callfree = callout; for (i = 1; i < ncallout; i++) callout[i-1].c_next = &callout[i]; callout[i-1].c_next = NULL; #ifdef DEBUG pmapdebug = opmapdebug; #endif printf("avail mem = %ld\n", ptoa(uvmexp.free)); printf("using %d buffers containing %d bytes of memory\n", nbuf, bufpages * CLBYTES); /* * Tell the VM system that the area before the text segment * is invalid. * * XXX Should just change KERNBASE and VM_MIN_KERNEL_ADDRESS, * XXX but not right now. */ if (uvm_map_protect(kernel_map, 0, round_page(&kernel_text), UVM_PROT_NONE, TRUE) != KERN_SUCCESS) panic("can't mark pre-text pages off-limits"); /* * Tell the VM system that writing to the kernel text isn't allowed. * If we don't, we might end up COW'ing the text segment! */ if (uvm_map_protect(kernel_map, trunc_page(&kernel_text), round_page(&etext), UVM_PROT_READ|UVM_PROT_EXEC, TRUE) != KERN_SUCCESS) panic("can't protect kernel text"); /* * Set up CPU-specific registers, cache, etc. */ initcpu(); /* * Set up buffers, so they can be used to read disk labels. */ bufinit(); }